summaryrefslogtreecommitdiff
path: root/src/soc/intel/tigerlake/include/soc/meminit.h
blob: a2fb3f4334e8c3fb49dab930bbed433faaa0d65a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/*
 * 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;
};

void meminit_lpddr4x(FSP_M_CONFIG *mem_cfg, const struct lpddr4x_cfg *board_cfg,
		const struct spd_info *spd, bool half_populated);

#endif /* _SOC_TIGERLAKE_MEMINIT_H_ */