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