blob: a66ef13c4e0115cdd711974de7c5ea4411bf0d57 [file] [log] [blame]
Angel Pons6bc13742020-04-05 15:46:38 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Aaron Durbinfc2e7412016-05-12 12:43:37 -05002#include <console/console.h>
Ravi Sarawadi15f6f3a2016-08-18 13:31:29 -07003#include <fsp/util.h>
4#include <memory_info.h>
Aaron Durbinfc2e7412016-05-12 12:43:37 -05005#include <soc/meminit.h>
Elyes Haouas72b41962022-07-07 12:15:50 +02006#include <stddef.h>
Brandon Breitensteinc31ba0e2016-07-27 17:34:45 -07007#include <fsp/soc_binding.h>
Aaron Durbinfc2e7412016-05-12 12:43:37 -05008#include <string.h>
9
Arthur Heymans6d6945b2018-12-29 14:00:46 +010010static size_t memory_size_mib;
Aaron Durbina695a732018-04-18 23:07:44 -060011
12size_t memory_in_system_in_mib(void)
13{
Arthur Heymans6d6945b2018-12-29 14:00:46 +010014 return memory_size_mib;
Aaron Durbina695a732018-04-18 23:07:44 -060015}
16
17static 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. */
Jamie Chenadda3992021-06-03 11:10:57 +080022 size_t sz = density;
Aaron Durbina695a732018-04-18 23:07:44 -060023
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
Arthur Heymans6d6945b2018-12-29 14:00:46 +010033 memory_size_mib += sz;
Aaron Durbina695a732018-04-18 23:07:44 -060034}
35
36size_t iohole_in_mib(void)
37{
38 return 2 * (GiB / MiB);
39}
40
John Zhaob3c27f02018-10-25 10:45:19 -070041static void set_lpddr4_defaults(FSP_M_CONFIG *cfg)
Aaron Durbinfc2e7412016-05-12 12:43:37 -050042{
Ravi Sarawadi577e41c2018-08-03 15:41:31 -070043 uint8_t odt_config;
44
Aaron Durbinfc2e7412016-05-12 12:43:37 -050045 /* 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;
Aaron Durbina695a732018-04-18 23:07:44 -060058 /* Field is in MiB units. */
59 cfg->LowMemoryMaxValue = iohole_in_mib();
Aaron Durbinfc2e7412016-05-12 12:43:37 -050060 /* 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
Ravi Sarawadia3d13fbd62017-04-25 19:30:58 -070094 /* Set CA ODT with default setting of ODT pins of LPDDR4 modules pulled
95 up to 1.1V. */
Ravi Sarawadi577e41c2018-08-03 15:41:31 -070096 odt_config = ODT_A_B_HIGH_HIGH;
97
Ravi Sarawadi577e41c2018-08-03 15:41:31 -070098 cfg->Ch0_OdtConfig = odt_config;
99 cfg->Ch1_OdtConfig = odt_config;
100 cfg->Ch2_OdtConfig = odt_config;
101 cfg->Ch3_OdtConfig = odt_config;
Aaron Durbinfc2e7412016-05-12 12:43:37 -0500102}
103
Aaron Durbinfd228e92018-03-16 12:55:58 -0600104struct speed_mapping {
105 int logical;
106 int fsp_value;
107};
Aaron Durbinfc2e7412016-05-12 12:43:37 -0500108
Aaron Durbinfd228e92018-03-16 12:55:58 -0600109struct fsp_speed_profiles {
110 const struct speed_mapping *mappings;
111 size_t num_mappings;
112};
113
114static 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
120static const struct fsp_speed_profiles apl_profile = {
121 .mappings = apl_mappings,
122 .num_mappings = ARRAY_SIZE(apl_mappings),
123};
124
125static 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
131static const struct fsp_speed_profiles glk_profile = {
132 .mappings = glk_mappings,
133 .num_mappings = ARRAY_SIZE(glk_mappings),
134};
135
136static const struct fsp_speed_profiles *get_fsp_profile(void)
137{
Angel Ponsb36100f2020-09-07 13:18:10 +0200138 if (CONFIG(SOC_INTEL_GEMINILAKE))
Aaron Durbinfd228e92018-03-16 12:55:58 -0600139 return &glk_profile;
140 else
141 return &apl_profile;
142}
143
144static 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;
Aaron Durbinfc2e7412016-05-12 12:43:37 -0500153 }
154
Aaron Durbinfd228e92018-03-16 12:55:58 -0600155 printk(BIOS_WARNING, "Invalid LPDDR4 speed: %d\n", speed);
156 /* Default to slowest speed */
157 return LP4_SPEED_1600;
158}
159
160static 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
174void meminit_lpddr4(FSP_M_CONFIG *cfg, int speed)
175{
176 speed = validate_speed(speed);
177
Aaron Durbinfc2e7412016-05-12 12:43:37 -0500178 printk(BIOS_INFO, "LP4DDR speed is %dMHz\n", speed);
Aaron Durbinfd228e92018-03-16 12:55:58 -0600179 cfg->Profile = fsp_memory_profile(speed);
Aaron Durbinfc2e7412016-05-12 12:43:37 -0500180
John Zhaob3c27f02018-10-25 10:45:19 -0700181 set_lpddr4_defaults(cfg);
Aaron Durbinfc2e7412016-05-12 12:43:37 -0500182}
183
Brandon Breitensteinc31ba0e2016-07-27 17:34:45 -0700184static void enable_logical_chan0(FSP_M_CONFIG *cfg,
Aaron Durbin48f662d2016-07-21 10:20:58 -0500185 int rank_density, int dual_rank,
Aaron Durbinfc2e7412016-05-12 12:43:37 -0500186 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;
Aaron Durbin17dbec12016-07-21 09:57:15 -0500191 int rank_mask;
Aaron Durbinfc2e7412016-05-12 12:43:37 -0500192
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 */
Aaron Durbin48f662d2016-07-21 10:20:58 -0500198 cfg->Ch0_DramDensity = rank_density;
199 cfg->Ch1_DramDensity = rank_density;
Aaron Durbin17dbec12016-07-21 09:57:15 -0500200 /* 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;
Aaron Durbinfc2e7412016-05-12 12:43:37 -0500204
205 /*
206 * CH0_DQB byte lanes in the bit swizzle configuration field are
207 * not 1:1. The mapping within the swizzling field is:
Jonathan Neuschäfer5268b762018-02-12 12:24:25 +0100208 * 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]
Aaron Durbinfc2e7412016-05-12 12:43:37 -0500212 */
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
Brandon Breitensteinc31ba0e2016-07-27 17:34:45 -0700229static void enable_logical_chan1(FSP_M_CONFIG *cfg,
Aaron Durbin48f662d2016-07-21 10:20:58 -0500230 int rank_density, int dual_rank,
Aaron Durbinfc2e7412016-05-12 12:43:37 -0500231 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;
Aaron Durbin17dbec12016-07-21 09:57:15 -0500236 int rank_mask;
Aaron Durbinfc2e7412016-05-12 12:43:37 -0500237
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 */
Aaron Durbin48f662d2016-07-21 10:20:58 -0500243 cfg->Ch2_DramDensity = rank_density;
244 cfg->Ch3_DramDensity = rank_density;
Aaron Durbin17dbec12016-07-21 09:57:15 -0500245 /* 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;
Aaron Durbinfc2e7412016-05-12 12:43:37 -0500249
250 /*
251 * CH1_DQB byte lanes in the bit swizzle configuration field are
252 * not 1:1. The mapping within the swizzling field is:
Jonathan Neuschäfer5268b762018-02-12 12:24:25 +0100253 * 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]
Aaron Durbinfc2e7412016-05-12 12:43:37 -0500257 */
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
Brandon Breitensteinc31ba0e2016-07-27 17:34:45 -0700274void meminit_lpddr4_enable_channel(FSP_M_CONFIG *cfg, int logical_chan,
Jamie Chenadda3992021-06-03 11:10:57 +0800275 int rank_density_gb, int dual_rank,
Aaron Durbinfc2e7412016-05-12 12:43:37 -0500276 const struct lpddr4_swizzle_cfg *scfg)
277{
Jamie Chenadda3992021-06-03 11:10:57 +0800278 int fsp_rank_density;
279
280 switch (rank_density_gb) {
Jamie Chend5d25552021-08-04 22:17:56 +0800281 case LP4_4Gb_DENSITY:
282 fsp_rank_density = 0;
283 break;
284 case LP4_6Gb_DENSITY:
285 fsp_rank_density = 1;
286 break;
Jamie Chenadda3992021-06-03 11:10:57 +0800287 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);
Aaron Durbinfc2e7412016-05-12 12:43:37 -0500298 return;
299 }
300
301 switch (logical_chan) {
302 case LP4_LCH0:
Jamie Chenadda3992021-06-03 11:10:57 +0800303 enable_logical_chan0(cfg, fsp_rank_density, dual_rank, scfg);
Aaron Durbinfc2e7412016-05-12 12:43:37 -0500304 break;
305 case LP4_LCH1:
Jamie Chenadda3992021-06-03 11:10:57 +0800306 enable_logical_chan1(cfg, fsp_rank_density, dual_rank, scfg);
Aaron Durbinfc2e7412016-05-12 12:43:37 -0500307 break;
308 default:
309 printk(BIOS_ERR, "Invalid logical channel: %d\n", logical_chan);
Aaron Durbina695a732018-04-18 23:07:44 -0600310 return;
Aaron Durbinfc2e7412016-05-12 12:43:37 -0500311 }
Jamie Chenadda3992021-06-03 11:10:57 +0800312 accumulate_channel_memory(rank_density_gb, dual_rank);
Aaron Durbinfc2e7412016-05-12 12:43:37 -0500313}
Aaron Durbin87579ae2016-07-06 22:45:57 -0500314
Brandon Breitensteinc31ba0e2016-07-27 17:34:45 -0700315void meminit_lpddr4_by_sku(FSP_M_CONFIG *cfg,
Aaron Durbin87579ae2016-07-06 22:45:57 -0500316 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
Aaron Durbin48f662d2016-07-21 10:20:58 -0500332 if (sku->ch0_rank_density) {
Jamie Chenadda3992021-06-03 11:10:57 +0800333 printk(BIOS_INFO, "LPDDR4 Ch0 density = %d Gb\n",
Aaron Durbin48f662d2016-07-21 10:20:58 -0500334 sku->ch0_rank_density);
335 meminit_lpddr4_enable_channel(cfg, LP4_LCH0,
336 sku->ch0_rank_density,
Aaron Durbin17dbec12016-07-21 09:57:15 -0500337 sku->ch0_dual_rank,
Aaron Durbin87579ae2016-07-06 22:45:57 -0500338 lpcfg->swizzle_config);
339 }
340
Aaron Durbin48f662d2016-07-21 10:20:58 -0500341 if (sku->ch1_rank_density) {
Jamie Chenadda3992021-06-03 11:10:57 +0800342 printk(BIOS_INFO, "LPDDR4 Ch1 density = %d Gb\n",
Aaron Durbin48f662d2016-07-21 10:20:58 -0500343 sku->ch1_rank_density);
344 meminit_lpddr4_enable_channel(cfg, LP4_LCH1,
345 sku->ch1_rank_density,
Aaron Durbin17dbec12016-07-21 09:57:15 -0500346 sku->ch1_dual_rank,
Aaron Durbin87579ae2016-07-06 22:45:57 -0500347 lpcfg->swizzle_config);
348 }
Andrey Petrovc42a9ac2016-08-25 11:06:08 -0700349
350 cfg->PeriodicRetrainingDisable = sku->disable_periodic_retraining;
Aaron Durbin87579ae2016-07-06 22:45:57 -0500351}
Ravi Sarawadi15f6f3a2016-08-18 13:31:29 -0700352
Ravi Sarawadia3d13fbd62017-04-25 19:30:58 -0700353uint8_t fsp_memory_soc_version(void)
354{
355 /* Bump this value when the memory configuration parameters change. */
356 return 1;
357}