From a01ee36288b26f31fc1e912324293104f33211c3 Mon Sep 17 00:00:00 2001 From: Rob Barnes Date: Mon, 14 Sep 2020 07:46:19 -0600 Subject: device/dram: Add method for converting MHz to MT/s Add method for converting DDR4 speed in MHz to MT/s. Checks that MHz is within a speed grade range. BUG=b:167155849 TEST=ddr4-test unit test BRANCH=Zork Change-Id: I1433f028afb794fe3e397b03f5bd0565494c8130 Signed-off-by: Rob Barnes Reviewed-on: https://review.coreboot.org/c/coreboot/+/45343 Tested-by: build bot (Jenkins) Reviewed-by: Paul Fagerburg Reviewed-by: Furquan Shaikh --- src/device/dram/Makefile.inc | 2 ++ src/device/dram/ddr4.c | 78 ++++++++++++++++++++++++++++++++++++++++++ src/include/device/dram/ddr4.h | 5 +++ 3 files changed, 85 insertions(+) (limited to 'src') diff --git a/src/device/dram/Makefile.inc b/src/device/dram/Makefile.inc index f397a534f2..f7118dbbc2 100644 --- a/src/device/dram/Makefile.inc +++ b/src/device/dram/Makefile.inc @@ -1 +1,3 @@ romstage-y += ddr4.c ddr3.c ddr2.c ddr_common.c + +ramstage-y += ddr4.c ddr3.c ddr2.c ddr_common.c diff --git a/src/device/dram/ddr4.c b/src/device/dram/ddr4.c index 429a9d271a..e670b20f72 100644 --- a/src/device/dram/ddr4.c +++ b/src/device/dram/ddr4.c @@ -9,6 +9,69 @@ #include #include +enum ddr4_speed_grade { + DDR4_1600, + DDR4_1866, + DDR4_2133, + DDR4_2400, + DDR4_2666, + DDR4_2933, + DDR4_3200 +}; + +struct ddr4_speed_attr { + uint32_t min_clock_mhz; // inclusive + uint32_t max_clock_mhz; // inclusive + uint32_t reported_mts; +}; + +/** + * DDR4 speed attributes derived from JEDEC 79-4C tables 169 & 170 + * + * min_clock_mhz = 1000/max_tCk_avg(ns) + 1 + * Adding 1 to make minimum inclusive + * max_clock_mhz = 1000/min_tCk_avg(ns) + * reported_mts = Standard reported DDR4 speed in MT/s + * May be 1 less than the actual max MT/s + */ +static const struct ddr4_speed_attr ddr4_speeds[] = { + [DDR4_1600] = { + .min_clock_mhz = 668, + .max_clock_mhz = 800, + .reported_mts = 1600 + }, + [DDR4_1866] = { + .min_clock_mhz = 801, + .max_clock_mhz = 934, + .reported_mts = 1866 + }, + [DDR4_2133] = { + .min_clock_mhz = 935, + .max_clock_mhz = 1067, + .reported_mts = 2133 + }, + [DDR4_2400] = { + .min_clock_mhz = 1068, + .max_clock_mhz = 1200, + .reported_mts = 2400 + }, + [DDR4_2666] = { + .min_clock_mhz = 1201, + .max_clock_mhz = 1333, + .reported_mts = 2666 + }, + [DDR4_2933] = { + .min_clock_mhz = 1334, + .max_clock_mhz = 1466, + .reported_mts = 2933 + }, + [DDR4_3200] = { + .min_clock_mhz = 1467, + .max_clock_mhz = 1600, + .reported_mts = 3200 + } +}; + typedef enum { BLOCK_0, /* Base Configuration and DRAM Parameters */ BLOCK_1, @@ -68,6 +131,21 @@ static bool block_exists(spd_block_type type, u8 dimm_type) } } +/** + * Converts DDR4 clock speed in MHz to the standard reported speed in MT/s + */ +uint16_t ddr4_speed_mhz_to_reported_mts(uint16_t speed_mhz) +{ + for (enum ddr4_speed_grade speed = 0; speed < ARRAY_SIZE(ddr4_speeds); speed++) { + const struct ddr4_speed_attr *speed_attr = &ddr4_speeds[speed]; + if (speed_mhz >= speed_attr->min_clock_mhz && + speed_mhz <= speed_attr->max_clock_mhz) { + return speed_attr->reported_mts; + } + } + printk(BIOS_ERR, "ERROR: DDR4 speed of %d MHz is out of range", speed_mhz); + return 0; +} /** * \brief Decode the raw SPD data diff --git a/src/include/device/dram/ddr4.h b/src/include/device/dram/ddr4.h index d22d4bc500..eac8bf8920 100644 --- a/src/include/device/dram/ddr4.h +++ b/src/include/device/dram/ddr4.h @@ -69,4 +69,9 @@ enum cb_err spd_add_smbios17_ddr4(const u8 channel, const u8 slot, const u16 selected_freq, const dimm_attr *info); +/** + * Converts DDR4 clock speed in MHz to the standard reported speed in MT/s + */ +uint16_t ddr4_speed_mhz_to_reported_mts(uint16_t speed_mhz); + #endif /* DEVICE_DRAM_DDR4L_H */ -- cgit v1.2.3