1 | /*␊ |
2 | * Force HPET enabled, via fix from:␊ |
3 | *␊ |
4 | * http://forum.voodooprojects.org/index.php/topic,1596.0.html␊ |
5 | */␊ |
6 | ␊ |
7 | //#include "libsaio.h"␊ |
8 | #include "boot.h"␊ |
9 | #include "pci.h"␊ |
10 | #include "hpet.h"␊ |
11 | #include "modules.h"␊ |
12 | ␊ |
13 | /*#ifndef DEBUG_HPET␊ |
14 | #define DEBUG_HPET 0␊ |
15 | #endif␊ |
16 | ␊ |
17 | #if DEBUG_HPET␊ |
18 | #define DBG(x...) printf(x)␊ |
19 | #else␊ |
20 | #define DBG(x...)␊ |
21 | #endif␊ |
22 | */␊ |
23 | ␊ |
24 | ␊ |
25 | void force_enable_hpet_intel(pci_dt_t *lpc_dev);␊ |
26 | void force_enable_hpet_via(pci_dt_t *lpc_dev);␊ |
27 | ␊ |
28 | ␊ |
29 | void HPET_hook(void* arg1, void* arg2, void* arg3, void* arg4)␊ |
30 | {␉␊ |
31 | ␉bool do_enable_hpet = false;␊ |
32 | ␉pci_dt_t* current = arg1;␊ |
33 | ␉␊ |
34 | ␉if (current->class_id != PCI_CLASS_BRIDGE_ISA)␊ |
35 | ␉␉return;␊ |
36 | ␉␊ |
37 | ␉getBoolForKey(kForceHPETKey, &do_enable_hpet, &bootInfo->bootConfig);␊ |
38 | ␉␊ |
39 | ␉if (do_enable_hpet)␊ |
40 | ␉␉force_enable_hpet(current);␊ |
41 | }␊ |
42 | ␊ |
43 | void HPET_start()␊ |
44 | {␊ |
45 | ␉register_hook_callback("PCIDevice", &HPET_hook);␊ |
46 | }␊ |
47 | ␊ |
48 | // Intel chipsets␊ |
49 | static struct lpc_controller_t lpc_controllers_intel[] = {␊ |
50 | ␊ |
51 | ␉// Default unknown chipset␊ |
52 | ␉{ 0, 0, "" },␊ |
53 | ␊ |
54 | ␉// Intel␊ |
55 | ␉{ 0x8086, 0x24dc, "ICH5" },␊ |
56 | ␉{ 0x8086, 0x2640, "ICH6" },␊ |
57 | ␉{ 0x8086, 0x2641, "ICH6M" },␊ |
58 | ␉␊ |
59 | ␉{ 0x8086, 0x27b0, "ICH7 DH" },␊ |
60 | ␉{ 0x8086, 0x27b8, "ICH7" },␊ |
61 | ␉{ 0x8086, 0x27b9, "ICH7M" },␊ |
62 | ␉{ 0x8086, 0x27bd, "ICH7M DH" },␊ |
63 | ␉␊ |
64 | ␉{ 0x8086, 0x27bc, "NM10" }, // Atom␊ |
65 | ␉␊ |
66 | ␉{ 0x8086, 0x2810, "ICH8R" },␊ |
67 | ␉{ 0x8086, 0x2811, "ICH8M-E" },␊ |
68 | ␉{ 0x8086, 0x2812, "ICH8DH" },␊ |
69 | ␉{ 0x8086, 0x2814, "ICH8DO" },␊ |
70 | ␉{ 0x8086, 0x2815, "ICH8M" },␊ |
71 | ␉␊ |
72 | ␉{ 0x8086, 0x2912, "ICH9DH" },␊ |
73 | ␉{ 0x8086, 0x2914, "ICH9DO" },␊ |
74 | ␉{ 0x8086, 0x2916, "ICH9R" },␊ |
75 | ␉{ 0x8086, 0x2917, "ICH9M-E" },␊ |
76 | ␉{ 0x8086, 0x2918, "ICH9" },␊ |
77 | ␉{ 0x8086, 0x2919, "ICH9M" },␊ |
78 | ␉␊ |
79 | ␉{ 0x8086, 0x3a14, "ICH10DO" },␊ |
80 | ␉{ 0x8086, 0x3a16, "ICH10R" },␊ |
81 | ␉{ 0x8086, 0x3a18, "ICH10" },␊ |
82 | ␉{ 0x8086, 0x3a1a, "ICH10D" },␊ |
83 | };␊ |
84 | ␊ |
85 | // VIA chipsets␊ |
86 | static struct lpc_controller_t lpc_controllers_via[] = {␊ |
87 | ␉// Default unknown chipset␊ |
88 | ␉{ 0, 0, "" },␊ |
89 | ␉␊ |
90 | ␉{ 0x1106, 0x3372, "VT8237S" },␊ |
91 | };␊ |
92 | ␊ |
93 | void force_enable_hpet(pci_dt_t *lpc_dev)␊ |
94 | {␊ |
95 | ␉switch(lpc_dev->vendor_id)␊ |
96 | ␉{␊ |
97 | ␉␉case 0x8086:␊ |
98 | ␉␉␉force_enable_hpet_intel(lpc_dev);␊ |
99 | ␉␉␉break;␊ |
100 | ␉␉␊ |
101 | ␉␉case 0x1106:␊ |
102 | ␉␉␉force_enable_hpet_via(lpc_dev);␊ |
103 | ␉␉␉break;␊ |
104 | ␉}␊ |
105 | ␉␊ |
106 | /*#if DEBUG_HPET␊ |
107 | ␉pause();␊ |
108 | #endif*/␊ |
109 | }␊ |
110 | ␊ |
111 | void force_enable_hpet_via(pci_dt_t *lpc_dev)␊ |
112 | {␉␊ |
113 | ␉int␉␉ i;␊ |
114 | ␉uint32_t val, hpet_address = 0xFED00000;␊ |
115 | ␉␊ |
116 | ␉for (i = 1; i < sizeof(lpc_controllers_via) / sizeof(lpc_controllers_via[0]); i++)␊ |
117 | ␉{␊ |
118 | ␉␉if ((lpc_controllers_via[i].vendor == lpc_dev->vendor_id) ␊ |
119 | ␉␉␉&& (lpc_controllers_via[i].device == lpc_dev->device_id))␊ |
120 | ␉␉{␉␊ |
121 | ␉␉␉val = pci_config_read32(lpc_dev->dev.addr, 0x68);␊ |
122 | ␉␉␉␊ |
123 | ␉␉␉verbose("VIA %s LPC Interface [%04x:%04x], MMIO\n", ␊ |
124 | ␉␉␉␉lpc_controllers_via[i].name, lpc_dev->vendor_id, lpc_dev->device_id);␊ |
125 | ␉␉␉␊ |
126 | ␉␉␉if (val & 0x80)␊ |
127 | ␉␉␉{␊ |
128 | ␉␉␉␉hpet_address = (val & ~0x3ff);␊ |
129 | ␉␉␉␉verbose("HPET at 0x%lx\n", hpet_address);␊ |
130 | ␉␉␉}␊ |
131 | ␉␉␉else ␊ |
132 | ␉␉␉{␊ |
133 | ␉␉␉␉val = 0xfed00000 | 0x80;␊ |
134 | ␉␉␉␉␊ |
135 | ␉␉␉␉pci_config_write32(lpc_dev->dev.addr, 0x68, val);␊ |
136 | ␉␉␉␉␊ |
137 | ␉␉␉␉val = pci_config_read32(lpc_dev->dev.addr, 0x68);␊ |
138 | ␉␉␉␉␊ |
139 | ␉␉␉␉if (val & 0x80)␊ |
140 | ␉␉␉␉{␊ |
141 | ␉␉␉␉␉hpet_address = (val & ~0x3ff);␊ |
142 | ␉␉␉␉␉verbose("Force enabled HPET at 0x%lx\n", hpet_address);␊ |
143 | ␉␉␉␉}␊ |
144 | ␉␉␉␉else␊ |
145 | ␉␉␉␉{␊ |
146 | ␉␉␉␉␉verbose("Unable to enable HPET");␊ |
147 | ␉␉␉␉}␊ |
148 | ␉␉␉}␊ |
149 | ␉␉}␊ |
150 | ␉}␊ |
151 | }␊ |
152 | ␊ |
153 | void force_enable_hpet_intel(pci_dt_t *lpc_dev)␊ |
154 | {␊ |
155 | ␉int␉␉␉i;␊ |
156 | ␉void␉ *rcba;␊ |
157 | ␉uint32_t␉val, hpet_address = 0xFED00000;␊ |
158 | ␉␊ |
159 | ␉/* LPC on Intel ICH is always (?) at 00:1f.0 */␊ |
160 | ␉for(i = 1; i < sizeof(lpc_controllers_intel) / sizeof(lpc_controllers_intel[0]); i++)␊ |
161 | ␉{␊ |
162 | ␉␉if ((lpc_controllers_intel[i].vendor == lpc_dev->vendor_id) ␊ |
163 | ␉␉␉&& (lpc_controllers_intel[i].device == lpc_dev->device_id))␊ |
164 | ␉␉{␊ |
165 | ␉␉␉rcba = (void *)(pci_config_read32(lpc_dev->dev.addr, 0xF0) & 0xFFFFC000);␊ |
166 | ␉␉␉␊ |
167 | ␉␉␉verbose("Intel(R) %s LPC Interface [%04x:%04x], MMIO @ 0x%lx\n", ␊ |
168 | ␉␉␉␉lpc_controllers_intel[i].name, lpc_dev->vendor_id, lpc_dev->device_id, rcba);␊ |
169 | ␉␉␉␊ |
170 | ␉␉␉if (rcba == 0)␊ |
171 | ␉␉␉␉verbose(" RCBA disabled; cannot force enable HPET\n");␊ |
172 | ␉␉␉else␊ |
173 | ␉␉␉{␊ |
174 | ␉␉␉␉val = REG32(rcba, 0x3404);␊ |
175 | ␉␉␉␉␊ |
176 | ␉␉␉␉if (val & 0x80)␊ |
177 | ␉␉␉␉{␊ |
178 | ␉␉␉␉␉// HPET is enabled in HPTC. Just not reported by BIOS␊ |
179 | ␉␉␉␉␉verbose(" HPET is enabled in HPTC, just not reported by BIOS\n");␊ |
180 | ␉␉␉␉␉hpet_address |= (val & 3) << 12 ;␊ |
181 | ␉␉␉␉␉verbose(" HPET MMIO @ 0x%lx\n", hpet_address);␊ |
182 | ␉␉␉␉}␊ |
183 | ␉␉␉␉else␊ |
184 | ␉␉␉␉{␊ |
185 | ␉␉␉␉␉// HPET disabled in HPTC. Trying to enable␊ |
186 | ␉␉␉␉␉verbose(" HPET is disabled in HPTC, trying to enable\n");␉␉␉␉␉␉␉␉␉␊ |
187 | ␉␉␉␉␉REG32(rcba, 0x3404) = val | 0x80;␊ |
188 | ␉␉␉␉␉hpet_address |= (val & 3) << 12 ;␊ |
189 | ␉␉␉␉␉verbose(" Force enabled HPET, MMIO @ 0x%lx\n", hpet_address);␊ |
190 | ␉␉␉␉}␊ |
191 | ␉␉␉␉␊ |
192 | ␉␉␉␉// verify if the job is done␊ |
193 | ␉␉␉␉val = REG32(rcba, 0x3404);␊ |
194 | ␉␉␉␉␊ |
195 | ␉␉␉␉if (!(val & 0x80))␊ |
196 | ␉␉␉␉␉verbose(" Failed to force enable HPET\n");␊ |
197 | ␉␉␉}␊ |
198 | ␉␉␉break;␊ |
199 | ␉␉}␊ |
200 | ␉}␊ |
201 | }␊ |
202 | |