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 <yuchi.chen@intel.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/84201
Reviewed-by: Shuo Liu <shuo.liu@intel.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Yuchi Chen 2024-09-03 22:58:00 +08:00 committed by Lean Sheng Tan
commit 7a7b4f05fc
4 changed files with 40 additions and 15 deletions

View file

@ -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.

View file

@ -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

View file

@ -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");

View file

@ -0,0 +1,19 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <device/smbus_host.h>
#include <spd_bin.h>
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);
}