/* * This file is part of the coreboot project. * * * SPDX-License-Identifier: GPL-2.0-or-later */ #ifndef _SOC_TIGERLAKE_MEMINIT_H_ #define _SOC_TIGERLAKE_MEMINIT_H_ #include #include #include #define BITS_PER_BYTE 8 #define LPDDR4X_CHANNELS 8 #define LPDDR4X_BYTES_PER_CHANNEL 2 #define DDR4_CHANNELS 2 #define DDR4_BYTES_PER_CHANNEL 8 enum mem_topology { MEMORY_DOWN, /* Supports reading SPD from CBFS or in-memory pointer. */ SODIMM, /* Supports reading SPD using SMBus (only for DDR4). */ MIXED, /* CH0 = MD, CH1 = SODIMM (only for DDR4). */ }; enum md_spd_loc { /* Read SPD from pointer provided to memory location. */ SPD_MEMPTR, /* Read SPD using index into spd.bin in CBFS. */ SPD_CBFS, }; struct spd_info { enum mem_topology topology; /* SPD info for Memory down topology */ enum md_spd_loc md_spd_loc; union { /* Used for SPD_CBFS */ uint8_t cbfs_index; struct { /* Used for SPD_MEMPTR */ uintptr_t data_ptr; size_t data_len; }; }; /* * SPD info for SODIMM topology. * Leave addr_dimmN as 0 for any DIMMs that are not populated. */ struct { /* SMBus address for DIMM0 within the channel. */ uint8_t addr_dimm0; /* SMBus address for DIMM1 within the channel. */ uint8_t addr_dimm1; } smbus_info[DDR4_CHANNELS]; }; /* Board-specific memory configuration information */ struct lpddr4x_cfg { /* * DQ CPU<>DRAM map: * LPDDR4x memory interface has 2 DQs per channel. Each DQ consists of 8 bits(1 * byte). Thus, dq_map is represented as DDR[7-0]_DQ[1-0][7:0], where * DDR[7-0] : LPDDR4x channel # * DQ[1-0] : DQ # within the channel * [7:0] : Bits within the DQ * * Index of the array represents DQ pin# on the CPU, whereas value in * the array represents DQ pin# on the memory part. */ uint8_t dq_map[LPDDR4X_CHANNELS][LPDDR4X_BYTES_PER_CHANNEL][BITS_PER_BYTE]; /* * DQS CPU<>DRAM map: * LPDDR4x memory interface has 2 DQS pairs(P/N) per channel. Thus, dqs_map is * represented as DDR[7-0]_DQS[1:0], where * DDR[7-0] : LPDDR4x channel # * DQS[1-0] : DQS # within the channel * * Index of the array represents DQS pin# on the CPU, whereas value in * the array represents DQ pin# on the memory part. */ uint8_t dqs_map[LPDDR4X_CHANNELS][LPDDR4X_BYTES_PER_CHANNEL]; /* * Early Command Training Enable/Disable Control * 1 = enable, 0 = disable */ uint8_t ect; }; /* Board-specific memory configuration information for DDR4 memory variant */ struct mb_ddr4_cfg { /* * DQ CPU<>DRAM map: * DDR4 memory interface has 8 DQs per channel. Each DQ consists of 8 bits(1 * byte). Thus, dq_map is represented as DDR[1-0]_DQ[7-0][7:0], where * DDR[1-0] : DDR4 channel # * DQ[7-0] : DQ # within the channel * [7:0] : Bits within the DQ * * Index of the array represents DQ pin# on the CPU, whereas value in * the array represents DQ pin# on the memory part. */ uint8_t dq_map[DDR4_CHANNELS][DDR4_BYTES_PER_CHANNEL][BITS_PER_BYTE]; /* * DQS CPU<>DRAM map: * DDR4 memory interface has 8 DQS pairs per channel. Thus, dqs_map is represented as * DDR[1-0]_DQS[7-0], where * DDR[1-0] : DDR4 channel # * DQS[7-0] : DQS # within the channel * * Index of the array represents DQS pin# on the CPU, whereas value in * the array represents DQS pin# on the memory part. */ uint8_t dqs_map[DDR4_CHANNELS][DDR4_BYTES_PER_CHANNEL]; /* * Indicates whether memory is interleaved. * Set to 1 for an interleaved design, * set to 0 for non-interleaved design. */ uint8_t dq_pins_interleaved; /* * Early Command Training Enable/Disable Control * 1 = enable, 0 = disable */ uint8_t ect; }; void meminit_lpddr4x(FSP_M_CONFIG *mem_cfg, const struct lpddr4x_cfg *board_cfg, const struct spd_info *spd, bool half_populated); /* Initialize DDR4 memory configurations */ void meminit_ddr4(FSP_M_CONFIG *mem_cfg, const struct mb_ddr4_cfg *board_cfg, const struct spd_info *spd, const bool half_populated); #endif /* _SOC_TIGERLAKE_MEMINIT_H_ */