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 |
