1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <console/console.h>
5 #include <soc/cnl_memcfg_init.h>
9 static void meminit_memcfg(FSP_M_CONFIG
*mem_cfg
,
10 const struct cnl_mb_cfg
*board_cfg
)
13 * DqByteMapChx expects 12 bytes of data, but the last 6 bytes
14 * are unused, so client passes in the relevant values and
15 * we null out the rest of the data.
17 memset(&mem_cfg
->DqByteMapCh0
, 0, sizeof(mem_cfg
->DqByteMapCh0
));
18 memcpy(&mem_cfg
->DqByteMapCh0
, &board_cfg
->dq_map
[DDR_CH0
],
19 sizeof(board_cfg
->dq_map
[DDR_CH0
]));
21 memset(&mem_cfg
->DqByteMapCh1
, 0, sizeof(mem_cfg
->DqByteMapCh1
));
22 memcpy(&mem_cfg
->DqByteMapCh1
, &board_cfg
->dq_map
[DDR_CH1
],
23 sizeof(board_cfg
->dq_map
[DDR_CH1
]));
25 memcpy(&mem_cfg
->DqsMapCpu2DramCh0
, &board_cfg
->dqs_map
[DDR_CH0
],
26 sizeof(board_cfg
->dqs_map
[DDR_CH0
]));
27 memcpy(&mem_cfg
->DqsMapCpu2DramCh1
, &board_cfg
->dqs_map
[DDR_CH1
],
28 sizeof(board_cfg
->dqs_map
[DDR_CH1
]));
30 memcpy(&mem_cfg
->RcompResistor
, &board_cfg
->rcomp_resistor
,
31 sizeof(mem_cfg
->RcompResistor
));
33 /* Early cannonlake requires rcomp targets to be 0 */
34 memcpy(&mem_cfg
->RcompTarget
, &board_cfg
->rcomp_targets
,
35 sizeof(mem_cfg
->RcompTarget
));
39 * Initialize default memory settings using spd data contained in a buffer.
41 static void meminit_spd_data(FSP_M_CONFIG
*mem_cfg
, uint8_t mem_slot
,
42 size_t spd_data_len
, uintptr_t spd_data_ptr
)
44 static size_t last_set_spd_data_len
= 0;
46 assert(spd_data_ptr
!= 0 && spd_data_len
!= 0);
48 if (last_set_spd_data_len
!= 0 &&
49 last_set_spd_data_len
!= spd_data_len
)
50 die("spd data length disparity among slots");
52 mem_cfg
->MemorySpdDataLen
= spd_data_len
;
53 last_set_spd_data_len
= spd_data_len
;
57 mem_cfg
->MemorySpdPtr00
= spd_data_ptr
;
60 mem_cfg
->MemorySpdPtr01
= spd_data_ptr
;
63 mem_cfg
->MemorySpdPtr10
= spd_data_ptr
;
66 mem_cfg
->MemorySpdPtr11
= spd_data_ptr
;
69 die("nonexistent memory slot");
71 printk(BIOS_INFO
, "memory slot: %d configuration done.\n", mem_slot
);
75 * Initialize default memory settings using the spd file specified by
76 * spd_index. The spd_index is an index into the SPD_SOURCES array defined
79 static void meminit_cbfs_spd_index(FSP_M_CONFIG
*mem_cfg
,
80 int spd_index
, uint8_t mem_slot
)
82 static size_t spd_data_len
;
83 static uintptr_t spd_data_ptr
;
84 static int last_spd_index
;
86 assert(mem_slot
< NUM_DIMM_SLOT
);
88 if ((spd_data_ptr
== 0) || (last_spd_index
!= spd_index
)) {
89 printk(BIOS_DEBUG
, "SPD INDEX = %d\n", spd_index
);
91 spd_data_ptr
= spd_cbfs_map(spd_index
);
93 die("spd.bin not found or incorrect index\n");
95 spd_data_len
= CONFIG_DIMM_SPD_SIZE
;
97 /* Memory leak is ok since we have memory mapped boot media */
98 assert(CONFIG(BOOT_DEVICE_MEMORY_MAPPED
));
100 last_spd_index
= spd_index
;
101 print_spd_info((unsigned char *)spd_data_ptr
);
104 meminit_spd_data(mem_cfg
, mem_slot
, spd_data_len
, spd_data_ptr
);
107 /* Initialize onboard memory configurations for CannonLake */
108 void cannonlake_memcfg_init(FSP_M_CONFIG
*mem_cfg
,
109 const struct cnl_mb_cfg
*cnl_cfg
)
111 const struct spd_info
*spdi
;
113 /* Early Command Training Enabled */
114 mem_cfg
->ECT
= cnl_cfg
->ect
;
115 mem_cfg
->DqPinsInterleaved
= cnl_cfg
->dq_pins_interleaved
;
116 mem_cfg
->CaVrefConfig
= cnl_cfg
->vref_ca_config
;
118 for (int i
= 0; i
< NUM_DIMM_SLOT
; i
++) {
119 spdi
= &(cnl_cfg
->spd
[i
]);
120 switch (spdi
->read_type
) {
124 mem_cfg
->SpdAddressTable
[i
] =
125 spdi
->spd_spec
.spd_smbus_address
;
128 meminit_cbfs_spd_index(mem_cfg
,
129 spdi
->spd_spec
.spd_index
, i
);
131 case READ_SPD_MEMPTR
:
132 meminit_spd_data(mem_cfg
, i
,
133 spdi
->spd_spec
.spd_data_ptr_info
.spd_data_len
,
134 spdi
->spd_spec
.spd_data_ptr_info
.spd_data_ptr
);
137 die("no valid way to read mem info");
141 meminit_memcfg(mem_cfg
, cnl_cfg
);