1bb0a56ecSDave Jones /* 2bb0a56ecSDave Jones * (C) 2002 - 2003 Dominik Brodowski <linux@brodo.de> 3bb0a56ecSDave Jones * 4bb0a56ecSDave Jones * Licensed under the terms of the GNU GPL License version 2. 5bb0a56ecSDave Jones * 6bb0a56ecSDave Jones * Library for common functions for Intel SpeedStep v.1 and v.2 support 7bb0a56ecSDave Jones * 8bb0a56ecSDave Jones * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous* 9bb0a56ecSDave Jones */ 10bb0a56ecSDave Jones 111c5864e2SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 121c5864e2SJoe Perches 13bb0a56ecSDave Jones #include <linux/kernel.h> 14bb0a56ecSDave Jones #include <linux/module.h> 15bb0a56ecSDave Jones #include <linux/moduleparam.h> 16bb0a56ecSDave Jones #include <linux/init.h> 17bb0a56ecSDave Jones #include <linux/cpufreq.h> 18bb0a56ecSDave Jones 19bb0a56ecSDave Jones #include <asm/msr.h> 20bb0a56ecSDave Jones #include <asm/tsc.h> 21bb0a56ecSDave Jones #include "speedstep-lib.h" 22bb0a56ecSDave Jones 23bb0a56ecSDave Jones #define PFX "speedstep-lib: " 24bb0a56ecSDave Jones 25bb0a56ecSDave Jones #ifdef CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK 26bb0a56ecSDave Jones static int relaxed_check; 27bb0a56ecSDave Jones #else 28bb0a56ecSDave Jones #define relaxed_check 0 29bb0a56ecSDave Jones #endif 30bb0a56ecSDave Jones 31bb0a56ecSDave Jones /********************************************************************* 32bb0a56ecSDave Jones * GET PROCESSOR CORE SPEED IN KHZ * 33bb0a56ecSDave Jones *********************************************************************/ 34bb0a56ecSDave Jones 35bb0a56ecSDave Jones static unsigned int pentium3_get_frequency(enum speedstep_processor processor) 36bb0a56ecSDave Jones { 37bb0a56ecSDave Jones /* See table 14 of p3_ds.pdf and table 22 of 29834003.pdf */ 38843791bbSColin Ian King static const struct { 39bb0a56ecSDave Jones unsigned int ratio; /* Frequency Multiplier (x10) */ 40bb0a56ecSDave Jones u8 bitmap; /* power on configuration bits 41bb0a56ecSDave Jones [27, 25:22] (in MSR 0x2a) */ 42bb0a56ecSDave Jones } msr_decode_mult[] = { 43bb0a56ecSDave Jones { 30, 0x01 }, 44bb0a56ecSDave Jones { 35, 0x05 }, 45bb0a56ecSDave Jones { 40, 0x02 }, 46bb0a56ecSDave Jones { 45, 0x06 }, 47bb0a56ecSDave Jones { 50, 0x00 }, 48bb0a56ecSDave Jones { 55, 0x04 }, 49bb0a56ecSDave Jones { 60, 0x0b }, 50bb0a56ecSDave Jones { 65, 0x0f }, 51bb0a56ecSDave Jones { 70, 0x09 }, 52bb0a56ecSDave Jones { 75, 0x0d }, 53bb0a56ecSDave Jones { 80, 0x0a }, 54bb0a56ecSDave Jones { 85, 0x26 }, 55bb0a56ecSDave Jones { 90, 0x20 }, 56bb0a56ecSDave Jones { 100, 0x2b }, 57bb0a56ecSDave Jones { 0, 0xff } /* error or unknown value */ 58bb0a56ecSDave Jones }; 59bb0a56ecSDave Jones 60bb0a56ecSDave Jones /* PIII(-M) FSB settings: see table b1-b of 24547206.pdf */ 61843791bbSColin Ian King static const struct { 62bb0a56ecSDave Jones unsigned int value; /* Front Side Bus speed in MHz */ 63bb0a56ecSDave Jones u8 bitmap; /* power on configuration bits [18: 19] 64bb0a56ecSDave Jones (in MSR 0x2a) */ 65bb0a56ecSDave Jones } msr_decode_fsb[] = { 66bb0a56ecSDave Jones { 66, 0x0 }, 67bb0a56ecSDave Jones { 100, 0x2 }, 68bb0a56ecSDave Jones { 133, 0x1 }, 69bb0a56ecSDave Jones { 0, 0xff} 70bb0a56ecSDave Jones }; 71bb0a56ecSDave Jones 72bb0a56ecSDave Jones u32 msr_lo, msr_tmp; 73bb0a56ecSDave Jones int i = 0, j = 0; 74bb0a56ecSDave Jones 75bb0a56ecSDave Jones /* read MSR 0x2a - we only need the low 32 bits */ 76bb0a56ecSDave Jones rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_tmp); 77bb0a56ecSDave Jones pr_debug("P3 - MSR_IA32_EBL_CR_POWERON: 0x%x 0x%x\n", msr_lo, msr_tmp); 78bb0a56ecSDave Jones msr_tmp = msr_lo; 79bb0a56ecSDave Jones 80bb0a56ecSDave Jones /* decode the FSB */ 81bb0a56ecSDave Jones msr_tmp &= 0x00c0000; 82bb0a56ecSDave Jones msr_tmp >>= 18; 83bb0a56ecSDave Jones while (msr_tmp != msr_decode_fsb[i].bitmap) { 84bb0a56ecSDave Jones if (msr_decode_fsb[i].bitmap == 0xff) 85bb0a56ecSDave Jones return 0; 86bb0a56ecSDave Jones i++; 87bb0a56ecSDave Jones } 88bb0a56ecSDave Jones 89bb0a56ecSDave Jones /* decode the multiplier */ 90bb0a56ecSDave Jones if (processor == SPEEDSTEP_CPU_PIII_C_EARLY) { 91bb0a56ecSDave Jones pr_debug("workaround for early PIIIs\n"); 92bb0a56ecSDave Jones msr_lo &= 0x03c00000; 93bb0a56ecSDave Jones } else 94bb0a56ecSDave Jones msr_lo &= 0x0bc00000; 95bb0a56ecSDave Jones msr_lo >>= 22; 96bb0a56ecSDave Jones while (msr_lo != msr_decode_mult[j].bitmap) { 97bb0a56ecSDave Jones if (msr_decode_mult[j].bitmap == 0xff) 98bb0a56ecSDave Jones return 0; 99bb0a56ecSDave Jones j++; 100bb0a56ecSDave Jones } 101bb0a56ecSDave Jones 102bb0a56ecSDave Jones pr_debug("speed is %u\n", 103bb0a56ecSDave Jones (msr_decode_mult[j].ratio * msr_decode_fsb[i].value * 100)); 104bb0a56ecSDave Jones 105bb0a56ecSDave Jones return msr_decode_mult[j].ratio * msr_decode_fsb[i].value * 100; 106bb0a56ecSDave Jones } 107bb0a56ecSDave Jones 108bb0a56ecSDave Jones 109bb0a56ecSDave Jones static unsigned int pentiumM_get_frequency(void) 110bb0a56ecSDave Jones { 111bb0a56ecSDave Jones u32 msr_lo, msr_tmp; 112bb0a56ecSDave Jones 113bb0a56ecSDave Jones rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_tmp); 114bb0a56ecSDave Jones pr_debug("PM - MSR_IA32_EBL_CR_POWERON: 0x%x 0x%x\n", msr_lo, msr_tmp); 115bb0a56ecSDave Jones 116bb0a56ecSDave Jones /* see table B-2 of 24547212.pdf */ 117bb0a56ecSDave Jones if (msr_lo & 0x00040000) { 118bb0a56ecSDave Jones printk(KERN_DEBUG PFX "PM - invalid FSB: 0x%x 0x%x\n", 119bb0a56ecSDave Jones msr_lo, msr_tmp); 120bb0a56ecSDave Jones return 0; 121bb0a56ecSDave Jones } 122bb0a56ecSDave Jones 123bb0a56ecSDave Jones msr_tmp = (msr_lo >> 22) & 0x1f; 124bb0a56ecSDave Jones pr_debug("bits 22-26 are 0x%x, speed is %u\n", 125bb0a56ecSDave Jones msr_tmp, (msr_tmp * 100 * 1000)); 126bb0a56ecSDave Jones 127bb0a56ecSDave Jones return msr_tmp * 100 * 1000; 128bb0a56ecSDave Jones } 129bb0a56ecSDave Jones 130bb0a56ecSDave Jones static unsigned int pentium_core_get_frequency(void) 131bb0a56ecSDave Jones { 132bb0a56ecSDave Jones u32 fsb = 0; 133bb0a56ecSDave Jones u32 msr_lo, msr_tmp; 134bb0a56ecSDave Jones int ret; 135bb0a56ecSDave Jones 136bb0a56ecSDave Jones rdmsr(MSR_FSB_FREQ, msr_lo, msr_tmp); 137bb0a56ecSDave Jones /* see table B-2 of 25366920.pdf */ 138bb0a56ecSDave Jones switch (msr_lo & 0x07) { 139bb0a56ecSDave Jones case 5: 140bb0a56ecSDave Jones fsb = 100000; 141bb0a56ecSDave Jones break; 142bb0a56ecSDave Jones case 1: 143bb0a56ecSDave Jones fsb = 133333; 144bb0a56ecSDave Jones break; 145bb0a56ecSDave Jones case 3: 146bb0a56ecSDave Jones fsb = 166667; 147bb0a56ecSDave Jones break; 148bb0a56ecSDave Jones case 2: 149bb0a56ecSDave Jones fsb = 200000; 150bb0a56ecSDave Jones break; 151bb0a56ecSDave Jones case 0: 152bb0a56ecSDave Jones fsb = 266667; 153bb0a56ecSDave Jones break; 154bb0a56ecSDave Jones case 4: 155bb0a56ecSDave Jones fsb = 333333; 156bb0a56ecSDave Jones break; 157bb0a56ecSDave Jones default: 158b49c22a6SJoe Perches pr_err("PCORE - MSR_FSB_FREQ undefined value\n"); 159bb0a56ecSDave Jones } 160bb0a56ecSDave Jones 161bb0a56ecSDave Jones rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_tmp); 162bb0a56ecSDave Jones pr_debug("PCORE - MSR_IA32_EBL_CR_POWERON: 0x%x 0x%x\n", 163bb0a56ecSDave Jones msr_lo, msr_tmp); 164bb0a56ecSDave Jones 165bb0a56ecSDave Jones msr_tmp = (msr_lo >> 22) & 0x1f; 166bb0a56ecSDave Jones pr_debug("bits 22-26 are 0x%x, speed is %u\n", 167bb0a56ecSDave Jones msr_tmp, (msr_tmp * fsb)); 168bb0a56ecSDave Jones 169bb0a56ecSDave Jones ret = (msr_tmp * fsb); 170bb0a56ecSDave Jones return ret; 171bb0a56ecSDave Jones } 172bb0a56ecSDave Jones 173bb0a56ecSDave Jones 174bb0a56ecSDave Jones static unsigned int pentium4_get_frequency(void) 175bb0a56ecSDave Jones { 176bb0a56ecSDave Jones struct cpuinfo_x86 *c = &boot_cpu_data; 177bb0a56ecSDave Jones u32 msr_lo, msr_hi, mult; 178bb0a56ecSDave Jones unsigned int fsb = 0; 179bb0a56ecSDave Jones unsigned int ret; 180bb0a56ecSDave Jones u8 fsb_code; 181bb0a56ecSDave Jones 182bb0a56ecSDave Jones /* Pentium 4 Model 0 and 1 do not have the Core Clock Frequency 183bb0a56ecSDave Jones * to System Bus Frequency Ratio Field in the Processor Frequency 184bb0a56ecSDave Jones * Configuration Register of the MSR. Therefore the current 185bb0a56ecSDave Jones * frequency cannot be calculated and has to be measured. 186bb0a56ecSDave Jones */ 187bb0a56ecSDave Jones if (c->x86_model < 2) 188bb0a56ecSDave Jones return cpu_khz; 189bb0a56ecSDave Jones 190bb0a56ecSDave Jones rdmsr(0x2c, msr_lo, msr_hi); 191bb0a56ecSDave Jones 192bb0a56ecSDave Jones pr_debug("P4 - MSR_EBC_FREQUENCY_ID: 0x%x 0x%x\n", msr_lo, msr_hi); 193bb0a56ecSDave Jones 194bb0a56ecSDave Jones /* decode the FSB: see IA-32 Intel (C) Architecture Software 195bb0a56ecSDave Jones * Developer's Manual, Volume 3: System Prgramming Guide, 196bb0a56ecSDave Jones * revision #12 in Table B-1: MSRs in the Pentium 4 and 197bb0a56ecSDave Jones * Intel Xeon Processors, on page B-4 and B-5. 198bb0a56ecSDave Jones */ 199bb0a56ecSDave Jones fsb_code = (msr_lo >> 16) & 0x7; 200bb0a56ecSDave Jones switch (fsb_code) { 201bb0a56ecSDave Jones case 0: 202bb0a56ecSDave Jones fsb = 100 * 1000; 203bb0a56ecSDave Jones break; 204bb0a56ecSDave Jones case 1: 205bb0a56ecSDave Jones fsb = 13333 * 10; 206bb0a56ecSDave Jones break; 207bb0a56ecSDave Jones case 2: 208bb0a56ecSDave Jones fsb = 200 * 1000; 209bb0a56ecSDave Jones break; 210bb0a56ecSDave Jones } 211bb0a56ecSDave Jones 212bb0a56ecSDave Jones if (!fsb) 213bb0a56ecSDave Jones printk(KERN_DEBUG PFX "couldn't detect FSB speed. " 214bb0a56ecSDave Jones "Please send an e-mail to <linux@brodo.de>\n"); 215bb0a56ecSDave Jones 216bb0a56ecSDave Jones /* Multiplier. */ 217bb0a56ecSDave Jones mult = msr_lo >> 24; 218bb0a56ecSDave Jones 219bb0a56ecSDave Jones pr_debug("P4 - FSB %u kHz; Multiplier %u; Speed %u kHz\n", 220bb0a56ecSDave Jones fsb, mult, (fsb * mult)); 221bb0a56ecSDave Jones 222bb0a56ecSDave Jones ret = (fsb * mult); 223bb0a56ecSDave Jones return ret; 224bb0a56ecSDave Jones } 225bb0a56ecSDave Jones 226bb0a56ecSDave Jones 227bb0a56ecSDave Jones /* Warning: may get called from smp_call_function_single. */ 228bb0a56ecSDave Jones unsigned int speedstep_get_frequency(enum speedstep_processor processor) 229bb0a56ecSDave Jones { 230bb0a56ecSDave Jones switch (processor) { 231bb0a56ecSDave Jones case SPEEDSTEP_CPU_PCORE: 232bb0a56ecSDave Jones return pentium_core_get_frequency(); 233bb0a56ecSDave Jones case SPEEDSTEP_CPU_PM: 234bb0a56ecSDave Jones return pentiumM_get_frequency(); 235bb0a56ecSDave Jones case SPEEDSTEP_CPU_P4D: 236bb0a56ecSDave Jones case SPEEDSTEP_CPU_P4M: 237bb0a56ecSDave Jones return pentium4_get_frequency(); 238bb0a56ecSDave Jones case SPEEDSTEP_CPU_PIII_T: 239bb0a56ecSDave Jones case SPEEDSTEP_CPU_PIII_C: 240bb0a56ecSDave Jones case SPEEDSTEP_CPU_PIII_C_EARLY: 241bb0a56ecSDave Jones return pentium3_get_frequency(processor); 242bb0a56ecSDave Jones default: 243bb0a56ecSDave Jones return 0; 244bb0a56ecSDave Jones }; 245bb0a56ecSDave Jones return 0; 246bb0a56ecSDave Jones } 247bb0a56ecSDave Jones EXPORT_SYMBOL_GPL(speedstep_get_frequency); 248bb0a56ecSDave Jones 249bb0a56ecSDave Jones 250bb0a56ecSDave Jones /********************************************************************* 251bb0a56ecSDave Jones * DETECT SPEEDSTEP-CAPABLE PROCESSOR * 252bb0a56ecSDave Jones *********************************************************************/ 253bb0a56ecSDave Jones 254fa8031aeSAndi Kleen /* Keep in sync with the x86_cpu_id tables in the different modules */ 255bb0a56ecSDave Jones unsigned int speedstep_detect_processor(void) 256bb0a56ecSDave Jones { 257bb0a56ecSDave Jones struct cpuinfo_x86 *c = &cpu_data(0); 258bb0a56ecSDave Jones u32 ebx, msr_lo, msr_hi; 259bb0a56ecSDave Jones 260bb0a56ecSDave Jones pr_debug("x86: %x, model: %x\n", c->x86, c->x86_model); 261bb0a56ecSDave Jones 262bb0a56ecSDave Jones if ((c->x86_vendor != X86_VENDOR_INTEL) || 263bb0a56ecSDave Jones ((c->x86 != 6) && (c->x86 != 0xF))) 264bb0a56ecSDave Jones return 0; 265bb0a56ecSDave Jones 266bb0a56ecSDave Jones if (c->x86 == 0xF) { 267bb0a56ecSDave Jones /* Intel Mobile Pentium 4-M 268bb0a56ecSDave Jones * or Intel Mobile Pentium 4 with 533 MHz FSB */ 269bb0a56ecSDave Jones if (c->x86_model != 2) 270bb0a56ecSDave Jones return 0; 271bb0a56ecSDave Jones 272bb0a56ecSDave Jones ebx = cpuid_ebx(0x00000001); 273bb0a56ecSDave Jones ebx &= 0x000000FF; 274bb0a56ecSDave Jones 275b399151cSJia Zhang pr_debug("ebx value is %x, x86_stepping is %x\n", ebx, c->x86_stepping); 276bb0a56ecSDave Jones 277b399151cSJia Zhang switch (c->x86_stepping) { 278bb0a56ecSDave Jones case 4: 279bb0a56ecSDave Jones /* 280bb0a56ecSDave Jones * B-stepping [M-P4-M] 281bb0a56ecSDave Jones * sample has ebx = 0x0f, production has 0x0e. 282bb0a56ecSDave Jones */ 283bb0a56ecSDave Jones if ((ebx == 0x0e) || (ebx == 0x0f)) 284bb0a56ecSDave Jones return SPEEDSTEP_CPU_P4M; 285bb0a56ecSDave Jones break; 286bb0a56ecSDave Jones case 7: 287bb0a56ecSDave Jones /* 288bb0a56ecSDave Jones * C-stepping [M-P4-M] 289bb0a56ecSDave Jones * needs to have ebx=0x0e, else it's a celeron: 290bb0a56ecSDave Jones * cf. 25130917.pdf / page 7, footnote 5 even 291bb0a56ecSDave Jones * though 25072120.pdf / page 7 doesn't say 292bb0a56ecSDave Jones * samples are only of B-stepping... 293bb0a56ecSDave Jones */ 294bb0a56ecSDave Jones if (ebx == 0x0e) 295bb0a56ecSDave Jones return SPEEDSTEP_CPU_P4M; 296bb0a56ecSDave Jones break; 297bb0a56ecSDave Jones case 9: 298bb0a56ecSDave Jones /* 299bb0a56ecSDave Jones * D-stepping [M-P4-M or M-P4/533] 300bb0a56ecSDave Jones * 301bb0a56ecSDave Jones * this is totally strange: CPUID 0x0F29 is 302bb0a56ecSDave Jones * used by M-P4-M, M-P4/533 and(!) Celeron CPUs. 303bb0a56ecSDave Jones * The latter need to be sorted out as they don't 304bb0a56ecSDave Jones * support speedstep. 305bb0a56ecSDave Jones * Celerons with CPUID 0x0F29 may have either 306bb0a56ecSDave Jones * ebx=0x8 or 0xf -- 25130917.pdf doesn't say anything 307bb0a56ecSDave Jones * specific. 308bb0a56ecSDave Jones * M-P4-Ms may have either ebx=0xe or 0xf [see above] 309bb0a56ecSDave Jones * M-P4/533 have either ebx=0xe or 0xf. [25317607.pdf] 310bb0a56ecSDave Jones * also, M-P4M HTs have ebx=0x8, too 311bb0a56ecSDave Jones * For now, they are distinguished by the model_id 312bb0a56ecSDave Jones * string 313bb0a56ecSDave Jones */ 314bb0a56ecSDave Jones if ((ebx == 0x0e) || 315bb0a56ecSDave Jones (strstr(c->x86_model_id, 316bb0a56ecSDave Jones "Mobile Intel(R) Pentium(R) 4") != NULL)) 317bb0a56ecSDave Jones return SPEEDSTEP_CPU_P4M; 318bb0a56ecSDave Jones break; 319bb0a56ecSDave Jones default: 320bb0a56ecSDave Jones break; 321bb0a56ecSDave Jones } 322bb0a56ecSDave Jones return 0; 323bb0a56ecSDave Jones } 324bb0a56ecSDave Jones 325bb0a56ecSDave Jones switch (c->x86_model) { 326bb0a56ecSDave Jones case 0x0B: /* Intel PIII [Tualatin] */ 327bb0a56ecSDave Jones /* cpuid_ebx(1) is 0x04 for desktop PIII, 328bb0a56ecSDave Jones * 0x06 for mobile PIII-M */ 329bb0a56ecSDave Jones ebx = cpuid_ebx(0x00000001); 330bb0a56ecSDave Jones pr_debug("ebx is %x\n", ebx); 331bb0a56ecSDave Jones 332bb0a56ecSDave Jones ebx &= 0x000000FF; 333bb0a56ecSDave Jones 334bb0a56ecSDave Jones if (ebx != 0x06) 335bb0a56ecSDave Jones return 0; 336bb0a56ecSDave Jones 337bb0a56ecSDave Jones /* So far all PIII-M processors support SpeedStep. See 338bb0a56ecSDave Jones * Intel's 24540640.pdf of June 2003 339bb0a56ecSDave Jones */ 340bb0a56ecSDave Jones return SPEEDSTEP_CPU_PIII_T; 341bb0a56ecSDave Jones 342bb0a56ecSDave Jones case 0x08: /* Intel PIII [Coppermine] */ 343bb0a56ecSDave Jones 344bb0a56ecSDave Jones /* all mobile PIII Coppermines have FSB 100 MHz 345bb0a56ecSDave Jones * ==> sort out a few desktop PIIIs. */ 346bb0a56ecSDave Jones rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_hi); 347bb0a56ecSDave Jones pr_debug("Coppermine: MSR_IA32_EBL_CR_POWERON is 0x%x, 0x%x\n", 348bb0a56ecSDave Jones msr_lo, msr_hi); 349bb0a56ecSDave Jones msr_lo &= 0x00c0000; 350bb0a56ecSDave Jones if (msr_lo != 0x0080000) 351bb0a56ecSDave Jones return 0; 352bb0a56ecSDave Jones 353bb0a56ecSDave Jones /* 354bb0a56ecSDave Jones * If the processor is a mobile version, 355bb0a56ecSDave Jones * platform ID has bit 50 set 356bb0a56ecSDave Jones * it has SpeedStep technology if either 357bb0a56ecSDave Jones * bit 56 or 57 is set 358bb0a56ecSDave Jones */ 359bb0a56ecSDave Jones rdmsr(MSR_IA32_PLATFORM_ID, msr_lo, msr_hi); 360bb0a56ecSDave Jones pr_debug("Coppermine: MSR_IA32_PLATFORM ID is 0x%x, 0x%x\n", 361bb0a56ecSDave Jones msr_lo, msr_hi); 362bb0a56ecSDave Jones if ((msr_hi & (1<<18)) && 363bb0a56ecSDave Jones (relaxed_check ? 1 : (msr_hi & (3<<24)))) { 364b399151cSJia Zhang if (c->x86_stepping == 0x01) { 365bb0a56ecSDave Jones pr_debug("early PIII version\n"); 366bb0a56ecSDave Jones return SPEEDSTEP_CPU_PIII_C_EARLY; 367bb0a56ecSDave Jones } else 368bb0a56ecSDave Jones return SPEEDSTEP_CPU_PIII_C; 369bb0a56ecSDave Jones } 3709bc70e69SGustavo A. R. Silva /* fall through */ 371bb0a56ecSDave Jones default: 372bb0a56ecSDave Jones return 0; 373bb0a56ecSDave Jones } 374bb0a56ecSDave Jones } 375bb0a56ecSDave Jones EXPORT_SYMBOL_GPL(speedstep_detect_processor); 376bb0a56ecSDave Jones 377bb0a56ecSDave Jones 378bb0a56ecSDave Jones /********************************************************************* 379bb0a56ecSDave Jones * DETECT SPEEDSTEP SPEEDS * 380bb0a56ecSDave Jones *********************************************************************/ 381bb0a56ecSDave Jones 382bb0a56ecSDave Jones unsigned int speedstep_get_freqs(enum speedstep_processor processor, 383bb0a56ecSDave Jones unsigned int *low_speed, 384bb0a56ecSDave Jones unsigned int *high_speed, 385bb0a56ecSDave Jones unsigned int *transition_latency, 386bb0a56ecSDave Jones void (*set_state) (unsigned int state)) 387bb0a56ecSDave Jones { 388bb0a56ecSDave Jones unsigned int prev_speed; 389bb0a56ecSDave Jones unsigned int ret = 0; 390bb0a56ecSDave Jones unsigned long flags; 39172e624deSAbhilash Jindal ktime_t tv1, tv2; 392bb0a56ecSDave Jones 393bb0a56ecSDave Jones if ((!processor) || (!low_speed) || (!high_speed) || (!set_state)) 394bb0a56ecSDave Jones return -EINVAL; 395bb0a56ecSDave Jones 396bb0a56ecSDave Jones pr_debug("trying to determine both speeds\n"); 397bb0a56ecSDave Jones 398bb0a56ecSDave Jones /* get current speed */ 399bb0a56ecSDave Jones prev_speed = speedstep_get_frequency(processor); 400bb0a56ecSDave Jones if (!prev_speed) 401bb0a56ecSDave Jones return -EIO; 402bb0a56ecSDave Jones 403bb0a56ecSDave Jones pr_debug("previous speed is %u\n", prev_speed); 404bb0a56ecSDave Jones 405d4d4eda2SMikulas Patocka preempt_disable(); 406bb0a56ecSDave Jones local_irq_save(flags); 407bb0a56ecSDave Jones 408bb0a56ecSDave Jones /* switch to low state */ 409bb0a56ecSDave Jones set_state(SPEEDSTEP_LOW); 410bb0a56ecSDave Jones *low_speed = speedstep_get_frequency(processor); 411bb0a56ecSDave Jones if (!*low_speed) { 412bb0a56ecSDave Jones ret = -EIO; 413bb0a56ecSDave Jones goto out; 414bb0a56ecSDave Jones } 415bb0a56ecSDave Jones 416bb0a56ecSDave Jones pr_debug("low speed is %u\n", *low_speed); 417bb0a56ecSDave Jones 418bb0a56ecSDave Jones /* start latency measurement */ 419bb0a56ecSDave Jones if (transition_latency) 42072e624deSAbhilash Jindal tv1 = ktime_get(); 421bb0a56ecSDave Jones 422bb0a56ecSDave Jones /* switch to high state */ 423bb0a56ecSDave Jones set_state(SPEEDSTEP_HIGH); 424bb0a56ecSDave Jones 425bb0a56ecSDave Jones /* end latency measurement */ 426bb0a56ecSDave Jones if (transition_latency) 42772e624deSAbhilash Jindal tv2 = ktime_get(); 428bb0a56ecSDave Jones 429bb0a56ecSDave Jones *high_speed = speedstep_get_frequency(processor); 430bb0a56ecSDave Jones if (!*high_speed) { 431bb0a56ecSDave Jones ret = -EIO; 432bb0a56ecSDave Jones goto out; 433bb0a56ecSDave Jones } 434bb0a56ecSDave Jones 435bb0a56ecSDave Jones pr_debug("high speed is %u\n", *high_speed); 436bb0a56ecSDave Jones 437bb0a56ecSDave Jones if (*low_speed == *high_speed) { 438bb0a56ecSDave Jones ret = -ENODEV; 439bb0a56ecSDave Jones goto out; 440bb0a56ecSDave Jones } 441bb0a56ecSDave Jones 442bb0a56ecSDave Jones /* switch to previous state, if necessary */ 443bb0a56ecSDave Jones if (*high_speed != prev_speed) 444bb0a56ecSDave Jones set_state(SPEEDSTEP_LOW); 445bb0a56ecSDave Jones 446bb0a56ecSDave Jones if (transition_latency) { 44772e624deSAbhilash Jindal *transition_latency = ktime_to_us(ktime_sub(tv2, tv1)); 448bb0a56ecSDave Jones pr_debug("transition latency is %u uSec\n", *transition_latency); 449bb0a56ecSDave Jones 450bb0a56ecSDave Jones /* convert uSec to nSec and add 20% for safety reasons */ 451bb0a56ecSDave Jones *transition_latency *= 1200; 452bb0a56ecSDave Jones 453bb0a56ecSDave Jones /* check if the latency measurement is too high or too low 454bb0a56ecSDave Jones * and set it to a safe value (500uSec) in that case 455bb0a56ecSDave Jones */ 456bb0a56ecSDave Jones if (*transition_latency > 10000000 || 457bb0a56ecSDave Jones *transition_latency < 50000) { 4581c5864e2SJoe Perches pr_warn("frequency transition measured seems out of range (%u nSec), falling back to a safe one of %u nSec\n", 459bb0a56ecSDave Jones *transition_latency, 500000); 460bb0a56ecSDave Jones *transition_latency = 500000; 461bb0a56ecSDave Jones } 462bb0a56ecSDave Jones } 463bb0a56ecSDave Jones 464bb0a56ecSDave Jones out: 465bb0a56ecSDave Jones local_irq_restore(flags); 466d4d4eda2SMikulas Patocka preempt_enable(); 467d4d4eda2SMikulas Patocka 468bb0a56ecSDave Jones return ret; 469bb0a56ecSDave Jones } 470bb0a56ecSDave Jones EXPORT_SYMBOL_GPL(speedstep_get_freqs); 471bb0a56ecSDave Jones 472bb0a56ecSDave Jones #ifdef CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK 473bb0a56ecSDave Jones module_param(relaxed_check, int, 0444); 474bb0a56ecSDave Jones MODULE_PARM_DESC(relaxed_check, 475bb0a56ecSDave Jones "Don't do all checks for speedstep capability."); 476bb0a56ecSDave Jones #endif 477bb0a56ecSDave Jones 478bb0a56ecSDave Jones MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>"); 479bb0a56ecSDave Jones MODULE_DESCRIPTION("Library for Intel SpeedStep 1 or 2 cpufreq drivers."); 480bb0a56ecSDave Jones MODULE_LICENSE("GPL"); 481