root/drivers/cpufreq/longhaul.c

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

DEFINITIONS

This source file includes following definitions.
  1. print_speed
  2. calc_speed
  3. longhaul_get_cpu_mult
  4. do_longhaul1
  5. do_powersaver
  6. longhaul_setstate
  7. guess_fsb
  8. longhaul_get_ranges
  9. longhaul_setup_voltagescaling
  10. longhaul_target
  11. longhaul_get
  12. longhaul_walk_callback
  13. enable_arbiter_disable
  14. longhaul_setup_southbridge
  15. longhaul_cpu_init
  16. longhaul_init
  17. longhaul_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  *  (C) 2001-2004  Dave Jones.
   4  *  (C) 2002  Padraig Brady. <padraig@antefacto.com>
   5  *
   6  *  Based upon datasheets & sample CPUs kindly provided by VIA.
   7  *
   8  *  VIA have currently 3 different versions of Longhaul.
   9  *  Version 1 (Longhaul) uses the BCR2 MSR at 0x1147.
  10  *   It is present only in Samuel 1 (C5A), Samuel 2 (C5B) stepping 0.
  11  *  Version 2 of longhaul is backward compatible with v1, but adds
  12  *   LONGHAUL MSR for purpose of both frequency and voltage scaling.
  13  *   Present in Samuel 2 (steppings 1-7 only) (C5B), and Ezra (C5C).
  14  *  Version 3 of longhaul got renamed to Powersaver and redesigned
  15  *   to use only the POWERSAVER MSR at 0x110a.
  16  *   It is present in Ezra-T (C5M), Nehemiah (C5X) and above.
  17  *   It's pretty much the same feature wise to longhaul v2, though
  18  *   there is provision for scaling FSB too, but this doesn't work
  19  *   too well in practice so we don't even try to use this.
  20  *
  21  *  BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
  22  */
  23 
  24 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  25 
  26 #include <linux/kernel.h>
  27 #include <linux/module.h>
  28 #include <linux/moduleparam.h>
  29 #include <linux/init.h>
  30 #include <linux/cpufreq.h>
  31 #include <linux/pci.h>
  32 #include <linux/slab.h>
  33 #include <linux/string.h>
  34 #include <linux/delay.h>
  35 #include <linux/timex.h>
  36 #include <linux/io.h>
  37 #include <linux/acpi.h>
  38 
  39 #include <asm/msr.h>
  40 #include <asm/cpu_device_id.h>
  41 #include <acpi/processor.h>
  42 
  43 #include "longhaul.h"
  44 
  45 #define TYPE_LONGHAUL_V1        1
  46 #define TYPE_LONGHAUL_V2        2
  47 #define TYPE_POWERSAVER         3
  48 
  49 #define CPU_SAMUEL      1
  50 #define CPU_SAMUEL2     2
  51 #define CPU_EZRA        3
  52 #define CPU_EZRA_T      4
  53 #define CPU_NEHEMIAH    5
  54 #define CPU_NEHEMIAH_C  6
  55 
  56 /* Flags */
  57 #define USE_ACPI_C3             (1 << 1)
  58 #define USE_NORTHBRIDGE         (1 << 2)
  59 
  60 static int cpu_model;
  61 static unsigned int numscales = 16;
  62 static unsigned int fsb;
  63 
  64 static const struct mV_pos *vrm_mV_table;
  65 static const unsigned char *mV_vrm_table;
  66 
  67 static unsigned int highest_speed, lowest_speed; /* kHz */
  68 static unsigned int minmult, maxmult;
  69 static int can_scale_voltage;
  70 static struct acpi_processor *pr;
  71 static struct acpi_processor_cx *cx;
  72 static u32 acpi_regs_addr;
  73 static u8 longhaul_flags;
  74 static unsigned int longhaul_index;
  75 
  76 /* Module parameters */
  77 static int scale_voltage;
  78 static int disable_acpi_c3;
  79 static int revid_errata;
  80 static int enable;
  81 
  82 /* Clock ratios multiplied by 10 */
  83 static int mults[32];
  84 static int eblcr[32];
  85 static int longhaul_version;
  86 static struct cpufreq_frequency_table *longhaul_table;
  87 
  88 static char speedbuffer[8];
  89 
  90 static char *print_speed(int speed)
  91 {
  92         if (speed < 1000) {
  93                 snprintf(speedbuffer, sizeof(speedbuffer), "%dMHz", speed);
  94                 return speedbuffer;
  95         }
  96 
  97         if (speed%1000 == 0)
  98                 snprintf(speedbuffer, sizeof(speedbuffer),
  99                         "%dGHz", speed/1000);
 100         else
 101                 snprintf(speedbuffer, sizeof(speedbuffer),
 102                         "%d.%dGHz", speed/1000, (speed%1000)/100);
 103 
 104         return speedbuffer;
 105 }
 106 
 107 
 108 static unsigned int calc_speed(int mult)
 109 {
 110         int khz;
 111         khz = (mult/10)*fsb;
 112         if (mult%10)
 113                 khz += fsb/2;
 114         khz *= 1000;
 115         return khz;
 116 }
 117 
 118 
 119 static int longhaul_get_cpu_mult(void)
 120 {
 121         unsigned long invalue = 0, lo, hi;
 122 
 123         rdmsr(MSR_IA32_EBL_CR_POWERON, lo, hi);
 124         invalue = (lo & (1<<22|1<<23|1<<24|1<<25))>>22;
 125         if (longhaul_version == TYPE_LONGHAUL_V2 ||
 126             longhaul_version == TYPE_POWERSAVER) {
 127                 if (lo & (1<<27))
 128                         invalue += 16;
 129         }
 130         return eblcr[invalue];
 131 }
 132 
 133 /* For processor with BCR2 MSR */
 134 
 135 static void do_longhaul1(unsigned int mults_index)
 136 {
 137         union msr_bcr2 bcr2;
 138 
 139         rdmsrl(MSR_VIA_BCR2, bcr2.val);
 140         /* Enable software clock multiplier */
 141         bcr2.bits.ESOFTBF = 1;
 142         bcr2.bits.CLOCKMUL = mults_index & 0xff;
 143 
 144         /* Sync to timer tick */
 145         safe_halt();
 146         /* Change frequency on next halt or sleep */
 147         wrmsrl(MSR_VIA_BCR2, bcr2.val);
 148         /* Invoke transition */
 149         ACPI_FLUSH_CPU_CACHE();
 150         halt();
 151 
 152         /* Disable software clock multiplier */
 153         local_irq_disable();
 154         rdmsrl(MSR_VIA_BCR2, bcr2.val);
 155         bcr2.bits.ESOFTBF = 0;
 156         wrmsrl(MSR_VIA_BCR2, bcr2.val);
 157 }
 158 
 159 /* For processor with Longhaul MSR */
 160 
 161 static void do_powersaver(int cx_address, unsigned int mults_index,
 162                           unsigned int dir)
 163 {
 164         union msr_longhaul longhaul;
 165         u32 t;
 166 
 167         rdmsrl(MSR_VIA_LONGHAUL, longhaul.val);
 168         /* Setup new frequency */
 169         if (!revid_errata)
 170                 longhaul.bits.RevisionKey = longhaul.bits.RevisionID;
 171         else
 172                 longhaul.bits.RevisionKey = 0;
 173         longhaul.bits.SoftBusRatio = mults_index & 0xf;
 174         longhaul.bits.SoftBusRatio4 = (mults_index & 0x10) >> 4;
 175         /* Setup new voltage */
 176         if (can_scale_voltage)
 177                 longhaul.bits.SoftVID = (mults_index >> 8) & 0x1f;
 178         /* Sync to timer tick */
 179         safe_halt();
 180         /* Raise voltage if necessary */
 181         if (can_scale_voltage && dir) {
 182                 longhaul.bits.EnableSoftVID = 1;
 183                 wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
 184                 /* Change voltage */
 185                 if (!cx_address) {
 186                         ACPI_FLUSH_CPU_CACHE();
 187                         halt();
 188                 } else {
 189                         ACPI_FLUSH_CPU_CACHE();
 190                         /* Invoke C3 */
 191                         inb(cx_address);
 192                         /* Dummy op - must do something useless after P_LVL3
 193                          * read */
 194                         t = inl(acpi_gbl_FADT.xpm_timer_block.address);
 195                 }
 196                 longhaul.bits.EnableSoftVID = 0;
 197                 wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
 198         }
 199 
 200         /* Change frequency on next halt or sleep */
 201         longhaul.bits.EnableSoftBusRatio = 1;
 202         wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
 203         if (!cx_address) {
 204                 ACPI_FLUSH_CPU_CACHE();
 205                 halt();
 206         } else {
 207                 ACPI_FLUSH_CPU_CACHE();
 208                 /* Invoke C3 */
 209                 inb(cx_address);
 210                 /* Dummy op - must do something useless after P_LVL3 read */
 211                 t = inl(acpi_gbl_FADT.xpm_timer_block.address);
 212         }
 213         /* Disable bus ratio bit */
 214         longhaul.bits.EnableSoftBusRatio = 0;
 215         wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
 216 
 217         /* Reduce voltage if necessary */
 218         if (can_scale_voltage && !dir) {
 219                 longhaul.bits.EnableSoftVID = 1;
 220                 wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
 221                 /* Change voltage */
 222                 if (!cx_address) {
 223                         ACPI_FLUSH_CPU_CACHE();
 224                         halt();
 225                 } else {
 226                         ACPI_FLUSH_CPU_CACHE();
 227                         /* Invoke C3 */
 228                         inb(cx_address);
 229                         /* Dummy op - must do something useless after P_LVL3
 230                          * read */
 231                         t = inl(acpi_gbl_FADT.xpm_timer_block.address);
 232                 }
 233                 longhaul.bits.EnableSoftVID = 0;
 234                 wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
 235         }
 236 }
 237 
 238 /**
 239  * longhaul_set_cpu_frequency()
 240  * @mults_index : bitpattern of the new multiplier.
 241  *
 242  * Sets a new clock ratio.
 243  */
 244 
 245 static int longhaul_setstate(struct cpufreq_policy *policy,
 246                 unsigned int table_index)
 247 {
 248         unsigned int mults_index;
 249         int speed, mult;
 250         struct cpufreq_freqs freqs;
 251         unsigned long flags;
 252         unsigned int pic1_mask, pic2_mask;
 253         u16 bm_status = 0;
 254         u32 bm_timeout = 1000;
 255         unsigned int dir = 0;
 256 
 257         mults_index = longhaul_table[table_index].driver_data;
 258         /* Safety precautions */
 259         mult = mults[mults_index & 0x1f];
 260         if (mult == -1)
 261                 return -EINVAL;
 262 
 263         speed = calc_speed(mult);
 264         if ((speed > highest_speed) || (speed < lowest_speed))
 265                 return -EINVAL;
 266 
 267         /* Voltage transition before frequency transition? */
 268         if (can_scale_voltage && longhaul_index < table_index)
 269                 dir = 1;
 270 
 271         freqs.old = calc_speed(longhaul_get_cpu_mult());
 272         freqs.new = speed;
 273 
 274         pr_debug("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n",
 275                         fsb, mult/10, mult%10, print_speed(speed/1000));
 276 retry_loop:
 277         preempt_disable();
 278         local_irq_save(flags);
 279 
 280         pic2_mask = inb(0xA1);
 281         pic1_mask = inb(0x21);  /* works on C3. save mask. */
 282         outb(0xFF, 0xA1);       /* Overkill */
 283         outb(0xFE, 0x21);       /* TMR0 only */
 284 
 285         /* Wait while PCI bus is busy. */
 286         if (acpi_regs_addr && (longhaul_flags & USE_NORTHBRIDGE
 287             || ((pr != NULL) && pr->flags.bm_control))) {
 288                 bm_status = inw(acpi_regs_addr);
 289                 bm_status &= 1 << 4;
 290                 while (bm_status && bm_timeout) {
 291                         outw(1 << 4, acpi_regs_addr);
 292                         bm_timeout--;
 293                         bm_status = inw(acpi_regs_addr);
 294                         bm_status &= 1 << 4;
 295                 }
 296         }
 297 
 298         if (longhaul_flags & USE_NORTHBRIDGE) {
 299                 /* Disable AGP and PCI arbiters */
 300                 outb(3, 0x22);
 301         } else if ((pr != NULL) && pr->flags.bm_control) {
 302                 /* Disable bus master arbitration */
 303                 acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 1);
 304         }
 305         switch (longhaul_version) {
 306 
 307         /*
 308          * Longhaul v1. (Samuel[C5A] and Samuel2 stepping 0[C5B])
 309          * Software controlled multipliers only.
 310          */
 311         case TYPE_LONGHAUL_V1:
 312                 do_longhaul1(mults_index);
 313                 break;
 314 
 315         /*
 316          * Longhaul v2 appears in Samuel2 Steppings 1->7 [C5B] and Ezra [C5C]
 317          *
 318          * Longhaul v3 (aka Powersaver). (Ezra-T [C5M] & Nehemiah [C5N])
 319          * Nehemiah can do FSB scaling too, but this has never been proven
 320          * to work in practice.
 321          */
 322         case TYPE_LONGHAUL_V2:
 323         case TYPE_POWERSAVER:
 324                 if (longhaul_flags & USE_ACPI_C3) {
 325                         /* Don't allow wakeup */
 326                         acpi_write_bit_register(ACPI_BITREG_BUS_MASTER_RLD, 0);
 327                         do_powersaver(cx->address, mults_index, dir);
 328                 } else {
 329                         do_powersaver(0, mults_index, dir);
 330                 }
 331                 break;
 332         }
 333 
 334         if (longhaul_flags & USE_NORTHBRIDGE) {
 335                 /* Enable arbiters */
 336                 outb(0, 0x22);
 337         } else if ((pr != NULL) && pr->flags.bm_control) {
 338                 /* Enable bus master arbitration */
 339                 acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 0);
 340         }
 341         outb(pic2_mask, 0xA1);  /* restore mask */
 342         outb(pic1_mask, 0x21);
 343 
 344         local_irq_restore(flags);
 345         preempt_enable();
 346 
 347         freqs.new = calc_speed(longhaul_get_cpu_mult());
 348         /* Check if requested frequency is set. */
 349         if (unlikely(freqs.new != speed)) {
 350                 pr_info("Failed to set requested frequency!\n");
 351                 /* Revision ID = 1 but processor is expecting revision key
 352                  * equal to 0. Jumpers at the bottom of processor will change
 353                  * multiplier and FSB, but will not change bits in Longhaul
 354                  * MSR nor enable voltage scaling. */
 355                 if (!revid_errata) {
 356                         pr_info("Enabling \"Ignore Revision ID\" option\n");
 357                         revid_errata = 1;
 358                         msleep(200);
 359                         goto retry_loop;
 360                 }
 361                 /* Why ACPI C3 sometimes doesn't work is a mystery for me.
 362                  * But it does happen. Processor is entering ACPI C3 state,
 363                  * but it doesn't change frequency. I tried poking various
 364                  * bits in northbridge registers, but without success. */
 365                 if (longhaul_flags & USE_ACPI_C3) {
 366                         pr_info("Disabling ACPI C3 support\n");
 367                         longhaul_flags &= ~USE_ACPI_C3;
 368                         if (revid_errata) {
 369                                 pr_info("Disabling \"Ignore Revision ID\" option\n");
 370                                 revid_errata = 0;
 371                         }
 372                         msleep(200);
 373                         goto retry_loop;
 374                 }
 375                 /* This shouldn't happen. Longhaul ver. 2 was reported not
 376                  * working on processors without voltage scaling, but with
 377                  * RevID = 1. RevID errata will make things right. Just
 378                  * to be 100% sure. */
 379                 if (longhaul_version == TYPE_LONGHAUL_V2) {
 380                         pr_info("Switching to Longhaul ver. 1\n");
 381                         longhaul_version = TYPE_LONGHAUL_V1;
 382                         msleep(200);
 383                         goto retry_loop;
 384                 }
 385         }
 386 
 387         if (!bm_timeout) {
 388                 pr_info("Warning: Timeout while waiting for idle PCI bus\n");
 389                 return -EBUSY;
 390         }
 391 
 392         return 0;
 393 }
 394 
 395 /*
 396  * Centaur decided to make life a little more tricky.
 397  * Only longhaul v1 is allowed to read EBLCR BSEL[0:1].
 398  * Samuel2 and above have to try and guess what the FSB is.
 399  * We do this by assuming we booted at maximum multiplier, and interpolate
 400  * between that value multiplied by possible FSBs and cpu_mhz which
 401  * was calculated at boot time. Really ugly, but no other way to do this.
 402  */
 403 
 404 #define ROUNDING        0xf
 405 
 406 static int guess_fsb(int mult)
 407 {
 408         int speed = cpu_khz / 1000;
 409         int i;
 410         int speeds[] = { 666, 1000, 1333, 2000 };
 411         int f_max, f_min;
 412 
 413         for (i = 0; i < 4; i++) {
 414                 f_max = ((speeds[i] * mult) + 50) / 100;
 415                 f_max += (ROUNDING / 2);
 416                 f_min = f_max - ROUNDING;
 417                 if ((speed <= f_max) && (speed >= f_min))
 418                         return speeds[i] / 10;
 419         }
 420         return 0;
 421 }
 422 
 423 
 424 static int longhaul_get_ranges(void)
 425 {
 426         unsigned int i, j, k = 0;
 427         unsigned int ratio;
 428         int mult;
 429 
 430         /* Get current frequency */
 431         mult = longhaul_get_cpu_mult();
 432         if (mult == -1) {
 433                 pr_info("Invalid (reserved) multiplier!\n");
 434                 return -EINVAL;
 435         }
 436         fsb = guess_fsb(mult);
 437         if (fsb == 0) {
 438                 pr_info("Invalid (reserved) FSB!\n");
 439                 return -EINVAL;
 440         }
 441         /* Get max multiplier - as we always did.
 442          * Longhaul MSR is useful only when voltage scaling is enabled.
 443          * C3 is booting at max anyway. */
 444         maxmult = mult;
 445         /* Get min multiplier */
 446         switch (cpu_model) {
 447         case CPU_NEHEMIAH:
 448                 minmult = 50;
 449                 break;
 450         case CPU_NEHEMIAH_C:
 451                 minmult = 40;
 452                 break;
 453         default:
 454                 minmult = 30;
 455                 break;
 456         }
 457 
 458         pr_debug("MinMult:%d.%dx MaxMult:%d.%dx\n",
 459                  minmult/10, minmult%10, maxmult/10, maxmult%10);
 460 
 461         highest_speed = calc_speed(maxmult);
 462         lowest_speed = calc_speed(minmult);
 463         pr_debug("FSB:%dMHz  Lowest speed: %s   Highest speed:%s\n", fsb,
 464                  print_speed(lowest_speed/1000),
 465                  print_speed(highest_speed/1000));
 466 
 467         if (lowest_speed == highest_speed) {
 468                 pr_info("highestspeed == lowest, aborting\n");
 469                 return -EINVAL;
 470         }
 471         if (lowest_speed > highest_speed) {
 472                 pr_info("nonsense! lowest (%d > %d) !\n",
 473                         lowest_speed, highest_speed);
 474                 return -EINVAL;
 475         }
 476 
 477         longhaul_table = kcalloc(numscales + 1, sizeof(*longhaul_table),
 478                                  GFP_KERNEL);
 479         if (!longhaul_table)
 480                 return -ENOMEM;
 481 
 482         for (j = 0; j < numscales; j++) {
 483                 ratio = mults[j];
 484                 if (ratio == -1)
 485                         continue;
 486                 if (ratio > maxmult || ratio < minmult)
 487                         continue;
 488                 longhaul_table[k].frequency = calc_speed(ratio);
 489                 longhaul_table[k].driver_data   = j;
 490                 k++;
 491         }
 492         if (k <= 1) {
 493                 kfree(longhaul_table);
 494                 return -ENODEV;
 495         }
 496         /* Sort */
 497         for (j = 0; j < k - 1; j++) {
 498                 unsigned int min_f, min_i;
 499                 min_f = longhaul_table[j].frequency;
 500                 min_i = j;
 501                 for (i = j + 1; i < k; i++) {
 502                         if (longhaul_table[i].frequency < min_f) {
 503                                 min_f = longhaul_table[i].frequency;
 504                                 min_i = i;
 505                         }
 506                 }
 507                 if (min_i != j) {
 508                         swap(longhaul_table[j].frequency,
 509                              longhaul_table[min_i].frequency);
 510                         swap(longhaul_table[j].driver_data,
 511                              longhaul_table[min_i].driver_data);
 512                 }
 513         }
 514 
 515         longhaul_table[k].frequency = CPUFREQ_TABLE_END;
 516 
 517         /* Find index we are running on */
 518         for (j = 0; j < k; j++) {
 519                 if (mults[longhaul_table[j].driver_data & 0x1f] == mult) {
 520                         longhaul_index = j;
 521                         break;
 522                 }
 523         }
 524         return 0;
 525 }
 526 
 527 
 528 static void longhaul_setup_voltagescaling(void)
 529 {
 530         struct cpufreq_frequency_table *freq_pos;
 531         union msr_longhaul longhaul;
 532         struct mV_pos minvid, maxvid, vid;
 533         unsigned int j, speed, pos, kHz_step, numvscales;
 534         int min_vid_speed;
 535 
 536         rdmsrl(MSR_VIA_LONGHAUL, longhaul.val);
 537         if (!(longhaul.bits.RevisionID & 1)) {
 538                 pr_info("Voltage scaling not supported by CPU\n");
 539                 return;
 540         }
 541 
 542         if (!longhaul.bits.VRMRev) {
 543                 pr_info("VRM 8.5\n");
 544                 vrm_mV_table = &vrm85_mV[0];
 545                 mV_vrm_table = &mV_vrm85[0];
 546         } else {
 547                 pr_info("Mobile VRM\n");
 548                 if (cpu_model < CPU_NEHEMIAH)
 549                         return;
 550                 vrm_mV_table = &mobilevrm_mV[0];
 551                 mV_vrm_table = &mV_mobilevrm[0];
 552         }
 553 
 554         minvid = vrm_mV_table[longhaul.bits.MinimumVID];
 555         maxvid = vrm_mV_table[longhaul.bits.MaximumVID];
 556 
 557         if (minvid.mV == 0 || maxvid.mV == 0 || minvid.mV > maxvid.mV) {
 558                 pr_info("Bogus values Min:%d.%03d Max:%d.%03d - Voltage scaling disabled\n",
 559                         minvid.mV/1000, minvid.mV%1000,
 560                         maxvid.mV/1000, maxvid.mV%1000);
 561                 return;
 562         }
 563 
 564         if (minvid.mV == maxvid.mV) {
 565                 pr_info("Claims to support voltage scaling but min & max are both %d.%03d - Voltage scaling disabled\n",
 566                         maxvid.mV/1000, maxvid.mV%1000);
 567                 return;
 568         }
 569 
 570         /* How many voltage steps*/
 571         numvscales = maxvid.pos - minvid.pos + 1;
 572         pr_info("Max VID=%d.%03d  Min VID=%d.%03d, %d possible voltage scales\n",
 573                 maxvid.mV/1000, maxvid.mV%1000,
 574                 minvid.mV/1000, minvid.mV%1000,
 575                 numvscales);
 576 
 577         /* Calculate max frequency at min voltage */
 578         j = longhaul.bits.MinMHzBR;
 579         if (longhaul.bits.MinMHzBR4)
 580                 j += 16;
 581         min_vid_speed = eblcr[j];
 582         if (min_vid_speed == -1)
 583                 return;
 584         switch (longhaul.bits.MinMHzFSB) {
 585         case 0:
 586                 min_vid_speed *= 13333;
 587                 break;
 588         case 1:
 589                 min_vid_speed *= 10000;
 590                 break;
 591         case 3:
 592                 min_vid_speed *= 6666;
 593                 break;
 594         default:
 595                 return;
 596                 break;
 597         }
 598         if (min_vid_speed >= highest_speed)
 599                 return;
 600         /* Calculate kHz for one voltage step */
 601         kHz_step = (highest_speed - min_vid_speed) / numvscales;
 602 
 603         cpufreq_for_each_entry_idx(freq_pos, longhaul_table, j) {
 604                 speed = freq_pos->frequency;
 605                 if (speed > min_vid_speed)
 606                         pos = (speed - min_vid_speed) / kHz_step + minvid.pos;
 607                 else
 608                         pos = minvid.pos;
 609                 freq_pos->driver_data |= mV_vrm_table[pos] << 8;
 610                 vid = vrm_mV_table[mV_vrm_table[pos]];
 611                 pr_info("f: %d kHz, index: %d, vid: %d mV\n",
 612                         speed, j, vid.mV);
 613         }
 614 
 615         can_scale_voltage = 1;
 616         pr_info("Voltage scaling enabled\n");
 617 }
 618 
 619 
 620 static int longhaul_target(struct cpufreq_policy *policy,
 621                             unsigned int table_index)
 622 {
 623         unsigned int i;
 624         unsigned int dir = 0;
 625         u8 vid, current_vid;
 626         int retval = 0;
 627 
 628         if (!can_scale_voltage)
 629                 retval = longhaul_setstate(policy, table_index);
 630         else {
 631                 /* On test system voltage transitions exceeding single
 632                  * step up or down were turning motherboard off. Both
 633                  * "ondemand" and "userspace" are unsafe. C7 is doing
 634                  * this in hardware, C3 is old and we need to do this
 635                  * in software. */
 636                 i = longhaul_index;
 637                 current_vid = (longhaul_table[longhaul_index].driver_data >> 8);
 638                 current_vid &= 0x1f;
 639                 if (table_index > longhaul_index)
 640                         dir = 1;
 641                 while (i != table_index) {
 642                         vid = (longhaul_table[i].driver_data >> 8) & 0x1f;
 643                         if (vid != current_vid) {
 644                                 retval = longhaul_setstate(policy, i);
 645                                 current_vid = vid;
 646                                 msleep(200);
 647                         }
 648                         if (dir)
 649                                 i++;
 650                         else
 651                                 i--;
 652                 }
 653                 retval = longhaul_setstate(policy, table_index);
 654         }
 655 
 656         longhaul_index = table_index;
 657         return retval;
 658 }
 659 
 660 
 661 static unsigned int longhaul_get(unsigned int cpu)
 662 {
 663         if (cpu)
 664                 return 0;
 665         return calc_speed(longhaul_get_cpu_mult());
 666 }
 667 
 668 static acpi_status longhaul_walk_callback(acpi_handle obj_handle,
 669                                           u32 nesting_level,
 670                                           void *context, void **return_value)
 671 {
 672         struct acpi_device *d;
 673 
 674         if (acpi_bus_get_device(obj_handle, &d))
 675                 return 0;
 676 
 677         *return_value = acpi_driver_data(d);
 678         return 1;
 679 }
 680 
 681 /* VIA don't support PM2 reg, but have something similar */
 682 static int enable_arbiter_disable(void)
 683 {
 684         struct pci_dev *dev;
 685         int status = 1;
 686         int reg;
 687         u8 pci_cmd;
 688 
 689         /* Find PLE133 host bridge */
 690         reg = 0x78;
 691         dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8601_0,
 692                              NULL);
 693         /* Find PM133/VT8605 host bridge */
 694         if (dev == NULL)
 695                 dev = pci_get_device(PCI_VENDOR_ID_VIA,
 696                                      PCI_DEVICE_ID_VIA_8605_0, NULL);
 697         /* Find CLE266 host bridge */
 698         if (dev == NULL) {
 699                 reg = 0x76;
 700                 dev = pci_get_device(PCI_VENDOR_ID_VIA,
 701                                      PCI_DEVICE_ID_VIA_862X_0, NULL);
 702                 /* Find CN400 V-Link host bridge */
 703                 if (dev == NULL)
 704                         dev = pci_get_device(PCI_VENDOR_ID_VIA, 0x7259, NULL);
 705         }
 706         if (dev != NULL) {
 707                 /* Enable access to port 0x22 */
 708                 pci_read_config_byte(dev, reg, &pci_cmd);
 709                 if (!(pci_cmd & 1<<7)) {
 710                         pci_cmd |= 1<<7;
 711                         pci_write_config_byte(dev, reg, pci_cmd);
 712                         pci_read_config_byte(dev, reg, &pci_cmd);
 713                         if (!(pci_cmd & 1<<7)) {
 714                                 pr_err("Can't enable access to port 0x22\n");
 715                                 status = 0;
 716                         }
 717                 }
 718                 pci_dev_put(dev);
 719                 return status;
 720         }
 721         return 0;
 722 }
 723 
 724 static int longhaul_setup_southbridge(void)
 725 {
 726         struct pci_dev *dev;
 727         u8 pci_cmd;
 728 
 729         /* Find VT8235 southbridge */
 730         dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, NULL);
 731         if (dev == NULL)
 732                 /* Find VT8237 southbridge */
 733                 dev = pci_get_device(PCI_VENDOR_ID_VIA,
 734                                      PCI_DEVICE_ID_VIA_8237, NULL);
 735         if (dev != NULL) {
 736                 /* Set transition time to max */
 737                 pci_read_config_byte(dev, 0xec, &pci_cmd);
 738                 pci_cmd &= ~(1 << 2);
 739                 pci_write_config_byte(dev, 0xec, pci_cmd);
 740                 pci_read_config_byte(dev, 0xe4, &pci_cmd);
 741                 pci_cmd &= ~(1 << 7);
 742                 pci_write_config_byte(dev, 0xe4, pci_cmd);
 743                 pci_read_config_byte(dev, 0xe5, &pci_cmd);
 744                 pci_cmd |= 1 << 7;
 745                 pci_write_config_byte(dev, 0xe5, pci_cmd);
 746                 /* Get address of ACPI registers block*/
 747                 pci_read_config_byte(dev, 0x81, &pci_cmd);
 748                 if (pci_cmd & 1 << 7) {
 749                         pci_read_config_dword(dev, 0x88, &acpi_regs_addr);
 750                         acpi_regs_addr &= 0xff00;
 751                         pr_info("ACPI I/O at 0x%x\n", acpi_regs_addr);
 752                 }
 753 
 754                 pci_dev_put(dev);
 755                 return 1;
 756         }
 757         return 0;
 758 }
 759 
 760 static int longhaul_cpu_init(struct cpufreq_policy *policy)
 761 {
 762         struct cpuinfo_x86 *c = &cpu_data(0);
 763         char *cpuname = NULL;
 764         int ret;
 765         u32 lo, hi;
 766 
 767         /* Check what we have on this motherboard */
 768         switch (c->x86_model) {
 769         case 6:
 770                 cpu_model = CPU_SAMUEL;
 771                 cpuname = "C3 'Samuel' [C5A]";
 772                 longhaul_version = TYPE_LONGHAUL_V1;
 773                 memcpy(mults, samuel1_mults, sizeof(samuel1_mults));
 774                 memcpy(eblcr, samuel1_eblcr, sizeof(samuel1_eblcr));
 775                 break;
 776 
 777         case 7:
 778                 switch (c->x86_stepping) {
 779                 case 0:
 780                         longhaul_version = TYPE_LONGHAUL_V1;
 781                         cpu_model = CPU_SAMUEL2;
 782                         cpuname = "C3 'Samuel 2' [C5B]";
 783                         /* Note, this is not a typo, early Samuel2's had
 784                          * Samuel1 ratios. */
 785                         memcpy(mults, samuel1_mults, sizeof(samuel1_mults));
 786                         memcpy(eblcr, samuel2_eblcr, sizeof(samuel2_eblcr));
 787                         break;
 788                 case 1 ... 15:
 789                         longhaul_version = TYPE_LONGHAUL_V2;
 790                         if (c->x86_stepping < 8) {
 791                                 cpu_model = CPU_SAMUEL2;
 792                                 cpuname = "C3 'Samuel 2' [C5B]";
 793                         } else {
 794                                 cpu_model = CPU_EZRA;
 795                                 cpuname = "C3 'Ezra' [C5C]";
 796                         }
 797                         memcpy(mults, ezra_mults, sizeof(ezra_mults));
 798                         memcpy(eblcr, ezra_eblcr, sizeof(ezra_eblcr));
 799                         break;
 800                 }
 801                 break;
 802 
 803         case 8:
 804                 cpu_model = CPU_EZRA_T;
 805                 cpuname = "C3 'Ezra-T' [C5M]";
 806                 longhaul_version = TYPE_POWERSAVER;
 807                 numscales = 32;
 808                 memcpy(mults, ezrat_mults, sizeof(ezrat_mults));
 809                 memcpy(eblcr, ezrat_eblcr, sizeof(ezrat_eblcr));
 810                 break;
 811 
 812         case 9:
 813                 longhaul_version = TYPE_POWERSAVER;
 814                 numscales = 32;
 815                 memcpy(mults, nehemiah_mults, sizeof(nehemiah_mults));
 816                 memcpy(eblcr, nehemiah_eblcr, sizeof(nehemiah_eblcr));
 817                 switch (c->x86_stepping) {
 818                 case 0 ... 1:
 819                         cpu_model = CPU_NEHEMIAH;
 820                         cpuname = "C3 'Nehemiah A' [C5XLOE]";
 821                         break;
 822                 case 2 ... 4:
 823                         cpu_model = CPU_NEHEMIAH;
 824                         cpuname = "C3 'Nehemiah B' [C5XLOH]";
 825                         break;
 826                 case 5 ... 15:
 827                         cpu_model = CPU_NEHEMIAH_C;
 828                         cpuname = "C3 'Nehemiah C' [C5P]";
 829                         break;
 830                 }
 831                 break;
 832 
 833         default:
 834                 cpuname = "Unknown";
 835                 break;
 836         }
 837         /* Check Longhaul ver. 2 */
 838         if (longhaul_version == TYPE_LONGHAUL_V2) {
 839                 rdmsr(MSR_VIA_LONGHAUL, lo, hi);
 840                 if (lo == 0 && hi == 0)
 841                         /* Looks like MSR isn't present */
 842                         longhaul_version = TYPE_LONGHAUL_V1;
 843         }
 844 
 845         pr_info("VIA %s CPU detected.  ", cpuname);
 846         switch (longhaul_version) {
 847         case TYPE_LONGHAUL_V1:
 848         case TYPE_LONGHAUL_V2:
 849                 pr_cont("Longhaul v%d supported\n", longhaul_version);
 850                 break;
 851         case TYPE_POWERSAVER:
 852                 pr_cont("Powersaver supported\n");
 853                 break;
 854         }
 855 
 856         /* Doesn't hurt */
 857         longhaul_setup_southbridge();
 858 
 859         /* Find ACPI data for processor */
 860         acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
 861                                 ACPI_UINT32_MAX, &longhaul_walk_callback, NULL,
 862                                 NULL, (void *)&pr);
 863 
 864         /* Check ACPI support for C3 state */
 865         if (pr != NULL && longhaul_version == TYPE_POWERSAVER) {
 866                 cx = &pr->power.states[ACPI_STATE_C3];
 867                 if (cx->address > 0 && cx->latency <= 1000)
 868                         longhaul_flags |= USE_ACPI_C3;
 869         }
 870         /* Disable if it isn't working */
 871         if (disable_acpi_c3)
 872                 longhaul_flags &= ~USE_ACPI_C3;
 873         /* Check if northbridge is friendly */
 874         if (enable_arbiter_disable())
 875                 longhaul_flags |= USE_NORTHBRIDGE;
 876 
 877         /* Check ACPI support for bus master arbiter disable */
 878         if (!(longhaul_flags & USE_ACPI_C3
 879              || longhaul_flags & USE_NORTHBRIDGE)
 880             && ((pr == NULL) || !(pr->flags.bm_control))) {
 881                 pr_err("No ACPI support: Unsupported northbridge\n");
 882                 return -ENODEV;
 883         }
 884 
 885         if (longhaul_flags & USE_NORTHBRIDGE)
 886                 pr_info("Using northbridge support\n");
 887         if (longhaul_flags & USE_ACPI_C3)
 888                 pr_info("Using ACPI support\n");
 889 
 890         ret = longhaul_get_ranges();
 891         if (ret != 0)
 892                 return ret;
 893 
 894         if ((longhaul_version != TYPE_LONGHAUL_V1) && (scale_voltage != 0))
 895                 longhaul_setup_voltagescaling();
 896 
 897         policy->transition_delay_us = 200000;   /* usec */
 898         policy->freq_table = longhaul_table;
 899 
 900         return 0;
 901 }
 902 
 903 static struct cpufreq_driver longhaul_driver = {
 904         .verify = cpufreq_generic_frequency_table_verify,
 905         .target_index = longhaul_target,
 906         .get    = longhaul_get,
 907         .init   = longhaul_cpu_init,
 908         .name   = "longhaul",
 909         .attr   = cpufreq_generic_attr,
 910 };
 911 
 912 static const struct x86_cpu_id longhaul_id[] = {
 913         { X86_VENDOR_CENTAUR, 6 },
 914         {}
 915 };
 916 MODULE_DEVICE_TABLE(x86cpu, longhaul_id);
 917 
 918 static int __init longhaul_init(void)
 919 {
 920         struct cpuinfo_x86 *c = &cpu_data(0);
 921 
 922         if (!x86_match_cpu(longhaul_id))
 923                 return -ENODEV;
 924 
 925         if (!enable) {
 926                 pr_err("Option \"enable\" not set - Aborting\n");
 927                 return -ENODEV;
 928         }
 929 #ifdef CONFIG_SMP
 930         if (num_online_cpus() > 1) {
 931                 pr_err("More than 1 CPU detected, longhaul disabled\n");
 932                 return -ENODEV;
 933         }
 934 #endif
 935 #ifdef CONFIG_X86_IO_APIC
 936         if (boot_cpu_has(X86_FEATURE_APIC)) {
 937                 pr_err("APIC detected. Longhaul is currently broken in this configuration.\n");
 938                 return -ENODEV;
 939         }
 940 #endif
 941         switch (c->x86_model) {
 942         case 6 ... 9:
 943                 return cpufreq_register_driver(&longhaul_driver);
 944         case 10:
 945                 pr_err("Use acpi-cpufreq driver for VIA C7\n");
 946         default:
 947                 ;
 948         }
 949 
 950         return -ENODEV;
 951 }
 952 
 953 
 954 static void __exit longhaul_exit(void)
 955 {
 956         struct cpufreq_policy *policy = cpufreq_cpu_get(0);
 957         int i;
 958 
 959         for (i = 0; i < numscales; i++) {
 960                 if (mults[i] == maxmult) {
 961                         struct cpufreq_freqs freqs;
 962 
 963                         freqs.old = policy->cur;
 964                         freqs.new = longhaul_table[i].frequency;
 965                         freqs.flags = 0;
 966 
 967                         cpufreq_freq_transition_begin(policy, &freqs);
 968                         longhaul_setstate(policy, i);
 969                         cpufreq_freq_transition_end(policy, &freqs, 0);
 970                         break;
 971                 }
 972         }
 973 
 974         cpufreq_cpu_put(policy);
 975         cpufreq_unregister_driver(&longhaul_driver);
 976         kfree(longhaul_table);
 977 }
 978 
 979 /* Even if BIOS is exporting ACPI C3 state, and it is used
 980  * with success when CPU is idle, this state doesn't
 981  * trigger frequency transition in some cases. */
 982 module_param(disable_acpi_c3, int, 0644);
 983 MODULE_PARM_DESC(disable_acpi_c3, "Don't use ACPI C3 support");
 984 /* Change CPU voltage with frequency. Very useful to save
 985  * power, but most VIA C3 processors aren't supporting it. */
 986 module_param(scale_voltage, int, 0644);
 987 MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor");
 988 /* Force revision key to 0 for processors which doesn't
 989  * support voltage scaling, but are introducing itself as
 990  * such. */
 991 module_param(revid_errata, int, 0644);
 992 MODULE_PARM_DESC(revid_errata, "Ignore CPU Revision ID");
 993 /* By default driver is disabled to prevent incompatible
 994  * system freeze. */
 995 module_param(enable, int, 0644);
 996 MODULE_PARM_DESC(enable, "Enable driver");
 997 
 998 MODULE_AUTHOR("Dave Jones");
 999 MODULE_DESCRIPTION("Longhaul driver for VIA Cyrix processors.");
1000 MODULE_LICENSE("GPL");
1001 
1002 late_initcall(longhaul_init);
1003 module_exit(longhaul_exit);

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