xref: /rk3399_ARM-atf/drivers/st/ddr/phy/phyinit/src/ddrphy_phyinit_c_initphyconfig.c (revision 681296444e508e722565c6713effd2cf346a4dcf)
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