blob: 3c4c16b5c296384323c7c3a2714b02c31919c01d [file] [log] [blame]
/*
* 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 <stddef.h>
#include <stdint.h>
#include <fsp/soc_binding.h>
#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_ */