diff options
author | Keith Hui <buurin@gmail.com> | 2023-07-15 12:08:51 -0400 |
---|---|---|
committer | Felix Held <felix-coreboot@felixheld.de> | 2023-11-13 20:30:33 +0000 |
commit | 1e9601c5ef80a5b2eea52e512c7933e2daebd337 (patch) | |
tree | d3a2b4689e2b7ad651c36c74d34b4e4427ff1ed2 /src/northbridge/intel/sandybridge/raminit_mrc.c | |
parent | 9e345c8400ce9233b31c28a2450cca6347cc186b (diff) | |
download | coreboot-1e9601c5ef80a5b2eea52e512c7933e2daebd337.tar.gz coreboot-1e9601c5ef80a5b2eea52e512c7933e2daebd337.tar.bz2 coreboot-1e9601c5ef80a5b2eea52e512c7933e2daebd337.zip |
nb/intel/sandybridge: Standardize MRC vs. native SPD mapping API
Changes both MRC and native raminit code path to get SPD mapping
from one place.
Boards with all memory socketed specify their mappings in a
devicetree setting introduced in commit 5709e03613b3
("nb/intel/sandybridge: Migrate MRC settings to devicetree") back in
May 2019 but remains unused as of this patch. This setting
will now hold raw SMBus addresses, and MRC raminit gets code to
translate them into a representation MRC expects.
Boards with soldered down memory (specifically with HAVE_SPD_IN_CBFS
in their board Kconfig), with or without socketed memory, specify
their layouts in mb_get_spd_map() as used by Haswell boards, where
they access hardware GPIO straps to select which SPD data to use.
This harmonizes the way boards specify their SPD layouts across
Haswell/SNB/IVB boards whether using MRC or native raminit. Going
forward they only need to specify the layout in one place. (Going
forward the devicetree setting should be backported to Haswell,
once we get native raminit working there.)
With this, northbridge code is now fully responsible for loading
all SPD data, be it from CBFS or SMBus.
To avoid breakage, transition will happen in stages:
1. This patch gets all the code in, and implements weak stubs that
maintain existing code and data flow (i.e. mainboards still populate
final SPD layout data). At this point devicetree already uses new
representation, but is still unused meaning no breakage.
2. Follow-up patch(es) remove mainboard_get_spd() from mainboards, and
replace it with mb_get_spd_map() or devicetree values (as appropriate)
with converted SPD info. The "weak" mainboard_get_spd() with new logic
takes over. Boards go Haswell Style at this point. Boards with MRC
raminit also lose code to fill in SPD data, allowing new data to take
hold.
3. Clean-up patch removes the weak functions and public prototypes re
mainboard_get_spd(), making it internal to northbridge. Changeover is
complete.
Change-Id: I1a75279d981e46505930a9ce1aae894ccc4e1f24
Signed-off-by: Keith Hui <buurin@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/76965
Reviewed-by: Martin L Roth <gaumless@gmail.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Diffstat (limited to 'src/northbridge/intel/sandybridge/raminit_mrc.c')
-rw-r--r-- | src/northbridge/intel/sandybridge/raminit_mrc.c | 63 |
1 files changed, 55 insertions, 8 deletions
diff --git a/src/northbridge/intel/sandybridge/raminit_mrc.c b/src/northbridge/intel/sandybridge/raminit_mrc.c index 69baf4427066..de41ae590f69 100644 --- a/src/northbridge/intel/sandybridge/raminit_mrc.c +++ b/src/northbridge/intel/sandybridge/raminit_mrc.c @@ -264,13 +264,7 @@ static void southbridge_fill_pei_data(struct pei_data *pei_data) static void devicetree_fill_pei_data(struct pei_data *pei_data) { - const struct northbridge_intel_sandybridge_config *cfg; - - const struct device *dev = pcidev_on_root(0, 0); - if (!dev || !dev->chip_info) - return; - - cfg = dev->chip_info; + const struct northbridge_intel_sandybridge_config *cfg = config_of_soc(); switch (cfg->max_mem_clock_mhz) { /* MRC only supports fixed numbers of frequencies */ @@ -292,7 +286,15 @@ static void devicetree_fill_pei_data(struct pei_data *pei_data) } - memcpy(pei_data->spd_addresses, cfg->spd_addresses, sizeof(pei_data->spd_addresses)); + /* + * SPD addresses are listed in devicetree as actual addresses, + * and for MRC need to be shifted left so bit 0 is always zero. + */ + if (!CONFIG(HAVE_SPD_IN_CBFS)) { + for (unsigned int i = 0; i < ARRAY_SIZE(cfg->spd_addresses); i++) { + pei_data->spd_addresses[i] = cfg->spd_addresses[i] << 1; + } + } memcpy(pei_data->ts_addresses, cfg->ts_addresses, sizeof(pei_data->ts_addresses)); pei_data->ec_present = cfg->ec_present; @@ -310,6 +312,49 @@ static void devicetree_fill_pei_data(struct pei_data *pei_data) pei_data->usb3.xhci_streams = cfg->usb3.xhci_streams; } +/* Temporary stub */ +__weak void mb_get_spd_map(struct spd_info *spdi) {} + +static void spd_fill_pei_data(struct pei_data *pei_data) +{ + struct spd_info spdi = {0}; + unsigned int i, have_memory_down; + + mb_get_spd_map(&spdi); + + for (i = 0; i < ARRAY_SIZE(spdi.addresses); i++) { + if (spdi.addresses[i] == SPD_MEMORY_DOWN) { + pei_data->spd_addresses[i] = 0; + have_memory_down = 1; + } else { + /* MRC expects left-aligned SMBus addresses. */ + pei_data->spd_addresses[i] = spdi.addresses[i] << 1; + } + } + /* Copy SPD data from CBFS for on-board memory */ + if (have_memory_down) { + printk(BIOS_DEBUG, "SPD index %d\n", spdi.spd_index); + + size_t spd_file_len; + uint8_t *spd_file = cbfs_map("spd.bin", &spd_file_len); + + if (!spd_file) + die("SPD data %s!", "not found"); + + if (spd_file_len < ((spdi.spd_index + 1) * SPD_SIZE_MAX_DDR3)) + die("SPD data %s!", "incomplete"); + + /* MRC only uses index 0... */ + memcpy(pei_data->spd_data[0], spd_file + (spdi.spd_index * SPD_SIZE_MAX_DDR3), SPD_SIZE_MAX_DDR3); + + /* but coreboot uses the other indices */ + for (i = 1; i < ARRAY_SIZE(spdi.addresses); i++) { + if (spdi.addresses[i] == SPD_MEMORY_DOWN) + memcpy(pei_data->spd_data[i], pei_data->spd_data[0], SPD_SIZE_MAX_DDR3); + } + } +} + static void disable_p2p(void) { /* Disable PCI-to-PCI bridge early to prevent probing by MRC */ @@ -337,6 +382,8 @@ void perform_raminit(int s3resume) northbridge_fill_pei_data(&pei_data); southbridge_fill_pei_data(&pei_data); devicetree_fill_pei_data(&pei_data); + if (CONFIG(HAVE_SPD_IN_CBFS)) + spd_fill_pei_data(&pei_data); mainboard_fill_pei_data(&pei_data); post_code(0x3a); |