2 * (C) 2001-2004 Dave Jones. <davej@codemonkey.org.uk>
3 * (C) 2002 Padraig Brady. <padraig@antefacto.com>
5 * Licensed under the terms of the GNU GPL License version 2.
6 * Based upon datasheets & sample CPUs kindly provided by VIA.
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.
21 * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
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>
35 #include <asm/timex.h>
38 #include <linux/acpi.h>
39 #include <acpi/processor.h>
43 #define PFX "longhaul: "
45 #define TYPE_LONGHAUL_V1 1
46 #define TYPE_LONGHAUL_V2 2
47 #define TYPE_POWERSAVER 3
53 #define CPU_NEHEMIAH 5
54 #define CPU_NEHEMIAH_C 6
57 #define USE_ACPI_C3 (1 << 1)
58 #define USE_NORTHBRIDGE (1 << 2)
61 static unsigned int numscales=16;
62 static unsigned int fsb;
64 static const struct mV_pos *vrm_mV_table;
65 static const unsigned char *mV_vrm_table;
67 static unsigned int highest_speed, lowest_speed; /* kHz */
68 static unsigned int minmult, maxmult;
69 static int can_scale_voltage;
70 static struct acpi_processor *pr = NULL;
71 static struct acpi_processor_cx *cx = NULL;
72 static u32 acpi_regs_addr;
73 static u8 longhaul_flags;
74 static unsigned int longhaul_index;
76 /* Module parameters */
77 static int scale_voltage;
79 #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg)
82 /* Clock ratios multiplied by 10 */
83 static int clock_ratio[32];
84 static int eblcr_table[32];
85 static int longhaul_version;
86 static struct cpufreq_frequency_table *longhaul_table;
88 #ifdef CONFIG_CPU_FREQ_DEBUG
89 static char speedbuffer[8];
91 static char *print_speed(int speed)
94 snprintf(speedbuffer, sizeof(speedbuffer),"%dMHz", speed);
99 snprintf(speedbuffer, sizeof(speedbuffer),
100 "%dGHz", speed/1000);
102 snprintf(speedbuffer, sizeof(speedbuffer),
103 "%d.%dGHz", speed/1000, (speed%1000)/100);
110 static unsigned int calc_speed(int mult)
121 static int longhaul_get_cpu_mult(void)
123 unsigned long invalue=0,lo, hi;
125 rdmsr (MSR_IA32_EBL_CR_POWERON, lo, hi);
126 invalue = (lo & (1<<22|1<<23|1<<24|1<<25)) >>22;
127 if (longhaul_version==TYPE_LONGHAUL_V2 || longhaul_version==TYPE_POWERSAVER) {
131 return eblcr_table[invalue];
134 /* For processor with BCR2 MSR */
136 static void do_longhaul1(unsigned int clock_ratio_index)
140 rdmsrl(MSR_VIA_BCR2, bcr2.val);
141 /* Enable software clock multiplier */
142 bcr2.bits.ESOFTBF = 1;
143 bcr2.bits.CLOCKMUL = clock_ratio_index & 0xff;
145 /* Sync to timer tick */
147 /* Change frequency on next halt or sleep */
148 wrmsrl(MSR_VIA_BCR2, bcr2.val);
149 /* Invoke transition */
150 ACPI_FLUSH_CPU_CACHE();
153 /* Disable software clock multiplier */
155 rdmsrl(MSR_VIA_BCR2, bcr2.val);
156 bcr2.bits.ESOFTBF = 0;
157 wrmsrl(MSR_VIA_BCR2, bcr2.val);
160 /* For processor with Longhaul MSR */
162 static void do_powersaver(int cx_address, unsigned int clock_ratio_index,
165 union msr_longhaul longhaul;
168 rdmsrl(MSR_VIA_LONGHAUL, longhaul.val);
169 /* Setup new frequency */
170 longhaul.bits.RevisionKey = longhaul.bits.RevisionID;
171 longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf;
172 longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
173 /* Setup new voltage */
174 if (can_scale_voltage)
175 longhaul.bits.SoftVID = (clock_ratio_index >> 8) & 0x1f;
176 /* Sync to timer tick */
178 /* Raise voltage if necessary */
179 if (can_scale_voltage && dir) {
180 longhaul.bits.EnableSoftVID = 1;
181 wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
184 ACPI_FLUSH_CPU_CACHE();
187 ACPI_FLUSH_CPU_CACHE();
190 /* Dummy op - must do something useless after P_LVL3
192 t = inl(acpi_gbl_FADT.xpm_timer_block.address);
194 longhaul.bits.EnableSoftVID = 0;
195 wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
198 /* Change frequency on next halt or sleep */
199 longhaul.bits.EnableSoftBusRatio = 1;
200 wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
202 ACPI_FLUSH_CPU_CACHE();
205 ACPI_FLUSH_CPU_CACHE();
208 /* Dummy op - must do something useless after P_LVL3 read */
209 t = inl(acpi_gbl_FADT.xpm_timer_block.address);
211 /* Disable bus ratio bit */
212 longhaul.bits.EnableSoftBusRatio = 0;
213 wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
215 /* Reduce voltage if necessary */
216 if (can_scale_voltage && !dir) {
217 longhaul.bits.EnableSoftVID = 1;
218 wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
221 ACPI_FLUSH_CPU_CACHE();
224 ACPI_FLUSH_CPU_CACHE();
227 /* Dummy op - must do something useless after P_LVL3
229 t = inl(acpi_gbl_FADT.xpm_timer_block.address);
231 longhaul.bits.EnableSoftVID = 0;
232 wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
237 * longhaul_set_cpu_frequency()
238 * @clock_ratio_index : bitpattern of the new multiplier.
240 * Sets a new clock ratio.
243 static void longhaul_setstate(unsigned int table_index)
245 unsigned int clock_ratio_index;
247 struct cpufreq_freqs freqs;
249 unsigned int pic1_mask, pic2_mask;
251 u32 bm_timeout = 1000;
252 unsigned int dir = 0;
254 clock_ratio_index = longhaul_table[table_index].index;
255 /* Safety precautions */
256 mult = clock_ratio[clock_ratio_index & 0x1f];
259 speed = calc_speed(mult);
260 if ((speed > highest_speed) || (speed < lowest_speed))
262 /* Voltage transition before frequency transition? */
263 if (can_scale_voltage && longhaul_index < table_index)
266 freqs.old = calc_speed(longhaul_get_cpu_mult());
268 freqs.cpu = 0; /* longhaul.c is UP only driver */
270 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
272 dprintk ("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n",
273 fsb, mult/10, mult%10, print_speed(speed/1000));
276 local_irq_save(flags);
278 pic2_mask = inb(0xA1);
279 pic1_mask = inb(0x21); /* works on C3. save mask. */
280 outb(0xFF,0xA1); /* Overkill */
281 outb(0xFE,0x21); /* TMR0 only */
283 /* Wait while PCI bus is busy. */
284 if (acpi_regs_addr && (longhaul_flags & USE_NORTHBRIDGE
285 || ((pr != NULL) && pr->flags.bm_control))) {
286 bm_status = inw(acpi_regs_addr);
288 while (bm_status && bm_timeout) {
289 outw(1 << 4, acpi_regs_addr);
291 bm_status = inw(acpi_regs_addr);
296 if (longhaul_flags & USE_NORTHBRIDGE) {
297 /* Disable AGP and PCI arbiters */
299 } else if ((pr != NULL) && pr->flags.bm_control) {
300 /* Disable bus master arbitration */
301 acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1);
303 switch (longhaul_version) {
306 * Longhaul v1. (Samuel[C5A] and Samuel2 stepping 0[C5B])
307 * Software controlled multipliers only.
309 case TYPE_LONGHAUL_V1:
310 do_longhaul1(clock_ratio_index);
314 * Longhaul v2 appears in Samuel2 Steppings 1->7 [C5B] and Ezra [C5C]
316 * Longhaul v3 (aka Powersaver). (Ezra-T [C5M] & Nehemiah [C5N])
317 * Nehemiah can do FSB scaling too, but this has never been proven
318 * to work in practice.
320 case TYPE_LONGHAUL_V2:
321 case TYPE_POWERSAVER:
322 if (longhaul_flags & USE_ACPI_C3) {
323 /* Don't allow wakeup */
324 acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0);
325 do_powersaver(cx->address, clock_ratio_index, dir);
327 do_powersaver(0, clock_ratio_index, dir);
332 if (longhaul_flags & USE_NORTHBRIDGE) {
333 /* Enable arbiters */
335 } else if ((pr != NULL) && pr->flags.bm_control) {
336 /* Enable bus master arbitration */
337 acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0);
339 outb(pic2_mask,0xA1); /* restore mask */
340 outb(pic1_mask,0x21);
342 local_irq_restore(flags);
345 freqs.new = calc_speed(longhaul_get_cpu_mult());
346 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
349 printk(KERN_INFO PFX "Warning: Timeout while waiting for idle PCI bus.\n");
353 * Centaur decided to make life a little more tricky.
354 * Only longhaul v1 is allowed to read EBLCR BSEL[0:1].
355 * Samuel2 and above have to try and guess what the FSB is.
356 * We do this by assuming we booted at maximum multiplier, and interpolate
357 * between that value multiplied by possible FSBs and cpu_mhz which
358 * was calculated at boot time. Really ugly, but no other way to do this.
363 static int guess_fsb(int mult)
365 int speed = cpu_khz / 1000;
367 int speeds[] = { 666, 1000, 1333, 2000 };
370 for (i = 0; i < 4; i++) {
371 f_max = ((speeds[i] * mult) + 50) / 100;
372 f_max += (ROUNDING / 2);
373 f_min = f_max - ROUNDING;
374 if ((speed <= f_max) && (speed >= f_min))
375 return speeds[i] / 10;
381 static int __init longhaul_get_ranges(void)
383 unsigned int i, j, k = 0;
387 /* Get current frequency */
388 mult = longhaul_get_cpu_mult();
390 printk(KERN_INFO PFX "Invalid (reserved) multiplier!\n");
393 fsb = guess_fsb(mult);
395 printk(KERN_INFO PFX "Invalid (reserved) FSB!\n");
398 /* Get max multiplier - as we always did.
399 * Longhaul MSR is usefull only when voltage scaling is enabled.
400 * C3 is booting at max anyway. */
402 /* Get min multiplier */
415 dprintk ("MinMult:%d.%dx MaxMult:%d.%dx\n",
416 minmult/10, minmult%10, maxmult/10, maxmult%10);
418 highest_speed = calc_speed(maxmult);
419 lowest_speed = calc_speed(minmult);
420 dprintk ("FSB:%dMHz Lowest speed: %s Highest speed:%s\n", fsb,
421 print_speed(lowest_speed/1000),
422 print_speed(highest_speed/1000));
424 if (lowest_speed == highest_speed) {
425 printk (KERN_INFO PFX "highestspeed == lowest, aborting.\n");
428 if (lowest_speed > highest_speed) {
429 printk (KERN_INFO PFX "nonsense! lowest (%d > %d) !\n",
430 lowest_speed, highest_speed);
434 longhaul_table = kmalloc((numscales + 1) * sizeof(struct cpufreq_frequency_table), GFP_KERNEL);
438 for (j = 0; j < numscales; j++) {
439 ratio = clock_ratio[j];
442 if (ratio > maxmult || ratio < minmult)
444 longhaul_table[k].frequency = calc_speed(ratio);
445 longhaul_table[k].index = j;
449 kfree(longhaul_table);
453 for (j = 0; j < k - 1; j++) {
454 unsigned int min_f, min_i;
455 min_f = longhaul_table[j].frequency;
457 for (i = j + 1; i < k; i++) {
458 if (longhaul_table[i].frequency < min_f) {
459 min_f = longhaul_table[i].frequency;
465 temp = longhaul_table[j].frequency;
466 longhaul_table[j].frequency = longhaul_table[min_i].frequency;
467 longhaul_table[min_i].frequency = temp;
468 temp = longhaul_table[j].index;
469 longhaul_table[j].index = longhaul_table[min_i].index;
470 longhaul_table[min_i].index = temp;
474 longhaul_table[k].frequency = CPUFREQ_TABLE_END;
476 /* Find index we are running on */
477 for (j = 0; j < k; j++) {
478 if (clock_ratio[longhaul_table[j].index & 0x1f] == mult) {
487 static void __init longhaul_setup_voltagescaling(void)
489 union msr_longhaul longhaul;
490 struct mV_pos minvid, maxvid, vid;
491 unsigned int j, speed, pos, kHz_step, numvscales;
494 rdmsrl(MSR_VIA_LONGHAUL, longhaul.val);
495 if (!(longhaul.bits.RevisionID & 1)) {
496 printk(KERN_INFO PFX "Voltage scaling not supported by CPU.\n");
500 if (!longhaul.bits.VRMRev) {
501 printk(KERN_INFO PFX "VRM 8.5\n");
502 vrm_mV_table = &vrm85_mV[0];
503 mV_vrm_table = &mV_vrm85[0];
505 printk(KERN_INFO PFX "Mobile VRM\n");
506 if (cpu_model < CPU_NEHEMIAH)
508 vrm_mV_table = &mobilevrm_mV[0];
509 mV_vrm_table = &mV_mobilevrm[0];
512 minvid = vrm_mV_table[longhaul.bits.MinimumVID];
513 maxvid = vrm_mV_table[longhaul.bits.MaximumVID];
515 if (minvid.mV == 0 || maxvid.mV == 0 || minvid.mV > maxvid.mV) {
516 printk (KERN_INFO PFX "Bogus values Min:%d.%03d Max:%d.%03d. "
517 "Voltage scaling disabled.\n",
518 minvid.mV/1000, minvid.mV%1000, maxvid.mV/1000, maxvid.mV%1000);
522 if (minvid.mV == maxvid.mV) {
523 printk (KERN_INFO PFX "Claims to support voltage scaling but min & max are "
524 "both %d.%03d. Voltage scaling disabled\n",
525 maxvid.mV/1000, maxvid.mV%1000);
529 /* How many voltage steps */
530 numvscales = maxvid.pos - minvid.pos + 1;
534 "%d possible voltage scales\n",
535 maxvid.mV/1000, maxvid.mV%1000,
536 minvid.mV/1000, minvid.mV%1000,
539 /* Calculate max frequency at min voltage */
540 j = longhaul.bits.MinMHzBR;
541 if (longhaul.bits.MinMHzBR4)
543 min_vid_speed = eblcr_table[j];
544 if (min_vid_speed == -1)
546 switch (longhaul.bits.MinMHzFSB) {
548 min_vid_speed *= 13333;
551 min_vid_speed *= 10000;
554 min_vid_speed *= 6666;
560 if (min_vid_speed >= highest_speed)
562 /* Calculate kHz for one voltage step */
563 kHz_step = (highest_speed - min_vid_speed) / numvscales;
566 while (longhaul_table[j].frequency != CPUFREQ_TABLE_END) {
567 speed = longhaul_table[j].frequency;
568 if (speed > min_vid_speed)
569 pos = (speed - min_vid_speed) / kHz_step + minvid.pos;
572 longhaul_table[j].index |= mV_vrm_table[pos] << 8;
573 vid = vrm_mV_table[mV_vrm_table[pos]];
574 printk(KERN_INFO PFX "f: %d kHz, index: %d, vid: %d mV\n", speed, j, vid.mV);
578 can_scale_voltage = 1;
579 printk(KERN_INFO PFX "Voltage scaling enabled.\n");
583 static int longhaul_verify(struct cpufreq_policy *policy)
585 return cpufreq_frequency_table_verify(policy, longhaul_table);
589 static int longhaul_target(struct cpufreq_policy *policy,
590 unsigned int target_freq, unsigned int relation)
592 unsigned int table_index = 0;
594 unsigned int dir = 0;
597 if (cpufreq_frequency_table_target(policy, longhaul_table, target_freq, relation, &table_index))
600 /* Don't set same frequency again */
601 if (longhaul_index == table_index)
604 if (!can_scale_voltage)
605 longhaul_setstate(table_index);
607 /* On test system voltage transitions exceeding single
608 * step up or down were turning motherboard off. Both
609 * "ondemand" and "userspace" are unsafe. C7 is doing
610 * this in hardware, C3 is old and we need to do this
613 current_vid = (longhaul_table[longhaul_index].index >> 8) & 0x1f;
614 if (table_index > longhaul_index)
616 while (i != table_index) {
617 vid = (longhaul_table[i].index >> 8) & 0x1f;
618 if (vid != current_vid) {
619 longhaul_setstate(i);
628 longhaul_setstate(table_index);
630 longhaul_index = table_index;
635 static unsigned int longhaul_get(unsigned int cpu)
639 return calc_speed(longhaul_get_cpu_mult());
642 static acpi_status longhaul_walk_callback(acpi_handle obj_handle,
644 void *context, void **return_value)
646 struct acpi_device *d;
648 if ( acpi_bus_get_device(obj_handle, &d) ) {
651 *return_value = (void *)acpi_driver_data(d);
655 /* VIA don't support PM2 reg, but have something similar */
656 static int enable_arbiter_disable(void)
663 /* Find PLE133 host bridge */
665 dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8601_0,
667 /* Find CLE266 host bridge */
670 dev = pci_get_device(PCI_VENDOR_ID_VIA,
671 PCI_DEVICE_ID_VIA_862X_0, NULL);
672 /* Find CN400 V-Link host bridge */
674 dev = pci_get_device(PCI_VENDOR_ID_VIA, 0x7259, NULL);
677 /* Enable access to port 0x22 */
678 pci_read_config_byte(dev, reg, &pci_cmd);
679 if (!(pci_cmd & 1<<7)) {
681 pci_write_config_byte(dev, reg, pci_cmd);
682 pci_read_config_byte(dev, reg, &pci_cmd);
683 if (!(pci_cmd & 1<<7)) {
685 "Can't enable access to port 0x22.\n");
695 static int longhaul_setup_southbridge(void)
700 /* Find VT8235 southbridge */
701 dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, NULL);
703 /* Find VT8237 southbridge */
704 dev = pci_get_device(PCI_VENDOR_ID_VIA,
705 PCI_DEVICE_ID_VIA_8237, NULL);
707 /* Set transition time to max */
708 pci_read_config_byte(dev, 0xec, &pci_cmd);
709 pci_cmd &= ~(1 << 2);
710 pci_write_config_byte(dev, 0xec, pci_cmd);
711 pci_read_config_byte(dev, 0xe4, &pci_cmd);
712 pci_cmd &= ~(1 << 7);
713 pci_write_config_byte(dev, 0xe4, pci_cmd);
714 pci_read_config_byte(dev, 0xe5, &pci_cmd);
716 pci_write_config_byte(dev, 0xe5, pci_cmd);
717 /* Get address of ACPI registers block*/
718 pci_read_config_byte(dev, 0x81, &pci_cmd);
719 if (pci_cmd & 1 << 7) {
720 pci_read_config_dword(dev, 0x88, &acpi_regs_addr);
721 acpi_regs_addr &= 0xff00;
722 printk(KERN_INFO PFX "ACPI I/O at 0x%x\n", acpi_regs_addr);
731 static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
733 struct cpuinfo_x86 *c = cpu_data;
738 /* Check what we have on this motherboard */
739 switch (c->x86_model) {
741 cpu_model = CPU_SAMUEL;
742 cpuname = "C3 'Samuel' [C5A]";
743 longhaul_version = TYPE_LONGHAUL_V1;
744 memcpy (clock_ratio, samuel1_clock_ratio, sizeof(samuel1_clock_ratio));
745 memcpy (eblcr_table, samuel1_eblcr, sizeof(samuel1_eblcr));
749 switch (c->x86_mask) {
751 longhaul_version = TYPE_LONGHAUL_V1;
752 cpu_model = CPU_SAMUEL2;
753 cpuname = "C3 'Samuel 2' [C5B]";
754 /* Note, this is not a typo, early Samuel2's had
756 memcpy(clock_ratio, samuel1_clock_ratio,
757 sizeof(samuel1_clock_ratio));
758 memcpy(eblcr_table, samuel2_eblcr,
759 sizeof(samuel2_eblcr));
762 longhaul_version = TYPE_LONGHAUL_V1;
763 if (c->x86_mask < 8) {
764 cpu_model = CPU_SAMUEL2;
765 cpuname = "C3 'Samuel 2' [C5B]";
767 cpu_model = CPU_EZRA;
768 cpuname = "C3 'Ezra' [C5C]";
770 memcpy(clock_ratio, ezra_clock_ratio,
771 sizeof(ezra_clock_ratio));
772 memcpy(eblcr_table, ezra_eblcr,
779 cpu_model = CPU_EZRA_T;
780 cpuname = "C3 'Ezra-T' [C5M]";
781 longhaul_version = TYPE_POWERSAVER;
783 memcpy (clock_ratio, ezrat_clock_ratio, sizeof(ezrat_clock_ratio));
784 memcpy (eblcr_table, ezrat_eblcr, sizeof(ezrat_eblcr));
788 longhaul_version = TYPE_POWERSAVER;
791 nehemiah_clock_ratio,
792 sizeof(nehemiah_clock_ratio));
793 memcpy(eblcr_table, nehemiah_eblcr, sizeof(nehemiah_eblcr));
794 switch (c->x86_mask) {
796 cpu_model = CPU_NEHEMIAH;
797 cpuname = "C3 'Nehemiah A' [C5XLOE]";
800 cpu_model = CPU_NEHEMIAH;
801 cpuname = "C3 'Nehemiah B' [C5XLOH]";
804 cpu_model = CPU_NEHEMIAH_C;
805 cpuname = "C3 'Nehemiah C' [C5P]";
814 /* Check Longhaul ver. 2 */
815 if (longhaul_version == TYPE_LONGHAUL_V2) {
816 rdmsr(MSR_VIA_LONGHAUL, lo, hi);
817 if (lo == 0 && hi == 0)
818 /* Looks like MSR isn't present */
819 longhaul_version = TYPE_LONGHAUL_V1;
822 printk (KERN_INFO PFX "VIA %s CPU detected. ", cpuname);
823 switch (longhaul_version) {
824 case TYPE_LONGHAUL_V1:
825 case TYPE_LONGHAUL_V2:
826 printk ("Longhaul v%d supported.\n", longhaul_version);
828 case TYPE_POWERSAVER:
829 printk ("Powersaver supported.\n");
834 longhaul_setup_southbridge();
836 /* Find ACPI data for processor */
837 acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
838 ACPI_UINT32_MAX, &longhaul_walk_callback,
841 /* Check ACPI support for C3 state */
842 if (pr != NULL && longhaul_version == TYPE_POWERSAVER) {
843 cx = &pr->power.states[ACPI_STATE_C3];
844 if (cx->address > 0 && cx->latency <= 1000)
845 longhaul_flags |= USE_ACPI_C3;
847 /* Check if northbridge is friendly */
848 if (enable_arbiter_disable())
849 longhaul_flags |= USE_NORTHBRIDGE;
851 /* Check ACPI support for bus master arbiter disable */
852 if (!(longhaul_flags & USE_ACPI_C3
853 || longhaul_flags & USE_NORTHBRIDGE)
854 && ((pr == NULL) || !(pr->flags.bm_control))) {
856 "No ACPI support. Unsupported northbridge.\n");
860 if (longhaul_flags & USE_NORTHBRIDGE)
861 printk(KERN_INFO PFX "Using northbridge support.\n");
862 if (longhaul_flags & USE_ACPI_C3)
863 printk(KERN_INFO PFX "Using ACPI support.\n");
865 ret = longhaul_get_ranges();
869 if ((longhaul_version != TYPE_LONGHAUL_V1) && (scale_voltage != 0))
870 longhaul_setup_voltagescaling();
872 policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
873 policy->cpuinfo.transition_latency = 200000; /* nsec */
874 policy->cur = calc_speed(longhaul_get_cpu_mult());
876 ret = cpufreq_frequency_table_cpuinfo(policy, longhaul_table);
880 cpufreq_frequency_table_get_attr(longhaul_table, policy->cpu);
885 static int __devexit longhaul_cpu_exit(struct cpufreq_policy *policy)
887 cpufreq_frequency_table_put_attr(policy->cpu);
891 static struct freq_attr* longhaul_attr[] = {
892 &cpufreq_freq_attr_scaling_available_freqs,
896 static struct cpufreq_driver longhaul_driver = {
897 .verify = longhaul_verify,
898 .target = longhaul_target,
900 .init = longhaul_cpu_init,
901 .exit = __devexit_p(longhaul_cpu_exit),
903 .owner = THIS_MODULE,
904 .attr = longhaul_attr,
908 static int __init longhaul_init(void)
910 struct cpuinfo_x86 *c = cpu_data;
912 if (c->x86_vendor != X86_VENDOR_CENTAUR || c->x86 != 6)
916 if (num_online_cpus() > 1) {
917 printk(KERN_ERR PFX "More than 1 CPU detected, longhaul disabled.\n");
921 #ifdef CONFIG_X86_IO_APIC
923 printk(KERN_ERR PFX "APIC detected. Longhaul is currently broken in this configuration.\n");
927 switch (c->x86_model) {
929 return cpufreq_register_driver(&longhaul_driver);
931 printk(KERN_ERR PFX "Use acpi-cpufreq driver for VIA C7\n");
940 static void __exit longhaul_exit(void)
944 for (i=0; i < numscales; i++) {
945 if (clock_ratio[i] == maxmult) {
946 longhaul_setstate(i);
951 cpufreq_unregister_driver(&longhaul_driver);
952 kfree(longhaul_table);
955 module_param (scale_voltage, int, 0644);
956 MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor");
958 MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>");
959 MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors.");
960 MODULE_LICENSE ("GPL");
962 late_initcall(longhaul_init);
963 module_exit(longhaul_exit);