Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  (C) 2001-2004  Dave Jones.
0004  *  (C) 2002  Padraig Brady. <padraig@antefacto.com>
0005  *
0006  *  Based upon datasheets & sample CPUs kindly provided by VIA.
0007  *
0008  *  VIA have currently 3 different versions of Longhaul.
0009  *  Version 1 (Longhaul) uses the BCR2 MSR at 0x1147.
0010  *   It is present only in Samuel 1 (C5A), Samuel 2 (C5B) stepping 0.
0011  *  Version 2 of longhaul is backward compatible with v1, but adds
0012  *   LONGHAUL MSR for purpose of both frequency and voltage scaling.
0013  *   Present in Samuel 2 (steppings 1-7 only) (C5B), and Ezra (C5C).
0014  *  Version 3 of longhaul got renamed to Powersaver and redesigned
0015  *   to use only the POWERSAVER MSR at 0x110a.
0016  *   It is present in Ezra-T (C5M), Nehemiah (C5X) and above.
0017  *   It's pretty much the same feature wise to longhaul v2, though
0018  *   there is provision for scaling FSB too, but this doesn't work
0019  *   too well in practice so we don't even try to use this.
0020  *
0021  *  BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
0022  */
0023 
0024 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0025 
0026 #include <linux/kernel.h>
0027 #include <linux/module.h>
0028 #include <linux/moduleparam.h>
0029 #include <linux/init.h>
0030 #include <linux/cpufreq.h>
0031 #include <linux/pci.h>
0032 #include <linux/slab.h>
0033 #include <linux/string.h>
0034 #include <linux/delay.h>
0035 #include <linux/timex.h>
0036 #include <linux/io.h>
0037 #include <linux/acpi.h>
0038 
0039 #include <asm/msr.h>
0040 #include <asm/cpu_device_id.h>
0041 #include <acpi/processor.h>
0042 
0043 #include "longhaul.h"
0044 
0045 #define TYPE_LONGHAUL_V1    1
0046 #define TYPE_LONGHAUL_V2    2
0047 #define TYPE_POWERSAVER     3
0048 
0049 #define CPU_SAMUEL  1
0050 #define CPU_SAMUEL2 2
0051 #define CPU_EZRA    3
0052 #define CPU_EZRA_T  4
0053 #define CPU_NEHEMIAH    5
0054 #define CPU_NEHEMIAH_C  6
0055 
0056 /* Flags */
0057 #define USE_ACPI_C3     (1 << 1)
0058 #define USE_NORTHBRIDGE     (1 << 2)
0059 
0060 static int cpu_model;
0061 static unsigned int numscales = 16;
0062 static unsigned int fsb;
0063 
0064 static const struct mV_pos *vrm_mV_table;
0065 static const unsigned char *mV_vrm_table;
0066 
0067 static unsigned int highest_speed, lowest_speed; /* kHz */
0068 static unsigned int minmult, maxmult;
0069 static int can_scale_voltage;
0070 static struct acpi_processor *pr;
0071 static struct acpi_processor_cx *cx;
0072 static u32 acpi_regs_addr;
0073 static u8 longhaul_flags;
0074 static unsigned int longhaul_index;
0075 
0076 /* Module parameters */
0077 static int scale_voltage;
0078 static int disable_acpi_c3;
0079 static int revid_errata;
0080 static int enable;
0081 
0082 /* Clock ratios multiplied by 10 */
0083 static int mults[32];
0084 static int eblcr[32];
0085 static int longhaul_version;
0086 static struct cpufreq_frequency_table *longhaul_table;
0087 
0088 static char speedbuffer[8];
0089 
0090 static char *print_speed(int speed)
0091 {
0092     if (speed < 1000) {
0093         snprintf(speedbuffer, sizeof(speedbuffer), "%dMHz", speed);
0094         return speedbuffer;
0095     }
0096 
0097     if (speed%1000 == 0)
0098         snprintf(speedbuffer, sizeof(speedbuffer),
0099             "%dGHz", speed/1000);
0100     else
0101         snprintf(speedbuffer, sizeof(speedbuffer),
0102             "%d.%dGHz", speed/1000, (speed%1000)/100);
0103 
0104     return speedbuffer;
0105 }
0106 
0107 
0108 static unsigned int calc_speed(int mult)
0109 {
0110     int khz;
0111     khz = (mult/10)*fsb;
0112     if (mult%10)
0113         khz += fsb/2;
0114     khz *= 1000;
0115     return khz;
0116 }
0117 
0118 
0119 static int longhaul_get_cpu_mult(void)
0120 {
0121     unsigned long invalue = 0, lo, hi;
0122 
0123     rdmsr(MSR_IA32_EBL_CR_POWERON, lo, hi);
0124     invalue = (lo & (1<<22|1<<23|1<<24|1<<25))>>22;
0125     if (longhaul_version == TYPE_LONGHAUL_V2 ||
0126         longhaul_version == TYPE_POWERSAVER) {
0127         if (lo & (1<<27))
0128             invalue += 16;
0129     }
0130     return eblcr[invalue];
0131 }
0132 
0133 /* For processor with BCR2 MSR */
0134 
0135 static void do_longhaul1(unsigned int mults_index)
0136 {
0137     union msr_bcr2 bcr2;
0138 
0139     rdmsrl(MSR_VIA_BCR2, bcr2.val);
0140     /* Enable software clock multiplier */
0141     bcr2.bits.ESOFTBF = 1;
0142     bcr2.bits.CLOCKMUL = mults_index & 0xff;
0143 
0144     /* Sync to timer tick */
0145     safe_halt();
0146     /* Change frequency on next halt or sleep */
0147     wrmsrl(MSR_VIA_BCR2, bcr2.val);
0148     /* Invoke transition */
0149     ACPI_FLUSH_CPU_CACHE();
0150     halt();
0151 
0152     /* Disable software clock multiplier */
0153     local_irq_disable();
0154     rdmsrl(MSR_VIA_BCR2, bcr2.val);
0155     bcr2.bits.ESOFTBF = 0;
0156     wrmsrl(MSR_VIA_BCR2, bcr2.val);
0157 }
0158 
0159 /* For processor with Longhaul MSR */
0160 
0161 static void do_powersaver(int cx_address, unsigned int mults_index,
0162               unsigned int dir)
0163 {
0164     union msr_longhaul longhaul;
0165     u32 t;
0166 
0167     rdmsrl(MSR_VIA_LONGHAUL, longhaul.val);
0168     /* Setup new frequency */
0169     if (!revid_errata)
0170         longhaul.bits.RevisionKey = longhaul.bits.RevisionID;
0171     else
0172         longhaul.bits.RevisionKey = 0;
0173     longhaul.bits.SoftBusRatio = mults_index & 0xf;
0174     longhaul.bits.SoftBusRatio4 = (mults_index & 0x10) >> 4;
0175     /* Setup new voltage */
0176     if (can_scale_voltage)
0177         longhaul.bits.SoftVID = (mults_index >> 8) & 0x1f;
0178     /* Sync to timer tick */
0179     safe_halt();
0180     /* Raise voltage if necessary */
0181     if (can_scale_voltage && dir) {
0182         longhaul.bits.EnableSoftVID = 1;
0183         wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
0184         /* Change voltage */
0185         if (!cx_address) {
0186             ACPI_FLUSH_CPU_CACHE();
0187             halt();
0188         } else {
0189             ACPI_FLUSH_CPU_CACHE();
0190             /* Invoke C3 */
0191             inb(cx_address);
0192             /* Dummy op - must do something useless after P_LVL3
0193              * read */
0194             t = inl(acpi_gbl_FADT.xpm_timer_block.address);
0195         }
0196         longhaul.bits.EnableSoftVID = 0;
0197         wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
0198     }
0199 
0200     /* Change frequency on next halt or sleep */
0201     longhaul.bits.EnableSoftBusRatio = 1;
0202     wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
0203     if (!cx_address) {
0204         ACPI_FLUSH_CPU_CACHE();
0205         halt();
0206     } else {
0207         ACPI_FLUSH_CPU_CACHE();
0208         /* Invoke C3 */
0209         inb(cx_address);
0210         /* Dummy op - must do something useless after P_LVL3 read */
0211         t = inl(acpi_gbl_FADT.xpm_timer_block.address);
0212     }
0213     /* Disable bus ratio bit */
0214     longhaul.bits.EnableSoftBusRatio = 0;
0215     wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
0216 
0217     /* Reduce voltage if necessary */
0218     if (can_scale_voltage && !dir) {
0219         longhaul.bits.EnableSoftVID = 1;
0220         wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
0221         /* Change voltage */
0222         if (!cx_address) {
0223             ACPI_FLUSH_CPU_CACHE();
0224             halt();
0225         } else {
0226             ACPI_FLUSH_CPU_CACHE();
0227             /* Invoke C3 */
0228             inb(cx_address);
0229             /* Dummy op - must do something useless after P_LVL3
0230              * read */
0231             t = inl(acpi_gbl_FADT.xpm_timer_block.address);
0232         }
0233         longhaul.bits.EnableSoftVID = 0;
0234         wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
0235     }
0236 }
0237 
0238 /**
0239  * longhaul_set_cpu_frequency()
0240  * @mults_index : bitpattern of the new multiplier.
0241  *
0242  * Sets a new clock ratio.
0243  */
0244 
0245 static int longhaul_setstate(struct cpufreq_policy *policy,
0246         unsigned int table_index)
0247 {
0248     unsigned int mults_index;
0249     int speed, mult;
0250     struct cpufreq_freqs freqs;
0251     unsigned long flags;
0252     unsigned int pic1_mask, pic2_mask;
0253     u16 bm_status = 0;
0254     u32 bm_timeout = 1000;
0255     unsigned int dir = 0;
0256 
0257     mults_index = longhaul_table[table_index].driver_data;
0258     /* Safety precautions */
0259     mult = mults[mults_index & 0x1f];
0260     if (mult == -1)
0261         return -EINVAL;
0262 
0263     speed = calc_speed(mult);
0264     if ((speed > highest_speed) || (speed < lowest_speed))
0265         return -EINVAL;
0266 
0267     /* Voltage transition before frequency transition? */
0268     if (can_scale_voltage && longhaul_index < table_index)
0269         dir = 1;
0270 
0271     freqs.old = calc_speed(longhaul_get_cpu_mult());
0272     freqs.new = speed;
0273 
0274     pr_debug("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n",
0275             fsb, mult/10, mult%10, print_speed(speed/1000));
0276 retry_loop:
0277     preempt_disable();
0278     local_irq_save(flags);
0279 
0280     pic2_mask = inb(0xA1);
0281     pic1_mask = inb(0x21);  /* works on C3. save mask. */
0282     outb(0xFF, 0xA1);   /* Overkill */
0283     outb(0xFE, 0x21);   /* TMR0 only */
0284 
0285     /* Wait while PCI bus is busy. */
0286     if (acpi_regs_addr && (longhaul_flags & USE_NORTHBRIDGE
0287         || ((pr != NULL) && pr->flags.bm_control))) {
0288         bm_status = inw(acpi_regs_addr);
0289         bm_status &= 1 << 4;
0290         while (bm_status && bm_timeout) {
0291             outw(1 << 4, acpi_regs_addr);
0292             bm_timeout--;
0293             bm_status = inw(acpi_regs_addr);
0294             bm_status &= 1 << 4;
0295         }
0296     }
0297 
0298     if (longhaul_flags & USE_NORTHBRIDGE) {
0299         /* Disable AGP and PCI arbiters */
0300         outb(3, 0x22);
0301     } else if ((pr != NULL) && pr->flags.bm_control) {
0302         /* Disable bus master arbitration */
0303         acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 1);
0304     }
0305     switch (longhaul_version) {
0306 
0307     /*
0308      * Longhaul v1. (Samuel[C5A] and Samuel2 stepping 0[C5B])
0309      * Software controlled multipliers only.
0310      */
0311     case TYPE_LONGHAUL_V1:
0312         do_longhaul1(mults_index);
0313         break;
0314 
0315     /*
0316      * Longhaul v2 appears in Samuel2 Steppings 1->7 [C5B] and Ezra [C5C]
0317      *
0318      * Longhaul v3 (aka Powersaver). (Ezra-T [C5M] & Nehemiah [C5N])
0319      * Nehemiah can do FSB scaling too, but this has never been proven
0320      * to work in practice.
0321      */
0322     case TYPE_LONGHAUL_V2:
0323     case TYPE_POWERSAVER:
0324         if (longhaul_flags & USE_ACPI_C3) {
0325             /* Don't allow wakeup */
0326             acpi_write_bit_register(ACPI_BITREG_BUS_MASTER_RLD, 0);
0327             do_powersaver(cx->address, mults_index, dir);
0328         } else {
0329             do_powersaver(0, mults_index, dir);
0330         }
0331         break;
0332     }
0333 
0334     if (longhaul_flags & USE_NORTHBRIDGE) {
0335         /* Enable arbiters */
0336         outb(0, 0x22);
0337     } else if ((pr != NULL) && pr->flags.bm_control) {
0338         /* Enable bus master arbitration */
0339         acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 0);
0340     }
0341     outb(pic2_mask, 0xA1);  /* restore mask */
0342     outb(pic1_mask, 0x21);
0343 
0344     local_irq_restore(flags);
0345     preempt_enable();
0346 
0347     freqs.new = calc_speed(longhaul_get_cpu_mult());
0348     /* Check if requested frequency is set. */
0349     if (unlikely(freqs.new != speed)) {
0350         pr_info("Failed to set requested frequency!\n");
0351         /* Revision ID = 1 but processor is expecting revision key
0352          * equal to 0. Jumpers at the bottom of processor will change
0353          * multiplier and FSB, but will not change bits in Longhaul
0354          * MSR nor enable voltage scaling. */
0355         if (!revid_errata) {
0356             pr_info("Enabling \"Ignore Revision ID\" option\n");
0357             revid_errata = 1;
0358             msleep(200);
0359             goto retry_loop;
0360         }
0361         /* Why ACPI C3 sometimes doesn't work is a mystery for me.
0362          * But it does happen. Processor is entering ACPI C3 state,
0363          * but it doesn't change frequency. I tried poking various
0364          * bits in northbridge registers, but without success. */
0365         if (longhaul_flags & USE_ACPI_C3) {
0366             pr_info("Disabling ACPI C3 support\n");
0367             longhaul_flags &= ~USE_ACPI_C3;
0368             if (revid_errata) {
0369                 pr_info("Disabling \"Ignore Revision ID\" option\n");
0370                 revid_errata = 0;
0371             }
0372             msleep(200);
0373             goto retry_loop;
0374         }
0375         /* This shouldn't happen. Longhaul ver. 2 was reported not
0376          * working on processors without voltage scaling, but with
0377          * RevID = 1. RevID errata will make things right. Just
0378          * to be 100% sure. */
0379         if (longhaul_version == TYPE_LONGHAUL_V2) {
0380             pr_info("Switching to Longhaul ver. 1\n");
0381             longhaul_version = TYPE_LONGHAUL_V1;
0382             msleep(200);
0383             goto retry_loop;
0384         }
0385     }
0386 
0387     if (!bm_timeout) {
0388         pr_info("Warning: Timeout while waiting for idle PCI bus\n");
0389         return -EBUSY;
0390     }
0391 
0392     return 0;
0393 }
0394 
0395 /*
0396  * Centaur decided to make life a little more tricky.
0397  * Only longhaul v1 is allowed to read EBLCR BSEL[0:1].
0398  * Samuel2 and above have to try and guess what the FSB is.
0399  * We do this by assuming we booted at maximum multiplier, and interpolate
0400  * between that value multiplied by possible FSBs and cpu_mhz which
0401  * was calculated at boot time. Really ugly, but no other way to do this.
0402  */
0403 
0404 #define ROUNDING    0xf
0405 
0406 static int guess_fsb(int mult)
0407 {
0408     int speed = cpu_khz / 1000;
0409     int i;
0410     int speeds[] = { 666, 1000, 1333, 2000 };
0411     int f_max, f_min;
0412 
0413     for (i = 0; i < 4; i++) {
0414         f_max = ((speeds[i] * mult) + 50) / 100;
0415         f_max += (ROUNDING / 2);
0416         f_min = f_max - ROUNDING;
0417         if ((speed <= f_max) && (speed >= f_min))
0418             return speeds[i] / 10;
0419     }
0420     return 0;
0421 }
0422 
0423 
0424 static int longhaul_get_ranges(void)
0425 {
0426     unsigned int i, j, k = 0;
0427     unsigned int ratio;
0428     int mult;
0429 
0430     /* Get current frequency */
0431     mult = longhaul_get_cpu_mult();
0432     if (mult == -1) {
0433         pr_info("Invalid (reserved) multiplier!\n");
0434         return -EINVAL;
0435     }
0436     fsb = guess_fsb(mult);
0437     if (fsb == 0) {
0438         pr_info("Invalid (reserved) FSB!\n");
0439         return -EINVAL;
0440     }
0441     /* Get max multiplier - as we always did.
0442      * Longhaul MSR is useful only when voltage scaling is enabled.
0443      * C3 is booting at max anyway. */
0444     maxmult = mult;
0445     /* Get min multiplier */
0446     switch (cpu_model) {
0447     case CPU_NEHEMIAH:
0448         minmult = 50;
0449         break;
0450     case CPU_NEHEMIAH_C:
0451         minmult = 40;
0452         break;
0453     default:
0454         minmult = 30;
0455         break;
0456     }
0457 
0458     pr_debug("MinMult:%d.%dx MaxMult:%d.%dx\n",
0459          minmult/10, minmult%10, maxmult/10, maxmult%10);
0460 
0461     highest_speed = calc_speed(maxmult);
0462     lowest_speed = calc_speed(minmult);
0463     pr_debug("FSB:%dMHz  Lowest speed: %s   Highest speed:%s\n", fsb,
0464          print_speed(lowest_speed/1000),
0465          print_speed(highest_speed/1000));
0466 
0467     if (lowest_speed == highest_speed) {
0468         pr_info("highestspeed == lowest, aborting\n");
0469         return -EINVAL;
0470     }
0471     if (lowest_speed > highest_speed) {
0472         pr_info("nonsense! lowest (%d > %d) !\n",
0473             lowest_speed, highest_speed);
0474         return -EINVAL;
0475     }
0476 
0477     longhaul_table = kcalloc(numscales + 1, sizeof(*longhaul_table),
0478                  GFP_KERNEL);
0479     if (!longhaul_table)
0480         return -ENOMEM;
0481 
0482     for (j = 0; j < numscales; j++) {
0483         ratio = mults[j];
0484         if (ratio == -1)
0485             continue;
0486         if (ratio > maxmult || ratio < minmult)
0487             continue;
0488         longhaul_table[k].frequency = calc_speed(ratio);
0489         longhaul_table[k].driver_data   = j;
0490         k++;
0491     }
0492     if (k <= 1) {
0493         kfree(longhaul_table);
0494         return -ENODEV;
0495     }
0496     /* Sort */
0497     for (j = 0; j < k - 1; j++) {
0498         unsigned int min_f, min_i;
0499         min_f = longhaul_table[j].frequency;
0500         min_i = j;
0501         for (i = j + 1; i < k; i++) {
0502             if (longhaul_table[i].frequency < min_f) {
0503                 min_f = longhaul_table[i].frequency;
0504                 min_i = i;
0505             }
0506         }
0507         if (min_i != j) {
0508             swap(longhaul_table[j].frequency,
0509                  longhaul_table[min_i].frequency);
0510             swap(longhaul_table[j].driver_data,
0511                  longhaul_table[min_i].driver_data);
0512         }
0513     }
0514 
0515     longhaul_table[k].frequency = CPUFREQ_TABLE_END;
0516 
0517     /* Find index we are running on */
0518     for (j = 0; j < k; j++) {
0519         if (mults[longhaul_table[j].driver_data & 0x1f] == mult) {
0520             longhaul_index = j;
0521             break;
0522         }
0523     }
0524     return 0;
0525 }
0526 
0527 
0528 static void longhaul_setup_voltagescaling(void)
0529 {
0530     struct cpufreq_frequency_table *freq_pos;
0531     union msr_longhaul longhaul;
0532     struct mV_pos minvid, maxvid, vid;
0533     unsigned int j, speed, pos, kHz_step, numvscales;
0534     int min_vid_speed;
0535 
0536     rdmsrl(MSR_VIA_LONGHAUL, longhaul.val);
0537     if (!(longhaul.bits.RevisionID & 1)) {
0538         pr_info("Voltage scaling not supported by CPU\n");
0539         return;
0540     }
0541 
0542     if (!longhaul.bits.VRMRev) {
0543         pr_info("VRM 8.5\n");
0544         vrm_mV_table = &vrm85_mV[0];
0545         mV_vrm_table = &mV_vrm85[0];
0546     } else {
0547         pr_info("Mobile VRM\n");
0548         if (cpu_model < CPU_NEHEMIAH)
0549             return;
0550         vrm_mV_table = &mobilevrm_mV[0];
0551         mV_vrm_table = &mV_mobilevrm[0];
0552     }
0553 
0554     minvid = vrm_mV_table[longhaul.bits.MinimumVID];
0555     maxvid = vrm_mV_table[longhaul.bits.MaximumVID];
0556 
0557     if (minvid.mV == 0 || maxvid.mV == 0 || minvid.mV > maxvid.mV) {
0558         pr_info("Bogus values Min:%d.%03d Max:%d.%03d - Voltage scaling disabled\n",
0559             minvid.mV/1000, minvid.mV%1000,
0560             maxvid.mV/1000, maxvid.mV%1000);
0561         return;
0562     }
0563 
0564     if (minvid.mV == maxvid.mV) {
0565         pr_info("Claims to support voltage scaling but min & max are both %d.%03d - Voltage scaling disabled\n",
0566             maxvid.mV/1000, maxvid.mV%1000);
0567         return;
0568     }
0569 
0570     /* How many voltage steps*/
0571     numvscales = maxvid.pos - minvid.pos + 1;
0572     pr_info("Max VID=%d.%03d  Min VID=%d.%03d, %d possible voltage scales\n",
0573         maxvid.mV/1000, maxvid.mV%1000,
0574         minvid.mV/1000, minvid.mV%1000,
0575         numvscales);
0576 
0577     /* Calculate max frequency at min voltage */
0578     j = longhaul.bits.MinMHzBR;
0579     if (longhaul.bits.MinMHzBR4)
0580         j += 16;
0581     min_vid_speed = eblcr[j];
0582     if (min_vid_speed == -1)
0583         return;
0584     switch (longhaul.bits.MinMHzFSB) {
0585     case 0:
0586         min_vid_speed *= 13333;
0587         break;
0588     case 1:
0589         min_vid_speed *= 10000;
0590         break;
0591     case 3:
0592         min_vid_speed *= 6666;
0593         break;
0594     default:
0595         return;
0596     }
0597     if (min_vid_speed >= highest_speed)
0598         return;
0599     /* Calculate kHz for one voltage step */
0600     kHz_step = (highest_speed - min_vid_speed) / numvscales;
0601 
0602     cpufreq_for_each_entry_idx(freq_pos, longhaul_table, j) {
0603         speed = freq_pos->frequency;
0604         if (speed > min_vid_speed)
0605             pos = (speed - min_vid_speed) / kHz_step + minvid.pos;
0606         else
0607             pos = minvid.pos;
0608         freq_pos->driver_data |= mV_vrm_table[pos] << 8;
0609         vid = vrm_mV_table[mV_vrm_table[pos]];
0610         pr_info("f: %d kHz, index: %d, vid: %d mV\n",
0611             speed, j, vid.mV);
0612     }
0613 
0614     can_scale_voltage = 1;
0615     pr_info("Voltage scaling enabled\n");
0616 }
0617 
0618 
0619 static int longhaul_target(struct cpufreq_policy *policy,
0620                 unsigned int table_index)
0621 {
0622     unsigned int i;
0623     unsigned int dir = 0;
0624     u8 vid, current_vid;
0625     int retval = 0;
0626 
0627     if (!can_scale_voltage)
0628         retval = longhaul_setstate(policy, table_index);
0629     else {
0630         /* On test system voltage transitions exceeding single
0631          * step up or down were turning motherboard off. Both
0632          * "ondemand" and "userspace" are unsafe. C7 is doing
0633          * this in hardware, C3 is old and we need to do this
0634          * in software. */
0635         i = longhaul_index;
0636         current_vid = (longhaul_table[longhaul_index].driver_data >> 8);
0637         current_vid &= 0x1f;
0638         if (table_index > longhaul_index)
0639             dir = 1;
0640         while (i != table_index) {
0641             vid = (longhaul_table[i].driver_data >> 8) & 0x1f;
0642             if (vid != current_vid) {
0643                 retval = longhaul_setstate(policy, i);
0644                 current_vid = vid;
0645                 msleep(200);
0646             }
0647             if (dir)
0648                 i++;
0649             else
0650                 i--;
0651         }
0652         retval = longhaul_setstate(policy, table_index);
0653     }
0654 
0655     longhaul_index = table_index;
0656     return retval;
0657 }
0658 
0659 
0660 static unsigned int longhaul_get(unsigned int cpu)
0661 {
0662     if (cpu)
0663         return 0;
0664     return calc_speed(longhaul_get_cpu_mult());
0665 }
0666 
0667 static acpi_status longhaul_walk_callback(acpi_handle obj_handle,
0668                       u32 nesting_level,
0669                       void *context, void **return_value)
0670 {
0671     struct acpi_device *d = acpi_fetch_acpi_dev(obj_handle);
0672 
0673     if (!d)
0674         return 0;
0675 
0676     *return_value = acpi_driver_data(d);
0677     return 1;
0678 }
0679 
0680 /* VIA don't support PM2 reg, but have something similar */
0681 static int enable_arbiter_disable(void)
0682 {
0683     struct pci_dev *dev;
0684     int status = 1;
0685     int reg;
0686     u8 pci_cmd;
0687 
0688     /* Find PLE133 host bridge */
0689     reg = 0x78;
0690     dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8601_0,
0691                  NULL);
0692     /* Find PM133/VT8605 host bridge */
0693     if (dev == NULL)
0694         dev = pci_get_device(PCI_VENDOR_ID_VIA,
0695                      PCI_DEVICE_ID_VIA_8605_0, NULL);
0696     /* Find CLE266 host bridge */
0697     if (dev == NULL) {
0698         reg = 0x76;
0699         dev = pci_get_device(PCI_VENDOR_ID_VIA,
0700                      PCI_DEVICE_ID_VIA_862X_0, NULL);
0701         /* Find CN400 V-Link host bridge */
0702         if (dev == NULL)
0703             dev = pci_get_device(PCI_VENDOR_ID_VIA, 0x7259, NULL);
0704     }
0705     if (dev != NULL) {
0706         /* Enable access to port 0x22 */
0707         pci_read_config_byte(dev, reg, &pci_cmd);
0708         if (!(pci_cmd & 1<<7)) {
0709             pci_cmd |= 1<<7;
0710             pci_write_config_byte(dev, reg, pci_cmd);
0711             pci_read_config_byte(dev, reg, &pci_cmd);
0712             if (!(pci_cmd & 1<<7)) {
0713                 pr_err("Can't enable access to port 0x22\n");
0714                 status = 0;
0715             }
0716         }
0717         pci_dev_put(dev);
0718         return status;
0719     }
0720     return 0;
0721 }
0722 
0723 static int longhaul_setup_southbridge(void)
0724 {
0725     struct pci_dev *dev;
0726     u8 pci_cmd;
0727 
0728     /* Find VT8235 southbridge */
0729     dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, NULL);
0730     if (dev == NULL)
0731         /* Find VT8237 southbridge */
0732         dev = pci_get_device(PCI_VENDOR_ID_VIA,
0733                      PCI_DEVICE_ID_VIA_8237, NULL);
0734     if (dev != NULL) {
0735         /* Set transition time to max */
0736         pci_read_config_byte(dev, 0xec, &pci_cmd);
0737         pci_cmd &= ~(1 << 2);
0738         pci_write_config_byte(dev, 0xec, pci_cmd);
0739         pci_read_config_byte(dev, 0xe4, &pci_cmd);
0740         pci_cmd &= ~(1 << 7);
0741         pci_write_config_byte(dev, 0xe4, pci_cmd);
0742         pci_read_config_byte(dev, 0xe5, &pci_cmd);
0743         pci_cmd |= 1 << 7;
0744         pci_write_config_byte(dev, 0xe5, pci_cmd);
0745         /* Get address of ACPI registers block*/
0746         pci_read_config_byte(dev, 0x81, &pci_cmd);
0747         if (pci_cmd & 1 << 7) {
0748             pci_read_config_dword(dev, 0x88, &acpi_regs_addr);
0749             acpi_regs_addr &= 0xff00;
0750             pr_info("ACPI I/O at 0x%x\n", acpi_regs_addr);
0751         }
0752 
0753         pci_dev_put(dev);
0754         return 1;
0755     }
0756     return 0;
0757 }
0758 
0759 static int longhaul_cpu_init(struct cpufreq_policy *policy)
0760 {
0761     struct cpuinfo_x86 *c = &cpu_data(0);
0762     char *cpuname = NULL;
0763     int ret;
0764     u32 lo, hi;
0765 
0766     /* Check what we have on this motherboard */
0767     switch (c->x86_model) {
0768     case 6:
0769         cpu_model = CPU_SAMUEL;
0770         cpuname = "C3 'Samuel' [C5A]";
0771         longhaul_version = TYPE_LONGHAUL_V1;
0772         memcpy(mults, samuel1_mults, sizeof(samuel1_mults));
0773         memcpy(eblcr, samuel1_eblcr, sizeof(samuel1_eblcr));
0774         break;
0775 
0776     case 7:
0777         switch (c->x86_stepping) {
0778         case 0:
0779             longhaul_version = TYPE_LONGHAUL_V1;
0780             cpu_model = CPU_SAMUEL2;
0781             cpuname = "C3 'Samuel 2' [C5B]";
0782             /* Note, this is not a typo, early Samuel2's had
0783              * Samuel1 ratios. */
0784             memcpy(mults, samuel1_mults, sizeof(samuel1_mults));
0785             memcpy(eblcr, samuel2_eblcr, sizeof(samuel2_eblcr));
0786             break;
0787         case 1 ... 15:
0788             longhaul_version = TYPE_LONGHAUL_V2;
0789             if (c->x86_stepping < 8) {
0790                 cpu_model = CPU_SAMUEL2;
0791                 cpuname = "C3 'Samuel 2' [C5B]";
0792             } else {
0793                 cpu_model = CPU_EZRA;
0794                 cpuname = "C3 'Ezra' [C5C]";
0795             }
0796             memcpy(mults, ezra_mults, sizeof(ezra_mults));
0797             memcpy(eblcr, ezra_eblcr, sizeof(ezra_eblcr));
0798             break;
0799         }
0800         break;
0801 
0802     case 8:
0803         cpu_model = CPU_EZRA_T;
0804         cpuname = "C3 'Ezra-T' [C5M]";
0805         longhaul_version = TYPE_POWERSAVER;
0806         numscales = 32;
0807         memcpy(mults, ezrat_mults, sizeof(ezrat_mults));
0808         memcpy(eblcr, ezrat_eblcr, sizeof(ezrat_eblcr));
0809         break;
0810 
0811     case 9:
0812         longhaul_version = TYPE_POWERSAVER;
0813         numscales = 32;
0814         memcpy(mults, nehemiah_mults, sizeof(nehemiah_mults));
0815         memcpy(eblcr, nehemiah_eblcr, sizeof(nehemiah_eblcr));
0816         switch (c->x86_stepping) {
0817         case 0 ... 1:
0818             cpu_model = CPU_NEHEMIAH;
0819             cpuname = "C3 'Nehemiah A' [C5XLOE]";
0820             break;
0821         case 2 ... 4:
0822             cpu_model = CPU_NEHEMIAH;
0823             cpuname = "C3 'Nehemiah B' [C5XLOH]";
0824             break;
0825         case 5 ... 15:
0826             cpu_model = CPU_NEHEMIAH_C;
0827             cpuname = "C3 'Nehemiah C' [C5P]";
0828             break;
0829         }
0830         break;
0831 
0832     default:
0833         cpuname = "Unknown";
0834         break;
0835     }
0836     /* Check Longhaul ver. 2 */
0837     if (longhaul_version == TYPE_LONGHAUL_V2) {
0838         rdmsr(MSR_VIA_LONGHAUL, lo, hi);
0839         if (lo == 0 && hi == 0)
0840             /* Looks like MSR isn't present */
0841             longhaul_version = TYPE_LONGHAUL_V1;
0842     }
0843 
0844     pr_info("VIA %s CPU detected.  ", cpuname);
0845     switch (longhaul_version) {
0846     case TYPE_LONGHAUL_V1:
0847     case TYPE_LONGHAUL_V2:
0848         pr_cont("Longhaul v%d supported\n", longhaul_version);
0849         break;
0850     case TYPE_POWERSAVER:
0851         pr_cont("Powersaver supported\n");
0852         break;
0853     }
0854 
0855     /* Doesn't hurt */
0856     longhaul_setup_southbridge();
0857 
0858     /* Find ACPI data for processor */
0859     acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
0860                 ACPI_UINT32_MAX, &longhaul_walk_callback, NULL,
0861                 NULL, (void *)&pr);
0862 
0863     /* Check ACPI support for C3 state */
0864     if (pr != NULL && longhaul_version == TYPE_POWERSAVER) {
0865         cx = &pr->power.states[ACPI_STATE_C3];
0866         if (cx->address > 0 && cx->latency <= 1000)
0867             longhaul_flags |= USE_ACPI_C3;
0868     }
0869     /* Disable if it isn't working */
0870     if (disable_acpi_c3)
0871         longhaul_flags &= ~USE_ACPI_C3;
0872     /* Check if northbridge is friendly */
0873     if (enable_arbiter_disable())
0874         longhaul_flags |= USE_NORTHBRIDGE;
0875 
0876     /* Check ACPI support for bus master arbiter disable */
0877     if (!(longhaul_flags & USE_ACPI_C3
0878          || longhaul_flags & USE_NORTHBRIDGE)
0879         && ((pr == NULL) || !(pr->flags.bm_control))) {
0880         pr_err("No ACPI support: Unsupported northbridge\n");
0881         return -ENODEV;
0882     }
0883 
0884     if (longhaul_flags & USE_NORTHBRIDGE)
0885         pr_info("Using northbridge support\n");
0886     if (longhaul_flags & USE_ACPI_C3)
0887         pr_info("Using ACPI support\n");
0888 
0889     ret = longhaul_get_ranges();
0890     if (ret != 0)
0891         return ret;
0892 
0893     if ((longhaul_version != TYPE_LONGHAUL_V1) && (scale_voltage != 0))
0894         longhaul_setup_voltagescaling();
0895 
0896     policy->transition_delay_us = 200000;   /* usec */
0897     policy->freq_table = longhaul_table;
0898 
0899     return 0;
0900 }
0901 
0902 static struct cpufreq_driver longhaul_driver = {
0903     .verify = cpufreq_generic_frequency_table_verify,
0904     .target_index = longhaul_target,
0905     .get    = longhaul_get,
0906     .init   = longhaul_cpu_init,
0907     .name   = "longhaul",
0908     .attr   = cpufreq_generic_attr,
0909 };
0910 
0911 static const struct x86_cpu_id longhaul_id[] = {
0912     X86_MATCH_VENDOR_FAM(CENTAUR, 6, NULL),
0913     {}
0914 };
0915 MODULE_DEVICE_TABLE(x86cpu, longhaul_id);
0916 
0917 static int __init longhaul_init(void)
0918 {
0919     struct cpuinfo_x86 *c = &cpu_data(0);
0920 
0921     if (!x86_match_cpu(longhaul_id))
0922         return -ENODEV;
0923 
0924     if (!enable) {
0925         pr_err("Option \"enable\" not set - Aborting\n");
0926         return -ENODEV;
0927     }
0928 #ifdef CONFIG_SMP
0929     if (num_online_cpus() > 1) {
0930         pr_err("More than 1 CPU detected, longhaul disabled\n");
0931         return -ENODEV;
0932     }
0933 #endif
0934 #ifdef CONFIG_X86_IO_APIC
0935     if (boot_cpu_has(X86_FEATURE_APIC)) {
0936         pr_err("APIC detected. Longhaul is currently broken in this configuration.\n");
0937         return -ENODEV;
0938     }
0939 #endif
0940     switch (c->x86_model) {
0941     case 6 ... 9:
0942         return cpufreq_register_driver(&longhaul_driver);
0943     case 10:
0944         pr_err("Use acpi-cpufreq driver for VIA C7\n");
0945     }
0946 
0947     return -ENODEV;
0948 }
0949 
0950 
0951 static void __exit longhaul_exit(void)
0952 {
0953     struct cpufreq_policy *policy = cpufreq_cpu_get(0);
0954     int i;
0955 
0956     for (i = 0; i < numscales; i++) {
0957         if (mults[i] == maxmult) {
0958             struct cpufreq_freqs freqs;
0959 
0960             freqs.old = policy->cur;
0961             freqs.new = longhaul_table[i].frequency;
0962             freqs.flags = 0;
0963 
0964             cpufreq_freq_transition_begin(policy, &freqs);
0965             longhaul_setstate(policy, i);
0966             cpufreq_freq_transition_end(policy, &freqs, 0);
0967             break;
0968         }
0969     }
0970 
0971     cpufreq_cpu_put(policy);
0972     cpufreq_unregister_driver(&longhaul_driver);
0973     kfree(longhaul_table);
0974 }
0975 
0976 /* Even if BIOS is exporting ACPI C3 state, and it is used
0977  * with success when CPU is idle, this state doesn't
0978  * trigger frequency transition in some cases. */
0979 module_param(disable_acpi_c3, int, 0644);
0980 MODULE_PARM_DESC(disable_acpi_c3, "Don't use ACPI C3 support");
0981 /* Change CPU voltage with frequency. Very useful to save
0982  * power, but most VIA C3 processors aren't supporting it. */
0983 module_param(scale_voltage, int, 0644);
0984 MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor");
0985 /* Force revision key to 0 for processors which doesn't
0986  * support voltage scaling, but are introducing itself as
0987  * such. */
0988 module_param(revid_errata, int, 0644);
0989 MODULE_PARM_DESC(revid_errata, "Ignore CPU Revision ID");
0990 /* By default driver is disabled to prevent incompatible
0991  * system freeze. */
0992 module_param(enable, int, 0644);
0993 MODULE_PARM_DESC(enable, "Enable driver");
0994 
0995 MODULE_AUTHOR("Dave Jones");
0996 MODULE_DESCRIPTION("Longhaul driver for VIA Cyrix processors.");
0997 MODULE_LICENSE("GPL");
0998 
0999 late_initcall(longhaul_init);
1000 module_exit(longhaul_exit);