From a8380fcfd80cca6ac88be5ac342e85c94d77ad7a Mon Sep 17 00:00:00 2001 From: Keith Hui Date: Mon, 4 Dec 2017 00:05:56 -0500 Subject: intel/i440bx: Correct RAM init programming Corrects MBSC/MBFS programming when initializing DRAM on boards with both 3 and 4 DIMM slots. Reformats comments to current coreboot standards. Drops some romcc "optimizations" no longer necessary. Boot tested on asus/p2b-ls, where it fixes a memory related hang after SeaBIOS resets the board with nothing to boot from. Change-Id: Ib8c21489338643e13f69bd58008d14733796d4d0 Signed-off-by: Keith Hui Reviewed-on: https://review.coreboot.org/22687 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer --- src/northbridge/intel/i440bx/raminit.c | 291 ++++++++++++++++++++------------- 1 file changed, 173 insertions(+), 118 deletions(-) (limited to 'src/northbridge/intel') diff --git a/src/northbridge/intel/i440bx/raminit.c b/src/northbridge/intel/i440bx/raminit.c index 84008e750a..49994edf17 100644 --- a/src/northbridge/intel/i440bx/raminit.c +++ b/src/northbridge/intel/i440bx/raminit.c @@ -132,12 +132,12 @@ static const u8 register_values[] = { * * [7:6] Reserved * [5:5] Module Mode Configuration (MMCONFIG) - * The combination of SDRAMPWR and this bit (which is set by an + * The combination of SDRAMPWR and this bit (set by an * external strapping option) determine how CKE works. * SDRAMPWR MMCONFIG - * 0 0 = 3 DIMM, CKE0[5:0] driven - * X 1 = 3 DIMM, CKE0 only - * 1 0 = 4 DIMM, GCKE only + * 0 0 = 3 DIMM, CKE[5:0] driven + * X 1 = 3 DIMM, CKE0 only + * 1 0 = 4 DIMM, GCKE only * [4:3] DRAM Type (DT) * 00 = EDO * 01 = SDRAM @@ -188,9 +188,6 @@ static const u8 register_values[] = { * you want to use the RAM area from 768 KB - 1 MB. If the PAM * registers are not set here appropriately, the RAM in that region * will not be accessible, thus a RAM check of it will also fail. - * - * TODO: This was set in sdram_set_spd_registers(). - * Test if it still works when set here. */ PAM0, 0x00, 0x30, PAM1, 0x00, 0x33, @@ -215,7 +212,7 @@ static const u8 register_values[] = { * 0x66 DRB6 = Total memory in row0+1+2+3+4+5+6 (in 8 MB) * 0x67 DRB7 = Total memory in row0+1+2+3+4+5+6+7 (in 8 MB) */ - /* Set the DRBs to zero for now, this will be fixed later. */ + /* DRBs will be set later. */ DRB0, 0x00, 0x00, DRB1, 0x00, 0x00, DRB2, 0x00, 0x00, @@ -304,7 +301,6 @@ static const u8 register_values[] = { #else SDRAMC + 0, 0x00, 0x00, /* The board has 3 DIMM slots. */ #endif - SDRAMC + 1, 0x00, 0x00, /* PGPOL - Paging Policy Register * 0x78 - 0x79 @@ -431,40 +427,44 @@ static void do_ram_command(u32 command) static void set_dram_buffer_strength(void) { - /* To give some breathing room for romcc, - * mbsc0 doubles as drb - * mbsc1 doubles as drb1 - * mbfs0 doubles as i and reg + /* + * Program MBSC[39:0] and MBFS[23:0]. + * + * The 440BX datasheet says buffer frequency is independent from bus + * frequency and mismatch both ways are possible. + * + * MBSC[47:40] and MBFS[23] are reserved. */ - uint8_t mbsc0,mbsc1,mbsc3,mbsc4,mbfs0,mbfs2,fsb; - /* Tally how many rows between rows 0-3 and rows 4-7 are populated. + unsigned int i, reg, drb; + uint8_t mbsc0, mbfs0, mbfs1, mbfs2; + uint16_t mbsc1, mbsc3; + + /* + * Tally how many rows between rows 0-3 and rows 4-7 are populated. * This determines how to program MBFS and MBSC. */ uint8_t dimm03 = 0; uint8_t dimm47 = 0; - mbsc0 = 0; - for (mbfs0 = DRB0; mbfs0 <= DRB7; mbfs0++) { - mbsc1 = pci_read_config8(NB, mbfs0); - if (mbsc0 != mbsc1) { - if (mbfs0 <= DRB3) { + for (drb = 0, i = DRB0; i <= DRB7; i++) { + reg = pci_read_config8(NB, i); + if (drb != reg) { + if (i <= DRB3) dimm03++; - } else { + else dimm47++; - } - mbsc0 = mbsc1; + + drb = reg; } } - /* Algorithm bitmap for programming MBSC[39:0] and MBFS[23:0]. - * - * The 440BX datasheet says buffer frequency is independent from bus - * frequency and mismatch both ways are possible. This is how it is - * programmed in the ASUS P2B-LS mainboard. + if (IS_ENABLED(CONFIG_SDRAMPWR_4DIMM)) { + /* + * For a 4 DIMM board, based on ASUS P2B-LS mainboard. * - * There are four main conditions to check when programming DRAM buffer - * frequency and strength: + * There are four main conditions to check when programming + * DRAM buffer frequency and strength: * * a: >2 rows populated across DIMM0,1 * b: >2 rows populated across DIMM2,3 @@ -474,113 +474,167 @@ static void set_dram_buffer_strength(void) * 6: NBXCFG[13] strapped as 66MHz * * CKE0/FENA ----------------------------------------------------------+ - * CKE1/GCKE -------------------[ MBFS ]------------------------+| + * CKE1/GCKE ----------------------[ MBFS ]---------------------+| + * DQMA/CASA[764320]# -------------[ 0 = 66MHz ]--------------------+|| + * DQMB1/CASB1# (Fixed for 66MHz) -[ 1 = 100MHz ]-------------------+||| + * DQMB5/CASB5# (Fixed for 66MHz) ---------------------------------+|||| + * DQMA1/CASA1# (Fixed for 66MHz) --------------------------------+||||| + * DQMA5/CASA5# (Fixed for 66MHz) -------------------------------+|||||| + * CSA[5:0]#,CSB[5:0]# ------------------------------------++++++||||||| + * CS[B7,A7,B6,A6]#/CKE[5342] -------------------------++++||||||||||||| + * MECC[7:0] #2/#1 ----------------------------------++||||||||||||||||| + * MD[63:0] #2/#1 ---------------------------------++||||||||||||||||||| + * MAB[12:11,9:0]#,MAB[13,10],WEB#,SRASB#,SCASB# -+||||||||||||||||||||| + * MAA[13:0],WEA#,SRASA#,SCASA# -----------------+|||||||||||||||||||||| + * Reserved ------------------------------------+||||||||||||||||||||||| + * |||||||||||||||||||||||| + * 3 32 21 10 0 * 2 21 10 0 + * 9876543210987654321098765432109876543210 * 321098765432109876543210 + * 10------------------------1010---------- a -1---------------11----- + * 11------------------------1111---------- !a -0---------------00----- + * --10--------------------------1010------ b --1----------------11--- + * --11--------------------------1111------ !b --0----------------00--- + * ----------------------------------1100-- c ----------------------1- + * ----------------------------------1011-- !c ----------------------0- + * ----1010101000000000000000------------00 1 ---11111111111111----1-0 + * ----000000000000000000000010101010----00 6 ---1111111111111100000-0 + * | | | | | | | | | | ||||||| | | | | | | + * | | | | | | | | | | ||||||| | | | | | +- CKE0/FENA + * | | | | | | | | | | ||||||| | | | | +--- CKE1/GCKE + * | | | | | | | | | | ||||||| | | | +----- DQMA/CASA[764320]# + * | | | | | | | | | | ||||||| | | +------- DQMB1/CASB1# (66MHz: 2x) + * | | | | | | | | | | ||||||| | +--------- DQMB5/CASB5# (66MHz: 2x) + * | | | | | | | | | | ||||||| +----------- DQMA1/CASA1# (66MHz: 2x) + * | | | | | | | | | | ||||||+------------- DQMA5/CASA5# (66MHz: 2x) + * | | | | | | | | | | ++++++-------------- CSA0-5#,CSB0-5# (1x) + * | | | | | | | | | +--------------------- CSA6#/CKE2 + * | | | | | | | | +---[ MBSC ]------ CSB6#/CKE4 + * | | | | | | | +-----[ 00 = 1x ]------ CSA7#/CKE3 + * | | | | | | +-------[ 01 invalid ]------ CSB7#/CKE5 + * | | | | | +---------[ 10 = 2x ]------ MECC[7:0] #1 + * | | | | +-----------[ 11 = 3x ]------ MECC[7:0] #2 + * | | | +--------------------------------- MD[63:0] #1 + * | | +----------------------------------- MD[63:0] #2 + * | +------------------ MAB[12:11,9:0]#,MAB[13,10],WEB#,SRASB#,SCASB# + * +------------------------------------- MAA[13:0],WEA#,SRASA#,SCASA# + */ + unsigned int fsb; + + mbsc0 = 0xa0; + mbsc1 = 0x002a; + mbfs1 = 0xff; + mbfs2 = 0x1f; + if (pci_read_config8(NB, NBXCFG + 1) & 0x30) { + fsb = 66; + mbsc3 = 0xa000; + mbfs0 = 0x80; + } else { + fsb = 100; + mbsc3 = 0xaaa0; + mbfs0 = 0x84; + } + if (dimm03 > 2) { + mbfs2 |= 0x40; + if (fsb == 100) + mbfs0 |= 0x60; + } else { + mbsc3 |= 0xc000; + if (fsb == 100) + mbsc1 |= 0x003c; + } + if (dimm47 > 2) { + mbfs2 |= 0x20; + if (fsb == 100) + mbfs0 |= 0x18; + } else { + mbsc3 |= 0x3000; + if (fsb == 100) { + mbsc1 |= 0x0003; + mbsc0 |= 0xc0; + } + } + if ((dimm03 + dimm47) > 4) { + mbsc0 |= 0x30; + mbfs0 |= 0x02; + } else { + mbsc0 |= 0x2c; + } + } else { + /* + * For a 3 DIMM board, based on ASUS P2B mainboard. + * + * There are two main conditions to check when programming DRAM buffer + * frequency and strength: + * + * a: >2 rows populated across DIMM0,1 + * c: >4 rows populated across all DIMM slots + * + * CKE0 ---------------------------------------------------------------+ + * CKE1 ------------------------[ MBFS ]------------------------+| * DQMA/CASA[764320]# ----------[ 0 = 66MHz ]-----------------------+|| * DQMB1/CASB1# ----------------[ 1 = 100MHz ]----------------------+||| * DQMB5/CASB5# ---------------------------------------------------+|||| * DQMA1/CASA1# --------------------------------------------------+||||| * DQMA5/CASA5# -------------------------------------------------+|||||| * CSA0-5#,CSB0-5# ----------------------------------------++++++||||||| - * CSA6#/CKE2# -------------------------------------------+||||||||||||| - * CSB6#/CKE4# ------------------------------------------+|||||||||||||| - * CSA7#/CKE3# -----------------------------------------+||||||||||||||| - * CSB7#/CKE5# ----------------------------------------+|||||||||||||||| + * CS[B7,A7,B6,A6]#/CKE[5342] -------------------------++++||||||||||||| * MECC[7:0] #2/#1 (100MHz) -------------------------++||||||||||||||||| * MD[63:0] #2/#1 (100MHz) ------------------------++||||||||||||||||||| * MAB[12:11,9:0]#,MAB[13,10],WEB#,SRASB#,SCASB# -+||||||||||||||||||||| * MAA[13:0],WEA#,SRASA#,SCASA# -----------------+|||||||||||||||||||||| * Reserved ------------------------------------+||||||||||||||||||||||| * |||||||||||||||||||||||| - * 3 32 21 10 0 * 2 21 10 0 - * 9876543210987654321098765432109876543210 * 321098765432109876543210 - * a 10------------------------1010---------- * -1---------------11----- a - *!a 11------------------------1111---------- * -0---------------00----- !a - * b --10--------------------------1010------ * --1----------------11--- b - *!b --11--------------------------1111------ * --0----------------00--- !b - * c ----------------------------------1100-- * ----------------------1- c - *!c ----------------------------------1011-- * ----------------------0- !c - * 1 ----1010101000000000000000------------00 * ---11111111111111----1-0 1 - * 6 ----000000000000000000000010101010----00 * ---1111111111111100000-0 6 - * | | | | | | | | | | ||||||| | | | | | | - * | | | | | | | | | | ||||||| | | | | | +- CKE0/FENA - * | | | | | | | | | | ||||||| | | | | +--- CKE1/GCKE - * | | | | | | | | | | ||||||| | | | +----- DQMA/CASA[764320]# - * | | | | | | | | | | ||||||| | | +------- DQMB1/CASB1# - * | | | | | | | | | | ||||||| | +--------- DQMB5/CASB5# - * | | | | | | | | | | ||||||| +----------- DQMA1/CASA1# - * | | | | | | | | | | ||||||+------------- DQMA5/CASA5# - * | | | | | | | | | | ++++++-------------- CSA0-5#,CSB0-5# [ 0=1x;1=2x ] - * | | | | | | | | | +--------------------- CSA6#/CKE2# - * | | | | | | | | +---[ MBSC ]------ CSB6#/CKE4# - * | | | | | | | +-----[ 00 = 1x ]------ CSA7#/CKE3# - * | | | | | | +-------[ 01 invalid ]------ CSB7#/CKE5# - * | | | | | +---------[ 10 = 2x ]------ MECC[7:0] #1 (2x) - * | | | | +-----------[ 11 = 3x ]------ MECC[7:0] #2 (2x) - * | | | +--------------------------------- MD[63:0] #1 (2x) - * | | +----------------------------------- MD[63:0] #2 (2x) - * | +------------------------------------- MAB[12:11,9:0]#,MAB[13,10],WEB#,SRASB#,SCASB# - * +--------------------------------------- MAA[13:0],WEA#,SRASA#,SCASA# - * MBSC[47:40] and MBFS[23] are reserved. - * - * This algorithm is checked against the ASUS P2B-LS (which has - * 4 DIMM slots) factory BIOS. - * Therefore it assumes a board with 4 slots, and will need testing - * on boards with 3 DIMM slots. + * 3 32 21 10 0 * 2 21 10 0 + * 9876543210987654321098765432109876543210 * 321098765432109876543210 + * 10------------------------1111---------- a -1---------------------- + * 11------------------------1010---------- !a -0---------------------- + * --110000000010101010111111----1010--1010 * --01111000000000000000-0 + * ----------------------------------11---- c ----------------------1- + * ----------------------------------10---- !c ----------------------0- + * | | | | | | | | | | ||||||| | | | | | | + * | | | | | | | | | | ||||||| | | | | | +- CKE0 + * | | | | | | | | | | ||||||| | | | | +--- CKE1 + * | | | | | | | | | | ||||||| | | | +----- DQMA/CASA[764320]# + * | | | | | | | | | | ||||||| | | +------- DQMB1/CASB1# + * | | | | | | | | | | ||||||| | +--------- DQMB5/CASB5# + * | | | | | | | | | | ||||||| +----------- DQMA1/CASA1# + * | | | | | | | | | | ||||||+------------- DQMA5/CASA5# + * | | | | | | | | | | ++++++-------------- CSA0-5#,CSB0-5# (2x) + * | | | | | | | | | +--------------------- CSA6#/CKE2 + * | | | | | | | | +---[ MBSC ]------ CSB6#/CKE4 + * | | | | | | | +-----[ 00 = 1x ]------ CSA7#/CKE3 + * | | | | | | +-------[ 01 invalid ]------ CSB7#/CKE5 + * | | | | | +---------[ 10 = 2x ]------ MECC[7:0] #1 (1x) + * | | | | +-----------[ 11 = 3x ]------ MECC[7:0] #2 (1x) + * | | | +--------------------------------- MD[63:0] #1 (1x) + * | | +----------------------------------- MD[63:0] #2 (1x) + * | +------------------ MAB[12:11,9:0]#,MAB[13,10],WEB#,SRASB#,SCASB# + * +------------------------------------- MAA[13:0],WEA#,SRASA#,SCASA# */ - mbsc0 = 0x80; - mbsc1 = 0x2a; - mbfs2 = 0x1f; - if (pci_read_config8(NB, NBXCFG + 1) & 0x30) { - fsb = 66; - mbsc3 = 0x00; - mbsc4 = 0x00; - mbfs0 = 0x80; - } else { - fsb = 100; - mbsc3 = 0xa0; - mbsc4 = 0x0a; - mbfs0 = 0x84; - } + mbsc0 = 0xaa; + mbsc1 = 0xafea; + mbsc3 = 0xb00a; + mbfs0 = 0x00; + mbfs1 = 0x00; + mbfs2 = 0x1e; - if (dimm03 > 2) { - mbsc4 = mbsc4 | 0x80; - mbsc1 = mbsc1 | 0x28; - mbfs2 = mbfs2 | 0x40; - mbfs0 = mbfs0 | 0x60; - } else { - mbsc4 = mbsc4 | 0xc0; - if (fsb == 100) { - mbsc1 = mbsc1 | 0x3c; + if (dimm03 > 2) { + mbsc1 |= 0x003c; + mbfs2 |= 0x40; + } else { + mbsc3 |= 0xc000; } - } - if (dimm47 > 2) { - mbsc4 = mbsc4 | 0x20; - mbsc1 = mbsc1 | 0x02; - mbsc0 = mbsc0 | 0x80; - mbfs2 = mbfs2 | 0x20; - mbfs0 = mbfs0 | 0x18; - } else { - mbsc4 = mbsc4 | 0x30; - if (fsb == 100) { - mbsc1 = mbsc1 | 0x03; - mbsc0 = mbsc0 | 0xc0; + if ((dimm03 + dimm47) > 4) { + mbsc0 |= 0x30; + mbfs0 |= 0x02; } } - if ((dimm03 + dimm47) > 4) { - mbsc0 = mbsc0 | 0x30; - mbfs0 = mbfs0 | 0x02; - } else { - mbsc0 = mbsc0 | 0x2c; - } pci_write_config8(NB, MBSC + 0, mbsc0); - pci_write_config8(NB, MBSC + 1, mbsc1); - pci_write_config8(NB, MBSC + 2, 0x00); - pci_write_config8(NB, MBSC + 3, mbsc3); - pci_write_config8(NB, MBSC + 4, mbsc4); - pci_write_config8(NB, MBFS + 0, mbfs0); - pci_write_config8(NB, MBFS + 1, 0xff); + pci_write_config16(NB, MBSC + 1, mbsc1); + pci_write_config16(NB, MBSC + 3, mbsc3); + pci_write_config16(NB, MBFS + 0, mbfs1 << 8 | mbfs0); pci_write_config8(NB, MBFS + 2, mbfs2); } @@ -683,7 +737,8 @@ static struct dimm_size spd_get_dimm_size(unsigned int device) sz.side1 *= 4; sz.side2 *= 4; - /* It is possible to partially use larger then supported + /* + * It is possible to partially use larger than supported * modules by setting them to a supported size. */ if (sz.side1 > 128) { -- cgit v1.2.3