aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/i386/kernel/cpu/cpufreq/longhaul.c71
1 files changed, 38 insertions, 33 deletions
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
index 087e941b43de..fd70c77acc1c 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -52,6 +52,10 @@
52#define CPU_EZRA_T 4 52#define CPU_EZRA_T 4
53#define CPU_NEHEMIAH 5 53#define CPU_NEHEMIAH 5
54 54
55/* Flags */
56#define USE_ACPI_C3 (1 << 1)
57#define USE_NORTHBRIDGE (1 << 2)
58
55static int cpu_model; 59static int cpu_model;
56static unsigned int numscales=16; 60static unsigned int numscales=16;
57static unsigned int fsb; 61static unsigned int fsb;
@@ -68,7 +72,7 @@ static unsigned int minmult, maxmult;
68static int can_scale_voltage; 72static int can_scale_voltage;
69static struct acpi_processor *pr = NULL; 73static struct acpi_processor *pr = NULL;
70static struct acpi_processor_cx *cx = NULL; 74static struct acpi_processor_cx *cx = NULL;
71static int port22_en; 75static u8 longhaul_flags;
72 76
73/* Module parameters */ 77/* Module parameters */
74static int scale_voltage; 78static int scale_voltage;
@@ -80,7 +84,6 @@ static int ignore_latency;
80/* Clock ratios multiplied by 10 */ 84/* Clock ratios multiplied by 10 */
81static int clock_ratio[32]; 85static int clock_ratio[32];
82static int eblcr_table[32]; 86static int eblcr_table[32];
83static unsigned int highest_speed, lowest_speed; /* kHz */
84static int longhaul_version; 87static int longhaul_version;
85static struct cpufreq_frequency_table *longhaul_table; 88static struct cpufreq_frequency_table *longhaul_table;
86 89
@@ -178,7 +181,7 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
178 safe_halt(); 181 safe_halt();
179 /* Change frequency on next halt or sleep */ 182 /* Change frequency on next halt or sleep */
180 wrmsrl(MSR_VIA_LONGHAUL, longhaul.val); 183 wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
181 if (port22_en) { 184 if (!cx_address) {
182 ACPI_FLUSH_CPU_CACHE(); 185 ACPI_FLUSH_CPU_CACHE();
183 /* Invoke C1 */ 186 /* Invoke C1 */
184 halt(); 187 halt();
@@ -189,7 +192,6 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
189 /* Dummy op - must do something useless after P_LVL3 read */ 192 /* Dummy op - must do something useless after P_LVL3 read */
190 t = inl(acpi_fadt.xpm_tmr_blk.address); 193 t = inl(acpi_fadt.xpm_tmr_blk.address);
191 } 194 }
192
193 /* Disable bus ratio bit */ 195 /* Disable bus ratio bit */
194 local_irq_disable(); 196 local_irq_disable();
195 longhaul.bits.RevisionKey = longhaul.bits.RevisionID; 197 longhaul.bits.RevisionKey = longhaul.bits.RevisionID;
@@ -243,15 +245,14 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
243 outb(0xFF,0xA1); /* Overkill */ 245 outb(0xFF,0xA1); /* Overkill */
244 outb(0xFE,0x21); /* TMR0 only */ 246 outb(0xFE,0x21); /* TMR0 only */
245 247
246 if (pr->flags.bm_control) { 248 if (longhaul_flags & USE_NORTHBRIDGE) {
249 /* Disable AGP and PCI arbiters */
250 outb(3, 0x22);
251 } else if ((pr != NULL) && pr->flags.bm_control) {
247 /* Disable bus master arbitration */ 252 /* Disable bus master arbitration */
248 acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1, 253 acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1,
249 ACPI_MTX_DO_NOT_LOCK); 254 ACPI_MTX_DO_NOT_LOCK);
250 } else if (port22_en) {
251 /* Disable AGP and PCI arbiters */
252 outb(3, 0x22);
253 } 255 }
254
255 switch (longhaul_version) { 256 switch (longhaul_version) {
256 257
257 /* 258 /*
@@ -278,22 +279,25 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
278 * to work in practice. 279 * to work in practice.
279 */ 280 */
280 case TYPE_POWERSAVER: 281 case TYPE_POWERSAVER:
281 /* Don't allow wakeup */ 282 if (longhaul_flags & USE_ACPI_C3) {
282 acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0, 283 /* Don't allow wakeup */
283 ACPI_MTX_DO_NOT_LOCK); 284 acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0,
284 do_powersaver(cx->address, clock_ratio_index); 285 ACPI_MTX_DO_NOT_LOCK);
286 do_powersaver(cx->address, clock_ratio_index);
287 } else {
288 do_powersaver(0, clock_ratio_index);
289 }
285 break; 290 break;
286 } 291 }
287 292
288 if (pr->flags.bm_control) { 293 if (longhaul_flags & USE_NORTHBRIDGE) {
294 /* Enable arbiters */
295 outb(0, 0x22);
296 } else if ((pr != NULL) && pr->flags.bm_control) {
289 /* Enable bus master arbitration */ 297 /* Enable bus master arbitration */
290 acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0, 298 acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0,
291 ACPI_MTX_DO_NOT_LOCK); 299 ACPI_MTX_DO_NOT_LOCK);
292 } else if (port22_en) {
293 /* Enable arbiters */
294 outb(0, 0x22);
295 } 300 }
296
297 outb(pic2_mask,0xA1); /* restore mask */ 301 outb(pic2_mask,0xA1); /* restore mask */
298 outb(pic1_mask,0x21); 302 outb(pic1_mask,0x21);
299 303
@@ -691,27 +695,32 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
691 /* Find ACPI data for processor */ 695 /* Find ACPI data for processor */
692 acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, 696 acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
693 &longhaul_walk_callback, NULL, (void *)&pr); 697 &longhaul_walk_callback, NULL, (void *)&pr);
694 if (pr == NULL)
695 goto err_acpi;
696 698
697 if (longhaul_version == TYPE_POWERSAVER) { 699 /* Check ACPI support for C3 state */
698 /* Check ACPI support for C3 state */ 700 if ((pr != NULL) && (longhaul_version == TYPE_POWERSAVER)) {
699 cx = &pr->power.states[ACPI_STATE_C3]; 701 cx = &pr->power.states[ACPI_STATE_C3];
700 if (cx->address > 0 && 702 if (cx->address > 0 &&
701 (cx->latency <= 1000 || ignore_latency != 0) ) { 703 (cx->latency <= 1000 || ignore_latency != 0) ) {
704 longhaul_flags |= USE_ACPI_C3;
702 goto print_support_type; 705 goto print_support_type;
703 } 706 }
704 } 707 }
708 /* Check if northbridge is friendly */
709 if (enable_arbiter_disable()) {
710 longhaul_flags |= USE_NORTHBRIDGE;
711 goto print_support_type;
712 }
713
714 /* No ACPI C3 or we can't use it */
705 /* Check ACPI support for bus master arbiter disable */ 715 /* Check ACPI support for bus master arbiter disable */
706 if (!pr->flags.bm_control) { 716 if ((pr == NULL) || !(pr->flags.bm_control)) {
707 if (enable_arbiter_disable()) { 717 printk(KERN_ERR PFX
708 port22_en = 1; 718 "No ACPI support. Unsupported northbridge.\n");
709 } else { 719 return -ENODEV;
710 goto err_acpi;
711 }
712 } 720 }
721
713print_support_type: 722print_support_type:
714 if (!port22_en) { 723 if (!(longhaul_flags & USE_NORTHBRIDGE)) {
715 printk (KERN_INFO PFX "Using ACPI support.\n"); 724 printk (KERN_INFO PFX "Using ACPI support.\n");
716 } else { 725 } else {
717 printk (KERN_INFO PFX "Using northbridge support.\n"); 726 printk (KERN_INFO PFX "Using northbridge support.\n");
@@ -736,10 +745,6 @@ print_support_type:
736 cpufreq_frequency_table_get_attr(longhaul_table, policy->cpu); 745 cpufreq_frequency_table_get_attr(longhaul_table, policy->cpu);
737 746
738 return 0; 747 return 0;
739
740err_acpi:
741 printk(KERN_ERR PFX "No ACPI support. Unsupported northbridge. Aborting.\n");
742 return -ENODEV;
743} 748}
744 749
745static int __devexit longhaul_cpu_exit(struct cpufreq_policy *policy) 750static int __devexit longhaul_cpu_exit(struct cpufreq_policy *policy)