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