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