Skip to content

Commit 6b121b4

Browse files
Sumit Guptavireshk
authored andcommitted
cpufreq: tegra194: save CPU data to avoid repeated SMP calls
Currently, we make SMP call on every frequency set request to get the physical 'CPU ID' and 'CLUSTER ID' for the target CPU. This change optimizes the repeated calls by storing the physical IDs and the per core frequency register offset for all CPUs during boot. Later this info is used directly when required to set the frequency or read it from ACTMON counters. Signed-off-by: Sumit Gupta <sumitg@nvidia.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
1 parent 823a6d9 commit 6b121b4

1 file changed

Lines changed: 51 additions & 28 deletions

File tree

drivers/cpufreq/tegra194-cpufreq.c

Lines changed: 51 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@
3939
/* cpufreq transisition latency */
4040
#define TEGRA_CPUFREQ_TRANSITION_LATENCY (300 * 1000) /* unit in nanoseconds */
4141

42+
struct tegra_cpu_data {
43+
u32 cpuid;
44+
u32 clusterid;
45+
void __iomem *freq_core_reg;
46+
};
47+
4248
struct tegra_cpu_ctr {
4349
u32 cpu;
4450
u32 coreclk_cnt, last_coreclk_cnt;
@@ -69,6 +75,7 @@ struct tegra194_cpufreq_data {
6975
struct cpufreq_frequency_table **bpmp_luts;
7076
const struct tegra_cpufreq_soc *soc;
7177
bool icc_dram_bw_scaling;
78+
struct tegra_cpu_data *cpu_data;
7279
};
7380

7481
static struct workqueue_struct *read_counters_wq;
@@ -116,34 +123,19 @@ static void tegra234_get_cpu_cluster_id(u32 cpu, u32 *cpuid, u32 *clusterid)
116123
static int tegra234_get_cpu_ndiv(u32 cpu, u32 cpuid, u32 clusterid, u64 *ndiv)
117124
{
118125
struct tegra194_cpufreq_data *data = cpufreq_get_driver_data();
119-
void __iomem *freq_core_reg;
120-
u64 mpidr_id;
121-
122-
/* use physical id to get address of per core frequency register */
123-
mpidr_id = (clusterid * data->soc->maxcpus_per_cluster) + cpuid;
124-
freq_core_reg = SCRATCH_FREQ_CORE_REG(data, mpidr_id);
125126

126-
*ndiv = readl(freq_core_reg) & NDIV_MASK;
127+
*ndiv = readl(data->cpu_data[cpu].freq_core_reg) & NDIV_MASK;
127128

128129
return 0;
129130
}
130131

131132
static void tegra234_set_cpu_ndiv(struct cpufreq_policy *policy, u64 ndiv)
132133
{
133134
struct tegra194_cpufreq_data *data = cpufreq_get_driver_data();
134-
void __iomem *freq_core_reg;
135-
u32 cpu, cpuid, clusterid;
136-
u64 mpidr_id;
137-
138-
for_each_cpu_and(cpu, policy->cpus, cpu_online_mask) {
139-
data->soc->ops->get_cpu_cluster_id(cpu, &cpuid, &clusterid);
140-
141-
/* use physical id to get address of per core frequency register */
142-
mpidr_id = (clusterid * data->soc->maxcpus_per_cluster) + cpuid;
143-
freq_core_reg = SCRATCH_FREQ_CORE_REG(data, mpidr_id);
135+
u32 cpu;
144136

145-
writel(ndiv, freq_core_reg);
146-
}
137+
for_each_cpu_and(cpu, policy->cpus, cpu_online_mask)
138+
writel(ndiv, data->cpu_data[cpu].freq_core_reg);
147139
}
148140

149141
/*
@@ -157,11 +149,10 @@ static void tegra234_read_counters(struct tegra_cpu_ctr *c)
157149
{
158150
struct tegra194_cpufreq_data *data = cpufreq_get_driver_data();
159151
void __iomem *actmon_reg;
160-
u32 cpuid, clusterid;
161152
u64 val;
162153

163-
data->soc->ops->get_cpu_cluster_id(c->cpu, &cpuid, &clusterid);
164-
actmon_reg = CORE_ACTMON_CNTR_REG(data, clusterid, cpuid);
154+
actmon_reg = CORE_ACTMON_CNTR_REG(data, data->cpu_data[c->cpu].clusterid,
155+
data->cpu_data[c->cpu].cpuid);
165156

166157
val = readq(actmon_reg);
167158
c->last_refclk_cnt = upper_32_bits(val);
@@ -357,19 +348,17 @@ static void tegra194_set_cpu_ndiv(struct cpufreq_policy *policy, u64 ndiv)
357348
static unsigned int tegra194_get_speed(u32 cpu)
358349
{
359350
struct tegra194_cpufreq_data *data = cpufreq_get_driver_data();
351+
u32 clusterid = data->cpu_data[cpu].clusterid;
360352
struct cpufreq_frequency_table *pos;
361-
u32 cpuid, clusterid;
362353
unsigned int rate;
363354
u64 ndiv;
364355
int ret;
365356

366-
data->soc->ops->get_cpu_cluster_id(cpu, &cpuid, &clusterid);
367-
368357
/* reconstruct actual cpu freq using counters */
369358
rate = tegra194_calculate_speed(cpu);
370359

371360
/* get last written ndiv value */
372-
ret = data->soc->ops->get_cpu_ndiv(cpu, cpuid, clusterid, &ndiv);
361+
ret = data->soc->ops->get_cpu_ndiv(cpu, data->cpu_data[cpu].cpuid, clusterid, &ndiv);
373362
if (WARN_ON_ONCE(ret))
374363
return rate;
375364

@@ -475,13 +464,12 @@ static int tegra194_cpufreq_init(struct cpufreq_policy *policy)
475464
{
476465
struct tegra194_cpufreq_data *data = cpufreq_get_driver_data();
477466
int maxcpus_per_cluster = data->soc->maxcpus_per_cluster;
467+
u32 clusterid = data->cpu_data[policy->cpu].clusterid;
478468
struct cpufreq_frequency_table *freq_table;
479469
struct cpufreq_frequency_table *bpmp_lut;
480470
u32 start_cpu, cpu;
481-
u32 clusterid;
482471
int ret;
483472

484-
data->soc->ops->get_cpu_cluster_id(policy->cpu, NULL, &clusterid);
485473
if (clusterid >= data->soc->num_clusters || !data->bpmp_luts[clusterid])
486474
return -EINVAL;
487475

@@ -659,13 +647,36 @@ tegra_cpufreq_bpmp_read_lut(struct platform_device *pdev, struct tegra_bpmp *bpm
659647
return freq_table;
660648
}
661649

650+
static int tegra194_cpufreq_store_physids(unsigned int cpu, struct tegra194_cpufreq_data *data)
651+
{
652+
int num_cpus = data->soc->maxcpus_per_cluster * data->soc->num_clusters;
653+
u32 cpuid, clusterid;
654+
u64 mpidr_id;
655+
656+
if (cpu > (num_cpus - 1)) {
657+
pr_err("cpufreq: wrong num of cpus or clusters in soc data\n");
658+
return -EINVAL;
659+
}
660+
661+
data->soc->ops->get_cpu_cluster_id(cpu, &cpuid, &clusterid);
662+
663+
mpidr_id = (clusterid * data->soc->maxcpus_per_cluster) + cpuid;
664+
665+
data->cpu_data[cpu].cpuid = cpuid;
666+
data->cpu_data[cpu].clusterid = clusterid;
667+
data->cpu_data[cpu].freq_core_reg = SCRATCH_FREQ_CORE_REG(data, mpidr_id);
668+
669+
return 0;
670+
}
671+
662672
static int tegra194_cpufreq_probe(struct platform_device *pdev)
663673
{
664674
const struct tegra_cpufreq_soc *soc;
665675
struct tegra194_cpufreq_data *data;
666676
struct tegra_bpmp *bpmp;
667677
struct device *cpu_dev;
668678
int err, i;
679+
u32 cpu;
669680

670681
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
671682
if (!data)
@@ -692,6 +703,12 @@ static int tegra194_cpufreq_probe(struct platform_device *pdev)
692703
return PTR_ERR(data->regs);
693704
}
694705

706+
data->cpu_data = devm_kcalloc(&pdev->dev, data->soc->num_clusters *
707+
data->soc->maxcpus_per_cluster,
708+
sizeof(*data->cpu_data), GFP_KERNEL);
709+
if (!data->cpu_data)
710+
return -ENOMEM;
711+
695712
platform_set_drvdata(pdev, data);
696713

697714
bpmp = tegra_bpmp_get(&pdev->dev);
@@ -713,6 +730,12 @@ static int tegra194_cpufreq_probe(struct platform_device *pdev)
713730
}
714731
}
715732

733+
for_each_possible_cpu(cpu) {
734+
err = tegra194_cpufreq_store_physids(cpu, data);
735+
if (err)
736+
goto err_free_res;
737+
}
738+
716739
tegra194_cpufreq_driver.driver_data = data;
717740

718741
/* Check for optional OPPv2 and interconnect paths on CPU0 to enable ICC scaling */

0 commit comments

Comments
 (0)