mb/lenovo/sklkbl: Use spd_tools infrastructure for SPD binaries

For the t470s variant, this patch replaces the vendor SPD binaries for
soldered-on RAM with ones generated from spd_tools. This is in
preparation for adding variants with more complex onboard RAM
configurations.

This patch has been successfully validated on hardware (Thinkpad T470s
20JT-S16E00 with 4GB soldered-on RAM and unpopulated DIMM slot).

Change-Id: I9cde4f05472105c238b3a8ee94cdedb89db08198
Depends-On: Ied92619130feaa160d01f75bc38230ab6a024ace
Signed-off-by: Johann C. Rode <jcrode@gmx.net>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/90027
Reviewed-by: Matt DeVillier <matt.devillier@gmail.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Johann C. Rode 2025-11-13 16:47:10 -08:00 committed by Matt DeVillier
commit 760e19e18f
33 changed files with 111 additions and 20 deletions

View file

@ -28,6 +28,7 @@ config BOARD_LENOVO_SKLKBL_THINKPAD_COMMON
config BOARD_LENOVO_T470S
bool
select BOARD_LENOVO_SKLKBL_THINKPAD_COMMON
select HAVE_SPD_IN_CBFS
config BOARD_LENOVO_T480
bool
@ -46,7 +47,6 @@ config BOARD_LENOVO_T580
select MEC1653_HAS_DEBUG_UNLOCK
select VARIANT_HAS_DGPU
if BOARD_LENOVO_SKLKBL_THINKPAD_COMMON
config MAINBOARD_DIR

View file

@ -13,6 +13,11 @@ ramstage-$(CONFIG_MAINBOARD_USE_LIBGFXINIT) += variants/$(VARIANT_DIR)/gma-mainb
subdirs-y += variants/$(VARIANT_DIR)
ifeq ($(CONFIG_BOARD_LENOVO_T470S),y)
subdirs-y += variants/$(VARIANT_DIR)/memory
subdirs-y += spd
endif
ifeq ($(CONFIG_VARIANT_HAS_DGPU),y)
CPPFLAGS_common += -I$(src)/mainboard/$(MAINBOARDDIR)/variants/$(VARIANT_DIR)/include
endif

View file

@ -0,0 +1,8 @@
## SPDX-License-Identifier: GPL-2.0-or-later
##
romstage-y += spd.c
ifneq ($(SPD_SOURCES),)
LIB_SPD_DEPS := $(SPD_SOURCES)
endif

View file

@ -0,0 +1,39 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <cbfs.h>
#include <console/console.h>
#include <device/dram/ddr4.h>
#include <spd.h>
#include "spd.h"
/* Get SPD data for on-board memory */
uint8_t *mainboard_find_spd_data(uint8_t spd_index)
{
uint8_t *spd_data;
size_t spd_file_len;
char *spd_file;
spd_file = cbfs_map("spd.bin", &spd_file_len);
if (!spd_file)
die("SPD data not found.");
if (spd_file_len < ((spd_index + 1) * SPD_SIZE_MAX_DDR4)) {
printk(BIOS_ERR,
"SPD index override to 0 due to incorrect SPD index.\n");
spd_index = 0;
}
if (spd_file_len < SPD_SIZE_MAX_DDR4)
die("Missing SPD data (spd.bin size %zu smaller than SPD size %u).", spd_file_len, SPD_SIZE_MAX_DDR4);
/* Assume same memory in both channels */
spd_index *= SPD_SIZE_MAX_DDR4;
spd_data = (uint8_t *)(spd_file + spd_index);
/* Make sure a valid SPD was found */
if (spd_data[0] == 0)
die("Invalid SPD data.");
return spd_data;
}

View file

@ -0,0 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef MAINBOARD_SPD_H
#define MAINBOARD_SPD_H
#include <stdint.h>
uint8_t *mainboard_find_spd_data(uint8_t spd_index);
#endif

View file

@ -5,7 +5,7 @@
void variant_config_gpios(void);
int variant_memory_sku(void);
uint8_t variant_memory_sku(void);
void ssdt_add_dgpu(const struct device *dev);

View file

@ -1,10 +0,0 @@
## SPDX-License-Identifier: GPL-2.0-only
# Add files spd_0.bin to spd_20.bin to the cbfs image
SPD_BINS := $(shell seq 0 20)
define SPD_template
cbfs-files-y += spd_$(1).bin
spd_$(1).bin-file := spd/spd_$(1).bin
spd_$(1).bin-type := raw
endef
$(foreach n,$(SPD_BINS),$(eval $(call SPD_template,$(n))))

View file

@ -0,0 +1,19 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# This is an auto-generated file. Do not edit!!
# Generated by:
# util/spd_tools/bin/part_id_gen TGL ddr4 src/mainboard/lenovo/sklkbl_thinkpad/variants/t470s/memory src/mainboard/lenovo/sklkbl_thinkpad/variants/t470s/memory/mem_parts_used.txt
SPD_SOURCES =
SPD_SOURCES += spd/ddr4/set-0/spd-10.hex # ID = 0(0b0000) Parts = MT40A512M16HA-083E:A
SPD_SOURCES += spd/ddr4/set-0/spd-11.hex # ID = 1(0b0001) Parts = MT40A1G16HBA-083E:A
SPD_SOURCES += spd/ddr4/set-0/spd-10.hex # ID = 2(0b0010) Parts = K4A8G165WB-BCPB
SPD_SOURCES += spd/ddr4/set-0/spd-empty.hex # ID = 3(0b0011)
SPD_SOURCES += spd/ddr4/set-0/spd-empty.hex # ID = 4(0b0100)
SPD_SOURCES += spd/ddr4/set-0/spd-empty.hex # ID = 5(0b0101)
SPD_SOURCES += spd/ddr4/set-0/spd-empty.hex # ID = 6(0b0110)
SPD_SOURCES += spd/ddr4/set-0/spd-empty.hex # ID = 7(0b0111)
SPD_SOURCES += spd/ddr4/set-0/spd-12.hex # ID = 8(0b1000) Parts = MT40A512M16JY-083E:B
SPD_SOURCES += spd/ddr4/set-0/spd-13.hex # ID = 9(0b1001) Parts = MT40A1G16WBU-083E:B
SPD_SOURCES += spd/ddr4/set-0/spd-12.hex # ID = 10(0b1010) Parts = K4A8G165WB-BCRC
SPD_SOURCES += spd/ddr4/set-0/spd-13.hex # ID = 11(0b1011) Parts = K4AAG165WB-MCRC
SPD_SOURCES += spd/ddr4/set-0/spd-12.hex # ID = 12(0b1100) Parts = H5AN8G6NAFR-UHC

View file

@ -0,0 +1,14 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# This is an auto-generated file. Do not edit!!
# Generated by:
# util/spd_tools/bin/part_id_gen TGL ddr4 src/mainboard/lenovo/sklkbl_thinkpad/variants/t470s/memory src/mainboard/lenovo/sklkbl_thinkpad/variants/t470s/memory/mem_parts_used.txt
DRAM Part Name ID to assign
MT40A512M16HA-083E:A 0 (0000)
MT40A1G16HBA-083E:A 1 (0001)
K4A8G165WB-BCPB 2 (0010)
MT40A512M16JY-083E:B 8 (1000)
MT40A1G16WBU-083E:B 9 (1001)
K4A8G165WB-BCRC 10 (1010)
K4AAG165WB-MCRC 11 (1011)
H5AN8G6NAFR-UHC 12 (1100)

View file

@ -0,0 +1,8 @@
MT40A512M16HA-083E:A,0
MT40A1G16HBA-083E:A,1
K4A8G165WB-BCPB,2
MT40A512M16JY-083E:B,8
MT40A1G16WBU-083E:B,9
K4A8G165WB-BCRC,10
K4AAG165WB-MCRC,11
H5AN8G6NAFR-UHC,12

View file

@ -6,6 +6,7 @@
#include <soc/romstage.h>
#include <spd_bin.h>
#include <stdio.h>
#include "../../spd/spd.h"
#include "../../variant.h"
static const struct pad_config memory_id_gpio_table[] = {
@ -16,7 +17,7 @@ static const struct pad_config memory_id_gpio_table[] = {
PAD_CFG_GPI_TRIG_OWN(GPP_F20, UP_20K, DEEP, OFF, ACPI), /* MEMORYID4 */
};
int variant_memory_sku(void)
uint8_t variant_memory_sku(void)
{
gpio_t spd_gpios[] = {
GPP_F16,
@ -31,9 +32,7 @@ int variant_memory_sku(void)
void mainboard_memory_init_params(FSPM_UPD *mupd)
{
int spd_idx;
char spd_name[20];
size_t spd_size;
uint8_t spd_idx;
FSP_M_CONFIG *mem_cfg = &mupd->FspmConfig;
mem_cfg->DqPinsInterleaved = true; /* DDR_DQ in interleave mode */
@ -45,8 +44,7 @@ void mainboard_memory_init_params(FSPM_UPD *mupd)
spd_idx = variant_memory_sku();
printk(BIOS_DEBUG, "Detected MEMORY_ID = %d\n", spd_idx);
snprintf(spd_name, sizeof(spd_name), "spd_%d.bin", spd_idx);
mem_cfg->MemorySpdPtr00 = (uintptr_t)cbfs_map(spd_name, &spd_size);
mem_cfg->MemorySpdPtr00 = (uintptr_t)mainboard_find_spd_data(spd_idx);
/* Get SPD for memory slot (CH B) */
struct spd_block blk = { .addr_map = { [1] = 0x51, } };

View file

@ -16,7 +16,7 @@ static const struct pad_config memory_id_gpio_table[] = {
PAD_CFG_GPI_TRIG_OWN(GPP_F20, UP_20K, DEEP, OFF, ACPI), /* MEMORYID4 */
};
int variant_memory_sku(void)
uint8_t variant_memory_sku(void)
{
gpio_t spd_gpios[] = {
GPP_F16,
@ -31,7 +31,7 @@ int variant_memory_sku(void)
void mainboard_memory_init_params(FSPM_UPD *mupd)
{
int spd_idx;
uint8_t spd_idx;
char spd_name[20];
size_t spd_size;