diff options
author | Venki Pallipadi <venkatesh.pallipadi@intel.com> | 2007-10-12 17:04:24 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@inhelltoy.tec.linutronix.de> | 2007-10-12 17:04:24 -0400 |
commit | bfe0c1cc6456bba1f4e3cc1fe29c0ea578ac763a (patch) | |
tree | 7bf60e24749a33fdac079a9c9829da24cf468e00 /arch | |
parent | 59c69f2a51b41e9886b85f61c04e8d0d2a35f37b (diff) |
x86: HPET force enable for ICH5
force_enable hpet for ICH5.
[ Build fixes from Andrew Morton ]
Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
Cc: Andi Kleen <ak@suse.de>
Cc: john stultz <johnstul@us.ibm.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/hpet.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/quirks.c | 103 |
2 files changed, 103 insertions, 2 deletions
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index a6c68915d2a9..f8367074da0d 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c | |||
@@ -181,7 +181,7 @@ static void hpet_start_counter(void) | |||
181 | 181 | ||
182 | static void hpet_resume_device(void) | 182 | static void hpet_resume_device(void) |
183 | { | 183 | { |
184 | ich_force_hpet_resume(); | 184 | force_hpet_resume(); |
185 | } | 185 | } |
186 | 186 | ||
187 | static void hpet_restart_counter(void) | 187 | static void hpet_restart_counter(void) |
diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c index d3ac703867d6..79133b1c2595 100644 --- a/arch/x86/kernel/quirks.c +++ b/arch/x86/kernel/quirks.c | |||
@@ -53,9 +53,15 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, quir | |||
53 | #if defined(CONFIG_HPET_TIMER) | 53 | #if defined(CONFIG_HPET_TIMER) |
54 | unsigned long force_hpet_address; | 54 | unsigned long force_hpet_address; |
55 | 55 | ||
56 | static enum { | ||
57 | NONE_FORCE_HPET_RESUME, | ||
58 | OLD_ICH_FORCE_HPET_RESUME, | ||
59 | ICH_FORCE_HPET_RESUME | ||
60 | } force_hpet_resume_type; | ||
61 | |||
56 | static void __iomem *rcba_base; | 62 | static void __iomem *rcba_base; |
57 | 63 | ||
58 | void ich_force_hpet_resume(void) | 64 | static void ich_force_hpet_resume(void) |
59 | { | 65 | { |
60 | u32 val; | 66 | u32 val; |
61 | 67 | ||
@@ -133,6 +139,7 @@ static void ich_force_enable_hpet(struct pci_dev *dev) | |||
133 | iounmap(rcba_base); | 139 | iounmap(rcba_base); |
134 | printk(KERN_DEBUG "Failed to force enable HPET\n"); | 140 | printk(KERN_DEBUG "Failed to force enable HPET\n"); |
135 | } else { | 141 | } else { |
142 | force_hpet_resume_type = ICH_FORCE_HPET_RESUME; | ||
136 | printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n", | 143 | printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n", |
137 | force_hpet_address); | 144 | force_hpet_address); |
138 | } | 145 | } |
@@ -148,4 +155,98 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31, | |||
148 | ich_force_enable_hpet); | 155 | ich_force_enable_hpet); |
149 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_1, | 156 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_1, |
150 | ich_force_enable_hpet); | 157 | ich_force_enable_hpet); |
158 | |||
159 | |||
160 | static struct pci_dev *cached_dev; | ||
161 | |||
162 | static void old_ich_force_hpet_resume(void) | ||
163 | { | ||
164 | u32 val; | ||
165 | u32 uninitialized_var(gen_cntl); | ||
166 | |||
167 | if (!force_hpet_address || !cached_dev) | ||
168 | return; | ||
169 | |||
170 | pci_read_config_dword(cached_dev, 0xD0, &gen_cntl); | ||
171 | gen_cntl &= (~(0x7 << 15)); | ||
172 | gen_cntl |= (0x4 << 15); | ||
173 | |||
174 | pci_write_config_dword(cached_dev, 0xD0, gen_cntl); | ||
175 | pci_read_config_dword(cached_dev, 0xD0, &gen_cntl); | ||
176 | val = gen_cntl >> 15; | ||
177 | val &= 0x7; | ||
178 | if (val == 0x4) | ||
179 | printk(KERN_DEBUG "Force enabled HPET at resume\n"); | ||
180 | else | ||
181 | BUG(); | ||
182 | } | ||
183 | |||
184 | static void old_ich_force_enable_hpet(struct pci_dev *dev) | ||
185 | { | ||
186 | u32 val; | ||
187 | u32 uninitialized_var(gen_cntl); | ||
188 | |||
189 | if (hpet_address || force_hpet_address) | ||
190 | return; | ||
191 | |||
192 | pci_read_config_dword(dev, 0xD0, &gen_cntl); | ||
193 | /* | ||
194 | * Bit 17 is HPET enable bit. | ||
195 | * Bit 16:15 control the HPET base address. | ||
196 | */ | ||
197 | val = gen_cntl >> 15; | ||
198 | val &= 0x7; | ||
199 | if (val & 0x4) { | ||
200 | val &= 0x3; | ||
201 | force_hpet_address = 0xFED00000 | (val << 12); | ||
202 | printk(KERN_DEBUG "HPET at base address 0x%lx\n", | ||
203 | force_hpet_address); | ||
204 | cached_dev = dev; | ||
205 | return; | ||
206 | } | ||
207 | |||
208 | /* | ||
209 | * HPET is disabled. Trying enabling at FED00000 and check | ||
210 | * whether it sticks | ||
211 | */ | ||
212 | gen_cntl &= (~(0x7 << 15)); | ||
213 | gen_cntl |= (0x4 << 15); | ||
214 | pci_write_config_dword(dev, 0xD0, gen_cntl); | ||
215 | |||
216 | pci_read_config_dword(dev, 0xD0, &gen_cntl); | ||
217 | |||
218 | val = gen_cntl >> 15; | ||
219 | val &= 0x7; | ||
220 | if (val & 0x4) { | ||
221 | /* HPET is enabled in HPTC. Just not reported by BIOS */ | ||
222 | val &= 0x3; | ||
223 | force_hpet_address = 0xFED00000 | (val << 12); | ||
224 | printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n", | ||
225 | force_hpet_address); | ||
226 | force_hpet_resume_type = OLD_ICH_FORCE_HPET_RESUME; | ||
227 | return; | ||
228 | } | ||
229 | |||
230 | printk(KERN_DEBUG "Failed to force enable HPET\n"); | ||
231 | } | ||
232 | |||
233 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, | ||
234 | old_ich_force_enable_hpet); | ||
235 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_12, | ||
236 | old_ich_force_enable_hpet); | ||
237 | |||
238 | void force_hpet_resume(void) | ||
239 | { | ||
240 | switch (force_hpet_resume_type) { | ||
241 | case ICH_FORCE_HPET_RESUME: | ||
242 | return ich_force_hpet_resume(); | ||
243 | |||
244 | case OLD_ICH_FORCE_HPET_RESUME: | ||
245 | return old_ich_force_hpet_resume(); | ||
246 | |||
247 | default: | ||
248 | break; | ||
249 | } | ||
250 | } | ||
251 | |||
151 | #endif | 252 | #endif |