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