aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorRafał Bilski <rafalbilski@interia.pl>2006-08-08 13:12:20 -0400
committerDave Jones <davej@redhat.com>2006-08-11 17:59:57 -0400
commit179da8e6e8903a8cdb19bb12672d50dc33f0fde6 (patch)
tree0e791d2d3890db822508f64d2bc1301ac307c982 /arch
parent05ca0350e8caa91a5ec9961c585c98005b6934ea (diff)
[CPUFREQ] Longhaul - Disable arbiter
ACPI C3 works for "Powersaver" processors, so use it only for them. Older CPU will change frequency on "halt" only. But we can protect transition in two ways: - by ACPI PM2 register, there is "bus master arbiter disable" bit. This isn't tested because VIA mainboards don't have PM2 register, - by PLE133 PCI/AGP arbiter disable register. There are two bits in this register. First is "PCI arbiter disable", second "AGP arbiter disable". This is working on VIA Epia 800 mainboards. Test on bm_control is more proper because this is true when PM2 register exist. Signed-off-by: Rafał Bilski <rafalbilski@interia.pl> Signed-off-by: Dave Jones <davej@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/i386/kernel/cpu/cpufreq/longhaul.c86
1 files changed, 64 insertions, 22 deletions
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
index 4f2c3aeef724..83a8793f1db8 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -27,6 +27,7 @@
27#include <linux/moduleparam.h> 27#include <linux/moduleparam.h>
28#include <linux/init.h> 28#include <linux/init.h>
29#include <linux/cpufreq.h> 29#include <linux/cpufreq.h>
30#include <linux/pci.h>
30#include <linux/slab.h> 31#include <linux/slab.h>
31#include <linux/string.h> 32#include <linux/string.h>
32 33
@@ -60,6 +61,7 @@ static int can_scale_voltage;
60static int vrmrev; 61static int vrmrev;
61static struct acpi_processor *pr = NULL; 62static struct acpi_processor *pr = NULL;
62static struct acpi_processor_cx *cx = NULL; 63static struct acpi_processor_cx *cx = NULL;
64static int port22_en = 0;
63 65
64/* Module parameters */ 66/* Module parameters */
65static int dont_scale_voltage; 67static int dont_scale_voltage;
@@ -124,10 +126,9 @@ static int longhaul_get_cpu_mult(void)
124 126
125/* For processor with BCR2 MSR */ 127/* For processor with BCR2 MSR */
126 128
127static void do_longhaul1(int cx_address, unsigned int clock_ratio_index) 129static void do_longhaul1(unsigned int clock_ratio_index)
128{ 130{
129 union msr_bcr2 bcr2; 131 union msr_bcr2 bcr2;
130 u32 t;
131 132
132 rdmsrl(MSR_VIA_BCR2, bcr2.val); 133 rdmsrl(MSR_VIA_BCR2, bcr2.val);
133 /* Enable software clock multiplier */ 134 /* Enable software clock multiplier */
@@ -136,13 +137,11 @@ static void do_longhaul1(int cx_address, unsigned int clock_ratio_index)
136 137
137 /* Sync to timer tick */ 138 /* Sync to timer tick */
138 safe_halt(); 139 safe_halt();
139 ACPI_FLUSH_CPU_CACHE();
140 /* Change frequency on next halt or sleep */ 140 /* Change frequency on next halt or sleep */
141 wrmsrl(MSR_VIA_BCR2, bcr2.val); 141 wrmsrl(MSR_VIA_BCR2, bcr2.val);
142 /* Invoke C3 */ 142 /* Invoke transition */
143 inb(cx_address); 143 ACPI_FLUSH_CPU_CACHE();
144 /* Dummy op - must do something useless after P_LVL3 read */ 144 halt();
145 t = inl(acpi_fadt.xpm_tmr_blk.address);
146 145
147 /* Disable software clock multiplier */ 146 /* Disable software clock multiplier */
148 local_irq_disable(); 147 local_irq_disable();
@@ -166,9 +165,9 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
166 165
167 /* Sync to timer tick */ 166 /* Sync to timer tick */
168 safe_halt(); 167 safe_halt();
169 ACPI_FLUSH_CPU_CACHE();
170 /* Change frequency on next halt or sleep */ 168 /* Change frequency on next halt or sleep */
171 wrmsrl(MSR_VIA_LONGHAUL, longhaul.val); 169 wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
170 ACPI_FLUSH_CPU_CACHE();
172 /* Invoke C3 */ 171 /* Invoke C3 */
173 inb(cx_address); 172 inb(cx_address);
174 /* Dummy op - must do something useless after P_LVL3 read */ 173 /* Dummy op - must do something useless after P_LVL3 read */
@@ -227,10 +226,13 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
227 outb(0xFF,0xA1); /* Overkill */ 226 outb(0xFF,0xA1); /* Overkill */
228 outb(0xFE,0x21); /* TMR0 only */ 227 outb(0xFE,0x21); /* TMR0 only */
229 228
230 /* Disable bus master arbitration */ 229 if (pr->flags.bm_control) {
231 if (pr->flags.bm_check) { 230 /* Disable bus master arbitration */
232 acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1, 231 acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1,
233 ACPI_MTX_DO_NOT_LOCK); 232 ACPI_MTX_DO_NOT_LOCK);
233 } else if (port22_en) {
234 /* Disable AGP and PCI arbiters */
235 outb(3, 0x22);
234 } 236 }
235 237
236 switch (longhaul_version) { 238 switch (longhaul_version) {
@@ -244,7 +246,7 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
244 */ 246 */
245 case TYPE_LONGHAUL_V1: 247 case TYPE_LONGHAUL_V1:
246 case TYPE_LONGHAUL_V2: 248 case TYPE_LONGHAUL_V2:
247 do_longhaul1(cx->address, clock_ratio_index); 249 do_longhaul1(clock_ratio_index);
248 break; 250 break;
249 251
250 /* 252 /*
@@ -259,14 +261,20 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
259 * to work in practice. 261 * to work in practice.
260 */ 262 */
261 case TYPE_POWERSAVER: 263 case TYPE_POWERSAVER:
264 /* Don't allow wakeup */
265 acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0,
266 ACPI_MTX_DO_NOT_LOCK);
262 do_powersaver(cx->address, clock_ratio_index); 267 do_powersaver(cx->address, clock_ratio_index);
263 break; 268 break;
264 } 269 }
265 270
266 /* Enable bus master arbitration */ 271 if (pr->flags.bm_control) {
267 if (pr->flags.bm_check) { 272 /* Enable bus master arbitration */
268 acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0, 273 acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0,
269 ACPI_MTX_DO_NOT_LOCK); 274 ACPI_MTX_DO_NOT_LOCK);
275 } else if (port22_en) {
276 /* Enable arbiters */
277 outb(0, 0x22);
270 } 278 }
271 279
272 outb(pic2_mask,0xA1); /* restore mask */ 280 outb(pic2_mask,0xA1); /* restore mask */
@@ -540,21 +548,33 @@ static acpi_status longhaul_walk_callback(acpi_handle obj_handle,
540 return 1; 548 return 1;
541} 549}
542 550
551/* VIA don't support PM2 reg, but have something similar */
552static int enable_arbiter_disable(void)
553{
554 struct pci_dev *dev;
555 u8 pci_cmd;
556
557 /* Find PLE133 host bridge */
558 dev = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8601_0, NULL);
559 if (dev != NULL) {
560 /* Enable access to port 0x22 */
561 pci_read_config_byte(dev, 0x78, &pci_cmd);
562 if ( !(pci_cmd & 1<<7) ) {
563 pci_cmd |= 1<<7;
564 pci_write_config_byte(dev, 0x78, pci_cmd);
565 }
566 return 1;
567 }
568 return 0;
569}
570
543static int __init longhaul_cpu_init(struct cpufreq_policy *policy) 571static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
544{ 572{
545 struct cpuinfo_x86 *c = cpu_data; 573 struct cpuinfo_x86 *c = cpu_data;
546 char *cpuname=NULL; 574 char *cpuname=NULL;
547 int ret; 575 int ret;
548 576
549 /* Check ACPI support for C3 state */ 577 /* Check what we have on this motherboard */
550 acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
551 &longhaul_walk_callback, NULL, (void *)&pr);
552 if (pr == NULL) goto err_acpi;
553
554 cx = &pr->power.states[ACPI_STATE_C3];
555 if (cx->address == 0 || cx->latency > 1000) goto err_acpi;
556
557 /* Now check what we have on this motherboard */
558 switch (c->x86_model) { 578 switch (c->x86_model) {
559 case 6: 579 case 6:
560 cpu_model = CPU_SAMUEL; 580 cpu_model = CPU_SAMUEL;
@@ -636,6 +656,28 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
636 break; 656 break;
637 }; 657 };
638 658
659 /* Find ACPI data for processor */
660 acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
661 &longhaul_walk_callback, NULL, (void *)&pr);
662 if (pr == NULL)
663 goto err_acpi;
664
665 if (longhaul_version == TYPE_POWERSAVER) {
666 /* Check ACPI support for C3 state */
667 cx = &pr->power.states[ACPI_STATE_C3];
668 if (cx->address == 0 || cx->latency > 1000)
669 goto err_acpi;
670 } else {
671 /* Check ACPI support for bus master arbiter disable */
672 if (!pr->flags.bm_control) {
673 if (!enable_arbiter_disable()) {
674 printk(KERN_ERR PFX "No ACPI support. No VT8601 host bridge. Aborting.\n");
675 return -ENODEV;
676 } else
677 port22_en = 1;
678 }
679 }
680
639 ret = longhaul_get_ranges(); 681 ret = longhaul_get_ranges();
640 if (ret != 0) 682 if (ret != 0)
641 return ret; 683 return ret;