[CPUFREQ] add atom family to p4-clockmod
[deliverable/linux.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
b9e7638a
DJ
171static void invalidate_entry(unsigned int entry)
172{
173 powernow_table[entry].frequency = CPUFREQ_ENTRY_INVALID;
174}
1da177e4 175
b9e7638a 176static int get_ranges(unsigned char *pst)
1da177e4
LT
177{
178 unsigned int j;
179 unsigned int speed;
180 u8 fid, vid;
181
b9e7638a
DJ
182 powernow_table = kzalloc((sizeof(struct cpufreq_frequency_table) *
183 (number_scales + 1)), GFP_KERNEL);
1da177e4
LT
184 if (!powernow_table)
185 return -ENOMEM;
1da177e4 186
b9e7638a 187 for (j = 0 ; j < number_scales; j++) {
1da177e4
LT
188 fid = *pst++;
189
190 powernow_table[j].frequency = (fsb * fid_codes[fid]) / 10;
191 powernow_table[j].index = fid; /* lower 8 bits */
192
193 speed = powernow_table[j].frequency;
194
b9e7638a 195 if ((fid_codes[fid] % 10) == 5) {
1da177e4
LT
196#ifdef CONFIG_X86_POWERNOW_K7_ACPI
197 if (have_a0 == 1)
b9e7638a 198 invalidate_entry(j);
1da177e4
LT
199#endif
200 }
201
202 if (speed < minimum_speed)
203 minimum_speed = speed;
204 if (speed > maximum_speed)
205 maximum_speed = speed;
206
207 vid = *pst++;
208 powernow_table[j].index |= (vid << 8); /* upper 8 bits */
209
b9e7638a 210 dprintk(" FID: 0x%x (%d.%dx [%dMHz]) "
32ee8c3e
DJ
211 "VID: 0x%x (%d.%03dV)\n", fid, fid_codes[fid] / 10,
212 fid_codes[fid] % 10, speed/1000, vid,
1da177e4
LT
213 mobile_vid_table[vid]/1000,
214 mobile_vid_table[vid]%1000);
215 }
216 powernow_table[number_scales].frequency = CPUFREQ_TABLE_END;
217 powernow_table[number_scales].index = 0;
218
219 return 0;
220}
221
222
223static void change_FID(int fid)
224{
225 union msr_fidvidctl fidvidctl;
226
b9e7638a 227 rdmsrl(MSR_K7_FID_VID_CTL, fidvidctl.val);
1da177e4
LT
228 if (fidvidctl.bits.FID != fid) {
229 fidvidctl.bits.SGTC = latency;
230 fidvidctl.bits.FID = fid;
231 fidvidctl.bits.VIDC = 0;
232 fidvidctl.bits.FIDC = 1;
b9e7638a 233 wrmsrl(MSR_K7_FID_VID_CTL, fidvidctl.val);
1da177e4
LT
234 }
235}
236
237
238static void change_VID(int vid)
239{
240 union msr_fidvidctl fidvidctl;
241
b9e7638a 242 rdmsrl(MSR_K7_FID_VID_CTL, fidvidctl.val);
1da177e4
LT
243 if (fidvidctl.bits.VID != vid) {
244 fidvidctl.bits.SGTC = latency;
245 fidvidctl.bits.VID = vid;
246 fidvidctl.bits.FIDC = 0;
247 fidvidctl.bits.VIDC = 1;
b9e7638a 248 wrmsrl(MSR_K7_FID_VID_CTL, fidvidctl.val);
1da177e4
LT
249 }
250}
251
252
b9e7638a 253static void change_speed(unsigned int index)
1da177e4
LT
254{
255 u8 fid, vid;
256 struct cpufreq_freqs freqs;
257 union msr_fidvidstatus fidvidstatus;
258 int cfid;
259
260 /* fid are the lower 8 bits of the index we stored into
261 * the cpufreq frequency table in powernow_decode_bios,
262 * vid are the upper 8 bits.
263 */
264
265 fid = powernow_table[index].index & 0xFF;
266 vid = (powernow_table[index].index & 0xFF00) >> 8;
267
268 freqs.cpu = 0;
269
b9e7638a 270 rdmsrl(MSR_K7_FID_VID_STATUS, fidvidstatus.val);
1da177e4
LT
271 cfid = fidvidstatus.bits.CFID;
272 freqs.old = fsb * fid_codes[cfid] / 10;
273
274 freqs.new = powernow_table[index].frequency;
275
276 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
277
278 /* Now do the magic poking into the MSRs. */
279
280 if (have_a0 == 1) /* A0 errata 5 */
281 local_irq_disable();
282
283 if (freqs.old > freqs.new) {
284 /* Going down, so change FID first */
285 change_FID(fid);
286 change_VID(vid);
287 } else {
288 /* Going up, so change VID first */
289 change_VID(vid);
290 change_FID(fid);
291 }
292
293
294 if (have_a0 == 1)
295 local_irq_enable();
296
297 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
298}
299
300
301#ifdef CONFIG_X86_POWERNOW_K7_ACPI
302
303static struct acpi_processor_performance *acpi_processor_perf;
304
305static int powernow_acpi_init(void)
306{
307 int i;
308 int retval = 0;
309 union powernow_acpi_control_t pc;
310
311 if (acpi_processor_perf != NULL && powernow_table != NULL) {
312 retval = -EINVAL;
313 goto err0;
314 }
315
bfdc708d 316 acpi_processor_perf = kzalloc(sizeof(struct acpi_processor_performance),
1da177e4 317 GFP_KERNEL);
1da177e4
LT
318 if (!acpi_processor_perf) {
319 retval = -ENOMEM;
320 goto err0;
321 }
322
2fdf66b4
RR
323 if (!alloc_cpumask_var(&acpi_processor_perf->shared_cpu_map,
324 GFP_KERNEL)) {
325 retval = -ENOMEM;
326 goto err05;
327 }
328
1da177e4
LT
329 if (acpi_processor_register_performance(acpi_processor_perf, 0)) {
330 retval = -EIO;
331 goto err1;
332 }
333
b9e7638a
DJ
334 if (acpi_processor_perf->control_register.space_id !=
335 ACPI_ADR_SPACE_FIXED_HARDWARE) {
1da177e4
LT
336 retval = -ENODEV;
337 goto err2;
338 }
339
b9e7638a
DJ
340 if (acpi_processor_perf->status_register.space_id !=
341 ACPI_ADR_SPACE_FIXED_HARDWARE) {
1da177e4
LT
342 retval = -ENODEV;
343 goto err2;
344 }
345
346 number_scales = acpi_processor_perf->state_count;
347
348 if (number_scales < 2) {
349 retval = -ENODEV;
350 goto err2;
351 }
352
b9e7638a
DJ
353 powernow_table = kzalloc((sizeof(struct cpufreq_frequency_table) *
354 (number_scales + 1)), GFP_KERNEL);
1da177e4
LT
355 if (!powernow_table) {
356 retval = -ENOMEM;
357 goto err2;
358 }
359
1da177e4
LT
360 pc.val = (unsigned long) acpi_processor_perf->states[0].control;
361 for (i = 0; i < number_scales; i++) {
362 u8 fid, vid;
dc2585eb
DD
363 struct acpi_processor_px *state =
364 &acpi_processor_perf->states[i];
365 unsigned int speed, speed_mhz;
1da177e4 366
dc2585eb 367 pc.val = (unsigned long) state->control;
b9e7638a 368 dprintk("acpi: P%d: %d MHz %d mW %d uS control %08x SGTC %d\n",
1da177e4 369 i,
dc2585eb
DD
370 (u32) state->core_frequency,
371 (u32) state->power,
372 (u32) state->transition_latency,
373 (u32) state->control,
1da177e4
LT
374 pc.bits.sgtc);
375
376 vid = pc.bits.vid;
377 fid = pc.bits.fid;
378
379 powernow_table[i].frequency = fsb * fid_codes[fid] / 10;
380 powernow_table[i].index = fid; /* lower 8 bits */
381 powernow_table[i].index |= (vid << 8); /* upper 8 bits */
382
383 speed = powernow_table[i].frequency;
dc2585eb
DD
384 speed_mhz = speed / 1000;
385
386 /* processor_perflib will multiply the MHz value by 1000 to
387 * get a KHz value (e.g. 1266000). However, powernow-k7 works
388 * with true KHz values (e.g. 1266768). To ensure that all
389 * powernow frequencies are available, we must ensure that
390 * ACPI doesn't restrict them, so we round up the MHz value
391 * to ensure that perflib's computed KHz value is greater than
392 * or equal to powernow's KHz value.
393 */
394 if (speed % 1000 > 0)
395 speed_mhz++;
1da177e4 396
b9e7638a 397 if ((fid_codes[fid] % 10) == 5) {
1da177e4 398 if (have_a0 == 1)
b9e7638a 399 invalidate_entry(i);
1da177e4
LT
400 }
401
b9e7638a 402 dprintk(" FID: 0x%x (%d.%dx [%dMHz]) "
32ee8c3e 403 "VID: 0x%x (%d.%03dV)\n", fid, fid_codes[fid] / 10,
dc2585eb 404 fid_codes[fid] % 10, speed_mhz, vid,
1da177e4
LT
405 mobile_vid_table[vid]/1000,
406 mobile_vid_table[vid]%1000);
407
dc2585eb
DD
408 if (state->core_frequency != speed_mhz) {
409 state->core_frequency = speed_mhz;
410 dprintk(" Corrected ACPI frequency to %d\n",
411 speed_mhz);
412 }
413
1da177e4
LT
414 if (latency < pc.bits.sgtc)
415 latency = pc.bits.sgtc;
416
417 if (speed < minimum_speed)
418 minimum_speed = speed;
419 if (speed > maximum_speed)
420 maximum_speed = speed;
421 }
422
423 powernow_table[i].frequency = CPUFREQ_TABLE_END;
424 powernow_table[i].index = 0;
425
426 /* notify BIOS that we exist */
427 acpi_processor_notify_smm(THIS_MODULE);
428
429 return 0;
430
431err2:
432 acpi_processor_unregister_performance(acpi_processor_perf, 0);
433err1:
2fdf66b4
RR
434 free_cpumask_var(acpi_processor_perf->shared_cpu_map);
435err05:
1da177e4
LT
436 kfree(acpi_processor_perf);
437err0:
b9e7638a
DJ
438 printk(KERN_WARNING PFX "ACPI perflib can not be used on "
439 "this platform\n");
1da177e4
LT
440 acpi_processor_perf = NULL;
441 return retval;
442}
443#else
444static int powernow_acpi_init(void)
445{
446 printk(KERN_INFO PFX "no support for ACPI processor found."
447 " Please recompile your kernel with ACPI processor\n");
448 return -EINVAL;
449}
450#endif
451
b9e7638a
DJ
452static void print_pst_entry(struct pst_s *pst, unsigned int j)
453{
454 dprintk("PST:%d (@%p)\n", j, pst);
455 dprintk(" cpuid: 0x%x fsb: %d maxFID: 0x%x startvid: 0x%x\n",
456 pst->cpuid, pst->fsbspeed, pst->maxfid, pst->startvid);
457}
458
459static int powernow_decode_bios(int maxfid, int startvid)
1da177e4
LT
460{
461 struct psb_s *psb;
462 struct pst_s *pst;
463 unsigned int i, j;
464 unsigned char *p;
465 unsigned int etuple;
466 unsigned int ret;
467
468 etuple = cpuid_eax(0x80000001);
469
b9e7638a 470 for (i = 0xC0000; i < 0xffff0 ; i += 16) {
1da177e4
LT
471
472 p = phys_to_virt(i);
473
b9e7638a
DJ
474 if (memcmp(p, "AMDK7PNOW!", 10) == 0) {
475 dprintk("Found PSB header at %p\n", p);
1da177e4 476 psb = (struct psb_s *) p;
b9e7638a 477 dprintk("Table version: 0x%x\n", psb->tableversion);
1da177e4 478 if (psb->tableversion != 0x12) {
b9e7638a
DJ
479 printk(KERN_INFO PFX "Sorry, only v1.2 tables"
480 " supported right now\n");
1da177e4
LT
481 return -ENODEV;
482 }
483
b9e7638a
DJ
484 dprintk("Flags: 0x%x\n", psb->flags);
485 if ((psb->flags & 1) == 0)
486 dprintk("Mobile voltage regulator\n");
487 else
488 dprintk("Desktop voltage regulator\n");
1da177e4
LT
489
490 latency = psb->settlingtime;
491 if (latency < 100) {
b9e7638a
DJ
492 printk(KERN_INFO PFX "BIOS set settling time "
493 "to %d microseconds. "
494 "Should be at least 100. "
495 "Correcting.\n", latency);
1da177e4
LT
496 latency = 100;
497 }
b9e7638a
DJ
498 dprintk("Settling Time: %d microseconds.\n",
499 psb->settlingtime);
500 dprintk("Has %d PST tables. (Only dumping ones "
501 "relevant to this CPU).\n",
502 psb->numpst);
1da177e4 503
b9e7638a 504 p += sizeof(struct psb_s);
1da177e4
LT
505
506 pst = (struct pst_s *) p;
507
b9e7638a 508 for (j = 0; j < psb->numpst; j++) {
1da177e4
LT
509 pst = (struct pst_s *) p;
510 number_scales = pst->numpstates;
511
b9e7638a
DJ
512 if ((etuple == pst->cpuid) &&
513 check_fsb(pst->fsbspeed) &&
514 (maxfid == pst->maxfid) &&
515 (startvid == pst->startvid)) {
516 print_pst_entry(pst, j);
517 p = (char *)pst + sizeof(struct pst_s);
518 ret = get_ranges(p);
1da177e4 519 return ret;
1da177e4 520 } else {
8cbe0169 521 unsigned int k;
b9e7638a
DJ
522 p = (char *)pst + sizeof(struct pst_s);
523 for (k = 0; k < number_scales; k++)
524 p += 2;
1da177e4
LT
525 }
526 }
b9e7638a
DJ
527 printk(KERN_INFO PFX "No PST tables match this cpuid "
528 "(0x%x)\n", etuple);
529 printk(KERN_INFO PFX "This is indicative of a broken "
530 "BIOS.\n");
1da177e4
LT
531
532 return -EINVAL;
533 }
534 p++;
535 }
536
537 return -ENODEV;
538}
539
540
b9e7638a 541static int powernow_target(struct cpufreq_policy *policy,
1da177e4
LT
542 unsigned int target_freq,
543 unsigned int relation)
544{
545 unsigned int newstate;
546
b9e7638a
DJ
547 if (cpufreq_frequency_table_target(policy, powernow_table, target_freq,
548 relation, &newstate))
1da177e4
LT
549 return -EINVAL;
550
551 change_speed(newstate);
552
553 return 0;
554}
555
556
b9e7638a 557static int powernow_verify(struct cpufreq_policy *policy)
1da177e4
LT
558{
559 return cpufreq_frequency_table_verify(policy, powernow_table);
560}
561
562/*
563 * We use the fact that the bus frequency is somehow
564 * a multiple of 100000/3 khz, then we compute sgtc according
565 * to this multiple.
566 * That way, we match more how AMD thinks all of that work.
567 * We will then get the same kind of behaviour already tested under
568 * the "well-known" other OS.
569 */
570static int __init fixup_sgtc(void)
571{
572 unsigned int sgtc;
573 unsigned int m;
574
575 m = fsb / 3333;
576 if ((m % 10) >= 5)
577 m += 5;
578
579 m /= 10;
580
581 sgtc = 100 * m * latency;
582 sgtc = sgtc / 3;
583 if (sgtc > 0xfffff) {
584 printk(KERN_WARNING PFX "SGTC too large %d\n", sgtc);
585 sgtc = 0xfffff;
586 }
587 return sgtc;
588}
589
590static unsigned int powernow_get(unsigned int cpu)
591{
592 union msr_fidvidstatus fidvidstatus;
593 unsigned int cfid;
594
595 if (cpu)
596 return 0;
b9e7638a 597 rdmsrl(MSR_K7_FID_VID_STATUS, fidvidstatus.val);
1da177e4
LT
598 cfid = fidvidstatus.bits.CFID;
599
b9e7638a 600 return fsb * fid_codes[cfid] / 10;
1da177e4
LT
601}
602
603
0b4b5dde 604static int __init acer_cpufreq_pst(const struct dmi_system_id *d)
1da177e4 605{
b9e7638a
DJ
606 printk(KERN_WARNING PFX
607 "%s laptop with broken PST tables in BIOS detected.\n",
608 d->ident);
609 printk(KERN_WARNING PFX
610 "You need to downgrade to 3A21 (09/09/2002), or try a newer "
611 "BIOS than 3A71 (01/20/2003)\n");
612 printk(KERN_WARNING PFX
613 "cpufreq scaling has been disabled as a result of this.\n");
1da177e4
LT
614 return 0;
615}
616
617/*
618 * Some Athlon laptops have really fucked PST tables.
619 * A BIOS update is all that can save them.
620 * Mention this, and disable cpufreq.
621 */
622static struct dmi_system_id __initdata powernow_dmi_table[] = {
623 {
624 .callback = acer_cpufreq_pst,
625 .ident = "Acer Aspire",
626 .matches = {
627 DMI_MATCH(DMI_SYS_VENDOR, "Insyde Software"),
628 DMI_MATCH(DMI_BIOS_VERSION, "3A71"),
629 },
630 },
631 { }
632};
633
b9e7638a 634static int __init powernow_cpu_init(struct cpufreq_policy *policy)
1da177e4
LT
635{
636 union msr_fidvidstatus fidvidstatus;
637 int result;
638
639 if (policy->cpu != 0)
640 return -ENODEV;
641
b9e7638a 642 rdmsrl(MSR_K7_FID_VID_STATUS, fidvidstatus.val);
1da177e4 643
436fe7b8 644 recalibrate_cpu_khz();
91350ed4
DJ
645
646 fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.CFID];
1da177e4
LT
647 if (!fsb) {
648 printk(KERN_WARNING PFX "can not determine bus frequency\n");
649 return -EINVAL;
650 }
7eb53d88 651 dprintk("FSB: %3dMHz\n", fsb/1000);
1da177e4
LT
652
653 if (dmi_check_system(powernow_dmi_table) || acpi_force) {
b9e7638a
DJ
654 printk(KERN_INFO PFX "PSB/PST known to be broken. "
655 "Trying ACPI instead\n");
1da177e4
LT
656 result = powernow_acpi_init();
657 } else {
b9e7638a
DJ
658 result = powernow_decode_bios(fidvidstatus.bits.MFID,
659 fidvidstatus.bits.SVID);
1da177e4 660 if (result) {
b9e7638a 661 printk(KERN_INFO PFX "Trying ACPI perflib\n");
1da177e4
LT
662 maximum_speed = 0;
663 minimum_speed = -1;
664 latency = 0;
665 result = powernow_acpi_init();
666 if (result) {
b9e7638a
DJ
667 printk(KERN_INFO PFX
668 "ACPI and legacy methods failed\n");
1da177e4
LT
669 }
670 } else {
671 /* SGTC use the bus clock as timer */
672 latency = fixup_sgtc();
673 printk(KERN_INFO PFX "SGTC: %d\n", latency);
674 }
675 }
676
677 if (result)
678 return result;
679
b9e7638a 680 printk(KERN_INFO PFX "Minimum speed %d MHz. Maximum speed %d MHz.\n",
1da177e4
LT
681 minimum_speed/1000, maximum_speed/1000);
682
b9e7638a
DJ
683 policy->cpuinfo.transition_latency =
684 cpufreq_scale(2000000UL, fsb, latency);
1da177e4
LT
685
686 policy->cur = powernow_get(0);
687
688 cpufreq_frequency_table_get_attr(powernow_table, policy->cpu);
689
690 return cpufreq_frequency_table_cpuinfo(policy, powernow_table);
691}
692
b9e7638a
DJ
693static int powernow_cpu_exit(struct cpufreq_policy *policy)
694{
1da177e4
LT
695 cpufreq_frequency_table_put_attr(policy->cpu);
696
697#ifdef CONFIG_X86_POWERNOW_K7_ACPI
698 if (acpi_processor_perf) {
699 acpi_processor_unregister_performance(acpi_processor_perf, 0);
2fdf66b4 700 free_cpumask_var(acpi_processor_perf->shared_cpu_map);
1da177e4
LT
701 kfree(acpi_processor_perf);
702 }
703#endif
704
4ae6673e 705 kfree(powernow_table);
1da177e4
LT
706 return 0;
707}
708
b9e7638a 709static struct freq_attr *powernow_table_attr[] = {
1da177e4
LT
710 &cpufreq_freq_attr_scaling_available_freqs,
711 NULL,
712};
713
221dee28 714static struct cpufreq_driver powernow_driver = {
1da177e4
LT
715 .verify = powernow_verify,
716 .target = powernow_target,
717 .get = powernow_get,
718 .init = powernow_cpu_init,
719 .exit = powernow_cpu_exit,
720 .name = "powernow-k7",
721 .owner = THIS_MODULE,
722 .attr = powernow_table_attr,
723};
724
b9e7638a 725static int __init powernow_init(void)
1da177e4 726{
b9e7638a 727 if (check_powernow() == 0)
1da177e4
LT
728 return -ENODEV;
729 return cpufreq_register_driver(&powernow_driver);
730}
731
732
b9e7638a 733static void __exit powernow_exit(void)
1da177e4
LT
734{
735 cpufreq_unregister_driver(&powernow_driver);
736}
737
738module_param(acpi_force, int, 0444);
739MODULE_PARM_DESC(acpi_force, "Force ACPI to be used.");
740
b9e7638a
DJ
741MODULE_AUTHOR("Dave Jones <davej@redhat.com>");
742MODULE_DESCRIPTION("Powernow driver for AMD K7 processors.");
743MODULE_LICENSE("GPL");
1da177e4
LT
744
745late_initcall(powernow_init);
746module_exit(powernow_exit);
747
This page took 0.444219 seconds and 5 git commands to generate.