Subrata Banik has submitted this change. ( https://review.coreboot.org/c/coreboot/+/85529?usp=email )
Change subject: soc/intel/alderlake: Add function to force disable memory channels ......................................................................
soc/intel/alderlake: Add function to force disable memory channels
Add a function `mem_init_override_channel_mask` to disable memory channels based on given bitmap where each bit represents a memory channel. A set bit will disable corresponding memory channel. Variants can override this bitmap by selecting `ENFORCE_MEM_CHANNEL_DISABLE` and implementing `mb_get_channel_disable_mask` to return the bitmap.
BUG=b:379311559 TEST=Make sure that channel mask is applied correctly.
Lotso without any channel mask: ``` lotso-rev0 ~ # dmidecode -t 17 | grep -E "(Locator: C|Size)" Size: 2 GB Locator: Channel-0-DIMM-0 Size: 2 GB Locator: Channel-1-DIMM-0 Size: 2 GB Locator: Channel-2-DIMM-0 Size: 2 GB Locator: Channel-3-DIMM-0 Size: 2 GB Locator: Channel-0-DIMM-0 Size: 2 GB Locator: Channel-1-DIMM-0 Size: 2 GB Locator: Channel-2-DIMM-0 Size: 2 GB Locator: Channel-3-DIMM-0
lotso-rev0 ~ # dmidecode -t 17 | grep Size | wc -l 8 ```
Lotso with channel 2 & 3 masked: ``` lotso-rev0 ~ # dmidecode -t 17 | grep -E "(Locator: C|Size)" Size: 2 GB Locator: Channel-0-DIMM-0 Size: 2 GB Locator: Channel-1-DIMM-0 Size: 2 GB Locator: Channel-0-DIMM-0 Size: 2 GB Locator: Channel-1-DIMM-0
lotso-rev0 ~ # dmidecode -t 17 | grep Size | wc -l 4 ```
Change-Id: Ibfeca4509cb3d88bc1bac2ac2d480e665d895bc5 Signed-off-by: Kapil Porwal kapilporwal@google.com Reviewed-on: https://review.coreboot.org/c/coreboot/+/85529 Reviewed-by: Subrata Banik subratabanik@google.com Tested-by: build bot (Jenkins) no-reply@coreboot.org Reviewed-by: Dinesh Gehlot digehlot@google.com Reviewed-by: Jayvik Desai jayvik@google.com --- M src/soc/intel/alderlake/Kconfig M src/soc/intel/alderlake/include/soc/meminit.h M src/soc/intel/alderlake/meminit.c 3 files changed, 54 insertions(+), 0 deletions(-)
Approvals: build bot (Jenkins): Verified Dinesh Gehlot: Looks good to me, approved Subrata Banik: Looks good to me, approved Jayvik Desai: Looks good to me, approved
diff --git a/src/soc/intel/alderlake/Kconfig b/src/soc/intel/alderlake/Kconfig index f6e9182..15f347f 100644 --- a/src/soc/intel/alderlake/Kconfig +++ b/src/soc/intel/alderlake/Kconfig @@ -441,6 +441,14 @@ int default 16
+config ENFORCE_MEM_CHANNEL_DISABLE + bool + default n + help + Select this option to disable certain memory channels on demand. If + selected, A function named mb_get_channel_disable_mask() must be + implemented to return the bit map of memory channels to disable. + config ALDERLAKE_ENABLE_SOC_WORKAROUND bool default y diff --git a/src/soc/intel/alderlake/include/soc/meminit.h b/src/soc/intel/alderlake/include/soc/meminit.h index 1d9eaf9..97fb77c 100644 --- a/src/soc/intel/alderlake/include/soc/meminit.h +++ b/src/soc/intel/alderlake/include/soc/meminit.h @@ -116,4 +116,16 @@ void memcfg_init(FSPM_UPD *memupd, const struct mb_cfg *mb_cfg, const struct mem_spd *spd_info, bool half_populated);
+/* + * This function is expected to return a bitmap of memory channels to + * disable. A set bit will disable corresponding memory channel. + * Variants can override this bitmap by selecting + * `ENFORCE_MEM_CHANNEL_DISABLE` and implementing this function. + */ +#if CONFIG(ENFORCE_MEM_CHANNEL_DISABLE) +uint8_t mb_get_channel_disable_mask(void); +#else +static inline uint8_t mb_get_channel_disable_mask(void) { return 0; } +#endif + #endif /* _SOC_ALDERLAKE_MEMINIT_H_ */ diff --git a/src/soc/intel/alderlake/meminit.c b/src/soc/intel/alderlake/meminit.c index 35c3252..6b3143e 100644 --- a/src/soc/intel/alderlake/meminit.c +++ b/src/soc/intel/alderlake/meminit.c @@ -233,6 +233,39 @@ mem_init_dqs_upds(mem_cfg, NULL, mb_cfg, true); }
+/* + * A memory channel will be disabled if corresponding bit in + * ch_disable_mask is set. + */ +static void mem_init_override_channel_mask(FSP_M_CONFIG *mem_cfg) +{ + uint8_t *disable_channel_upds[MRC_CHANNELS] = { + &mem_cfg->DisableMc0Ch0, + &mem_cfg->DisableMc0Ch1, + &mem_cfg->DisableMc0Ch2, + &mem_cfg->DisableMc0Ch3, + &mem_cfg->DisableMc1Ch0, + &mem_cfg->DisableMc1Ch1, + &mem_cfg->DisableMc1Ch2, + &mem_cfg->DisableMc1Ch3, + }; + + uint8_t ch_disable_mask = mb_get_channel_disable_mask(); + if (ch_disable_mask == 0) + return; + + /* Mc0Ch0 cannot be disabled */ + if (ch_disable_mask & BIT(0)) { + printk(BIOS_ERR, "Cannot disable the first memory channel (Mc0Ch0).\n"); + return; + } + + for (size_t ch = 0; ch < MRC_CHANNELS; ch++) { + if (ch_disable_mask & BIT(ch)) + *disable_channel_upds[ch] = 1; + } +} + void memcfg_init(FSPM_UPD *memupd, const struct mb_cfg *mb_cfg, const struct mem_spd *spd_info, bool half_populated) { @@ -283,6 +316,7 @@ mem_populate_channel_data(memupd, &soc_mem_cfg[mb_cfg->type], spd_info, half_populated, &data); mem_init_spd_upds(mem_cfg, &data); + mem_init_override_channel_mask(mem_cfg); mem_init_dq_upds(mem_cfg, &data, mb_cfg, dq_dqs_auto_detect); mem_init_dqs_upds(mem_cfg, &data, mb_cfg, dq_dqs_auto_detect); }