Commit 848cb944213e88e4929a7efcc1c92bb6b6445353

Authored by Hans-Christian Egtvedt
Committed by Rafael J. Wysocki
1 parent 2e6a5c80e6

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 = {