diff options
-rw-r--r-- | arch/i386/kernel/cpu/cpufreq/longhaul.c | 71 |
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 | |||
55 | static int cpu_model; | 59 | static int cpu_model; |
56 | static unsigned int numscales=16; | 60 | static unsigned int numscales=16; |
57 | static unsigned int fsb; | 61 | static unsigned int fsb; |
@@ -68,7 +72,7 @@ static unsigned int minmult, maxmult; | |||
68 | static int can_scale_voltage; | 72 | static int can_scale_voltage; |
69 | static struct acpi_processor *pr = NULL; | 73 | static struct acpi_processor *pr = NULL; |
70 | static struct acpi_processor_cx *cx = NULL; | 74 | static struct acpi_processor_cx *cx = NULL; |
71 | static int port22_en; | 75 | static u8 longhaul_flags; |
72 | 76 | ||
73 | /* Module parameters */ | 77 | /* Module parameters */ |
74 | static int scale_voltage; | 78 | static int scale_voltage; |
@@ -80,7 +84,6 @@ static int ignore_latency; | |||
80 | /* Clock ratios multiplied by 10 */ | 84 | /* Clock ratios multiplied by 10 */ |
81 | static int clock_ratio[32]; | 85 | static int clock_ratio[32]; |
82 | static int eblcr_table[32]; | 86 | static int eblcr_table[32]; |
83 | static unsigned int highest_speed, lowest_speed; /* kHz */ | ||
84 | static int longhaul_version; | 87 | static int longhaul_version; |
85 | static struct cpufreq_frequency_table *longhaul_table; | 88 | static 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 | |||
713 | print_support_type: | 722 | print_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 | |||
740 | err_acpi: | ||
741 | printk(KERN_ERR PFX "No ACPI support. Unsupported northbridge. Aborting.\n"); | ||
742 | return -ENODEV; | ||
743 | } | 748 | } |
744 | 749 | ||
745 | static int __devexit longhaul_cpu_exit(struct cpufreq_policy *policy) | 750 | static int __devexit longhaul_cpu_exit(struct cpufreq_policy *policy) |