Commit 848cb944213e88e4929a7efcc1c92bb6b6445353
Committed by
Rafael J. Wysocki
1 parent
2e6a5c80e6
Exists in
master
and in
16 other branches
cpufreq: at32ap: add frequency table
This patch adds a dynamically calculated frequency table to the at32ap driver. In short the architecture can scale in power of two between a maximum and minimum frequency. Min, max, and the steps in between are added to the table. Signed-off-by: Hans-Christian Egtvedt <egtvedt@samfundet.no> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Showing 1 changed file with 46 additions and 3 deletions Side-by-side Diff
drivers/cpufreq/at32ap-cpufreq.c
... | ... | @@ -19,8 +19,10 @@ |
19 | 19 | #include <linux/clk.h> |
20 | 20 | #include <linux/err.h> |
21 | 21 | #include <linux/export.h> |
22 | +#include <linux/slab.h> | |
22 | 23 | |
23 | 24 | static struct clk *cpuclk; |
25 | +static struct cpufreq_frequency_table *freq_table; | |
24 | 26 | |
25 | 27 | static int at32_verify_speed(struct cpufreq_policy *policy) |
26 | 28 | { |
27 | 29 | |
... | ... | @@ -85,13 +87,17 @@ |
85 | 87 | |
86 | 88 | static int __init at32_cpufreq_driver_init(struct cpufreq_policy *policy) |
87 | 89 | { |
90 | + unsigned int frequency, rate; | |
91 | + int retval, steps, i; | |
92 | + | |
88 | 93 | if (policy->cpu != 0) |
89 | 94 | return -EINVAL; |
90 | 95 | |
91 | 96 | cpuclk = clk_get(NULL, "cpu"); |
92 | 97 | if (IS_ERR(cpuclk)) { |
93 | 98 | pr_debug("cpufreq: could not get CPU clk\n"); |
94 | - return PTR_ERR(cpuclk); | |
99 | + retval = PTR_ERR(cpuclk); | |
100 | + goto out_err; | |
95 | 101 | } |
96 | 102 | |
97 | 103 | policy->cpuinfo.min_freq = (clk_round_rate(cpuclk, 1) + 500) / 1000; |
98 | 104 | |
... | ... | @@ -101,9 +107,46 @@ |
101 | 107 | policy->min = policy->cpuinfo.min_freq; |
102 | 108 | policy->max = policy->cpuinfo.max_freq; |
103 | 109 | |
104 | - printk("cpufreq: AT32AP CPU frequency driver\n"); | |
110 | + /* | |
111 | + * AVR32 CPU frequency rate scales in power of two between maximum and | |
112 | + * minimum, also add space for the table end marker. | |
113 | + * | |
114 | + * Further validate that the frequency is usable, and append it to the | |
115 | + * frequency table. | |
116 | + */ | |
117 | + steps = fls(policy->cpuinfo.max_freq / policy->cpuinfo.min_freq) + 1; | |
118 | + freq_table = kzalloc(steps * sizeof(struct cpufreq_frequency_table), | |
119 | + GFP_KERNEL); | |
120 | + if (!freq_table) { | |
121 | + retval = -ENOMEM; | |
122 | + goto out_err_put_clk; | |
123 | + } | |
105 | 124 | |
106 | - return 0; | |
125 | + frequency = policy->cpuinfo.max_freq; | |
126 | + for (i = 0; i < (steps - 1); i++) { | |
127 | + rate = clk_round_rate(cpuclk, frequency * 1000) / 1000; | |
128 | + | |
129 | + if (rate != frequency) | |
130 | + freq_table[i].frequency = CPUFREQ_ENTRY_INVALID; | |
131 | + else | |
132 | + freq_table[i].frequency = frequency; | |
133 | + | |
134 | + frequency /= 2; | |
135 | + } | |
136 | + | |
137 | + freq_table[steps - 1].frequency = CPUFREQ_TABLE_END; | |
138 | + | |
139 | + retval = cpufreq_table_validate_and_show(policy, freq_table); | |
140 | + if (!retval) { | |
141 | + printk("cpufreq: AT32AP CPU frequency driver\n"); | |
142 | + return 0; | |
143 | + } | |
144 | + | |
145 | + kfree(freq_table); | |
146 | +out_err_put_clk: | |
147 | + clk_put(cpuclk); | |
148 | +out_err: | |
149 | + return retval; | |
107 | 150 | } |
108 | 151 | |
109 | 152 | static struct cpufreq_driver at32_driver = { |