0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
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
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;
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
0077 static int scale_voltage;
0078 static int disable_acpi_c3;
0079 static int revid_errata;
0080 static int enable;
0081
0082
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
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
0141 bcr2.bits.ESOFTBF = 1;
0142 bcr2.bits.CLOCKMUL = mults_index & 0xff;
0143
0144
0145 safe_halt();
0146
0147 wrmsrl(MSR_VIA_BCR2, bcr2.val);
0148
0149 ACPI_FLUSH_CPU_CACHE();
0150 halt();
0151
0152
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
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
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
0176 if (can_scale_voltage)
0177 longhaul.bits.SoftVID = (mults_index >> 8) & 0x1f;
0178
0179 safe_halt();
0180
0181 if (can_scale_voltage && dir) {
0182 longhaul.bits.EnableSoftVID = 1;
0183 wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
0184
0185 if (!cx_address) {
0186 ACPI_FLUSH_CPU_CACHE();
0187 halt();
0188 } else {
0189 ACPI_FLUSH_CPU_CACHE();
0190
0191 inb(cx_address);
0192
0193
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
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
0209 inb(cx_address);
0210
0211 t = inl(acpi_gbl_FADT.xpm_timer_block.address);
0212 }
0213
0214 longhaul.bits.EnableSoftBusRatio = 0;
0215 wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
0216
0217
0218 if (can_scale_voltage && !dir) {
0219 longhaul.bits.EnableSoftVID = 1;
0220 wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
0221
0222 if (!cx_address) {
0223 ACPI_FLUSH_CPU_CACHE();
0224 halt();
0225 } else {
0226 ACPI_FLUSH_CPU_CACHE();
0227
0228 inb(cx_address);
0229
0230
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
0240
0241
0242
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
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
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);
0282 outb(0xFF, 0xA1);
0283 outb(0xFE, 0x21);
0284
0285
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
0300 outb(3, 0x22);
0301 } else if ((pr != NULL) && pr->flags.bm_control) {
0302
0303 acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 1);
0304 }
0305 switch (longhaul_version) {
0306
0307
0308
0309
0310
0311 case TYPE_LONGHAUL_V1:
0312 do_longhaul1(mults_index);
0313 break;
0314
0315
0316
0317
0318
0319
0320
0321
0322 case TYPE_LONGHAUL_V2:
0323 case TYPE_POWERSAVER:
0324 if (longhaul_flags & USE_ACPI_C3) {
0325
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
0336 outb(0, 0x22);
0337 } else if ((pr != NULL) && pr->flags.bm_control) {
0338
0339 acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 0);
0340 }
0341 outb(pic2_mask, 0xA1);
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
0349 if (unlikely(freqs.new != speed)) {
0350 pr_info("Failed to set requested frequency!\n");
0351
0352
0353
0354
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
0362
0363
0364
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
0376
0377
0378
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
0397
0398
0399
0400
0401
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
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
0442
0443
0444 maxmult = mult;
0445
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
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
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
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
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
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
0631
0632
0633
0634
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
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
0689 reg = 0x78;
0690 dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8601_0,
0691 NULL);
0692
0693 if (dev == NULL)
0694 dev = pci_get_device(PCI_VENDOR_ID_VIA,
0695 PCI_DEVICE_ID_VIA_8605_0, NULL);
0696
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
0702 if (dev == NULL)
0703 dev = pci_get_device(PCI_VENDOR_ID_VIA, 0x7259, NULL);
0704 }
0705 if (dev != NULL) {
0706
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
0729 dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, NULL);
0730 if (dev == NULL)
0731
0732 dev = pci_get_device(PCI_VENDOR_ID_VIA,
0733 PCI_DEVICE_ID_VIA_8237, NULL);
0734 if (dev != NULL) {
0735
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
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
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
0783
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
0837 if (longhaul_version == TYPE_LONGHAUL_V2) {
0838 rdmsr(MSR_VIA_LONGHAUL, lo, hi);
0839 if (lo == 0 && hi == 0)
0840
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
0856 longhaul_setup_southbridge();
0857
0858
0859 acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
0860 ACPI_UINT32_MAX, &longhaul_walk_callback, NULL,
0861 NULL, (void *)&pr);
0862
0863
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
0870 if (disable_acpi_c3)
0871 longhaul_flags &= ~USE_ACPI_C3;
0872
0873 if (enable_arbiter_disable())
0874 longhaul_flags |= USE_NORTHBRIDGE;
0875
0876
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;
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
0977
0978
0979 module_param(disable_acpi_c3, int, 0644);
0980 MODULE_PARM_DESC(disable_acpi_c3, "Don't use ACPI C3 support");
0981
0982
0983 module_param(scale_voltage, int, 0644);
0984 MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor");
0985
0986
0987
0988 module_param(revid_errata, int, 0644);
0989 MODULE_PARM_DESC(revid_errata, "Ignore CPU Revision ID");
0990
0991
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);