Skip to content

Commit e010d1d

Browse files
jonhuntervireshk
authored andcommitted
cpufreq: tegra186: Fix get frequency callback
Commit b89c01c ("cpufreq: tegra186: Fix initial frequency") implemented the CPUFREQ 'get' callback to determine the current operating frequency for each CPU. This implementation used a simple looked up to determine the current operating frequency. The problem with this is that frequency table for different Tegra186 devices may vary and so the default boot frequency for Tegra186 device may or may not be present in the frequency table. If the default boot frequency is not present in the frequency table, this causes the function tegra186_cpufreq_get() to return 0 and in turn causes cpufreq_online() to fail which prevents CPUFREQ from working. Fix this by always calculating the CPU frequency based upon the current 'ndiv' setting for the CPU. Note that the CPU frequency for Tegra186 is calculated by reading the current 'ndiv' setting, multiplying by the CPU reference clock and dividing by a constant divisor. Fixes: b89c01c ("cpufreq: tegra186: Fix initial frequency") Signed-off-by: Jon Hunter <jonathanh@nvidia.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
1 parent 3650b22 commit e010d1d

1 file changed

Lines changed: 21 additions & 12 deletions

File tree

drivers/cpufreq/tegra186-cpufreq.c

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ static const struct tegra186_cpufreq_cluster_info tegra186_clusters[] = {
4242
struct tegra186_cpufreq_cluster {
4343
const struct tegra186_cpufreq_cluster_info *info;
4444
struct cpufreq_frequency_table *table;
45+
u32 ref_clk_khz;
46+
u32 div;
4547
};
4648

4749
struct tegra186_cpufreq_data {
@@ -94,7 +96,7 @@ static int tegra186_cpufreq_set_target(struct cpufreq_policy *policy,
9496

9597
static unsigned int tegra186_cpufreq_get(unsigned int cpu)
9698
{
97-
struct cpufreq_frequency_table *tbl;
99+
struct tegra186_cpufreq_data *data = cpufreq_get_driver_data();
98100
struct cpufreq_policy *policy;
99101
void __iomem *edvd_reg;
100102
unsigned int i, freq = 0;
@@ -104,17 +106,23 @@ static unsigned int tegra186_cpufreq_get(unsigned int cpu)
104106
if (!policy)
105107
return 0;
106108

107-
tbl = policy->freq_table;
108109
edvd_reg = policy->driver_data;
109110
ndiv = readl(edvd_reg) & EDVD_CORE_VOLT_FREQ_F_MASK;
110111

111-
for (i = 0; tbl[i].frequency != CPUFREQ_TABLE_END; i++) {
112-
if ((tbl[i].driver_data & EDVD_CORE_VOLT_FREQ_F_MASK) == ndiv) {
113-
freq = tbl[i].frequency;
114-
break;
112+
for (i = 0; i < data->num_clusters; i++) {
113+
struct tegra186_cpufreq_cluster *cluster = &data->clusters[i];
114+
int core;
115+
116+
for (core = 0; core < ARRAY_SIZE(cluster->info->cpus); core++) {
117+
if (cluster->info->cpus[core] != policy->cpu)
118+
continue;
119+
120+
freq = (cluster->ref_clk_khz * ndiv) / cluster->div;
121+
goto out;
115122
}
116123
}
117124

125+
out:
118126
cpufreq_cpu_put(policy);
119127

120128
return freq;
@@ -133,7 +141,7 @@ static struct cpufreq_driver tegra186_cpufreq_driver = {
133141

134142
static struct cpufreq_frequency_table *init_vhint_table(
135143
struct platform_device *pdev, struct tegra_bpmp *bpmp,
136-
unsigned int cluster_id)
144+
struct tegra186_cpufreq_cluster *cluster)
137145
{
138146
struct cpufreq_frequency_table *table;
139147
struct mrq_cpu_vhint_request req;
@@ -152,7 +160,7 @@ static struct cpufreq_frequency_table *init_vhint_table(
152160

153161
memset(&req, 0, sizeof(req));
154162
req.addr = phys;
155-
req.cluster_id = cluster_id;
163+
req.cluster_id = cluster->info->bpmp_cluster_id;
156164

157165
memset(&msg, 0, sizeof(msg));
158166
msg.mrq = MRQ_CPU_VHINT;
@@ -185,6 +193,9 @@ static struct cpufreq_frequency_table *init_vhint_table(
185193
goto free;
186194
}
187195

196+
cluster->ref_clk_khz = data->ref_clk_hz / 1000;
197+
cluster->div = data->pdiv * data->mdiv;
198+
188199
for (i = data->vfloor, j = 0; i <= data->vceil; i++) {
189200
struct cpufreq_frequency_table *point;
190201
u16 ndiv = data->ndiv[i];
@@ -202,8 +213,7 @@ static struct cpufreq_frequency_table *init_vhint_table(
202213

203214
point = &table[j++];
204215
point->driver_data = edvd_val;
205-
point->frequency = data->ref_clk_hz * ndiv / data->pdiv /
206-
data->mdiv / 1000;
216+
point->frequency = (cluster->ref_clk_khz * ndiv) / cluster->div;
207217
}
208218

209219
table[j].frequency = CPUFREQ_TABLE_END;
@@ -245,8 +255,7 @@ static int tegra186_cpufreq_probe(struct platform_device *pdev)
245255
struct tegra186_cpufreq_cluster *cluster = &data->clusters[i];
246256

247257
cluster->info = &tegra186_clusters[i];
248-
cluster->table = init_vhint_table(
249-
pdev, bpmp, cluster->info->bpmp_cluster_id);
258+
cluster->table = init_vhint_table(pdev, bpmp, cluster);
250259
if (IS_ERR(cluster->table)) {
251260
err = PTR_ERR(cluster->table);
252261
goto put_bpmp;

0 commit comments

Comments
 (0)