0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0017
0018 #include <linux/kernel.h>
0019 #include <linux/module.h>
0020 #include <linux/moduleparam.h>
0021 #include <linux/init.h>
0022 #include <linux/cpufreq.h>
0023 #include <linux/slab.h>
0024 #include <linux/string.h>
0025 #include <linux/dmi.h>
0026 #include <linux/timex.h>
0027 #include <linux/io.h>
0028
0029 #include <asm/timer.h> /* Needed for recalibrate_cpu_khz() */
0030 #include <asm/msr.h>
0031 #include <asm/cpu_device_id.h>
0032
0033 #ifdef CONFIG_X86_POWERNOW_K7_ACPI
0034 #include <linux/acpi.h>
0035 #include <acpi/processor.h>
0036 #endif
0037
0038 #include "powernow-k7.h"
0039
0040 struct psb_s {
0041 u8 signature[10];
0042 u8 tableversion;
0043 u8 flags;
0044 u16 settlingtime;
0045 u8 reserved1;
0046 u8 numpst;
0047 };
0048
0049 struct pst_s {
0050 u32 cpuid;
0051 u8 fsbspeed;
0052 u8 maxfid;
0053 u8 startvid;
0054 u8 numpstates;
0055 };
0056
0057 #ifdef CONFIG_X86_POWERNOW_K7_ACPI
0058 union powernow_acpi_control_t {
0059 struct {
0060 unsigned long fid:5,
0061 vid:5,
0062 sgtc:20,
0063 res1:2;
0064 } bits;
0065 unsigned long val;
0066 };
0067 #endif
0068
0069
0070 static const int mobile_vid_table[32] = {
0071 2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650,
0072 1600, 1550, 1500, 1450, 1400, 1350, 1300, 0,
0073 1275, 1250, 1225, 1200, 1175, 1150, 1125, 1100,
0074 1075, 1050, 1025, 1000, 975, 950, 925, 0,
0075 };
0076
0077
0078 static const int fid_codes[32] = {
0079 110, 115, 120, 125, 50, 55, 60, 65,
0080 70, 75, 80, 85, 90, 95, 100, 105,
0081 30, 190, 40, 200, 130, 135, 140, 210,
0082 150, 225, 160, 165, 170, 180, -1, -1,
0083 };
0084
0085
0086
0087
0088
0089 static int acpi_force;
0090
0091 static struct cpufreq_frequency_table *powernow_table;
0092
0093 static unsigned int can_scale_bus;
0094 static unsigned int can_scale_vid;
0095 static unsigned int minimum_speed = -1;
0096 static unsigned int maximum_speed;
0097 static unsigned int number_scales;
0098 static unsigned int fsb;
0099 static unsigned int latency;
0100 static char have_a0;
0101
0102 static int check_fsb(unsigned int fsbspeed)
0103 {
0104 int delta;
0105 unsigned int f = fsb / 1000;
0106
0107 delta = (fsbspeed > f) ? fsbspeed - f : f - fsbspeed;
0108 return delta < 5;
0109 }
0110
0111 static const struct x86_cpu_id powernow_k7_cpuids[] = {
0112 X86_MATCH_VENDOR_FAM(AMD, 6, NULL),
0113 {}
0114 };
0115 MODULE_DEVICE_TABLE(x86cpu, powernow_k7_cpuids);
0116
0117 static int check_powernow(void)
0118 {
0119 struct cpuinfo_x86 *c = &cpu_data(0);
0120 unsigned int maxei, eax, ebx, ecx, edx;
0121
0122 if (!x86_match_cpu(powernow_k7_cpuids))
0123 return 0;
0124
0125
0126 maxei = cpuid_eax(0x80000000);
0127 if (maxei < 0x80000007) {
0128 #ifdef MODULE
0129 pr_info("No powernow capabilities detected\n");
0130 #endif
0131 return 0;
0132 }
0133
0134 if ((c->x86_model == 6) && (c->x86_stepping == 0)) {
0135 pr_info("K7 660[A0] core detected, enabling errata workarounds\n");
0136 have_a0 = 1;
0137 }
0138
0139 cpuid(0x80000007, &eax, &ebx, &ecx, &edx);
0140
0141
0142 if (!(edx & (1 << 1 | 1 << 2)))
0143 return 0;
0144
0145 pr_info("PowerNOW! Technology present. Can scale: ");
0146
0147 if (edx & 1 << 1) {
0148 pr_cont("frequency");
0149 can_scale_bus = 1;
0150 }
0151
0152 if ((edx & (1 << 1 | 1 << 2)) == 0x6)
0153 pr_cont(" and ");
0154
0155 if (edx & 1 << 2) {
0156 pr_cont("voltage");
0157 can_scale_vid = 1;
0158 }
0159
0160 pr_cont("\n");
0161 return 1;
0162 }
0163
0164 #ifdef CONFIG_X86_POWERNOW_K7_ACPI
0165 static void invalidate_entry(unsigned int entry)
0166 {
0167 powernow_table[entry].frequency = CPUFREQ_ENTRY_INVALID;
0168 }
0169 #endif
0170
0171 static int get_ranges(unsigned char *pst)
0172 {
0173 unsigned int j;
0174 unsigned int speed;
0175 u8 fid, vid;
0176
0177 powernow_table = kzalloc((sizeof(*powernow_table) *
0178 (number_scales + 1)), GFP_KERNEL);
0179 if (!powernow_table)
0180 return -ENOMEM;
0181
0182 for (j = 0 ; j < number_scales; j++) {
0183 fid = *pst++;
0184
0185 powernow_table[j].frequency = (fsb * fid_codes[fid]) / 10;
0186 powernow_table[j].driver_data = fid;
0187
0188 speed = powernow_table[j].frequency;
0189
0190 if ((fid_codes[fid] % 10) == 5) {
0191 #ifdef CONFIG_X86_POWERNOW_K7_ACPI
0192 if (have_a0 == 1)
0193 invalidate_entry(j);
0194 #endif
0195 }
0196
0197 if (speed < minimum_speed)
0198 minimum_speed = speed;
0199 if (speed > maximum_speed)
0200 maximum_speed = speed;
0201
0202 vid = *pst++;
0203 powernow_table[j].driver_data |= (vid << 8);
0204
0205 pr_debug(" FID: 0x%x (%d.%dx [%dMHz]) "
0206 "VID: 0x%x (%d.%03dV)\n", fid, fid_codes[fid] / 10,
0207 fid_codes[fid] % 10, speed/1000, vid,
0208 mobile_vid_table[vid]/1000,
0209 mobile_vid_table[vid]%1000);
0210 }
0211 powernow_table[number_scales].frequency = CPUFREQ_TABLE_END;
0212 powernow_table[number_scales].driver_data = 0;
0213
0214 return 0;
0215 }
0216
0217
0218 static void change_FID(int fid)
0219 {
0220 union msr_fidvidctl fidvidctl;
0221
0222 rdmsrl(MSR_K7_FID_VID_CTL, fidvidctl.val);
0223 if (fidvidctl.bits.FID != fid) {
0224 fidvidctl.bits.SGTC = latency;
0225 fidvidctl.bits.FID = fid;
0226 fidvidctl.bits.VIDC = 0;
0227 fidvidctl.bits.FIDC = 1;
0228 wrmsrl(MSR_K7_FID_VID_CTL, fidvidctl.val);
0229 }
0230 }
0231
0232
0233 static void change_VID(int vid)
0234 {
0235 union msr_fidvidctl fidvidctl;
0236
0237 rdmsrl(MSR_K7_FID_VID_CTL, fidvidctl.val);
0238 if (fidvidctl.bits.VID != vid) {
0239 fidvidctl.bits.SGTC = latency;
0240 fidvidctl.bits.VID = vid;
0241 fidvidctl.bits.FIDC = 0;
0242 fidvidctl.bits.VIDC = 1;
0243 wrmsrl(MSR_K7_FID_VID_CTL, fidvidctl.val);
0244 }
0245 }
0246
0247
0248 static int powernow_target(struct cpufreq_policy *policy, unsigned int index)
0249 {
0250 u8 fid, vid;
0251 struct cpufreq_freqs freqs;
0252 union msr_fidvidstatus fidvidstatus;
0253 int cfid;
0254
0255
0256
0257
0258
0259
0260 fid = powernow_table[index].driver_data & 0xFF;
0261 vid = (powernow_table[index].driver_data & 0xFF00) >> 8;
0262
0263 rdmsrl(MSR_K7_FID_VID_STATUS, fidvidstatus.val);
0264 cfid = fidvidstatus.bits.CFID;
0265 freqs.old = fsb * fid_codes[cfid] / 10;
0266
0267 freqs.new = powernow_table[index].frequency;
0268
0269
0270
0271 if (have_a0 == 1)
0272 local_irq_disable();
0273
0274 if (freqs.old > freqs.new) {
0275
0276 change_FID(fid);
0277 change_VID(vid);
0278 } else {
0279
0280 change_VID(vid);
0281 change_FID(fid);
0282 }
0283
0284
0285 if (have_a0 == 1)
0286 local_irq_enable();
0287
0288 return 0;
0289 }
0290
0291
0292 #ifdef CONFIG_X86_POWERNOW_K7_ACPI
0293
0294 static struct acpi_processor_performance *acpi_processor_perf;
0295
0296 static int powernow_acpi_init(void)
0297 {
0298 int i;
0299 int retval = 0;
0300 union powernow_acpi_control_t pc;
0301
0302 if (acpi_processor_perf != NULL && powernow_table != NULL) {
0303 retval = -EINVAL;
0304 goto err0;
0305 }
0306
0307 acpi_processor_perf = kzalloc(sizeof(*acpi_processor_perf), GFP_KERNEL);
0308 if (!acpi_processor_perf) {
0309 retval = -ENOMEM;
0310 goto err0;
0311 }
0312
0313 if (!zalloc_cpumask_var(&acpi_processor_perf->shared_cpu_map,
0314 GFP_KERNEL)) {
0315 retval = -ENOMEM;
0316 goto err05;
0317 }
0318
0319 if (acpi_processor_register_performance(acpi_processor_perf, 0)) {
0320 retval = -EIO;
0321 goto err1;
0322 }
0323
0324 if (acpi_processor_perf->control_register.space_id !=
0325 ACPI_ADR_SPACE_FIXED_HARDWARE) {
0326 retval = -ENODEV;
0327 goto err2;
0328 }
0329
0330 if (acpi_processor_perf->status_register.space_id !=
0331 ACPI_ADR_SPACE_FIXED_HARDWARE) {
0332 retval = -ENODEV;
0333 goto err2;
0334 }
0335
0336 number_scales = acpi_processor_perf->state_count;
0337
0338 if (number_scales < 2) {
0339 retval = -ENODEV;
0340 goto err2;
0341 }
0342
0343 powernow_table = kzalloc((sizeof(*powernow_table) *
0344 (number_scales + 1)), GFP_KERNEL);
0345 if (!powernow_table) {
0346 retval = -ENOMEM;
0347 goto err2;
0348 }
0349
0350 pc.val = (unsigned long) acpi_processor_perf->states[0].control;
0351 for (i = 0; i < number_scales; i++) {
0352 u8 fid, vid;
0353 struct acpi_processor_px *state =
0354 &acpi_processor_perf->states[i];
0355 unsigned int speed, speed_mhz;
0356
0357 pc.val = (unsigned long) state->control;
0358 pr_debug("acpi: P%d: %d MHz %d mW %d uS control %08x SGTC %d\n",
0359 i,
0360 (u32) state->core_frequency,
0361 (u32) state->power,
0362 (u32) state->transition_latency,
0363 (u32) state->control,
0364 pc.bits.sgtc);
0365
0366 vid = pc.bits.vid;
0367 fid = pc.bits.fid;
0368
0369 powernow_table[i].frequency = fsb * fid_codes[fid] / 10;
0370 powernow_table[i].driver_data = fid;
0371 powernow_table[i].driver_data |= (vid << 8);
0372
0373 speed = powernow_table[i].frequency;
0374 speed_mhz = speed / 1000;
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384 if (speed % 1000 > 0)
0385 speed_mhz++;
0386
0387 if ((fid_codes[fid] % 10) == 5) {
0388 if (have_a0 == 1)
0389 invalidate_entry(i);
0390 }
0391
0392 pr_debug(" FID: 0x%x (%d.%dx [%dMHz]) "
0393 "VID: 0x%x (%d.%03dV)\n", fid, fid_codes[fid] / 10,
0394 fid_codes[fid] % 10, speed_mhz, vid,
0395 mobile_vid_table[vid]/1000,
0396 mobile_vid_table[vid]%1000);
0397
0398 if (state->core_frequency != speed_mhz) {
0399 state->core_frequency = speed_mhz;
0400 pr_debug(" Corrected ACPI frequency to %d\n",
0401 speed_mhz);
0402 }
0403
0404 if (latency < pc.bits.sgtc)
0405 latency = pc.bits.sgtc;
0406
0407 if (speed < minimum_speed)
0408 minimum_speed = speed;
0409 if (speed > maximum_speed)
0410 maximum_speed = speed;
0411 }
0412
0413 powernow_table[i].frequency = CPUFREQ_TABLE_END;
0414 powernow_table[i].driver_data = 0;
0415
0416
0417 acpi_processor_notify_smm(THIS_MODULE);
0418
0419 return 0;
0420
0421 err2:
0422 acpi_processor_unregister_performance(0);
0423 err1:
0424 free_cpumask_var(acpi_processor_perf->shared_cpu_map);
0425 err05:
0426 kfree(acpi_processor_perf);
0427 err0:
0428 pr_warn("ACPI perflib can not be used on this platform\n");
0429 acpi_processor_perf = NULL;
0430 return retval;
0431 }
0432 #else
0433 static int powernow_acpi_init(void)
0434 {
0435 pr_info("no support for ACPI processor found - please recompile your kernel with ACPI processor\n");
0436 return -EINVAL;
0437 }
0438 #endif
0439
0440 static void print_pst_entry(struct pst_s *pst, unsigned int j)
0441 {
0442 pr_debug("PST:%d (@%p)\n", j, pst);
0443 pr_debug(" cpuid: 0x%x fsb: %d maxFID: 0x%x startvid: 0x%x\n",
0444 pst->cpuid, pst->fsbspeed, pst->maxfid, pst->startvid);
0445 }
0446
0447 static int powernow_decode_bios(int maxfid, int startvid)
0448 {
0449 struct psb_s *psb;
0450 struct pst_s *pst;
0451 unsigned int i, j;
0452 unsigned char *p;
0453 unsigned int etuple;
0454 unsigned int ret;
0455
0456 etuple = cpuid_eax(0x80000001);
0457
0458 for (i = 0xC0000; i < 0xffff0 ; i += 16) {
0459
0460 p = phys_to_virt(i);
0461
0462 if (memcmp(p, "AMDK7PNOW!", 10) == 0) {
0463 pr_debug("Found PSB header at %p\n", p);
0464 psb = (struct psb_s *) p;
0465 pr_debug("Table version: 0x%x\n", psb->tableversion);
0466 if (psb->tableversion != 0x12) {
0467 pr_info("Sorry, only v1.2 tables supported right now\n");
0468 return -ENODEV;
0469 }
0470
0471 pr_debug("Flags: 0x%x\n", psb->flags);
0472 if ((psb->flags & 1) == 0)
0473 pr_debug("Mobile voltage regulator\n");
0474 else
0475 pr_debug("Desktop voltage regulator\n");
0476
0477 latency = psb->settlingtime;
0478 if (latency < 100) {
0479 pr_info("BIOS set settling time to %d microseconds. Should be at least 100. Correcting.\n",
0480 latency);
0481 latency = 100;
0482 }
0483 pr_debug("Settling Time: %d microseconds.\n",
0484 psb->settlingtime);
0485 pr_debug("Has %d PST tables. (Only dumping ones "
0486 "relevant to this CPU).\n",
0487 psb->numpst);
0488
0489 p += sizeof(*psb);
0490
0491 pst = (struct pst_s *) p;
0492
0493 for (j = 0; j < psb->numpst; j++) {
0494 pst = (struct pst_s *) p;
0495 number_scales = pst->numpstates;
0496
0497 if ((etuple == pst->cpuid) &&
0498 check_fsb(pst->fsbspeed) &&
0499 (maxfid == pst->maxfid) &&
0500 (startvid == pst->startvid)) {
0501 print_pst_entry(pst, j);
0502 p = (char *)pst + sizeof(*pst);
0503 ret = get_ranges(p);
0504 return ret;
0505 } else {
0506 unsigned int k;
0507 p = (char *)pst + sizeof(*pst);
0508 for (k = 0; k < number_scales; k++)
0509 p += 2;
0510 }
0511 }
0512 pr_info("No PST tables match this cpuid (0x%x)\n",
0513 etuple);
0514 pr_info("This is indicative of a broken BIOS\n");
0515
0516 return -EINVAL;
0517 }
0518 p++;
0519 }
0520
0521 return -ENODEV;
0522 }
0523
0524
0525
0526
0527
0528
0529
0530
0531
0532
0533 static int fixup_sgtc(void)
0534 {
0535 unsigned int sgtc;
0536 unsigned int m;
0537
0538 m = fsb / 3333;
0539 if ((m % 10) >= 5)
0540 m += 5;
0541
0542 m /= 10;
0543
0544 sgtc = 100 * m * latency;
0545 sgtc = sgtc / 3;
0546 if (sgtc > 0xfffff) {
0547 pr_warn("SGTC too large %d\n", sgtc);
0548 sgtc = 0xfffff;
0549 }
0550 return sgtc;
0551 }
0552
0553 static unsigned int powernow_get(unsigned int cpu)
0554 {
0555 union msr_fidvidstatus fidvidstatus;
0556 unsigned int cfid;
0557
0558 if (cpu)
0559 return 0;
0560 rdmsrl(MSR_K7_FID_VID_STATUS, fidvidstatus.val);
0561 cfid = fidvidstatus.bits.CFID;
0562
0563 return fsb * fid_codes[cfid] / 10;
0564 }
0565
0566
0567 static int acer_cpufreq_pst(const struct dmi_system_id *d)
0568 {
0569 pr_warn("%s laptop with broken PST tables in BIOS detected\n",
0570 d->ident);
0571 pr_warn("You need to downgrade to 3A21 (09/09/2002), or try a newer BIOS than 3A71 (01/20/2003)\n");
0572 pr_warn("cpufreq scaling has been disabled as a result of this\n");
0573 return 0;
0574 }
0575
0576
0577
0578
0579
0580
0581 static const struct dmi_system_id powernow_dmi_table[] = {
0582 {
0583 .callback = acer_cpufreq_pst,
0584 .ident = "Acer Aspire",
0585 .matches = {
0586 DMI_MATCH(DMI_SYS_VENDOR, "Insyde Software"),
0587 DMI_MATCH(DMI_BIOS_VERSION, "3A71"),
0588 },
0589 },
0590 { }
0591 };
0592
0593 static int powernow_cpu_init(struct cpufreq_policy *policy)
0594 {
0595 union msr_fidvidstatus fidvidstatus;
0596 int result;
0597
0598 if (policy->cpu != 0)
0599 return -ENODEV;
0600
0601 rdmsrl(MSR_K7_FID_VID_STATUS, fidvidstatus.val);
0602
0603 recalibrate_cpu_khz();
0604
0605 fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.CFID];
0606 if (!fsb) {
0607 pr_warn("can not determine bus frequency\n");
0608 return -EINVAL;
0609 }
0610 pr_debug("FSB: %3dMHz\n", fsb/1000);
0611
0612 if (dmi_check_system(powernow_dmi_table) || acpi_force) {
0613 pr_info("PSB/PST known to be broken - trying ACPI instead\n");
0614 result = powernow_acpi_init();
0615 } else {
0616 result = powernow_decode_bios(fidvidstatus.bits.MFID,
0617 fidvidstatus.bits.SVID);
0618 if (result) {
0619 pr_info("Trying ACPI perflib\n");
0620 maximum_speed = 0;
0621 minimum_speed = -1;
0622 latency = 0;
0623 result = powernow_acpi_init();
0624 if (result) {
0625 pr_info("ACPI and legacy methods failed\n");
0626 }
0627 } else {
0628
0629 latency = fixup_sgtc();
0630 pr_info("SGTC: %d\n", latency);
0631 }
0632 }
0633
0634 if (result)
0635 return result;
0636
0637 pr_info("Minimum speed %d MHz - Maximum speed %d MHz\n",
0638 minimum_speed/1000, maximum_speed/1000);
0639
0640 policy->cpuinfo.transition_latency =
0641 cpufreq_scale(2000000UL, fsb, latency);
0642 policy->freq_table = powernow_table;
0643
0644 return 0;
0645 }
0646
0647 static int powernow_cpu_exit(struct cpufreq_policy *policy)
0648 {
0649 #ifdef CONFIG_X86_POWERNOW_K7_ACPI
0650 if (acpi_processor_perf) {
0651 acpi_processor_unregister_performance(0);
0652 free_cpumask_var(acpi_processor_perf->shared_cpu_map);
0653 kfree(acpi_processor_perf);
0654 }
0655 #endif
0656
0657 kfree(powernow_table);
0658 return 0;
0659 }
0660
0661 static struct cpufreq_driver powernow_driver = {
0662 .verify = cpufreq_generic_frequency_table_verify,
0663 .target_index = powernow_target,
0664 .get = powernow_get,
0665 #ifdef CONFIG_X86_POWERNOW_K7_ACPI
0666 .bios_limit = acpi_processor_get_bios_limit,
0667 #endif
0668 .init = powernow_cpu_init,
0669 .exit = powernow_cpu_exit,
0670 .name = "powernow-k7",
0671 .attr = cpufreq_generic_attr,
0672 };
0673
0674 static int __init powernow_init(void)
0675 {
0676 if (check_powernow() == 0)
0677 return -ENODEV;
0678 return cpufreq_register_driver(&powernow_driver);
0679 }
0680
0681
0682 static void __exit powernow_exit(void)
0683 {
0684 cpufreq_unregister_driver(&powernow_driver);
0685 }
0686
0687 module_param(acpi_force, int, 0444);
0688 MODULE_PARM_DESC(acpi_force, "Force ACPI to be used.");
0689
0690 MODULE_AUTHOR("Dave Jones");
0691 MODULE_DESCRIPTION("Powernow driver for AMD K7 processors.");
0692 MODULE_LICENSE("GPL");
0693
0694 late_initcall(powernow_init);
0695 module_exit(powernow_exit);
0696