summaryrefslogtreecommitdiff
path: root/src/device
diff options
context:
space:
mode:
authorNicola Corna <nicola@corna.info>2016-11-16 08:57:15 +0100
committerMartin Roth <martinroth@google.com>2016-12-27 18:18:04 +0100
commit76f8dbc4f70469e0b5913796d6130e85df1cdd77 (patch)
treee28af65fa0a0c8134840d2de087b96dfa0794fae /src/device
parentaa5c8f78f98614130cfb4802faa30b6a6b92e815 (diff)
downloadcoreboot-76f8dbc4f70469e0b5913796d6130e85df1cdd77.tar.xz
device/dram/ddr3: add FTB timings
SPD revision 1.1 introduced FTB timings, an extra set of SPD values that specify a more precise tCKmin, tAAmin, tRCDmin, tRPmin and tRCmin. For backwards compatibility, the MTB is usually rounded up and the FTB part is negative. For this reason some memories were not set up optimally, as the FTB part was ignored and the resulting timing wasn't set to the minimum value. The tests were performed on a Lenovo X220 with two Micron 8KTF51264HZ-1G9E (1866 MHz): reading only the MTB part, coreboot reports a tCKmin of 1.125 ns, corresponding to a working frequency of 800 MHz; with the additional tCKmin FTB part (-0.054 ns) the new (rounded) value is 1.070 ns, valid for a 933 MHz operation. Tested also with Ballistix DDR3-1866 SODIMM on Lenovo T420: the memory is now detected as DDR3-1866 instead of DDR3-1600. Some manufacturers (like Micron) seems to expect a small rounding on the timings, so a nearest-value rounding is performed. If this assumption isn't correct, an error up to ~2 ps can be committed, which is low enough to be safely ignored. Change-Id: Ib98f2e70820f207429d04ca6421680109a81f457 Signed-off-by: Nicola Corna <nicola@corna.info> Reviewed-on: https://review.coreboot.org/17476 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Rudolph <siro@das-labor.org> Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Diffstat (limited to 'src/device')
-rw-r--r--src/device/dram/ddr3.c37
1 files changed, 30 insertions, 7 deletions
diff --git a/src/device/dram/ddr3.c b/src/device/dram/ddr3.c
index 6e5c541a85..db661a9886 100644
--- a/src/device/dram/ddr3.c
+++ b/src/device/dram/ddr3.c
@@ -129,9 +129,10 @@ int spd_decode_ddr3(dimm_attr * dimm, spd_raw_data spd)
{
int ret;
u16 crc, spd_crc;
- u8 ftb_divisor, ftb_dividend, capacity_shift, bus_width;
+ u8 capacity_shift, bus_width;
u8 reg8;
u32 mtb; /* medium time base */
+ u32 ftb; /* fine time base */
unsigned int val, param;
ret = SPD_STATUS_OK;
@@ -263,12 +264,6 @@ int spd_decode_ddr3(dimm_attr * dimm, spd_raw_data spd)
dimm->size_mb = ((1 << (capacity_shift + (25 - 20))) * bus_width
* dimm->ranks) / dimm->width;
- /* Fine Timebase (FTB) Dividend/Divisor */
- /* Dividend */
- ftb_dividend = (spd[9] >> 4) & 0x0f;
- /* Divisor */
- ftb_divisor = spd[9] & 0x0f;
-
/* Medium Timebase =
* Medium Timebase (MTB) Dividend /
* Medium Timebase (MTB) Divisor */
@@ -301,6 +296,34 @@ int spd_decode_ddr3(dimm_attr * dimm, spd_raw_data spd)
/* Minimum Four Activate Window Delay Time (tFAWmin) */
dimm->tFAW = (((spd[28] & 0x0f) << 8) + spd[29]) * mtb;
+ printram(" FTB timings :");
+ /* FTB is introduced in SPD revision 1.1 */
+ if (spd[1] >= 0x11 && spd[9] & 0x0f) {
+ printram(" yes\n");
+
+ /* Fine timebase (1/256 ps) =
+ * Fine Timebase (FTB) Dividend /
+ * Fine Timebase (FTB) Divisor */
+ ftb = (((u16) spd[9] & 0xf0) << 4) / (spd[9] & 0x0f);
+
+ /* SPD recommends to round up the MTB part and use a negative
+ * FTB, so a negative rounding should be always safe */
+
+ /* SDRAM Minimum Cycle Time (tCKmin) correction */
+ dimm->tCK += (s32)((s8) spd[34] * ftb - 500) / 1000;
+ /* Minimum CAS Latency Time (tAAmin) correction */
+ dimm->tAA += (s32)((s8) spd[35] * ftb - 500) / 1000;
+ /* Minimum RAS# to CAS# Delay Time (tRCDmin) correction */
+ dimm->tRCD += (s32)((s8) spd[36] * ftb - 500) / 1000;
+ /* Minimum Row Precharge Delay Time (tRPmin) correction */
+ dimm->tRP += (s32)((s8) spd[37] * ftb - 500) / 1000;
+ /* Minimum Active to Active/Refresh Delay Time (tRCmin) corr. */
+ dimm->tRC += (s32)((s8) spd[38] * ftb - 500) / 1000;
+ }
+ else {
+ printram(" no\n");
+ }
+
/* SDRAM Optional Features */
reg8 = spd[30];
printram(" Optional features :");