aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/cpufreq/powernow-k6.c76
1 files changed, 72 insertions, 4 deletions
diff --git a/drivers/cpufreq/powernow-k6.c b/drivers/cpufreq/powernow-k6.c
index 1332b72f373a..16359ab2c459 100644
--- a/drivers/cpufreq/powernow-k6.c
+++ b/drivers/cpufreq/powernow-k6.c
@@ -26,6 +26,14 @@
26static unsigned int busfreq; /* FSB, in 10 kHz */ 26static unsigned int busfreq; /* FSB, in 10 kHz */
27static unsigned int max_multiplier; 27static unsigned int max_multiplier;
28 28
29static unsigned int param_busfreq = 0;
30static unsigned int param_max_multiplier = 0;
31
32module_param_named(max_multiplier, param_max_multiplier, uint, S_IRUGO);
33MODULE_PARM_DESC(max_multiplier, "Maximum multiplier (allowed values: 20 30 35 40 45 50 55 60)");
34
35module_param_named(bus_frequency, param_busfreq, uint, S_IRUGO);
36MODULE_PARM_DESC(bus_frequency, "Bus frequency in kHz");
29 37
30/* Clock ratio multiplied by 10 - see table 27 in AMD#23446 */ 38/* Clock ratio multiplied by 10 - see table 27 in AMD#23446 */
31static struct cpufreq_frequency_table clock_ratio[] = { 39static struct cpufreq_frequency_table clock_ratio[] = {
@@ -40,6 +48,27 @@ static struct cpufreq_frequency_table clock_ratio[] = {
40 {0, CPUFREQ_TABLE_END} 48 {0, CPUFREQ_TABLE_END}
41}; 49};
42 50
51static const struct {
52 unsigned freq;
53 unsigned mult;
54} usual_frequency_table[] = {
55 { 400000, 40 }, // 100 * 4
56 { 450000, 45 }, // 100 * 4.5
57 { 475000, 50 }, // 95 * 5
58 { 500000, 50 }, // 100 * 5
59 { 506250, 45 }, // 112.5 * 4.5
60 { 533500, 55 }, // 97 * 5.5
61 { 550000, 55 }, // 100 * 5.5
62 { 562500, 50 }, // 112.5 * 5
63 { 570000, 60 }, // 95 * 6
64 { 600000, 60 }, // 100 * 6
65 { 618750, 55 }, // 112.5 * 5.5
66 { 660000, 55 }, // 120 * 5.5
67 { 675000, 60 }, // 112.5 * 6
68 { 720000, 60 }, // 120 * 6
69};
70
71#define FREQ_RANGE 3000
43 72
44/** 73/**
45 * powernow_k6_get_cpu_multiplier - returns the current FSB multiplier 74 * powernow_k6_get_cpu_multiplier - returns the current FSB multiplier
@@ -125,17 +154,56 @@ static int powernow_k6_target(struct cpufreq_policy *policy,
125 return 0; 154 return 0;
126} 155}
127 156
128
129static int powernow_k6_cpu_init(struct cpufreq_policy *policy) 157static int powernow_k6_cpu_init(struct cpufreq_policy *policy)
130{ 158{
131 unsigned int i, f; 159 unsigned int i, f;
160 unsigned khz;
132 161
133 if (policy->cpu != 0) 162 if (policy->cpu != 0)
134 return -ENODEV; 163 return -ENODEV;
135 164
136 /* get frequencies */ 165 max_multiplier = 0;
137 max_multiplier = powernow_k6_get_cpu_multiplier(); 166 khz = cpu_khz;
138 busfreq = cpu_khz / max_multiplier; 167 for (i = 0; i < ARRAY_SIZE(usual_frequency_table); i++) {
168 if (khz >= usual_frequency_table[i].freq - FREQ_RANGE &&
169 khz <= usual_frequency_table[i].freq + FREQ_RANGE) {
170 khz = usual_frequency_table[i].freq;
171 max_multiplier = usual_frequency_table[i].mult;
172 break;
173 }
174 }
175 if (param_max_multiplier) {
176 for (i = 0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) {
177 if (clock_ratio[i].driver_data == param_max_multiplier) {
178 max_multiplier = param_max_multiplier;
179 goto have_max_multiplier;
180 }
181 }
182 printk(KERN_ERR "powernow-k6: invalid max_multiplier parameter, valid parameters 20, 30, 35, 40, 45, 50, 55, 60\n");
183 return -EINVAL;
184 }
185
186 if (!max_multiplier) {
187 printk(KERN_WARNING "powernow-k6: unknown frequency %u, cannot determine current multiplier\n", khz);
188 printk(KERN_WARNING "powernow-k6: use module parameters max_multiplier and bus_frequency\n");
189 return -EOPNOTSUPP;
190 }
191
192have_max_multiplier:
193 param_max_multiplier = max_multiplier;
194
195 if (param_busfreq) {
196 if (param_busfreq >= 50000 && param_busfreq <= 150000) {
197 busfreq = param_busfreq / 10;
198 goto have_busfreq;
199 }
200 printk(KERN_ERR "powernow-k6: invalid bus_frequency parameter, allowed range 50000 - 150000 kHz\n");
201 return -EINVAL;
202 }
203
204 busfreq = khz / max_multiplier;
205have_busfreq:
206 param_busfreq = busfreq * 10;
139 207
140 /* table init */ 208 /* table init */
141 for (i = 0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) { 209 for (i = 0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) {