From 48be29e3920aef1254eca97298c4155864e72fc8 Mon Sep 17 00:00:00 2001 From: Furquan Shaikh Date: Tue, 5 Dec 2017 14:48:44 -0800 Subject: [PATCH] mb/google/poppy: Add support for DDR4 memory This change updates memory SPD handling code in baseboard poppy to allow variants to define either LPDDR3 or DDR4 memory types. In addition to that, it also updates the function to print SPD info considering offsets that might be different across the two memory types. BUG=b:70188937 Change-Id: Iefad01719c62264fb0d7e987904e77647d6026c2 Signed-off-by: Furquan Shaikh Reviewed-on: https://review.coreboot.org/22745 Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin --- src/mainboard/google/poppy/romstage.c | 114 +++++++++++------- .../baseboard/include/baseboard/variants.h | 7 ++ .../google/poppy/variants/baseboard/memory.c | 1 + .../google/poppy/variants/nautilus/memory.c | 1 + 4 files changed, 82 insertions(+), 41 deletions(-) diff --git a/src/mainboard/google/poppy/romstage.c b/src/mainboard/google/poppy/romstage.c index 2a6cd90ea7..6bb4076d0d 100644 --- a/src/mainboard/google/poppy/romstage.c +++ b/src/mainboard/google/poppy/romstage.c @@ -22,20 +22,52 @@ #include -#define SPD_LEN 256 +/* Offset to identify DRAM type. */ +#define SPD_DRAM_TYPE_OFF 2 +#define SPD_DRAM_LPDDR3 0xf1 +#define SPD_DRAM_DDR4 0x0c -#define SPD_DRAM_TYPE 2 -#define SPD_DRAM_DDR3 0x0b -#define SPD_DRAM_LPDDR3 0xf1 -#define SPD_DENSITY_BANKS 4 -#define SPD_ADDRESSING 5 -#define SPD_ORGANIZATION 7 -#define SPD_BUS_DEV_WIDTH 8 -#define SPD_PART_OFF 128 -#define SPD_PART_LEN 18 -#define SPD_MANU_OFF 148 +/* Length of SPD data. */ +#define SPD_LEN_LPDDR3 256 +#define SPD_LEN_DDR4 512 -static void mainboard_print_spd_info(uint8_t spd[]) +/* Fields that are common across different memory types. */ +#define SPD_DENSITY_BANKS_OFF 4 +#define SPD_ADDRESSING_OFF 5 +#define SPD_PART_LEN 18 + +/* Fields that are different depending upon memory type. */ +#define SPD_ORG_OFF_LPDDR3 7 +#define SPD_BUSW_OFF_LPDDR3 8 +#define SPD_PART_OFF_LPDDR3 128 + +#define SPD_ORG_OFF_DDR4 12 +#define SPD_BUSW_OFF_DDR4 13 +#define SPD_PART_OFF_DDR4 329 + +#define SPD_INFO(_type) \ + [MEMORY_##_type] = { \ + .str = #_type, \ + .type_code = SPD_DRAM_##_type, \ + .len = SPD_LEN_##_type, \ + .org_off = SPD_ORG_OFF_##_type, \ + .busw_off = SPD_BUSW_OFF_##_type, \ + .part_off = SPD_PART_OFF_##_type, \ + } + +static const struct dram_info { + const char *str; + uint16_t type_code; + uint16_t len; + uint16_t org_off; + uint16_t busw_off; + uint16_t part_off; +} spd_info[MEMORY_COUNT] = { + SPD_INFO(LPDDR3), + SPD_INFO(DDR4), +}; + +static void mainboard_print_spd_info(const uint8_t *spd, enum memory_type type) { const int spd_banks[8] = { 8, 16, 32, 64, -1, -1, -1, -1 }; const int spd_capmb[8] = { 1, 2, 4, 8, 16, 32, 64, 0 }; @@ -45,28 +77,23 @@ static void mainboard_print_spd_info(uint8_t spd[]) const int spd_devw[8] = { 4, 8, 16, 32, -1, -1, -1, -1 }; const int spd_busw[8] = { 8, 16, 32, 64, -1, -1, -1, -1 }; char spd_name[SPD_PART_LEN+1] = { 0 }; + const struct dram_info *info = &spd_info[type]; - int banks = spd_banks[(spd[SPD_DENSITY_BANKS] >> 4) & 7]; - int capmb = spd_capmb[spd[SPD_DENSITY_BANKS] & 7] * 256; - int rows = spd_rows[(spd[SPD_ADDRESSING] >> 3) & 7]; - int cols = spd_cols[spd[SPD_ADDRESSING] & 7]; - int ranks = spd_ranks[(spd[SPD_ORGANIZATION] >> 3) & 7]; - int devw = spd_devw[spd[SPD_ORGANIZATION] & 7]; - int busw = spd_busw[spd[SPD_BUS_DEV_WIDTH] & 7]; + assert (info->type_code == spd[SPD_DRAM_TYPE_OFF]); /* Module type */ - printk(BIOS_INFO, "SPD: module type is "); - switch (spd[SPD_DRAM_TYPE]) { - case SPD_DRAM_LPDDR3: - printk(BIOS_INFO, "LPDDR3\n"); - break; - default: - printk(BIOS_INFO, "Unknown (%02x)\n", spd[SPD_DRAM_TYPE]); - return; - } + printk(BIOS_INFO, "SPD: module type is %s\n", info->str); + + int banks = spd_banks[(spd[SPD_DENSITY_BANKS_OFF] >> 4) & 7]; + int capmb = spd_capmb[spd[SPD_DENSITY_BANKS_OFF] & 7] * 256; + int rows = spd_rows[(spd[SPD_ADDRESSING_OFF] >> 3) & 7]; + int cols = spd_cols[spd[SPD_ADDRESSING_OFF] & 7]; + int ranks = spd_ranks[(spd[info->org_off] >> 3) & 7]; + int devw = spd_devw[spd[info->org_off] & 7]; + int busw = spd_busw[spd[info->busw_off] & 7]; /* Module Part Number */ - memcpy(spd_name, &spd[SPD_PART_OFF], SPD_PART_LEN); + memcpy(spd_name, &spd[info->part_off], SPD_PART_LEN); spd_name[SPD_PART_LEN] = 0; printk(BIOS_INFO, "SPD: module part is %s\n", spd_name); @@ -83,11 +110,12 @@ static void mainboard_print_spd_info(uint8_t spd[]) } } -static uintptr_t mainboard_get_spd_data(void) +static uintptr_t mainboard_get_spd_data(enum memory_type type) { char *spd_file; size_t spd_file_len; int spd_index; + const size_t spd_len = spd_info[type].len; spd_index = variant_memory_sku(); assert(spd_index >= 0); @@ -100,17 +128,15 @@ static uintptr_t mainboard_get_spd_data(void) die("SPD data not found."); /* make sure we have at least one SPD in the file. */ - if (spd_file_len < SPD_LEN) + if (spd_file_len < spd_len) die("Missing SPD data."); /* Make sure we did not overrun the buffer */ - if (spd_file_len < ((spd_index + 1) * SPD_LEN)) { - printk(BIOS_ERR, "SPD index override to 1 - old hardware?\n"); - spd_index = 1; - } + if (spd_file_len < ((spd_index + 1) * spd_len)) + die("Invalid SPD index."); - spd_index *= SPD_LEN; - mainboard_print_spd_info((uint8_t *)(spd_file + spd_index)); + spd_index *= spd_len; + mainboard_print_spd_info((uint8_t *)(spd_file + spd_index), type); return (uintptr_t)(spd_file + spd_index); } @@ -122,13 +148,19 @@ void mainboard_memory_init_params(FSPM_UPD *mupd) variant_memory_params(&p); - memcpy(&mem_cfg->DqByteMapCh0, p.dq_map, p.dq_map_size); - memcpy(&mem_cfg->DqsMapCpu2DramCh0, p.dqs_map, p.dqs_map_size); + assert(p.type < MEMORY_COUNT); + + if (p.dq_map && p.dq_map_size) + memcpy(&mem_cfg->DqByteMapCh0, p.dq_map, p.dq_map_size); + + if (p.dqs_map && p.dqs_map_size) + memcpy(&mem_cfg->DqsMapCpu2DramCh0, p.dqs_map, p.dqs_map_size); + memcpy(&mem_cfg->RcompResistor, p.rcomp_resistor, p.rcomp_resistor_size); memcpy(&mem_cfg->RcompTarget, p.rcomp_target, p.rcomp_target_size); - mem_cfg->MemorySpdPtr00 = mainboard_get_spd_data(); + mem_cfg->MemorySpdPtr00 = mainboard_get_spd_data(p.type); mem_cfg->MemorySpdPtr10 = mem_cfg->MemorySpdPtr00; - mem_cfg->MemorySpdDataLen = SPD_LEN; + mem_cfg->MemorySpdDataLen = spd_info[p.type].len; } diff --git a/src/mainboard/google/poppy/variants/baseboard/include/baseboard/variants.h b/src/mainboard/google/poppy/variants/baseboard/include/baseboard/variants.h index 62389afaae..c88b99a7bd 100644 --- a/src/mainboard/google/poppy/variants/baseboard/include/baseboard/variants.h +++ b/src/mainboard/google/poppy/variants/baseboard/include/baseboard/variants.h @@ -29,7 +29,14 @@ const struct pad_config *variant_early_gpio_table(size_t *num); const struct cros_gpio *variant_cros_gpios(size_t *num); +enum memory_type { + MEMORY_LPDDR3, + MEMORY_DDR4, + MEMORY_COUNT, +}; + struct memory_params { + enum memory_type type; const void *dq_map; size_t dq_map_size; const void *dqs_map; diff --git a/src/mainboard/google/poppy/variants/baseboard/memory.c b/src/mainboard/google/poppy/variants/baseboard/memory.c index d3f1286716..8134f1a36e 100644 --- a/src/mainboard/google/poppy/variants/baseboard/memory.c +++ b/src/mainboard/google/poppy/variants/baseboard/memory.c @@ -39,6 +39,7 @@ static const u16 rcomp_target[] = { 100, 40, 40, 23, 40 }; void __attribute__((weak)) variant_memory_params(struct memory_params *p) { + p->type = MEMORY_LPDDR3; p->dq_map = dq_map; p->dq_map_size = sizeof(dq_map); p->dqs_map = dqs_map; diff --git a/src/mainboard/google/poppy/variants/nautilus/memory.c b/src/mainboard/google/poppy/variants/nautilus/memory.c index 508c299532..dc845bcb7f 100644 --- a/src/mainboard/google/poppy/variants/nautilus/memory.c +++ b/src/mainboard/google/poppy/variants/nautilus/memory.c @@ -37,6 +37,7 @@ static const u16 rcomp_target[] = { 100, 40, 40, 23, 40 }; void variant_memory_params(struct memory_params *p) { + p->type = MEMORY_LPDDR3; p->dq_map = dq_map; p->dq_map_size = sizeof(dq_map); p->dqs_map = dqs_map;