diff options
-rw-r--r-- | arch/x86/kernel/hpet.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/quirks.c | 103 | ||||
-rw-r--r-- | include/asm-x86/hpet.h | 2 | ||||
-rw-r--r-- | include/linux/pci_ids.h | 1 |
4 files changed, 105 insertions, 3 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 |
diff --git a/include/asm-x86/hpet.h b/include/asm-x86/hpet.h index 47de4b8cdda9..d4ab6db050b6 100644 --- a/include/asm-x86/hpet.h +++ b/include/asm-x86/hpet.h | |||
@@ -67,7 +67,7 @@ extern unsigned long force_hpet_address; | |||
67 | extern int is_hpet_enabled(void); | 67 | extern int is_hpet_enabled(void); |
68 | extern int hpet_enable(void); | 68 | extern int hpet_enable(void); |
69 | extern unsigned long hpet_readl(unsigned long a); | 69 | extern unsigned long hpet_readl(unsigned long a); |
70 | extern void ich_force_hpet_resume(void); | 70 | extern void force_hpet_resume(void); |
71 | 71 | ||
72 | #ifdef CONFIG_HPET_EMULATE_RTC | 72 | #ifdef CONFIG_HPET_EMULATE_RTC |
73 | 73 | ||
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 3948708c42ca..584741bb73b3 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h | |||
@@ -2242,6 +2242,7 @@ | |||
2242 | #define PCI_DEVICE_ID_INTEL_82801EB_5 0x24d5 | 2242 | #define PCI_DEVICE_ID_INTEL_82801EB_5 0x24d5 |
2243 | #define PCI_DEVICE_ID_INTEL_82801EB_6 0x24d6 | 2243 | #define PCI_DEVICE_ID_INTEL_82801EB_6 0x24d6 |
2244 | #define PCI_DEVICE_ID_INTEL_82801EB_11 0x24db | 2244 | #define PCI_DEVICE_ID_INTEL_82801EB_11 0x24db |
2245 | #define PCI_DEVICE_ID_INTEL_82801EB_12 0x24dc | ||
2245 | #define PCI_DEVICE_ID_INTEL_82801EB_13 0x24dd | 2246 | #define PCI_DEVICE_ID_INTEL_82801EB_13 0x24dd |
2246 | #define PCI_DEVICE_ID_INTEL_ESB_1 0x25a1 | 2247 | #define PCI_DEVICE_ID_INTEL_ESB_1 0x25a1 |
2247 | #define PCI_DEVICE_ID_INTEL_ESB_2 0x25a2 | 2248 | #define PCI_DEVICE_ID_INTEL_ESB_2 0x25a2 |