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