Chameleon

Chameleon Svn Source Tree

Root/branches/ErmaC/Enoch/i386/libsaio/hpet.c

1/*
2 * Copyright (c) 2009 Evan Lojewski. All rights reserved.
3 */
4
5/*
6 * High Precision Event Timer (HPET)
7 */
8
9#include "libsaio.h"
10#include "pci.h"
11#include "hpet.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
23void force_enable_hpet_intel(pci_dt_t *lpc_dev);
24void force_enable_hpet_nvidia(pci_dt_t *lpc_dev);
25void force_enable_hpet_via(pci_dt_t *lpc_dev);
26
27/*
28 * Force HPET enabled
29 *
30 * VIA fix from http://forum.voodooprojects.org/index.php/topic,1596.0.html
31 */
32
33static struct lpc_controller_t lpc_controllers_intel[] = {
34
35// Default unknown chipset
36{ 0, 0, "" },
37
38// Intel
39{ 0x8086, 0x24dc, "ICH5" },
40{ 0x8086, 0x2640, "ICH6" },
41{ 0x8086, 0x2641, "ICH6M" },
42{ 0x8086, 0x2670, "631xESB" },
43
44{ 0x8086, 0x27b0, "ICH7 DH" },
45{ 0x8086, 0x27b8, "ICH7" },
46{ 0x8086, 0x27b9, "ICH7M" },
47{ 0x8086, 0x27bd, "ICH7M DH" },
48
49{ 0x8086, 0x27bc, "NM10" },
50
51{ 0x8086, 0x2810, "ICH8R" },
52{ 0x8086, 0x2811, "ICH8M-E" },
53{ 0x8086, 0x2812, "ICH8DH" },
54{ 0x8086, 0x2814, "ICH8DO" },
55{ 0x8086, 0x2815, "ICH8M" },
56
57{ 0x8086, 0x2912, "ICH9DH" },
58{ 0x8086, 0x2914, "ICH9DO" },
59{ 0x8086, 0x2916, "ICH9R" },
60{ 0x8086, 0x2917, "ICH9M-E" },
61{ 0x8086, 0x2918, "ICH9" },
62{ 0x8086, 0x2919, "ICH9M" },
63
64{ 0x8086, 0x3a14, "ICH10DO" },
65{ 0x8086, 0x3a16, "ICH10R" },
66{ 0x8086, 0x3a18, "ICH10" },
67{ 0x8086, 0x3a1a, "ICH10D" },
68{ 0x8086, 0x3b00, "5 Series" },
69 { 0x8086, 0x3b01, "Mobile 5 Series" },
70{ 0x8086, 0x3b02, "5 Series" },
71{ 0x8086, 0x3b09, "Mobile 5 Series" },
72
73{ 0x8086, 0x1c41, "Mobile SFF 6 Series" },
74{ 0x8086, 0x1c42, "6 Series" },
75{ 0x8086, 0x1c43, "Mobile 6 Series" },
76{ 0x8086, 0x1c44, "Z68" },
77{ 0x8086, 0x1c46, "UM67" },
78{ 0x8086, 0x1c47, "UM67" },
79{ 0x8086, 0x1c49, "HM65" },
80{ 0x8086, 0x1c4a, "H67" },
81{ 0x8086, 0x1c4b, "HM67" },
82{ 0x8086, 0x1c4c, "Q65" },
83{ 0x8086, 0x1c4d, "QS67" },
84{ 0x8086, 0x1c4e, "Q67" },
85{ 0x8086, 0x1c4f, "QM67" },
86{ 0x8086, 0x1c50, "B65" },
87{ 0x8086, 0x1c52, "C202" },
88{ 0x8086, 0x1c54, "C204" },
89{ 0x8086, 0x1c56, "C206" },
90{ 0x8086, 0x1c5c, "H61" },
91
92{ 0x8086, 0x1c58, "B65" },
93{ 0x8086, 0x1c59, "HM67" },
94{ 0x8086, 0x1c5a, "Q67" },
95
96//{ 0x8086, 0x1dc1, "PATSBURG" },
97
98{ 0x8086, 0x1e41, "Mobile C216/7 Series" },
99{ 0x8086, 0x1e42, "Mobile 7 Series" },
100{ 0x8086, 0x1e43, "Mobile 7 Series" },
101{ 0x8086, 0x1e44, "Z77" },
102{ 0x8086, 0x1e45, "H71" },
103{ 0x8086, 0x1e46, "Z75" },
104{ 0x8086, 0x1e47, "Q77" },
105{ 0x8086, 0x1e48, "Q75" },
106{ 0x8086, 0x1e49, "B75" },
107{ 0x8086, 0x1e4a, "H77" },
108{ 0x8086, 0x1e4b, "B75" },
109
110{ 0x8086, 0x8119, "SCH 8119" },
111
112};
113
114static struct lpc_controller_t lpc_controllers_nvidia[] = {
115
116// Default unknown chipset
117{ 0, 0, "" },
118
119// nVidia
120{ 0x10de, 0x0aac, "MCP79" },
121{ 0x10de, 0x0aae, "MCP79" },
122{ 0x10de, 0x0aaf, "MCP79" },
123{ 0x10de, 0x0d80, "MCP89" },
124{ 0x10de, 0x0d81, "MCP89" },
125{ 0x10de, 0x0d82, "MCP89" },
126{ 0x10de, 0x0d83, "MCP89" },
127
128};
129
130static struct lpc_controller_t lpc_controllers_via[] = {
131// Default unknown chipset
132{ 0, 0, "" },
133
134{ 0x1106, 0x3372, "VT8237S" },
135};
136
137/* ErmaC add lpc for nVidia */
138void force_enable_hpet_nvidia(pci_dt_t *lpc_dev)
139{
140uint32_tval, hpet_address = 0xFED00000;
141int i;
142void*rcba;
143
144for(i = 1; i < sizeof(lpc_controllers_nvidia) / sizeof(lpc_controllers_nvidia[0]); i++)
145{
146if ((lpc_controllers_nvidia[i].vendor == lpc_dev->vendor_id) && (lpc_controllers_nvidia[i].device == lpc_dev->device_id))
147{
148
149rcba = (void *)(pci_config_read32(lpc_dev->dev.addr, 0xF0) & 0xFFFFC000);
150
151DBG("nVidia(R) %s LPC Interface [%04x:%04x], MMIO @ 0x%lx\n",
152lpc_controllers_nvidia[i].name, lpc_dev->vendor_id, lpc_dev->device_id, rcba);
153
154if (rcba == 0)
155{
156printf(" RCBA disabled; cannot force enable HPET\n");
157}
158else
159{
160val = REG32(rcba, 0x3404);
161if (val & 0x80)
162{
163// HPET is enabled in HPTC. Just not reported by BIOS
164DBG(" HPET is enabled in HPTC, just not reported by BIOS\n");
165hpet_address |= (val & 3) << 12 ;
166DBG(" HPET MMIO @ 0x%lx\n", hpet_address);
167}
168else
169{
170// HPET disabled in HPTC. Trying to enable
171DBG(" HPET is disabled in HPTC, trying to enable\n");
172REG32(rcba, 0x3404) = val | 0x80;
173hpet_address |= (val & 3) << 12 ;
174DBG(" Force enabled HPET, MMIO @ 0x%lx\n", hpet_address);
175}
176
177// verify if the job is done
178val = REG32(rcba, 0x3404);
179if (!(val & 0x80))
180{
181printf(" Failed to force enable HPET\n");
182}
183}
184break;
185}
186}
187}
188
189void force_enable_hpet_via(pci_dt_t *lpc_dev)
190{
191uint32_tval, hpet_address = 0xFED00000;
192int i;
193
194for(i = 1; i < sizeof(lpc_controllers_via) / sizeof(lpc_controllers_via[0]); i++)
195{
196if ((lpc_controllers_via[i].vendor == lpc_dev->vendor_id) && (lpc_controllers_via[i].device == lpc_dev->device_id))
197{
198val = pci_config_read32(lpc_dev->dev.addr, 0x68);
199
200DBG("VIA %s LPC Interface [%04x:%04x], MMIO\n",
201lpc_controllers_via[i].name, lpc_dev->vendor_id, lpc_dev->device_id);
202
203if (val & 0x80)
204{
205hpet_address = (val & ~0x3ff);
206DBG("HPET at 0x%lx\n", hpet_address);
207}
208else
209{
210val = 0xfed00000 | 0x80;
211pci_config_write32(lpc_dev->dev.addr, 0x68, val);
212val = pci_config_read32(lpc_dev->dev.addr, 0x68);
213if (val & 0x80)
214{
215hpet_address = (val & ~0x3ff);
216DBG("Force enabled HPET at 0x%lx\n", hpet_address);
217}
218else
219{
220DBG("Unable to enable HPET");
221}
222}
223}
224}
225}
226
227void force_enable_hpet_intel(pci_dt_t *lpc_dev)
228{
229uint32_tval, hpet_address = 0xFED00000;
230int i;
231void*rcba;
232
233/* LPC on Intel ICH is always (?) at 00:1f.0 */
234for(i = 1; i < sizeof(lpc_controllers_intel) / sizeof(lpc_controllers_intel[0]); i++)
235{
236if ((lpc_controllers_intel[i].vendor == lpc_dev->vendor_id) && (lpc_controllers_intel[i].device == lpc_dev->device_id))
237{
238
239rcba = (void *)(pci_config_read32(lpc_dev->dev.addr, 0xF0) & 0xFFFFC000);
240
241DBG("Intel(R) %s LPC Interface [%04x:%04x], MMIO @ 0x%lx\n",
242lpc_controllers_intel[i].name, lpc_dev->vendor_id, lpc_dev->device_id, rcba);
243
244if (rcba == 0)
245{
246printf(" RCBA disabled; cannot force enable HPET\n");
247}
248else
249{
250val = REG32(rcba, 0x3404);
251if (val & 0x80)
252{
253// HPET is enabled in HPTC. Just not reported by BIOS
254DBG(" HPET is enabled in HPTC, just not reported by BIOS\n");
255hpet_address |= (val & 3) << 12 ;
256DBG(" HPET MMIO @ 0x%lx\n", hpet_address);
257}
258else
259{
260// HPET disabled in HPTC. Trying to enable
261DBG(" HPET is disabled in HPTC, trying to enable\n");
262REG32(rcba, 0x3404) = val | 0x80;
263hpet_address |= (val & 3) << 12 ;
264DBG(" Force enabled HPET, MMIO @ 0x%lx\n", hpet_address);
265}
266
267// verify if the job is done
268val = REG32(rcba, 0x3404);
269if (!(val & 0x80))
270{
271printf(" Failed to force enable HPET\n");
272}
273}
274break;
275}
276}
277}
278
279void force_enable_hpet(pci_dt_t *lpc_dev)
280{
281switch(lpc_dev->vendor_id)
282{
283case 0x8086:
284force_enable_hpet_intel(lpc_dev);
285break;
286
287case 0x10de:
288force_enable_hpet_nvidia(lpc_dev);
289break;
290
291case 0x1106:
292force_enable_hpet_via(lpc_dev);
293break;
294}
295
296#if DEBUG_HPET
297printf("Press [Enter] to continue...\n");
298getchar();
299#endif
300
301}
302

Archive Download this file

Revision: 2458