summaryrefslogtreecommitdiffstats
path: root/src/northbridge/intel/sandybridge/raminit_mrc.c
diff options
context:
space:
mode:
authorKeith Hui <buurin@gmail.com>2023-07-15 12:08:51 -0400
committerFelix Held <felix-coreboot@felixheld.de>2023-11-13 20:30:33 +0000
commit1e9601c5ef80a5b2eea52e512c7933e2daebd337 (patch)
treed3a2b4689e2b7ad651c36c74d34b4e4427ff1ed2 /src/northbridge/intel/sandybridge/raminit_mrc.c
parent9e345c8400ce9233b31c28a2450cca6347cc186b (diff)
downloadcoreboot-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.c63
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);