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