From bb9d106eab6212229fb1d6d4645f93bb883850ac Mon Sep 17 00:00:00 2001 From: Matt DeVillier Date: Mon, 22 Aug 2022 17:27:11 -0500 Subject: [PATCH] device/dram: Add function to convert freq to MT/s for (LP)DDR5 As the frequency field in the SMBIOS type 17 table is deprecated, we need to provide the maximum and configured speed in MT/s. Add a method to convert from frequency to MT/s using a lookup table. BUG=b:239000826 TEST=Build and verify with other patches in train Change-Id: I0402b33a667f7d72918365a6a79b13c5b1719c0d Signed-off-by: Matt DeVillier Reviewed-on: https://review.coreboot.org/c/coreboot/+/66953 Tested-by: build bot (Jenkins) Reviewed-by: Raul Rangel Reviewed-by: Fred Reitberger Reviewed-by: Marshall Dawson --- src/device/dram/Makefile.inc | 4 +- src/device/dram/ddr5.c | 128 +++++++++++++++++++++++++++++++++ src/include/device/dram/ddr5.h | 20 ++++++ 3 files changed, 150 insertions(+), 2 deletions(-) create mode 100644 src/device/dram/ddr5.c create mode 100644 src/include/device/dram/ddr5.h diff --git a/src/device/dram/Makefile.inc b/src/device/dram/Makefile.inc index b91b128f85..31dfb91d7f 100644 --- a/src/device/dram/Makefile.inc +++ b/src/device/dram/Makefile.inc @@ -1,3 +1,3 @@ -romstage-y += lpddr4.c ddr4.c ddr3.c ddr2.c ddr_common.c +romstage-y += ddr5.c lpddr4.c ddr4.c ddr3.c ddr2.c ddr_common.c -ramstage-y += lpddr4.c ddr4.c ddr3.c ddr2.c ddr_common.c spd.c +ramstage-y += ddr5.c lpddr4.c ddr4.c ddr3.c ddr2.c ddr_common.c spd.c diff --git a/src/device/dram/ddr5.c b/src/device/dram/ddr5.c new file mode 100644 index 0000000000..698f77df05 --- /dev/null +++ b/src/device/dram/ddr5.c @@ -0,0 +1,128 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include +#include + +enum ddr5_speed_grade { + DDR5_1333, + DDR5_1600, + DDR5_1866, + DDR5_2133, + DDR5_2400, + DDR5_2667, + DDR5_2933, + DDR5_3200, + DDR5_3733, + DDR5_4267, + DDR5_4800, + DDR5_5500, + DDR5_6000, + DDR5_6400, +}; + +struct ddr5_speed_attr { + uint32_t min_clock_mhz; // inclusive + uint32_t max_clock_mhz; // inclusive + uint32_t reported_mts; +}; + +/** + * (LP)DDR5 speed attributes derived from JEDEC JESD79-5B, JESD209-5B and industry norms + * + * min_clock_mhz = previous max speed + 1 + * max_clock_mhz = 50% of speed grade, +/- 1 + * reported_mts = Standard reported DDR5 speed in MT/s + * May be slightly less than the actual max MT/s + */ +static const struct ddr5_speed_attr ddr5_speeds[] = { + [DDR5_1333] = { + .min_clock_mhz = 10, + .max_clock_mhz = 667, + .reported_mts = 1333, + }, + [DDR5_1600] = { + .min_clock_mhz = 668, + .max_clock_mhz = 800, + .reported_mts = 1600, + }, + [DDR5_1866] = { + .min_clock_mhz = 801, + .max_clock_mhz = 933, + .reported_mts = 1866, + }, + [DDR5_2133] = { + .min_clock_mhz = 934, + .max_clock_mhz = 1067, + .reported_mts = 2133, + }, + [DDR5_2400] = { + .min_clock_mhz = 1068, + .max_clock_mhz = 1200, + .reported_mts = 2400, + }, + [DDR5_2667] = { + .min_clock_mhz = 1201, + .max_clock_mhz = 1333, + .reported_mts = 2667, + }, + [DDR5_2933] = { + .min_clock_mhz = 1334, + .max_clock_mhz = 1467, + .reported_mts = 2933, + }, + [DDR5_3200] = { + .min_clock_mhz = 1468, + .max_clock_mhz = 1600, + .reported_mts = 3200, + }, + [DDR5_3733] = { + .min_clock_mhz = 1601, + .max_clock_mhz = 1866, + .reported_mts = 3733 + }, + [DDR5_4267] = { + .min_clock_mhz = 1867, + .max_clock_mhz = 2133, + .reported_mts = 4267 + }, + [DDR5_4800] = { + .min_clock_mhz = 2134, + .max_clock_mhz = 2400, + .reported_mts = 4800 + }, + [DDR5_5500] = { + .min_clock_mhz = 2401, + .max_clock_mhz = 2750, + .reported_mts = 5500 + }, + [DDR5_6000] = { + .min_clock_mhz = 2751, + .max_clock_mhz = 3000, + .reported_mts = 6000 + }, + [DDR5_6400] = { + .min_clock_mhz = 3001, + .max_clock_mhz = 3200, + .reported_mts = 6400 + }, +}; + +/** + * Converts DDR5 clock speed in MHz to the standard reported speed in MT/s + */ +uint16_t ddr5_speed_mhz_to_reported_mts(uint16_t speed_mhz) +{ + for (enum ddr5_speed_grade speed = 0; speed < ARRAY_SIZE(ddr5_speeds); speed++) { + const struct ddr5_speed_attr *speed_attr = &ddr5_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, "DDR5 speed of %d MHz is out of range\n", speed_mhz); + return 0; +} diff --git a/src/include/device/dram/ddr5.h b/src/include/device/dram/ddr5.h new file mode 100644 index 0000000000..a509126371 --- /dev/null +++ b/src/include/device/dram/ddr5.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef DEVICE_DRAM_DDR5_H +#define DEVICE_DRAM_DDR5_H + +/** + * @file ddr5.h + * + * \brief Utilities for decoding (LP)DDR5 info + */ + +#include +#include + +/** + * Converts DDR5 clock speed in MHz to the standard reported speed in MT/s + */ +uint16_t ddr5_speed_mhz_to_reported_mts(uint16_t speed_mhz); + +#endif /* DEVICE_DRAM_DDR5_H */