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 <buurin@gmail.com> Reviewed-on: http://review.coreboot.org/128 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
parent
6de1ee4a30
commit
e089a3f68d
|
@ -258,7 +258,7 @@ static const u8 register_values[] = {
|
||||||
* 01 4 KB
|
* 01 4 KB
|
||||||
* 10 8 KB
|
* 10 8 KB
|
||||||
* 11 Reserved
|
* 11 Reserved
|
||||||
*
|
*
|
||||||
* RPS bits Corresponding DRB register
|
* RPS bits Corresponding DRB register
|
||||||
* [01:00] DRB[0], row 0
|
* [01:00] DRB[0], row 0
|
||||||
* [03:02] DRB[1], row 1
|
* [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)
|
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 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;
|
rps = 0;
|
||||||
drb = 0;
|
drb = 0;
|
||||||
bpr = 0;
|
bpr = 0;
|
||||||
nbxecc = 0xff;
|
|
||||||
|
|
||||||
for (i = 0; i < DIMM_SOCKETS; i++) {
|
for (i = 0; i < DIMM_SOCKETS; i++) {
|
||||||
unsigned int device;
|
unsigned int device;
|
||||||
device = DIMM0 + i;
|
device = DIMM0 + i;
|
||||||
bpr >>= 2;
|
bpr >>= 2;
|
||||||
|
nbxecc >>= 2;
|
||||||
|
|
||||||
/* First check if a DIMM is actually present. */
|
/* First check if a DIMM is actually present. */
|
||||||
value = spd_read_byte(device, SPD_MEMORY_TYPE);
|
value = spd_read_byte(device, SPD_MEMORY_TYPE);
|
||||||
|
@ -742,13 +746,13 @@ static void set_dram_row_attributes(void)
|
||||||
|| value == SPD_MEMORY_TYPE_SDRAM) {
|
|| value == SPD_MEMORY_TYPE_SDRAM) {
|
||||||
|
|
||||||
if (value == SPD_MEMORY_TYPE_EDO) {
|
if (value == SPD_MEMORY_TYPE_EDO) {
|
||||||
edosd |= 0x02;
|
edo = 1;
|
||||||
} else if (value == SPD_MEMORY_TYPE_SDRAM) {
|
} else if (value == SPD_MEMORY_TYPE_SDRAM) {
|
||||||
edosd |= 0x04;
|
sd = 1;
|
||||||
}
|
}
|
||||||
PRINT_DEBUG("Found DIMM in slot %d\n", i);
|
PRINT_DEBUG("Found DIMM in slot %d\n", i);
|
||||||
|
|
||||||
if (edosd == 0x06) {
|
if (edo && sd) {
|
||||||
print_err("Mixing EDO/SDRAM unsupported!\n");
|
print_err("Mixing EDO/SDRAM unsupported!\n");
|
||||||
die("HALT\n");
|
die("HALT\n");
|
||||||
}
|
}
|
||||||
|
@ -764,24 +768,38 @@ static void set_dram_row_attributes(void)
|
||||||
* TODO: Other register than NBXCFG also needs this
|
* TODO: Other register than NBXCFG also needs this
|
||||||
* ECC information.
|
* ECC information.
|
||||||
*/
|
*/
|
||||||
ecc = spd_read_byte(device, SPD_DIMM_CONFIG_TYPE);
|
value = spd_read_byte(device, SPD_DIMM_CONFIG_TYPE);
|
||||||
|
|
||||||
/* Data width */
|
/* Data width */
|
||||||
width = spd_read_byte(device, SPD_MODULE_DATA_WIDTH_LSB);
|
width = spd_read_byte(device, SPD_MODULE_DATA_WIDTH_LSB);
|
||||||
|
|
||||||
/* Exclude error checking data width from page size calculations */
|
/* Exclude error checking data width from page size calculations */
|
||||||
if (ecc) {
|
if (value) {
|
||||||
value = spd_read_byte(device,
|
value = spd_read_byte(device,
|
||||||
SPD_ERROR_CHECKING_SDRAM_WIDTH);
|
SPD_ERROR_CHECKING_SDRAM_WIDTH);
|
||||||
width -= value;
|
width -= value;
|
||||||
/* ### ECC */
|
/* ### ECC */
|
||||||
/* Clear top 2 bits to help set up NBXCFG. */
|
/* Clear top 2 bits to help set up NBXCFG. */
|
||||||
ecc &= 0x3f;
|
nbxecc &= 0x3f;
|
||||||
} else {
|
} else {
|
||||||
/* Without ECC, top 2 bits should be 11. */
|
/* 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. */
|
/* Calculate page size in bits. */
|
||||||
value = ((1 << col) * width);
|
value = ((1 << col) * width);
|
||||||
|
|
||||||
|
@ -801,7 +819,6 @@ static void set_dram_row_attributes(void)
|
||||||
* Second bank of 1-bank DIMMs "doesn't have
|
* Second bank of 1-bank DIMMs "doesn't have
|
||||||
* ECC" - or anything.
|
* ECC" - or anything.
|
||||||
*/
|
*/
|
||||||
ecc |= 0x80;
|
|
||||||
if (dra == 2) {
|
if (dra == 2) {
|
||||||
dra = 0x0; /* 2KB */
|
dra = 0x0; /* 2KB */
|
||||||
} else if (dra == 4) {
|
} 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. */
|
/* If there's no DIMM in the slot, set dra to 0x00. */
|
||||||
dra = 0x00;
|
dra = 0x00;
|
||||||
ecc = 0xc0;
|
|
||||||
/* Still have to propagate DRB over. */
|
/* Still have to propagate DRB over. */
|
||||||
drb &= 0xff;
|
drb &= 0xff;
|
||||||
drb |= (drb << 8);
|
drb |= (drb << 8);
|
||||||
|
@ -895,7 +911,6 @@ static void set_dram_row_attributes(void)
|
||||||
drb >>= 8;
|
drb >>= 8;
|
||||||
|
|
||||||
rps |= (dra & 0x0f) << (i * 4);
|
rps |= (dra & 0x0f) << (i * 4);
|
||||||
nbxecc = (nbxecc >> 2) | (ecc & 0xc0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set paging policy register. */
|
/* Set paging policy register. */
|
||||||
|
@ -910,20 +925,19 @@ static void set_dram_row_attributes(void)
|
||||||
pci_write_config8(NB, NBXCFG + 3, nbxecc);
|
pci_write_config8(NB, NBXCFG + 3, nbxecc);
|
||||||
PRINT_DEBUG("NBXECC[31:24] has been set to 0x%02x\n", nbxecc);
|
PRINT_DEBUG("NBXECC[31:24] has been set to 0x%02x\n", nbxecc);
|
||||||
|
|
||||||
/* Set DRAMC[4:3] to proper memory type (EDO/SDRAM).
|
/* Set DRAMC[4:3] to proper memory type (EDO/SDRAM/Registered SDRAM). */
|
||||||
* TODO: Registered SDRAM support.
|
|
||||||
*/
|
/* i will be used to set DRAMC[4:3]. */
|
||||||
edosd &= 0x07;
|
if (regsd && sd) {
|
||||||
if (edosd & 0x02) {
|
i = 0x10; // Registered SDRAM
|
||||||
edosd |= 0x00;
|
} else if (sd) {
|
||||||
} else if (edosd & 0x04) {
|
i = 0x08; // SDRAM
|
||||||
edosd |= 0x08;
|
} 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 = pci_read_config8(NB, DRAMC) & 0xe7;
|
||||||
value |= edosd;
|
value |= i;
|
||||||
pci_write_config8(NB, DRAMC, value);
|
pci_write_config8(NB, DRAMC, value);
|
||||||
PRINT_DEBUG("DRAMC has been set to 0x%02x\n", value);
|
PRINT_DEBUG("DRAMC has been set to 0x%02x\n", value);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue