1 /* SPDX-License-Identifier: GPL-2.0-only */
2 #include <assert.h>
3 #include <console/console.h>
4 #include <fsp/util.h>
5 #include <soc/cnl_memcfg_init.h>
6 #include <spd_bin.h>
7 #include <string.h>
8
meminit_memcfg(FSP_M_CONFIG * mem_cfg,const struct cnl_mb_cfg * board_cfg)9 static void meminit_memcfg(FSP_M_CONFIG *mem_cfg,
10 const struct cnl_mb_cfg *board_cfg)
11 {
12 /*
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.
16 */
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]));
20
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]));
24
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]));
29
30 memcpy(&mem_cfg->RcompResistor, &board_cfg->rcomp_resistor,
31 sizeof(mem_cfg->RcompResistor));
32
33 /* Early cannonlake requires rcomp targets to be 0 */
34 memcpy(&mem_cfg->RcompTarget, &board_cfg->rcomp_targets,
35 sizeof(mem_cfg->RcompTarget));
36 }
37
38 /*
39 * Initialize default memory settings using spd data contained in a buffer.
40 */
meminit_spd_data(FSP_M_CONFIG * mem_cfg,uint8_t mem_slot,size_t spd_data_len,uintptr_t spd_data_ptr)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)
43 {
44 static size_t last_set_spd_data_len = 0;
45
46 assert(spd_data_ptr != 0 && spd_data_len != 0);
47
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");
51
52 mem_cfg->MemorySpdDataLen = spd_data_len;
53 last_set_spd_data_len = spd_data_len;
54
55 switch (mem_slot) {
56 case 0:
57 mem_cfg->MemorySpdPtr00 = spd_data_ptr;
58 break;
59 case 1:
60 mem_cfg->MemorySpdPtr01 = spd_data_ptr;
61 break;
62 case 2:
63 mem_cfg->MemorySpdPtr10 = spd_data_ptr;
64 break;
65 case 3:
66 mem_cfg->MemorySpdPtr11 = spd_data_ptr;
67 break;
68 default:
69 die("nonexistent memory slot");
70 }
71 printk(BIOS_INFO, "memory slot: %d configuration done.\n", mem_slot);
72 }
73
74 /*
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
77 * in spd/Makefile.mk.
78 */
meminit_cbfs_spd_index(FSP_M_CONFIG * mem_cfg,int spd_index,uint8_t mem_slot)79 static void meminit_cbfs_spd_index(FSP_M_CONFIG *mem_cfg,
80 int spd_index, uint8_t mem_slot)
81 {
82 static size_t spd_data_len;
83 static uintptr_t spd_data_ptr;
84 static int last_spd_index;
85
86 assert(mem_slot < NUM_DIMM_SLOT);
87
88 if ((spd_data_ptr == 0) || (last_spd_index != spd_index)) {
89 printk(BIOS_DEBUG, "SPD INDEX = %d\n", spd_index);
90
91 spd_data_ptr = spd_cbfs_map(spd_index);
92 if (!spd_data_ptr)
93 die("spd.bin not found or incorrect index\n");
94
95 spd_data_len = CONFIG_DIMM_SPD_SIZE;
96
97 /* Memory leak is ok since we have memory mapped boot media */
98 assert(CONFIG(BOOT_DEVICE_MEMORY_MAPPED));
99
100 last_spd_index = spd_index;
101 print_spd_info((unsigned char *)spd_data_ptr);
102 }
103
104 meminit_spd_data(mem_cfg, mem_slot, spd_data_len, spd_data_ptr);
105 }
106
107 /* Initialize onboard memory configurations for CannonLake */
cannonlake_memcfg_init(FSP_M_CONFIG * mem_cfg,const struct cnl_mb_cfg * cnl_cfg)108 void cannonlake_memcfg_init(FSP_M_CONFIG *mem_cfg,
109 const struct cnl_mb_cfg *cnl_cfg)
110 {
111 const struct spd_info *spdi;
112
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;
117
118 for (int i = 0; i < NUM_DIMM_SLOT; i++) {
119 spdi = &(cnl_cfg->spd[i]);
120 switch (spdi->read_type) {
121 case NOT_EXISTING:
122 break;
123 case READ_SMBUS:
124 mem_cfg->SpdAddressTable[i] =
125 spdi->spd_spec.spd_smbus_address;
126 break;
127 case READ_SPD_CBFS:
128 meminit_cbfs_spd_index(mem_cfg,
129 spdi->spd_spec.spd_index, i);
130 break;
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);
135 break;
136 default:
137 die("no valid way to read mem info");
138 }
139 }
140
141 meminit_memcfg(mem_cfg, cnl_cfg);
142 }
143