MAINTAINERS: Update ARM Versatile Express platform entry
[linux-2.6-block.git] / drivers / cpufreq / powernow-k7.c
CommitLineData
1da177e4
LT
1/*
2 * AMD K7 Powernow driver.
f4432c5c 3 * (C) 2003 Dave Jones on behalf of SuSE Labs.
1da177e4
LT
4 *
5 * Licensed under the terms of the GNU GPL License version 2.
6 * Based upon datasheets & sample CPUs kindly provided by AMD.
7 *
b9e7638a
DJ
8 * Errata 5:
9 * CPU 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:
12 * CPU with half frequency multipliers may hang upon wakeup from disconnect.
13 * - We disable half multipliers if ACPI is used on A0 stepping CPUs.
1da177e4
LT
14 */
15
1da177e4
LT
16#include <linux/kernel.h>
17#include <linux/module.h>
18#include <linux/moduleparam.h>
19#include <linux/init.h>
20#include <linux/cpufreq.h>
21#include <linux/slab.h>
22#include <linux/string.h>
23#include <linux/dmi.h>
b9e7638a
DJ
24#include <linux/timex.h>
25#include <linux/io.h>
1da177e4 26
b9e7638a 27#include <asm/timer.h> /* Needed for recalibrate_cpu_khz() */
1da177e4 28#include <asm/msr.h>
fa8031ae 29#include <asm/cpu_device_id.h>
1da177e4
LT
30
31#ifdef CONFIG_X86_POWERNOW_K7_ACPI
32#include <linux/acpi.h>
33#include <acpi/processor.h>
34#endif
35
36#include "powernow-k7.h"
37
38#define PFX "powernow: "
39
40
41struct psb_s {
42 u8 signature[10];
43 u8 tableversion;
44 u8 flags;
45 u16 settlingtime;
46 u8 reserved1;
47 u8 numpst;
48};
49
50struct pst_s {
51 u32 cpuid;
52 u8 fsbspeed;
53 u8 maxfid;
54 u8 startvid;
55 u8 numpstates;
56};
57
58#ifdef CONFIG_X86_POWERNOW_K7_ACPI
59union powernow_acpi_control_t {
60 struct {
61 unsigned long fid:5,
b9e7638a
DJ
62 vid:5,
63 sgtc:20,
64 res1:2;
1da177e4
LT
65 } bits;
66 unsigned long val;
67};
68#endif
69
1da177e4 70/* divide by 1000 to get VCore voltage in V. */
bd5ab26a 71static const int mobile_vid_table[32] = {
1da177e4
LT
72 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};
1da177e4
LT
77
78/* divide by 10 to get FID. */
bd5ab26a 79static const int fid_codes[32] = {
1da177e4
LT
80 110, 115, 120, 125, 50, 55, 60, 65,
81 70, 75, 80, 85, 90, 95, 100, 105,
82 30, 190, 40, 200, 130, 135, 140, 210,
83 150, 225, 160, 165, 170, 180, -1, -1,
84};
85
86/* This parameter is used in order to force ACPI instead of legacy method for
87 * configuration purpose.
88 */
89
90static int acpi_force;
91
92static struct cpufreq_frequency_table *powernow_table;
93
94static unsigned int can_scale_bus;
95static unsigned int can_scale_vid;
fff78ad5 96static unsigned int minimum_speed = -1;
1da177e4
LT
97static unsigned int maximum_speed;
98static unsigned int number_scales;
99static unsigned int fsb;
100static unsigned int latency;
101static char have_a0;
102
1da177e4
LT
103static int check_fsb(unsigned int fsbspeed)
104{
105 int delta;
106 unsigned int f = fsb / 1000;
107
108 delta = (fsbspeed > f) ? fsbspeed - f : f - fsbspeed;
b9e7638a 109 return delta < 5;
1da177e4
LT
110}
111
fa8031ae 112static const struct x86_cpu_id powernow_k7_cpuids[] = {
30bcfff9 113 { X86_VENDOR_AMD, 6, },
fa8031ae
AK
114 {}
115};
116MODULE_DEVICE_TABLE(x86cpu, powernow_k7_cpuids);
117
1da177e4
LT
118static int check_powernow(void)
119{
92cb7612 120 struct cpuinfo_x86 *c = &cpu_data(0);
1da177e4
LT
121 unsigned int maxei, eax, ebx, ecx, edx;
122
fa8031ae 123 if (!x86_match_cpu(powernow_k7_cpuids))
1da177e4 124 return 0;
1da177e4
LT
125
126 /* Get maximum capabilities */
b9e7638a 127 maxei = cpuid_eax(0x80000000);
1da177e4
LT
128 if (maxei < 0x80000007) { /* Any powernow info ? */
129#ifdef MODULE
b9e7638a 130 printk(KERN_INFO PFX "No powernow capabilities detected\n");
1da177e4
LT
131#endif
132 return 0;
133 }
134
135 if ((c->x86_model == 6) && (c->x86_mask == 0)) {
b9e7638a
DJ
136 printk(KERN_INFO PFX "K7 660[A0] core detected, "
137 "enabling errata workarounds\n");
1da177e4
LT
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
b9e7638a 147 printk(KERN_INFO PFX "PowerNOW! Technology present. Can scale: ");
1da177e4
LT
148
149 if (edx & 1 << 1) {
b9e7638a
DJ
150 printk("frequency");
151 can_scale_bus = 1;
1da177e4
LT
152 }
153
154 if ((edx & (1 << 1 | 1 << 2)) == 0x6)
b9e7638a 155 printk(" and ");
1da177e4
LT
156
157 if (edx & 1 << 2) {
b9e7638a
DJ
158 printk("voltage");
159 can_scale_vid = 1;
1da177e4
LT
160 }
161
b9e7638a 162 printk(".\n");
1da177e4
LT
163 return 1;
164}
165
d38e73e8 166#ifdef CONFIG_X86_POWERNOW_K7_ACPI
b9e7638a
DJ
167static void invalidate_entry(unsigned int entry)
168{
169 powernow_table[entry].frequency = CPUFREQ_ENTRY_INVALID;
170}
d38e73e8 171#endif
1da177e4 172
b9e7638a 173static int get_ranges(unsigned char *pst)
1da177e4
LT
174{
175 unsigned int j;
176 unsigned int speed;
177 u8 fid, vid;
178
d5b73cd8 179 powernow_table = kzalloc((sizeof(*powernow_table) *
b9e7638a 180 (number_scales + 1)), GFP_KERNEL);
1da177e4
LT
181 if (!powernow_table)
182 return -ENOMEM;
1da177e4 183
b9e7638a 184 for (j = 0 ; j < number_scales; j++) {
1da177e4
LT
185 fid = *pst++;
186
187 powernow_table[j].frequency = (fsb * fid_codes[fid]) / 10;
50701588 188 powernow_table[j].driver_data = fid; /* lower 8 bits */
1da177e4
LT
189
190 speed = powernow_table[j].frequency;
191
b9e7638a 192 if ((fid_codes[fid] % 10) == 5) {
1da177e4
LT
193#ifdef CONFIG_X86_POWERNOW_K7_ACPI
194 if (have_a0 == 1)
b9e7638a 195 invalidate_entry(j);
1da177e4
LT
196#endif
197 }
198
199 if (speed < minimum_speed)
200 minimum_speed = speed;
201 if (speed > maximum_speed)
202 maximum_speed = speed;
203
204 vid = *pst++;
50701588 205 powernow_table[j].driver_data |= (vid << 8); /* upper 8 bits */
1da177e4 206
2d06d8c4 207 pr_debug(" FID: 0x%x (%d.%dx [%dMHz]) "
32ee8c3e
DJ
208 "VID: 0x%x (%d.%03dV)\n", fid, fid_codes[fid] / 10,
209 fid_codes[fid] % 10, speed/1000, vid,
1da177e4
LT
210 mobile_vid_table[vid]/1000,
211 mobile_vid_table[vid]%1000);
212 }
213 powernow_table[number_scales].frequency = CPUFREQ_TABLE_END;
50701588 214 powernow_table[number_scales].driver_data = 0;
1da177e4
LT
215
216 return 0;
217}
218
219
220static void change_FID(int fid)
221{
222 union msr_fidvidctl fidvidctl;
223
b9e7638a 224 rdmsrl(MSR_K7_FID_VID_CTL, fidvidctl.val);
1da177e4
LT
225 if (fidvidctl.bits.FID != fid) {
226 fidvidctl.bits.SGTC = latency;
227 fidvidctl.bits.FID = fid;
228 fidvidctl.bits.VIDC = 0;
229 fidvidctl.bits.FIDC = 1;
b9e7638a 230 wrmsrl(MSR_K7_FID_VID_CTL, fidvidctl.val);
1da177e4
LT
231 }
232}
233
234
235static void change_VID(int vid)
236{
237 union msr_fidvidctl fidvidctl;
238
b9e7638a 239 rdmsrl(MSR_K7_FID_VID_CTL, fidvidctl.val);
1da177e4
LT
240 if (fidvidctl.bits.VID != vid) {
241 fidvidctl.bits.SGTC = latency;
242 fidvidctl.bits.VID = vid;
243 fidvidctl.bits.FIDC = 0;
244 fidvidctl.bits.VIDC = 1;
b9e7638a 245 wrmsrl(MSR_K7_FID_VID_CTL, fidvidctl.val);
1da177e4
LT
246 }
247}
248
249
9c0ebcf7 250static int powernow_target(struct cpufreq_policy *policy, unsigned int index)
1da177e4
LT
251{
252 u8 fid, vid;
253 struct cpufreq_freqs freqs;
254 union msr_fidvidstatus fidvidstatus;
255 int cfid;
256
257 /* fid are the lower 8 bits of the index we stored into
258 * the cpufreq frequency table in powernow_decode_bios,
259 * vid are the upper 8 bits.
260 */
261
50701588
VK
262 fid = powernow_table[index].driver_data & 0xFF;
263 vid = (powernow_table[index].driver_data & 0xFF00) >> 8;
1da177e4 264
b9e7638a 265 rdmsrl(MSR_K7_FID_VID_STATUS, fidvidstatus.val);
1da177e4
LT
266 cfid = fidvidstatus.bits.CFID;
267 freqs.old = fsb * fid_codes[cfid] / 10;
268
269 freqs.new = powernow_table[index].frequency;
270
1da177e4
LT
271 /* Now do the magic poking into the MSRs. */
272
273 if (have_a0 == 1) /* A0 errata 5 */
274 local_irq_disable();
275
276 if (freqs.old > freqs.new) {
277 /* Going down, so change FID first */
278 change_FID(fid);
279 change_VID(vid);
280 } else {
281 /* Going up, so change VID first */
282 change_VID(vid);
283 change_FID(fid);
284 }
285
286
287 if (have_a0 == 1)
288 local_irq_enable();
289
9c0ebcf7 290 return 0;
1da177e4
LT
291}
292
293
294#ifdef CONFIG_X86_POWERNOW_K7_ACPI
295
296static struct acpi_processor_performance *acpi_processor_perf;
297
298static int powernow_acpi_init(void)
299{
300 int i;
301 int retval = 0;
302 union powernow_acpi_control_t pc;
303
304 if (acpi_processor_perf != NULL && powernow_table != NULL) {
305 retval = -EINVAL;
306 goto err0;
307 }
308
d5b73cd8 309 acpi_processor_perf = kzalloc(sizeof(*acpi_processor_perf), GFP_KERNEL);
1da177e4
LT
310 if (!acpi_processor_perf) {
311 retval = -ENOMEM;
312 goto err0;
313 }
314
eaa95840 315 if (!zalloc_cpumask_var(&acpi_processor_perf->shared_cpu_map,
2fdf66b4
RR
316 GFP_KERNEL)) {
317 retval = -ENOMEM;
318 goto err05;
319 }
320
1da177e4
LT
321 if (acpi_processor_register_performance(acpi_processor_perf, 0)) {
322 retval = -EIO;
323 goto err1;
324 }
325
b9e7638a
DJ
326 if (acpi_processor_perf->control_register.space_id !=
327 ACPI_ADR_SPACE_FIXED_HARDWARE) {
1da177e4
LT
328 retval = -ENODEV;
329 goto err2;
330 }
331
b9e7638a
DJ
332 if (acpi_processor_perf->status_register.space_id !=
333 ACPI_ADR_SPACE_FIXED_HARDWARE) {
1da177e4
LT
334 retval = -ENODEV;
335 goto err2;
336 }
337
338 number_scales = acpi_processor_perf->state_count;
339
340 if (number_scales < 2) {
341 retval = -ENODEV;
342 goto err2;
343 }
344
d5b73cd8 345 powernow_table = kzalloc((sizeof(*powernow_table) *
b9e7638a 346 (number_scales + 1)), GFP_KERNEL);
1da177e4
LT
347 if (!powernow_table) {
348 retval = -ENOMEM;
349 goto err2;
350 }
351
1da177e4
LT
352 pc.val = (unsigned long) acpi_processor_perf->states[0].control;
353 for (i = 0; i < number_scales; i++) {
354 u8 fid, vid;
dc2585eb
DD
355 struct acpi_processor_px *state =
356 &acpi_processor_perf->states[i];
357 unsigned int speed, speed_mhz;
1da177e4 358
dc2585eb 359 pc.val = (unsigned long) state->control;
2d06d8c4 360 pr_debug("acpi: P%d: %d MHz %d mW %d uS control %08x SGTC %d\n",
1da177e4 361 i,
dc2585eb
DD
362 (u32) state->core_frequency,
363 (u32) state->power,
364 (u32) state->transition_latency,
365 (u32) state->control,
1da177e4
LT
366 pc.bits.sgtc);
367
368 vid = pc.bits.vid;
369 fid = pc.bits.fid;
370
371 powernow_table[i].frequency = fsb * fid_codes[fid] / 10;
50701588
VK
372 powernow_table[i].driver_data = fid; /* lower 8 bits */
373 powernow_table[i].driver_data |= (vid << 8); /* upper 8 bits */
1da177e4
LT
374
375 speed = powernow_table[i].frequency;
dc2585eb
DD
376 speed_mhz = speed / 1000;
377
378 /* processor_perflib will multiply the MHz value by 1000 to
379 * get a KHz value (e.g. 1266000). However, powernow-k7 works
380 * with true KHz values (e.g. 1266768). To ensure that all
381 * powernow frequencies are available, we must ensure that
382 * ACPI doesn't restrict them, so we round up the MHz value
383 * to ensure that perflib's computed KHz value is greater than
384 * or equal to powernow's KHz value.
385 */
386 if (speed % 1000 > 0)
387 speed_mhz++;
1da177e4 388
b9e7638a 389 if ((fid_codes[fid] % 10) == 5) {
1da177e4 390 if (have_a0 == 1)
b9e7638a 391 invalidate_entry(i);
1da177e4
LT
392 }
393
2d06d8c4 394 pr_debug(" FID: 0x%x (%d.%dx [%dMHz]) "
32ee8c3e 395 "VID: 0x%x (%d.%03dV)\n", fid, fid_codes[fid] / 10,
dc2585eb 396 fid_codes[fid] % 10, speed_mhz, vid,
1da177e4
LT
397 mobile_vid_table[vid]/1000,
398 mobile_vid_table[vid]%1000);
399
dc2585eb
DD
400 if (state->core_frequency != speed_mhz) {
401 state->core_frequency = speed_mhz;
2d06d8c4 402 pr_debug(" Corrected ACPI frequency to %d\n",
dc2585eb
DD
403 speed_mhz);
404 }
405
1da177e4
LT
406 if (latency < pc.bits.sgtc)
407 latency = pc.bits.sgtc;
408
409 if (speed < minimum_speed)
410 minimum_speed = speed;
411 if (speed > maximum_speed)
412 maximum_speed = speed;
413 }
414
415 powernow_table[i].frequency = CPUFREQ_TABLE_END;
50701588 416 powernow_table[i].driver_data = 0;
1da177e4
LT
417
418 /* notify BIOS that we exist */
419 acpi_processor_notify_smm(THIS_MODULE);
420
421 return 0;
422
423err2:
b2f8dc4c 424 acpi_processor_unregister_performance(0);
1da177e4 425err1:
2fdf66b4
RR
426 free_cpumask_var(acpi_processor_perf->shared_cpu_map);
427err05:
1da177e4
LT
428 kfree(acpi_processor_perf);
429err0:
b9e7638a
DJ
430 printk(KERN_WARNING PFX "ACPI perflib can not be used on "
431 "this platform\n");
1da177e4
LT
432 acpi_processor_perf = NULL;
433 return retval;
434}
435#else
436static int powernow_acpi_init(void)
437{
438 printk(KERN_INFO PFX "no support for ACPI processor found."
439 " Please recompile your kernel with ACPI processor\n");
440 return -EINVAL;
441}
442#endif
443
b9e7638a
DJ
444static void print_pst_entry(struct pst_s *pst, unsigned int j)
445{
2d06d8c4
DB
446 pr_debug("PST:%d (@%p)\n", j, pst);
447 pr_debug(" cpuid: 0x%x fsb: %d maxFID: 0x%x startvid: 0x%x\n",
b9e7638a
DJ
448 pst->cpuid, pst->fsbspeed, pst->maxfid, pst->startvid);
449}
450
451static int powernow_decode_bios(int maxfid, int startvid)
1da177e4
LT
452{
453 struct psb_s *psb;
454 struct pst_s *pst;
455 unsigned int i, j;
456 unsigned char *p;
457 unsigned int etuple;
458 unsigned int ret;
459
460 etuple = cpuid_eax(0x80000001);
461
b9e7638a 462 for (i = 0xC0000; i < 0xffff0 ; i += 16) {
1da177e4
LT
463
464 p = phys_to_virt(i);
465
b9e7638a 466 if (memcmp(p, "AMDK7PNOW!", 10) == 0) {
2d06d8c4 467 pr_debug("Found PSB header at %p\n", p);
1da177e4 468 psb = (struct psb_s *) p;
2d06d8c4 469 pr_debug("Table version: 0x%x\n", psb->tableversion);
1da177e4 470 if (psb->tableversion != 0x12) {
b9e7638a
DJ
471 printk(KERN_INFO PFX "Sorry, only v1.2 tables"
472 " supported right now\n");
1da177e4
LT
473 return -ENODEV;
474 }
475
2d06d8c4 476 pr_debug("Flags: 0x%x\n", psb->flags);
b9e7638a 477 if ((psb->flags & 1) == 0)
2d06d8c4 478 pr_debug("Mobile voltage regulator\n");
b9e7638a 479 else
2d06d8c4 480 pr_debug("Desktop voltage regulator\n");
1da177e4
LT
481
482 latency = psb->settlingtime;
483 if (latency < 100) {
b9e7638a
DJ
484 printk(KERN_INFO PFX "BIOS set settling time "
485 "to %d microseconds. "
486 "Should be at least 100. "
487 "Correcting.\n", latency);
1da177e4
LT
488 latency = 100;
489 }
2d06d8c4 490 pr_debug("Settling Time: %d microseconds.\n",
b9e7638a 491 psb->settlingtime);
2d06d8c4 492 pr_debug("Has %d PST tables. (Only dumping ones "
b9e7638a
DJ
493 "relevant to this CPU).\n",
494 psb->numpst);
1da177e4 495
d5b73cd8 496 p += sizeof(*psb);
1da177e4
LT
497
498 pst = (struct pst_s *) p;
499
b9e7638a 500 for (j = 0; j < psb->numpst; j++) {
1da177e4
LT
501 pst = (struct pst_s *) p;
502 number_scales = pst->numpstates;
503
b9e7638a
DJ
504 if ((etuple == pst->cpuid) &&
505 check_fsb(pst->fsbspeed) &&
506 (maxfid == pst->maxfid) &&
507 (startvid == pst->startvid)) {
508 print_pst_entry(pst, j);
d5b73cd8 509 p = (char *)pst + sizeof(*pst);
b9e7638a 510 ret = get_ranges(p);
1da177e4 511 return ret;
1da177e4 512 } else {
8cbe0169 513 unsigned int k;
d5b73cd8 514 p = (char *)pst + sizeof(*pst);
b9e7638a
DJ
515 for (k = 0; k < number_scales; k++)
516 p += 2;
1da177e4
LT
517 }
518 }
b9e7638a
DJ
519 printk(KERN_INFO PFX "No PST tables match this cpuid "
520 "(0x%x)\n", etuple);
521 printk(KERN_INFO PFX "This is indicative of a broken "
522 "BIOS.\n");
1da177e4
LT
523
524 return -EINVAL;
525 }
526 p++;
527 }
528
529 return -ENODEV;
530}
531
532
1da177e4
LT
533/*
534 * We use the fact that the bus frequency is somehow
535 * a multiple of 100000/3 khz, then we compute sgtc according
536 * to this multiple.
537 * That way, we match more how AMD thinks all of that work.
538 * We will then get the same kind of behaviour already tested under
539 * the "well-known" other OS.
540 */
2760984f 541static int fixup_sgtc(void)
1da177e4
LT
542{
543 unsigned int sgtc;
544 unsigned int m;
545
546 m = fsb / 3333;
547 if ((m % 10) >= 5)
548 m += 5;
549
550 m /= 10;
551
552 sgtc = 100 * m * latency;
553 sgtc = sgtc / 3;
554 if (sgtc > 0xfffff) {
555 printk(KERN_WARNING PFX "SGTC too large %d\n", sgtc);
556 sgtc = 0xfffff;
557 }
558 return sgtc;
559}
560
561static unsigned int powernow_get(unsigned int cpu)
562{
563 union msr_fidvidstatus fidvidstatus;
564 unsigned int cfid;
565
566 if (cpu)
567 return 0;
b9e7638a 568 rdmsrl(MSR_K7_FID_VID_STATUS, fidvidstatus.val);
1da177e4
LT
569 cfid = fidvidstatus.bits.CFID;
570
b9e7638a 571 return fsb * fid_codes[cfid] / 10;
1da177e4
LT
572}
573
574
2760984f 575static int acer_cpufreq_pst(const struct dmi_system_id *d)
1da177e4 576{
b9e7638a
DJ
577 printk(KERN_WARNING PFX
578 "%s laptop with broken PST tables in BIOS detected.\n",
579 d->ident);
580 printk(KERN_WARNING PFX
581 "You need to downgrade to 3A21 (09/09/2002), or try a newer "
582 "BIOS than 3A71 (01/20/2003)\n");
583 printk(KERN_WARNING PFX
584 "cpufreq scaling has been disabled as a result of this.\n");
1da177e4
LT
585 return 0;
586}
587
588/*
589 * Some Athlon laptops have really fucked PST tables.
590 * A BIOS update is all that can save them.
591 * Mention this, and disable cpufreq.
592 */
2760984f 593static struct dmi_system_id powernow_dmi_table[] = {
1da177e4
LT
594 {
595 .callback = acer_cpufreq_pst,
596 .ident = "Acer Aspire",
597 .matches = {
598 DMI_MATCH(DMI_SYS_VENDOR, "Insyde Software"),
599 DMI_MATCH(DMI_BIOS_VERSION, "3A71"),
600 },
601 },
602 { }
603};
604
2760984f 605static int powernow_cpu_init(struct cpufreq_policy *policy)
1da177e4
LT
606{
607 union msr_fidvidstatus fidvidstatus;
608 int result;
609
610 if (policy->cpu != 0)
611 return -ENODEV;
612
b9e7638a 613 rdmsrl(MSR_K7_FID_VID_STATUS, fidvidstatus.val);
1da177e4 614
436fe7b8 615 recalibrate_cpu_khz();
91350ed4
DJ
616
617 fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.CFID];
1da177e4
LT
618 if (!fsb) {
619 printk(KERN_WARNING PFX "can not determine bus frequency\n");
620 return -EINVAL;
621 }
2d06d8c4 622 pr_debug("FSB: %3dMHz\n", fsb/1000);
1da177e4
LT
623
624 if (dmi_check_system(powernow_dmi_table) || acpi_force) {
b9e7638a
DJ
625 printk(KERN_INFO PFX "PSB/PST known to be broken. "
626 "Trying ACPI instead\n");
1da177e4
LT
627 result = powernow_acpi_init();
628 } else {
b9e7638a
DJ
629 result = powernow_decode_bios(fidvidstatus.bits.MFID,
630 fidvidstatus.bits.SVID);
1da177e4 631 if (result) {
b9e7638a 632 printk(KERN_INFO PFX "Trying ACPI perflib\n");
1da177e4
LT
633 maximum_speed = 0;
634 minimum_speed = -1;
635 latency = 0;
636 result = powernow_acpi_init();
637 if (result) {
b9e7638a
DJ
638 printk(KERN_INFO PFX
639 "ACPI and legacy methods failed\n");
1da177e4
LT
640 }
641 } else {
642 /* SGTC use the bus clock as timer */
643 latency = fixup_sgtc();
644 printk(KERN_INFO PFX "SGTC: %d\n", latency);
645 }
646 }
647
648 if (result)
649 return result;
650
b9e7638a 651 printk(KERN_INFO PFX "Minimum speed %d MHz. Maximum speed %d MHz.\n",
1da177e4
LT
652 minimum_speed/1000, maximum_speed/1000);
653
b9e7638a
DJ
654 policy->cpuinfo.transition_latency =
655 cpufreq_scale(2000000UL, fsb, latency);
1da177e4 656
b147405a 657 return cpufreq_table_validate_and_show(policy, powernow_table);
1da177e4
LT
658}
659
b9e7638a
DJ
660static int powernow_cpu_exit(struct cpufreq_policy *policy)
661{
1da177e4
LT
662#ifdef CONFIG_X86_POWERNOW_K7_ACPI
663 if (acpi_processor_perf) {
b2f8dc4c 664 acpi_processor_unregister_performance(0);
2fdf66b4 665 free_cpumask_var(acpi_processor_perf->shared_cpu_map);
1da177e4
LT
666 kfree(acpi_processor_perf);
667 }
668#endif
669
4ae6673e 670 kfree(powernow_table);
1da177e4
LT
671 return 0;
672}
673
221dee28 674static struct cpufreq_driver powernow_driver = {
d63bd27f 675 .verify = cpufreq_generic_frequency_table_verify,
9c0ebcf7 676 .target_index = powernow_target,
e2f74f35
TR
677 .get = powernow_get,
678#ifdef CONFIG_X86_POWERNOW_K7_ACPI
679 .bios_limit = acpi_processor_get_bios_limit,
680#endif
681 .init = powernow_cpu_init,
682 .exit = powernow_cpu_exit,
683 .name = "powernow-k7",
d63bd27f 684 .attr = cpufreq_generic_attr,
1da177e4
LT
685};
686
b9e7638a 687static int __init powernow_init(void)
1da177e4 688{
b9e7638a 689 if (check_powernow() == 0)
1da177e4
LT
690 return -ENODEV;
691 return cpufreq_register_driver(&powernow_driver);
692}
693
694
b9e7638a 695static void __exit powernow_exit(void)
1da177e4
LT
696{
697 cpufreq_unregister_driver(&powernow_driver);
698}
699
700module_param(acpi_force, int, 0444);
701MODULE_PARM_DESC(acpi_force, "Force ACPI to be used.");
702
d5e80b4b 703MODULE_AUTHOR("Dave Jones");
b9e7638a
DJ
704MODULE_DESCRIPTION("Powernow driver for AMD K7 processors.");
705MODULE_LICENSE("GPL");
1da177e4
LT
706
707late_initcall(powernow_init);
708module_exit(powernow_exit);
709