aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq/arm_big_little_dt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/cpufreq/arm_big_little_dt.c')
-rw-r--r--drivers/cpufreq/arm_big_little_dt.c94
1 files changed, 58 insertions, 36 deletions
diff --git a/drivers/cpufreq/arm_big_little_dt.c b/drivers/cpufreq/arm_big_little_dt.c
index 44be3115375c..fd9e3ea6a480 100644
--- a/drivers/cpufreq/arm_big_little_dt.c
+++ b/drivers/cpufreq/arm_big_little_dt.c
@@ -19,69 +19,75 @@
19 19
20#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 20#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
21 21
22#include <linux/cpu.h>
22#include <linux/cpufreq.h> 23#include <linux/cpufreq.h>
23#include <linux/device.h> 24#include <linux/device.h>
24#include <linux/export.h> 25#include <linux/export.h>
25#include <linux/module.h> 26#include <linux/module.h>
26#include <linux/of.h> 27#include <linux/of.h>
27#include <linux/opp.h> 28#include <linux/opp.h>
29#include <linux/platform_device.h>
28#include <linux/slab.h> 30#include <linux/slab.h>
29#include <linux/types.h> 31#include <linux/types.h>
30#include "arm_big_little.h" 32#include "arm_big_little.h"
31 33
32static int dt_init_opp_table(struct device *cpu_dev) 34/* get cpu node with valid operating-points */
35static struct device_node *get_cpu_node_with_valid_op(int cpu)
33{ 36{
34 struct device_node *np, *parent; 37 struct device_node *np = NULL, *parent;
35 int count = 0, ret; 38 int count = 0;
36 39
37 parent = of_find_node_by_path("/cpus"); 40 parent = of_find_node_by_path("/cpus");
38 if (!parent) { 41 if (!parent) {
39 pr_err("failed to find OF /cpus\n"); 42 pr_err("failed to find OF /cpus\n");
40 return -ENOENT; 43 return NULL;
41 } 44 }
42 45
43 for_each_child_of_node(parent, np) { 46 for_each_child_of_node(parent, np) {
44 if (count++ != cpu_dev->id) 47 if (count++ != cpu)
45 continue; 48 continue;
46 if (!of_get_property(np, "operating-points", NULL)) { 49 if (!of_get_property(np, "operating-points", NULL)) {
47 ret = -ENODATA; 50 of_node_put(np);
48 } else { 51 np = NULL;
49 cpu_dev->of_node = np;
50 ret = of_init_opp_table(cpu_dev);
51 } 52 }
52 of_node_put(np);
53 of_node_put(parent);
54 53
55 return ret; 54 break;
56 } 55 }
57 56
58 return -ENODEV; 57 of_node_put(parent);
58 return np;
59} 59}
60 60
61static int dt_get_transition_latency(struct device *cpu_dev) 61static int dt_init_opp_table(struct device *cpu_dev)
62{ 62{
63 struct device_node *np, *parent; 63 struct device_node *np;
64 u32 transition_latency = CPUFREQ_ETERNAL; 64 int ret;
65 int count = 0;
66 65
67 parent = of_find_node_by_path("/cpus"); 66 np = get_cpu_node_with_valid_op(cpu_dev->id);
68 if (!parent) { 67 if (!np)
69 pr_err("failed to find OF /cpus\n"); 68 return -ENODATA;
70 return -ENOENT;
71 }
72 69
73 for_each_child_of_node(parent, np) { 70 cpu_dev->of_node = np;
74 if (count++ != cpu_dev->id) 71 ret = of_init_opp_table(cpu_dev);
75 continue; 72 of_node_put(np);
76 73
77 of_property_read_u32(np, "clock-latency", &transition_latency); 74 return ret;
78 of_node_put(np); 75}
79 of_node_put(parent);
80 76
81 return 0; 77static int dt_get_transition_latency(struct device *cpu_dev)
82 } 78{
79 struct device_node *np;
80 u32 transition_latency = CPUFREQ_ETERNAL;
81
82 np = get_cpu_node_with_valid_op(cpu_dev->id);
83 if (!np)
84 return CPUFREQ_ETERNAL;
83 85
84 return -ENODEV; 86 of_property_read_u32(np, "clock-latency", &transition_latency);
87 of_node_put(np);
88
89 pr_debug("%s: clock-latency: %d\n", __func__, transition_latency);
90 return transition_latency;
85} 91}
86 92
87static struct cpufreq_arm_bL_ops dt_bL_ops = { 93static struct cpufreq_arm_bL_ops dt_bL_ops = {
@@ -90,17 +96,33 @@ static struct cpufreq_arm_bL_ops dt_bL_ops = {
90 .init_opp_table = dt_init_opp_table, 96 .init_opp_table = dt_init_opp_table,
91}; 97};
92 98
93static int generic_bL_init(void) 99static int generic_bL_probe(struct platform_device *pdev)
94{ 100{
101 struct device_node *np;
102
103 np = get_cpu_node_with_valid_op(0);
104 if (!np)
105 return -ENODEV;
106
107 of_node_put(np);
95 return bL_cpufreq_register(&dt_bL_ops); 108 return bL_cpufreq_register(&dt_bL_ops);
96} 109}
97module_init(generic_bL_init);
98 110
99static void generic_bL_exit(void) 111static int generic_bL_remove(struct platform_device *pdev)
100{ 112{
101 return bL_cpufreq_unregister(&dt_bL_ops); 113 bL_cpufreq_unregister(&dt_bL_ops);
114 return 0;
102} 115}
103module_exit(generic_bL_exit); 116
117static struct platform_driver generic_bL_platdrv = {
118 .driver = {
119 .name = "arm-bL-cpufreq-dt",
120 .owner = THIS_MODULE,
121 },
122 .probe = generic_bL_probe,
123 .remove = generic_bL_remove,
124};
125module_platform_driver(generic_bL_platdrv);
104 126
105MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>"); 127MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>");
106MODULE_DESCRIPTION("Generic ARM big LITTLE cpufreq driver via DT"); 128MODULE_DESCRIPTION("Generic ARM big LITTLE cpufreq driver via DT");