1bb0a56ecSDave Jones /* 2b2bd68e1SAndreas Herrmann * (c) 2003-2012 Advanced Micro Devices, Inc. 3bb0a56ecSDave Jones * Your use of this code is subject to the terms and conditions of the 4bb0a56ecSDave Jones * GNU general public license version 2. See "COPYING" or 5bb0a56ecSDave Jones * http://www.gnu.org/licenses/gpl.html 6bb0a56ecSDave Jones * 7b2bd68e1SAndreas Herrmann * Maintainer: 829c4bcddSAndreas Herrmann * Andreas Herrmann <herrmann.der.user@googlemail.com> 9bb0a56ecSDave Jones * 10bb0a56ecSDave Jones * Based on the powernow-k7.c module written by Dave Jones. 11bb0a56ecSDave Jones * (C) 2003 Dave Jones on behalf of SuSE Labs 12bb0a56ecSDave Jones * (C) 2004 Dominik Brodowski <linux@brodo.de> 13bb0a56ecSDave Jones * (C) 2004 Pavel Machek <pavel@ucw.cz> 14bb0a56ecSDave Jones * Licensed under the terms of the GNU GPL License version 2. 15bb0a56ecSDave Jones * Based upon datasheets & sample CPUs kindly provided by AMD. 16bb0a56ecSDave Jones * 17bb0a56ecSDave Jones * Valuable input gratefully received from Dave Jones, Pavel Machek, 18bb0a56ecSDave Jones * Dominik Brodowski, Jacob Shin, and others. 19bb0a56ecSDave Jones * Originally developed by Paul Devriendt. 20bb0a56ecSDave Jones * 21b2bd68e1SAndreas Herrmann * Processor information obtained from Chapter 9 (Power and Thermal 22b2bd68e1SAndreas Herrmann * Management) of the "BIOS and Kernel Developer's Guide (BKDG) for 23b2bd68e1SAndreas Herrmann * the AMD Athlon 64 and AMD Opteron Processors" and section "2.x 24b2bd68e1SAndreas Herrmann * Power Management" in BKDGs for newer AMD CPU families. 25b2bd68e1SAndreas Herrmann * 26b2bd68e1SAndreas Herrmann * Tables for specific CPUs can be inferred from AMD's processor 27b2bd68e1SAndreas Herrmann * power and thermal data sheets, (e.g. 30417.pdf, 30430.pdf, 43375.pdf) 28bb0a56ecSDave Jones */ 29bb0a56ecSDave Jones 30bb0a56ecSDave Jones #include <linux/kernel.h> 31bb0a56ecSDave Jones #include <linux/smp.h> 32bb0a56ecSDave Jones #include <linux/module.h> 33bb0a56ecSDave Jones #include <linux/init.h> 34bb0a56ecSDave Jones #include <linux/cpufreq.h> 35bb0a56ecSDave Jones #include <linux/slab.h> 36bb0a56ecSDave Jones #include <linux/string.h> 37bb0a56ecSDave Jones #include <linux/cpumask.h> 38bb0a56ecSDave Jones #include <linux/io.h> 39bb0a56ecSDave Jones #include <linux/delay.h> 40bb0a56ecSDave Jones 41bb0a56ecSDave Jones #include <asm/msr.h> 42fa8031aeSAndi Kleen #include <asm/cpu_device_id.h> 43bb0a56ecSDave Jones 44bb0a56ecSDave Jones #include <linux/acpi.h> 45bb0a56ecSDave Jones #include <linux/mutex.h> 46bb0a56ecSDave Jones #include <acpi/processor.h> 47bb0a56ecSDave Jones 48bb0a56ecSDave Jones #define PFX "powernow-k8: " 49bb0a56ecSDave Jones #define VERSION "version 2.20.00" 50bb0a56ecSDave Jones #include "powernow-k8.h" 51bb0a56ecSDave Jones 52bb0a56ecSDave Jones /* serialize freq changes */ 53bb0a56ecSDave Jones static DEFINE_MUTEX(fidvid_mutex); 54bb0a56ecSDave Jones 55bb0a56ecSDave Jones static DEFINE_PER_CPU(struct powernow_k8_data *, powernow_data); 56bb0a56ecSDave Jones 57bb0a56ecSDave Jones static struct cpufreq_driver cpufreq_amd64_driver; 58bb0a56ecSDave Jones 59bb0a56ecSDave Jones #ifndef CONFIG_SMP 60bb0a56ecSDave Jones static inline const struct cpumask *cpu_core_mask(int cpu) 61bb0a56ecSDave Jones { 62bb0a56ecSDave Jones return cpumask_of(0); 63bb0a56ecSDave Jones } 64bb0a56ecSDave Jones #endif 65bb0a56ecSDave Jones 66bb0a56ecSDave Jones /* Return a frequency in MHz, given an input fid */ 67bb0a56ecSDave Jones static u32 find_freq_from_fid(u32 fid) 68bb0a56ecSDave Jones { 69bb0a56ecSDave Jones return 800 + (fid * 100); 70bb0a56ecSDave Jones } 71bb0a56ecSDave Jones 72bb0a56ecSDave Jones /* Return a frequency in KHz, given an input fid */ 73bb0a56ecSDave Jones static u32 find_khz_freq_from_fid(u32 fid) 74bb0a56ecSDave Jones { 75bb0a56ecSDave Jones return 1000 * find_freq_from_fid(fid); 76bb0a56ecSDave Jones } 77bb0a56ecSDave Jones 78bb0a56ecSDave Jones /* Return the vco fid for an input fid 79bb0a56ecSDave Jones * 80bb0a56ecSDave Jones * Each "low" fid has corresponding "high" fid, and you can get to "low" fids 81bb0a56ecSDave Jones * only from corresponding high fids. This returns "high" fid corresponding to 82bb0a56ecSDave Jones * "low" one. 83bb0a56ecSDave Jones */ 84bb0a56ecSDave Jones static u32 convert_fid_to_vco_fid(u32 fid) 85bb0a56ecSDave Jones { 86bb0a56ecSDave Jones if (fid < HI_FID_TABLE_BOTTOM) 87bb0a56ecSDave Jones return 8 + (2 * fid); 88bb0a56ecSDave Jones else 89bb0a56ecSDave Jones return fid; 90bb0a56ecSDave Jones } 91bb0a56ecSDave Jones 92bb0a56ecSDave Jones /* 93bb0a56ecSDave Jones * Return 1 if the pending bit is set. Unless we just instructed the processor 94bb0a56ecSDave Jones * to transition to a new state, seeing this bit set is really bad news. 95bb0a56ecSDave Jones */ 96bb0a56ecSDave Jones static int pending_bit_stuck(void) 97bb0a56ecSDave Jones { 98bb0a56ecSDave Jones u32 lo, hi; 99bb0a56ecSDave Jones 100bb0a56ecSDave Jones rdmsr(MSR_FIDVID_STATUS, lo, hi); 101bb0a56ecSDave Jones return lo & MSR_S_LO_CHANGE_PENDING ? 1 : 0; 102bb0a56ecSDave Jones } 103bb0a56ecSDave Jones 104bb0a56ecSDave Jones /* 105bb0a56ecSDave Jones * Update the global current fid / vid values from the status msr. 106bb0a56ecSDave Jones * Returns 1 on error. 107bb0a56ecSDave Jones */ 108bb0a56ecSDave Jones static int query_current_values_with_pending_wait(struct powernow_k8_data *data) 109bb0a56ecSDave Jones { 110bb0a56ecSDave Jones u32 lo, hi; 111bb0a56ecSDave Jones u32 i = 0; 112bb0a56ecSDave Jones 113bb0a56ecSDave Jones do { 114bb0a56ecSDave Jones if (i++ > 10000) { 115bb0a56ecSDave Jones pr_debug("detected change pending stuck\n"); 116bb0a56ecSDave Jones return 1; 117bb0a56ecSDave Jones } 118bb0a56ecSDave Jones rdmsr(MSR_FIDVID_STATUS, lo, hi); 119bb0a56ecSDave Jones } while (lo & MSR_S_LO_CHANGE_PENDING); 120bb0a56ecSDave Jones 121bb0a56ecSDave Jones data->currvid = hi & MSR_S_HI_CURRENT_VID; 122bb0a56ecSDave Jones data->currfid = lo & MSR_S_LO_CURRENT_FID; 123bb0a56ecSDave Jones 124bb0a56ecSDave Jones return 0; 125bb0a56ecSDave Jones } 126bb0a56ecSDave Jones 127bb0a56ecSDave Jones /* the isochronous relief time */ 128bb0a56ecSDave Jones static void count_off_irt(struct powernow_k8_data *data) 129bb0a56ecSDave Jones { 130bb0a56ecSDave Jones udelay((1 << data->irt) * 10); 131bb0a56ecSDave Jones return; 132bb0a56ecSDave Jones } 133bb0a56ecSDave Jones 134bb0a56ecSDave Jones /* the voltage stabilization time */ 135bb0a56ecSDave Jones static void count_off_vst(struct powernow_k8_data *data) 136bb0a56ecSDave Jones { 137bb0a56ecSDave Jones udelay(data->vstable * VST_UNITS_20US); 138bb0a56ecSDave Jones return; 139bb0a56ecSDave Jones } 140bb0a56ecSDave Jones 141bb0a56ecSDave Jones /* need to init the control msr to a safe value (for each cpu) */ 142bb0a56ecSDave Jones static void fidvid_msr_init(void) 143bb0a56ecSDave Jones { 144bb0a56ecSDave Jones u32 lo, hi; 145bb0a56ecSDave Jones u8 fid, vid; 146bb0a56ecSDave Jones 147bb0a56ecSDave Jones rdmsr(MSR_FIDVID_STATUS, lo, hi); 148bb0a56ecSDave Jones vid = hi & MSR_S_HI_CURRENT_VID; 149bb0a56ecSDave Jones fid = lo & MSR_S_LO_CURRENT_FID; 150bb0a56ecSDave Jones lo = fid | (vid << MSR_C_LO_VID_SHIFT); 151bb0a56ecSDave Jones hi = MSR_C_HI_STP_GNT_BENIGN; 152bb0a56ecSDave Jones pr_debug("cpu%d, init lo 0x%x, hi 0x%x\n", smp_processor_id(), lo, hi); 153bb0a56ecSDave Jones wrmsr(MSR_FIDVID_CTL, lo, hi); 154bb0a56ecSDave Jones } 155bb0a56ecSDave Jones 156bb0a56ecSDave Jones /* write the new fid value along with the other control fields to the msr */ 157bb0a56ecSDave Jones static int write_new_fid(struct powernow_k8_data *data, u32 fid) 158bb0a56ecSDave Jones { 159bb0a56ecSDave Jones u32 lo; 160bb0a56ecSDave Jones u32 savevid = data->currvid; 161bb0a56ecSDave Jones u32 i = 0; 162bb0a56ecSDave Jones 163bb0a56ecSDave Jones if ((fid & INVALID_FID_MASK) || (data->currvid & INVALID_VID_MASK)) { 164bb0a56ecSDave Jones printk(KERN_ERR PFX "internal error - overflow on fid write\n"); 165bb0a56ecSDave Jones return 1; 166bb0a56ecSDave Jones } 167bb0a56ecSDave Jones 168bb0a56ecSDave Jones lo = fid; 169bb0a56ecSDave Jones lo |= (data->currvid << MSR_C_LO_VID_SHIFT); 170bb0a56ecSDave Jones lo |= MSR_C_LO_INIT_FID_VID; 171bb0a56ecSDave Jones 172bb0a56ecSDave Jones pr_debug("writing fid 0x%x, lo 0x%x, hi 0x%x\n", 173bb0a56ecSDave Jones fid, lo, data->plllock * PLL_LOCK_CONVERSION); 174bb0a56ecSDave Jones 175bb0a56ecSDave Jones do { 176bb0a56ecSDave Jones wrmsr(MSR_FIDVID_CTL, lo, data->plllock * PLL_LOCK_CONVERSION); 177bb0a56ecSDave Jones if (i++ > 100) { 178bb0a56ecSDave Jones printk(KERN_ERR PFX 179bb0a56ecSDave Jones "Hardware error - pending bit very stuck - " 180bb0a56ecSDave Jones "no further pstate changes possible\n"); 181bb0a56ecSDave Jones return 1; 182bb0a56ecSDave Jones } 183bb0a56ecSDave Jones } while (query_current_values_with_pending_wait(data)); 184bb0a56ecSDave Jones 185bb0a56ecSDave Jones count_off_irt(data); 186bb0a56ecSDave Jones 187bb0a56ecSDave Jones if (savevid != data->currvid) { 188bb0a56ecSDave Jones printk(KERN_ERR PFX 189bb0a56ecSDave Jones "vid change on fid trans, old 0x%x, new 0x%x\n", 190bb0a56ecSDave Jones savevid, data->currvid); 191bb0a56ecSDave Jones return 1; 192bb0a56ecSDave Jones } 193bb0a56ecSDave Jones 194bb0a56ecSDave Jones if (fid != data->currfid) { 195bb0a56ecSDave Jones printk(KERN_ERR PFX 196bb0a56ecSDave Jones "fid trans failed, fid 0x%x, curr 0x%x\n", fid, 197bb0a56ecSDave Jones data->currfid); 198bb0a56ecSDave Jones return 1; 199bb0a56ecSDave Jones } 200bb0a56ecSDave Jones 201bb0a56ecSDave Jones return 0; 202bb0a56ecSDave Jones } 203bb0a56ecSDave Jones 204bb0a56ecSDave Jones /* Write a new vid to the hardware */ 205bb0a56ecSDave Jones static int write_new_vid(struct powernow_k8_data *data, u32 vid) 206bb0a56ecSDave Jones { 207bb0a56ecSDave Jones u32 lo; 208bb0a56ecSDave Jones u32 savefid = data->currfid; 209bb0a56ecSDave Jones int i = 0; 210bb0a56ecSDave Jones 211bb0a56ecSDave Jones if ((data->currfid & INVALID_FID_MASK) || (vid & INVALID_VID_MASK)) { 212bb0a56ecSDave Jones printk(KERN_ERR PFX "internal error - overflow on vid write\n"); 213bb0a56ecSDave Jones return 1; 214bb0a56ecSDave Jones } 215bb0a56ecSDave Jones 216bb0a56ecSDave Jones lo = data->currfid; 217bb0a56ecSDave Jones lo |= (vid << MSR_C_LO_VID_SHIFT); 218bb0a56ecSDave Jones lo |= MSR_C_LO_INIT_FID_VID; 219bb0a56ecSDave Jones 220bb0a56ecSDave Jones pr_debug("writing vid 0x%x, lo 0x%x, hi 0x%x\n", 221bb0a56ecSDave Jones vid, lo, STOP_GRANT_5NS); 222bb0a56ecSDave Jones 223bb0a56ecSDave Jones do { 224bb0a56ecSDave Jones wrmsr(MSR_FIDVID_CTL, lo, STOP_GRANT_5NS); 225bb0a56ecSDave Jones if (i++ > 100) { 226bb0a56ecSDave Jones printk(KERN_ERR PFX "internal error - pending bit " 227bb0a56ecSDave Jones "very stuck - no further pstate " 228bb0a56ecSDave Jones "changes possible\n"); 229bb0a56ecSDave Jones return 1; 230bb0a56ecSDave Jones } 231bb0a56ecSDave Jones } while (query_current_values_with_pending_wait(data)); 232bb0a56ecSDave Jones 233bb0a56ecSDave Jones if (savefid != data->currfid) { 234bb0a56ecSDave Jones printk(KERN_ERR PFX "fid changed on vid trans, old " 235bb0a56ecSDave Jones "0x%x new 0x%x\n", 236bb0a56ecSDave Jones savefid, data->currfid); 237bb0a56ecSDave Jones return 1; 238bb0a56ecSDave Jones } 239bb0a56ecSDave Jones 240bb0a56ecSDave Jones if (vid != data->currvid) { 241bb0a56ecSDave Jones printk(KERN_ERR PFX "vid trans failed, vid 0x%x, " 242bb0a56ecSDave Jones "curr 0x%x\n", 243bb0a56ecSDave Jones vid, data->currvid); 244bb0a56ecSDave Jones return 1; 245bb0a56ecSDave Jones } 246bb0a56ecSDave Jones 247bb0a56ecSDave Jones return 0; 248bb0a56ecSDave Jones } 249bb0a56ecSDave Jones 250bb0a56ecSDave Jones /* 251bb0a56ecSDave Jones * Reduce the vid by the max of step or reqvid. 252bb0a56ecSDave Jones * Decreasing vid codes represent increasing voltages: 253bb0a56ecSDave Jones * vid of 0 is 1.550V, vid of 0x1e is 0.800V, vid of VID_OFF is off. 254bb0a56ecSDave Jones */ 255bb0a56ecSDave Jones static int decrease_vid_code_by_step(struct powernow_k8_data *data, 256bb0a56ecSDave Jones u32 reqvid, u32 step) 257bb0a56ecSDave Jones { 258bb0a56ecSDave Jones if ((data->currvid - reqvid) > step) 259bb0a56ecSDave Jones reqvid = data->currvid - step; 260bb0a56ecSDave Jones 261bb0a56ecSDave Jones if (write_new_vid(data, reqvid)) 262bb0a56ecSDave Jones return 1; 263bb0a56ecSDave Jones 264bb0a56ecSDave Jones count_off_vst(data); 265bb0a56ecSDave Jones 266bb0a56ecSDave Jones return 0; 267bb0a56ecSDave Jones } 268bb0a56ecSDave Jones 269bb0a56ecSDave Jones /* Change Opteron/Athlon64 fid and vid, by the 3 phases. */ 270bb0a56ecSDave Jones static int transition_fid_vid(struct powernow_k8_data *data, 271bb0a56ecSDave Jones u32 reqfid, u32 reqvid) 272bb0a56ecSDave Jones { 273bb0a56ecSDave Jones if (core_voltage_pre_transition(data, reqvid, reqfid)) 274bb0a56ecSDave Jones return 1; 275bb0a56ecSDave Jones 276bb0a56ecSDave Jones if (core_frequency_transition(data, reqfid)) 277bb0a56ecSDave Jones return 1; 278bb0a56ecSDave Jones 279bb0a56ecSDave Jones if (core_voltage_post_transition(data, reqvid)) 280bb0a56ecSDave Jones return 1; 281bb0a56ecSDave Jones 282bb0a56ecSDave Jones if (query_current_values_with_pending_wait(data)) 283bb0a56ecSDave Jones return 1; 284bb0a56ecSDave Jones 285bb0a56ecSDave Jones if ((reqfid != data->currfid) || (reqvid != data->currvid)) { 286bb0a56ecSDave Jones printk(KERN_ERR PFX "failed (cpu%d): req 0x%x 0x%x, " 287bb0a56ecSDave Jones "curr 0x%x 0x%x\n", 288bb0a56ecSDave Jones smp_processor_id(), 289bb0a56ecSDave Jones reqfid, reqvid, data->currfid, data->currvid); 290bb0a56ecSDave Jones return 1; 291bb0a56ecSDave Jones } 292bb0a56ecSDave Jones 293bb0a56ecSDave Jones pr_debug("transitioned (cpu%d): new fid 0x%x, vid 0x%x\n", 294bb0a56ecSDave Jones smp_processor_id(), data->currfid, data->currvid); 295bb0a56ecSDave Jones 296bb0a56ecSDave Jones return 0; 297bb0a56ecSDave Jones } 298bb0a56ecSDave Jones 299bb0a56ecSDave Jones /* Phase 1 - core voltage transition ... setup voltage */ 300bb0a56ecSDave Jones static int core_voltage_pre_transition(struct powernow_k8_data *data, 301bb0a56ecSDave Jones u32 reqvid, u32 reqfid) 302bb0a56ecSDave Jones { 303bb0a56ecSDave Jones u32 rvosteps = data->rvo; 304bb0a56ecSDave Jones u32 savefid = data->currfid; 305bb0a56ecSDave Jones u32 maxvid, lo, rvomult = 1; 306bb0a56ecSDave Jones 307bb0a56ecSDave Jones pr_debug("ph1 (cpu%d): start, currfid 0x%x, currvid 0x%x, " 308bb0a56ecSDave Jones "reqvid 0x%x, rvo 0x%x\n", 309bb0a56ecSDave Jones smp_processor_id(), 310bb0a56ecSDave Jones data->currfid, data->currvid, reqvid, data->rvo); 311bb0a56ecSDave Jones 312bb0a56ecSDave Jones if ((savefid < LO_FID_TABLE_TOP) && (reqfid < LO_FID_TABLE_TOP)) 313bb0a56ecSDave Jones rvomult = 2; 314bb0a56ecSDave Jones rvosteps *= rvomult; 315bb0a56ecSDave Jones rdmsr(MSR_FIDVID_STATUS, lo, maxvid); 316bb0a56ecSDave Jones maxvid = 0x1f & (maxvid >> 16); 317bb0a56ecSDave Jones pr_debug("ph1 maxvid=0x%x\n", maxvid); 318bb0a56ecSDave Jones if (reqvid < maxvid) /* lower numbers are higher voltages */ 319bb0a56ecSDave Jones reqvid = maxvid; 320bb0a56ecSDave Jones 321bb0a56ecSDave Jones while (data->currvid > reqvid) { 322bb0a56ecSDave Jones pr_debug("ph1: curr 0x%x, req vid 0x%x\n", 323bb0a56ecSDave Jones data->currvid, reqvid); 324bb0a56ecSDave Jones if (decrease_vid_code_by_step(data, reqvid, data->vidmvs)) 325bb0a56ecSDave Jones return 1; 326bb0a56ecSDave Jones } 327bb0a56ecSDave Jones 328bb0a56ecSDave Jones while ((rvosteps > 0) && 329bb0a56ecSDave Jones ((rvomult * data->rvo + data->currvid) > reqvid)) { 330bb0a56ecSDave Jones if (data->currvid == maxvid) { 331bb0a56ecSDave Jones rvosteps = 0; 332bb0a56ecSDave Jones } else { 333bb0a56ecSDave Jones pr_debug("ph1: changing vid for rvo, req 0x%x\n", 334bb0a56ecSDave Jones data->currvid - 1); 335bb0a56ecSDave Jones if (decrease_vid_code_by_step(data, data->currvid-1, 1)) 336bb0a56ecSDave Jones return 1; 337bb0a56ecSDave Jones rvosteps--; 338bb0a56ecSDave Jones } 339bb0a56ecSDave Jones } 340bb0a56ecSDave Jones 341bb0a56ecSDave Jones if (query_current_values_with_pending_wait(data)) 342bb0a56ecSDave Jones return 1; 343bb0a56ecSDave Jones 344bb0a56ecSDave Jones if (savefid != data->currfid) { 345bb0a56ecSDave Jones printk(KERN_ERR PFX "ph1 err, currfid changed 0x%x\n", 346bb0a56ecSDave Jones data->currfid); 347bb0a56ecSDave Jones return 1; 348bb0a56ecSDave Jones } 349bb0a56ecSDave Jones 350bb0a56ecSDave Jones pr_debug("ph1 complete, currfid 0x%x, currvid 0x%x\n", 351bb0a56ecSDave Jones data->currfid, data->currvid); 352bb0a56ecSDave Jones 353bb0a56ecSDave Jones return 0; 354bb0a56ecSDave Jones } 355bb0a56ecSDave Jones 356bb0a56ecSDave Jones /* Phase 2 - core frequency transition */ 357bb0a56ecSDave Jones static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid) 358bb0a56ecSDave Jones { 359bb0a56ecSDave Jones u32 vcoreqfid, vcocurrfid, vcofiddiff; 360bb0a56ecSDave Jones u32 fid_interval, savevid = data->currvid; 361bb0a56ecSDave Jones 362bb0a56ecSDave Jones if (data->currfid == reqfid) { 363bb0a56ecSDave Jones printk(KERN_ERR PFX "ph2 null fid transition 0x%x\n", 364bb0a56ecSDave Jones data->currfid); 365bb0a56ecSDave Jones return 0; 366bb0a56ecSDave Jones } 367bb0a56ecSDave Jones 368bb0a56ecSDave Jones pr_debug("ph2 (cpu%d): starting, currfid 0x%x, currvid 0x%x, " 369bb0a56ecSDave Jones "reqfid 0x%x\n", 370bb0a56ecSDave Jones smp_processor_id(), 371bb0a56ecSDave Jones data->currfid, data->currvid, reqfid); 372bb0a56ecSDave Jones 373bb0a56ecSDave Jones vcoreqfid = convert_fid_to_vco_fid(reqfid); 374bb0a56ecSDave Jones vcocurrfid = convert_fid_to_vco_fid(data->currfid); 375bb0a56ecSDave Jones vcofiddiff = vcocurrfid > vcoreqfid ? vcocurrfid - vcoreqfid 376bb0a56ecSDave Jones : vcoreqfid - vcocurrfid; 377bb0a56ecSDave Jones 378bb0a56ecSDave Jones if ((reqfid <= LO_FID_TABLE_TOP) && (data->currfid <= LO_FID_TABLE_TOP)) 379bb0a56ecSDave Jones vcofiddiff = 0; 380bb0a56ecSDave Jones 381bb0a56ecSDave Jones while (vcofiddiff > 2) { 382bb0a56ecSDave Jones (data->currfid & 1) ? (fid_interval = 1) : (fid_interval = 2); 383bb0a56ecSDave Jones 384bb0a56ecSDave Jones if (reqfid > data->currfid) { 385bb0a56ecSDave Jones if (data->currfid > LO_FID_TABLE_TOP) { 386bb0a56ecSDave Jones if (write_new_fid(data, 387bb0a56ecSDave Jones data->currfid + fid_interval)) 388bb0a56ecSDave Jones return 1; 389bb0a56ecSDave Jones } else { 390bb0a56ecSDave Jones if (write_new_fid 391bb0a56ecSDave Jones (data, 392bb0a56ecSDave Jones 2 + convert_fid_to_vco_fid(data->currfid))) 393bb0a56ecSDave Jones return 1; 394bb0a56ecSDave Jones } 395bb0a56ecSDave Jones } else { 396bb0a56ecSDave Jones if (write_new_fid(data, data->currfid - fid_interval)) 397bb0a56ecSDave Jones return 1; 398bb0a56ecSDave Jones } 399bb0a56ecSDave Jones 400bb0a56ecSDave Jones vcocurrfid = convert_fid_to_vco_fid(data->currfid); 401bb0a56ecSDave Jones vcofiddiff = vcocurrfid > vcoreqfid ? vcocurrfid - vcoreqfid 402bb0a56ecSDave Jones : vcoreqfid - vcocurrfid; 403bb0a56ecSDave Jones } 404bb0a56ecSDave Jones 405bb0a56ecSDave Jones if (write_new_fid(data, reqfid)) 406bb0a56ecSDave Jones return 1; 407bb0a56ecSDave Jones 408bb0a56ecSDave Jones if (query_current_values_with_pending_wait(data)) 409bb0a56ecSDave Jones return 1; 410bb0a56ecSDave Jones 411bb0a56ecSDave Jones if (data->currfid != reqfid) { 412bb0a56ecSDave Jones printk(KERN_ERR PFX 413bb0a56ecSDave Jones "ph2: mismatch, failed fid transition, " 414bb0a56ecSDave Jones "curr 0x%x, req 0x%x\n", 415bb0a56ecSDave Jones data->currfid, reqfid); 416bb0a56ecSDave Jones return 1; 417bb0a56ecSDave Jones } 418bb0a56ecSDave Jones 419bb0a56ecSDave Jones if (savevid != data->currvid) { 420bb0a56ecSDave Jones printk(KERN_ERR PFX "ph2: vid changed, save 0x%x, curr 0x%x\n", 421bb0a56ecSDave Jones savevid, data->currvid); 422bb0a56ecSDave Jones return 1; 423bb0a56ecSDave Jones } 424bb0a56ecSDave Jones 425bb0a56ecSDave Jones pr_debug("ph2 complete, currfid 0x%x, currvid 0x%x\n", 426bb0a56ecSDave Jones data->currfid, data->currvid); 427bb0a56ecSDave Jones 428bb0a56ecSDave Jones return 0; 429bb0a56ecSDave Jones } 430bb0a56ecSDave Jones 431bb0a56ecSDave Jones /* Phase 3 - core voltage transition flow ... jump to the final vid. */ 432bb0a56ecSDave Jones static int core_voltage_post_transition(struct powernow_k8_data *data, 433bb0a56ecSDave Jones u32 reqvid) 434bb0a56ecSDave Jones { 435bb0a56ecSDave Jones u32 savefid = data->currfid; 436bb0a56ecSDave Jones u32 savereqvid = reqvid; 437bb0a56ecSDave Jones 438bb0a56ecSDave Jones pr_debug("ph3 (cpu%d): starting, currfid 0x%x, currvid 0x%x\n", 439bb0a56ecSDave Jones smp_processor_id(), 440bb0a56ecSDave Jones data->currfid, data->currvid); 441bb0a56ecSDave Jones 442bb0a56ecSDave Jones if (reqvid != data->currvid) { 443bb0a56ecSDave Jones if (write_new_vid(data, reqvid)) 444bb0a56ecSDave Jones return 1; 445bb0a56ecSDave Jones 446bb0a56ecSDave Jones if (savefid != data->currfid) { 447bb0a56ecSDave Jones printk(KERN_ERR PFX 448bb0a56ecSDave Jones "ph3: bad fid change, save 0x%x, curr 0x%x\n", 449bb0a56ecSDave Jones savefid, data->currfid); 450bb0a56ecSDave Jones return 1; 451bb0a56ecSDave Jones } 452bb0a56ecSDave Jones 453bb0a56ecSDave Jones if (data->currvid != reqvid) { 454bb0a56ecSDave Jones printk(KERN_ERR PFX 455bb0a56ecSDave Jones "ph3: failed vid transition\n, " 456bb0a56ecSDave Jones "req 0x%x, curr 0x%x", 457bb0a56ecSDave Jones reqvid, data->currvid); 458bb0a56ecSDave Jones return 1; 459bb0a56ecSDave Jones } 460bb0a56ecSDave Jones } 461bb0a56ecSDave Jones 462bb0a56ecSDave Jones if (query_current_values_with_pending_wait(data)) 463bb0a56ecSDave Jones return 1; 464bb0a56ecSDave Jones 465bb0a56ecSDave Jones if (savereqvid != data->currvid) { 466bb0a56ecSDave Jones pr_debug("ph3 failed, currvid 0x%x\n", data->currvid); 467bb0a56ecSDave Jones return 1; 468bb0a56ecSDave Jones } 469bb0a56ecSDave Jones 470bb0a56ecSDave Jones if (savefid != data->currfid) { 471bb0a56ecSDave Jones pr_debug("ph3 failed, currfid changed 0x%x\n", 472bb0a56ecSDave Jones data->currfid); 473bb0a56ecSDave Jones return 1; 474bb0a56ecSDave Jones } 475bb0a56ecSDave Jones 476bb0a56ecSDave Jones pr_debug("ph3 complete, currfid 0x%x, currvid 0x%x\n", 477bb0a56ecSDave Jones data->currfid, data->currvid); 478bb0a56ecSDave Jones 479bb0a56ecSDave Jones return 0; 480bb0a56ecSDave Jones } 481bb0a56ecSDave Jones 482fa8031aeSAndi Kleen static const struct x86_cpu_id powernow_k8_ids[] = { 483fa8031aeSAndi Kleen /* IO based frequency switching */ 484fa8031aeSAndi Kleen { X86_VENDOR_AMD, 0xf }, 485fa8031aeSAndi Kleen {} 486fa8031aeSAndi Kleen }; 487fa8031aeSAndi Kleen MODULE_DEVICE_TABLE(x86cpu, powernow_k8_ids); 488fa8031aeSAndi Kleen 489bb0a56ecSDave Jones static void check_supported_cpu(void *_rc) 490bb0a56ecSDave Jones { 491bb0a56ecSDave Jones u32 eax, ebx, ecx, edx; 492bb0a56ecSDave Jones int *rc = _rc; 493bb0a56ecSDave Jones 494bb0a56ecSDave Jones *rc = -ENODEV; 495bb0a56ecSDave Jones 496bb0a56ecSDave Jones eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE); 497bb0a56ecSDave Jones 498bb0a56ecSDave Jones if ((eax & CPUID_XFAM) == CPUID_XFAM_K8) { 499bb0a56ecSDave Jones if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) || 500bb0a56ecSDave Jones ((eax & CPUID_XMOD) > CPUID_XMOD_REV_MASK)) { 501bb0a56ecSDave Jones printk(KERN_INFO PFX 502bb0a56ecSDave Jones "Processor cpuid %x not supported\n", eax); 503bb0a56ecSDave Jones return; 504bb0a56ecSDave Jones } 505bb0a56ecSDave Jones 506bb0a56ecSDave Jones eax = cpuid_eax(CPUID_GET_MAX_CAPABILITIES); 507bb0a56ecSDave Jones if (eax < CPUID_FREQ_VOLT_CAPABILITIES) { 508bb0a56ecSDave Jones printk(KERN_INFO PFX 509bb0a56ecSDave Jones "No frequency change capabilities detected\n"); 510bb0a56ecSDave Jones return; 511bb0a56ecSDave Jones } 512bb0a56ecSDave Jones 513bb0a56ecSDave Jones cpuid(CPUID_FREQ_VOLT_CAPABILITIES, &eax, &ebx, &ecx, &edx); 514bb0a56ecSDave Jones if ((edx & P_STATE_TRANSITION_CAPABLE) 515bb0a56ecSDave Jones != P_STATE_TRANSITION_CAPABLE) { 516bb0a56ecSDave Jones printk(KERN_INFO PFX 517bb0a56ecSDave Jones "Power state transitions not supported\n"); 518bb0a56ecSDave Jones return; 519bb0a56ecSDave Jones } 520bb0a56ecSDave Jones *rc = 0; 521bb0a56ecSDave Jones } 522e1f0b8e9SMatthew Garrett } 523bb0a56ecSDave Jones 524bb0a56ecSDave Jones static int check_pst_table(struct powernow_k8_data *data, struct pst_s *pst, 525bb0a56ecSDave Jones u8 maxvid) 526bb0a56ecSDave Jones { 527bb0a56ecSDave Jones unsigned int j; 528bb0a56ecSDave Jones u8 lastfid = 0xff; 529bb0a56ecSDave Jones 530bb0a56ecSDave Jones for (j = 0; j < data->numps; j++) { 531bb0a56ecSDave Jones if (pst[j].vid > LEAST_VID) { 532bb0a56ecSDave Jones printk(KERN_ERR FW_BUG PFX "vid %d invalid : 0x%x\n", 533bb0a56ecSDave Jones j, pst[j].vid); 534bb0a56ecSDave Jones return -EINVAL; 535bb0a56ecSDave Jones } 536bb0a56ecSDave Jones if (pst[j].vid < data->rvo) { 537bb0a56ecSDave Jones /* vid + rvo >= 0 */ 538bb0a56ecSDave Jones printk(KERN_ERR FW_BUG PFX "0 vid exceeded with pstate" 539bb0a56ecSDave Jones " %d\n", j); 540bb0a56ecSDave Jones return -ENODEV; 541bb0a56ecSDave Jones } 542bb0a56ecSDave Jones if (pst[j].vid < maxvid + data->rvo) { 543bb0a56ecSDave Jones /* vid + rvo >= maxvid */ 544bb0a56ecSDave Jones printk(KERN_ERR FW_BUG PFX "maxvid exceeded with pstate" 545bb0a56ecSDave Jones " %d\n", j); 546bb0a56ecSDave Jones return -ENODEV; 547bb0a56ecSDave Jones } 548bb0a56ecSDave Jones if (pst[j].fid > MAX_FID) { 549bb0a56ecSDave Jones printk(KERN_ERR FW_BUG PFX "maxfid exceeded with pstate" 550bb0a56ecSDave Jones " %d\n", j); 551bb0a56ecSDave Jones return -ENODEV; 552bb0a56ecSDave Jones } 553bb0a56ecSDave Jones if (j && (pst[j].fid < HI_FID_TABLE_BOTTOM)) { 554bb0a56ecSDave Jones /* Only first fid is allowed to be in "low" range */ 555bb0a56ecSDave Jones printk(KERN_ERR FW_BUG PFX "two low fids - %d : " 556bb0a56ecSDave Jones "0x%x\n", j, pst[j].fid); 557bb0a56ecSDave Jones return -EINVAL; 558bb0a56ecSDave Jones } 559bb0a56ecSDave Jones if (pst[j].fid < lastfid) 560bb0a56ecSDave Jones lastfid = pst[j].fid; 561bb0a56ecSDave Jones } 562bb0a56ecSDave Jones if (lastfid & 1) { 563bb0a56ecSDave Jones printk(KERN_ERR FW_BUG PFX "lastfid invalid\n"); 564bb0a56ecSDave Jones return -EINVAL; 565bb0a56ecSDave Jones } 566bb0a56ecSDave Jones if (lastfid > LO_FID_TABLE_TOP) 567bb0a56ecSDave Jones printk(KERN_INFO FW_BUG PFX 568bb0a56ecSDave Jones "first fid not from lo freq table\n"); 569bb0a56ecSDave Jones 570bb0a56ecSDave Jones return 0; 571bb0a56ecSDave Jones } 572bb0a56ecSDave Jones 573bb0a56ecSDave Jones static void invalidate_entry(struct cpufreq_frequency_table *powernow_table, 574bb0a56ecSDave Jones unsigned int entry) 575bb0a56ecSDave Jones { 576bb0a56ecSDave Jones powernow_table[entry].frequency = CPUFREQ_ENTRY_INVALID; 577bb0a56ecSDave Jones } 578bb0a56ecSDave Jones 579bb0a56ecSDave Jones static void print_basics(struct powernow_k8_data *data) 580bb0a56ecSDave Jones { 581bb0a56ecSDave Jones int j; 582bb0a56ecSDave Jones for (j = 0; j < data->numps; j++) { 583bb0a56ecSDave Jones if (data->powernow_table[j].frequency != 584bb0a56ecSDave Jones CPUFREQ_ENTRY_INVALID) { 585bb0a56ecSDave Jones printk(KERN_INFO PFX 586bb0a56ecSDave Jones "fid 0x%x (%d MHz), vid 0x%x\n", 58750701588SViresh Kumar data->powernow_table[j].driver_data & 0xff, 588bb0a56ecSDave Jones data->powernow_table[j].frequency/1000, 58950701588SViresh Kumar data->powernow_table[j].driver_data >> 8); 590bb0a56ecSDave Jones } 591bb0a56ecSDave Jones } 592bb0a56ecSDave Jones if (data->batps) 593bb0a56ecSDave Jones printk(KERN_INFO PFX "Only %d pstates on battery\n", 594bb0a56ecSDave Jones data->batps); 595bb0a56ecSDave Jones } 596bb0a56ecSDave Jones 597bb0a56ecSDave Jones static int fill_powernow_table(struct powernow_k8_data *data, 598bb0a56ecSDave Jones struct pst_s *pst, u8 maxvid) 599bb0a56ecSDave Jones { 600bb0a56ecSDave Jones struct cpufreq_frequency_table *powernow_table; 601bb0a56ecSDave Jones unsigned int j; 602bb0a56ecSDave Jones 603bb0a56ecSDave Jones if (data->batps) { 604bb0a56ecSDave Jones /* use ACPI support to get full speed on mains power */ 605bb0a56ecSDave Jones printk(KERN_WARNING PFX 606bb0a56ecSDave Jones "Only %d pstates usable (use ACPI driver for full " 607bb0a56ecSDave Jones "range\n", data->batps); 608bb0a56ecSDave Jones data->numps = data->batps; 609bb0a56ecSDave Jones } 610bb0a56ecSDave Jones 611bb0a56ecSDave Jones for (j = 1; j < data->numps; j++) { 612bb0a56ecSDave Jones if (pst[j-1].fid >= pst[j].fid) { 613bb0a56ecSDave Jones printk(KERN_ERR PFX "PST out of sequence\n"); 614bb0a56ecSDave Jones return -EINVAL; 615bb0a56ecSDave Jones } 616bb0a56ecSDave Jones } 617bb0a56ecSDave Jones 618bb0a56ecSDave Jones if (data->numps < 2) { 619bb0a56ecSDave Jones printk(KERN_ERR PFX "no p states to transition\n"); 620bb0a56ecSDave Jones return -ENODEV; 621bb0a56ecSDave Jones } 622bb0a56ecSDave Jones 623bb0a56ecSDave Jones if (check_pst_table(data, pst, maxvid)) 624bb0a56ecSDave Jones return -EINVAL; 625bb0a56ecSDave Jones 626d5b73cd8SViresh Kumar powernow_table = kmalloc((sizeof(*powernow_table) 627bb0a56ecSDave Jones * (data->numps + 1)), GFP_KERNEL); 628bb0a56ecSDave Jones if (!powernow_table) { 629bb0a56ecSDave Jones printk(KERN_ERR PFX "powernow_table memory alloc failure\n"); 630bb0a56ecSDave Jones return -ENOMEM; 631bb0a56ecSDave Jones } 632bb0a56ecSDave Jones 633bb0a56ecSDave Jones for (j = 0; j < data->numps; j++) { 634bb0a56ecSDave Jones int freq; 63550701588SViresh Kumar powernow_table[j].driver_data = pst[j].fid; /* lower 8 bits */ 63650701588SViresh Kumar powernow_table[j].driver_data |= (pst[j].vid << 8); /* upper 8 bits */ 637bb0a56ecSDave Jones freq = find_khz_freq_from_fid(pst[j].fid); 638bb0a56ecSDave Jones powernow_table[j].frequency = freq; 639bb0a56ecSDave Jones } 640bb0a56ecSDave Jones powernow_table[data->numps].frequency = CPUFREQ_TABLE_END; 64150701588SViresh Kumar powernow_table[data->numps].driver_data = 0; 642bb0a56ecSDave Jones 643bb0a56ecSDave Jones if (query_current_values_with_pending_wait(data)) { 644bb0a56ecSDave Jones kfree(powernow_table); 645bb0a56ecSDave Jones return -EIO; 646bb0a56ecSDave Jones } 647bb0a56ecSDave Jones 648bb0a56ecSDave Jones pr_debug("cfid 0x%x, cvid 0x%x\n", data->currfid, data->currvid); 649bb0a56ecSDave Jones data->powernow_table = powernow_table; 650bb0a56ecSDave Jones if (cpumask_first(cpu_core_mask(data->cpu)) == data->cpu) 651bb0a56ecSDave Jones print_basics(data); 652bb0a56ecSDave Jones 653bb0a56ecSDave Jones for (j = 0; j < data->numps; j++) 654bb0a56ecSDave Jones if ((pst[j].fid == data->currfid) && 655bb0a56ecSDave Jones (pst[j].vid == data->currvid)) 656bb0a56ecSDave Jones return 0; 657bb0a56ecSDave Jones 658bb0a56ecSDave Jones pr_debug("currfid/vid do not match PST, ignoring\n"); 659bb0a56ecSDave Jones return 0; 660bb0a56ecSDave Jones } 661bb0a56ecSDave Jones 662bb0a56ecSDave Jones /* Find and validate the PSB/PST table in BIOS. */ 663bb0a56ecSDave Jones static int find_psb_table(struct powernow_k8_data *data) 664bb0a56ecSDave Jones { 665bb0a56ecSDave Jones struct psb_s *psb; 666bb0a56ecSDave Jones unsigned int i; 667bb0a56ecSDave Jones u32 mvs; 668bb0a56ecSDave Jones u8 maxvid; 669bb0a56ecSDave Jones u32 cpst = 0; 670bb0a56ecSDave Jones u32 thiscpuid; 671bb0a56ecSDave Jones 672bb0a56ecSDave Jones for (i = 0xc0000; i < 0xffff0; i += 0x10) { 673bb0a56ecSDave Jones /* Scan BIOS looking for the signature. */ 674bb0a56ecSDave Jones /* It can not be at ffff0 - it is too big. */ 675bb0a56ecSDave Jones 676bb0a56ecSDave Jones psb = phys_to_virt(i); 677bb0a56ecSDave Jones if (memcmp(psb, PSB_ID_STRING, PSB_ID_STRING_LEN) != 0) 678bb0a56ecSDave Jones continue; 679bb0a56ecSDave Jones 680bb0a56ecSDave Jones pr_debug("found PSB header at 0x%p\n", psb); 681bb0a56ecSDave Jones 682bb0a56ecSDave Jones pr_debug("table vers: 0x%x\n", psb->tableversion); 683bb0a56ecSDave Jones if (psb->tableversion != PSB_VERSION_1_4) { 684bb0a56ecSDave Jones printk(KERN_ERR FW_BUG PFX "PSB table is not v1.4\n"); 685bb0a56ecSDave Jones return -ENODEV; 686bb0a56ecSDave Jones } 687bb0a56ecSDave Jones 688bb0a56ecSDave Jones pr_debug("flags: 0x%x\n", psb->flags1); 689bb0a56ecSDave Jones if (psb->flags1) { 690bb0a56ecSDave Jones printk(KERN_ERR FW_BUG PFX "unknown flags\n"); 691bb0a56ecSDave Jones return -ENODEV; 692bb0a56ecSDave Jones } 693bb0a56ecSDave Jones 694bb0a56ecSDave Jones data->vstable = psb->vstable; 695bb0a56ecSDave Jones pr_debug("voltage stabilization time: %d(*20us)\n", 696bb0a56ecSDave Jones data->vstable); 697bb0a56ecSDave Jones 698bb0a56ecSDave Jones pr_debug("flags2: 0x%x\n", psb->flags2); 699bb0a56ecSDave Jones data->rvo = psb->flags2 & 3; 700bb0a56ecSDave Jones data->irt = ((psb->flags2) >> 2) & 3; 701bb0a56ecSDave Jones mvs = ((psb->flags2) >> 4) & 3; 702bb0a56ecSDave Jones data->vidmvs = 1 << mvs; 703bb0a56ecSDave Jones data->batps = ((psb->flags2) >> 6) & 3; 704bb0a56ecSDave Jones 705bb0a56ecSDave Jones pr_debug("ramp voltage offset: %d\n", data->rvo); 706bb0a56ecSDave Jones pr_debug("isochronous relief time: %d\n", data->irt); 707bb0a56ecSDave Jones pr_debug("maximum voltage step: %d - 0x%x\n", mvs, data->vidmvs); 708bb0a56ecSDave Jones 709bb0a56ecSDave Jones pr_debug("numpst: 0x%x\n", psb->num_tables); 710bb0a56ecSDave Jones cpst = psb->num_tables; 711bb0a56ecSDave Jones if ((psb->cpuid == 0x00000fc0) || 712bb0a56ecSDave Jones (psb->cpuid == 0x00000fe0)) { 713bb0a56ecSDave Jones thiscpuid = cpuid_eax(CPUID_PROCESSOR_SIGNATURE); 714bb0a56ecSDave Jones if ((thiscpuid == 0x00000fc0) || 715bb0a56ecSDave Jones (thiscpuid == 0x00000fe0)) 716bb0a56ecSDave Jones cpst = 1; 717bb0a56ecSDave Jones } 718bb0a56ecSDave Jones if (cpst != 1) { 719bb0a56ecSDave Jones printk(KERN_ERR FW_BUG PFX "numpst must be 1\n"); 720bb0a56ecSDave Jones return -ENODEV; 721bb0a56ecSDave Jones } 722bb0a56ecSDave Jones 723bb0a56ecSDave Jones data->plllock = psb->plllocktime; 724bb0a56ecSDave Jones pr_debug("plllocktime: 0x%x (units 1us)\n", psb->plllocktime); 725bb0a56ecSDave Jones pr_debug("maxfid: 0x%x\n", psb->maxfid); 726bb0a56ecSDave Jones pr_debug("maxvid: 0x%x\n", psb->maxvid); 727bb0a56ecSDave Jones maxvid = psb->maxvid; 728bb0a56ecSDave Jones 729bb0a56ecSDave Jones data->numps = psb->numps; 730bb0a56ecSDave Jones pr_debug("numpstates: 0x%x\n", data->numps); 731bb0a56ecSDave Jones return fill_powernow_table(data, 732bb0a56ecSDave Jones (struct pst_s *)(psb+1), maxvid); 733bb0a56ecSDave Jones } 734bb0a56ecSDave Jones /* 735bb0a56ecSDave Jones * If you see this message, complain to BIOS manufacturer. If 736bb0a56ecSDave Jones * he tells you "we do not support Linux" or some similar 737bb0a56ecSDave Jones * nonsense, remember that Windows 2000 uses the same legacy 738bb0a56ecSDave Jones * mechanism that the old Linux PSB driver uses. Tell them it 739bb0a56ecSDave Jones * is broken with Windows 2000. 740bb0a56ecSDave Jones * 741bb0a56ecSDave Jones * The reference to the AMD documentation is chapter 9 in the 742bb0a56ecSDave Jones * BIOS and Kernel Developer's Guide, which is available on 743bb0a56ecSDave Jones * www.amd.com 744bb0a56ecSDave Jones */ 745bb0a56ecSDave Jones printk(KERN_ERR FW_BUG PFX "No PSB or ACPI _PSS objects\n"); 746bb0a56ecSDave Jones printk(KERN_ERR PFX "Make sure that your BIOS is up to date" 747bb0a56ecSDave Jones " and Cool'N'Quiet support is enabled in BIOS setup\n"); 748bb0a56ecSDave Jones return -ENODEV; 749bb0a56ecSDave Jones } 750bb0a56ecSDave Jones 751bb0a56ecSDave Jones static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, 752bb0a56ecSDave Jones unsigned int index) 753bb0a56ecSDave Jones { 754bb0a56ecSDave Jones u64 control; 755bb0a56ecSDave Jones 756e1f0b8e9SMatthew Garrett if (!data->acpi_data.state_count) 757bb0a56ecSDave Jones return; 758bb0a56ecSDave Jones 759bb0a56ecSDave Jones control = data->acpi_data.states[index].control; 760bb0a56ecSDave Jones data->irt = (control >> IRT_SHIFT) & IRT_MASK; 761bb0a56ecSDave Jones data->rvo = (control >> RVO_SHIFT) & RVO_MASK; 762bb0a56ecSDave Jones data->exttype = (control >> EXT_TYPE_SHIFT) & EXT_TYPE_MASK; 763bb0a56ecSDave Jones data->plllock = (control >> PLL_L_SHIFT) & PLL_L_MASK; 764bb0a56ecSDave Jones data->vidmvs = 1 << ((control >> MVS_SHIFT) & MVS_MASK); 765bb0a56ecSDave Jones data->vstable = (control >> VST_SHIFT) & VST_MASK; 766bb0a56ecSDave Jones } 767bb0a56ecSDave Jones 768bb0a56ecSDave Jones static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) 769bb0a56ecSDave Jones { 770bb0a56ecSDave Jones struct cpufreq_frequency_table *powernow_table; 771bb0a56ecSDave Jones int ret_val = -ENODEV; 772bb0a56ecSDave Jones u64 control, status; 773bb0a56ecSDave Jones 774bb0a56ecSDave Jones if (acpi_processor_register_performance(&data->acpi_data, data->cpu)) { 775bb0a56ecSDave Jones pr_debug("register performance failed: bad ACPI data\n"); 776bb0a56ecSDave Jones return -EIO; 777bb0a56ecSDave Jones } 778bb0a56ecSDave Jones 779bb0a56ecSDave Jones /* verify the data contained in the ACPI structures */ 780bb0a56ecSDave Jones if (data->acpi_data.state_count <= 1) { 781bb0a56ecSDave Jones pr_debug("No ACPI P-States\n"); 782bb0a56ecSDave Jones goto err_out; 783bb0a56ecSDave Jones } 784bb0a56ecSDave Jones 785bb0a56ecSDave Jones control = data->acpi_data.control_register.space_id; 786bb0a56ecSDave Jones status = data->acpi_data.status_register.space_id; 787bb0a56ecSDave Jones 788bb0a56ecSDave Jones if ((control != ACPI_ADR_SPACE_FIXED_HARDWARE) || 789bb0a56ecSDave Jones (status != ACPI_ADR_SPACE_FIXED_HARDWARE)) { 790bb0a56ecSDave Jones pr_debug("Invalid control/status registers (%llx - %llx)\n", 791bb0a56ecSDave Jones control, status); 792bb0a56ecSDave Jones goto err_out; 793bb0a56ecSDave Jones } 794bb0a56ecSDave Jones 795bb0a56ecSDave Jones /* fill in data->powernow_table */ 796d5b73cd8SViresh Kumar powernow_table = kmalloc((sizeof(*powernow_table) 797bb0a56ecSDave Jones * (data->acpi_data.state_count + 1)), GFP_KERNEL); 798bb0a56ecSDave Jones if (!powernow_table) { 799bb0a56ecSDave Jones pr_debug("powernow_table memory alloc failure\n"); 800bb0a56ecSDave Jones goto err_out; 801bb0a56ecSDave Jones } 802bb0a56ecSDave Jones 803bb0a56ecSDave Jones /* fill in data */ 804bb0a56ecSDave Jones data->numps = data->acpi_data.state_count; 805bb0a56ecSDave Jones powernow_k8_acpi_pst_values(data, 0); 806bb0a56ecSDave Jones 807bb0a56ecSDave Jones ret_val = fill_powernow_table_fidvid(data, powernow_table); 808bb0a56ecSDave Jones if (ret_val) 809bb0a56ecSDave Jones goto err_out_mem; 810bb0a56ecSDave Jones 811bb0a56ecSDave Jones powernow_table[data->acpi_data.state_count].frequency = 812bb0a56ecSDave Jones CPUFREQ_TABLE_END; 81350701588SViresh Kumar powernow_table[data->acpi_data.state_count].driver_data = 0; 814bb0a56ecSDave Jones data->powernow_table = powernow_table; 815bb0a56ecSDave Jones 816bb0a56ecSDave Jones if (cpumask_first(cpu_core_mask(data->cpu)) == data->cpu) 817bb0a56ecSDave Jones print_basics(data); 818bb0a56ecSDave Jones 819bb0a56ecSDave Jones /* notify BIOS that we exist */ 820bb0a56ecSDave Jones acpi_processor_notify_smm(THIS_MODULE); 821bb0a56ecSDave Jones 822bb0a56ecSDave Jones if (!zalloc_cpumask_var(&data->acpi_data.shared_cpu_map, GFP_KERNEL)) { 823bb0a56ecSDave Jones printk(KERN_ERR PFX 824bb0a56ecSDave Jones "unable to alloc powernow_k8_data cpumask\n"); 825bb0a56ecSDave Jones ret_val = -ENOMEM; 826bb0a56ecSDave Jones goto err_out_mem; 827bb0a56ecSDave Jones } 828bb0a56ecSDave Jones 829bb0a56ecSDave Jones return 0; 830bb0a56ecSDave Jones 831bb0a56ecSDave Jones err_out_mem: 832bb0a56ecSDave Jones kfree(powernow_table); 833bb0a56ecSDave Jones 834bb0a56ecSDave Jones err_out: 835bb0a56ecSDave Jones acpi_processor_unregister_performance(&data->acpi_data, data->cpu); 836bb0a56ecSDave Jones 837bb0a56ecSDave Jones /* data->acpi_data.state_count informs us at ->exit() 838bb0a56ecSDave Jones * whether ACPI was used */ 839bb0a56ecSDave Jones data->acpi_data.state_count = 0; 840bb0a56ecSDave Jones 841bb0a56ecSDave Jones return ret_val; 842bb0a56ecSDave Jones } 843bb0a56ecSDave Jones 844bb0a56ecSDave Jones static int fill_powernow_table_fidvid(struct powernow_k8_data *data, 845bb0a56ecSDave Jones struct cpufreq_frequency_table *powernow_table) 846bb0a56ecSDave Jones { 847bb0a56ecSDave Jones int i; 848bb0a56ecSDave Jones 849bb0a56ecSDave Jones for (i = 0; i < data->acpi_data.state_count; i++) { 850bb0a56ecSDave Jones u32 fid; 851bb0a56ecSDave Jones u32 vid; 852bb0a56ecSDave Jones u32 freq, index; 853bb0a56ecSDave Jones u64 status, control; 854bb0a56ecSDave Jones 855bb0a56ecSDave Jones if (data->exttype) { 856bb0a56ecSDave Jones status = data->acpi_data.states[i].status; 857bb0a56ecSDave Jones fid = status & EXT_FID_MASK; 858bb0a56ecSDave Jones vid = (status >> VID_SHIFT) & EXT_VID_MASK; 859bb0a56ecSDave Jones } else { 860bb0a56ecSDave Jones control = data->acpi_data.states[i].control; 861bb0a56ecSDave Jones fid = control & FID_MASK; 862bb0a56ecSDave Jones vid = (control >> VID_SHIFT) & VID_MASK; 863bb0a56ecSDave Jones } 864bb0a56ecSDave Jones 865bb0a56ecSDave Jones pr_debug(" %d : fid 0x%x, vid 0x%x\n", i, fid, vid); 866bb0a56ecSDave Jones 867bb0a56ecSDave Jones index = fid | (vid<<8); 86850701588SViresh Kumar powernow_table[i].driver_data = index; 869bb0a56ecSDave Jones 870bb0a56ecSDave Jones freq = find_khz_freq_from_fid(fid); 871bb0a56ecSDave Jones powernow_table[i].frequency = freq; 872bb0a56ecSDave Jones 873bb0a56ecSDave Jones /* verify frequency is OK */ 874bb0a56ecSDave Jones if ((freq > (MAX_FREQ * 1000)) || (freq < (MIN_FREQ * 1000))) { 875bb0a56ecSDave Jones pr_debug("invalid freq %u kHz, ignoring\n", freq); 876bb0a56ecSDave Jones invalidate_entry(powernow_table, i); 877bb0a56ecSDave Jones continue; 878bb0a56ecSDave Jones } 879bb0a56ecSDave Jones 880bb0a56ecSDave Jones /* verify voltage is OK - 881bb0a56ecSDave Jones * BIOSs are using "off" to indicate invalid */ 882bb0a56ecSDave Jones if (vid == VID_OFF) { 883bb0a56ecSDave Jones pr_debug("invalid vid %u, ignoring\n", vid); 884bb0a56ecSDave Jones invalidate_entry(powernow_table, i); 885bb0a56ecSDave Jones continue; 886bb0a56ecSDave Jones } 887bb0a56ecSDave Jones 888bb0a56ecSDave Jones if (freq != (data->acpi_data.states[i].core_frequency * 1000)) { 889bb0a56ecSDave Jones printk(KERN_INFO PFX "invalid freq entries " 890bb0a56ecSDave Jones "%u kHz vs. %u kHz\n", freq, 891bb0a56ecSDave Jones (unsigned int) 892bb0a56ecSDave Jones (data->acpi_data.states[i].core_frequency 893bb0a56ecSDave Jones * 1000)); 894bb0a56ecSDave Jones invalidate_entry(powernow_table, i); 895bb0a56ecSDave Jones continue; 896bb0a56ecSDave Jones } 897bb0a56ecSDave Jones } 898bb0a56ecSDave Jones return 0; 899bb0a56ecSDave Jones } 900bb0a56ecSDave Jones 901bb0a56ecSDave Jones static void powernow_k8_cpu_exit_acpi(struct powernow_k8_data *data) 902bb0a56ecSDave Jones { 903bb0a56ecSDave Jones if (data->acpi_data.state_count) 904bb0a56ecSDave Jones acpi_processor_unregister_performance(&data->acpi_data, 905bb0a56ecSDave Jones data->cpu); 906bb0a56ecSDave Jones free_cpumask_var(data->acpi_data.shared_cpu_map); 907bb0a56ecSDave Jones } 908bb0a56ecSDave Jones 909bb0a56ecSDave Jones static int get_transition_latency(struct powernow_k8_data *data) 910bb0a56ecSDave Jones { 911bb0a56ecSDave Jones int max_latency = 0; 912bb0a56ecSDave Jones int i; 913bb0a56ecSDave Jones for (i = 0; i < data->acpi_data.state_count; i++) { 914bb0a56ecSDave Jones int cur_latency = data->acpi_data.states[i].transition_latency 915bb0a56ecSDave Jones + data->acpi_data.states[i].bus_master_latency; 916bb0a56ecSDave Jones if (cur_latency > max_latency) 917bb0a56ecSDave Jones max_latency = cur_latency; 918bb0a56ecSDave Jones } 919bb0a56ecSDave Jones if (max_latency == 0) { 920e1f0b8e9SMatthew Garrett pr_err(FW_WARN PFX "Invalid zero transition latency\n"); 921bb0a56ecSDave Jones max_latency = 1; 922bb0a56ecSDave Jones } 923bb0a56ecSDave Jones /* value in usecs, needs to be in nanoseconds */ 924bb0a56ecSDave Jones return 1000 * max_latency; 925bb0a56ecSDave Jones } 926bb0a56ecSDave Jones 927bb0a56ecSDave Jones /* Take a frequency, and issue the fid/vid transition command */ 928bb0a56ecSDave Jones static int transition_frequency_fidvid(struct powernow_k8_data *data, 929bb0a56ecSDave Jones unsigned int index) 930bb0a56ecSDave Jones { 931b43a7ffbSViresh Kumar struct cpufreq_policy *policy; 932bb0a56ecSDave Jones u32 fid = 0; 933bb0a56ecSDave Jones u32 vid = 0; 934b43a7ffbSViresh Kumar int res; 935bb0a56ecSDave Jones struct cpufreq_freqs freqs; 936bb0a56ecSDave Jones 937bb0a56ecSDave Jones pr_debug("cpu %d transition to index %u\n", smp_processor_id(), index); 938bb0a56ecSDave Jones 939bb0a56ecSDave Jones /* fid/vid correctness check for k8 */ 940bb0a56ecSDave Jones /* fid are the lower 8 bits of the index we stored into 941bb0a56ecSDave Jones * the cpufreq frequency table in find_psb_table, vid 942bb0a56ecSDave Jones * are the upper 8 bits. 943bb0a56ecSDave Jones */ 94450701588SViresh Kumar fid = data->powernow_table[index].driver_data & 0xFF; 94550701588SViresh Kumar vid = (data->powernow_table[index].driver_data & 0xFF00) >> 8; 946bb0a56ecSDave Jones 947bb0a56ecSDave Jones pr_debug("table matched fid 0x%x, giving vid 0x%x\n", fid, vid); 948bb0a56ecSDave Jones 949bb0a56ecSDave Jones if (query_current_values_with_pending_wait(data)) 950bb0a56ecSDave Jones return 1; 951bb0a56ecSDave Jones 952bb0a56ecSDave Jones if ((data->currvid == vid) && (data->currfid == fid)) { 953bb0a56ecSDave Jones pr_debug("target matches current values (fid 0x%x, vid 0x%x)\n", 954bb0a56ecSDave Jones fid, vid); 955bb0a56ecSDave Jones return 0; 956bb0a56ecSDave Jones } 957bb0a56ecSDave Jones 958bb0a56ecSDave Jones pr_debug("cpu %d, changing to fid 0x%x, vid 0x%x\n", 959bb0a56ecSDave Jones smp_processor_id(), fid, vid); 960bb0a56ecSDave Jones freqs.old = find_khz_freq_from_fid(data->currfid); 961bb0a56ecSDave Jones freqs.new = find_khz_freq_from_fid(fid); 962bb0a56ecSDave Jones 963b43a7ffbSViresh Kumar policy = cpufreq_cpu_get(smp_processor_id()); 964b43a7ffbSViresh Kumar cpufreq_cpu_put(policy); 965b43a7ffbSViresh Kumar 966b43a7ffbSViresh Kumar cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); 967bb0a56ecSDave Jones 968bb0a56ecSDave Jones res = transition_fid_vid(data, fid, vid); 969a9d3d206SKonrad Rzeszutek Wilk if (res) 9707f77a563SViresh Kumar freqs.new = freqs.old; 9717f77a563SViresh Kumar else 972bb0a56ecSDave Jones freqs.new = find_khz_freq_from_fid(data->currfid); 973bb0a56ecSDave Jones 974b43a7ffbSViresh Kumar cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); 975bb0a56ecSDave Jones return res; 976bb0a56ecSDave Jones } 977bb0a56ecSDave Jones 9786889125bSTejun Heo struct powernowk8_target_arg { 9796889125bSTejun Heo struct cpufreq_policy *pol; 9806889125bSTejun Heo unsigned targfreq; 9816889125bSTejun Heo unsigned relation; 9826889125bSTejun Heo }; 9836889125bSTejun Heo 9846889125bSTejun Heo static long powernowk8_target_fn(void *arg) 985bb0a56ecSDave Jones { 9866889125bSTejun Heo struct powernowk8_target_arg *pta = arg; 9876889125bSTejun Heo struct cpufreq_policy *pol = pta->pol; 9886889125bSTejun Heo unsigned targfreq = pta->targfreq; 9896889125bSTejun Heo unsigned relation = pta->relation; 990bb0a56ecSDave Jones struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu); 991bb0a56ecSDave Jones u32 checkfid; 992bb0a56ecSDave Jones u32 checkvid; 993bb0a56ecSDave Jones unsigned int newstate; 9946889125bSTejun Heo int ret; 995bb0a56ecSDave Jones 996bb0a56ecSDave Jones if (!data) 997bb0a56ecSDave Jones return -EINVAL; 998bb0a56ecSDave Jones 999bb0a56ecSDave Jones checkfid = data->currfid; 1000bb0a56ecSDave Jones checkvid = data->currvid; 1001bb0a56ecSDave Jones 1002bb0a56ecSDave Jones if (pending_bit_stuck()) { 1003bb0a56ecSDave Jones printk(KERN_ERR PFX "failing targ, change pending bit set\n"); 10046889125bSTejun Heo return -EIO; 1005bb0a56ecSDave Jones } 1006bb0a56ecSDave Jones 1007bb0a56ecSDave Jones pr_debug("targ: cpu %d, %d kHz, min %d, max %d, relation %d\n", 1008bb0a56ecSDave Jones pol->cpu, targfreq, pol->min, pol->max, relation); 1009bb0a56ecSDave Jones 1010bb0a56ecSDave Jones if (query_current_values_with_pending_wait(data)) 10116889125bSTejun Heo return -EIO; 1012bb0a56ecSDave Jones 1013bb0a56ecSDave Jones pr_debug("targ: curr fid 0x%x, vid 0x%x\n", 1014bb0a56ecSDave Jones data->currfid, data->currvid); 1015bb0a56ecSDave Jones 1016bb0a56ecSDave Jones if ((checkvid != data->currvid) || 1017bb0a56ecSDave Jones (checkfid != data->currfid)) { 1018e1f0b8e9SMatthew Garrett pr_info(PFX 1019e1f0b8e9SMatthew Garrett "error - out of sync, fix 0x%x 0x%x, vid 0x%x 0x%x\n", 1020bb0a56ecSDave Jones checkfid, data->currfid, 1021bb0a56ecSDave Jones checkvid, data->currvid); 1022bb0a56ecSDave Jones } 1023bb0a56ecSDave Jones 1024bb0a56ecSDave Jones if (cpufreq_frequency_table_target(pol, data->powernow_table, 1025bb0a56ecSDave Jones targfreq, relation, &newstate)) 10266889125bSTejun Heo return -EIO; 1027bb0a56ecSDave Jones 1028bb0a56ecSDave Jones mutex_lock(&fidvid_mutex); 1029bb0a56ecSDave Jones 1030bb0a56ecSDave Jones powernow_k8_acpi_pst_values(data, newstate); 1031bb0a56ecSDave Jones 1032bb0a56ecSDave Jones ret = transition_frequency_fidvid(data, newstate); 1033e1f0b8e9SMatthew Garrett 1034bb0a56ecSDave Jones if (ret) { 1035bb0a56ecSDave Jones printk(KERN_ERR PFX "transition frequency failed\n"); 1036bb0a56ecSDave Jones mutex_unlock(&fidvid_mutex); 10376889125bSTejun Heo return 1; 1038bb0a56ecSDave Jones } 1039bb0a56ecSDave Jones mutex_unlock(&fidvid_mutex); 1040bb0a56ecSDave Jones 1041bb0a56ecSDave Jones pol->cur = find_khz_freq_from_fid(data->currfid); 1042bb0a56ecSDave Jones 10436889125bSTejun Heo return 0; 10446889125bSTejun Heo } 10456889125bSTejun Heo 10466889125bSTejun Heo /* Driver entry point to switch to the target frequency */ 10476889125bSTejun Heo static int powernowk8_target(struct cpufreq_policy *pol, 10486889125bSTejun Heo unsigned targfreq, unsigned relation) 10496889125bSTejun Heo { 10506889125bSTejun Heo struct powernowk8_target_arg pta = { .pol = pol, .targfreq = targfreq, 10516889125bSTejun Heo .relation = relation }; 10526889125bSTejun Heo 10536889125bSTejun Heo return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta); 1054bb0a56ecSDave Jones } 1055bb0a56ecSDave Jones 1056bb0a56ecSDave Jones struct init_on_cpu { 1057bb0a56ecSDave Jones struct powernow_k8_data *data; 1058bb0a56ecSDave Jones int rc; 1059bb0a56ecSDave Jones }; 1060bb0a56ecSDave Jones 10612760984fSPaul Gortmaker static void powernowk8_cpu_init_on_cpu(void *_init_on_cpu) 1062bb0a56ecSDave Jones { 1063bb0a56ecSDave Jones struct init_on_cpu *init_on_cpu = _init_on_cpu; 1064bb0a56ecSDave Jones 1065bb0a56ecSDave Jones if (pending_bit_stuck()) { 1066bb0a56ecSDave Jones printk(KERN_ERR PFX "failing init, change pending bit set\n"); 1067bb0a56ecSDave Jones init_on_cpu->rc = -ENODEV; 1068bb0a56ecSDave Jones return; 1069bb0a56ecSDave Jones } 1070bb0a56ecSDave Jones 1071bb0a56ecSDave Jones if (query_current_values_with_pending_wait(init_on_cpu->data)) { 1072bb0a56ecSDave Jones init_on_cpu->rc = -ENODEV; 1073bb0a56ecSDave Jones return; 1074bb0a56ecSDave Jones } 1075bb0a56ecSDave Jones 1076bb0a56ecSDave Jones fidvid_msr_init(); 1077bb0a56ecSDave Jones 1078bb0a56ecSDave Jones init_on_cpu->rc = 0; 1079bb0a56ecSDave Jones } 1080bb0a56ecSDave Jones 108156835e6cSBorislav Petkov static const char missing_pss_msg[] = 108256835e6cSBorislav Petkov KERN_ERR 108356835e6cSBorislav Petkov FW_BUG PFX "No compatible ACPI _PSS objects found.\n" 108456835e6cSBorislav Petkov FW_BUG PFX "First, make sure Cool'N'Quiet is enabled in the BIOS.\n" 108556835e6cSBorislav Petkov FW_BUG PFX "If that doesn't help, try upgrading your BIOS.\n"; 108656835e6cSBorislav Petkov 1087bb0a56ecSDave Jones /* per CPU init entry point to the driver */ 10882760984fSPaul Gortmaker static int powernowk8_cpu_init(struct cpufreq_policy *pol) 1089bb0a56ecSDave Jones { 1090bb0a56ecSDave Jones struct powernow_k8_data *data; 1091bb0a56ecSDave Jones struct init_on_cpu init_on_cpu; 1092bb0a56ecSDave Jones int rc; 1093bb0a56ecSDave Jones 1094bb0a56ecSDave Jones smp_call_function_single(pol->cpu, check_supported_cpu, &rc, 1); 1095bb0a56ecSDave Jones if (rc) 1096bb0a56ecSDave Jones return -ENODEV; 1097bb0a56ecSDave Jones 1098d5b73cd8SViresh Kumar data = kzalloc(sizeof(*data), GFP_KERNEL); 1099bb0a56ecSDave Jones if (!data) { 1100bb0a56ecSDave Jones printk(KERN_ERR PFX "unable to alloc powernow_k8_data"); 1101bb0a56ecSDave Jones return -ENOMEM; 1102bb0a56ecSDave Jones } 1103bb0a56ecSDave Jones 1104bb0a56ecSDave Jones data->cpu = pol->cpu; 1105bb0a56ecSDave Jones 1106bb0a56ecSDave Jones if (powernow_k8_cpu_init_acpi(data)) { 1107bb0a56ecSDave Jones /* 1108bb0a56ecSDave Jones * Use the PSB BIOS structure. This is only available on 1109bb0a56ecSDave Jones * an UP version, and is deprecated by AMD. 1110bb0a56ecSDave Jones */ 1111bb0a56ecSDave Jones if (num_online_cpus() != 1) { 111256835e6cSBorislav Petkov printk_once(missing_pss_msg); 1113bb0a56ecSDave Jones goto err_out; 1114bb0a56ecSDave Jones } 1115bb0a56ecSDave Jones if (pol->cpu != 0) { 1116bb0a56ecSDave Jones printk(KERN_ERR FW_BUG PFX "No ACPI _PSS objects for " 1117bb0a56ecSDave Jones "CPU other than CPU0. Complain to your BIOS " 1118bb0a56ecSDave Jones "vendor.\n"); 1119bb0a56ecSDave Jones goto err_out; 1120bb0a56ecSDave Jones } 1121bb0a56ecSDave Jones rc = find_psb_table(data); 1122bb0a56ecSDave Jones if (rc) 1123bb0a56ecSDave Jones goto err_out; 1124bb0a56ecSDave Jones 1125bb0a56ecSDave Jones /* Take a crude guess here. 1126bb0a56ecSDave Jones * That guess was in microseconds, so multiply with 1000 */ 1127bb0a56ecSDave Jones pol->cpuinfo.transition_latency = ( 1128bb0a56ecSDave Jones ((data->rvo + 8) * data->vstable * VST_UNITS_20US) + 1129bb0a56ecSDave Jones ((1 << data->irt) * 30)) * 1000; 1130bb0a56ecSDave Jones } else /* ACPI _PSS objects available */ 1131bb0a56ecSDave Jones pol->cpuinfo.transition_latency = get_transition_latency(data); 1132bb0a56ecSDave Jones 1133bb0a56ecSDave Jones /* only run on specific CPU from here on */ 1134bb0a56ecSDave Jones init_on_cpu.data = data; 1135bb0a56ecSDave Jones smp_call_function_single(data->cpu, powernowk8_cpu_init_on_cpu, 1136bb0a56ecSDave Jones &init_on_cpu, 1); 1137bb0a56ecSDave Jones rc = init_on_cpu.rc; 1138bb0a56ecSDave Jones if (rc != 0) 1139bb0a56ecSDave Jones goto err_out_exit_acpi; 1140bb0a56ecSDave Jones 1141bb0a56ecSDave Jones cpumask_copy(pol->cpus, cpu_core_mask(pol->cpu)); 1142bb0a56ecSDave Jones data->available_cores = pol->cpus; 1143bb0a56ecSDave Jones 1144bb0a56ecSDave Jones pol->cur = find_khz_freq_from_fid(data->currfid); 1145bb0a56ecSDave Jones pr_debug("policy current frequency %d kHz\n", pol->cur); 1146bb0a56ecSDave Jones 1147bb0a56ecSDave Jones /* min/max the cpu is capable of */ 1148b147405aSViresh Kumar if (cpufreq_table_validate_and_show(pol, data->powernow_table)) { 1149bb0a56ecSDave Jones printk(KERN_ERR FW_BUG PFX "invalid powernow_table\n"); 1150bb0a56ecSDave Jones powernow_k8_cpu_exit_acpi(data); 1151bb0a56ecSDave Jones kfree(data->powernow_table); 1152bb0a56ecSDave Jones kfree(data); 1153bb0a56ecSDave Jones return -EINVAL; 1154bb0a56ecSDave Jones } 1155bb0a56ecSDave Jones 1156bb0a56ecSDave Jones pr_debug("cpu_init done, current fid 0x%x, vid 0x%x\n", 1157bb0a56ecSDave Jones data->currfid, data->currvid); 1158bb0a56ecSDave Jones 1159bb0a56ecSDave Jones per_cpu(powernow_data, pol->cpu) = data; 1160bb0a56ecSDave Jones 1161bb0a56ecSDave Jones return 0; 1162bb0a56ecSDave Jones 1163bb0a56ecSDave Jones err_out_exit_acpi: 1164bb0a56ecSDave Jones powernow_k8_cpu_exit_acpi(data); 1165bb0a56ecSDave Jones 1166bb0a56ecSDave Jones err_out: 1167bb0a56ecSDave Jones kfree(data); 1168bb0a56ecSDave Jones return -ENODEV; 1169bb0a56ecSDave Jones } 1170bb0a56ecSDave Jones 1171c0e61cb1SBill Pemberton static int powernowk8_cpu_exit(struct cpufreq_policy *pol) 1172bb0a56ecSDave Jones { 1173bb0a56ecSDave Jones struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu); 1174bb0a56ecSDave Jones 1175bb0a56ecSDave Jones if (!data) 1176bb0a56ecSDave Jones return -EINVAL; 1177bb0a56ecSDave Jones 1178bb0a56ecSDave Jones powernow_k8_cpu_exit_acpi(data); 1179bb0a56ecSDave Jones 1180bb0a56ecSDave Jones cpufreq_frequency_table_put_attr(pol->cpu); 1181bb0a56ecSDave Jones 1182bb0a56ecSDave Jones kfree(data->powernow_table); 1183bb0a56ecSDave Jones kfree(data); 1184bb0a56ecSDave Jones per_cpu(powernow_data, pol->cpu) = NULL; 1185bb0a56ecSDave Jones 1186bb0a56ecSDave Jones return 0; 1187bb0a56ecSDave Jones } 1188bb0a56ecSDave Jones 1189bb0a56ecSDave Jones static void query_values_on_cpu(void *_err) 1190bb0a56ecSDave Jones { 1191bb0a56ecSDave Jones int *err = _err; 1192bb0a56ecSDave Jones struct powernow_k8_data *data = __this_cpu_read(powernow_data); 1193bb0a56ecSDave Jones 1194bb0a56ecSDave Jones *err = query_current_values_with_pending_wait(data); 1195bb0a56ecSDave Jones } 1196bb0a56ecSDave Jones 1197bb0a56ecSDave Jones static unsigned int powernowk8_get(unsigned int cpu) 1198bb0a56ecSDave Jones { 1199bb0a56ecSDave Jones struct powernow_k8_data *data = per_cpu(powernow_data, cpu); 1200bb0a56ecSDave Jones unsigned int khz = 0; 1201bb0a56ecSDave Jones int err; 1202bb0a56ecSDave Jones 1203bb0a56ecSDave Jones if (!data) 1204bb0a56ecSDave Jones return 0; 1205bb0a56ecSDave Jones 1206bb0a56ecSDave Jones smp_call_function_single(cpu, query_values_on_cpu, &err, true); 1207bb0a56ecSDave Jones if (err) 1208bb0a56ecSDave Jones goto out; 1209bb0a56ecSDave Jones 1210bb0a56ecSDave Jones khz = find_khz_freq_from_fid(data->currfid); 1211bb0a56ecSDave Jones 1212bb0a56ecSDave Jones 1213bb0a56ecSDave Jones out: 1214bb0a56ecSDave Jones return khz; 1215bb0a56ecSDave Jones } 1216bb0a56ecSDave Jones 1217bb0a56ecSDave Jones static struct cpufreq_driver cpufreq_amd64_driver = { 1218*d63bd27fSViresh Kumar .verify = cpufreq_generic_frequency_table_verify, 1219bb0a56ecSDave Jones .target = powernowk8_target, 1220bb0a56ecSDave Jones .bios_limit = acpi_processor_get_bios_limit, 1221bb0a56ecSDave Jones .init = powernowk8_cpu_init, 1222ce2650d4SBill Pemberton .exit = powernowk8_cpu_exit, 1223bb0a56ecSDave Jones .get = powernowk8_get, 1224bb0a56ecSDave Jones .name = "powernow-k8", 1225*d63bd27fSViresh Kumar .attr = cpufreq_generic_attr, 1226bb0a56ecSDave Jones }; 1227bb0a56ecSDave Jones 12284827ea6eSBorislav Petkov static void __request_acpi_cpufreq(void) 12294827ea6eSBorislav Petkov { 12304827ea6eSBorislav Petkov const char *cur_drv, *drv = "acpi-cpufreq"; 12314827ea6eSBorislav Petkov 12324827ea6eSBorislav Petkov cur_drv = cpufreq_get_current_driver(); 12334827ea6eSBorislav Petkov if (!cur_drv) 12344827ea6eSBorislav Petkov goto request; 12354827ea6eSBorislav Petkov 12364827ea6eSBorislav Petkov if (strncmp(cur_drv, drv, min_t(size_t, strlen(cur_drv), strlen(drv)))) 12374827ea6eSBorislav Petkov pr_warn(PFX "WTF driver: %s\n", cur_drv); 12384827ea6eSBorislav Petkov 12394827ea6eSBorislav Petkov return; 12404827ea6eSBorislav Petkov 12414827ea6eSBorislav Petkov request: 12424827ea6eSBorislav Petkov pr_warn(PFX "This CPU is not supported anymore, using acpi-cpufreq instead.\n"); 12434827ea6eSBorislav Petkov request_module(drv); 12444827ea6eSBorislav Petkov } 12454827ea6eSBorislav Petkov 1246bb0a56ecSDave Jones /* driver entry point for init */ 12472760984fSPaul Gortmaker static int powernowk8_init(void) 1248bb0a56ecSDave Jones { 1249e1f0b8e9SMatthew Garrett unsigned int i, supported_cpus = 0; 1250c0939e46SBorislav Petkov int ret; 1251bb0a56ecSDave Jones 1252e1f0b8e9SMatthew Garrett if (static_cpu_has(X86_FEATURE_HW_PSTATE)) { 12534827ea6eSBorislav Petkov __request_acpi_cpufreq(); 1254e1f0b8e9SMatthew Garrett return -ENODEV; 1255e1f0b8e9SMatthew Garrett } 1256e1f0b8e9SMatthew Garrett 1257fa8031aeSAndi Kleen if (!x86_match_cpu(powernow_k8_ids)) 1258fa8031aeSAndi Kleen return -ENODEV; 1259fa8031aeSAndi Kleen 1260c0939e46SBorislav Petkov get_online_cpus(); 1261bb0a56ecSDave Jones for_each_online_cpu(i) { 1262c0939e46SBorislav Petkov smp_call_function_single(i, check_supported_cpu, &ret, 1); 1263c0939e46SBorislav Petkov if (!ret) 1264bb0a56ecSDave Jones supported_cpus++; 1265bb0a56ecSDave Jones } 1266bb0a56ecSDave Jones 1267c0939e46SBorislav Petkov if (supported_cpus != num_online_cpus()) { 1268c0939e46SBorislav Petkov put_online_cpus(); 1269bb0a56ecSDave Jones return -ENODEV; 1270c0939e46SBorislav Petkov } 1271c0939e46SBorislav Petkov put_online_cpus(); 1272bb0a56ecSDave Jones 1273c0939e46SBorislav Petkov ret = cpufreq_register_driver(&cpufreq_amd64_driver); 1274c0939e46SBorislav Petkov if (ret) 1275c0939e46SBorislav Petkov return ret; 1276a2060958SAndre Przywara 1277a2060958SAndre Przywara pr_info(PFX "Found %d %s (%d cpu cores) (" VERSION ")\n", 1278c0939e46SBorislav Petkov num_online_nodes(), boot_cpu_data.x86_model_id, supported_cpus); 1279a2060958SAndre Przywara 1280c0939e46SBorislav Petkov return ret; 1281bb0a56ecSDave Jones } 1282bb0a56ecSDave Jones 1283bb0a56ecSDave Jones /* driver entry point for term */ 1284bb0a56ecSDave Jones static void __exit powernowk8_exit(void) 1285bb0a56ecSDave Jones { 1286bb0a56ecSDave Jones pr_debug("exit\n"); 1287bb0a56ecSDave Jones 1288bb0a56ecSDave Jones cpufreq_unregister_driver(&cpufreq_amd64_driver); 1289bb0a56ecSDave Jones } 1290bb0a56ecSDave Jones 1291bb0a56ecSDave Jones MODULE_AUTHOR("Paul Devriendt <paul.devriendt@amd.com> and " 1292bb0a56ecSDave Jones "Mark Langsdorf <mark.langsdorf@amd.com>"); 1293bb0a56ecSDave Jones MODULE_DESCRIPTION("AMD Athlon 64 and Opteron processor frequency driver."); 1294bb0a56ecSDave Jones MODULE_LICENSE("GPL"); 1295bb0a56ecSDave Jones 1296bb0a56ecSDave Jones late_initcall(powernowk8_init); 1297bb0a56ecSDave Jones module_exit(powernowk8_exit); 1298