1 /*
2 * Copyright (C) 2021-2024, STMicroelectronics - All Rights Reserved
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <stdlib.h>
8
9 #include <common/debug.h>
10
11 #include <ddrphy_phyinit.h>
12 #include <ddrphy_wrapper.h>
13
14 #include <lib/mmio.h>
15 #include <lib/utils_def.h>
16
17 #include <platform_def.h>
18
19 /*
20 * Program txslewrate:
21 * - txslewrate::txpredrvmode is dependent on dramtype.
22 * - txslewrate::txprep and txslewrate::txpren are technology-specific.
23 */
txslewrate_program(struct stm32mp_ddr_config * config)24 static void txslewrate_program(struct stm32mp_ddr_config *config)
25 {
26 uint32_t txpredrvmode;
27 uint32_t byte;
28 uint32_t txpren; /* Default to 0xf (max). Optimal setting is technology specific */
29 uint32_t txprep; /* Default to 0xf (max). Optimal setting is technology specific */
30 uint16_t txslewrate;
31
32 #if STM32MP_DDR3_TYPE
33 txpredrvmode = 0x3U;
34 #elif STM32MP_DDR4_TYPE
35 txpredrvmode = 0x2U;
36 #else /* STM32MP_LPDDR4_TYPE */
37 txpredrvmode = 0x1U;
38 #endif /* STM32MP_DDR3_TYPE */
39
40 txprep = config->uia.txslewrisedq;
41 txpren = config->uia.txslewfalldq;
42
43 txslewrate = (uint16_t)((txpredrvmode << CSR_TXPREDRVMODE_LSB) |
44 (txpren << CSR_TXPREN_LSB) |
45 (txprep << CSR_TXPREP_LSB));
46
47 for (byte = 0U; byte < config->uib.numdbyte; byte++) {
48 uint32_t c_addr;
49 uint32_t lane;
50
51 c_addr = byte << 12;
52 for (lane = 0U; lane <= B_MAX; lane++) {
53 uint32_t b_addr;
54
55 b_addr = lane << 8;
56 mmio_write_16((uintptr_t)(DDRPHYC_BASE + (4U * (TDBYTE | c_addr | b_addr |
57 CSR_TXSLEWRATE_ADDR))),
58 txslewrate);
59 }
60 }
61 }
62
63 /*
64 * Program atxslewrate:
65 * - atxslewrate::atxpredrvmode is dependent on dramtype and whether
66 * the ACX4 instance is used for AC or CK.
67 * - atxslewrate::atxprep and atxslewrate::atxpren are technology-specific.
68 */
atxslewrate_program(struct stm32mp_ddr_config * config)69 static void atxslewrate_program(struct stm32mp_ddr_config *config)
70 {
71 uint32_t anib;
72 uint32_t atxpren; /* Default to 0xf (max). Optimal setting is technology specific */
73 uint32_t atxprep; /* Default to 0xf (max). Optimal setting is technology specific */
74 uint32_t ck_anib_inst[2] = {0};
75
76 atxprep = config->uia.txslewriseac;
77 atxpren = config->uia.txslewfallac;
78
79 /*
80 * # of ANIBs CK ANIB Instance
81 * ACX8 ANIB 1
82 */
83 if (config->uib.numanib == 8U) {
84 ck_anib_inst[0] = 1U;
85 ck_anib_inst[1] = 1U;
86 }
87
88 for (anib = 0U; anib < config->uib.numanib; anib++) {
89 uint32_t atxpredrvmode;
90 uint32_t c_addr;
91 uint16_t atxslewrate;
92
93 c_addr = anib << 12;
94
95 if ((anib == ck_anib_inst[0]) || (anib == ck_anib_inst[1])) {
96 /* CK ANIB instance */
97 #if STM32MP_DDR3_TYPE || STM32MP_DDR4_TYPE
98 atxpredrvmode = 0x0U;
99 #else /* STM32MP_LPDDR4_TYPE */
100 atxpredrvmode = 0x1U;
101 #endif /* STM32MP_DDR3_TYPE || STM32MP_DDR4_TYPE */
102 } else {
103 /* non-CK ANIB instance */
104 #if STM32MP_DDR3_TYPE || STM32MP_DDR4_TYPE
105 atxpredrvmode = 0x3U;
106 #else /* STM32MP_LPDDR4_TYPE */
107 atxpredrvmode = 0x1U;
108 #endif /* STM32MP_DDR3_TYPE || STM32MP_DDR4_TYPE */
109 }
110
111 atxslewrate = (uint16_t)((atxpredrvmode << CSR_ATXPREDRVMODE_LSB) |
112 (atxpren << CSR_ATXPREN_LSB) |
113 (atxprep << CSR_ATXPREP_LSB));
114
115 mmio_write_16((uintptr_t)(DDRPHYC_BASE + (4U * (TANIB | c_addr |
116 CSR_ATXSLEWRATE_ADDR))),
117 atxslewrate);
118 }
119 }
120
121 #if STM32MP_DDR3_TYPE || STM32MP_DDR4_TYPE
122 /*
123 * Program dfirddatacsdestmap and dfiwrdatacsdestmap:
124 * - Dependencies: mb_ddr_1d->msgmisc[6] Determine Partial Rank Support.
125 */
dfidatacsdestmap_program(struct pmu_smb_ddr_1d * mb_ddr_1d)126 static void dfidatacsdestmap_program(struct pmu_smb_ddr_1d *mb_ddr_1d)
127 {
128 if ((mb_ddr_1d->msgmisc & 0x40U) != 0U) {
129 uint16_t dfirddatacsdestmap = 0xA0U;
130 uint16_t dfiwrdatacsdestmap = 0xA0U;
131
132 mmio_write_16((uintptr_t)(DDRPHYC_BASE + (4U * (TMASTER |
133 CSR_DFIRDDATACSDESTMAP_ADDR))),
134 dfirddatacsdestmap);
135 mmio_write_16((uintptr_t)(DDRPHYC_BASE + (4U * (TMASTER |
136 CSR_DFIWRDATACSDESTMAP_ADDR))),
137 dfiwrdatacsdestmap);
138 }
139 }
140 #endif /* STM32MP_DDR3_TYPE || STM32MP_DDR4_TYPE */
141
142 /*
143 * Program pllctrl2:
144 * - Calculate PLL controls from frequency.
145 */
pllctrl2_program(struct stm32mp_ddr_config * config)146 static void pllctrl2_program(struct stm32mp_ddr_config *config)
147 {
148 uint16_t pllctrl2;
149 uint32_t halffreq = config->uib.frequency / 2U;
150
151 if (halffreq < 235U) {
152 pllctrl2 = 0x7U;
153 } else if (halffreq < 313U) {
154 pllctrl2 = 0x6U;
155 } else if (halffreq < 469U) {
156 pllctrl2 = 0xBU;
157 } else if (halffreq < 625U) {
158 pllctrl2 = 0xAU;
159 } else if (halffreq < 938U) {
160 pllctrl2 = 0x19U;
161 } else if (halffreq < 1067U) {
162 pllctrl2 = 0x18U;
163 } else {
164 pllctrl2 = 0x19U;
165 }
166
167 mmio_write_16((uintptr_t)(DDRPHYC_BASE + (4U * (TMASTER | CSR_PLLCTRL2_ADDR))), pllctrl2);
168 }
169
170 /*
171 * Program ardptrinitval:
172 * - The values programmed here assume ideal properties of DfiClk and Pclk including:
173 * - DfiClk skew
174 * - DfiClk jitter
175 * - DfiClk PVT variations
176 * - Pclk skew
177 * - Pclk jitter
178 *
179 * ardptrinitval Programmed differently based on PLL Bypass mode and frequency:
180 * - PLL Bypassed mode:
181 * - For MemClk frequency > 933MHz, the valid range of ardptrinitval[3:0] is: 2-5
182 * - For MemClk frequency < 933MHz, the valid range of ardptrinitval[3:0] is: 1-5
183 * - PLL Enabled mode:
184 * - For MemClk frequency > 933MHz, the valid range of ardptrinitval[3:0] is: 1-5
185 * - For MemClk frequency < 933MHz, the valid range of ardptrinitval[3:0] is: 0-5
186 */
ardptrinitval_program(struct stm32mp_ddr_config * config,uint32_t * ardptrinitval)187 static void ardptrinitval_program(struct stm32mp_ddr_config *config, uint32_t *ardptrinitval)
188 {
189 uint16_t regdata;
190
191 if (config->uib.frequency >= 933U) {
192 regdata = 0x2U;
193 } else {
194 regdata = 0x1U;
195 }
196
197 /* Add one UI for synchronizer on SyncBus when PLL is bypassed */
198 if (config->uib.pllbypass == 1U) {
199 regdata++;
200 }
201
202 mmio_write_16((uintptr_t)(DDRPHYC_BASE + (4U * (TMASTER | CSR_ARDPTRINITVAL_ADDR))),
203 regdata);
204
205 *ardptrinitval = (uint32_t)regdata;
206 }
207
208 #if STM32MP_LPDDR4_TYPE
209 /*
210 * Program ProcOdtCtl:
211 * - Sets procodtalwayson/procodtalwaysoff for LPDDR4 using the PIE register seq0bgpr4.
212 */
procodtctl_program(void)213 static void procodtctl_program(void)
214 {
215 mmio_write_16((uintptr_t)(DDRPHYC_BASE + (4U * (TINITENG | C0 | CSR_SEQ0BGPR4_ADDR))), 0U);
216 }
217 #endif /* STM32MP_LPDDR4_TYPE */
218
219 /*
220 * Program dbytedllmodecntrl:
221 * - dllrxpreamblemode
222 * Program dqspreamblecontrol:
223 * - Fields:
224 * - twotckrxdqspre
225 * - twotcktxdqspre
226 * - positiondfeinit
227 * - lp4tgltwotcktxdqspre
228 * - lp4postambleext
229 * - lp4sttcprebridgerxen
230 * - Dependencies:
231 * - user_input_advanced.lp4rxpreamblemode (LPDDR4)
232 * - user_input_advanced.lp4postambleext (LPDDR4)
233 * - user_input_advanced.wdqsext (LPDDR4)
234 * - user_input_advanced.d4rxpreamblelength (DDR4)
235 * - user_input_advanced.d4txpreamblelength (DDR4)
236 */
dbytedllmodecntrl_program(struct stm32mp_ddr_config * config,uint32_t * twotckrxdqspre)237 static void dbytedllmodecntrl_program(struct stm32mp_ddr_config *config, uint32_t *twotckrxdqspre)
238 {
239 uint32_t disdllgainivseed = 1U;
240 uint32_t disdllseedsel = 0U;
241 uint32_t dllgainiv = 0x1U;
242 uint32_t dllgaintv = 0x6U;
243 uint32_t dllrxpreamblemode = 0U;
244 uint32_t lcdlseed0 = 0x21U;
245 uint32_t lp4postambleext = 0U;
246 uint32_t lp4sttcprebridgerxen = 0U;
247 uint32_t lp4tgltwotcktxdqspre = 0U;
248 uint32_t positiondfeinit;
249 uint32_t twotcktxdqspre = 0U;
250 uint32_t wdqsextension = 0U;
251 uint16_t dbytedllmodecntrl;
252 uint16_t dllgainctl;
253 uint16_t dlllockparam;
254 uint16_t dqspreamblecontrol;
255
256 #if STM32MP_DDR3_TYPE
257 /* Same as default */
258 *twotckrxdqspre = 0x0U;
259 lp4sttcprebridgerxen = 0x0U;
260 dllrxpreamblemode = 0x0U;
261 twotcktxdqspre = 0x0U;
262 lp4tgltwotcktxdqspre = 0x0U;
263 positiondfeinit = 0x0U;
264 lp4postambleext = 0x0U;
265 #elif STM32MP_DDR4_TYPE
266 *twotckrxdqspre = config->uia.d4rxpreamblelength;
267 lp4sttcprebridgerxen = 0x0U;
268 dllrxpreamblemode = 0x1U;
269 twotcktxdqspre = config->uia.d4txpreamblelength;
270 lp4tgltwotcktxdqspre = 0x0U;
271 positiondfeinit = 0x2U;
272 lp4postambleext = 0x0U;
273 #else /* STM32MP_LPDDR4_TYPE */
274 /* Set to 1 if static Rx preamble */
275 *twotckrxdqspre = (config->uia.lp4rxpreamblemode == 0U) ? 1U : 0U;
276 /* Set to 1 if static Rx preamble */
277 lp4sttcprebridgerxen = (config->uia.lp4rxpreamblemode == 0U) ? 1U : 0U;
278 dllrxpreamblemode = 0x1U;
279 /* Must be 2*Tck Tx preamble according to JEDEC (mr1.OP[2] = 1) */
280 twotcktxdqspre = 0x1U;
281 /* Must be toggling Tx preamble */
282 lp4tgltwotcktxdqspre = 0x1U;
283 positiondfeinit = 0x0U;
284 lp4postambleext = config->uia.lp4postambleext;
285 wdqsextension = config->uia.wdqsext;
286 #endif /* STM32MP_DDR3_TYPE */
287
288 dqspreamblecontrol = (uint16_t)((wdqsextension << CSR_WDQSEXTENSION_LSB) |
289 (lp4sttcprebridgerxen << CSR_LP4STTCPREBRIDGERXEN_LSB) |
290 (lp4postambleext << CSR_LP4POSTAMBLEEXT_LSB) |
291 (lp4tgltwotcktxdqspre << CSR_LP4TGLTWOTCKTXDQSPRE_LSB) |
292 (positiondfeinit << CSR_POSITIONDFEINIT_LSB) |
293 (twotcktxdqspre << CSR_TWOTCKTXDQSPRE_LSB) |
294 (*twotckrxdqspre << CSR_TWOTCKRXDQSPRE_LSB));
295
296 mmio_write_16((uintptr_t)(DDRPHYC_BASE + (4U * (TMASTER | CSR_DQSPREAMBLECONTROL_ADDR))),
297 dqspreamblecontrol);
298
299 dbytedllmodecntrl = (uint16_t)(dllrxpreamblemode << CSR_DLLRXPREAMBLEMODE_LSB);
300 mmio_write_16((uintptr_t)(DDRPHYC_BASE + (4U * (TMASTER | CSR_DBYTEDLLMODECNTRL_ADDR))),
301 dbytedllmodecntrl);
302
303 dllgainctl = (uint16_t)(dllgainiv | (dllgaintv << CSR_DLLGAINTV_LSB));
304 dlllockparam = (uint16_t)(disdllseedsel | (disdllgainivseed << CSR_DISDLLGAINIVSEED_LSB) |
305 (lcdlseed0 << CSR_LCDLSEED0_LSB));
306
307 mmio_write_16((uintptr_t)(DDRPHYC_BASE + (4U * (TMASTER | CSR_DLLLOCKPARAM_ADDR))),
308 dlllockparam);
309
310 mmio_write_16((uintptr_t)(DDRPHYC_BASE + (4U * (TMASTER | CSR_DLLGAINCTL_ADDR))),
311 dllgainctl);
312 }
313
314 /*
315 * Program procodttimectl:
316 * - Fields:
317 * - POdtStartDelay[3:2]
318 * - POdtTailWidth[1:0]
319 * - Dependencies:
320 * - user_input_basic.frequency
321 * - user_input_advanced.wdqsext
322 */
procodttimectl_program(struct stm32mp_ddr_config * config,uint32_t twotckrxdqspre)323 static void procodttimectl_program(struct stm32mp_ddr_config *config, uint32_t twotckrxdqspre)
324 {
325 uint16_t procodttimectl;
326
327 if (config->uia.wdqsext != 0U) {
328 /* POdtStartDelay = 0x0 and POdtTailWidth = 0x3 */
329 procodttimectl = 0x3U;
330 } else if (config->uib.frequency <= 933U) {
331 /* Memclk Freq <= 933MHz: POdtStartDelay = 0x2 and POdtTailWidth = 0x2 */
332 procodttimectl = 0xAU;
333 } else if (config->uib.frequency <= 1200U) {
334 /* 933MHz < Memclk Freq <= 1200MHz */
335 if (twotckrxdqspre == 1U) {
336 /* POdtStartDelay = 0x0 and POdtTailWidth = 0x2 */
337 procodttimectl = 0x2U;
338 } else {
339 /* POdtStartDelay = 0x1 and POdtTailWidth = 0x2 */
340 procodttimectl = 0x6U;
341 }
342 } else {
343 /* Memclk Freq > 1200MHz */
344 if (twotckrxdqspre == 1U) {
345 /* POdtStartDelay = 0x0 and POdtTailWidth = 0x3 */
346 procodttimectl = 0x3U;
347 } else {
348 /* POdtStartDelay = 0x1 and POdtTailWidth = 0x3 */
349 procodttimectl = 0x7U;
350 }
351 }
352
353 mmio_write_16((uintptr_t)(DDRPHYC_BASE + (4U * (TMASTER | CSR_PROCODTTIMECTL_ADDR))),
354 procodttimectl);
355 }
356
357 /*
358 * Program txodtdrvstren:
359 * - Fields:
360 * - ODTStrenP_px[5:0]
361 * - ODTStrenN_px[11:6]
362 * - Dependencies:
363 * - user_input_basic.numdbyte
364 * - user_input_advanced.odtimpedance
365 * \return 0 on success.
366 */
txodtdrvstren_program(struct stm32mp_ddr_config * config)367 static int txodtdrvstren_program(struct stm32mp_ddr_config *config)
368 {
369 uint32_t byte;
370 int odtstrenn_state;
371 int odtstrenp_state;
372 uint16_t txodtdrvstren;
373
374 odtstrenp_state = ddrphy_phyinit_mapdrvstren(config->uia.odtimpedance, ODTSTRENP);
375 if (odtstrenp_state < 0) {
376 return odtstrenp_state;
377 }
378
379 odtstrenn_state = ddrphy_phyinit_mapdrvstren(config->uia.odtimpedance, ODTSTRENN);
380 if (odtstrenn_state < 0) {
381 return odtstrenn_state;
382 }
383
384 txodtdrvstren = (uint16_t)((odtstrenn_state << CSR_ODTSTRENN_LSB) | odtstrenp_state);
385
386 for (byte = 0U; byte < config->uib.numdbyte; byte++) {
387 uint32_t c_addr;
388 uint32_t lane;
389
390 c_addr = byte << 12;
391 for (lane = 0U; lane <= B_MAX; lane++) {
392 uint32_t b_addr;
393
394 b_addr = lane << 8;
395 mmio_write_16((uintptr_t)(DDRPHYC_BASE + (4U * (TDBYTE | c_addr | b_addr |
396 CSR_TXODTDRVSTREN_ADDR))),
397 txodtdrvstren);
398 }
399 }
400
401 return 0;
402 }
403
404 /*
405 * Program tximpedancectrl1:
406 * - Fields:
407 * - DrvStrenFSDqP[5:0]
408 * - DrvStrenFSDqN[11:6]
409 * - Dependencies:
410 * - user_input_basic.numdbyte
411 * - user_input_advanced.tximpedance
412 * \return 0 on success.
413 */
tximpedancectrl1_program(struct stm32mp_ddr_config * config)414 static int tximpedancectrl1_program(struct stm32mp_ddr_config *config)
415 {
416 uint32_t byte;
417 int drvstrenfsdqn_state;
418 int drvstrenfsdqp_state;
419 uint16_t tximpedancectrl1;
420
421 drvstrenfsdqp_state = ddrphy_phyinit_mapdrvstren(config->uia.tximpedance,
422 DRVSTRENFSDQP);
423 if (drvstrenfsdqp_state < 0) {
424 return drvstrenfsdqp_state;
425 }
426
427 drvstrenfsdqn_state = ddrphy_phyinit_mapdrvstren(config->uia.tximpedance,
428 DRVSTRENFSDQN);
429 if (drvstrenfsdqn_state < 0) {
430 return drvstrenfsdqn_state;
431 }
432
433 tximpedancectrl1 = (uint16_t)((drvstrenfsdqn_state << CSR_DRVSTRENFSDQN_LSB) |
434 (drvstrenfsdqp_state << CSR_DRVSTRENFSDQP_LSB));
435
436 for (byte = 0U; byte < config->uib.numdbyte; byte++) {
437 uint32_t c_addr;
438 uint32_t lane;
439
440 c_addr = byte << 12;
441 for (lane = 0U; lane <= B_MAX; lane++) {
442 uint32_t b_addr;
443
444 b_addr = lane << 8;
445 mmio_write_16((uintptr_t)(DDRPHYC_BASE + (4U *
446 (TDBYTE | c_addr | b_addr |
447 CSR_TXIMPEDANCECTRL1_ADDR))),
448 tximpedancectrl1);
449 }
450 }
451
452 return 0;
453 }
454
455 /*
456 * Program atximpedance:
457 * - Fields:
458 * - ADrvStrenP[4:0]
459 * - ADrvStrenN[9:5]
460 * - Dependencies:
461 * - user_input_basic.numanib
462 * - user_input_advanced.atximpedance
463 * \return 0 on success.
464 */
atximpedance_program(struct stm32mp_ddr_config * config)465 static int atximpedance_program(struct stm32mp_ddr_config *config)
466 {
467 int adrvstrenn_state;
468 int adrvstrenp_state;
469 uint32_t anib;
470 uint16_t atximpedance;
471
472 adrvstrenp_state = ddrphy_phyinit_mapdrvstren(config->uia.atximpedance,
473 ADRVSTRENP);
474 if (adrvstrenp_state < 0) {
475 return adrvstrenp_state;
476 }
477
478 adrvstrenn_state = ddrphy_phyinit_mapdrvstren(config->uia.atximpedance,
479 ADRVSTRENN);
480 if (adrvstrenn_state < 0) {
481 return adrvstrenn_state;
482 }
483
484 atximpedance = (uint16_t)((adrvstrenn_state << CSR_ADRVSTRENN_LSB) |
485 (adrvstrenp_state << CSR_ADRVSTRENP_LSB));
486
487 for (anib = 0U; anib < config->uib.numanib; anib++) {
488 uint32_t c_addr;
489
490 c_addr = anib << 12;
491 mmio_write_16((uintptr_t)(DDRPHYC_BASE + (4U * (TANIB | c_addr |
492 CSR_ATXIMPEDANCE_ADDR))),
493 atximpedance);
494 }
495
496 return 0;
497 }
498
499 /*
500 * Program dfimode:
501 * - Dependencies:
502 * - user_input_basic.dfi1exists
503 */
dfimode_program(struct stm32mp_ddr_config * config)504 static void dfimode_program(struct stm32mp_ddr_config *config)
505 {
506 uint16_t dfimode = 0x5U;
507
508 #if STM32MP_DDR3_TYPE || STM32MP_DDR4_TYPE
509 if (config->uib.dfi1exists == 0U) {
510 dfimode = 0x1U; /* DFI1 does not physically exists */
511 }
512 #endif /* STM32MP_DDR3_TYPE || STM32MP_DDR4_TYPE */
513
514 mmio_write_16((uintptr_t)(DDRPHYC_BASE + (4U * (TMASTER | CSR_DFIMODE_ADDR))), dfimode);
515 }
516
517 /*
518 * Program dficamode:
519 * - Fields:
520 * - DfiLp3CAMode
521 * - DfiD4CAMode
522 * - DfiLp4CAMode
523 * - DfiD4AltCAMode
524 */
dficamode_program(void)525 static void dficamode_program(void)
526 {
527 uint16_t dficamode;
528
529 #if STM32MP_DDR3_TYPE
530 dficamode = 0U;
531 #elif STM32MP_DDR4_TYPE
532 dficamode = 2U;
533 #else /* STM32MP_LPDDR4_TYPE */
534 dficamode = 4U;
535 #endif /* STM32MP_DDR3_TYPE */
536
537 mmio_write_16((uintptr_t)(DDRPHYC_BASE + (4U * (TMASTER | CSR_DFICAMODE_ADDR))), dficamode);
538 }
539
540 /*
541 * Program caldrvstr0:
542 * - Fields:
543 * - caldrvstrpd50[3:0]
544 * - caldrvstrpu50[7:4]
545 * - Dependencies:
546 * - user_input_advanced.extcalresval
547 */
caldrvstr0_program(struct stm32mp_ddr_config * config)548 static void caldrvstr0_program(struct stm32mp_ddr_config *config)
549 {
550 uint16_t caldrvstr0;
551 uint16_t caldrvstrp50 = (uint16_t)config->uia.extcalresval;
552
553 caldrvstr0 = (caldrvstrp50 << CSR_CALDRVSTRPU50_LSB) | caldrvstrp50;
554
555 mmio_write_16((uintptr_t)(DDRPHYC_BASE + (4U * (TMASTER | CSR_CALDRVSTR0_ADDR))),
556 caldrvstr0);
557 }
558
559 /*
560 * Program CalUclkInfo:
561 * - Impedance calibration CLK Counter.
562 * - Fields:
563 * - caluclkticksper1us
564 * - Dependencies:
565 * - user_input_basic.frequency
566 */
caluclkinfo_program(struct stm32mp_ddr_config * config)567 static void caluclkinfo_program(struct stm32mp_ddr_config *config)
568 {
569 uint32_t caluclkticksper1us_x10;
570 uint16_t caluclkticksper1us;
571
572 /* Number of DfiClk cycles per 1us */
573 caluclkticksper1us_x10 = (10U * config->uib.frequency) / 2U;
574 caluclkticksper1us = (uint16_t)(caluclkticksper1us_x10 / 10U);
575
576 if ((config->uib.frequency % 2U) != 0U) {
577 caluclkticksper1us++;
578 }
579
580 if (caluclkticksper1us < 24U) {
581 /* Minimum value of caluclkticksper1us = 24 */
582 caluclkticksper1us = 24U;
583 }
584
585 mmio_write_16((uintptr_t)(DDRPHYC_BASE + (4U * (TMASTER | CSR_CALUCLKINFO_ADDR))),
586 caluclkticksper1us);
587 }
588
589 /*
590 * Program Calibration CSRs based on user input
591 * - Fields:
592 * - calinterval
593 * - calonce
594 * - Dependencies:
595 * - user_input_advanced.calinterval
596 * - user_input_advanced.calonce
597 */
calibration_program(struct stm32mp_ddr_config * config)598 static void calibration_program(struct stm32mp_ddr_config *config)
599 {
600 uint32_t calinterval;
601 uint32_t calonce;
602 uint16_t calrate;
603
604 calinterval = config->uia.calinterval;
605 calonce = config->uia.calonce;
606
607 calrate = (uint16_t)((calonce << CSR_CALONCE_LSB) | (calinterval << CSR_CALINTERVAL_LSB));
608
609 mmio_write_16((uintptr_t)(DDRPHYC_BASE + (4U * (TMASTER | CSR_CALRATE_ADDR))), calrate);
610 }
611
612 /*
613 * Program vrefinglobal:
614 * - dqdqsrcvcntrl and csrvrefinglobal to select Global VREF
615 * from Master to be used in each DQ.
616 * - Fields:
617 * - globalvrefinsel: Select Range of GlobalVref DAC. Default: set to 1.
618 * - globalvrefindac: Vref level is set based on mb_ddr_1d->phyvref value.
619 * The following formula is used to convert the phyvref into the register setting.
620 * \f{eqnarray*}{
621 * PhyVrefPrcnt &=& \frac{mb_ddr_1d->phyvref}{128} \\
622 * if globalvrefinsel = 1 :
623 * globalvrefindac &=& 1+\frac{PhyVrefPrcnt}{0.005} \\
624 * if globalvrefinsel = 0 :
625 * globalvrefindac &=& \frac{(PhyVrefPrcnt-0.345)}{0.005} \\
626 * RxVref &=& (globalvrefindac == 0) ? Hi-Z : (PhyVrefPrcnt \times VDDQ)
627 * \f}
628 *
629 * Program dqdqsrcvcntrl:
630 * - dqdqsrcvcntrl and csrvrefinglobal to select Global VREF
631 * from Master to be used in each DQ
632 * - Fields:
633 * - selanalogvref
634 * - majormodedbyte
635 * - ExtVrefRange
636 * - DfeCtrl
637 * - GainCurrAdj
638 * - Dependencies:
639 * - user_input_basic.numdbyte
640 */
vrefinglobal_program(struct stm32mp_ddr_config * config,struct pmu_smb_ddr_1d * mb_ddr_1d)641 static void vrefinglobal_program(struct stm32mp_ddr_config *config,
642 struct pmu_smb_ddr_1d *mb_ddr_1d)
643 {
644 uint32_t majormodedbyte;
645 int32_t vref_percentvddq = (int32_t)mb_ddr_1d->phyvref * 1000 * 100 / 128;
646 uint8_t globalvrefindac = 0x0U;
647 uint8_t globalvrefinsel = 0x4U;
648 uint32_t byte;
649 uint32_t dfectrl_defval = 0U;
650 uint32_t extvrefrange_defval = 0U;
651 uint32_t gaincurradj_defval = 0xBU;
652 uint32_t selanalogvref = 1U; /* Use Global VREF from Master */
653 uint16_t dqdqsrcvcntrl;
654 uint16_t vrefinglobal;
655
656 #if STM32MP_DDR3_TYPE
657 majormodedbyte = 0U;
658 #elif STM32MP_DDR4_TYPE
659 majormodedbyte = 3U;
660 #else /* STM32MP_LPDDR4_TYPE */
661 majormodedbyte = 2U;
662 #endif /* STM32MP_DDR3_TYPE */
663
664 /* Check range1 first. Only use range0 if customer input maxes out range1. */
665 globalvrefindac = (uint8_t)((vref_percentvddq / 500) + 1);
666 if (globalvrefindac > 127U) {
667 /* Min value is 1 */
668 globalvrefindac = (uint8_t)(MAX((vref_percentvddq - 34500), 500) / 500);
669 globalvrefinsel = 0x0U;
670 }
671 globalvrefindac = MIN(globalvrefindac, (uint8_t)127);
672
673 vrefinglobal = (uint16_t)((globalvrefindac << CSR_GLOBALVREFINDAC_LSB) | globalvrefinsel);
674 mmio_write_16((uintptr_t)(DDRPHYC_BASE + (4U * (TMASTER | CSR_VREFINGLOBAL_ADDR))),
675 vrefinglobal);
676
677 dqdqsrcvcntrl = (uint16_t)((gaincurradj_defval << CSR_GAINCURRADJ_LSB) |
678 (majormodedbyte << CSR_MAJORMODEDBYTE_LSB) |
679 (dfectrl_defval << CSR_DFECTRL_LSB) |
680 (extvrefrange_defval << CSR_EXTVREFRANGE_LSB) |
681 (selanalogvref << CSR_SELANALOGVREF_LSB));
682
683 for (byte = 0U; byte < config->uib.numdbyte; byte++) {
684 uint32_t c_addr;
685 uint32_t lane;
686
687 c_addr = byte << 12;
688 for (lane = 0U; lane <= B_MAX; lane++) {
689 uint32_t b_addr;
690
691 b_addr = lane << 8;
692 mmio_write_16((uintptr_t)(DDRPHYC_BASE + (4U * (TDBYTE | c_addr | b_addr |
693 CSR_DQDQSRCVCNTRL_ADDR))),
694 dqdqsrcvcntrl);
695 }
696 }
697 }
698
699 /*
700 * Program dfifreqratio :
701 * - Dependencies:
702 * - user_input_basic.dfifreqratio
703 */
dfifreqratio_program(struct stm32mp_ddr_config * config)704 static void dfifreqratio_program(struct stm32mp_ddr_config *config)
705 {
706 uint16_t dfifreqratio;
707
708 dfifreqratio = (uint16_t)config->uib.dfifreqratio;
709
710 mmio_write_16((uintptr_t)(DDRPHYC_BASE + (4U * (TMASTER | CSR_DFIFREQRATIO_ADDR))),
711 dfifreqratio);
712 }
713
714 /*
715 * Program tristatemodeca based on dramtype and 2T Timing
716 * - Fields:
717 * - CkDisVal
718 * - disdynadrtri
719 * - ddr2tmode
720 * - Dependencies:
721 * - user_input_advanced.is2ttiming
722 * - user_input_advanced.disdynadrtri
723 */
tristatemodeca_program(struct stm32mp_ddr_config * config)724 static void tristatemodeca_program(struct stm32mp_ddr_config *config)
725 {
726 uint32_t ckdisval_def;
727 uint32_t ddr2tmode;
728 uint32_t disdynadrtri;
729 uint16_t tristatemodeca;
730
731 /* CkDisVal depends on dramtype */
732 #if STM32MP_DDR3_TYPE || STM32MP_DDR4_TYPE
733 ckdisval_def = 1U; /* {CLK_t,CLK_c} = 2'b00; */
734 #else /* STM32MP_LPDDR4_TYPE */
735 ckdisval_def = 0U; /* {CLK_t,CLK_c} = 2'b01; */
736 #endif /* STM32MP_DDR3_TYPE || STM32MP_DDR4_TYPE */
737
738 #if STM32MP_DDR3_TYPE || STM32MP_DDR4_TYPE
739 disdynadrtri = config->uia.disdynadrtri;
740 #else /* STM32MP_LPDDR4_TYPE */
741 disdynadrtri = 1U;
742 #endif /* STM32MP_DDR3_TYPE || STM32MP_DDR4_TYPE */
743
744 ddr2tmode = config->uia.is2ttiming;
745
746 tristatemodeca = (uint16_t)((ckdisval_def << CSR_CKDISVAL_LSB) |
747 (ddr2tmode << CSR_DDR2TMODE_LSB) |
748 (disdynadrtri << CSR_DISDYNADRTRI_LSB));
749
750 mmio_write_16((uintptr_t)(DDRPHYC_BASE + (4U * (TMASTER | CSR_TRISTATEMODECA_ADDR))),
751 tristatemodeca);
752 }
753
754 /*
755 * Program DfiXlat based on Pll Bypass Input
756 * - Dependencies:
757 * - user_input_basic.frequency
758 * - user_input_basic.pllbypass
759 */
dfixlat_program(struct stm32mp_ddr_config * config)760 static void dfixlat_program(struct stm32mp_ddr_config *config)
761 {
762 uint16_t loopvector;
763 uint16_t pllbypass_dat = 0U;
764
765 pllbypass_dat |= (uint16_t)config->uib.pllbypass;
766
767 for (loopvector = 0U; loopvector < 8U; loopvector++) {
768 uint16_t dfifreqxlat_dat;
769 uintptr_t reg = (uintptr_t)(DDRPHYC_BASE + (4U * (C0 | TMASTER |
770 (CSR_DFIFREQXLAT0_ADDR +
771 loopvector))));
772
773 #if STM32MP_DDR3_TYPE || STM32MP_DDR4_TYPE
774 if (loopvector == 0U) {
775 /*
776 * Relock DfiFreq = 00,01,02,03) Use StartVec 5 (pll_enabled) or
777 * StartVec 6 (pll_bypassed).
778 */
779 dfifreqxlat_dat = pllbypass_dat + 0x5555U;
780
781 mmio_write_16(reg, dfifreqxlat_dat);
782 } else if (loopvector == 7U) {
783 /* LP3-entry DfiFreq = 1F */
784 mmio_write_16(reg, 0xF000U);
785 } else {
786 /*
787 * Everything else = skip retrain (could also map to 0000 since retrain
788 * code is excluded, but this is cleaner).
789 */
790 mmio_write_16(reg, 0x5555U);
791 }
792 #else /* STM32MP_LPDDR4_TYPE */
793 if (loopvector == 0U) {
794 uint16_t skipddc_dat = 0U; /*
795 * Set to vector offset based on frequency
796 * to disable dram drift compensation.
797 */
798
799 if (config->uib.frequency < 333U) {
800 skipddc_dat |= 0x5U;
801 }
802
803 /*
804 * Retrain & Relock DfiFreq = 00,01,02,03) Use StartVec 0 (pll_enabled) or
805 * StartVec 1 (pll_bypassed).
806 */
807 dfifreqxlat_dat = pllbypass_dat + skipddc_dat;
808 mmio_write_16(reg, dfifreqxlat_dat);
809 } else if (loopvector == 2U) {
810 /*
811 * Retrain only DfiFreq = 08,09,0A,0B) Use StartVec 4 (1, and maybe 2,3,
812 * used by verif).
813 */
814 mmio_write_16(reg, 0x4444U);
815 } else if (loopvector == 3U) {
816 /* Phymstr type state change, StartVec 8 */
817 mmio_write_16(reg, 0x8888U);
818 } else if (loopvector == 4U) {
819 /*
820 * Relock only DfiFreq = 10,11,12,13 Use StartVec 5 (pll_enabled) or
821 * StartVec 6 (pll_bypassed).
822 */
823 dfifreqxlat_dat = pllbypass_dat + 0x5555U;
824 mmio_write_16(reg, dfifreqxlat_dat);
825 } else if (loopvector == 7U) {
826 /* LP3-entry DfiFreq = 1F */
827 mmio_write_16(reg, 0xF000U);
828 } else {
829 /* Everything else */
830 mmio_write_16(reg, 0x0000U);
831 }
832 #endif /* STM32MP_DDR3_TYPE || STM32MP_DDR4_TYPE */
833 }
834 }
835
836 /*
837 * Program dqdqsrcvcntrl1 (Receiver Powerdown) and DbyteMiscMode
838 * - see function ddrphy_phyinit_isdbytedisabled() to determine
839 * which DBytes are turned off completely based on PHY configuration.
840 * - Fields:
841 * - DByteDisable
842 * - PowerDownRcvr
843 * - PowerDownRcvrDqs
844 * - RxPadStandbyEn
845 * - Dependencies:
846 * - user_input_basic.numdbyte
847 * - user_input_basic.dramdatawidth (DDR3/DDR4)
848 * - mb_ddr_1d->mr5 (DDR4)
849 * - user_input_advanced.lp4dbird (LPDDR4)
850 */
dqdqsrcvcntrl1_program(struct stm32mp_ddr_config * config,struct pmu_smb_ddr_1d * mb_ddr_1d)851 static void dqdqsrcvcntrl1_program(struct stm32mp_ddr_config *config,
852 struct pmu_smb_ddr_1d *mb_ddr_1d)
853 {
854 uint32_t d;
855 uint16_t mr5 __maybe_unused;
856 uint16_t regdata;
857 uint16_t regdata1;
858 uint16_t regdata2; /* Turn off Rx of DBI lane */
859
860 regdata = 0x1U << CSR_DBYTEDISABLE_LSB;
861
862 regdata1 = (0x1FFU << CSR_POWERDOWNRCVR_LSB) |
863 (0x1U << CSR_POWERDOWNRCVRDQS_LSB) |
864 (0x1U << CSR_RXPADSTANDBYEN_LSB);
865
866 regdata2 = (0x100U << CSR_POWERDOWNRCVR_LSB) | CSR_RXPADSTANDBYEN_MASK;
867
868 #if STM32MP_DDR4_TYPE
869 /* OR all mr4 masked values, to help check in next loop */
870 mr5 = (mb_ddr_1d->mr5 >> 12) & 0x1U;
871 #endif /* STM32MP_DDR4_TYPE */
872
873 for (d = 0U; d < config->uib.numdbyte; d++) {
874 uint32_t c_addr;
875
876 c_addr = d * C1;
877 if (ddrphy_phyinit_isdbytedisabled(config, mb_ddr_1d, d) != 0) {
878 mmio_write_16((uintptr_t)(DDRPHYC_BASE + (4U * (c_addr | TDBYTE |
879 CSR_DBYTEMISCMODE_ADDR))),
880 regdata);
881 mmio_write_16((uintptr_t)(DDRPHYC_BASE + (4U * (c_addr | TDBYTE |
882 CSR_DQDQSRCVCNTRL1_ADDR))),
883 regdata1);
884 } else {
885 /* Disable RDBI lane if not used. */
886 #if STM32MP_DDR3_TYPE
887 if (config->uib.dramdatawidth != 4U) {
888 #elif STM32MP_DDR4_TYPE
889 if ((config->uib.dramdatawidth != 4U) && (mr5 == 0U)) {
890 #else /* STM32MP_LPDDR4_TYPE */
891 if (config->uia.lp4dbird == 0U) {
892 #endif /* STM32MP_DDR3_TYPE */
893 mmio_write_16((uintptr_t)
894 (DDRPHYC_BASE + (4U * (c_addr | TDBYTE |
895 CSR_DQDQSRCVCNTRL1_ADDR))),
896 regdata2);
897 }
898 }
899 }
900 }
901
902 /*
903 * Program masterx4config
904 * - Fields:
905 * - x4tg
906 * - masterx4config
907 * - Dependencies:
908 * - user_input_basic.dramdatawidth
909 *
910 * \note PHY does not support mixed dram device data width
911 */
912 static void masterx4config_program(struct stm32mp_ddr_config *config)
913 {
914 uint32_t x4tg = 0U;
915 uint16_t masterx4config;
916
917 if (config->uib.dramdatawidth == 4U) {
918 x4tg = 0xFU;
919 }
920
921 masterx4config = (uint16_t)(x4tg << CSR_X4TG_LSB);
922
923 mmio_write_16((uintptr_t)(DDRPHYC_BASE + (4U * (TMASTER | CSR_MASTERX4CONFIG_ADDR))),
924 masterx4config);
925 }
926
927 #if !STM32MP_DDR3_TYPE
928 /*
929 * Program dmipinpresent based on dramtype and Read-DBI enable
930 * - Fields:
931 * - RdDbiEnabled
932 * - Dependencies:
933 * - mb_ddr_1d->mr5 (DDR4)
934 * - user_input_advanced.lp4dbird (LPDDR4)
935 */
936 static void dmipinpresent_program(struct stm32mp_ddr_config *config,
937 struct pmu_smb_ddr_1d *mb_ddr_1d)
938 {
939 uint16_t dmipinpresent;
940
941 #if STM32MP_DDR4_TYPE
942 /* For DDR4, Read DBI is enabled in mr5-A12 */
943 dmipinpresent = (mb_ddr_1d->mr5 >> 12) & 0x1U;
944 #else /* STM32MP_LPDDR4_TYPE */
945 dmipinpresent = (uint16_t)config->uia.lp4dbird;
946 #endif /* STM32MP_DDR4_TYPE */
947
948 mmio_write_16((uintptr_t)(DDRPHYC_BASE + (4U * (TMASTER | CSR_DMIPINPRESENT_ADDR))),
949 dmipinpresent);
950 }
951 #endif /* !STM32MP_DDR3_TYPE */
952
953 /*
954 * Program aforcetricont and acx4anibdis
955 * - Fields:
956 * - aforcetricont
957 * - acx4anibdis
958 * - Dependencies:
959 * - user_input_basic.numrank_dfi0
960 * - user_input_basic.numrank_dfi1
961 * - user_input_basic.numanib
962 * - user_input_advanced.disableunusedaddrlns
963 */
964 static void aforcetricont_acx4anibdis_program(struct stm32mp_ddr_config *config)
965 {
966 uint32_t anib;
967 uint16_t acx4anibdis = 0x0U;
968
969 for (anib = 0U; (anib < config->uib.numanib) && (config->uia.disableunusedaddrlns != 0U);
970 anib++) {
971 uint32_t c_addr;
972 #if STM32MP_DDR3_TYPE || STM32MP_DDR4_TYPE
973 uint32_t numrank = config->uib.numrank_dfi0 + config->uib.numrank_dfi1;
974 #else /* STM32MP_LPDDR4_TYPE */
975 uint32_t numrank0 = config->uib.numrank_dfi0;
976 uint32_t numrank1 = config->uib.numrank_dfi1;
977 #endif /* STM32MP_DDR3_TYPE || STM32MP_DDR4_TYPE */
978 uint16_t aforcetricont = 0x0U;
979
980 c_addr = anib << 12;
981
982 #if STM32MP_DDR3_TYPE || STM32MP_DDR4_TYPE
983 if ((anib == 0U) && (numrank == 1U)) {
984 aforcetricont = 0x2U;
985 } else if ((anib == 1U) && (numrank == 1U)) {
986 aforcetricont = 0xCU;
987 } else if (anib == 6U) {
988 aforcetricont = 0x1U;
989 }
990 #else /* STM32MP_LPDDR4_TYPE */
991 if ((anib == 0U) && (numrank0 == 0U)) {
992 aforcetricont = 0xFU;
993 } else if ((anib == 0U) && (numrank0 == 1U)) {
994 aforcetricont = 0x2U;
995 } else if ((anib == 1U) && (numrank0 == 0U)) {
996 aforcetricont = 0xFU;
997 } else if ((anib == 1U) && (numrank0 == 1U)) {
998 aforcetricont = 0x8U;
999 } else if ((anib == 2U) && (numrank0 == 0U)) {
1000 aforcetricont = 0xFU;
1001 } else if ((anib == 3U) && (numrank1 == 0U)) {
1002 aforcetricont = 0xFU;
1003 } else if ((anib == 3U) && (numrank1 == 1U)) {
1004 aforcetricont = 0x2U;
1005 } else if ((anib == 4U) && (numrank1 == 0U)) {
1006 aforcetricont = 0xFU;
1007 } else if ((anib == 4U) && (numrank1 == 1U)) {
1008 aforcetricont = 0x8U;
1009 } else if ((anib == 5U) && (numrank1 == 0U)) {
1010 aforcetricont = 0xFU;
1011 } else if (anib == 6U) {
1012 aforcetricont = 0xFU;
1013 } else if (anib == 7U) {
1014 aforcetricont = 0xFU;
1015 }
1016
1017 /*
1018 * If all the lanes can be disabled, and Anib is not the first or last disable
1019 * entire chiplet
1020 */
1021 if ((aforcetricont == 0xFU) && (anib != 0U) &&
1022 (anib != (config->uib.numanib - 1U))) {
1023 acx4anibdis = acx4anibdis | (0x1U << anib);
1024 }
1025 #endif /* STM32MP_DDR3_TYPE || STM32MP_DDR4_TYPE */
1026
1027 mmio_write_16((uintptr_t)(DDRPHYC_BASE + (4U * (TANIB | c_addr |
1028 CSR_AFORCETRICONT_ADDR))),
1029 aforcetricont);
1030 }
1031
1032 mmio_write_16((uintptr_t)(DDRPHYC_BASE + (4U * (TMASTER | CSR_ACX4ANIBDIS_ADDR))),
1033 acx4anibdis);
1034 }
1035
1036 /*
1037 * Implements Step C of initialization sequence
1038 *
1039 * This function programs majority of PHY configuration registers based
1040 * on data input into PhyInit data structures.
1041 *
1042 * This function programs PHY configuration registers based on information
1043 * provided in the PhyInit data structures (config->uib, config->uia).
1044 * The user can overwrite the programming of this function by modifying
1045 * ddrphy_phyinit_usercustom_custompretrain(). Please see
1046 * ddrphy_phyinit_struct.h for PhyInit data structure definition.
1047 *
1048 * \return 0 on success.
1049 */
1050 int ddrphy_phyinit_c_initphyconfig(struct stm32mp_ddr_config *config,
1051 struct pmu_smb_ddr_1d *mb_ddr_1d, uint32_t *ardptrinitval)
1052 {
1053 uint32_t twotckrxdqspre;
1054 int ret;
1055
1056 /*
1057 * Step (C) Initialize PHY Configuration
1058 * Load the required PHY configuration registers for the appropriate mode and memory
1059 * configuration.
1060 */
1061
1062 txslewrate_program(config);
1063
1064 atxslewrate_program(config);
1065
1066 #if STM32MP_DDR3_TYPE || STM32MP_DDR4_TYPE
1067 dfidatacsdestmap_program(mb_ddr_1d);
1068 #endif /* STM32MP_DDR3_TYPE || STM32MP_DDR4_TYPE */
1069
1070 pllctrl2_program(config);
1071
1072 ardptrinitval_program(config, ardptrinitval);
1073
1074 #if STM32MP_LPDDR4_TYPE
1075 procodtctl_program();
1076 #endif /* STM32MP_LPDDR4_TYPE */
1077
1078 dbytedllmodecntrl_program(config, &twotckrxdqspre);
1079
1080 procodttimectl_program(config, twotckrxdqspre);
1081
1082 ret = txodtdrvstren_program(config);
1083 if (ret != 0) {
1084 return ret;
1085 }
1086
1087 ret = tximpedancectrl1_program(config);
1088 if (ret != 0) {
1089 return ret;
1090 }
1091
1092 ret = atximpedance_program(config);
1093 if (ret != 0) {
1094 return ret;
1095 }
1096
1097 dfimode_program(config);
1098
1099 dficamode_program();
1100
1101 caldrvstr0_program(config);
1102
1103 caluclkinfo_program(config);
1104
1105 calibration_program(config);
1106
1107 vrefinglobal_program(config, mb_ddr_1d);
1108
1109 dfifreqratio_program(config);
1110
1111 tristatemodeca_program(config);
1112
1113 dfixlat_program(config);
1114
1115 dqdqsrcvcntrl1_program(config, mb_ddr_1d);
1116
1117 masterx4config_program(config);
1118
1119 #if !STM32MP_DDR3_TYPE
1120 dmipinpresent_program(config, mb_ddr_1d);
1121
1122 #if STM32MP_LPDDR4_TYPE
1123 /*
1124 * Program DFIPHYUPD
1125 * - Fields:
1126 * - DFIPHYUPDMODE
1127 * - DFIPHYUPDCNT
1128 * - Dependencies:
1129 * - user_input_advanced.disablephyupdate
1130 */
1131 if (config->uia.disablephyupdate != 0U) {
1132 mmio_write_16((uintptr_t)(DDRPHYC_BASE + (4U * (TMASTER | CSR_DFIPHYUPD_ADDR))),
1133 0x0U);
1134 }
1135 #endif /* STM32MP_LPDDR4_TYPE */
1136 #endif /* !STM32MP_DDR3_TYPE */
1137
1138 aforcetricont_acx4anibdis_program(config);
1139
1140 return 0;
1141 }
1142