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>
This commit is contained in:
parent
8ea2b0ab46
commit
3153432b83
3 changed files with 54 additions and 0 deletions
|
|
@ -441,6 +441,14 @@ config MRC_CHANNEL_WIDTH
|
|||
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
|
||||
|
|
|
|||
|
|
@ -116,4 +116,16 @@ struct mb_cfg {
|
|||
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_ */
|
||||
|
|
|
|||
|
|
@ -233,6 +233,39 @@ static void ddr5_fill_dimm_module_info(FSP_M_CONFIG *mem_cfg, const struct mb_cf
|
|||
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 @@ void memcfg_init(FSPM_UPD *memupd, const struct mb_cfg *mb_cfg,
|
|||
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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue