24 #include <linux/kernel.h>
25 #include <linux/module.h>
29 #include <linux/pci.h>
30 #include <linux/slab.h>
31 #include <linux/string.h>
33 #include <linux/timex.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;
68 static unsigned int minmult, maxmult;
69 static int can_scale_voltage;
72 static u32 acpi_regs_addr;
73 static u8 longhaul_flags;
74 static unsigned int longhaul_index;
77 static int scale_voltage;
78 static int disable_acpi_c3;
79 static int revid_errata;
85 static int longhaul_version;
88 static char speedbuffer[8];
90 static char *print_speed(
int speed)
93 snprintf(speedbuffer,
sizeof(speedbuffer),
"%dMHz", speed);
98 snprintf(speedbuffer,
sizeof(speedbuffer),
101 snprintf(speedbuffer,
sizeof(speedbuffer),
102 "%d.%dGHz", speed/1000, (speed%1000)/100);
108 static unsigned int calc_speed(
int mult)
119 static int longhaul_get_cpu_mult(
void)
121 unsigned long invalue = 0,
lo,
hi;
124 invalue = (
lo & (1<<22|1<<23|1<<24|1<<25))>>22;
130 return eblcr[invalue];
135 static void do_longhaul1(
unsigned int mults_index)
141 bcr2.bits.ESOFTBF = 1;
142 bcr2.bits.CLOCKMUL = mults_index & 0xff;
155 bcr2.bits.ESOFTBF = 0;
161 static void do_powersaver(
int cx_address,
unsigned int mults_index,
170 longhaul.bits.RevisionKey = longhaul.bits.RevisionID;
172 longhaul.bits.RevisionKey = 0;
173 longhaul.bits.SoftBusRatio = mults_index & 0xf;
174 longhaul.bits.SoftBusRatio4 = (mults_index & 0x10) >> 4;
176 if (can_scale_voltage)
177 longhaul.bits.SoftVID = (mults_index >> 8) & 0x1f;
181 if (can_scale_voltage && dir) {
182 longhaul.bits.EnableSoftVID = 1;
196 longhaul.bits.EnableSoftVID = 0;
201 longhaul.bits.EnableSoftBusRatio = 1;
214 longhaul.bits.EnableSoftBusRatio = 0;
218 if (can_scale_voltage && !dir) {
219 longhaul.bits.EnableSoftVID = 1;
233 longhaul.bits.EnableSoftVID = 0;
245 static void longhaul_setstate(
unsigned int table_index)
247 unsigned int mults_index;
251 unsigned int pic1_mask, pic2_mask;
253 u32 bm_timeout = 1000;
254 unsigned int dir = 0;
256 mults_index = longhaul_table[table_index].
index;
258 mult = mults[mults_index & 0x1f];
261 speed = calc_speed(mult);
262 if ((speed > highest_speed) || (speed < lowest_speed))
265 if (can_scale_voltage && longhaul_index < table_index)
268 freqs.old = calc_speed(longhaul_get_cpu_mult());
274 pr_debug(
"Setting to FSB:%dMHz Mult:%d.%dx (%s)\n",
275 fsb, mult/10, mult%10, print_speed(speed/1000));
280 pic2_mask =
inb(0xA1);
281 pic1_mask =
inb(0x21);
287 || ((pr !=
NULL) && pr->
flags.bm_control))) {
288 bm_status =
inw(acpi_regs_addr);
290 while (bm_status && bm_timeout) {
291 outw(1 << 4, acpi_regs_addr);
293 bm_status =
inw(acpi_regs_addr);
301 }
else if ((pr !=
NULL) && pr->
flags.bm_control) {
305 switch (longhaul_version) {
312 do_longhaul1(mults_index);
327 do_powersaver(cx->
address, mults_index, dir);
329 do_powersaver(0, mults_index, dir);
334 if (longhaul_flags & USE_NORTHBRIDGE) {
337 }
else if ((pr !=
NULL) && pr->
flags.bm_control) {
341 outb(pic2_mask, 0xA1);
342 outb(pic1_mask, 0x21);
347 freqs.new = calc_speed(longhaul_get_cpu_mult());
368 longhaul_flags &= ~USE_ACPI_C3;
371 "Revision ID\" option.\n");
407 static int guess_fsb(
int mult)
411 int speeds[] = { 666, 1000, 1333, 2000 };
414 for (i = 0; i < 4; i++) {
415 f_max = ((speeds[
i] *
mult) + 50) / 100;
418 if ((speed <= f_max) && (speed >= f_min))
419 return speeds[
i] / 10;
425 static int __cpuinit longhaul_get_ranges(
void)
427 unsigned int i,
j,
k = 0;
432 mult = longhaul_get_cpu_mult();
437 fsb = guess_fsb(mult);
459 pr_debug(
"MinMult:%d.%dx MaxMult:%d.%dx\n",
460 minmult/10, minmult%10, maxmult/10, maxmult%10);
462 highest_speed = calc_speed(maxmult);
463 lowest_speed = calc_speed(minmult);
464 pr_debug(
"FSB:%dMHz Lowest speed: %s Highest speed:%s\n", fsb,
465 print_speed(lowest_speed/1000),
466 print_speed(highest_speed/1000));
468 if (lowest_speed == highest_speed) {
472 if (lowest_speed > highest_speed) {
474 lowest_speed, highest_speed);
478 longhaul_table =
kmalloc((numscales + 1) *
sizeof(*longhaul_table),
483 for (j = 0; j < numscales; j++) {
487 if (ratio > maxmult || ratio < minmult)
489 longhaul_table[
k].
frequency = calc_speed(ratio);
494 kfree(longhaul_table);
498 for (j = 0; j < k - 1; j++) {
499 unsigned int min_f, min_i;
502 for (i = j + 1; i <
k; i++) {
503 if (longhaul_table[i].
frequency < min_f) {
510 longhaul_table[min_i].frequency);
512 longhaul_table[min_i].index);
519 for (j = 0; j <
k; j++) {
520 if (mults[longhaul_table[j].
index & 0x1f] == mult) {
529 static void __cpuinit longhaul_setup_voltagescaling(
void)
533 unsigned int j, speed,
pos, kHz_step, numvscales;
537 if (!(longhaul.bits.RevisionID & 1)) {
542 if (!longhaul.bits.VRMRev) {
544 vrm_mV_table = &vrm85_mV[0];
545 mV_vrm_table = &mV_vrm85[0];
550 vrm_mV_table = &mobilevrm_mV[0];
551 mV_vrm_table = &mV_mobilevrm[0];
554 minvid = vrm_mV_table[longhaul.bits.MinimumVID];
555 maxvid = vrm_mV_table[longhaul.bits.MaximumVID];
557 if (minvid.mV == 0 || maxvid.mV == 0 || minvid.mV > maxvid.mV) {
559 "Voltage scaling disabled.\n",
560 minvid.mV/1000, minvid.mV%1000,
561 maxvid.mV/1000, maxvid.mV%1000);
565 if (minvid.mV == maxvid.mV) {
567 "min & max are both %d.%03d. "
568 "Voltage scaling disabled\n",
569 maxvid.mV/1000, maxvid.mV%1000);
574 numvscales = maxvid.pos - minvid.pos + 1;
578 "%d possible voltage scales\n",
579 maxvid.mV/1000, maxvid.mV%1000,
580 minvid.mV/1000, minvid.mV%1000,
584 j = longhaul.bits.MinMHzBR;
585 if (longhaul.bits.MinMHzBR4)
587 min_vid_speed = eblcr[
j];
588 if (min_vid_speed == -1)
590 switch (longhaul.bits.MinMHzFSB) {
592 min_vid_speed *= 13333;
595 min_vid_speed *= 10000;
598 min_vid_speed *= 6666;
604 if (min_vid_speed >= highest_speed)
607 kHz_step = (highest_speed - min_vid_speed) / numvscales;
612 if (speed > min_vid_speed)
613 pos = (speed - min_vid_speed) / kHz_step + minvid.pos;
616 longhaul_table[j].
index |= mV_vrm_table[pos] << 8;
617 vid = vrm_mV_table[mV_vrm_table[pos]];
623 can_scale_voltage = 1;
635 unsigned int target_freq,
unsigned int relation)
637 unsigned int table_index = 0;
639 unsigned int dir = 0;
643 relation, &table_index))
647 if (longhaul_index == table_index)
650 if (!can_scale_voltage)
651 longhaul_setstate(table_index);
659 current_vid = (longhaul_table[longhaul_index].
index >> 8);
661 if (table_index > longhaul_index)
663 while (i != table_index) {
664 vid = (longhaul_table[
i].
index >> 8) & 0x1f;
665 if (vid != current_vid) {
666 longhaul_setstate(i);
675 longhaul_setstate(table_index);
677 longhaul_index = table_index;
682 static unsigned int longhaul_get(
unsigned int cpu)
686 return calc_speed(longhaul_get_cpu_mult());
693 struct acpi_device *
d;
698 *return_value = acpi_driver_data(d);
703 static int enable_arbiter_disable(
void)
729 pci_read_config_byte(dev, reg, &pci_cmd);
730 if (!(pci_cmd & 1<<7)) {
732 pci_write_config_byte(dev, reg, pci_cmd);
733 pci_read_config_byte(dev, reg, &pci_cmd);
734 if (!(pci_cmd & 1<<7)) {
736 "Can't enable access to port 0x22.\n");
746 static int longhaul_setup_southbridge(
void)
759 pci_read_config_byte(dev, 0xec, &pci_cmd);
760 pci_cmd &= ~(1 << 2);
761 pci_write_config_byte(dev, 0xec, pci_cmd);
762 pci_read_config_byte(dev, 0xe4, &pci_cmd);
763 pci_cmd &= ~(1 << 7);
764 pci_write_config_byte(dev, 0xe4, pci_cmd);
765 pci_read_config_byte(dev, 0xe5, &pci_cmd);
767 pci_write_config_byte(dev, 0xe5, pci_cmd);
769 pci_read_config_byte(dev, 0x81, &pci_cmd);
770 if (pci_cmd & 1 << 7) {
771 pci_read_config_dword(dev, 0x88, &acpi_regs_addr);
772 acpi_regs_addr &= 0xff00;
786 char *cpuname =
NULL;
794 cpuname =
"C3 'Samuel' [C5A]";
796 memcpy(mults, samuel1_mults,
sizeof(samuel1_mults));
797 memcpy(eblcr, samuel1_eblcr,
sizeof(samuel1_eblcr));
805 cpuname =
"C3 'Samuel 2' [C5B]";
808 memcpy(mults, samuel1_mults,
sizeof(samuel1_mults));
809 memcpy(eblcr, samuel2_eblcr,
sizeof(samuel2_eblcr));
815 cpuname =
"C3 'Samuel 2' [C5B]";
818 cpuname =
"C3 'Ezra' [C5C]";
820 memcpy(mults, ezra_mults,
sizeof(ezra_mults));
821 memcpy(eblcr, ezra_eblcr,
sizeof(ezra_eblcr));
828 cpuname =
"C3 'Ezra-T' [C5M]";
831 memcpy(mults, ezrat_mults,
sizeof(ezrat_mults));
832 memcpy(eblcr, ezrat_eblcr,
sizeof(ezrat_eblcr));
838 memcpy(mults, nehemiah_mults,
sizeof(nehemiah_mults));
839 memcpy(eblcr, nehemiah_eblcr,
sizeof(nehemiah_eblcr));
843 cpuname =
"C3 'Nehemiah A' [C5XLOE]";
847 cpuname =
"C3 'Nehemiah B' [C5XLOH]";
851 cpuname =
"C3 'Nehemiah C' [C5P]";
863 if (lo == 0 && hi == 0)
869 switch (longhaul_version) {
880 longhaul_setup_southbridge();
895 longhaul_flags &= ~USE_ACPI_C3;
897 if (enable_arbiter_disable())
901 if (!(longhaul_flags & USE_ACPI_C3
902 || longhaul_flags & USE_NORTHBRIDGE)
903 && ((pr ==
NULL) || !(pr->
flags.bm_control))) {
905 "No ACPI support. Unsupported northbridge.\n");
909 if (longhaul_flags & USE_NORTHBRIDGE)
911 if (longhaul_flags & USE_ACPI_C3)
914 ret = longhaul_get_ranges();
919 longhaul_setup_voltagescaling();
921 policy->
cpuinfo.transition_latency = 200000;
922 policy->
cur = calc_speed(longhaul_get_cpu_mult());
939 static struct freq_attr *longhaul_attr[] = {
945 .verify = longhaul_verify,
946 .target = longhaul_target,
948 .init = longhaul_cpu_init,
952 .attr = longhaul_attr,
955 static const struct x86_cpu_id longhaul_id[] = {
961 static int __init longhaul_init(
void)
971 "longhaul disabled.\n");
975 #ifdef CONFIG_X86_IO_APIC
978 "broken in this configuration.\n");
995 static void __exit longhaul_exit(
void)
999 for (i = 0; i < numscales; i++) {
1000 if (mults[i] == maxmult) {
1001 longhaul_setstate(i);
1007 kfree(longhaul_table);