aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/cpu/cpufreq/longhaul.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/cpu/cpufreq/longhaul.c')
-rw-r--r--arch/i386/kernel/cpu/cpufreq/longhaul.c58
1 files changed, 53 insertions, 5 deletions
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
index ab0f9f5aac11..04e3563da4fe 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -29,6 +29,7 @@
29#include <linux/cpufreq.h> 29#include <linux/cpufreq.h>
30#include <linux/slab.h> 30#include <linux/slab.h>
31#include <linux/string.h> 31#include <linux/string.h>
32#include <linux/pci.h>
32 33
33#include <asm/msr.h> 34#include <asm/msr.h>
34#include <asm/timex.h> 35#include <asm/timex.h>
@@ -119,7 +120,13 @@ static int longhaul_get_cpu_mult(void)
119static void do_powersaver(union msr_longhaul *longhaul, 120static void do_powersaver(union msr_longhaul *longhaul,
120 unsigned int clock_ratio_index) 121 unsigned int clock_ratio_index)
121{ 122{
123 struct pci_dev *dev;
124 unsigned long flags;
125 unsigned int tmp_mask;
122 int version; 126 int version;
127 int i;
128 u16 pci_cmd;
129 u16 cmd_state[64];
123 130
124 switch (cpu_model) { 131 switch (cpu_model) {
125 case CPU_EZRA_T: 132 case CPU_EZRA_T:
@@ -137,17 +144,58 @@ static void do_powersaver(union msr_longhaul *longhaul,
137 longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4; 144 longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
138 longhaul->bits.EnableSoftBusRatio = 1; 145 longhaul->bits.EnableSoftBusRatio = 1;
139 longhaul->bits.RevisionKey = 0; 146 longhaul->bits.RevisionKey = 0;
140 local_irq_disable(); 147
141 wrmsrl(MSR_VIA_LONGHAUL, longhaul->val); 148 preempt_disable();
149 local_irq_save(flags);
150
151 /*
152 * get current pci bus master state for all devices
153 * and clear bus master bit
154 */
155 dev = NULL;
156 i = 0;
157 do {
158 dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
159 if (dev != NULL) {
160 pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
161 cmd_state[i++] = pci_cmd;
162 pci_cmd &= ~PCI_COMMAND_MASTER;
163 pci_write_config_word(dev, PCI_COMMAND, pci_cmd);
164 }
165 } while (dev != NULL);
166
167 tmp_mask=inb(0x21); /* works on C3. save mask. */
168 outb(0xFE,0x21); /* TMR0 only */
169 outb(0xFF,0x80); /* delay */
170
142 local_irq_enable(); 171 local_irq_enable();
172
173 __hlt();
174 wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
143 __hlt(); 175 __hlt();
144 176
177 local_irq_disable();
178
179 outb(tmp_mask,0x21); /* restore mask */
180
181 /* restore pci bus master state for all devices */
182 dev = NULL;
183 i = 0;
184 do {
185 dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
186 if (dev != NULL) {
187 pci_cmd = cmd_state[i++];
188 pci_write_config_byte(dev, PCI_COMMAND, pci_cmd);
189 }
190 } while (dev != NULL);
191 local_irq_restore(flags);
192 preempt_enable();
193
194 /* disable bus ratio bit */
145 rdmsrl(MSR_VIA_LONGHAUL, longhaul->val); 195 rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
146 longhaul->bits.EnableSoftBusRatio = 0; 196 longhaul->bits.EnableSoftBusRatio = 0;
147 longhaul->bits.RevisionKey = version; 197 longhaul->bits.RevisionKey = version;
148 local_irq_disable();
149 wrmsrl(MSR_VIA_LONGHAUL, longhaul->val); 198 wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
150 local_irq_enable();
151} 199}
152 200
153/** 201/**
@@ -578,7 +626,7 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
578 longhaul_setup_voltagescaling(); 626 longhaul_setup_voltagescaling();
579 627
580 policy->governor = CPUFREQ_DEFAULT_GOVERNOR; 628 policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
581 policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; 629 policy->cpuinfo.transition_latency = 200000; /* nsec */
582 policy->cur = calc_speed(longhaul_get_cpu_mult()); 630 policy->cur = calc_speed(longhaul_get_cpu_mult());
583 631
584 ret = cpufreq_frequency_table_cpuinfo(policy, longhaul_table); 632 ret = cpufreq_frequency_table_cpuinfo(policy, longhaul_table);