From 7a7b4f05fc6375d63e2128c791006c5f9e1c45ac Mon Sep 17 00:00:00 2001 From: Yuchi Chen Date: Tue, 3 Sep 2024 22:58:00 +0800 Subject: include/spd_bin.h: Add SPD IO layer By default, PCH SMBus codes will be called to retrieve SPD data. This patch adds a SPD IO layer so that SoC could implement its specific SPD IO layer functions such as using Integrated Memory Controller to get SPD data. Change-Id: I656298aeda409fca3c85266b5b8727fac9bfc917 Signed-off-by: Yuchi Chen Reviewed-on: https://review.coreboot.org/c/coreboot/+/84201 Reviewed-by: Shuo Liu Tested-by: build bot (Jenkins) --- src/include/spd_bin.h | 4 ++++ src/soc/intel/common/block/smbus/Makefile.mk | 2 ++ src/soc/intel/common/block/smbus/smbuslib.c | 30 +++++++++++++-------------- src/soc/intel/common/block/smbus/spd_access.c | 19 +++++++++++++++++ 4 files changed, 40 insertions(+), 15 deletions(-) create mode 100644 src/soc/intel/common/block/smbus/spd_access.c diff --git a/src/include/spd_bin.h b/src/include/spd_bin.h index c51e449559..434d674755 100644 --- a/src/include/spd_bin.h +++ b/src/include/spd_bin.h @@ -49,6 +49,10 @@ uintptr_t spd_cbfs_map(u8 spd_index); void dump_spd_info(struct spd_block *blk); void get_spd_smbus(struct spd_block *blk); +int spd_read_byte(u8 slave_addr, u8 bus_addr); +int spd_read_word(u8 slave_addr, u8 bus_addr); +void spd_write_byte(u8 slave_addr, u8 bus_addr, u8 value); + /* * get_spd_sn returns the SODIMM serial number. It only supports DDR3 and DDR4. * return CB_SUCCESS, sn is the serial number and sn=0xffffffff if the dimm is not present. diff --git a/src/soc/intel/common/block/smbus/Makefile.mk b/src/soc/intel/common/block/smbus/Makefile.mk index 777d92ad09..dd568144e5 100644 --- a/src/soc/intel/common/block/smbus/Makefile.mk +++ b/src/soc/intel/common/block/smbus/Makefile.mk @@ -1,8 +1,10 @@ ## SPDX-License-Identifier: GPL-2.0-only +bootblock-$(CONFIG_SOC_INTEL_COMMON_BLOCK_SMBUS) += spd_access.c bootblock-$(CONFIG_SOC_INTEL_COMMON_BLOCK_SMBUS) += smbuslib.c bootblock-$(CONFIG_SOC_INTEL_COMMON_BLOCK_SMBUS) += smbus_early.c bootblock-$(CONFIG_SOC_INTEL_COMMON_BLOCK_TCO) += tco.c +romstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_SMBUS) += spd_access.c romstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_SMBUS) += smbuslib.c romstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_SMBUS) += smbus_early.c romstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_TCO) += tco.c diff --git a/src/soc/intel/common/block/smbus/smbuslib.c b/src/soc/intel/common/block/smbus/smbuslib.c index aff6fb0a1b..deb09b390d 100644 --- a/src/soc/intel/common/block/smbus/smbuslib.c +++ b/src/soc/intel/common/block/smbus/smbuslib.c @@ -20,7 +20,7 @@ static void update_spd_len(struct spd_block *blk) blk->len = SPD_PAGE_LEN; } -static void smbus_read_spd(u8 *spd, u8 addr) +static void spd_read(u8 *spd, u8 addr) { u16 i; u8 step = 1; @@ -31,9 +31,9 @@ static void smbus_read_spd(u8 *spd, u8 addr) for (i = 0; i < SPD_PAGE_LEN; i += step) { if (CONFIG(SPD_READ_BY_WORD)) ((u16*)spd)[i / sizeof(uint16_t)] = - smbus_read_word(addr, i); + spd_read_word(addr, i); else - spd[i] = smbus_read_byte(addr, i); + spd[i] = spd_read_byte(addr, i); } } @@ -42,11 +42,11 @@ static int get_spd(u8 *spd, u8 addr) { if (CONFIG_DIMM_SPD_SIZE > SPD_PAGE_LEN) { /* Restore to page 0 before reading */ - smbus_write_byte(SPD_PAGE_0, 0, 0); + spd_write_byte(SPD_PAGE_0, 0, 0); } /* If address is not 0, it will return CB_ERR(-1) if no dimm */ - if (smbus_read_byte(addr, 0) < 0) { + if (spd_read_byte(addr, 0) < 0) { printk(BIOS_INFO, "No memory dimm at address %02X\n", addr << 1); return -1; @@ -54,20 +54,20 @@ static int get_spd(u8 *spd, u8 addr) if (i2c_eeprom_read(addr, 0, SPD_PAGE_LEN, spd) < 0) { printk(BIOS_INFO, "do_i2c_eeprom_read failed, using fallback\n"); - smbus_read_spd(spd, addr); + spd_read(spd, addr); } /* Check if module is DDR4, DDR4 spd is 512 byte. */ if (spd[SPD_DRAM_TYPE] == SPD_DRAM_DDR4 && CONFIG_DIMM_SPD_SIZE > SPD_PAGE_LEN) { /* Switch to page 1 */ - smbus_write_byte(SPD_PAGE_1, 0, 0); + spd_write_byte(SPD_PAGE_1, 0, 0); if (i2c_eeprom_read(addr, 0, SPD_PAGE_LEN, spd + SPD_PAGE_LEN) < 0) { printk(BIOS_INFO, "do_i2c_eeprom_read failed, using fallback\n"); - smbus_read_spd(spd + SPD_PAGE_LEN, addr); + spd_read(spd + SPD_PAGE_LEN, addr); } /* Restore to page 0 */ - smbus_write_byte(SPD_PAGE_0, 0, 0); + spd_write_byte(SPD_PAGE_0, 0, 0); } return 0; } @@ -109,11 +109,11 @@ enum cb_err get_spd_sn(u8 addr, u32 *sn) if (CONFIG_DIMM_SPD_SIZE > SPD_PAGE_LEN) { /* Restore to page 0 before reading */ - smbus_write_byte(SPD_PAGE_0, 0, 0); + spd_write_byte(SPD_PAGE_0, 0, 0); } /* If dimm is not present, set sn to 0xff. */ - smbus_ret = smbus_read_byte(addr, SPD_DRAM_TYPE); + smbus_ret = spd_read_byte(addr, SPD_DRAM_TYPE); if (smbus_ret < 0) { printk(BIOS_INFO, "No memory dimm at address %02X\n", addr << 1); *sn = 0xffffffff; @@ -125,17 +125,17 @@ enum cb_err get_spd_sn(u8 addr, u32 *sn) /* Check if module is DDR4, DDR4 spd is 512 byte. */ if (dram_type == SPD_DRAM_DDR4 && CONFIG_DIMM_SPD_SIZE > SPD_PAGE_LEN) { /* Switch to page 1 */ - smbus_write_byte(SPD_PAGE_1, 0, 0); + spd_write_byte(SPD_PAGE_1, 0, 0); for (i = 0; i < SPD_SN_LEN; i++) - *((u8 *)sn + i) = smbus_read_byte(addr, + *((u8 *)sn + i) = spd_read_byte(addr, i + DDR4_SPD_SN_OFF); /* Restore to page 0 */ - smbus_write_byte(SPD_PAGE_0, 0, 0); + spd_write_byte(SPD_PAGE_0, 0, 0); } else if (dram_type == SPD_DRAM_DDR3) { for (i = 0; i < SPD_SN_LEN; i++) - *((u8 *)sn + i) = smbus_read_byte(addr, + *((u8 *)sn + i) = spd_read_byte(addr, i + DDR3_SPD_SN_OFF); } else { printk(BIOS_ERR, "Unsupported dram_type\n"); diff --git a/src/soc/intel/common/block/smbus/spd_access.c b/src/soc/intel/common/block/smbus/spd_access.c new file mode 100644 index 0000000000..f37e3132f6 --- /dev/null +++ b/src/soc/intel/common/block/smbus/spd_access.c @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include + +int spd_read_byte(u8 slave_addr, u8 bus_addr) +{ + return smbus_read_byte(slave_addr, bus_addr); +} + +int spd_read_word(u8 slave_addr, u8 bus_addr) +{ + return smbus_read_word(slave_addr, bus_addr); +} + +void spd_write_byte(u8 slave_addr, u8 bus_addr, u8 value) +{ + smbus_write_byte(slave_addr, bus_addr, value); +} -- cgit v1.2.3