blob: 1b446d79a8fdd2d2a92f8ea04dbaa41da57a4f88 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * AMD K7 Powernow driver.
Dave Jonesf4432c52008-10-20 13:31:45 -04003 * (C) 2003 Dave Jones on behalf of SuSE Labs.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 * (C) 2003-2004 Dave Jones <davej@redhat.com>
5 *
6 * Licensed under the terms of the GNU GPL License version 2.
7 * Based upon datasheets & sample CPUs kindly provided by AMD.
8 *
9 * Errata 5: Processor may fail to execute a FID/VID change in presence of interrupt.
10 * - We cli/sti on stepping A0 CPUs around the FID/VID transition.
11 * Errata 15: Processors with half frequency multipliers may hang upon wakeup from disconnect.
12 * - We disable half multipliers if ACPI is used on A0 stepping CPUs.
13 */
14
Linus Torvalds1da177e2005-04-16 15:20:36 -070015#include <linux/kernel.h>
16#include <linux/module.h>
17#include <linux/moduleparam.h>
18#include <linux/init.h>
19#include <linux/cpufreq.h>
20#include <linux/slab.h>
21#include <linux/string.h>
22#include <linux/dmi.h>
23
24#include <asm/msr.h>
Dave Jones91350ed2005-05-31 19:03:45 -070025#include <asm/timer.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <asm/timex.h>
27#include <asm/io.h>
28#include <asm/system.h>
29
30#ifdef CONFIG_X86_POWERNOW_K7_ACPI
31#include <linux/acpi.h>
32#include <acpi/processor.h>
33#endif
34
35#include "powernow-k7.h"
36
37#define PFX "powernow: "
38
39
40struct psb_s {
41 u8 signature[10];
42 u8 tableversion;
43 u8 flags;
44 u16 settlingtime;
45 u8 reserved1;
46 u8 numpst;
47};
48
49struct pst_s {
50 u32 cpuid;
51 u8 fsbspeed;
52 u8 maxfid;
53 u8 startvid;
54 u8 numpstates;
55};
56
57#ifdef CONFIG_X86_POWERNOW_K7_ACPI
58union powernow_acpi_control_t {
59 struct {
60 unsigned long fid:5,
61 vid:5,
62 sgtc:20,
63 res1:2;
64 } bits;
65 unsigned long val;
66};
67#endif
68
69#ifdef CONFIG_CPU_FREQ_DEBUG
70/* divide by 1000 to get VCore voltage in V. */
Dave Jonesbd5ab262007-02-22 19:11:16 -050071static const int mobile_vid_table[32] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070072 2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650,
73 1600, 1550, 1500, 1450, 1400, 1350, 1300, 0,
74 1275, 1250, 1225, 1200, 1175, 1150, 1125, 1100,
75 1075, 1050, 1025, 1000, 975, 950, 925, 0,
76};
77#endif
78
79/* divide by 10 to get FID. */
Dave Jonesbd5ab262007-02-22 19:11:16 -050080static const int fid_codes[32] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070081 110, 115, 120, 125, 50, 55, 60, 65,
82 70, 75, 80, 85, 90, 95, 100, 105,
83 30, 190, 40, 200, 130, 135, 140, 210,
84 150, 225, 160, 165, 170, 180, -1, -1,
85};
86
87/* This parameter is used in order to force ACPI instead of legacy method for
88 * configuration purpose.
89 */
90
91static int acpi_force;
92
93static struct cpufreq_frequency_table *powernow_table;
94
95static unsigned int can_scale_bus;
96static unsigned int can_scale_vid;
97static unsigned int minimum_speed=-1;
98static unsigned int maximum_speed;
99static unsigned int number_scales;
100static unsigned int fsb;
101static unsigned int latency;
102static char have_a0;
103
104#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "powernow-k7", msg)
105
106static int check_fsb(unsigned int fsbspeed)
107{
108 int delta;
109 unsigned int f = fsb / 1000;
110
111 delta = (fsbspeed > f) ? fsbspeed - f : f - fsbspeed;
112 return (delta < 5);
113}
114
115static int check_powernow(void)
116{
Mike Travis92cb7612007-10-19 20:35:04 +0200117 struct cpuinfo_x86 *c = &cpu_data(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118 unsigned int maxei, eax, ebx, ecx, edx;
119
120 if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 !=6)) {
121#ifdef MODULE
122 printk (KERN_INFO PFX "This module only works with AMD K7 CPUs\n");
123#endif
124 return 0;
125 }
126
127 /* Get maximum capabilities */
128 maxei = cpuid_eax (0x80000000);
129 if (maxei < 0x80000007) { /* Any powernow info ? */
130#ifdef MODULE
131 printk (KERN_INFO PFX "No powernow capabilities detected\n");
132#endif
133 return 0;
134 }
135
136 if ((c->x86_model == 6) && (c->x86_mask == 0)) {
137 printk (KERN_INFO PFX "K7 660[A0] core detected, enabling errata workarounds\n");
138 have_a0 = 1;
139 }
140
141 cpuid(0x80000007, &eax, &ebx, &ecx, &edx);
142
143 /* Check we can actually do something before we say anything.*/
144 if (!(edx & (1 << 1 | 1 << 2)))
145 return 0;
146
147 printk (KERN_INFO PFX "PowerNOW! Technology present. Can scale: ");
148
149 if (edx & 1 << 1) {
150 printk ("frequency");
151 can_scale_bus=1;
152 }
153
154 if ((edx & (1 << 1 | 1 << 2)) == 0x6)
155 printk (" and ");
156
157 if (edx & 1 << 2) {
158 printk ("voltage");
159 can_scale_vid=1;
160 }
161
162 printk (".\n");
163 return 1;
164}
165
166
167static int get_ranges (unsigned char *pst)
168{
169 unsigned int j;
170 unsigned int speed;
171 u8 fid, vid;
172
Dave Jonesbfdc7082005-10-20 15:16:15 -0700173 powernow_table = kzalloc((sizeof(struct cpufreq_frequency_table) * (number_scales + 1)), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174 if (!powernow_table)
175 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176
177 for (j=0 ; j < number_scales; j++) {
178 fid = *pst++;
179
180 powernow_table[j].frequency = (fsb * fid_codes[fid]) / 10;
181 powernow_table[j].index = fid; /* lower 8 bits */
182
183 speed = powernow_table[j].frequency;
184
185 if ((fid_codes[fid] % 10)==5) {
186#ifdef CONFIG_X86_POWERNOW_K7_ACPI
187 if (have_a0 == 1)
188 powernow_table[j].frequency = CPUFREQ_ENTRY_INVALID;
189#endif
190 }
191
192 if (speed < minimum_speed)
193 minimum_speed = speed;
194 if (speed > maximum_speed)
195 maximum_speed = speed;
196
197 vid = *pst++;
198 powernow_table[j].index |= (vid << 8); /* upper 8 bits */
199
200 dprintk (" FID: 0x%x (%d.%dx [%dMHz]) "
Dave Jones32ee8c32006-02-28 00:43:23 -0500201 "VID: 0x%x (%d.%03dV)\n", fid, fid_codes[fid] / 10,
202 fid_codes[fid] % 10, speed/1000, vid,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203 mobile_vid_table[vid]/1000,
204 mobile_vid_table[vid]%1000);
205 }
206 powernow_table[number_scales].frequency = CPUFREQ_TABLE_END;
207 powernow_table[number_scales].index = 0;
208
209 return 0;
210}
211
212
213static void change_FID(int fid)
214{
215 union msr_fidvidctl fidvidctl;
216
217 rdmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val);
218 if (fidvidctl.bits.FID != fid) {
219 fidvidctl.bits.SGTC = latency;
220 fidvidctl.bits.FID = fid;
221 fidvidctl.bits.VIDC = 0;
222 fidvidctl.bits.FIDC = 1;
223 wrmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val);
224 }
225}
226
227
228static void change_VID(int vid)
229{
230 union msr_fidvidctl fidvidctl;
231
232 rdmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val);
233 if (fidvidctl.bits.VID != vid) {
234 fidvidctl.bits.SGTC = latency;
235 fidvidctl.bits.VID = vid;
236 fidvidctl.bits.FIDC = 0;
237 fidvidctl.bits.VIDC = 1;
238 wrmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val);
239 }
240}
241
242
243static void change_speed (unsigned int index)
244{
245 u8 fid, vid;
246 struct cpufreq_freqs freqs;
247 union msr_fidvidstatus fidvidstatus;
248 int cfid;
249
250 /* fid are the lower 8 bits of the index we stored into
251 * the cpufreq frequency table in powernow_decode_bios,
252 * vid are the upper 8 bits.
253 */
254
255 fid = powernow_table[index].index & 0xFF;
256 vid = (powernow_table[index].index & 0xFF00) >> 8;
257
258 freqs.cpu = 0;
259
260 rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val);
261 cfid = fidvidstatus.bits.CFID;
262 freqs.old = fsb * fid_codes[cfid] / 10;
263
264 freqs.new = powernow_table[index].frequency;
265
266 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
267
268 /* Now do the magic poking into the MSRs. */
269
270 if (have_a0 == 1) /* A0 errata 5 */
271 local_irq_disable();
272
273 if (freqs.old > freqs.new) {
274 /* Going down, so change FID first */
275 change_FID(fid);
276 change_VID(vid);
277 } else {
278 /* Going up, so change VID first */
279 change_VID(vid);
280 change_FID(fid);
281 }
282
283
284 if (have_a0 == 1)
285 local_irq_enable();
286
287 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
288}
289
290
291#ifdef CONFIG_X86_POWERNOW_K7_ACPI
292
293static struct acpi_processor_performance *acpi_processor_perf;
294
295static int powernow_acpi_init(void)
296{
297 int i;
298 int retval = 0;
299 union powernow_acpi_control_t pc;
300
301 if (acpi_processor_perf != NULL && powernow_table != NULL) {
302 retval = -EINVAL;
303 goto err0;
304 }
305
Dave Jonesbfdc7082005-10-20 15:16:15 -0700306 acpi_processor_perf = kzalloc(sizeof(struct acpi_processor_performance),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308 if (!acpi_processor_perf) {
309 retval = -ENOMEM;
310 goto err0;
311 }
312
Rusty Russell2fdf66b2008-12-31 18:08:47 -0800313 if (!alloc_cpumask_var(&acpi_processor_perf->shared_cpu_map,
314 GFP_KERNEL)) {
315 retval = -ENOMEM;
316 goto err05;
317 }
318
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319 if (acpi_processor_register_performance(acpi_processor_perf, 0)) {
320 retval = -EIO;
321 goto err1;
322 }
323
324 if (acpi_processor_perf->control_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) {
325 retval = -ENODEV;
326 goto err2;
327 }
328
329 if (acpi_processor_perf->status_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) {
330 retval = -ENODEV;
331 goto err2;
332 }
333
334 number_scales = acpi_processor_perf->state_count;
335
336 if (number_scales < 2) {
337 retval = -ENODEV;
338 goto err2;
339 }
340
Dave Jonesbfdc7082005-10-20 15:16:15 -0700341 powernow_table = kzalloc((number_scales + 1) * (sizeof(struct cpufreq_frequency_table)), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 if (!powernow_table) {
343 retval = -ENOMEM;
344 goto err2;
345 }
346
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347 pc.val = (unsigned long) acpi_processor_perf->states[0].control;
348 for (i = 0; i < number_scales; i++) {
349 u8 fid, vid;
Daniel Drakedc2585e2007-05-02 23:19:05 +0100350 struct acpi_processor_px *state =
351 &acpi_processor_perf->states[i];
352 unsigned int speed, speed_mhz;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353
Daniel Drakedc2585e2007-05-02 23:19:05 +0100354 pc.val = (unsigned long) state->control;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 dprintk ("acpi: P%d: %d MHz %d mW %d uS control %08x SGTC %d\n",
356 i,
Daniel Drakedc2585e2007-05-02 23:19:05 +0100357 (u32) state->core_frequency,
358 (u32) state->power,
359 (u32) state->transition_latency,
360 (u32) state->control,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361 pc.bits.sgtc);
362
363 vid = pc.bits.vid;
364 fid = pc.bits.fid;
365
366 powernow_table[i].frequency = fsb * fid_codes[fid] / 10;
367 powernow_table[i].index = fid; /* lower 8 bits */
368 powernow_table[i].index |= (vid << 8); /* upper 8 bits */
369
370 speed = powernow_table[i].frequency;
Daniel Drakedc2585e2007-05-02 23:19:05 +0100371 speed_mhz = speed / 1000;
372
373 /* processor_perflib will multiply the MHz value by 1000 to
374 * get a KHz value (e.g. 1266000). However, powernow-k7 works
375 * with true KHz values (e.g. 1266768). To ensure that all
376 * powernow frequencies are available, we must ensure that
377 * ACPI doesn't restrict them, so we round up the MHz value
378 * to ensure that perflib's computed KHz value is greater than
379 * or equal to powernow's KHz value.
380 */
381 if (speed % 1000 > 0)
382 speed_mhz++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383
384 if ((fid_codes[fid] % 10)==5) {
385 if (have_a0 == 1)
386 powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
387 }
388
389 dprintk (" FID: 0x%x (%d.%dx [%dMHz]) "
Dave Jones32ee8c32006-02-28 00:43:23 -0500390 "VID: 0x%x (%d.%03dV)\n", fid, fid_codes[fid] / 10,
Daniel Drakedc2585e2007-05-02 23:19:05 +0100391 fid_codes[fid] % 10, speed_mhz, vid,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 mobile_vid_table[vid]/1000,
393 mobile_vid_table[vid]%1000);
394
Daniel Drakedc2585e2007-05-02 23:19:05 +0100395 if (state->core_frequency != speed_mhz) {
396 state->core_frequency = speed_mhz;
397 dprintk(" Corrected ACPI frequency to %d\n",
398 speed_mhz);
399 }
400
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 if (latency < pc.bits.sgtc)
402 latency = pc.bits.sgtc;
403
404 if (speed < minimum_speed)
405 minimum_speed = speed;
406 if (speed > maximum_speed)
407 maximum_speed = speed;
408 }
409
410 powernow_table[i].frequency = CPUFREQ_TABLE_END;
411 powernow_table[i].index = 0;
412
413 /* notify BIOS that we exist */
414 acpi_processor_notify_smm(THIS_MODULE);
415
416 return 0;
417
418err2:
419 acpi_processor_unregister_performance(acpi_processor_perf, 0);
420err1:
Rusty Russell2fdf66b2008-12-31 18:08:47 -0800421 free_cpumask_var(acpi_processor_perf->shared_cpu_map);
422err05:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 kfree(acpi_processor_perf);
424err0:
425 printk(KERN_WARNING PFX "ACPI perflib can not be used in this platform\n");
426 acpi_processor_perf = NULL;
427 return retval;
428}
429#else
430static int powernow_acpi_init(void)
431{
432 printk(KERN_INFO PFX "no support for ACPI processor found."
433 " Please recompile your kernel with ACPI processor\n");
434 return -EINVAL;
435}
436#endif
437
438static int powernow_decode_bios (int maxfid, int startvid)
439{
440 struct psb_s *psb;
441 struct pst_s *pst;
442 unsigned int i, j;
443 unsigned char *p;
444 unsigned int etuple;
445 unsigned int ret;
446
447 etuple = cpuid_eax(0x80000001);
448
449 for (i=0xC0000; i < 0xffff0 ; i+=16) {
450
451 p = phys_to_virt(i);
452
453 if (memcmp(p, "AMDK7PNOW!", 10) == 0){
454 dprintk ("Found PSB header at %p\n", p);
455 psb = (struct psb_s *) p;
456 dprintk ("Table version: 0x%x\n", psb->tableversion);
457 if (psb->tableversion != 0x12) {
458 printk (KERN_INFO PFX "Sorry, only v1.2 tables supported right now\n");
459 return -ENODEV;
460 }
461
462 dprintk ("Flags: 0x%x\n", psb->flags);
463 if ((psb->flags & 1)==0) {
464 dprintk ("Mobile voltage regulator\n");
465 } else {
466 dprintk ("Desktop voltage regulator\n");
467 }
468
469 latency = psb->settlingtime;
470 if (latency < 100) {
Joe Perchescdbec9a2007-11-19 17:48:01 -0800471 printk(KERN_INFO PFX "BIOS set settling time to %d microseconds. "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 "Should be at least 100. Correcting.\n", latency);
473 latency = 100;
474 }
475 dprintk ("Settling Time: %d microseconds.\n", psb->settlingtime);
476 dprintk ("Has %d PST tables. (Only dumping ones relevant to this CPU).\n", psb->numpst);
477
478 p += sizeof (struct psb_s);
479
480 pst = (struct pst_s *) p;
481
Dave Jones8cbe0162006-05-30 17:26:08 -0400482 for (j=0; j<psb->numpst; j++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 pst = (struct pst_s *) p;
484 number_scales = pst->numpstates;
485
486 if ((etuple == pst->cpuid) && check_fsb(pst->fsbspeed) &&
487 (maxfid==pst->maxfid) && (startvid==pst->startvid))
488 {
Dave Jones8cbe0162006-05-30 17:26:08 -0400489 dprintk ("PST:%d (@%p)\n", j, pst);
Dave Jones32ee8c32006-02-28 00:43:23 -0500490 dprintk (" cpuid: 0x%x fsb: %d maxFID: 0x%x startvid: 0x%x\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491 pst->cpuid, pst->fsbspeed, pst->maxfid, pst->startvid);
492
493 ret = get_ranges ((char *) pst + sizeof (struct pst_s));
494 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 } else {
Dave Jones8cbe0162006-05-30 17:26:08 -0400496 unsigned int k;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 p = (char *) pst + sizeof (struct pst_s);
Dave Jones8cbe0162006-05-30 17:26:08 -0400498 for (k=0; k<number_scales; k++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 p+=2;
500 }
501 }
502 printk (KERN_INFO PFX "No PST tables match this cpuid (0x%x)\n", etuple);
503 printk (KERN_INFO PFX "This is indicative of a broken BIOS.\n");
504
505 return -EINVAL;
506 }
507 p++;
508 }
509
510 return -ENODEV;
511}
512
513
514static int powernow_target (struct cpufreq_policy *policy,
515 unsigned int target_freq,
516 unsigned int relation)
517{
518 unsigned int newstate;
519
520 if (cpufreq_frequency_table_target(policy, powernow_table, target_freq, relation, &newstate))
521 return -EINVAL;
522
523 change_speed(newstate);
524
525 return 0;
526}
527
528
529static int powernow_verify (struct cpufreq_policy *policy)
530{
531 return cpufreq_frequency_table_verify(policy, powernow_table);
532}
533
534/*
535 * We use the fact that the bus frequency is somehow
536 * a multiple of 100000/3 khz, then we compute sgtc according
537 * to this multiple.
538 * That way, we match more how AMD thinks all of that work.
539 * We will then get the same kind of behaviour already tested under
540 * the "well-known" other OS.
541 */
542static int __init fixup_sgtc(void)
543{
544 unsigned int sgtc;
545 unsigned int m;
546
547 m = fsb / 3333;
548 if ((m % 10) >= 5)
549 m += 5;
550
551 m /= 10;
552
553 sgtc = 100 * m * latency;
554 sgtc = sgtc / 3;
555 if (sgtc > 0xfffff) {
556 printk(KERN_WARNING PFX "SGTC too large %d\n", sgtc);
557 sgtc = 0xfffff;
558 }
559 return sgtc;
560}
561
562static unsigned int powernow_get(unsigned int cpu)
563{
564 union msr_fidvidstatus fidvidstatus;
565 unsigned int cfid;
566
567 if (cpu)
568 return 0;
569 rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val);
570 cfid = fidvidstatus.bits.CFID;
571
572 return (fsb * fid_codes[cfid] / 10);
573}
574
575
Thomas Gleixner0b4b5dd2007-10-17 18:04:40 +0200576static int __init acer_cpufreq_pst(const struct dmi_system_id *d)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577{
578 printk(KERN_WARNING "%s laptop with broken PST tables in BIOS detected.\n", d->ident);
579 printk(KERN_WARNING "You need to downgrade to 3A21 (09/09/2002), or try a newer BIOS than 3A71 (01/20/2003)\n");
580 printk(KERN_WARNING "cpufreq scaling has been disabled as a result of this.\n");
581 return 0;
582}
583
584/*
585 * Some Athlon laptops have really fucked PST tables.
586 * A BIOS update is all that can save them.
587 * Mention this, and disable cpufreq.
588 */
589static struct dmi_system_id __initdata powernow_dmi_table[] = {
590 {
591 .callback = acer_cpufreq_pst,
592 .ident = "Acer Aspire",
593 .matches = {
594 DMI_MATCH(DMI_SYS_VENDOR, "Insyde Software"),
595 DMI_MATCH(DMI_BIOS_VERSION, "3A71"),
596 },
597 },
598 { }
599};
600
601static int __init powernow_cpu_init (struct cpufreq_policy *policy)
602{
603 union msr_fidvidstatus fidvidstatus;
604 int result;
605
606 if (policy->cpu != 0)
607 return -ENODEV;
608
609 rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val);
610
Dave Jones436fe7b2006-06-05 14:03:50 -0400611 recalibrate_cpu_khz();
Dave Jones91350ed2005-05-31 19:03:45 -0700612
613 fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.CFID];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 if (!fsb) {
615 printk(KERN_WARNING PFX "can not determine bus frequency\n");
616 return -EINVAL;
617 }
Dave Jones7eb53d82005-05-31 19:03:42 -0700618 dprintk("FSB: %3dMHz\n", fsb/1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619
620 if (dmi_check_system(powernow_dmi_table) || acpi_force) {
621 printk (KERN_INFO PFX "PSB/PST known to be broken. Trying ACPI instead\n");
622 result = powernow_acpi_init();
623 } else {
624 result = powernow_decode_bios(fidvidstatus.bits.MFID, fidvidstatus.bits.SVID);
625 if (result) {
626 printk (KERN_INFO PFX "Trying ACPI perflib\n");
627 maximum_speed = 0;
628 minimum_speed = -1;
629 latency = 0;
630 result = powernow_acpi_init();
631 if (result) {
632 printk (KERN_INFO PFX "ACPI and legacy methods failed\n");
Daniel Drakedc2585e2007-05-02 23:19:05 +0100633 printk (KERN_INFO PFX "See http://www.codemonkey.org.uk/projects/cpufreq/powernow-k7.html\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 }
635 } else {
636 /* SGTC use the bus clock as timer */
637 latency = fixup_sgtc();
638 printk(KERN_INFO PFX "SGTC: %d\n", latency);
639 }
640 }
641
642 if (result)
643 return result;
644
645 printk (KERN_INFO PFX "Minimum speed %d MHz. Maximum speed %d MHz.\n",
646 minimum_speed/1000, maximum_speed/1000);
647
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 policy->cpuinfo.transition_latency = cpufreq_scale(2000000UL, fsb, latency);
649
650 policy->cur = powernow_get(0);
651
652 cpufreq_frequency_table_get_attr(powernow_table, policy->cpu);
653
654 return cpufreq_frequency_table_cpuinfo(policy, powernow_table);
655}
656
657static int powernow_cpu_exit (struct cpufreq_policy *policy) {
658 cpufreq_frequency_table_put_attr(policy->cpu);
659
660#ifdef CONFIG_X86_POWERNOW_K7_ACPI
661 if (acpi_processor_perf) {
662 acpi_processor_unregister_performance(acpi_processor_perf, 0);
Rusty Russell2fdf66b2008-12-31 18:08:47 -0800663 free_cpumask_var(acpi_processor_perf->shared_cpu_map);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 kfree(acpi_processor_perf);
665 }
666#endif
667
Jesper Juhl4ae66732005-06-25 14:58:48 -0700668 kfree(powernow_table);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669 return 0;
670}
671
672static struct freq_attr* powernow_table_attr[] = {
673 &cpufreq_freq_attr_scaling_available_freqs,
674 NULL,
675};
676
Linus Torvalds221dee22007-02-26 14:55:48 -0800677static struct cpufreq_driver powernow_driver = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678 .verify = powernow_verify,
679 .target = powernow_target,
680 .get = powernow_get,
681 .init = powernow_cpu_init,
682 .exit = powernow_cpu_exit,
683 .name = "powernow-k7",
684 .owner = THIS_MODULE,
685 .attr = powernow_table_attr,
686};
687
688static int __init powernow_init (void)
689{
690 if (check_powernow()==0)
691 return -ENODEV;
692 return cpufreq_register_driver(&powernow_driver);
693}
694
695
696static void __exit powernow_exit (void)
697{
698 cpufreq_unregister_driver(&powernow_driver);
699}
700
701module_param(acpi_force, int, 0444);
702MODULE_PARM_DESC(acpi_force, "Force ACPI to be used.");
703
Dave Jonesf4432c52008-10-20 13:31:45 -0400704MODULE_AUTHOR ("Dave Jones <davej@redhat.com>");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705MODULE_DESCRIPTION ("Powernow driver for AMD K7 processors.");
706MODULE_LICENSE ("GPL");
707
708late_initcall(powernow_init);
709module_exit(powernow_exit);
710