From a24e1dd6dacc4036466f5fc8acd5a1c4306790d2 Mon Sep 17 00:00:00 2001 From: Elia Yehuda Date: Fri, 5 Jun 2009 00:22:25 +0000 Subject: Add a hopefully more correct and flexible set_dram_buffer_strength() function based on test results with many different DIMMs. Tested by Uwe Hermann on hardware. Might need a small increase of ROM_IMAGE_SIZE for some boards, we'll see. Signed-off-by: Elia Yehuda Acked-by: Corey Osgood Acked-by: Uwe Hermann git-svn-id: svn://svn.coreboot.org/coreboot/trunk@4338 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- src/northbridge/intel/i82810/raminit.c | 75 +++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) (limited to 'src/northbridge') diff --git a/src/northbridge/intel/i82810/raminit.c b/src/northbridge/intel/i82810/raminit.c index 0b3e965192..d5b4864104 100644 --- a/src/northbridge/intel/i82810/raminit.c +++ b/src/northbridge/intel/i82810/raminit.c @@ -72,6 +72,12 @@ static const u8 translate_i82810_to_bank[] = { /* MB */0, 0, 0, 8, 0, 16, 16, 0, 32, 32, 0, 64, 64, 0, 128, 128, }; +struct dimm_info { + u8 ds; /* dual-sided */ + u8 ss; /* single-sided */ + u8 size; +}; + /*----------------------------------------------------------------------------- SDRAM configuration functions. -----------------------------------------------------------------------------*/ @@ -275,10 +281,77 @@ static void set_dram_timing(void) * 0x1145 384MB 0xdf 256MB dual-sided 128MB single-sided * 0x4445 384MB 0xfd 128MB single-sided 256MB dual-sided * 0x0001 512MB 0xff 256MB dual-sided 256MB dual-sided + * + * See also: + * http://www.coreboot.org/pipermail/coreboot/2009-May/047966.html */ static void set_dram_buffer_strength(void) { - pci_write_config16(PCI_DEV(0, 0, 0), BUFF_SC, 0x77da); + struct dimm_info d0, d1; + u16 buff_sc; + + /* Check first slot. */ + d0.size = d0.ds = d0.ss = 0; + if (smbus_read_byte(DIMM_SPD_BASE, SPD_MEMORY_TYPE) + == SPD_MEMORY_TYPE_SDRAM) { + d0.size = smbus_read_byte(DIMM_SPD_BASE, SPD_BANK_DENSITY); + d0.ds = smbus_read_byte(DIMM_SPD_BASE, SPD_NUM_DIMM_BANKS) > 1; + d0.ss = !d0.ds; + } + + /* Check second slot. */ + d1.size = d1.ds = d1.ss = 0; + if (smbus_read_byte(DIMM_SPD_BASE + 1, SPD_MEMORY_TYPE) + == SPD_MEMORY_TYPE_SDRAM) { + d1.size = smbus_read_byte(DIMM_SPD_BASE + 1, SPD_BANK_DENSITY); + d1.ds = smbus_read_byte(DIMM_SPD_BASE + 1, + SPD_NUM_DIMM_BANKS) > 1; + d1.ss = !d1.ds; + } + + buff_sc = 0; + + /* Tame the beast... */ + if ((d0.ds && d1.ds) || (d0.ds && d1.ss) || (d0.ss && d1.ds)) + buff_sc |= 1; + if ((d0.size && !d1.size) || (!d0.size && d1.size) || (d0.ss && d1.ss)) + buff_sc |= 1 << 1; + if ((d0.ds && !d1.size) || (!d0.size && d1.ds) || (d0.ss && d1.ss) + || (d0.ds && d1.ss) || (d0.ss && d1.ds)) + buff_sc |= 1 << 2; + if ((d0.ss && !d1.size) || (!d0.size && d1.ss)) + buff_sc |= 1 << 3; + if ((d0.size && !d1.size) || (!d0.size && d1.size)) + buff_sc |= 1 << 4; + if ((d0.ds && !d1.size) || (!d0.size && d1.ds) || (d0.ds && d1.ss) + || (d0.ss && d1.ds)) + buff_sc |= 1 << 6; + if ((d0.ss && !d1.size) || (!d0.size && d1.ss) || (d0.ss && d1.ss)) + buff_sc |= 3 << 6; + if ((!d0.size && d1.ss) || (d0.ds && d1.ss) || (d0.ss && d1.ss)) + buff_sc |= 1 << 8; + if (d0.size && !d1.size) + buff_sc |= 3 << 8; + if ((d0.ss && !d1.size) || (d0.ss && d1.ss) || (d0.ss && d1.ds)) + buff_sc |= 1 << 10; + if (!d0.size && d1.size) + buff_sc |= 3 << 10; + if ((d0.size && !d1.size) || (d0.ss && !d1.size) || (!d0.size && d1.ss) + || (d0.ss && d1.ss) || (d0.ds && d1.ss)) + buff_sc |= 1 << 12; + if (d0.size && !d1.size) + buff_sc |= 1 << 13; + if ((!d0.size && d1.size) || (d0.ss && !d1.size) || (d0.ss && d1.ss) + || (d0.ss && d1.ds)) + buff_sc |= 1 << 14; + if (!d0.size && d1.size) + buff_sc |= 1 << 15; + + print_debug("BUFF_SC calculated to 0x"); + print_debug_hex16(buff_sc); + print_debug("\r\n"); + + pci_write_config16(PCI_DEV(0, 0, 0), BUFF_SC, buff_sc); } /*----------------------------------------------------------------------------- -- cgit v1.2.3