Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/i386/modules/Memory/dram_controllers.c

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
31static void setup_p35(pci_dt_t *dram_dev);
32static void setup_nhm(pci_dt_t *dram_dev);
33static void get_fsb_i965(pci_dt_t *dram_dev);
34static void get_fsb_im965(pci_dt_t *dram_dev);
35static void get_fsb_nhm(pci_dt_t *dram_dev);
36static void get_timings_i965(pci_dt_t *dram_dev);
37static void get_timings_im965(pci_dt_t *dram_dev);
38static void get_timings_p35(pci_dt_t *dram_dev);
39static void get_timings_nhm(pci_dt_t *dram_dev);
40
41/*
42 * Initialise memory controller functions
43 */
44
45// Setup P35 Memory Controller
46static void setup_p35(pci_dt_t *dram_dev)
47{
48uint32_t dev0;
49
50// Activate MMR I/O
51dev0 = pci_config_read32(dram_dev->dev.addr, 0x48);
52if (!(dev0 & 0x1))
53pci_config_write8(dram_dev->dev.addr, 0x48, (dev0 | 1));
54}
55
56int nhm_bus = 0x3F;
57
58
59// Setup Nehalem Integrated Memory Controller
60static void setup_nhm(pci_dt_t *dram_dev)
61{
62 static long possible_nhm_bus[] = {0xFF, 0x7F, 0x3F};
63unsigned long did, vid;
64int i;
65
66// Nehalem supports Scrubbing
67// First, locate the PCI bus where the MCH is located
68for(i = 0; (unsigned)i < sizeof(possible_nhm_bus); i++)
69{
70vid = pci_config_read16(PCIADDR(possible_nhm_bus[i], 3, 4), PCI_VENDOR_ID);
71did = pci_config_read16(PCIADDR(possible_nhm_bus[i], 3, 4), PCI_DEVICE_ID);
72vid &= 0xFFFF;
73did &= 0xFF00;
74
75if(vid == 0x8086 && did >= 0x2C00)
76nhm_bus = possible_nhm_bus[i];
77}
78}
79
80/*
81 * Retrieve memory controller fsb functions
82 */
83
84
85// Get i965 Memory Speed
86static void get_fsb_i965(pci_dt_t *dram_dev)
87{
88uint32_t dev0, mch_ratio, mch_cfg, mch_fsb;
89
90long *ptr;
91
92// Find Ratio
93dev0 = pci_config_read32(dram_dev->dev.addr, 0x48);
94dev0 &= 0xFFFFC000;
95ptr = (long*)(dev0 + 0xC00);
96mch_cfg = *ptr & 0xFFFF;
97
98mch_ratio = 100000;
99
100switch (mch_cfg & 7)
101{
102case 0: mch_fsb = 1066; break;
103case 1: mch_fsb = 533; break;
104 default:
105case 2: mch_fsb = 800; break;
106case 3: mch_fsb = 667; break;
107case 4: mch_fsb = 1333; break;
108case 6: mch_fsb = 1600; break;
109}
110
111DBG("mch_fsb %d\n", mch_fsb);
112
113switch (mch_fsb)
114{
115case 533:
116switch ((mch_cfg >> 4) & 7)
117{
118case 1:mch_ratio = 200000; break;
119case 2:mch_ratio = 250000; break;
120case 3:mch_ratio = 300000; break;
121}
122break;
123
124default:
125case 800:
126switch ((mch_cfg >> 4) & 7)
127{
128case 0:mch_ratio = 100000; break;
129case 1:mch_ratio = 125000; break;
130case 2:mch_ratio = 166667; break; // 1.666666667
131case 3:mch_ratio = 200000; break;
132case 4:mch_ratio = 266667; break; // 2.666666667
133case 5:mch_ratio = 333333; break; // 3.333333333
134}
135break;
136
137case 1066:
138switch ((mch_cfg >> 4) & 7)
139{
140case 1:mch_ratio = 100000; break;
141case 2:mch_ratio = 125000; break;
142case 3:mch_ratio = 150000; break;
143case 4:mch_ratio = 200000; break;
144case 5:mch_ratio = 250000; break;
145}
146break;
147
148case 1333:
149switch ((mch_cfg >> 4) & 7)
150{
151case 2:mch_ratio = 100000; break;
152case 3:mch_ratio = 120000; break;
153case 4:mch_ratio = 160000; break;
154case 5:mch_ratio = 200000; break;
155}
156break;
157
158case 1600:
159switch ((mch_cfg >> 4) & 7)
160{
161case 3:mch_ratio = 100000; break;
162case 4:mch_ratio = 133333; break; // 1.333333333
163case 5:mch_ratio = 150000; break;
164case 6:mch_ratio = 200000; break;
165}
166break;
167}
168
169DBG("mch_ratio %d\n", mch_ratio);
170
171// Compute RAM Frequency
172 safe_set_env(envRamFrequency, ((get_env(envFSBFreq) * mch_ratio) / 100000));
173
174DBG("ram_fsb %d\n", (uint32_t)get_env(envRamFrequency));
175
176}
177
178// Get i965m Memory Speed
179static void get_fsb_im965(pci_dt_t *dram_dev)
180{
181uint32_t dev0, mch_ratio, mch_cfg, mch_fsb;
182
183long *ptr;
184
185// Find Ratio
186dev0 = pci_config_read32(dram_dev->dev.addr, 0x48);
187dev0 &= 0xFFFFC000;
188ptr = (long*)(dev0 + 0xC00);
189mch_cfg = *ptr & 0xFFFF;
190
191mch_ratio = 100000;
192
193switch (mch_cfg & 7)
194{
195case 1: mch_fsb = 533; break;
196default:
197case 2:mch_fsb = 800; break;
198case 3:mch_fsb = 667; break;
199case 6:mch_fsb = 1066; break;
200}
201
202switch (mch_fsb)
203{
204case 533:
205switch ((mch_cfg >> 4) & 7)
206{
207case 1:mch_ratio = 125000; break;
208case 2:mch_ratio = 150000; break;
209case 3:mch_ratio = 200000; break;
210}
211break;
212
213case 667:
214switch ((mch_cfg >> 4)& 7)
215{
216case 1:mch_ratio = 100000; break;
217case 2:mch_ratio = 120000; break;
218case 3:mch_ratio = 160000; break;
219case 4:mch_ratio = 200000; break;
220case 5:mch_ratio = 240000; break;
221}
222break;
223
224default:
225case 800:
226switch ((mch_cfg >> 4) & 7)
227{
228case 1:mch_ratio = 83333; break; // 0.833333333
229case 2:mch_ratio = 100000; break;
230case 3:mch_ratio = 133333; break; // 1.333333333
231case 4:mch_ratio = 166667; break; // 1.666666667
232case 5:mch_ratio = 200000; break;
233}
234break;
235case 1066:
236switch ((mch_cfg >> 4)&7) {
237case 5:mch_ratio = 150000; break;
238case 6:mch_ratio = 200000; break;
239}
240
241}
242
243// Compute RAM Frequency
244safe_set_env(envRamFrequency, ((get_env(envFSBFreq) * mch_ratio) / 100000));
245
246DBG("ram_fsb %d\n", (uint32_t)get_env(envRamFrequency));
247}
248
249
250// Get iCore7 Memory Speed
251static void get_fsb_nhm(pci_dt_t *dram_dev)
252{
253uint32_t mch_ratio, mc_dimm_clk_ratio;
254
255// Get the clock ratio
256mc_dimm_clk_ratio = pci_config_read16(PCIADDR(nhm_bus, 3, 4), 0x54 );
257mch_ratio = (mc_dimm_clk_ratio & 0x1F);
258
259// Compute RAM Frequency
260 safe_set_env(envRamFrequency, ((get_env(envFSBFreq) * mch_ratio) / 2));
261
262DBG("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
270static void get_timings_i965(pci_dt_t *dram_dev)
271{
272// Thanks for CDH optis
273uint32_t dev0, c0ckectrl, c1ckectrl, offset;
274uint32_t ODT_Control_Register, Precharge_Register, ACT_Register, Read_Register;
275#if UNUSED
276 unsigned long Misc_Register;
277#endif
278long *ptr;
279
280// Read MMR Base Address
281dev0 = pci_config_read32(dram_dev->dev.addr, 0x48);
282dev0 &= 0xFFFFC000;
283
284ptr = (long*)(dev0 + 0x260);
285c0ckectrl = *ptr & 0xFFFFFFFF;
286
287ptr = (long*)(dev0 + 0x660);
288c1ckectrl = *ptr & 0xFFFFFFFF;
289
290// If DIMM 0 not populated, check DIMM 1
291((c0ckectrl) >> 20 & 0xF) ? (offset = 0) : (offset = 0x400);
292
293ptr = (long*)(dev0 + offset + 0x29C);
294ODT_Control_Register = *ptr & 0xFFFFFFFF;
295
296ptr = (long*)(dev0 + offset + 0x250);
297Precharge_Register = *ptr & 0xFFFFFFFF;
298
299ptr = (long*)(dev0 + offset + 0x252);
300ACT_Register = *ptr & 0xFFFFFFFF;
301
302ptr = (long*)(dev0 + offset + 0x258);
303Read_Register = *ptr & 0xFFFFFFFF;
304#if UNUSED
305ptr = (long*)(dev0 + offset + 0x244);
306Misc_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
323if ((c0ckectrl >> 20 & 0xF) && (c1ckectrl >> 20 & 0xF))
324safe_set_env(envRamChannels, SMB_MEM_CHANNEL_DUAL);
325else
326 safe_set_env(envRamChannels, SMB_MEM_CHANNEL_SINGLE);
327}
328
329// Get im965 Memory Timings
330static void get_timings_im965(pci_dt_t *dram_dev)
331{
332// Thanks for CDH optis
333uint32_t dev0, c0ckectrl, c1ckectrl, offset, ODT_Control_Register, Precharge_Register;
334long *ptr;
335
336// Read MMR Base Address
337dev0 = pci_config_read32(dram_dev->dev.addr, 0x48);
338dev0 &= 0xFFFFC000;
339
340ptr = (long*)(dev0 + 0x1200);
341c0ckectrl = *ptr & 0xFFFFFFFF;
342
343ptr = (long*)(dev0 + 0x1300);
344c1ckectrl = *ptr & 0xFFFFFFFF;
345
346// If DIMM 0 not populated, check DIMM 1
347((c0ckectrl) >> 20 & 0xF) ? (offset = 0) : (offset = 0x100);
348
349ptr = (long*)(dev0 + offset + 0x121C);
350ODT_Control_Register = *ptr & 0xFFFFFFFF;
351
352ptr = (long*)(dev0 + offset + 0x1214);
353Precharge_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
370if ((c0ckectrl >> 20 & 0xF) && (c1ckectrl >> 20 & 0xF))
371 safe_set_env(envRamChannels, SMB_MEM_CHANNEL_DUAL);
372else
373 safe_set_env(envRamChannels, SMB_MEM_CHANNEL_SINGLE);
374}
375
376// Get P35 Memory Timings
377static void get_timings_p35(pci_dt_t *dram_dev)
378{
379// Thanks for CDH optis
380unsigned long dev0, Memory_Check, c0ckectrl, c1ckectrl, offset;
381unsigned long ODT_Control_Register, Precharge_Register, ACT_Register, Read_Register;
382#if UNUSED
383 unsigned long Misc_Register;
384#endif
385long *ptr;
386
387//Device_ID = pci_config_read16(dram_dev->dev.addr, 0x02);
388//Device_ID &= 0xFFFF;
389
390// Now, read MMR Base Address
391dev0 = pci_config_read32(dram_dev->dev.addr, 0x48);
392dev0 &= 0xFFFFC000;
393
394ptr = (long*)(dev0 + 0x260);
395c0ckectrl = *ptr & 0xFFFFFFFF;
396
397ptr = (long*)(dev0 + 0x660);
398c1ckectrl = *ptr & 0xFFFFFFFF;
399
400// If DIMM 0 not populated, check DIMM 1
401((c0ckectrl) >> 20 & 0xF) ? (offset = 0) : (offset = 0x400);
402
403ptr = (long*)(dev0 + offset + 0x265);
404ODT_Control_Register = *ptr & 0xFFFFFFFF;
405
406ptr = (long*)(dev0 + offset + 0x25D);
407Precharge_Register = *ptr & 0xFFFFFFFF;
408
409ptr = (long*)(dev0 + offset + 0x252);
410ACT_Register = *ptr & 0xFFFFFFFF;
411
412ptr = (long*)(dev0 + offset + 0x258);
413Read_Register = *ptr & 0xFFFFFFFF;
414#if UNUSED
415ptr = (long*)(dev0 + offset + 0x244);
416Misc_Register = *ptr & 0xFFFFFFFF;
417#endif
418// On P45, check 1A8
419if(dram_dev->device_id > 0x2E00) {
420ptr = (long*)(dev0 + offset + 0x1A8);
421Memory_Check = *ptr & 0xFFFFFFFF;
422Memory_Check >>= 2;
423Memory_Check &= 1;
424Memory_Check = !Memory_Check;
425} else {
426ptr = (long*)(dev0 + offset + 0x1E8);
427Memory_Check = *ptr & 0xFFFFFFFF;
428}
429
430// Determine DDR-II or DDR-III
431if (Memory_Check & 1)
432 safe_set_env(envRamType,SMB_MEM_TYPE_DDR2);
433else
434 safe_set_env(envRamType,SMB_MEM_TYPE_DDR3);
435
436// CAS Latency (tCAS)
437if(dram_dev->device_id > 0x2E00)
438 safe_set_env(envRamCas,((ODT_Control_Register >> 8) & 0x3F) - 6);
439else
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
452if (((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
459static void get_timings_nhm(pci_dt_t *dram_dev)
460{
461unsigned long mc_channel_bank_timing, mc_control, mc_channel_mrs_value;
462int fvc_bn = 4;
463
464// Find which channels are populated
465mc_control = pci_config_read16(PCIADDR(nhm_bus, 3, 0), 0x48);
466mc_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
472if(mc_control & 1)
473fvc_bn = 4;
474else if(mc_control & 2)
475fvc_bn = 5;
476else if(mc_control & 7)
477fvc_bn = 6;
478
479// Now, detect timings
480mc_channel_bank_timing = pci_config_read32(PCIADDR(nhm_bus, fvc_bn, 0), 0x88);
481mc_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
496if (mc_control == 1 || mc_control == 2 || mc_control == 4 )
497 safe_set_env(envRamChannels, SMB_MEM_CHANNEL_SINGLE);
498else if (mc_control == 7)
499safe_set_env(envRamChannels, SMB_MEM_CHANNEL_TRIPLE);
500else
501 safe_set_env(envRamChannels, SMB_MEM_CHANNEL_DUAL);
502}
503
504static 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
544static const char *memory_channel_types[] =
545{
546"Unknown", "Single", "Dual", "Triple"
547};
548
549void scan_dram_controller(pci_dt_t *dram_dev)
550{
551int i;
552for(i = 1; (unsigned)i < sizeof(dram_controllers) / sizeof(dram_controllers[0]); i++)
553if ((dram_controllers[i].vendor == dram_dev->vendor_id)
554&& (dram_controllers[i].device == dram_dev->device_id))
555{
556verbose("%s%s DRAM Controller [%4x:%4x] at %02x:%02x.%x\n",
557(dram_dev->vendor_id == 0x8086) ? "Intel " : "" ,
558dram_controllers[i].name, dram_dev->vendor_id, dram_dev->device_id,
559dram_dev->dev.bits.bus, dram_dev->dev.bits.dev, dram_dev->dev.bits.func);
560
561if (dram_controllers[i].initialise != NULL)
562dram_controllers[i].initialise(dram_dev);
563
564if (dram_controllers[i].poll_timings != NULL)
565dram_controllers[i].poll_timings(dram_dev);
566
567if (dram_controllers[i].poll_speed != NULL)
568dram_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

Archive Download this file

Revision: 2006