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