Compare commits

...

3 Commits

Author SHA1 Message Date
a8bf2b32ae soc/intel/common/blk/memory: Make mixed topo work
When using a mixed memory topology with DDR4, it's not possible to boot
when no DIMMs are installed, even though memory-down is available. This
happens because the DIMM SPD length defaults to 256 when no DIMM SPD is
available. Relax the length check when no DIMMs are present to overcome
this problem.

Tested on system76/lemp10. Unit boots with and without DIMM installed.

Change-Id: I1cabf64fade1c06a44b6c3892659d54febc7a79a
Signed-off-by: Angel Pons <th3fanbus@gmail.com>
Tested-by: Tim Crawford <tcrawford@system76.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/60800
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
Reviewed-by: Tim Crawford <tcrawford@system76.com>
2022-01-07 18:38:36 -07:00
43019aa7da soc/intel/common/memory: Don't die if SPD lengths differ
Revert from die() to printk() if SPD lengths are different for mixed
memory topology. Fixes booting system76/lemp10 when a DIMM is not
present.

Change-Id: Iec8dd693353abbe5047eb3d108e449209bae9436
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-01-05 10:02:48 -07:00
2018180c47 mb/system76/lemp10: Fix memory info
The Lemur Pro, with its mixed memory topology, only has a DIMM at
address 0x52.

Change-Id: Iecea8c70c7fd40943d86f8918f8e3b384538b5c3
Fixes: 4dcee4f21d ("mb/system76/lemp10: Add System76 Lemur Pro 10")
Signed-off-by: Tim Crawford <tcrawford@system76.com>
2022-01-05 09:38:21 -07:00
2 changed files with 10 additions and 6 deletions

View File

@ -13,7 +13,6 @@ void mainboard_memory_init_params(FSPM_UPD *mupd)
.topo = MEM_TOPO_MIXED, .topo = MEM_TOPO_MIXED,
.cbfs_index = 0, .cbfs_index = 0,
.smbus = { .smbus = {
[0] = { .addr_dimm[0] = 0x50, },
[1] = { .addr_dimm[0] = 0x52, }, [1] = { .addr_dimm[0] = 0x52, },
}, },
}; };

View File

@ -6,6 +6,7 @@
#include <commonlib/region.h> #include <commonlib/region.h>
#include <spd_bin.h> #include <spd_bin.h>
#include <string.h> #include <string.h>
#include <types.h>
_Static_assert(CONFIG_MRC_CHANNEL_WIDTH > 0, "MRC channel width must be >0!"); _Static_assert(CONFIG_MRC_CHANNEL_WIDTH > 0, "MRC channel width must be >0!");
_Static_assert(CONFIG_DATA_BUS_WIDTH > 0, "Data bus width must be >0!"); _Static_assert(CONFIG_DATA_BUS_WIDTH > 0, "Data bus width must be >0!");
@ -93,7 +94,7 @@ static void read_spd_md(const struct soc_mem_cfg *soc_mem_cfg, const struct mem_
#define CH_DIMM_OFFSET(ch, dimm) ((ch) * CONFIG_DIMMS_PER_CHANNEL + (dimm)) #define CH_DIMM_OFFSET(ch, dimm) ((ch) * CONFIG_DIMMS_PER_CHANNEL + (dimm))
static void read_spd_dimm(const struct soc_mem_cfg *soc_mem_cfg, const struct mem_spd *info, static bool read_spd_dimm(const struct soc_mem_cfg *soc_mem_cfg, const struct mem_spd *info,
bool half_populated, struct mem_channel_data *channel_data, bool half_populated, struct mem_channel_data *channel_data,
size_t *spd_len) size_t *spd_len)
{ {
@ -109,7 +110,7 @@ static void read_spd_dimm(const struct soc_mem_cfg *soc_mem_cfg, const struct me
uint32_t pop_mask = 0; uint32_t pop_mask = 0;
if (!(info->topo & MEM_TOPO_DIMM_MODULE)) if (!(info->topo & MEM_TOPO_DIMM_MODULE))
return; return false;
for (ch = 0; ch < num_phys_ch; ch++) { for (ch = 0; ch < num_phys_ch; ch++) {
for (dimm = 0; dimm < CONFIG_DIMMS_PER_CHANNEL; dimm++) { for (dimm = 0; dimm < CONFIG_DIMMS_PER_CHANNEL; dimm++) {
@ -137,6 +138,8 @@ static void read_spd_dimm(const struct soc_mem_cfg *soc_mem_cfg, const struct me
} }
channel_data->ch_population_flags |= populated_mask_to_flag(pop_mask, num_phys_ch); channel_data->ch_population_flags |= populated_mask_to_flag(pop_mask, num_phys_ch);
return pop_mask != 0;
} }
void mem_populate_channel_data(const struct soc_mem_cfg *soc_mem_cfg, void mem_populate_channel_data(const struct soc_mem_cfg *soc_mem_cfg,
@ -145,11 +148,12 @@ void mem_populate_channel_data(const struct soc_mem_cfg *soc_mem_cfg,
struct mem_channel_data *data) struct mem_channel_data *data)
{ {
size_t spd_md_len = 0, spd_dimm_len = 0; size_t spd_md_len = 0, spd_dimm_len = 0;
bool have_dimms;
memset(data, 0, sizeof(*data)); memset(data, 0, sizeof(*data));
read_spd_md(soc_mem_cfg, spd_info, half_populated, data, &spd_md_len); read_spd_md(soc_mem_cfg, spd_info, half_populated, data, &spd_md_len);
read_spd_dimm(soc_mem_cfg, spd_info, half_populated, data, &spd_dimm_len); have_dimms = read_spd_dimm(soc_mem_cfg, spd_info, half_populated, data, &spd_dimm_len);
if (data->ch_population_flags == NO_CHANNEL_POPULATED) if (data->ch_population_flags == NO_CHANNEL_POPULATED)
die("No channels are populated. Incorrect memory configuration!\n"); die("No channels are populated. Incorrect memory configuration!\n");
@ -161,11 +165,12 @@ void mem_populate_channel_data(const struct soc_mem_cfg *soc_mem_cfg,
} else { } else {
/* /*
* SPD lengths must match for CBFS and EEPROM SPD for mixed * SPD lengths must match for CBFS and EEPROM SPD for mixed
* topology. * topology. Skip this check when no DIMMs are installed.
*/ */
if (spd_md_len != spd_dimm_len) if (have_dimms && spd_md_len != spd_dimm_len)
die("Length of SPD does not match for mixed topology!\n"); die("Length of SPD does not match for mixed topology!\n");
/* Use memory-down SPD length in case there are no DIMMs installed */
data->spd_len = spd_md_len; data->spd_len = spd_md_len;
} }
} }