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