]>
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 <[email protected]> | |
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 SH |
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 | ||
8a67f0ef VK |
46 | static int dt_get_transition_latency(struct device *cpu_dev) |
47 | { | |
92a9b5c2 | 48 | struct device_node *np; |
8a67f0ef | 49 | u32 transition_latency = CPUFREQ_ETERNAL; |
8a67f0ef | 50 | |
da0eb143 SH |
51 | np = of_node_get(cpu_dev->of_node); |
52 | if (!np) { | |
53 | pr_info("Failed to find cpu node. Use CPUFREQ_ETERNAL transition latency\n"); | |
3c792e0f | 54 | return CPUFREQ_ETERNAL; |
da0eb143 | 55 | } |
763f8c3f | 56 | |
92a9b5c2 VK |
57 | of_property_read_u32(np, "clock-latency", &transition_latency); |
58 | of_node_put(np); | |
8a67f0ef | 59 | |
92a9b5c2 VK |
60 | pr_debug("%s: clock-latency: %d\n", __func__, transition_latency); |
61 | return transition_latency; | |
8a67f0ef VK |
62 | } |
63 | ||
64 | static struct cpufreq_arm_bL_ops dt_bL_ops = { | |
65 | .name = "dt-bl", | |
66 | .get_transition_latency = dt_get_transition_latency, | |
d9975b0b SH |
67 | .init_opp_table = dev_pm_opp_of_cpumask_add_table, |
68 | .free_opp_table = dev_pm_opp_of_cpumask_remove_table, | |
8a67f0ef VK |
69 | }; |
70 | ||
9076eaca | 71 | static int generic_bL_probe(struct platform_device *pdev) |
8a67f0ef | 72 | { |
92a9b5c2 VK |
73 | struct device_node *np; |
74 | ||
75 | np = get_cpu_node_with_valid_op(0); | |
76 | if (!np) | |
77 | return -ENODEV; | |
78 | ||
79 | of_node_put(np); | |
8a67f0ef VK |
80 | return bL_cpufreq_register(&dt_bL_ops); |
81 | } | |
8a67f0ef | 82 | |
9076eaca | 83 | static int generic_bL_remove(struct platform_device *pdev) |
8a67f0ef | 84 | { |
9076eaca VK |
85 | bL_cpufreq_unregister(&dt_bL_ops); |
86 | return 0; | |
8a67f0ef | 87 | } |
9076eaca VK |
88 | |
89 | static struct platform_driver generic_bL_platdrv = { | |
90 | .driver = { | |
91 | .name = "arm-bL-cpufreq-dt", | |
9076eaca VK |
92 | }, |
93 | .probe = generic_bL_probe, | |
94 | .remove = generic_bL_remove, | |
95 | }; | |
96 | module_platform_driver(generic_bL_platdrv); | |
8a67f0ef VK |
97 | |
98 | MODULE_AUTHOR("Viresh Kumar <[email protected]>"); | |
99 | MODULE_DESCRIPTION("Generic ARM big LITTLE cpufreq driver via DT"); | |
39c8bbaf | 100 | MODULE_LICENSE("GPL v2"); |