blob: 9ec1ffa82d1da1084d4bca8ba0f2e29db27b90e8 [file] [log] [blame]
Angel Ponsfabfe9d2020-04-05 15:47:07 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Aamir Bohradd7acaa2020-03-25 11:36:22 +05302
3#include <assert.h>
4#include <console/console.h>
5#include <fsp/util.h>
Aamir Bohra512b77a2020-03-25 13:20:34 +05306#include <soc/meminit.h>
Aamir Bohradd7acaa2020-03-25 11:36:22 +05307#include <spd_bin.h>
8#include <string.h>
9
10static void spd_read_from_cbfs(const struct spd_info *spd_info, uintptr_t *spd_data_ptr,
11 size_t *spd_data_len)
12{
Aamir Bohradd7acaa2020-03-25 11:36:22 +053013 size_t spd_index = spd_info->spd_spec.spd_index;
14
15 printk(BIOS_DEBUG, "SPD INDEX = %lu\n", spd_index);
Aamir Bohradd7acaa2020-03-25 11:36:22 +053016
17 /* Memory leak is ok since we have memory mapped boot media */
18 assert(CONFIG(BOOT_DEVICE_MEMORY_MAPPED));
19
Julius Wernera9b44f42021-02-05 17:27:45 -080020 *spd_data_len = CONFIG_DIMM_SPD_SIZE;
21 *spd_data_ptr = spd_cbfs_map(spd_index);
22 if (!*spd_data_ptr)
23 die("spd.bin not found or incorrect index\n");
Aamir Bohradd7acaa2020-03-25 11:36:22 +053024}
25
26static void get_spd_data(const struct spd_info *spd_info, uintptr_t *spd_data_ptr,
27 size_t *spd_data_len)
28{
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;
32 return;
33 }
34
35 if (spd_info->read_type == READ_SPD_CBFS) {
36 spd_read_from_cbfs(spd_info, spd_data_ptr, spd_data_len);
37 return;
38 }
39
40 die("no valid way to read SPD info");
41}
42
43static void meminit_dq_dqs_map(FSP_M_CONFIG *mem_cfg, const struct mb_cfg *board_cfg,
44 bool half_populated)
45{
46 memcpy(&mem_cfg->RcompResistor, &board_cfg->rcomp_resistor,
47 sizeof(mem_cfg->RcompResistor));
48
49 memcpy(&mem_cfg->RcompTarget, &board_cfg->rcomp_targets,
50 sizeof(mem_cfg->RcompTarget));
51
52 memcpy(&mem_cfg->DqByteMapCh0, &board_cfg->dq_map[DDR_CH0],
53 sizeof(board_cfg->dq_map[DDR_CH0]));
54
55 memcpy(&mem_cfg->DqsMapCpu2DramCh0, &board_cfg->dqs_map[DDR_CH0],
56 sizeof(board_cfg->dqs_map[DDR_CH0]));
57
58 if (half_populated)
59 return;
60
61 memcpy(&mem_cfg->DqByteMapCh1, &board_cfg->dq_map[DDR_CH1],
62 sizeof(board_cfg->dq_map[DDR_CH1]));
63
64 memcpy(&mem_cfg->DqsMapCpu2DramCh1, &board_cfg->dqs_map[DDR_CH1],
65 sizeof(board_cfg->dqs_map[DDR_CH1]));
66}
67
68static void meminit_channels(FSP_M_CONFIG *mem_cfg, const struct mb_cfg *board_cfg,
69 uintptr_t spd_data_ptr, bool half_populated)
70{
71 /* Channel 0 */
72 mem_cfg->MemorySpdPtr00 = spd_data_ptr;
73 mem_cfg->MemorySpdPtr01 = 0;
74
75 if (half_populated) {
76 printk(BIOS_INFO, "%s: DRAM half-populated\n", __func__);
77 spd_data_ptr = 0;
78 }
79
80 /* Channel 1 */
81 mem_cfg->MemorySpdPtr10 = spd_data_ptr;
82 mem_cfg->MemorySpdPtr11 = 0;
83
84 meminit_dq_dqs_map(mem_cfg, board_cfg, half_populated);
85}
86
87/* Initialize onboard memory configurations for lpddr4x */
88void memcfg_init(FSP_M_CONFIG *mem_cfg, const struct mb_cfg *board_cfg,
89 const struct spd_info *spd_info, bool half_populated)
90{
91
92 if (spd_info->read_type == READ_SMBUS) {
93 for (int i = 0; i < NUM_DIMM_SLOT; i++)
94 mem_cfg->SpdAddressTable[i] = spd_info->spd_spec.spd_smbus_address[i];
95
96 meminit_dq_dqs_map(mem_cfg, board_cfg, half_populated);
97 } else {
98 uintptr_t spd_data_ptr = 0;
99 size_t spd_data_len = 0;
100 memset(&mem_cfg->SpdAddressTable, 0, sizeof(mem_cfg->SpdAddressTable));
101 get_spd_data(spd_info, &spd_data_ptr, &spd_data_len);
102 print_spd_info((unsigned char *)spd_data_ptr);
103
104 mem_cfg->MemorySpdDataLen = spd_data_len;
105 meminit_channels(mem_cfg, board_cfg, spd_data_ptr, half_populated);
106 }
107
108 /* Early Command Training Enabled */
109 mem_cfg->ECT = board_cfg->ect;
110
111 mem_cfg->UserBd = board_cfg->UserBd;
112}