Root/
Source at commit HEAD created 5 years 6 days ago. By ifabio, Few update to kernelPatcher (Credits to CrazyBirdy) | |
---|---|
1 | /*␊ |
2 | * dram controller access and scan from the pci host controller␊ |
3 | * Integrated and adapted for chameleon 2.0 RC5 by Rekursor from bs0d work␊ |
4 | * original source comes from:␊ |
5 | *␊ |
6 | * memtest86␊ |
7 | *␊ |
8 | * Released under version 2 of the Gnu Public License.␊ |
9 | * By Chris Brady, cbrady@sgi.com␊ |
10 | * ----------------------------------------------------␊ |
11 | * MemTest86+ V4.00 Specific code (GPL V2.0)␊ |
12 | * By Samuel DEMEULEMEESTER, sdemeule@memtest.org␊ |
13 | * http://www.canardpc.com - http://www.memtest.org␊ |
14 | */␊ |
15 | ␊ |
16 | #include "config.h"␊ |
17 | #include "libsaio.h"␊ |
18 | #include "bootstruct.h"␊ |
19 | #include "pci.h"␊ |
20 | #include "platform.h"␊ |
21 | #include "dram_controllers.h"␊ |
22 | ␊ |
23 | #if DEBUG_DRAM␊ |
24 | ␉#define DBG(x...) printf(x)␊ |
25 | #else␊ |
26 | ␉#define DBG(x...)␊ |
27 | #endif␊ |
28 | ␊ |
29 | /*␊ |
30 | * Initialise memory controller functions␊ |
31 | */␊ |
32 | ␊ |
33 | // Setup P35 Memory Controller␊ |
34 | static void setup_p35(pci_dt_t *dram_dev)␊ |
35 | {␊ |
36 | ␉uint32_t dev0;␊ |
37 | ␊ |
38 | ␉// Activate MMR I/O␊ |
39 | ␉dev0 = pci_config_read32(dram_dev->dev.addr, 0x48);␊ |
40 | ␉if (!(dev0 & 0x1)) {␊ |
41 | ␉␉pci_config_write8(dram_dev->dev.addr, 0x48, (dev0 | 1));␊ |
42 | ␉}␊ |
43 | }␊ |
44 | ␊ |
45 | int nhm_bus = 0x3F;␊ |
46 | ␊ |
47 | // Setup Nehalem Integrated Memory Controller␊ |
48 | static void setup_nhm(pci_dt_t *dram_dev)␊ |
49 | {␊ |
50 | ␉static long possible_nhm_bus[] = {0xFF, 0x7F, 0x3F};␊ |
51 | ␉unsigned long did, vid;␊ |
52 | ␉int i;␊ |
53 | ␊ |
54 | ␉// Nehalem supports Scrubbing␊ |
55 | ␉// First, locate the PCI bus where the MCH is located␊ |
56 | ␉for(i = 0; i < (sizeof(possible_nhm_bus)/sizeof(possible_nhm_bus[0])); i++) {␊ |
57 | ␉␉vid = pci_config_read16(PCIADDR(possible_nhm_bus[i], 3, 4), PCI_VENDOR_ID);␊ |
58 | ␉␉did = pci_config_read16(PCIADDR(possible_nhm_bus[i], 3, 4), PCI_DEVICE_ID);␊ |
59 | ␉␉vid &= 0xFFFF;␊ |
60 | ␉␉did &= 0xFF00;␊ |
61 | ␊ |
62 | ␉␉if(vid == 0x8086 && did >= 0x2C00) {␊ |
63 | ␉␉␉nhm_bus = possible_nhm_bus[i]; ␊ |
64 | ␉␉}␊ |
65 | ␉}␊ |
66 | }␊ |
67 | ␊ |
68 | /*␊ |
69 | * Retrieve memory controller fsb functions␊ |
70 | */␊ |
71 | ␊ |
72 | ␊ |
73 | // Get i965 Memory Speed␊ |
74 | static void get_fsb_i965(pci_dt_t *dram_dev)␊ |
75 | {␊ |
76 | ␉uint32_t dev0, mch_ratio, mch_cfg, mch_fsb;␊ |
77 | ␊ |
78 | ␉long *ptr;␊ |
79 | ␊ |
80 | ␉// Find Ratio␊ |
81 | ␉dev0 = pci_config_read32(dram_dev->dev.addr, 0x48);␊ |
82 | ␉dev0 &= 0xFFFFC000;␊ |
83 | ␉ptr = (long*)(dev0 + 0xC00);␊ |
84 | ␉mch_cfg = *ptr & 0xFFFF;␊ |
85 | ␊ |
86 | ␉mch_ratio = 100000;␊ |
87 | ␊ |
88 | ␉switch (mch_cfg & 7) {␊ |
89 | ␉␉case 0: mch_fsb = 1066; break;␊ |
90 | ␉␉case 1: mch_fsb = 533; break;␊ |
91 | ␉␉default:␊ |
92 | ␉␉case 2: mch_fsb = 800; break;␊ |
93 | ␉␉case 3: mch_fsb = 667; break;␊ |
94 | ␉␉case 4: mch_fsb = 1333; break;␊ |
95 | ␉␉case 6: mch_fsb = 1600; break;␊ |
96 | ␉}␊ |
97 | ␊ |
98 | ␉DBG("mch_fsb %d\n", mch_fsb);␊ |
99 | ␊ |
100 | ␉switch (mch_fsb) {␊ |
101 | ␉␉case 533:␊ |
102 | ␉␉switch ((mch_cfg >> 4) & 7) {␊ |
103 | ␉␉␉case 1:␉mch_ratio = 200000; break;␊ |
104 | ␉␉␉case 2:␉mch_ratio = 250000; break;␊ |
105 | ␉␉␉case 3:␉mch_ratio = 300000; break;␊ |
106 | ␉␉}␊ |
107 | ␉␉break;␊ |
108 | ␊ |
109 | ␉␉default:␊ |
110 | ␉␉case 800:␊ |
111 | ␉␉switch ((mch_cfg >> 4) & 7) {␊ |
112 | ␉␉␉case 0:␉mch_ratio = 100000; break;␊ |
113 | ␉␉␉case 1:␉mch_ratio = 125000; break;␊ |
114 | ␉␉␉case 2:␉mch_ratio = 166667; break; // 1.666666667␊ |
115 | ␉␉␉case 3:␉mch_ratio = 200000; break;␊ |
116 | ␉␉␉case 4:␉mch_ratio = 266667; break; // 2.666666667␊ |
117 | ␉␉␉case 5:␉mch_ratio = 333333; break; // 3.333333333␊ |
118 | ␉␉}␊ |
119 | ␉␉break;␊ |
120 | ␊ |
121 | ␉␉case 1066:␊ |
122 | ␉␉switch ((mch_cfg >> 4) & 7) {␊ |
123 | ␉␉␉case 1:␉mch_ratio = 100000; break;␊ |
124 | ␉␉␉case 2:␉mch_ratio = 125000; break;␊ |
125 | ␉␉␉case 3:␉mch_ratio = 150000; break;␊ |
126 | ␉␉␉case 4:␉mch_ratio = 200000; break;␊ |
127 | ␉␉␉case 5:␉mch_ratio = 250000; break;␊ |
128 | ␉␉}␊ |
129 | ␉␉break;␊ |
130 | ␊ |
131 | ␉␉case 1333:␊ |
132 | ␉␉switch ((mch_cfg >> 4) & 7) {␊ |
133 | ␉␉␉case 2:␉mch_ratio = 100000; break;␊ |
134 | ␉␉␉case 3:␉mch_ratio = 120000; break;␊ |
135 | ␉␉␉case 4:␉mch_ratio = 160000; break;␊ |
136 | ␉␉␉case 5:␉mch_ratio = 200000; break;␊ |
137 | ␉␉}␊ |
138 | ␉␉break;␊ |
139 | ␊ |
140 | ␉␉case 1600:␊ |
141 | ␉␉switch ((mch_cfg >> 4) & 7)␊ |
142 | ␉␉{␊ |
143 | ␉␉␉case 3:␉mch_ratio = 100000; break;␊ |
144 | ␉␉␉case 4:␉mch_ratio = 133333; break; // 1.333333333␊ |
145 | ␉␉␉case 5:␉mch_ratio = 150000; break;␊ |
146 | ␉␉␉case 6:␉mch_ratio = 200000; break;␊ |
147 | ␉␉}␊ |
148 | ␉␉break;␊ |
149 | ␉}␊ |
150 | ␊ |
151 | ␉DBG("mch_ratio %d\n", mch_ratio);␊ |
152 | ␊ |
153 | ␉// Compute RAM Frequency␊ |
154 | ␉Platform.RAM.Frequency = (Platform.CPU.FSBFrequency * mch_ratio) / 100000;␊ |
155 | ␊ |
156 | ␉DBG("ram_fsb %d\n", Platform.RAM.Frequency);␊ |
157 | ␊ |
158 | }␊ |
159 | ␊ |
160 | // Get i965m Memory Speed␊ |
161 | static void get_fsb_im965(pci_dt_t *dram_dev)␊ |
162 | {␊ |
163 | ␉uint32_t dev0, mch_ratio, mch_cfg, mch_fsb;␊ |
164 | ␊ |
165 | ␉long *ptr;␊ |
166 | ␊ |
167 | ␉// Find Ratio␊ |
168 | ␉dev0 = pci_config_read32(dram_dev->dev.addr, 0x48);␊ |
169 | ␉dev0 &= 0xFFFFC000;␊ |
170 | ␉ptr = (long*)(dev0 + 0xC00);␊ |
171 | ␉mch_cfg = *ptr & 0xFFFF;␊ |
172 | ␊ |
173 | ␉mch_ratio = 100000;␊ |
174 | ␊ |
175 | ␉switch (mch_cfg & 7) {␊ |
176 | ␉␉case 1: mch_fsb = 533; break;␊ |
177 | ␉␉default: ␊ |
178 | ␉␉case 2:␉mch_fsb = 800; break;␊ |
179 | ␉␉case 3:␉mch_fsb = 667; break;␊ |
180 | ␉␉case 6:␉mch_fsb = 1066; break;␊ |
181 | ␉}␊ |
182 | ␊ |
183 | ␉switch (mch_fsb) {␊ |
184 | ␉␉case 533:␊ |
185 | ␉␉␉switch ((mch_cfg >> 4) & 7) {␊ |
186 | ␉␉␉␉case 1:␉mch_ratio = 125000; break;␊ |
187 | ␉␉␉␉case 2:␉mch_ratio = 150000; break;␊ |
188 | ␉␉␉␉case 3:␉mch_ratio = 200000; break;␊ |
189 | ␉␉␉}␊ |
190 | ␉␉␉break;␊ |
191 | ␊ |
192 | ␉␉case 667:␊ |
193 | ␉␉␉switch ((mch_cfg >> 4)& 7) {␊ |
194 | ␉␉␉␉case 1:␉mch_ratio = 100000; break;␊ |
195 | ␉␉␉␉case 2:␉mch_ratio = 120000; break;␊ |
196 | ␉␉␉␉case 3:␉mch_ratio = 160000; break;␊ |
197 | ␉␉␉␉case 4:␉mch_ratio = 200000; break;␊ |
198 | ␉␉␉␉case 5:␉mch_ratio = 240000; break;␊ |
199 | ␉␉␉}␊ |
200 | ␉␉␉break;␊ |
201 | ␊ |
202 | ␉␉default:␊ |
203 | ␉␉case 800:␊ |
204 | ␉␉␉switch ((mch_cfg >> 4) & 7) {␊ |
205 | ␉␉␉␉case 1:␉mch_ratio = 83333; break; // 0.833333333␊ |
206 | ␉␉␉␉case 2:␉mch_ratio = 100000; break;␊ |
207 | ␉␉␉␉case 3:␉mch_ratio = 133333; break; // 1.333333333␊ |
208 | ␉␉␉␉case 4:␉mch_ratio = 166667; break; // 1.666666667␊ |
209 | ␉␉␉␉case 5:␉mch_ratio = 200000; break;␊ |
210 | ␉␉␉}␊ |
211 | ␉␉␉break;␊ |
212 | ␉␉case 1066:␊ |
213 | ␉␉␉switch ((mch_cfg >> 4)&7) {␊ |
214 | ␉␉␉␉case 5:␉mch_ratio = 150000; break;␊ |
215 | ␉␉␉␉case 6:␉mch_ratio = 200000; break;␊ |
216 | ␉␉␉}␊ |
217 | ␊ |
218 | ␉}␊ |
219 | ␊ |
220 | ␉// Compute RAM Frequency␊ |
221 | ␉Platform.RAM.Frequency = (Platform.CPU.FSBFrequency * mch_ratio) / 100000;␊ |
222 | ␉// DBG("ram_fsb %d\n", Platform.RAM.Frequency);␊ |
223 | }␊ |
224 | ␊ |
225 | ␊ |
226 | // Get iCore7 Memory Speed␊ |
227 | static void get_fsb_nhm(pci_dt_t *dram_dev)␊ |
228 | {␊ |
229 | ␉uint32_t mch_ratio, mc_dimm_clk_ratio;␊ |
230 | ␊ |
231 | ␉// Get the clock ratio␊ |
232 | ␉mc_dimm_clk_ratio = pci_config_read16(PCIADDR(nhm_bus, 3, 4), 0x54 );␊ |
233 | ␉mch_ratio = (mc_dimm_clk_ratio & 0x1F);␊ |
234 | ␊ |
235 | ␉// Compute RAM Frequency␊ |
236 | ␉Platform.RAM.Frequency = Platform.CPU.FSBFrequency * mch_ratio / 2;␊ |
237 | ␉// DBG("ram_fsb %d\n", Platform.RAM.Frequency);␊ |
238 | }␊ |
239 | ␊ |
240 | /*␊ |
241 | * Retrieve memory controller info functions␊ |
242 | */␊ |
243 | ␊ |
244 | // Get i965 Memory Timings␊ |
245 | static void get_timings_i965(pci_dt_t *dram_dev)␊ |
246 | {␊ |
247 | ␉// Thanks for CDH optis␊ |
248 | ␉uint32_t dev0, c0ckectrl, c1ckectrl, offset;␊ |
249 | ␉uint32_t ODT_Control_Register, Precharge_Register, ACT_Register, Read_Register, Misc_Register;␊ |
250 | ␊ |
251 | ␉long *ptr;␊ |
252 | ␊ |
253 | ␉// Read MMR Base Address␊ |
254 | ␉dev0 = pci_config_read32(dram_dev->dev.addr, 0x48);␊ |
255 | ␉dev0 &= 0xFFFFC000;␊ |
256 | ␊ |
257 | ␉ptr = (long*)(dev0 + 0x260);␊ |
258 | ␉c0ckectrl = *ptr & 0xFFFFFFFF;␉␊ |
259 | ␊ |
260 | ␉ptr = (long*)(dev0 + 0x660);␊ |
261 | ␉c1ckectrl = *ptr & 0xFFFFFFFF;␊ |
262 | ␊ |
263 | ␉// If DIMM 0 not populated, check DIMM 1␊ |
264 | ␉((c0ckectrl) >> 20 & 0xF) ? (offset = 0) : (offset = 0x400);␊ |
265 | ␊ |
266 | ␉ptr = (long*)(dev0 + offset + 0x29C);␊ |
267 | ␉ODT_Control_Register = *ptr & 0xFFFFFFFF;␊ |
268 | ␊ |
269 | ␉ptr = (long*)(dev0 + offset + 0x250);␉␊ |
270 | ␉Precharge_Register = *ptr & 0xFFFFFFFF;␊ |
271 | ␊ |
272 | ␉ptr = (long*)(dev0 + offset + 0x252);␊ |
273 | ␉ACT_Register = *ptr & 0xFFFFFFFF;␊ |
274 | ␊ |
275 | ␉ptr = (long*)(dev0 + offset + 0x258);␊ |
276 | ␉Read_Register = *ptr & 0xFFFFFFFF;␊ |
277 | ␊ |
278 | ␉ptr = (long*)(dev0 + offset + 0x244);␊ |
279 | ␉Misc_Register = *ptr & 0xFFFFFFFF;␊ |
280 | ␊ |
281 | ␉// 965 Series only support DDR2␊ |
282 | ␉Platform.RAM.Type = SMB_MEM_TYPE_DDR2;␊ |
283 | ␊ |
284 | ␉// CAS Latency (tCAS)␊ |
285 | ␉Platform.RAM.CAS = ((ODT_Control_Register >> 17) & 7) + 3;␊ |
286 | ␊ |
287 | ␉// RAS-To-CAS (tRCD)␊ |
288 | ␉Platform.RAM.TRC = (Read_Register >> 16) & 0xF;␊ |
289 | ␊ |
290 | ␉// RAS Precharge (tRP)␊ |
291 | ␉Platform.RAM.TRP = (ACT_Register >> 13) & 0xF;␊ |
292 | ␊ |
293 | ␉// RAS Active to precharge (tRAS)␊ |
294 | ␉Platform.RAM.RAS = (Precharge_Register >> 11) & 0x1F;␊ |
295 | ␊ |
296 | ␉if ((c0ckectrl >> 20 & 0xF) && (c1ckectrl >> 20 & 0xF)) {␊ |
297 | ␉␉Platform.RAM.Channels = SMB_MEM_CHANNEL_DUAL;␊ |
298 | ␉} else {␊ |
299 | ␉␉Platform.RAM.Channels = SMB_MEM_CHANNEL_SINGLE;␊ |
300 | ␉}␊ |
301 | }␊ |
302 | ␊ |
303 | // Get im965 Memory Timings␊ |
304 | static void get_timings_im965(pci_dt_t *dram_dev)␊ |
305 | {␊ |
306 | ␉// Thanks for CDH optis␊ |
307 | ␉uint32_t dev0, c0ckectrl, c1ckectrl, offset, ODT_Control_Register, Precharge_Register;␊ |
308 | ␉long *ptr;␊ |
309 | ␊ |
310 | ␉// Read MMR Base Address␊ |
311 | ␉dev0 = pci_config_read32(dram_dev->dev.addr, 0x48);␊ |
312 | ␉dev0 &= 0xFFFFC000;␊ |
313 | ␊ |
314 | ␉ptr = (long*)(dev0 + 0x1200);␊ |
315 | ␉c0ckectrl = *ptr & 0xFFFFFFFF;␉␊ |
316 | ␊ |
317 | ␉ptr = (long*)(dev0 + 0x1300);␊ |
318 | ␉c1ckectrl = *ptr & 0xFFFFFFFF;␊ |
319 | ␊ |
320 | ␉// If DIMM 0 not populated, check DIMM 1␊ |
321 | ␉((c0ckectrl) >> 20 & 0xF) ? (offset = 0) : (offset = 0x100);␊ |
322 | ␊ |
323 | ␉ptr = (long*)(dev0 + offset + 0x121C);␊ |
324 | ␉ODT_Control_Register = *ptr & 0xFFFFFFFF;␊ |
325 | ␊ |
326 | ␉ptr = (long*)(dev0 + offset + 0x1214);␉␊ |
327 | ␉Precharge_Register = *ptr & 0xFFFFFFFF;␊ |
328 | ␊ |
329 | ␉// Series only support DDR2␊ |
330 | ␉Platform.RAM.Type = SMB_MEM_TYPE_DDR2;␊ |
331 | ␊ |
332 | ␉// CAS Latency (tCAS)␊ |
333 | ␉Platform.RAM.CAS = ((ODT_Control_Register >> 23) & 7) + 3;␊ |
334 | ␊ |
335 | ␉// RAS-To-CAS (tRCD)␊ |
336 | ␉Platform.RAM.TRC = ((Precharge_Register >> 5) & 7) + 2;␊ |
337 | ␊ |
338 | ␉// RAS Precharge (tRP)␊ |
339 | ␉Platform.RAM.TRP= (Precharge_Register & 7) + 2;␊ |
340 | ␊ |
341 | ␉// RAS Active to precharge (tRAS)␊ |
342 | ␉Platform.RAM.RAS = (Precharge_Register >> 21) & 0x1F;␊ |
343 | ␊ |
344 | ␉if ((c0ckectrl >> 20 & 0xF) && (c1ckectrl >> 20 & 0xF)) {␊ |
345 | ␉␉Platform.RAM.Channels = SMB_MEM_CHANNEL_DUAL;␊ |
346 | ␉} else {␊ |
347 | ␉␉Platform.RAM.Channels = SMB_MEM_CHANNEL_SINGLE;␊ |
348 | ␉}␊ |
349 | }␊ |
350 | ␊ |
351 | // Get P35 Memory Timings␊ |
352 | static void get_timings_p35(pci_dt_t *dram_dev)␊ |
353 | {␊ |
354 | ␉// Thanks for CDH optis␊ |
355 | ␉unsigned long dev0, Memory_Check, c0ckectrl, c1ckectrl, offset;␊ |
356 | ␉unsigned long ODT_Control_Register, Precharge_Register, ACT_Register, Read_Register, Misc_Register;␊ |
357 | ␉long *ptr;␊ |
358 | ␊ |
359 | ␉//Device_ID = pci_config_read16(dram_dev->dev.addr, 0x02);␊ |
360 | ␉//Device_ID &= 0xFFFF;␊ |
361 | ␊ |
362 | ␉// Now, read MMR Base Address␊ |
363 | ␉dev0 = pci_config_read32(dram_dev->dev.addr, 0x48);␊ |
364 | ␉dev0 &= 0xFFFFC000;␊ |
365 | ␊ |
366 | ␉ptr = (long*)(dev0 + 0x260);␊ |
367 | ␉c0ckectrl = *ptr & 0xFFFFFFFF;␊ |
368 | ␊ |
369 | ␉ptr = (long*)(dev0 + 0x660);␊ |
370 | ␉c1ckectrl = *ptr & 0xFFFFFFFF;␊ |
371 | ␊ |
372 | ␉// If DIMM 0 not populated, check DIMM 1␊ |
373 | ␉((c0ckectrl) >> 20 & 0xF) ? (offset = 0) : (offset = 0x400);␊ |
374 | ␊ |
375 | ␉ptr = (long*)(dev0 + offset + 0x265);␊ |
376 | ␉ODT_Control_Register = *ptr & 0xFFFFFFFF;␊ |
377 | ␊ |
378 | ␉ptr = (long*)(dev0 + offset + 0x25D);␊ |
379 | ␉Precharge_Register = *ptr & 0xFFFFFFFF;␊ |
380 | ␊ |
381 | ␉ptr = (long*)(dev0 + offset + 0x252);␊ |
382 | ␉ACT_Register = *ptr & 0xFFFFFFFF;␊ |
383 | ␊ |
384 | ␉ptr = (long*)(dev0 + offset + 0x258);␊ |
385 | ␉Read_Register = *ptr & 0xFFFFFFFF;␊ |
386 | ␊ |
387 | ␉ptr = (long*)(dev0 + offset + 0x244);␊ |
388 | ␉Misc_Register = *ptr & 0xFFFFFFFF;␊ |
389 | ␊ |
390 | ␉ptr = (long*)(dev0 + offset + 0x1E8);␊ |
391 | ␉Memory_Check = *ptr & 0xFFFFFFFF;␊ |
392 | ␊ |
393 | ␉// On P45, check 1A8␊ |
394 | ␉if(dram_dev->device_id > 0x2E00) {␊ |
395 | ␉␉ptr = (long*)(dev0 + offset + 0x1A8);␊ |
396 | ␉␉Memory_Check = *ptr & 0xFFFFFFFF;␊ |
397 | ␉␉Memory_Check >>= 2;␊ |
398 | ␉␉Memory_Check &= 1;␊ |
399 | ␉␉Memory_Check = !Memory_Check;␊ |
400 | ␉} else {␊ |
401 | ␉␉ptr = (long*)(dev0 + offset + 0x1E8);␊ |
402 | ␉␉Memory_Check = *ptr & 0xFFFFFFFF;␊ |
403 | ␉}␊ |
404 | ␊ |
405 | ␉// Determine DDR-II or DDR-III␊ |
406 | ␉if (Memory_Check & 1) {␊ |
407 | ␉␉Platform.RAM.Type = SMB_MEM_TYPE_DDR2;␊ |
408 | ␉} else {␊ |
409 | ␉␉Platform.RAM.Type = SMB_MEM_TYPE_DDR3;␊ |
410 | ␉}␊ |
411 | ␊ |
412 | ␉// CAS Latency (tCAS)␊ |
413 | ␉if(dram_dev->device_id > 0x2E00) {␊ |
414 | ␉␉Platform.RAM.CAS = ((ODT_Control_Register >> 8) & 0x3F) - 6;␊ |
415 | ␉} else {␊ |
416 | ␉␉Platform.RAM.CAS = ((ODT_Control_Register >> 8) & 0x3F) - 9;␊ |
417 | ␉}␊ |
418 | ␊ |
419 | ␉// RAS-To-CAS (tRCD)␊ |
420 | ␉Platform.RAM.TRC = (Read_Register >> 17) & 0xF;␊ |
421 | ␊ |
422 | ␉// RAS Precharge (tRP)␊ |
423 | ␉Platform.RAM.TRP = (ACT_Register >> 13) & 0xF;␊ |
424 | ␊ |
425 | ␉// RAS Active to precharge (tRAS)␊ |
426 | ␉Platform.RAM.RAS = Precharge_Register & 0x3F;␊ |
427 | ␊ |
428 | ␉// Channel configuration␊ |
429 | ␉if (((c0ckectrl >> 20) & 0xF) && ((c1ckectrl >> 20) & 0xF)) {␊ |
430 | ␉␉Platform.RAM.Channels = SMB_MEM_CHANNEL_DUAL;␊ |
431 | ␉} else {␊ |
432 | ␉␉Platform.RAM.Channels = SMB_MEM_CHANNEL_SINGLE;␊ |
433 | ␉}␊ |
434 | }␊ |
435 | ␊ |
436 | // Get Nehalem Memory Timings␊ |
437 | static void get_timings_nhm(pci_dt_t *dram_dev)␊ |
438 | {␊ |
439 | ␉unsigned long mc_channel_bank_timing, mc_control, mc_channel_mrs_value;␊ |
440 | ␉int fvc_bn = 4;␊ |
441 | ␊ |
442 | ␉// Find which channels are populated␊ |
443 | ␉mc_control = pci_config_read16(PCIADDR(nhm_bus, 3, 0), 0x48);␊ |
444 | ␉mc_control = (mc_control >> 8) & 0x7;␊ |
445 | ␊ |
446 | ␉// DDR-III␊ |
447 | ␉Platform.RAM.Type = SMB_MEM_TYPE_DDR3;␊ |
448 | ␊ |
449 | ␉// Get the first valid channel␊ |
450 | ␉if(mc_control & 1) {␊ |
451 | ␉␉fvc_bn = 4; ␊ |
452 | ␉} else if(mc_control & 2) {␊ |
453 | ␉␉fvc_bn = 5; ␊ |
454 | ␉} else if(mc_control & 7) {␊ |
455 | ␉␉fvc_bn = 6; ␊ |
456 | ␉}␊ |
457 | ␊ |
458 | ␉// Now, detect timings␊ |
459 | ␉mc_channel_bank_timing = pci_config_read32(PCIADDR(nhm_bus, fvc_bn, 0), 0x88);␊ |
460 | ␉mc_channel_mrs_value = pci_config_read32(PCIADDR(nhm_bus, fvc_bn, 0), 0x70);␊ |
461 | ␊ |
462 | ␉// CAS Latency (tCAS)␊ |
463 | ␉Platform.RAM.CAS = ((mc_channel_mrs_value >> 4) & 0xF ) + 4;␊ |
464 | ␊ |
465 | ␉// RAS-To-CAS (tRCD)␊ |
466 | ␉Platform.RAM.TRC = (mc_channel_bank_timing >> 9) & 0xF; ␊ |
467 | ␊ |
468 | ␉// RAS Active to precharge (tRAS)␊ |
469 | ␉Platform.RAM.RAS = (mc_channel_bank_timing >> 4) & 0x1F; ␊ |
470 | ␊ |
471 | ␉// RAS Precharge (tRP)␊ |
472 | ␉Platform.RAM.TRP = mc_channel_bank_timing & 0xF;␊ |
473 | ␊ |
474 | ␉// Single , Dual or Triple Channels␊ |
475 | ␉if (mc_control == 1 || mc_control == 2 || mc_control == 4 ) {␊ |
476 | ␉␉Platform.RAM.Channels = SMB_MEM_CHANNEL_SINGLE;␊ |
477 | ␉} else if (mc_control == 7) {␊ |
478 | ␉␉Platform.RAM.Channels = SMB_MEM_CHANNEL_TRIPLE;␊ |
479 | ␉} else ␉{␊ |
480 | ␉␉Platform.RAM.Channels = SMB_MEM_CHANNEL_DUAL;␊ |
481 | ␉}␊ |
482 | }␊ |
483 | ␊ |
484 | static struct mem_controller_t dram_controllers[] = {␊ |
485 | ␊ |
486 | ␉// Default unknown chipset␊ |
487 | ␉{ 0, 0, "",␉␉␉␉␉NULL, NULL, NULL },␊ |
488 | ␊ |
489 | ␉// Intel␊ |
490 | ␉{ 0x8086, 0x7190, "VMWare",␉␉␉NULL, NULL, NULL },␊ |
491 | ␊ |
492 | ␉{ 0x8086, 0x1A30, "82845 845 [Brookdale]",␉NULL, NULL, NULL },␊ |
493 | ␉␊ |
494 | ␉{ 0x8086, 0x2970, "82946GZ/PL/GL",␉␉setup_p35, get_fsb_i965,␉get_timings_i965␉},␊ |
495 | ␉{ 0x8086, 0x2990, "82Q963/Q965",␉␉setup_p35, get_fsb_i965,␉get_timings_i965␉},␊ |
496 | ␉{ 0x8086, 0x29A0, "P965/G965",␉␉␉setup_p35, get_fsb_i965,␉get_timings_i965␉},␊ |
497 | ␊ |
498 | ␉{ 0x8086, 0x2A00, "GM965/GL960",␉␉setup_p35, get_fsb_im965,␉get_timings_im965␉},␊ |
499 | ␉{ 0x8086, 0x2A10, "GME965/GLE960",␉␉setup_p35, get_fsb_im965,␉get_timings_im965␉},␊ |
500 | ␉{ 0x8086, 0x2A40, "PM/GM45/47",␉␉␉setup_p35, get_fsb_im965,␉get_timings_im965␉},␊ |
501 | ␊ |
502 | ␉{ 0x8086, 0x29B0, "Q35",␉␉␉setup_p35, get_fsb_i965,␉get_timings_p35␉␉},␊ |
503 | ␉{ 0x8086, 0x29C0, "P35/G33",␉␉␉setup_p35, get_fsb_i965,␉get_timings_p35␉␉},␊ |
504 | ␉{ 0x8086, 0x29D0, "Q33",␉␉␉setup_p35, get_fsb_i965,␉get_timings_p35␉␉},␊ |
505 | ␉{ 0x8086, 0x29E0, "X38/X48",␉␉␉setup_p35, get_fsb_i965,␉get_timings_p35␉␉},␊ |
506 | ␉{ 0x8086, 0x29F0, "3200/3210",␉␉␉setup_p35, get_fsb_i965,␉get_timings_p35␉␉},␊ |
507 | ␊ |
508 | ␉{ 0x8086, 0x2E00, "Eaglelake",␉␉␉setup_p35, get_fsb_i965,␉get_timings_p35␉␉},␊ |
509 | ␉{ 0x8086, 0x2E10, "Q45/Q43",␉␉␉setup_p35, get_fsb_i965,␉get_timings_p35␉␉},␊ |
510 | ␉{ 0x8086, 0x2E20, "P45/G45",␉␉␉setup_p35, get_fsb_i965,␉get_timings_p35␉␉},␊ |
511 | ␉{ 0x8086, 0x2E30, "G41",␉␉␉setup_p35, get_fsb_i965,␉get_timings_p35␉␉},␊ |
512 | ␊ |
513 | ␉{ 0x8086, 0xD131, "NHM IMC",␉␉␉setup_nhm, get_fsb_nhm,␉␉get_timings_nhm␉␉},␊ |
514 | ␉{ 0x8086, 0xD132, "NHM IMC",␉␉␉setup_nhm, get_fsb_nhm,␉␉get_timings_nhm␉␉},␊ |
515 | ␉{ 0x8086, 0x3400, "5520/5500/X58",␉␉setup_nhm, get_fsb_nhm,␉␉get_timings_nhm␉␉},␊ |
516 | ␉{ 0x8086, 0x3401, "5520/5500/X58",␉␉setup_nhm, get_fsb_nhm,␉␉get_timings_nhm␉␉},␊ |
517 | ␉{ 0x8086, 0x3402, "5520/5500/X58",␉␉setup_nhm, get_fsb_nhm,␉␉get_timings_nhm␉␉},␊ |
518 | ␉{ 0x8086, 0x3403, "5500",␉␉␉setup_nhm, get_fsb_nhm,␉␉get_timings_nhm␉␉},␊ |
519 | ␉{ 0x8086, 0x3404, "X58",␉␉␉setup_nhm, get_fsb_nhm,␉␉get_timings_nhm␉␉},␊ |
520 | ␉{ 0x8086, 0x3405, "X58",␉␉␉setup_nhm, get_fsb_nhm,␉␉get_timings_nhm␉␉},␊ |
521 | ␉{ 0x8086, 0x3406, "5520",␉␉␉setup_nhm, get_fsb_nhm,␉␉get_timings_nhm␉␉},␊ |
522 | ␉{ 0x8086, 0x3407, "X58",␉␉␉setup_nhm, get_fsb_nhm,␉␉get_timings_nhm␉␉},␊ |
523 | };␊ |
524 | ␊ |
525 | static const char *memory_channel_types[] =␊ |
526 | {␊ |
527 | ␉"Unknown", "Single", "Dual", "Triple" /*, "Quad" */␊ |
528 | };␊ |
529 | ␊ |
530 | void scan_dram_controller(pci_dt_t *dram_dev)␊ |
531 | {␊ |
532 | ␉verbose("[ DRAM CONTROLLER ]\n");␊ |
533 | ␉int i;␊ |
534 | ␉for(i = 1; i < sizeof(dram_controllers) / sizeof(dram_controllers[0]); i++)␊ |
535 | ␉{␊ |
536 | ␉␉if ((dram_controllers[i].vendor == dram_dev->vendor_id) && (dram_controllers[i].device == dram_dev->device_id)) {␊ |
537 | ␉␉␉verbose("\t%s%s DRAM Controller [%4x:%4x] at %02x:%02x.%x\n", ␊ |
538 | ␉␉␉␉(dram_dev->vendor_id == 0x8086) ? "Intel " : "" ,␊ |
539 | ␉␉␉␉dram_controllers[i].name, dram_dev->vendor_id, dram_dev->device_id,␊ |
540 | ␉␉␉␉dram_dev->dev.bits.bus, dram_dev->dev.bits.dev, dram_dev->dev.bits.func);␊ |
541 | ␊ |
542 | ␉␉␉if (dram_controllers[i].initialise != NULL) {␊ |
543 | ␉␉␉␉dram_controllers[i].initialise(dram_dev);␊ |
544 | ␉␉␉}␊ |
545 | ␊ |
546 | ␉␉␉if (dram_controllers[i].poll_timings != NULL) {␊ |
547 | ␉␉␉␉dram_controllers[i].poll_timings(dram_dev);␊ |
548 | ␉␉␉}␊ |
549 | ␊ |
550 | ␉␉␉if (dram_controllers[i].poll_speed != NULL) {␊ |
551 | ␉␉␉␉dram_controllers[i].poll_speed(dram_dev);␊ |
552 | ␉␉␉}␊ |
553 | ␊ |
554 | ␉␉␉verbose("\tFrequency detected: %d MHz (%d) %s Channel \n\t\tCAS:%d tRC:%d tRP:%d RAS:%d (%d-%d-%d-%d)\n", ␊ |
555 | ␉␉␉␉(uint32_t)Platform.RAM.Frequency / 1000000,␊ |
556 | ␉␉␉␉(uint32_t)Platform.RAM.Frequency / 500000,␊ |
557 | ␉␉␉␉memory_channel_types[Platform.RAM.Channels]␊ |
558 | ␉␉␉␉,Platform.RAM.CAS, Platform.RAM.TRC, Platform.RAM.TRP, Platform.RAM.RAS␊ |
559 | ␉␉␉␉,Platform.RAM.CAS, Platform.RAM.TRC, Platform.RAM.TRP, Platform.RAM.RAS);␊ |
560 | //␉␉␉getchar();␊ |
561 | ␉␉}␊ |
562 | ␉}␊ |
563 | ␉verbose("\n");␊ |
564 | }␊ |
565 |