Commit | Line | Data |
---|---|---|
8a67f0ef VK |
1 | /* |
2 | * Generic big.LITTLE CPUFreq Interface driver | |
3 | * | |
4 | * It provides necessary ops to arm_big_little cpufreq driver and gets | |
5 | * Frequency information from Device Tree. Freq table in DT must be in KHz. | |
6 | * | |
7 | * Copyright (C) 2013 Linaro. | |
8 | * Viresh Kumar <viresh.kumar@linaro.org> | |
9 | * | |
10 | * This program is free software; you can redistribute it and/or modify | |
11 | * it under the terms of the GNU General Public License version 2 as | |
12 | * published by the Free Software Foundation. | |
13 | * | |
14 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | |
15 | * kind, whether express or implied; without even the implied warranty | |
16 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | * GNU General Public License for more details. | |
18 | */ | |
19 | ||
20 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
21 | ||
22 | #include <linux/cpufreq.h> | |
23 | #include <linux/device.h> | |
24 | #include <linux/export.h> | |
25 | #include <linux/module.h> | |
da0eb143 | 26 | #include <linux/of_device.h> |
e4db1c74 | 27 | #include <linux/pm_opp.h> |
9076eaca | 28 | #include <linux/platform_device.h> |
8a67f0ef VK |
29 | #include <linux/slab.h> |
30 | #include <linux/types.h> | |
31 | #include "arm_big_little.h" | |
32 | ||
92a9b5c2 VK |
33 | /* get cpu node with valid operating-points */ |
34 | static struct device_node *get_cpu_node_with_valid_op(int cpu) | |
8a67f0ef | 35 | { |
da0eb143 | 36 | struct device_node *np = of_cpu_device_node_get(cpu); |
8a67f0ef | 37 | |
da0eb143 SK |
38 | if (!of_get_property(np, "operating-points", NULL)) { |
39 | of_node_put(np); | |
40 | np = NULL; | |
763f8c3f VK |
41 | } |
42 | ||
92a9b5c2 VK |
43 | return np; |
44 | } | |
45 | ||
46 | static int dt_init_opp_table(struct device *cpu_dev) | |
47 | { | |
48 | struct device_node *np; | |
49 | int ret; | |
50 | ||
da0eb143 SK |
51 | np = of_node_get(cpu_dev->of_node); |
52 | if (!np) { | |
53 | pr_err("failed to find cpu%d node\n", cpu_dev->id); | |
54 | return -ENOENT; | |
55 | } | |
92a9b5c2 | 56 | |
92a9b5c2 VK |
57 | ret = of_init_opp_table(cpu_dev); |
58 | of_node_put(np); | |
59 | ||
60 | return ret; | |
8a67f0ef VK |
61 | } |
62 | ||
63 | static int dt_get_transition_latency(struct device *cpu_dev) | |
64 | { | |
92a9b5c2 | 65 | struct device_node *np; |
8a67f0ef | 66 | u32 transition_latency = CPUFREQ_ETERNAL; |
8a67f0ef | 67 | |
da0eb143 SK |
68 | np = of_node_get(cpu_dev->of_node); |
69 | if (!np) { | |
70 | pr_info("Failed to find cpu node. Use CPUFREQ_ETERNAL transition latency\n"); | |
3c792e0f | 71 | return CPUFREQ_ETERNAL; |
da0eb143 | 72 | } |
763f8c3f | 73 | |
92a9b5c2 VK |
74 | of_property_read_u32(np, "clock-latency", &transition_latency); |
75 | of_node_put(np); | |
8a67f0ef | 76 | |
92a9b5c2 VK |
77 | pr_debug("%s: clock-latency: %d\n", __func__, transition_latency); |
78 | return transition_latency; | |
8a67f0ef VK |
79 | } |
80 | ||
81 | static struct cpufreq_arm_bL_ops dt_bL_ops = { | |
82 | .name = "dt-bl", | |
83 | .get_transition_latency = dt_get_transition_latency, | |
84 | .init_opp_table = dt_init_opp_table, | |
85 | }; | |
86 | ||
9076eaca | 87 | static int generic_bL_probe(struct platform_device *pdev) |
8a67f0ef | 88 | { |
92a9b5c2 VK |
89 | struct device_node *np; |
90 | ||
91 | np = get_cpu_node_with_valid_op(0); | |
92 | if (!np) | |
93 | return -ENODEV; | |
94 | ||
95 | of_node_put(np); | |
8a67f0ef VK |
96 | return bL_cpufreq_register(&dt_bL_ops); |
97 | } | |
8a67f0ef | 98 | |
9076eaca | 99 | static int generic_bL_remove(struct platform_device *pdev) |
8a67f0ef | 100 | { |
9076eaca VK |
101 | bL_cpufreq_unregister(&dt_bL_ops); |
102 | return 0; | |
8a67f0ef | 103 | } |
9076eaca VK |
104 | |
105 | static struct platform_driver generic_bL_platdrv = { | |
106 | .driver = { | |
107 | .name = "arm-bL-cpufreq-dt", | |
108 | .owner = THIS_MODULE, | |
109 | }, | |
110 | .probe = generic_bL_probe, | |
111 | .remove = generic_bL_remove, | |
112 | }; | |
113 | module_platform_driver(generic_bL_platdrv); | |
8a67f0ef VK |
114 | |
115 | MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>"); | |
116 | MODULE_DESCRIPTION("Generic ARM big LITTLE cpufreq driver via DT"); | |
117 | MODULE_LICENSE("GPL"); |