From e089a3f68ddbbaaceb25d00322b3e7ccc27a48a8 Mon Sep 17 00:00:00 2001 From: Keith Hui Date: Tue, 2 Aug 2011 22:28:14 -0400 Subject: northbridge/intel/i440bx: Registered SDRAM modules support and fixes Adds support for initializing registered SDRAM modules on Intel 440BX northbridge. Drops unneeded romcc-inspired programming tricks. Only set nbxecc flags (see 440BX datasheet, page 3-16) when a non-ECC module has been detected in a row via SPD; also drops an unneeded intermediate variable used in setting them. Boot tested on ASUS P2B-LS with regular and registered ECC SDRAM under Linux and memtest86+. Change-Id: Idc99d49567cca55f819d6b0e98952b1c3256498a Signed-off-by: Keith Hui Reviewed-on: http://review.coreboot.org/128 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer --- src/northbridge/intel/i440bx/raminit.c | 64 +++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 25 deletions(-) (limited to 'src/northbridge/intel/i440bx') diff --git a/src/northbridge/intel/i440bx/raminit.c b/src/northbridge/intel/i440bx/raminit.c index 9fc124b7ff..232b87249c 100644 --- a/src/northbridge/intel/i440bx/raminit.c +++ b/src/northbridge/intel/i440bx/raminit.c @@ -258,7 +258,7 @@ static const u8 register_values[] = { * 01 4 KB * 10 8 KB * 11 Reserved - * + * * RPS bits Corresponding DRB register * [01:00] DRB[0], row 0 * [03:02] DRB[1], row 1 @@ -721,19 +721,23 @@ static struct dimm_size spd_get_dimm_size(unsigned int device) */ static void set_dram_row_attributes(void) { - int i, dra, drb, col, width, value, rps, edosd, ecc, nbxecc; + int i, dra, drb, col, width, value, rps; u8 bpr; /* Top 8 bits of PGPOL */ + u8 nbxecc = 0; /* NBXCFG[31:24] */ + u8 edo, sd, regsd; /* EDO, SDRAM, registered SDRAM */ - edosd = 0; + edo = 0; + sd = 0; + regsd = 1; rps = 0; drb = 0; bpr = 0; - nbxecc = 0xff; for (i = 0; i < DIMM_SOCKETS; i++) { unsigned int device; device = DIMM0 + i; bpr >>= 2; + nbxecc >>= 2; /* First check if a DIMM is actually present. */ value = spd_read_byte(device, SPD_MEMORY_TYPE); @@ -742,13 +746,13 @@ static void set_dram_row_attributes(void) || value == SPD_MEMORY_TYPE_SDRAM) { if (value == SPD_MEMORY_TYPE_EDO) { - edosd |= 0x02; + edo = 1; } else if (value == SPD_MEMORY_TYPE_SDRAM) { - edosd |= 0x04; + sd = 1; } PRINT_DEBUG("Found DIMM in slot %d\n", i); - if (edosd == 0x06) { + if (edo && sd) { print_err("Mixing EDO/SDRAM unsupported!\n"); die("HALT\n"); } @@ -764,23 +768,37 @@ static void set_dram_row_attributes(void) * TODO: Other register than NBXCFG also needs this * ECC information. */ - ecc = spd_read_byte(device, SPD_DIMM_CONFIG_TYPE); + value = spd_read_byte(device, SPD_DIMM_CONFIG_TYPE); /* Data width */ width = spd_read_byte(device, SPD_MODULE_DATA_WIDTH_LSB); /* Exclude error checking data width from page size calculations */ - if (ecc) { + if (value) { value = spd_read_byte(device, SPD_ERROR_CHECKING_SDRAM_WIDTH); width -= value; /* ### ECC */ /* Clear top 2 bits to help set up NBXCFG. */ - ecc &= 0x3f; + nbxecc &= 0x3f; } else { /* Without ECC, top 2 bits should be 11. */ - ecc |= 0xc0; + nbxecc |= 0xc0; + } + + /* If any installed DIMM is *not* registered, this system cannot be + * configured for registered SDRAM. + * By registered, only the address and control lines need to be, which + * we can tell by reading SPD byte 21, bit 1. + */ + value = spd_read_byte(device, SPD_MODULE_ATTRIBUTES); + + PRINT_DEBUG("DIMM is "); + if ((value & MODULE_REGISTERED) == 0) { + regsd = 0; + PRINT_DEBUG("not "); } + PRINT_DEBUG("registered\n"); /* Calculate page size in bits. */ value = ((1 << col) * width); @@ -801,7 +819,6 @@ static void set_dram_row_attributes(void) * Second bank of 1-bank DIMMs "doesn't have * ECC" - or anything. */ - ecc |= 0x80; if (dra == 2) { dra = 0x0; /* 2KB */ } else if (dra == 4) { @@ -878,7 +895,6 @@ static void set_dram_row_attributes(void) /* If there's no DIMM in the slot, set dra to 0x00. */ dra = 0x00; - ecc = 0xc0; /* Still have to propagate DRB over. */ drb &= 0xff; drb |= (drb << 8); @@ -895,7 +911,6 @@ static void set_dram_row_attributes(void) drb >>= 8; rps |= (dra & 0x0f) << (i * 4); - nbxecc = (nbxecc >> 2) | (ecc & 0xc0); } /* Set paging policy register. */ @@ -910,20 +925,19 @@ static void set_dram_row_attributes(void) pci_write_config8(NB, NBXCFG + 3, nbxecc); PRINT_DEBUG("NBXECC[31:24] has been set to 0x%02x\n", nbxecc); - /* Set DRAMC[4:3] to proper memory type (EDO/SDRAM). - * TODO: Registered SDRAM support. - */ - edosd &= 0x07; - if (edosd & 0x02) { - edosd |= 0x00; - } else if (edosd & 0x04) { - edosd |= 0x08; + /* Set DRAMC[4:3] to proper memory type (EDO/SDRAM/Registered SDRAM). */ + + /* i will be used to set DRAMC[4:3]. */ + if (regsd && sd) { + i = 0x10; // Registered SDRAM + } else if (sd) { + i = 0x08; // SDRAM + } else { + i = 0; // EDO } - edosd &= 0x18; - /* edosd is now in the form needed for DRAMC[4:3]. */ value = pci_read_config8(NB, DRAMC) & 0xe7; - value |= edosd; + value |= i; pci_write_config8(NB, DRAMC, value); PRINT_DEBUG("DRAMC has been set to 0x%02x\n", value); } -- cgit v1.2.3