Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/i386/modules/HPET/HPET.c

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

Archive Download this file

Revision: 1913