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