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