aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPi-Cheng Chen <pi-cheng.chen@linaro.org>2015-12-09 22:48:13 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-12-11 20:27:16 -0500
commit89b56047f6f9b15fa3e9df3e34fa391835972ab7 (patch)
tree6bb8490762da6fd7905d586aebb4cad80a2988d1
parent63d1d656a5232f2f189b217b50542eadcf9d74ae (diff)
cpufreq: mt8173: Move resources allocation into ->probe()
Since the return value of ->init() of cpufreq driver is not propagated to the device driver model now, move resources allocation into ->probe() to handle -EPROBE_DEFER properly. Signed-off-by: Pi-Cheng Chen <pi-cheng.chen@linaro.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/cpufreq/mt8173-cpufreq.c92
1 files changed, 68 insertions, 24 deletions
diff --git a/drivers/cpufreq/mt8173-cpufreq.c b/drivers/cpufreq/mt8173-cpufreq.c
index 9d0fe37b4c3e..fd601b92f5ec 100644
--- a/drivers/cpufreq/mt8173-cpufreq.c
+++ b/drivers/cpufreq/mt8173-cpufreq.c
@@ -41,16 +41,35 @@
41 * the original PLL becomes stable at target frequency. 41 * the original PLL becomes stable at target frequency.
42 */ 42 */
43struct mtk_cpu_dvfs_info { 43struct mtk_cpu_dvfs_info {
44 struct cpumask cpus;
44 struct device *cpu_dev; 45 struct device *cpu_dev;
45 struct regulator *proc_reg; 46 struct regulator *proc_reg;
46 struct regulator *sram_reg; 47 struct regulator *sram_reg;
47 struct clk *cpu_clk; 48 struct clk *cpu_clk;
48 struct clk *inter_clk; 49 struct clk *inter_clk;
49 struct thermal_cooling_device *cdev; 50 struct thermal_cooling_device *cdev;
51 struct list_head list_head;
50 int intermediate_voltage; 52 int intermediate_voltage;
51 bool need_voltage_tracking; 53 bool need_voltage_tracking;
52}; 54};
53 55
56static LIST_HEAD(dvfs_info_list);
57
58static struct mtk_cpu_dvfs_info *mtk_cpu_dvfs_info_lookup(int cpu)
59{
60 struct mtk_cpu_dvfs_info *info;
61 struct list_head *list;
62
63 list_for_each(list, &dvfs_info_list) {
64 info = list_entry(list, struct mtk_cpu_dvfs_info, list_head);
65
66 if (cpumask_test_cpu(cpu, &info->cpus))
67 return info;
68 }
69
70 return NULL;
71}
72
54static int mtk_cpufreq_voltage_tracking(struct mtk_cpu_dvfs_info *info, 73static int mtk_cpufreq_voltage_tracking(struct mtk_cpu_dvfs_info *info,
55 int new_vproc) 74 int new_vproc)
56{ 75{
@@ -402,6 +421,9 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
402 */ 421 */
403 info->need_voltage_tracking = !IS_ERR(sram_reg); 422 info->need_voltage_tracking = !IS_ERR(sram_reg);
404 423
424 /* CPUs in the same cluster share a clock and power domain. */
425 cpumask_copy(&info->cpus, &cpu_topology[cpu].core_sibling);
426
405 return 0; 427 return 0;
406 428
407out_free_opp_table: 429out_free_opp_table:
@@ -440,22 +462,18 @@ static int mtk_cpufreq_init(struct cpufreq_policy *policy)
440 struct cpufreq_frequency_table *freq_table; 462 struct cpufreq_frequency_table *freq_table;
441 int ret; 463 int ret;
442 464
443 info = kzalloc(sizeof(*info), GFP_KERNEL); 465 info = mtk_cpu_dvfs_info_lookup(policy->cpu);
444 if (!info) 466 if (!info) {
445 return -ENOMEM; 467 pr_err("dvfs info for cpu%d is not initialized.\n",
446 468 policy->cpu);
447 ret = mtk_cpu_dvfs_info_init(info, policy->cpu); 469 return -EINVAL;
448 if (ret) {
449 pr_err("%s failed to initialize dvfs info for cpu%d\n",
450 __func__, policy->cpu);
451 goto out_free_dvfs_info;
452 } 470 }
453 471
454 ret = dev_pm_opp_init_cpufreq_table(info->cpu_dev, &freq_table); 472 ret = dev_pm_opp_init_cpufreq_table(info->cpu_dev, &freq_table);
455 if (ret) { 473 if (ret) {
456 pr_err("failed to init cpufreq table for cpu%d: %d\n", 474 pr_err("failed to init cpufreq table for cpu%d: %d\n",
457 policy->cpu, ret); 475 policy->cpu, ret);
458 goto out_release_dvfs_info; 476 return ret;
459 } 477 }
460 478
461 ret = cpufreq_table_validate_and_show(policy, freq_table); 479 ret = cpufreq_table_validate_and_show(policy, freq_table);
@@ -464,8 +482,7 @@ static int mtk_cpufreq_init(struct cpufreq_policy *policy)
464 goto out_free_cpufreq_table; 482 goto out_free_cpufreq_table;
465 } 483 }
466 484
467 /* CPUs in the same cluster share a clock and power domain. */ 485 cpumask_copy(policy->cpus, &info->cpus);
468 cpumask_copy(policy->cpus, &cpu_topology[policy->cpu].core_sibling);
469 policy->driver_data = info; 486 policy->driver_data = info;
470 policy->clk = info->cpu_clk; 487 policy->clk = info->cpu_clk;
471 488
@@ -473,13 +490,6 @@ static int mtk_cpufreq_init(struct cpufreq_policy *policy)
473 490
474out_free_cpufreq_table: 491out_free_cpufreq_table:
475 dev_pm_opp_free_cpufreq_table(info->cpu_dev, &freq_table); 492 dev_pm_opp_free_cpufreq_table(info->cpu_dev, &freq_table);
476
477out_release_dvfs_info:
478 mtk_cpu_dvfs_info_release(info);
479
480out_free_dvfs_info:
481 kfree(info);
482
483 return ret; 493 return ret;
484} 494}
485 495
@@ -489,8 +499,6 @@ static int mtk_cpufreq_exit(struct cpufreq_policy *policy)
489 499
490 cpufreq_cooling_unregister(info->cdev); 500 cpufreq_cooling_unregister(info->cdev);
491 dev_pm_opp_free_cpufreq_table(info->cpu_dev, &policy->freq_table); 501 dev_pm_opp_free_cpufreq_table(info->cpu_dev, &policy->freq_table);
492 mtk_cpu_dvfs_info_release(info);
493 kfree(info);
494 502
495 return 0; 503 return 0;
496} 504}
@@ -510,11 +518,47 @@ static struct cpufreq_driver mt8173_cpufreq_driver = {
510 518
511static int mt8173_cpufreq_probe(struct platform_device *pdev) 519static int mt8173_cpufreq_probe(struct platform_device *pdev)
512{ 520{
513 int ret; 521 struct mtk_cpu_dvfs_info *info;
522 struct list_head *list, *tmp;
523 int cpu, ret;
524
525 for_each_possible_cpu(cpu) {
526 info = mtk_cpu_dvfs_info_lookup(cpu);
527 if (info)
528 continue;
529
530 info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
531 if (!info) {
532 ret = -ENOMEM;
533 goto release_dvfs_info_list;
534 }
535
536 ret = mtk_cpu_dvfs_info_init(info, cpu);
537 if (ret) {
538 dev_err(&pdev->dev,
539 "failed to initialize dvfs info for cpu%d\n",
540 cpu);
541 goto release_dvfs_info_list;
542 }
543
544 list_add(&info->list_head, &dvfs_info_list);
545 }
514 546
515 ret = cpufreq_register_driver(&mt8173_cpufreq_driver); 547 ret = cpufreq_register_driver(&mt8173_cpufreq_driver);
516 if (ret) 548 if (ret) {
517 pr_err("failed to register mtk cpufreq driver\n"); 549 dev_err(&pdev->dev, "failed to register mtk cpufreq driver\n");
550 goto release_dvfs_info_list;
551 }
552
553 return 0;
554
555release_dvfs_info_list:
556 list_for_each_safe(list, tmp, &dvfs_info_list) {
557 info = list_entry(list, struct mtk_cpu_dvfs_info, list_head);
558
559 mtk_cpu_dvfs_info_release(info);
560 list_del(list);
561 }
518 562
519 return ret; 563 return ret;
520} 564}