aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq/cpufreq-dt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/cpufreq/cpufreq-dt.c')
-rw-r--r--drivers/cpufreq/cpufreq-dt.c66
1 files changed, 43 insertions, 23 deletions
diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
index f657c571b18e..9bc2720628a4 100644
--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
@@ -58,6 +58,8 @@ static int set_target(struct cpufreq_policy *policy, unsigned int index)
58 old_freq = clk_get_rate(cpu_clk) / 1000; 58 old_freq = clk_get_rate(cpu_clk) / 1000;
59 59
60 if (!IS_ERR(cpu_reg)) { 60 if (!IS_ERR(cpu_reg)) {
61 unsigned long opp_freq;
62
61 rcu_read_lock(); 63 rcu_read_lock();
62 opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_Hz); 64 opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_Hz);
63 if (IS_ERR(opp)) { 65 if (IS_ERR(opp)) {
@@ -67,13 +69,16 @@ static int set_target(struct cpufreq_policy *policy, unsigned int index)
67 return PTR_ERR(opp); 69 return PTR_ERR(opp);
68 } 70 }
69 volt = dev_pm_opp_get_voltage(opp); 71 volt = dev_pm_opp_get_voltage(opp);
72 opp_freq = dev_pm_opp_get_freq(opp);
70 rcu_read_unlock(); 73 rcu_read_unlock();
71 tol = volt * priv->voltage_tolerance / 100; 74 tol = volt * priv->voltage_tolerance / 100;
72 volt_old = regulator_get_voltage(cpu_reg); 75 volt_old = regulator_get_voltage(cpu_reg);
76 dev_dbg(cpu_dev, "Found OPP: %ld kHz, %ld uV\n",
77 opp_freq / 1000, volt);
73 } 78 }
74 79
75 dev_dbg(cpu_dev, "%u MHz, %ld mV --> %u MHz, %ld mV\n", 80 dev_dbg(cpu_dev, "%u MHz, %ld mV --> %u MHz, %ld mV\n",
76 old_freq / 1000, volt_old ? volt_old / 1000 : -1, 81 old_freq / 1000, (volt_old > 0) ? volt_old / 1000 : -1,
77 new_freq / 1000, volt ? volt / 1000 : -1); 82 new_freq / 1000, volt ? volt / 1000 : -1);
78 83
79 /* scaling up? scale voltage before frequency */ 84 /* scaling up? scale voltage before frequency */
@@ -89,7 +94,7 @@ static int set_target(struct cpufreq_policy *policy, unsigned int index)
89 ret = clk_set_rate(cpu_clk, freq_exact); 94 ret = clk_set_rate(cpu_clk, freq_exact);
90 if (ret) { 95 if (ret) {
91 dev_err(cpu_dev, "failed to set clock rate: %d\n", ret); 96 dev_err(cpu_dev, "failed to set clock rate: %d\n", ret);
92 if (!IS_ERR(cpu_reg)) 97 if (!IS_ERR(cpu_reg) && volt_old > 0)
93 regulator_set_voltage_tol(cpu_reg, volt_old, tol); 98 regulator_set_voltage_tol(cpu_reg, volt_old, tol);
94 return ret; 99 return ret;
95 } 100 }
@@ -181,7 +186,6 @@ static int cpufreq_init(struct cpufreq_policy *policy)
181{ 186{
182 struct cpufreq_dt_platform_data *pd; 187 struct cpufreq_dt_platform_data *pd;
183 struct cpufreq_frequency_table *freq_table; 188 struct cpufreq_frequency_table *freq_table;
184 struct thermal_cooling_device *cdev;
185 struct device_node *np; 189 struct device_node *np;
186 struct private_data *priv; 190 struct private_data *priv;
187 struct device *cpu_dev; 191 struct device *cpu_dev;
@@ -210,7 +214,7 @@ static int cpufreq_init(struct cpufreq_policy *policy)
210 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 214 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
211 if (!priv) { 215 if (!priv) {
212 ret = -ENOMEM; 216 ret = -ENOMEM;
213 goto out_put_node; 217 goto out_free_opp;
214 } 218 }
215 219
216 of_property_read_u32(np, "voltage-tolerance", &priv->voltage_tolerance); 220 of_property_read_u32(np, "voltage-tolerance", &priv->voltage_tolerance);
@@ -264,20 +268,6 @@ static int cpufreq_init(struct cpufreq_policy *policy)
264 goto out_free_priv; 268 goto out_free_priv;
265 } 269 }
266 270
267 /*
268 * For now, just loading the cooling device;
269 * thermal DT code takes care of matching them.
270 */
271 if (of_find_property(np, "#cooling-cells", NULL)) {
272 cdev = of_cpufreq_cooling_register(np, cpu_present_mask);
273 if (IS_ERR(cdev))
274 dev_err(cpu_dev,
275 "running cpufreq without cooling device: %ld\n",
276 PTR_ERR(cdev));
277 else
278 priv->cdev = cdev;
279 }
280
281 priv->cpu_dev = cpu_dev; 271 priv->cpu_dev = cpu_dev;
282 priv->cpu_reg = cpu_reg; 272 priv->cpu_reg = cpu_reg;
283 policy->driver_data = priv; 273 policy->driver_data = priv;
@@ -287,7 +277,7 @@ static int cpufreq_init(struct cpufreq_policy *policy)
287 if (ret) { 277 if (ret) {
288 dev_err(cpu_dev, "%s: invalid frequency table: %d\n", __func__, 278 dev_err(cpu_dev, "%s: invalid frequency table: %d\n", __func__,
289 ret); 279 ret);
290 goto out_cooling_unregister; 280 goto out_free_cpufreq_table;
291 } 281 }
292 282
293 policy->cpuinfo.transition_latency = transition_latency; 283 policy->cpuinfo.transition_latency = transition_latency;
@@ -300,12 +290,12 @@ static int cpufreq_init(struct cpufreq_policy *policy)
300 290
301 return 0; 291 return 0;
302 292
303out_cooling_unregister: 293out_free_cpufreq_table:
304 cpufreq_cooling_unregister(priv->cdev);
305 dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); 294 dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
306out_free_priv: 295out_free_priv:
307 kfree(priv); 296 kfree(priv);
308out_put_node: 297out_free_opp:
298 of_free_opp_table(cpu_dev);
309 of_node_put(np); 299 of_node_put(np);
310out_put_reg_clk: 300out_put_reg_clk:
311 clk_put(cpu_clk); 301 clk_put(cpu_clk);
@@ -319,8 +309,10 @@ static int cpufreq_exit(struct cpufreq_policy *policy)
319{ 309{
320 struct private_data *priv = policy->driver_data; 310 struct private_data *priv = policy->driver_data;
321 311
322 cpufreq_cooling_unregister(priv->cdev); 312 if (priv->cdev)
313 cpufreq_cooling_unregister(priv->cdev);
323 dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table); 314 dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
315 of_free_opp_table(priv->cpu_dev);
324 clk_put(policy->clk); 316 clk_put(policy->clk);
325 if (!IS_ERR(priv->cpu_reg)) 317 if (!IS_ERR(priv->cpu_reg))
326 regulator_put(priv->cpu_reg); 318 regulator_put(priv->cpu_reg);
@@ -329,6 +321,33 @@ static int cpufreq_exit(struct cpufreq_policy *policy)
329 return 0; 321 return 0;
330} 322}
331 323
324static void cpufreq_ready(struct cpufreq_policy *policy)
325{
326 struct private_data *priv = policy->driver_data;
327 struct device_node *np = of_node_get(priv->cpu_dev->of_node);
328
329 if (WARN_ON(!np))
330 return;
331
332 /*
333 * For now, just loading the cooling device;
334 * thermal DT code takes care of matching them.
335 */
336 if (of_find_property(np, "#cooling-cells", NULL)) {
337 priv->cdev = of_cpufreq_cooling_register(np,
338 policy->related_cpus);
339 if (IS_ERR(priv->cdev)) {
340 dev_err(priv->cpu_dev,
341 "running cpufreq without cooling device: %ld\n",
342 PTR_ERR(priv->cdev));
343
344 priv->cdev = NULL;
345 }
346 }
347
348 of_node_put(np);
349}
350
332static struct cpufreq_driver dt_cpufreq_driver = { 351static struct cpufreq_driver dt_cpufreq_driver = {
333 .flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK, 352 .flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK,
334 .verify = cpufreq_generic_frequency_table_verify, 353 .verify = cpufreq_generic_frequency_table_verify,
@@ -336,6 +355,7 @@ static struct cpufreq_driver dt_cpufreq_driver = {
336 .get = cpufreq_generic_get, 355 .get = cpufreq_generic_get,
337 .init = cpufreq_init, 356 .init = cpufreq_init,
338 .exit = cpufreq_exit, 357 .exit = cpufreq_exit,
358 .ready = cpufreq_ready,
339 .name = "cpufreq-dt", 359 .name = "cpufreq-dt",
340 .attr = cpufreq_generic_attr, 360 .attr = cpufreq_generic_attr,
341}; 361};