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