xref: /aosp_15_r20/external/coreboot/src/soc/intel/cannonlake/cnl_memcfg_init.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
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