root/drivers/cpufreq/speedstep-lib.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pentium3_get_frequency
  2. pentiumM_get_frequency
  3. pentium_core_get_frequency
  4. pentium4_get_frequency
  5. speedstep_get_frequency
  6. speedstep_detect_processor
  7. speedstep_get_freqs

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

/* [<][>][^][v][top][bottom][index][help] */