From 3cf94032bced9345f4b9d71b7d2becab4dfcd530 Mon Sep 17 00:00:00 2001 From: Arthur Heymans Date: Wed, 5 Apr 2017 16:17:26 +0200 Subject: nb/x4x/raminit: Rewrite SPD decode and timing selection This is mostly written from scratch and uses common spd ddr2 decode functions. This improves the following: * This fixes incorrect CAS/Freq detection on DDR2; * Fixes tRFC computation; tRFC == 78 is a valid timing which is excluded and 0 ends up being used; (TESTED) * Timings selection does not use loops; * Removes ddr3 spd decode and is re-added in follow-up patches using common ddr3 spd functions; * Raminit would bail out if a dimm was unsupported, now in some cases it just marks the dimm slot as empty; * It dramatically reduces stack usage since it does not allocate 4 times 256 bytes to store full SPDs, amongs other unused things that were stored in sysinfo; * Reports when no dimms are present; * Uses i2c block read to read SPD which is about 5 times faster than bytewise read, with a fallback to smbus mode in case of failure, which does seem to happen when the system is forcefully powered off. Change-Id: I760eeaa3bd4f2bc25a517ddb1b9533c971454071 Signed-off-by: Arthur Heymans Reviewed-on: https://review.coreboot.org/19143 Tested-by: build bot (Jenkins) Reviewed-by: Martin Roth --- src/northbridge/intel/x4x/raminit_ddr2.c | 124 ++----------------------------- 1 file changed, 6 insertions(+), 118 deletions(-) (limited to 'src/northbridge/intel/x4x/raminit_ddr2.c') diff --git a/src/northbridge/intel/x4x/raminit_ddr2.c b/src/northbridge/intel/x4x/raminit_ddr2.c index 02c7fee475..e6ba2dcef8 100644 --- a/src/northbridge/intel/x4x/raminit_ddr2.c +++ b/src/northbridge/intel/x4x/raminit_ddr2.c @@ -31,12 +31,12 @@ #define ME_UMA_SIZEMB 0 -static u32 fsb2mhz(u32 speed) +u32 fsb2mhz(u32 speed) { return (speed * 267) + 800; } -static u32 ddr2mhz(u32 speed) +u32 ddr2mhz(u32 speed) { static const u16 mhz[] = { 0, 0, 667, 800, 1067, 1333 }; @@ -64,113 +64,6 @@ static u8 msbpos(u32 val) return (u8)(pos & 0xff); } -static void sdram_detect_smallest_params2(struct sysinfo *s) -{ - u16 mult[6] = { - 5000, // 400 - 3750, // 533 - 3000, // 667 - 2500, // 800 - 1875, // 1066 - 1500, // 1333 - }; - - u8 i; - u32 tmp; - u32 maxtras = 0; - u32 maxtrp = 0; - u32 maxtrcd = 0; - u32 maxtwr = 0; - u32 maxtrfc = 0; - u32 maxtwtr = 0; - u32 maxtrrd = 0; - u32 maxtrtp = 0; - - FOR_EACH_POPULATED_DIMM(s->dimms, i) { - maxtras = MAX(maxtras, s->dimms[i].spd_data[30] * 1000); - maxtrp = MAX(maxtrp, (s->dimms[i].spd_data[27] * 1000) >> 2); - maxtrcd = MAX(maxtrcd, (s->dimms[i].spd_data[29] * 1000) >> 2); - maxtwr = MAX(maxtwr, (s->dimms[i].spd_data[36] * 1000) >> 2); - maxtrfc = MAX(maxtrfc, s->dimms[i].spd_data[42] * 1000 + - (s->dimms[i].spd_data[40] & 0xf)); - maxtwtr = MAX(maxtwtr, (s->dimms[i].spd_data[37] * 1000) >> 2); - maxtrrd = MAX(maxtrrd, (s->dimms[i].spd_data[28] * 1000) >> 2); - maxtrtp = MAX(maxtrtp, (s->dimms[i].spd_data[38] * 1000) >> 2); - } - for (i = 9; i < 24; i++) { - tmp = mult[s->selected_timings.mem_clk] * i; - if (tmp >= maxtras) { - s->selected_timings.tRAS = i; - break; - } - } - for (i = 3; i < 10; i++) { - tmp = mult[s->selected_timings.mem_clk] * i; - if (tmp >= maxtrp) { - s->selected_timings.tRP = i; - break; - } - } - for (i = 3; i < 10; i++) { - tmp = mult[s->selected_timings.mem_clk] * i; - if (tmp >= maxtrcd) { - s->selected_timings.tRCD = i; - break; - } - } - for (i = 3; i < 15; i++) { - tmp = mult[s->selected_timings.mem_clk] * i; - if (tmp >= maxtwr) { - s->selected_timings.tWR = i; - break; - } - } - for (i = 15; i < 78; i++) { - tmp = mult[s->selected_timings.mem_clk] * i; - if (tmp >= maxtrfc) { - s->selected_timings.tRFC = ((i + 16) & 0xfe) - 15; - break; - } - } - for (i = 4; i < 15; i++) { - tmp = mult[s->selected_timings.mem_clk] * i; - if (tmp >= maxtwtr) { - s->selected_timings.tWTR = i; - break; - } - } - for (i = 2; i < 15; i++) { - tmp = mult[s->selected_timings.mem_clk] * i; - if (tmp >= maxtrrd) { - s->selected_timings.tRRD = i; - break; - } - } - for (i = 4; i < 15; i++) { - tmp = mult[s->selected_timings.mem_clk] * i; - if (tmp >= maxtrtp) { - s->selected_timings.tRTP = i; - break; - } - } - - s->selected_timings.fsb_clk = s->max_fsb; - - printk(BIOS_DEBUG, "Selected timings:\n"); - printk(BIOS_DEBUG, "\tFSB: %dMHz\n", fsb2mhz(s->selected_timings.fsb_clk)); - printk(BIOS_DEBUG, "\tDDR: %dMHz\n", ddr2mhz(s->selected_timings.mem_clk)); - - printk(BIOS_DEBUG, "\tCAS: %d\n", s->selected_timings.CAS); - printk(BIOS_DEBUG, "\ttRAS: %d\n", s->selected_timings.tRAS); - printk(BIOS_DEBUG, "\ttRP: %d\n", s->selected_timings.tRP); - printk(BIOS_DEBUG, "\ttRCD: %d\n", s->selected_timings.tRCD); - printk(BIOS_DEBUG, "\ttWR: %d\n", s->selected_timings.tWR); - printk(BIOS_DEBUG, "\ttRFC: %d\n", s->selected_timings.tRFC); - printk(BIOS_DEBUG, "\ttWTR: %d\n", s->selected_timings.tWTR); - printk(BIOS_DEBUG, "\ttRRD: %d\n", s->selected_timings.tRRD); - printk(BIOS_DEBUG, "\ttRTP: %d\n", s->selected_timings.tRTP); -} - static void clkcross_ddr2(struct sysinfo *s) { u8 i, j; @@ -500,8 +393,7 @@ static void timings_ddr2(struct sysinfo *s) twl = s->selected_timings.CAS - 1; FOR_EACH_POPULATED_DIMM(s->dimms, i) { - if (s->dimms[i].banks == 1) { - /* 8 banks */ + if (s->dimms[i].n_banks == N_BANKS_8) { trpmod = 1; bankmod = 0; } @@ -1276,11 +1168,12 @@ static void dradrb_ddr2(struct sysinfo *s) i = ch << 1; else i = (ch << 1) + 1; - dra = dratab[s->dimms[i].banks] + + dra = dratab[s->dimms[i].n_banks] [s->dimms[i].width] [s->dimms[i].cols-9] [s->dimms[i].rows-12]; - if (s->dimms[i].banks == 1) + if (s->dimms[i].n_banks == N_BANKS_8) dra |= 0x80; if (ch == 0) { c0dra |= dra << (r*8); @@ -1313,12 +1206,10 @@ static void dradrb_ddr2(struct sysinfo *s) if (ch == 0) { dra0 = (c0dra >> (8*r)) & 0x7f; c0drb = (u16)(c0drb + drbtab[dra0]); - s->dimms[i].rank_capacity_mb = drbtab[dra0] << 6; MCHBAR16(0x200 + 2*r) = c0drb; } else { dra1 = (c1dra >> (8*r)) & 0x7f; c1drb = (u16)(c1drb + drbtab[dra1]); - s->dimms[i].rank_capacity_mb = drbtab[dra1] << 6; MCHBAR16(0x600 + 2*r) = c1drb; } } @@ -1588,9 +1479,6 @@ void raminit_ddr2(struct sysinfo *s) u8 r, bank; u32 reg32; - // Select timings based on SPD info - sdram_detect_smallest_params2(s); - if (s->boot_path != BOOT_PATH_WARM_RESET) { // Clear self refresh MCHBAR32(PMSTS_MCHBAR) = MCHBAR32(PMSTS_MCHBAR) -- cgit v1.2.3