From 903c9764a16fba61bf90187d6f7e2afde37cfec0 Mon Sep 17 00:00:00 2001 From: Lijian Zhao Date: Mon, 20 Aug 2018 14:06:13 -0700 Subject: soc/intel/cannonlake: Change LPDDR4 to MEMCFG Modify the previously SOC_CNL_LPDDR4_INIT to SOC_CNL_MEMCFG_INIT, to make the infrasturture to handle both LPDDR4 and DDR4 cases in the future. Consider the case of reading SPD from SMBus other than providing SPD pointer directly. BUG=N/A TEST=Verify "./util/abuild/abuild -p none -t google/zoombini -x -a" compiles successfully. Change-Id: I2f898147f67dd52b89cc3d9fc4e6b3854fa81f57 Signed-off-by: Lijian Zhao Reviewed-on: https://review.coreboot.org/28248 Reviewed-by: Nick Vaccaro Reviewed-by: Paul Menzel Tested-by: build bot (Jenkins) --- src/soc/intel/cannonlake/Kconfig | 2 +- src/soc/intel/cannonlake/Makefile.inc | 2 +- src/soc/intel/cannonlake/cnl_lpddr4_init.c | 111 ------------------ src/soc/intel/cannonlake/cnl_memcfg_init.c | 129 +++++++++++++++++++++ .../intel/cannonlake/include/soc/cnl_lpddr4_init.h | 106 ----------------- .../intel/cannonlake/include/soc/cnl_memcfg_init.h | 115 ++++++++++++++++++ 6 files changed, 246 insertions(+), 219 deletions(-) delete mode 100644 src/soc/intel/cannonlake/cnl_lpddr4_init.c create mode 100644 src/soc/intel/cannonlake/cnl_memcfg_init.c delete mode 100644 src/soc/intel/cannonlake/include/soc/cnl_lpddr4_init.h create mode 100644 src/soc/intel/cannonlake/include/soc/cnl_memcfg_init.h (limited to 'src/soc') diff --git a/src/soc/intel/cannonlake/Kconfig b/src/soc/intel/cannonlake/Kconfig index e6a2062c4a..ef39706b8d 100644 --- a/src/soc/intel/cannonlake/Kconfig +++ b/src/soc/intel/cannonlake/Kconfig @@ -184,7 +184,7 @@ config CPU_BCLK_MHZ int default 100 -config SOC_INTEL_CANNONLAKE_LPDDR4_INIT +config SOC_INTEL_CANNONLAKE_MEMCFG_INIT bool default n diff --git a/src/soc/intel/cannonlake/Makefile.inc b/src/soc/intel/cannonlake/Makefile.inc index 013e86a922..065d92b6e5 100644 --- a/src/soc/intel/cannonlake/Makefile.inc +++ b/src/soc/intel/cannonlake/Makefile.inc @@ -22,7 +22,7 @@ bootblock-y += lpc.c bootblock-y += p2sb.c bootblock-$(CONFIG_UART_DEBUG) += uart.c -romstage-$(CONFIG_SOC_INTEL_CANNONLAKE_LPDDR4_INIT) += cnl_lpddr4_init.c +romstage-$(CONFIG_SOC_INTEL_CANNONLAKE_MEMCFG_INIT) += cnl_memcfg_init.c romstage-y += gpio.c romstage-y += gspi.c romstage-y += i2c.c diff --git a/src/soc/intel/cannonlake/cnl_lpddr4_init.c b/src/soc/intel/cannonlake/cnl_lpddr4_init.c deleted file mode 100644 index ea8c410267..0000000000 --- a/src/soc/intel/cannonlake/cnl_lpddr4_init.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright 2017 Google Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ -#include -#include -#include -#include -#include -#include - -static void meminit_lpddr4(FSP_M_CONFIG *mem_cfg, - const struct lpddr4_cfg *board_cfg, - size_t spd_data_len, uintptr_t spd_data_ptr) -{ - /* - * DqByteMapChx expects 12 bytes of data, but the last 6 bytes - * are unused, so client passes in the relevant values and - * we null out the rest of the data. - */ - memset(&mem_cfg->DqByteMapCh0, 0, sizeof(mem_cfg->DqByteMapCh0)); - memcpy(&mem_cfg->DqByteMapCh0, &board_cfg->dq_map[LP4_CH0], - sizeof(board_cfg->dq_map[LP4_CH0])); - - memset(&mem_cfg->DqByteMapCh1, 0, sizeof(mem_cfg->DqByteMapCh1)); - memcpy(&mem_cfg->DqByteMapCh1, &board_cfg->dq_map[LP4_CH1], - sizeof(board_cfg->dq_map[LP4_CH1])); - - memcpy(&mem_cfg->DqsMapCpu2DramCh0, &board_cfg->dqs_map[LP4_CH0], - sizeof(board_cfg->dqs_map[LP4_CH0])); - memcpy(&mem_cfg->DqsMapCpu2DramCh1, &board_cfg->dqs_map[LP4_CH1], - sizeof(board_cfg->dqs_map[LP4_CH1])); - - memcpy(&mem_cfg->RcompResistor, &board_cfg->rcomp_resistor, - sizeof(mem_cfg->RcompResistor)); - - /* Early cannonlake requires rcomp targets to be 0 */ - memcpy(&mem_cfg->RcompTarget, &board_cfg->rcomp_targets, - sizeof(mem_cfg->RcompTarget)); - - mem_cfg->MemorySpdDataLen = spd_data_len; - mem_cfg->MemorySpdPtr00 = spd_data_ptr; - - /* Use the same spd data for channel 1, Dimm 0 */ - mem_cfg->MemorySpdPtr10 = mem_cfg->MemorySpdPtr00; -} - -/* - * Initialize default LPDDR4 settings using spd data contained in a buffer. - */ -static void meminit_lpddr4_spd_data(FSP_M_CONFIG *mem_cfg, - const struct lpddr4_cfg *cnl_cfg, - size_t spd_data_len, uintptr_t spd_data_ptr) -{ - assert(spd_data_ptr && spd_data_len); - meminit_lpddr4(mem_cfg, cnl_cfg, spd_data_len, spd_data_ptr); -} - -/* - * Initialize default LPDDR4 settings using the spd file specified by - * spd_index. The spd_index is an index into the SPD_SOURCES array defined - * in spd/Makefile.inc. - */ -static void meminit_lpddr4_cbfs_spd_index(FSP_M_CONFIG *mem_cfg, - const struct lpddr4_cfg *cnl_cfg, - int spd_index) -{ - size_t spd_data_len; - uintptr_t spd_data_ptr; - struct region_device spd_rdev; - - 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"); - spd_data_len = region_device_sz(&spd_rdev); - /* Memory leak is ok since we have memory mapped boot media */ - assert(IS_ENABLED(CONFIG_BOOT_DEVICE_MEMORY_MAPPED)); - spd_data_ptr = (uintptr_t)rdev_mmap_full(&spd_rdev); - meminit_lpddr4_spd_data(mem_cfg, cnl_cfg, spd_data_len, spd_data_ptr); -} - -/* Initialize LPDDR4 settings for CannonLake */ -void cannonlake_lpddr4_init(FSP_M_CONFIG *mem_cfg, - const struct lpddr4_cfg *cnl_cfg, - const struct spd_info *spd) -{ - /* Early Command Training Enabled */ - mem_cfg->ECT = cnl_cfg->ect; - mem_cfg->DqPinsInterleaved = cnl_cfg->dq_pins_interleaved; - mem_cfg->RefClk = 0; /* Auto Select CLK freq */ - mem_cfg->CaVrefConfig = 0; /* VREF_CA->CHA/CHB */ - - if (spd->spd_by_index) { - meminit_lpddr4_cbfs_spd_index(mem_cfg, cnl_cfg, - spd->spd_spec.spd_index); - } else { - meminit_lpddr4_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); - } -} diff --git a/src/soc/intel/cannonlake/cnl_memcfg_init.c b/src/soc/intel/cannonlake/cnl_memcfg_init.c new file mode 100644 index 0000000000..9f9592b5db --- /dev/null +++ b/src/soc/intel/cannonlake/cnl_memcfg_init.c @@ -0,0 +1,129 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2017 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include + +static void meminit_memcfg(FSP_M_CONFIG *mem_cfg, + const struct cnl_mb_cfg *board_cfg) +{ + /* + * DqByteMapChx expects 12 bytes of data, but the last 6 bytes + * are unused, so client passes in the relevant values and + * we null out the rest of the data. + */ + 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])); + + 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])); + + memcpy(&mem_cfg->DqsMapCpu2DramCh0, &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])); + + memcpy(&mem_cfg->RcompResistor, &board_cfg->rcomp_resistor, + 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 *board_cfg, + size_t spd_data_len, uintptr_t spd_data_ptr) +{ + mem_cfg->MemorySpdDataLen = spd_data_len; + mem_cfg->MemorySpdPtr00 = spd_data_ptr; + + /* Use the same spd data for channel 1, Dimm 0 */ + mem_cfg->MemorySpdPtr10 = mem_cfg->MemorySpdPtr00; +} + +/* + * 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) +{ + assert(spd_data_ptr && spd_data_len); + meminit_memcfg_spd(mem_cfg, cnl_cfg, spd_data_len, spd_data_ptr); +} + +/* + * Initialize default memory settings using the spd file specified by + * spd_index. The spd_index is an index into the SPD_SOURCES array defined + * 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) +{ + size_t spd_data_len; + uintptr_t spd_data_ptr; + struct region_device spd_rdev; + + 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"); + spd_data_len = region_device_sz(&spd_rdev); + /* Memory leak is ok since we have memory mapped boot media */ + assert(IS_ENABLED(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); +} + +/* 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) +{ + bool OnModuleSpd; + /* 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 = 1; + } + } + + 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_lpddr4_init.h b/src/soc/intel/cannonlake/include/soc/cnl_lpddr4_init.h deleted file mode 100644 index db1c3a57c9..0000000000 --- a/src/soc/intel/cannonlake/include/soc/cnl_lpddr4_init.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright 2017 Google Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef _SOC_CANNONLAKE_LPDDR4_INIT_H_ -#define _SOC_CANNONLAKE_LPDDR4_INIT_H_ - -#include -#include -#include - -/* Number of dq bits controlled per dqs */ -#define DQ_BITS_PER_DQS 8 - -/* - * Number of LPDDR4 packages, where a "package" represents a 64-bit solution. - */ -#define LP4_NUM_PACKAGES 2 - -/* 64-bit Channel identification */ -enum { - LP4_CH0, - LP4_CH1, - LP4_NUM_CHANNELS -}; - -struct spd_by_pointer { - size_t spd_data_len; - uintptr_t spd_data_ptr; -}; - -struct spd_info { - bool spd_by_index; - union spd_data_by { - int spd_index; - struct spd_by_pointer spd_data_ptr_info; - } spd_spec; -}; - -/* Board-specific lpddr4 dq mapping information */ -struct lpddr4_cfg { - /* - * For each channel, there are 3 sets of DQ byte mappings, - * where each set has a package 0 and a package 1 value (package 0 - * represents the first 64-bit lpddr4 chip combination, and package 1 - * represents the second 64-bit lpddr4 chip combination). - * The first three sets are for CLK, CMD, and CTL. - * The fsp package actually expects 6 sets, but the last 3 sets are - * not used in CNL, so we only define the three sets that are used - * and let the meminit_lpddr4() routine take care of clearing the - * unused fields for the caller. - */ - const uint8_t dq_map[LP4_NUM_CHANNELS][3][LP4_NUM_PACKAGES]; - - /* - * DQS CPU<>DRAM map Ch0 and Ch1. Each array entry represents a - * mapping of a dq bit on the CPU to the bit it's connected to on - * the memory part. The array index represents the dqs bit number - * on the memory part, and the values in the array represent which - * pin on the CPU that DRAM pin connects to. - */ - const uint8_t dqs_map[LP4_NUM_CHANNELS][DQ_BITS_PER_DQS]; - - /* - * Rcomp resistor values. These values represent the resistance in - * ohms of the three rcomp resistors attached to the DDR_COMP_0, - * DDR_COMP_1, and DDR_COMP_2 pins on the DRAM. - */ - const uint16_t rcomp_resistor[3]; - - /* - * Rcomp target values. These will typically be the following - * values for Cannon Lake : { 80, 40, 40, 40, 30 } - */ - const uint16_t rcomp_targets[5]; - - /* - * Indicates whether memory is interleaved. - * Set to 1 for an interleaved design, - * set to 0 for non-interleaved design. - */ - const uint8_t dq_pins_interleaved; - - /* Early Command Training Enabled */ - const uint8_t ect; -}; - -/* - * Initialize default LPDDR4 settings for CannonLake. - */ -void cannonlake_lpddr4_init(FSP_M_CONFIG *mem_cfg, - const struct lpddr4_cfg *cnl_cfg, - const struct spd_info *spd); - -#endif /* _SOC_CANNONLAKE_LPDDR4_INIT_H_ */ diff --git a/src/soc/intel/cannonlake/include/soc/cnl_memcfg_init.h b/src/soc/intel/cannonlake/include/soc/cnl_memcfg_init.h new file mode 100644 index 0000000000..7a76eb09f1 --- /dev/null +++ b/src/soc/intel/cannonlake/include/soc/cnl_memcfg_init.h @@ -0,0 +1,115 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2017 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _SOC_CANNONLAKE_MEMCFG_INIT_H_ +#define _SOC_CANNONLAKE_MEMCFG_INIT_H_ + +#include +#include +#include + +/* Number of dq bits controlled per dqs */ +#define DQ_BITS_PER_DQS 8 + +/* + * Number of memory packages, where a "package" represents a 64-bit solution. + */ +#define DDR_NUM_PACKAGES 2 + +/* 64-bit Channel identification */ +enum { + DDR_CH0, + DDR_CH1, + DDR_NUM_CHANNELS +}; + +struct spd_by_pointer { + size_t spd_data_len; + uintptr_t spd_data_ptr; +}; + +struct spd_info { + bool spd_by_index; + union spd_data_by { + int spd_index; + struct spd_by_pointer spd_data_ptr_info; + } spd_spec; + const uint8_t spd_smbus_address[4]; +}; + +/* Board-specific memory dq mapping information */ +struct cnl_mb_cfg { + /* + * For each channel, there are 3 sets of DQ byte mappings, + * where each set has a package 0 and a package 1 value (package 0 + * represents the first 64-bit lpddr4 chip combination, and package 1 + * represents the second 64-bit lpddr4 chip combination). + * The first three sets are for CLK, CMD, and CTL. + * The fsp package actually expects 6 sets, but the last 3 sets are + * not used in CNL, so we only define the three sets that are used + * and let the meminit_lpddr4() routine take care of clearing the + * unused fields for the caller. + */ + const uint8_t dq_map[DDR_NUM_CHANNELS][3][DDR_NUM_PACKAGES]; + + /* + * DQS CPU<>DRAM map Ch0 and Ch1. Each array entry represents a + * mapping of a dq bit on the CPU to the bit it's connected to on + * the memory part. The array index represents the dqs bit number + * on the memory part, and the values in the array represent which + * pin on the CPU that DRAM pin connects to. + */ + const uint8_t dqs_map[DDR_NUM_CHANNELS][DQ_BITS_PER_DQS]; + + /* + * Rcomp resistor values. These values represent the resistance in + * ohms of the three rcomp resistors attached to the DDR_COMP_0, + * DDR_COMP_1, and DDR_COMP_2 pins on the DRAM. + */ + const uint16_t rcomp_resistor[3]; + + /* + * Rcomp target values. These will typically be the following + * values for Cannon Lake : { 80, 40, 40, 40, 30 } + */ + const uint16_t rcomp_targets[5]; + + /* + * Indicates whether memory is interleaved. + * Set to 1 for an interleaved design, + * set to 0 for non-interleaved design. + */ + const uint8_t dq_pins_interleaved; + + /* + * VREF_CA configuraation. + * Set to 0 VREF_CA goes to both CH_A and CH_B, + * set to 1 VREF_CA goes to CH_A and VREF_DQ_A goes to CH_B, + * set to 2 VREF_CA goes to CH_A and VREF_DQ_B goes to CH_B. + */ + const uint8_t vref_ca_config; + + /* Early Command Training Enabled */ + const uint8_t ect; +}; + +/* + * 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); + +#endif /* _SOC_CANNONLAKE_MEMCFG_INIT_H_ */ -- cgit v1.2.3