Chameleon Applications

Chameleon Applications Svn Source Tree

Root/branches/iFabio/i386/libsaio/dram_controllers.c

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

Archive Download this file

Revision: 214