From 0d4200fef396fb0d1fbf28b4ced475fbf59b5b85 Mon Sep 17 00:00:00 2001 From: Philip Chen Date: Mon, 29 Apr 2019 10:18:24 -0700 Subject: [PATCH] soc/intel/cannonlake: Support different SPD read type for each slot Also clean up cannonlake_memcfg_init. The major changes include: (1) Add enum 'mem_info_read_type' to spd_info. (2) Add per-dimm-slot spd_info to cnl_mb_cfg. (3) Setup memory config for each slot independently. (4) Squash meminit_memcfg_spd(). BUG=chromium:960581, b:124990009 BRANCH=none TEST=boot hatch, hatch_whl, and kohaku Change-Id: I686a85996858204c20fd05ef24787a0487817c34 Signed-off-by: Philip Chen Reviewed-on: https://review.coreboot.org/c/coreboot/+/32513 Reviewed-by: Paul Fagerburg Reviewed-by: Furquan Shaikh Tested-by: build bot (Jenkins) --- src/mainboard/google/hatch/romstage.c | 54 ++++++-- .../baseboard/include/baseboard/gpio.h | 7 -- .../baseboard/include/baseboard/variants.h | 3 - .../google/hatch/variants/baseboard/memory.c | 33 +---- .../google/hatch/variants/kohaku/memory.c | 29 +---- src/mainboard/google/sarien/romstage.c | 27 ++-- src/mainboard/intel/coffeelake_rvp/memory.c | 25 +++- src/mainboard/intel/coffeelake_rvp/romstage.c | 10 +- src/soc/intel/cannonlake/cnl_memcfg_init.c | 115 ++++++++++-------- .../cannonlake/include/soc/cnl_memcfg_init.h | 38 +++--- 10 files changed, 179 insertions(+), 162 deletions(-) diff --git a/src/mainboard/google/hatch/romstage.c b/src/mainboard/google/hatch/romstage.c index bdf951b016..2c630a8ce8 100644 --- a/src/mainboard/google/hatch/romstage.c +++ b/src/mainboard/google/hatch/romstage.c @@ -16,23 +16,63 @@ #include #include #include +#include #include #include #include #include +/* Memory configuration board straps */ +#define GPIO_MEM_CONFIG_0 GPP_F20 +#define GPIO_MEM_CONFIG_1 GPP_F21 +#define GPIO_MEM_CONFIG_2 GPP_F11 +#define GPIO_MEM_CONFIG_3 GPP_F22 + +/* + * GPIO_MEM_CH_SEL is set to 1 for single channel skus + * and 0 for dual channel skus. + */ +#define GPIO_MEM_CH_SEL GPP_F2 + +static int memory_sku(void) +{ + const gpio_t spd_gpios[] = { + GPIO_MEM_CONFIG_0, + GPIO_MEM_CONFIG_1, + GPIO_MEM_CONFIG_2, + GPIO_MEM_CONFIG_3, + }; + + return gpio_base2_value(spd_gpios, ARRAY_SIZE(spd_gpios)); +} + void mainboard_memory_init_params(FSPM_UPD *memupd) { struct cnl_mb_cfg memcfg; - - const struct spd_info spd = { - .spd_by_index = true, - .spd_spec.spd_index = variant_memory_sku(), - }; + int mem_sku; + int is_single_ch_mem; variant_memory_params(&memcfg); - cannonlake_memcfg_init(&memupd->FspmConfig, - &memcfg, &spd); + mem_sku = memory_sku(); + /* + * GPP_F2 is the MEM_CH_SEL gpio, which is set to 1 for single + * channel skus and 0 for dual channel skus. + */ + is_single_ch_mem = gpio_get(GPIO_MEM_CH_SEL); + + /* + * spd[0]-spd[3] map to CH0D0, CH0D1, CH1D0, CH1D1 respectively. + * Dual-DIMM memory is not used in hatch family, so we only + * fill in spd_info for CH0D0 and CH1D0 here. + */ + memcfg.spd[0].read_type = READ_SPD_CBFS; + memcfg.spd[0].spd_spec.spd_index = mem_sku; + if (!is_single_ch_mem) { + memcfg.spd[2].read_type = READ_SPD_CBFS; + memcfg.spd[2].spd_spec.spd_index = mem_sku; + } + + cannonlake_memcfg_init(&memupd->FspmConfig, &memcfg); } void mainboard_get_dram_part_num(const char **part_num, size_t *len) diff --git a/src/mainboard/google/hatch/variants/baseboard/include/baseboard/gpio.h b/src/mainboard/google/hatch/variants/baseboard/include/baseboard/gpio.h index 5d6311ba24..e83732cb62 100644 --- a/src/mainboard/google/hatch/variants/baseboard/include/baseboard/gpio.h +++ b/src/mainboard/google/hatch/variants/baseboard/include/baseboard/gpio.h @@ -22,13 +22,6 @@ #define GPIO_PCH_WP GPP_C20 -/* Memory configuration board straps */ -#define GPIO_MEM_CONFIG_0 GPP_F20 -#define GPIO_MEM_CONFIG_1 GPP_F21 -#define GPIO_MEM_CONFIG_2 GPP_F11 -#define GPIO_MEM_CONFIG_3 GPP_F22 - - /* EC wake pin is LAN_WAKE# */ #define GPE_EC_WAKE GPE0_LAN_WAK diff --git a/src/mainboard/google/hatch/variants/baseboard/include/baseboard/variants.h b/src/mainboard/google/hatch/variants/baseboard/include/baseboard/variants.h index d41ad536f2..17bd5df63d 100644 --- a/src/mainboard/google/hatch/variants/baseboard/include/baseboard/variants.h +++ b/src/mainboard/google/hatch/variants/baseboard/include/baseboard/variants.h @@ -31,9 +31,6 @@ const struct pad_config *base_early_gpio_table(size_t *num); const struct pad_config *override_gpio_table(size_t *num); const struct pad_config *override_early_gpio_table(size_t *num); -/* Return memory SKU for the board. */ -int variant_memory_sku(void); - /* Return board specific memory configuration */ void variant_memory_params(struct cnl_mb_cfg *bcfg); diff --git a/src/mainboard/google/hatch/variants/baseboard/memory.c b/src/mainboard/google/hatch/variants/baseboard/memory.c index 580bdc9ab3..bcfc49f20e 100644 --- a/src/mainboard/google/hatch/variants/baseboard/memory.c +++ b/src/mainboard/google/hatch/variants/baseboard/memory.c @@ -15,16 +15,15 @@ #include #include -#include #include #include static const struct cnl_mb_cfg baseboard_memcfg = { /* Baseboard uses 121, 81 and 100 rcomp resistors */ - .rcomp_resistor = { 121, 81, 100 }, + .rcomp_resistor = {121, 81, 100}, /* Baseboard Rcomp target values */ - .rcomp_targets = { 100, 40, 20, 20, 26 }, + .rcomp_targets = {100, 40, 20, 20, 26}, /* Set CaVref config to 2 */ .vref_ca_config = 2, @@ -36,32 +35,4 @@ static const struct cnl_mb_cfg baseboard_memcfg = { void __weak variant_memory_params(struct cnl_mb_cfg *bcfg) { memcpy(bcfg, &baseboard_memcfg, sizeof(baseboard_memcfg)); - /* - * GPP_F2 is the MEM_CH_SEL gpio, which is set to 1 for single - * channel skus and 0 for dual channel skus. - */ - if (gpio_get(GPP_F2) == 1) { - /* - * Single channel config: for Hatch, Channel 0 is - * always populated. - */ - bcfg->channel_empty[0] = 0; - bcfg->channel_empty[1] = 1; - } else { - /* Dual channel config: both channels populated. */ - bcfg->channel_empty[0] = 0; - bcfg->channel_empty[1] = 0; - } -} - -int __weak variant_memory_sku(void) -{ - const gpio_t spd_gpios[] = { - GPIO_MEM_CONFIG_0, - GPIO_MEM_CONFIG_1, - GPIO_MEM_CONFIG_2, - GPIO_MEM_CONFIG_3, - }; - - return gpio_base2_value(spd_gpios, ARRAY_SIZE(spd_gpios)); } diff --git a/src/mainboard/google/hatch/variants/kohaku/memory.c b/src/mainboard/google/hatch/variants/kohaku/memory.c index 27ae3d8fb2..490124776e 100644 --- a/src/mainboard/google/hatch/variants/kohaku/memory.c +++ b/src/mainboard/google/hatch/variants/kohaku/memory.c @@ -15,7 +15,6 @@ #include #include -#include #include #include @@ -30,8 +29,8 @@ static const struct cnl_mb_cfg baseboard_memcfg = { * the index = pin number on SoC * the value = pin number on lpddr3 part */ - .dqs_map[DDR_CH0] = { 0, 1, 3, 2, 5, 7, 6, 4 }, - .dqs_map[DDR_CH1] = { 1, 3, 2, 0, 5, 7, 6, 4 }, + .dqs_map[DDR_CH0] = {0, 1, 3, 2, 5, 7, 6, 4}, + .dqs_map[DDR_CH1] = {1, 3, 2, 0, 5, 7, 6, 4}, .dq_map[DDR_CH0] = { {0xf, 0xf0}, @@ -40,7 +39,7 @@ static const struct cnl_mb_cfg baseboard_memcfg = { {0xf, 0x0}, {0xff, 0x0}, {0xff, 0x0} - }, + }, .dq_map[DDR_CH1] = { {0xf, 0xf0}, {0x0, 0xf0}, @@ -48,13 +47,13 @@ static const struct cnl_mb_cfg baseboard_memcfg = { {0xf, 0x0}, {0xff, 0x0}, {0xff, 0x0} - }, + }, /* Kohaku uses 200, 80.6 and 162 rcomp resistors */ - .rcomp_resistor = { 200, 81, 162 }, + .rcomp_resistor = {200, 81, 162}, /* Kohaku Rcomp target values */ - .rcomp_targets = { 100, 40, 40, 23, 40 }, + .rcomp_targets = {100, 40, 40, 23, 40}, /* Set CaVref config to 0 for LPDDR3 */ .vref_ca_config = 0, @@ -66,20 +65,4 @@ static const struct cnl_mb_cfg baseboard_memcfg = { void variant_memory_params(struct cnl_mb_cfg *bcfg) { memcpy(bcfg, &baseboard_memcfg, sizeof(baseboard_memcfg)); - /* - * GPP_F2 is the MEM_CH_SEL gpio, which is set to 1 for single - * channel skus and 0 for dual channel skus. - */ - if (gpio_get(GPP_F2) == 1) { - /* - * Single channel config: for kohaku, Channel 0 is - * always populated. - */ - bcfg->channel_empty[0] = 0; - bcfg->channel_empty[1] = 1; - } else { - /* Dual channel config: both channels populated. */ - bcfg->channel_empty[0] = 0; - bcfg->channel_empty[1] = 0; - } } diff --git a/src/mainboard/google/sarien/romstage.c b/src/mainboard/google/sarien/romstage.c index e83cd4aed4..20eee7f34b 100644 --- a/src/mainboard/google/sarien/romstage.c +++ b/src/mainboard/google/sarien/romstage.c @@ -18,6 +18,18 @@ #include static const struct cnl_mb_cfg memcfg = { + /* Access memory info through SMBUS. */ + .spd[0] = { + .read_type = READ_SMBUS, + .spd_spec = {.spd_smbus_address = 0xa0}, + }, + .spd[1] = {.read_type = NOT_EXISTING}, + .spd[2] = { + .read_type = READ_SMBUS, + .spd_spec = {.spd_smbus_address = 0xa4}, + }, + .spd[3] = {.read_type = NOT_EXISTING}, + /* * The dqs_map arrays map the ddr4 pins to the SoC pins * for both channels. @@ -25,16 +37,16 @@ static const struct cnl_mb_cfg memcfg = { * the index = pin number on ddr4 part * the value = pin number on SoC */ - .dqs_map[DDR_CH0] = { 0, 1, 4, 5, 2, 3, 6, 7 }, - .dqs_map[DDR_CH1] = { 0, 1, 4, 5, 2, 3, 6, 7 }, + .dqs_map[DDR_CH0] = {0, 1, 4, 5, 2, 3, 6, 7}, + .dqs_map[DDR_CH1] = {0, 1, 4, 5, 2, 3, 6, 7}, /* Baseboard uses 121, 81 and 100 rcomp resistors */ - .rcomp_resistor = { 121, 81, 100 }, + .rcomp_resistor = {121, 81, 100}, /* * Baseboard Rcomp target values. */ - .rcomp_targets = { 100, 40, 20, 20, 26 }, + .rcomp_targets = {100, 40, 20, 20, 26}, /* Disable Early Command Training */ .ect = 0, @@ -45,12 +57,7 @@ static const struct cnl_mb_cfg memcfg = { void mainboard_memory_init_params(FSPM_UPD *memupd) { - const struct spd_info spd = { - .spd_smbus_address[0] = 0xa0, - .spd_smbus_address[2] = 0xa4 - }; - wilco_ec_romstage_init(); - cannonlake_memcfg_init(&memupd->FspmConfig, &memcfg, &spd); + cannonlake_memcfg_init(&memupd->FspmConfig, &memcfg); } diff --git a/src/mainboard/intel/coffeelake_rvp/memory.c b/src/mainboard/intel/coffeelake_rvp/memory.c index a13000cc13..b093a20d2c 100644 --- a/src/mainboard/intel/coffeelake_rvp/memory.c +++ b/src/mainboard/intel/coffeelake_rvp/memory.c @@ -20,6 +20,23 @@ #include static const struct cnl_mb_cfg baseboard_memcfg_cfg = { + /* Access memory info through SMBUS. */ + .spd[0] = { + .read_type = READ_SMBUS, + .spd_spec = {.spd_smbus_address = 0xA0} + }, + .spd[1] = { + .read_type = READ_SMBUS, + .spd_spec = {.spd_smbus_address = 0xA2} + }, + .spd[2] = { + .read_type = READ_SMBUS, + .spd_spec = {.spd_smbus_address = 0xA4} + }, + .spd[3] = { + .read_type = READ_SMBUS, + .spd_spec = {.spd_smbus_address = 0xA6} + }, /* * The dqs_map arrays map the ddr4 pins to the SoC pins * for both channels. @@ -27,16 +44,16 @@ static const struct cnl_mb_cfg baseboard_memcfg_cfg = { * the index = pin number on ddr4 part * the value = pin number on SoC */ - .dqs_map[DDR_CH0] = { 0, 1, 3, 2, 4, 5, 6, 7 }, - .dqs_map[DDR_CH1] = { 1, 0, 4, 5, 2, 3, 6, 7 }, + .dqs_map[DDR_CH0] = {0, 1, 3, 2, 4, 5, 6, 7}, + .dqs_map[DDR_CH1] = {1, 0, 4, 5, 2, 3, 6, 7}, /* Baseboard uses 121, 81 and 100 rcomp resistors */ - .rcomp_resistor = { 121, 81, 100 }, + .rcomp_resistor = {121, 81, 100}, /* * Baseboard Rcomp target values. */ - .rcomp_targets = { 100, 40, 20, 20, 26 }, + .rcomp_targets = {100, 40, 20, 20, 26}, /* Baseboard is an interleaved design */ .dq_pins_interleaved = 1, diff --git a/src/mainboard/intel/coffeelake_rvp/romstage.c b/src/mainboard/intel/coffeelake_rvp/romstage.c index 1ab2d78b5a..09ef148e36 100644 --- a/src/mainboard/intel/coffeelake_rvp/romstage.c +++ b/src/mainboard/intel/coffeelake_rvp/romstage.c @@ -20,13 +20,5 @@ void mainboard_memory_init_params(FSPM_UPD *memupd) { - const struct spd_info spd = { - .spd_smbus_address[0] = 0xA0, - .spd_smbus_address[1] = 0xA2, - .spd_smbus_address[2] = 0xA4, - .spd_smbus_address[3] = 0xA6, - }; - - cannonlake_memcfg_init(&memupd->FspmConfig, - variant_memcfg_config(), &spd); + cannonlake_memcfg_init(&memupd->FspmConfig, variant_memcfg_config()); } diff --git a/src/soc/intel/cannonlake/cnl_memcfg_init.c b/src/soc/intel/cannonlake/cnl_memcfg_init.c index db001b82ae..4ebd9978ae 100644 --- a/src/soc/intel/cannonlake/cnl_memcfg_init.c +++ b/src/soc/intel/cannonlake/cnl_memcfg_init.c @@ -20,7 +20,7 @@ #include static void meminit_memcfg(FSP_M_CONFIG *mem_cfg, - const struct cnl_mb_cfg *board_cfg) + const struct cnl_mb_cfg *board_cfg) { /* * DqByteMapChx expects 12 bytes of data, but the last 6 bytes @@ -29,47 +29,58 @@ static void meminit_memcfg(FSP_M_CONFIG *mem_cfg, */ memset(&mem_cfg->DqByteMapCh0, 0, sizeof(mem_cfg->DqByteMapCh0)); memcpy(&mem_cfg->DqByteMapCh0, &board_cfg->dq_map[DDR_CH0], - sizeof(board_cfg->dq_map[DDR_CH0])); + sizeof(board_cfg->dq_map[DDR_CH0])); memset(&mem_cfg->DqByteMapCh1, 0, sizeof(mem_cfg->DqByteMapCh1)); memcpy(&mem_cfg->DqByteMapCh1, &board_cfg->dq_map[DDR_CH1], - sizeof(board_cfg->dq_map[DDR_CH1])); + sizeof(board_cfg->dq_map[DDR_CH1])); memcpy(&mem_cfg->DqsMapCpu2DramCh0, &board_cfg->dqs_map[DDR_CH0], - sizeof(board_cfg->dqs_map[DDR_CH0])); + sizeof(board_cfg->dqs_map[DDR_CH0])); memcpy(&mem_cfg->DqsMapCpu2DramCh1, &board_cfg->dqs_map[DDR_CH1], - sizeof(board_cfg->dqs_map[DDR_CH1])); + sizeof(board_cfg->dqs_map[DDR_CH1])); memcpy(&mem_cfg->RcompResistor, &board_cfg->rcomp_resistor, - sizeof(mem_cfg->RcompResistor)); + sizeof(mem_cfg->RcompResistor)); /* Early cannonlake requires rcomp targets to be 0 */ memcpy(&mem_cfg->RcompTarget, &board_cfg->rcomp_targets, - sizeof(mem_cfg->RcompTarget)); -} - -static void meminit_memcfg_spd(FSP_M_CONFIG *mem_cfg, - const struct cnl_mb_cfg *cnl_cfg, - size_t spd_data_len, uintptr_t spd_data_ptr) -{ - mem_cfg->MemorySpdDataLen = spd_data_len; - - if (cnl_cfg->channel_empty[0] == 0) - mem_cfg->MemorySpdPtr00 = spd_data_ptr; - - if (cnl_cfg->channel_empty[1] == 0) - mem_cfg->MemorySpdPtr10 = spd_data_ptr; + sizeof(mem_cfg->RcompTarget)); } /* * Initialize default memory settings using spd data contained in a buffer. */ -static void meminit_spd_data(FSP_M_CONFIG *mem_cfg, - const struct cnl_mb_cfg *cnl_cfg, - size_t spd_data_len, uintptr_t spd_data_ptr) +static void meminit_spd_data(FSP_M_CONFIG *mem_cfg, uint8_t mem_slot, + size_t spd_data_len, uintptr_t spd_data_ptr) { - assert(spd_data_ptr && spd_data_len); - meminit_memcfg_spd(mem_cfg, cnl_cfg, spd_data_len, spd_data_ptr); + static size_t last_set_spd_data_len = 0; + + assert(spd_data_ptr != 0 && spd_data_len != 0); + + if (last_set_spd_data_len != 0 && + last_set_spd_data_len != spd_data_len) + die("spd data length disparity among slots"); + + mem_cfg->MemorySpdDataLen = spd_data_len; + last_set_spd_data_len = spd_data_len; + + switch (mem_slot) { + case 0: + mem_cfg->MemorySpdPtr00 = spd_data_ptr; + break; + case 1: + mem_cfg->MemorySpdPtr01 = spd_data_ptr; + break; + case 2: + mem_cfg->MemorySpdPtr10 = spd_data_ptr; + break; + case 3: + mem_cfg->MemorySpdPtr11 = spd_data_ptr; + break; + default: + die("nonexistent memory slot"); + } } /* @@ -78,13 +89,13 @@ static void meminit_spd_data(FSP_M_CONFIG *mem_cfg, * in spd/Makefile.inc. */ static void meminit_cbfs_spd_index(FSP_M_CONFIG *mem_cfg, - const struct cnl_mb_cfg *cnl_cfg, - int spd_index) + int spd_index, uint8_t mem_slot) { size_t spd_data_len; uintptr_t spd_data_ptr; struct region_device spd_rdev; + assert(mem_slot < NUM_DIMM_SLOT); printk(BIOS_DEBUG, "SPD INDEX = %d\n", spd_index); if (get_spd_cbfs_rdev(&spd_rdev, spd_index) < 0) die("spd.bin not found or incorrect index\n"); @@ -92,40 +103,42 @@ static void meminit_cbfs_spd_index(FSP_M_CONFIG *mem_cfg, /* Memory leak is ok since we have memory mapped boot media */ assert(CONFIG(BOOT_DEVICE_MEMORY_MAPPED)); spd_data_ptr = (uintptr_t)rdev_mmap_full(&spd_rdev); - meminit_spd_data(mem_cfg, cnl_cfg, spd_data_len, spd_data_ptr); + meminit_spd_data(mem_cfg, mem_slot, spd_data_len, spd_data_ptr); } /* Initialize onboard memory configurations for CannonLake */ void cannonlake_memcfg_init(FSP_M_CONFIG *mem_cfg, - const struct cnl_mb_cfg *cnl_cfg, - const struct spd_info *spd) + const struct cnl_mb_cfg *cnl_cfg) { - bool OnModuleSpd = false; + const struct spd_info *spdi; + /* Early Command Training Enabled */ mem_cfg->ECT = cnl_cfg->ect; mem_cfg->DqPinsInterleaved = cnl_cfg->dq_pins_interleaved; mem_cfg->CaVrefConfig = cnl_cfg->vref_ca_config; - /* Spd pointer will only be used if all smbus slave address of memory - * sockets on the platform is empty */ - for (int i = 0; i < ARRAY_SIZE(mem_cfg->SpdAddressTable); i++) { - if (spd->spd_smbus_address[i] != 0) { - mem_cfg->SpdAddressTable[i] = spd->spd_smbus_address[i]; - OnModuleSpd = true; + for (int i = 0; i < NUM_DIMM_SLOT; i++) { + spdi = &(cnl_cfg->spd[i]); + switch (spdi->read_type) { + case NOT_EXISTING: + break; + case READ_SMBUS: + mem_cfg->SpdAddressTable[i] = + spdi->spd_spec.spd_smbus_address; + break; + case READ_SPD_CBFS: + meminit_cbfs_spd_index(mem_cfg, + spdi->spd_spec.spd_index, i); + break; + case READ_SPD_MEMPTR: + meminit_spd_data(mem_cfg, i, + spdi->spd_spec.spd_data_ptr_info.spd_data_len, + spdi->spd_spec.spd_data_ptr_info.spd_data_ptr); + break; + default: + die("no valid way to read mem info"); } + + meminit_memcfg(mem_cfg, cnl_cfg); } - - if (!OnModuleSpd) { - if (spd->spd_by_index) { - meminit_cbfs_spd_index(mem_cfg, cnl_cfg, - spd->spd_spec.spd_index); - } else { - meminit_spd_data(mem_cfg, cnl_cfg, - spd->spd_spec.spd_data_ptr_info.spd_data_len, - spd->spd_spec.spd_data_ptr_info.spd_data_ptr); - } - } - - meminit_memcfg(mem_cfg, cnl_cfg); - } diff --git a/src/soc/intel/cannonlake/include/soc/cnl_memcfg_init.h b/src/soc/intel/cannonlake/include/soc/cnl_memcfg_init.h index e602a33f78..d5f6c39f24 100644 --- a/src/soc/intel/cannonlake/include/soc/cnl_memcfg_init.h +++ b/src/soc/intel/cannonlake/include/soc/cnl_memcfg_init.h @@ -23,6 +23,9 @@ /* Number of dq bits controlled per dqs */ #define DQ_BITS_PER_DQS 8 +/* Number of memory DIMM slots available on Cannonlake board */ +#define NUM_DIMM_SLOT 4 + /* * Number of memory packages, where a "package" represents a 64-bit solution. */ @@ -40,17 +43,32 @@ struct spd_by_pointer { uintptr_t spd_data_ptr; }; +enum mem_info_read_type { + NOT_EXISTING, /* No memory in this slot */ + READ_SMBUS, /* Read on-module spd by SMBUS. */ + READ_SPD_CBFS, /* Find spd file in CBFS. */ + READ_SPD_MEMPTR /* Find spd data from pointer. */ +}; + struct spd_info { - bool spd_by_index; + enum mem_info_read_type read_type; union spd_data_by { + /* To read on-module spd when read_type is READ_SMBUS. */ + uint8_t spd_smbus_address; + + /* To identify spd file when read_type is READ_SPD_CBFS. */ int spd_index; + + /* To find spd data when read_type is READ_SPD_MEMPTR. */ struct spd_by_pointer spd_data_ptr_info; } spd_spec; - uint8_t spd_smbus_address[4]; }; /* Board-specific memory dq mapping information */ struct cnl_mb_cfg { + /* Parameters required to access SPD for CH0D0/CH0D1/CH1D0/CH1D1. */ + struct spd_info spd[NUM_DIMM_SLOT]; + /* * For each channel, there are 6 sets of DQ byte mappings, * where each set has a package 0 and a package 1 value (package 0 @@ -107,26 +125,12 @@ struct cnl_mb_cfg { /* Early Command Training Enabled */ uint8_t ect; - - /* - * Flags to indicate which channels are populated. We - * currently support single or dual channel configurations. - * Set 1 to indicate that the channel is not populated Set 0 - * to indicate that the channel is populated. For example, - * dual channel memory configuration would have both - * channel_empty[0] = 0 and channel_empty[1] = 0. Note that - * this flag is only used for soldered down DRAM where we get - * SPD data from CBFS. We need the value 0 to default to - * populated in order to support existing boards. - */ - uint8_t channel_empty[2]; }; /* * Initialize default memory configurations for CannonLake. */ void cannonlake_memcfg_init(FSP_M_CONFIG *mem_cfg, - const struct cnl_mb_cfg *cnl_cfg, - const struct spd_info *spd); + const struct cnl_mb_cfg *cnl_cfg); #endif /* _SOC_CANNONLAKE_MEMCFG_INIT_H_ */