1 /* SPDX-License-Identifier: GPL-2.0-only */
2 #include <console/console.h>
4 #include <memory_info.h>
5 #include <soc/meminit.h>
7 #include <fsp/soc_binding.h>
10 static size_t memory_size_mib
;
12 size_t memory_in_system_in_mib(void)
14 return memory_size_mib
;
17 static void accumulate_channel_memory(int density
, int dual_rank
)
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. */
24 /* Two DRAMs per channel. */
27 /* Two ranks per channel. */
33 memory_size_mib
+= sz
;
36 size_t iohole_in_mib(void)
38 return 2 * (GiB
/ MiB
);
41 static void set_lpddr4_defaults(FSP_M_CONFIG
*cfg
)
45 /* Enable memory down BGA since it's the only LPDDR4 packaging. */
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;
63 /* Always default to attempt to use saved training data. */
64 cfg
->DisableFastBoot
= 0;
66 /* LPDDR4 is memory down so no SPD addresses. */
67 cfg
->DIMM0SPDAddress
= 0;
68 cfg
->DIMM1SPDAddress
= 0;
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;
77 * Set the device width to x16 which is half a LPDDR4 module as that's
78 * what the reference code expects.
80 cfg
->Ch0_DeviceWidth
= 0x1;
81 cfg
->Ch1_DeviceWidth
= 0x1;
82 cfg
->Ch2_DeviceWidth
= 0x1;
83 cfg
->Ch3_DeviceWidth
= 0x1;
86 * Enable bank hashing (bit 1) and rank interleaving (bit 0) with
87 * a 1KiB address mapping (bits 5:4).
89 cfg
->Ch0_Option
= 0x3;
90 cfg
->Ch1_Option
= 0x3;
91 cfg
->Ch2_Option
= 0x3;
92 cfg
->Ch3_Option
= 0x3;
94 /* Set CA ODT with default setting of ODT pins of LPDDR4 modules pulled
96 odt_config
= ODT_A_B_HIGH_HIGH
;
98 cfg
->Ch0_OdtConfig
= odt_config
;
99 cfg
->Ch1_OdtConfig
= odt_config
;
100 cfg
->Ch2_OdtConfig
= odt_config
;
101 cfg
->Ch3_OdtConfig
= odt_config
;
104 struct speed_mapping
{
109 struct fsp_speed_profiles
{
110 const struct speed_mapping
*mappings
;
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 },
120 static const struct fsp_speed_profiles apl_profile
= {
121 .mappings
= apl_mappings
,
122 .num_mappings
= ARRAY_SIZE(apl_mappings
),
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 },
131 static const struct fsp_speed_profiles glk_profile
= {
132 .mappings
= glk_mappings
,
133 .num_mappings
= ARRAY_SIZE(glk_mappings
),
136 static const struct fsp_speed_profiles
*get_fsp_profile(void)
138 if (CONFIG(SOC_INTEL_GEMINILAKE
))
144 static int validate_speed(int speed
)
146 const struct fsp_speed_profiles
*fsp_profile
= get_fsp_profile();
149 for (i
= 0; i
< fsp_profile
->num_mappings
; i
++) {
150 /* Mapping exists. */
151 if (fsp_profile
->mappings
[i
].logical
== speed
)
155 printk(BIOS_WARNING
, "Invalid LPDDR4 speed: %d\n", speed
);
156 /* Default to slowest speed */
157 return LP4_SPEED_1600
;
160 static int fsp_memory_profile(int speed
)
162 const struct fsp_speed_profiles
*fsp_profile
= get_fsp_profile();
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
;
170 /* should never happen. */
174 void meminit_lpddr4(FSP_M_CONFIG
*cfg
, int speed
)
176 speed
= validate_speed(speed
);
178 printk(BIOS_INFO
, "LP4DDR speed is %dMHz\n", speed
);
179 cfg
->Profile
= fsp_memory_profile(speed
);
181 set_lpddr4_defaults(cfg
);
184 static void enable_logical_chan0(FSP_M_CONFIG
*cfg
,
185 int rank_density
, int dual_rank
,
186 const struct lpddr4_swizzle_cfg
*scfg
)
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
;
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.
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
;
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]
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
);
220 * CH0_DQA byte lanes in the bit swizzle configuration field are 1:1.
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
);
229 static void enable_logical_chan1(FSP_M_CONFIG
*cfg
,
230 int rank_density
, int dual_rank
,
231 const struct lpddr4_swizzle_cfg
*scfg
)
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
;
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.
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
;
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]
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
);
265 * CH1_DQA byte lanes in the bit swizzle configuration field are 1:1.
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
);
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
)
278 int fsp_rank_density
;
280 switch (rank_density_gb
) {
281 case LP4_4Gb_DENSITY
:
282 fsp_rank_density
= 0;
284 case LP4_6Gb_DENSITY
:
285 fsp_rank_density
= 1;
287 case LP4_8Gb_DENSITY
:
288 fsp_rank_density
= 2;
290 case LP4_12Gb_DENSITY
:
291 fsp_rank_density
= 3;
293 case LP4_16Gb_DENSITY
:
294 fsp_rank_density
= 4;
297 printk(BIOS_ERR
, "Invalid LPDDR4 density: %d Gb\n", rank_density_gb
);
301 switch (logical_chan
) {
303 enable_logical_chan0(cfg
, fsp_rank_density
, dual_rank
, scfg
);
306 enable_logical_chan1(cfg
, fsp_rank_density
, dual_rank
, scfg
);
309 printk(BIOS_ERR
, "Invalid logical channel: %d\n", logical_chan
);
312 accumulate_channel_memory(rank_density_gb
, dual_rank
);
315 void meminit_lpddr4_by_sku(FSP_M_CONFIG
*cfg
,
316 const struct lpddr4_cfg
*lpcfg
, size_t sku_id
)
318 const struct lpddr4_sku
*sku
;
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
);
326 printk(BIOS_INFO
, "LPDDR4 SKU id = 0x%zx\n", sku_id
);
328 sku
= &lpcfg
->skus
[sku_id
];
330 meminit_lpddr4(cfg
, sku
->speed
);
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
,
338 lpcfg
->swizzle_config
);
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
,
347 lpcfg
->swizzle_config
);
350 cfg
->PeriodicRetrainingDisable
= sku
->disable_periodic_retraining
;
353 uint8_t fsp_memory_soc_version(void)
355 /* Bump this value when the memory configuration parameters change. */