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