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