1 /* SPDX-License-Identifier: GPL-2.0-only */
4 #include <console/console.h>
6 #include <soc/meminit.h>
10 static void spd_read_from_cbfs(const struct spd_info
*spd_info
, uintptr_t *spd_data_ptr
,
13 size_t spd_index
= spd_info
->spd_spec
.spd_index
;
15 printk(BIOS_DEBUG
, "SPD INDEX = %zu\n", spd_index
);
17 /* Memory leak is ok since we have memory mapped boot media */
18 assert(CONFIG(BOOT_DEVICE_MEMORY_MAPPED
));
20 *spd_data_len
= CONFIG_DIMM_SPD_SIZE
;
21 *spd_data_ptr
= spd_cbfs_map(spd_index
);
23 die("spd.bin not found or incorrect index\n");
26 static void get_spd_data(const struct spd_info
*spd_info
, uintptr_t *spd_data_ptr
,
29 if (spd_info
->read_type
== READ_SPD_MEMPTR
) {
30 *spd_data_ptr
= spd_info
->spd_spec
.spd_data_ptr_info
.spd_data_ptr
;
31 *spd_data_len
= spd_info
->spd_spec
.spd_data_ptr_info
.spd_data_len
;
35 if (spd_info
->read_type
== READ_SPD_CBFS
) {
36 spd_read_from_cbfs(spd_info
, spd_data_ptr
, spd_data_len
);
40 die("no valid way to read SPD info");
43 static void meminit_dq_dqs_map(FSP_M_CONFIG
*mem_cfg
, const struct mb_cfg
*board_cfg
,
46 memcpy(&mem_cfg
->RcompResistor
, &board_cfg
->rcomp_resistor
,
47 sizeof(mem_cfg
->RcompResistor
));
49 memcpy(&mem_cfg
->RcompTarget
, &board_cfg
->rcomp_targets
,
50 sizeof(mem_cfg
->RcompTarget
));
52 memcpy(&mem_cfg
->DqByteMapCh0
, &board_cfg
->dq_map
[DDR_CH0
],
53 sizeof(board_cfg
->dq_map
[DDR_CH0
]));
55 memcpy(&mem_cfg
->DqsMapCpu2DramCh0
, &board_cfg
->dqs_map
[DDR_CH0
],
56 sizeof(board_cfg
->dqs_map
[DDR_CH0
]));
61 memcpy(&mem_cfg
->DqByteMapCh1
, &board_cfg
->dq_map
[DDR_CH1
],
62 sizeof(board_cfg
->dq_map
[DDR_CH1
]));
64 memcpy(&mem_cfg
->DqsMapCpu2DramCh1
, &board_cfg
->dqs_map
[DDR_CH1
],
65 sizeof(board_cfg
->dqs_map
[DDR_CH1
]));
68 static void meminit_channels(FSP_M_CONFIG
*mem_cfg
, const struct mb_cfg
*board_cfg
,
69 uintptr_t spd_data_ptr
, bool half_populated
)
72 mem_cfg
->MemorySpdPtr00
= spd_data_ptr
;
73 mem_cfg
->MemorySpdPtr01
= 0;
76 printk(BIOS_INFO
, "%s: DRAM half-populated\n", __func__
);
81 mem_cfg
->MemorySpdPtr10
= spd_data_ptr
;
82 mem_cfg
->MemorySpdPtr11
= 0;
84 meminit_dq_dqs_map(mem_cfg
, board_cfg
, half_populated
);
87 /* Initialize onboard memory configurations for lpddr4x */
88 void memcfg_init(FSP_M_CONFIG
*mem_cfg
, const struct mb_cfg
*board_cfg
,
89 const struct spd_info
*spd_info
, bool half_populated
)
91 if (spd_info
->read_type
== READ_SMBUS
) {
92 for (int i
= 0; i
< NUM_DIMM_SLOT
; i
++)
93 mem_cfg
->SpdAddressTable
[i
] = spd_info
->spd_spec
.spd_smbus_address
[i
];
95 meminit_dq_dqs_map(mem_cfg
, board_cfg
, half_populated
);
97 uintptr_t spd_data_ptr
= 0;
98 size_t spd_data_len
= 0;
99 memset(&mem_cfg
->SpdAddressTable
, 0, sizeof(mem_cfg
->SpdAddressTable
));
100 get_spd_data(spd_info
, &spd_data_ptr
, &spd_data_len
);
101 print_spd_info((unsigned char *)spd_data_ptr
);
103 mem_cfg
->MemorySpdDataLen
= spd_data_len
;
104 meminit_channels(mem_cfg
, board_cfg
, spd_data_ptr
, half_populated
);
107 /* Early Command Training Enabled */
108 mem_cfg
->ECT
= board_cfg
->ect
;
109 mem_cfg
->DqPinsInterleaved
= board_cfg
->dq_pins_interleaved
;
110 mem_cfg
->CaVrefConfig
= board_cfg
->vref_ca_config
;
111 mem_cfg
->UserBd
= board_cfg
->UserBd
;