xref: /aosp_15_r20/external/coreboot/src/soc/intel/apollolake/meminit.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 #include <console/console.h>
3 #include <fsp/util.h>
4 #include <memory_info.h>
5 #include <soc/meminit.h>
6 #include <stddef.h>
7 #include <fsp/soc_binding.h>
8 #include <string.h>
9 
10 static size_t memory_size_mib;
11 
memory_in_system_in_mib(void)12 size_t memory_in_system_in_mib(void)
13 {
14 	return memory_size_mib;
15 }
16 
accumulate_channel_memory(int density,int dual_rank)17 static void accumulate_channel_memory(int density, int dual_rank)
18 {
19 	/* For this platform LPDDR4 memory is 4 DRAM parts that are x32. 2 of
20 	   the parts are composed into a x64 memory channel. Thus there are 2
21 	   channels composed of 2 DRAMs. */
22 	size_t sz = density;
23 
24 	/* Two DRAMs per channel. */
25 	sz *= 2;
26 
27 	/* Two ranks per channel. */
28 	if (dual_rank)
29 		sz *= 2;
30 
31 	sz *= GiB / MiB;
32 
33 	memory_size_mib += sz;
34 }
35 
iohole_in_mib(void)36 size_t iohole_in_mib(void)
37 {
38 	return 2 * (GiB / MiB);
39 }
40 
set_lpddr4_defaults(FSP_M_CONFIG * cfg)41 static void set_lpddr4_defaults(FSP_M_CONFIG *cfg)
42 {
43 	uint8_t odt_config;
44 
45 	/* Enable memory down BGA since it's the only LPDDR4 packaging. */
46 	cfg->Package = 1;
47 	cfg->MemoryDown = 1;
48 
49 	cfg->ScramblerSupport = 1;
50 	cfg->ChannelHashMask = 0x36;
51 	cfg->SliceHashMask = 0x9;
52 	cfg->InterleavedMode = 2;
53 	cfg->ChannelsSlicesEnable = 0;
54 	cfg->MinRefRate2xEnable = 0;
55 	cfg->DualRankSupportEnable = 1;
56 	/* Don't enforce a memory size limit. */
57 	cfg->MemorySizeLimit = 0;
58 	/* Field is in MiB units. */
59 	cfg->LowMemoryMaxValue = iohole_in_mib();
60 	/* No restrictions on memory above 4GiB */
61 	cfg->HighMemoryMaxValue = 0;
62 
63 	/* Always default to attempt to use saved training data. */
64 	cfg->DisableFastBoot = 0;
65 
66 	/* LPDDR4 is memory down so no SPD addresses. */
67 	cfg->DIMM0SPDAddress = 0;
68 	cfg->DIMM1SPDAddress = 0;
69 
70 	/* Clear all the rank enables. */
71 	cfg->Ch0_RankEnable = 0x0;
72 	cfg->Ch1_RankEnable = 0x0;
73 	cfg->Ch2_RankEnable = 0x0;
74 	cfg->Ch3_RankEnable = 0x0;
75 
76 	/*
77 	 * Set the device width to x16 which is half a LPDDR4 module as that's
78 	 * what the reference code expects.
79 	 */
80 	cfg->Ch0_DeviceWidth = 0x1;
81 	cfg->Ch1_DeviceWidth = 0x1;
82 	cfg->Ch2_DeviceWidth = 0x1;
83 	cfg->Ch3_DeviceWidth = 0x1;
84 
85 	/*
86 	 * Enable bank hashing (bit 1) and rank interleaving (bit 0) with
87 	 * a 1KiB address mapping (bits 5:4).
88 	 */
89 	cfg->Ch0_Option = 0x3;
90 	cfg->Ch1_Option = 0x3;
91 	cfg->Ch2_Option = 0x3;
92 	cfg->Ch3_Option = 0x3;
93 
94 	/* Set CA ODT with default setting of ODT pins of LPDDR4 modules pulled
95 	   up to 1.1V. */
96 	odt_config = ODT_A_B_HIGH_HIGH;
97 
98 	cfg->Ch0_OdtConfig = odt_config;
99 	cfg->Ch1_OdtConfig = odt_config;
100 	cfg->Ch2_OdtConfig = odt_config;
101 	cfg->Ch3_OdtConfig = odt_config;
102 }
103 
104 struct speed_mapping {
105 	int logical;
106 	int fsp_value;
107 };
108 
109 struct fsp_speed_profiles {
110 	const struct speed_mapping *mappings;
111 	size_t num_mappings;
112 };
113 
114 static const struct speed_mapping apl_mappings[] = {
115 	{ .logical = LP4_SPEED_1600, .fsp_value = 0x9 },
116 	{ .logical = LP4_SPEED_2133, .fsp_value = 0xa },
117 	{ .logical = LP4_SPEED_2400, .fsp_value = 0xb },
118 };
119 
120 static const struct fsp_speed_profiles apl_profile = {
121 	.mappings = apl_mappings,
122 	.num_mappings = ARRAY_SIZE(apl_mappings),
123 };
124 
125 static const struct speed_mapping glk_mappings[] = {
126 	{ .logical = LP4_SPEED_1600, .fsp_value = 0x4 },
127 	{ .logical = LP4_SPEED_2133, .fsp_value = 0x6 },
128 	{ .logical = LP4_SPEED_2400, .fsp_value = 0x7 },
129 };
130 
131 static const struct fsp_speed_profiles glk_profile = {
132 	.mappings = glk_mappings,
133 	.num_mappings = ARRAY_SIZE(glk_mappings),
134 };
135 
get_fsp_profile(void)136 static const struct fsp_speed_profiles *get_fsp_profile(void)
137 {
138 	if (CONFIG(SOC_INTEL_GEMINILAKE))
139 		return &glk_profile;
140 	else
141 		return &apl_profile;
142 }
143 
validate_speed(int speed)144 static int validate_speed(int speed)
145 {
146 	const struct fsp_speed_profiles *fsp_profile = get_fsp_profile();
147 	size_t i;
148 
149 	for (i = 0; i < fsp_profile->num_mappings; i++) {
150 		/* Mapping exists. */
151 		if (fsp_profile->mappings[i].logical == speed)
152 			return speed;
153 	}
154 
155 	printk(BIOS_WARNING, "Invalid LPDDR4 speed: %d\n", speed);
156 	/* Default to slowest speed */
157 	return LP4_SPEED_1600;
158 }
159 
fsp_memory_profile(int speed)160 static int fsp_memory_profile(int speed)
161 {
162 	const struct fsp_speed_profiles *fsp_profile = get_fsp_profile();
163 	size_t i;
164 
165 	for (i = 0; i < fsp_profile->num_mappings; i++) {
166 		if (fsp_profile->mappings[i].logical == speed)
167 			return fsp_profile->mappings[i].fsp_value;
168 	}
169 
170 	/* should never happen. */
171 	return -1;
172 }
173 
meminit_lpddr4(FSP_M_CONFIG * cfg,int speed)174 void meminit_lpddr4(FSP_M_CONFIG *cfg, int speed)
175 {
176 	speed = validate_speed(speed);
177 
178 	printk(BIOS_INFO, "LP4DDR speed is %dMHz\n", speed);
179 	cfg->Profile = fsp_memory_profile(speed);
180 
181 	set_lpddr4_defaults(cfg);
182 }
183 
enable_logical_chan0(FSP_M_CONFIG * cfg,int rank_density,int dual_rank,const struct lpddr4_swizzle_cfg * scfg)184 static void enable_logical_chan0(FSP_M_CONFIG *cfg,
185 					int rank_density, int dual_rank,
186 					const struct lpddr4_swizzle_cfg *scfg)
187 {
188 	const struct lpddr4_chan_swizzle_cfg *chan;
189 	/* Number of bytes to copy per DQS. */
190 	const size_t sz = DQ_BITS_PER_DQS;
191 	int rank_mask;
192 
193 	/*
194 	 * Logical channel 0 is comprised of physical channel 0 and 1.
195 	 * Physical channel 0 is comprised of the CH0_DQB signals.
196 	 * Physical channel 1 is comprised of the CH0_DQA signals.
197 	 */
198 	cfg->Ch0_DramDensity = rank_density;
199 	cfg->Ch1_DramDensity = rank_density;
200 	/* Enable ranks on both channels depending on dual rank option. */
201 	rank_mask = dual_rank ? 0x3 : 0x1;
202 	cfg->Ch0_RankEnable = rank_mask;
203 	cfg->Ch1_RankEnable = rank_mask;
204 
205 	/*
206 	 * CH0_DQB byte lanes in the bit swizzle configuration field are
207 	 * not 1:1. The mapping within the swizzling field is:
208 	 *   indices [0:7]   - byte lane 1 (DQS1) DQ[8:15]
209 	 *   indices [8:15]  - byte lane 0 (DQS0) DQ[0:7]
210 	 *   indices [16:23] - byte lane 3 (DQS3) DQ[24:31]
211 	 *   indices [24:31] - byte lane 2 (DQS2) DQ[16:23]
212 	 */
213 	chan = &scfg->phys[LP4_PHYS_CH0B];
214 	memcpy(&cfg->Ch0_Bit_swizzling[0], &chan->dqs[LP4_DQS1], sz);
215 	memcpy(&cfg->Ch0_Bit_swizzling[8], &chan->dqs[LP4_DQS0], sz);
216 	memcpy(&cfg->Ch0_Bit_swizzling[16], &chan->dqs[LP4_DQS3], sz);
217 	memcpy(&cfg->Ch0_Bit_swizzling[24], &chan->dqs[LP4_DQS2], sz);
218 
219 	/*
220 	 * CH0_DQA byte lanes in the bit swizzle configuration field are 1:1.
221 	 */
222 	chan = &scfg->phys[LP4_PHYS_CH0A];
223 	memcpy(&cfg->Ch1_Bit_swizzling[0], &chan->dqs[LP4_DQS0], sz);
224 	memcpy(&cfg->Ch1_Bit_swizzling[8], &chan->dqs[LP4_DQS1], sz);
225 	memcpy(&cfg->Ch1_Bit_swizzling[16], &chan->dqs[LP4_DQS2], sz);
226 	memcpy(&cfg->Ch1_Bit_swizzling[24], &chan->dqs[LP4_DQS3], sz);
227 }
228 
enable_logical_chan1(FSP_M_CONFIG * cfg,int rank_density,int dual_rank,const struct lpddr4_swizzle_cfg * scfg)229 static void enable_logical_chan1(FSP_M_CONFIG *cfg,
230 					int rank_density, int dual_rank,
231 					const struct lpddr4_swizzle_cfg *scfg)
232 {
233 	const struct lpddr4_chan_swizzle_cfg *chan;
234 	/* Number of bytes to copy per DQS. */
235 	const size_t sz = DQ_BITS_PER_DQS;
236 	int rank_mask;
237 
238 	/*
239 	 * Logical channel 1 is comprised of physical channel 2 and 3.
240 	 * Physical channel 2 is comprised of the CH1_DQB signals.
241 	 * Physical channel 3 is comprised of the CH1_DQA signals.
242 	 */
243 	cfg->Ch2_DramDensity = rank_density;
244 	cfg->Ch3_DramDensity = rank_density;
245 	/* Enable ranks on both channels depending on dual rank option. */
246 	rank_mask = dual_rank ? 0x3 : 0x1;
247 	cfg->Ch2_RankEnable = rank_mask;
248 	cfg->Ch3_RankEnable = rank_mask;
249 
250 	/*
251 	 * CH1_DQB byte lanes in the bit swizzle configuration field are
252 	 * not 1:1. The mapping within the swizzling field is:
253 	 *   indices [0:7]   - byte lane 1 (DQS1) DQ[8:15]
254 	 *   indices [8:15]  - byte lane 0 (DQS0) DQ[0:7]
255 	 *   indices [16:23] - byte lane 3 (DQS3) DQ[24:31]
256 	 *   indices [24:31] - byte lane 2 (DQS2) DQ[16:23]
257 	 */
258 	chan = &scfg->phys[LP4_PHYS_CH1B];
259 	memcpy(&cfg->Ch2_Bit_swizzling[0], &chan->dqs[LP4_DQS1], sz);
260 	memcpy(&cfg->Ch2_Bit_swizzling[8], &chan->dqs[LP4_DQS0], sz);
261 	memcpy(&cfg->Ch2_Bit_swizzling[16], &chan->dqs[LP4_DQS3], sz);
262 	memcpy(&cfg->Ch2_Bit_swizzling[24], &chan->dqs[LP4_DQS2], sz);
263 
264 	/*
265 	 * CH1_DQA byte lanes in the bit swizzle configuration field are 1:1.
266 	 */
267 	chan = &scfg->phys[LP4_PHYS_CH1A];
268 	memcpy(&cfg->Ch3_Bit_swizzling[0], &chan->dqs[LP4_DQS0], sz);
269 	memcpy(&cfg->Ch3_Bit_swizzling[8], &chan->dqs[LP4_DQS1], sz);
270 	memcpy(&cfg->Ch3_Bit_swizzling[16], &chan->dqs[LP4_DQS2], sz);
271 	memcpy(&cfg->Ch3_Bit_swizzling[24], &chan->dqs[LP4_DQS3], sz);
272 }
273 
meminit_lpddr4_enable_channel(FSP_M_CONFIG * cfg,int logical_chan,int rank_density_gb,int dual_rank,const struct lpddr4_swizzle_cfg * scfg)274 void meminit_lpddr4_enable_channel(FSP_M_CONFIG *cfg, int logical_chan,
275 					int rank_density_gb, int dual_rank,
276 					const struct lpddr4_swizzle_cfg *scfg)
277 {
278 	int fsp_rank_density;
279 
280 	switch (rank_density_gb) {
281 	case LP4_4Gb_DENSITY:
282 		fsp_rank_density = 0;
283 		break;
284 	case LP4_6Gb_DENSITY:
285 		fsp_rank_density = 1;
286 		break;
287 	case LP4_8Gb_DENSITY:
288 		fsp_rank_density = 2;
289 		break;
290 	case LP4_12Gb_DENSITY:
291 		fsp_rank_density = 3;
292 		break;
293 	case LP4_16Gb_DENSITY:
294 		fsp_rank_density = 4;
295 		break;
296 	default:
297 		printk(BIOS_ERR, "Invalid LPDDR4 density: %d Gb\n", rank_density_gb);
298 		return;
299 	}
300 
301 	switch (logical_chan) {
302 	case LP4_LCH0:
303 		enable_logical_chan0(cfg, fsp_rank_density, dual_rank, scfg);
304 		break;
305 	case LP4_LCH1:
306 		enable_logical_chan1(cfg, fsp_rank_density, dual_rank, scfg);
307 		break;
308 	default:
309 		printk(BIOS_ERR, "Invalid logical channel: %d\n", logical_chan);
310 		return;
311 	}
312 	accumulate_channel_memory(rank_density_gb, dual_rank);
313 }
314 
meminit_lpddr4_by_sku(FSP_M_CONFIG * cfg,const struct lpddr4_cfg * lpcfg,size_t sku_id)315 void meminit_lpddr4_by_sku(FSP_M_CONFIG *cfg,
316 				const struct lpddr4_cfg *lpcfg, size_t sku_id)
317 {
318 	const struct lpddr4_sku *sku;
319 
320 	if (sku_id >= lpcfg->num_skus) {
321 		printk(BIOS_ERR, "Too few LPDDR4 SKUs: 0x%zx/0x%zx\n",
322 			sku_id, lpcfg->num_skus);
323 		return;
324 	}
325 
326 	printk(BIOS_INFO, "LPDDR4 SKU id = 0x%zx\n", sku_id);
327 
328 	sku = &lpcfg->skus[sku_id];
329 
330 	meminit_lpddr4(cfg, sku->speed);
331 
332 	if (sku->ch0_rank_density) {
333 		printk(BIOS_INFO, "LPDDR4 Ch0 density = %d Gb\n",
334 			sku->ch0_rank_density);
335 		meminit_lpddr4_enable_channel(cfg, LP4_LCH0,
336 						sku->ch0_rank_density,
337 						sku->ch0_dual_rank,
338 						lpcfg->swizzle_config);
339 	}
340 
341 	if (sku->ch1_rank_density) {
342 		printk(BIOS_INFO, "LPDDR4 Ch1 density = %d Gb\n",
343 			sku->ch1_rank_density);
344 		meminit_lpddr4_enable_channel(cfg, LP4_LCH1,
345 						sku->ch1_rank_density,
346 						sku->ch1_dual_rank,
347 						lpcfg->swizzle_config);
348 	}
349 
350 	cfg->PeriodicRetrainingDisable = sku->disable_periodic_retraining;
351 }
352 
fsp_memory_soc_version(void)353 uint8_t fsp_memory_soc_version(void)
354 {
355 	/* Bump this value when the memory configuration parameters change. */
356 	return 1;
357 }
358