xref: /rk3399_ARM-atf/drivers/st/ddr/phy/phyinit/src/ddrphy_phyinit_sequence.c (revision eaaf26e3e6ac347cbfda00b6ba7d327e715d68f0)
1*79629b1aSNicolas Le Bayon /*
2*79629b1aSNicolas Le Bayon  * Copyright (C) 2021-2024, STMicroelectronics - All Rights Reserved
3*79629b1aSNicolas Le Bayon  *
4*79629b1aSNicolas Le Bayon  * SPDX-License-Identifier: BSD-3-Clause
5*79629b1aSNicolas Le Bayon  */
6*79629b1aSNicolas Le Bayon 
7*79629b1aSNicolas Le Bayon #include <arch_helpers.h>
8*79629b1aSNicolas Le Bayon 
9*79629b1aSNicolas Le Bayon #include <common/debug.h>
10*79629b1aSNicolas Le Bayon 
11*79629b1aSNicolas Le Bayon #include <ddrphy_phyinit.h>
12*79629b1aSNicolas Le Bayon 
13*79629b1aSNicolas Le Bayon /*
14*79629b1aSNicolas Le Bayon  * This function implements the flow of PhyInit software to initialize the PHY.
15*79629b1aSNicolas Le Bayon  *
16*79629b1aSNicolas Le Bayon  * The execution sequence follows the overview figure provided in the Reference Manual.
17*79629b1aSNicolas Le Bayon  *
18*79629b1aSNicolas Le Bayon  * \returns 0 on completion of the sequence, EXIT_FAILURE on error.
19*79629b1aSNicolas Le Bayon  */
ddrphy_phyinit_sequence(struct stm32mp_ddr_config * config,bool skip_training,bool reten)20*79629b1aSNicolas Le Bayon int ddrphy_phyinit_sequence(struct stm32mp_ddr_config *config, bool skip_training, bool reten)
21*79629b1aSNicolas Le Bayon {
22*79629b1aSNicolas Le Bayon 	int ret;
23*79629b1aSNicolas Le Bayon 	uint32_t ardptrinitval;	/*
24*79629b1aSNicolas Le Bayon 				 * Represents the value stored in Step C into the register with the
25*79629b1aSNicolas Le Bayon 				 * same name. Defined as a global variable so that implementation
26*79629b1aSNicolas Le Bayon 				 * of ddrphy_phyinit_progcsrskiptrain() function does not require
27*79629b1aSNicolas Le Bayon 				 * a PHY read register implementation.
28*79629b1aSNicolas Le Bayon 				 */
29*79629b1aSNicolas Le Bayon 	struct pmu_smb_ddr_1d mb_ddr_1d; /* Firmware 1D Message Block structure */
30*79629b1aSNicolas Le Bayon 
31*79629b1aSNicolas Le Bayon 	/* Check user input pstate number consistency vs. SW capabilities */
32*79629b1aSNicolas Le Bayon 	if (config->uib.numpstates > 1U) {
33*79629b1aSNicolas Le Bayon 		return -1;
34*79629b1aSNicolas Le Bayon 	}
35*79629b1aSNicolas Le Bayon 
36*79629b1aSNicolas Le Bayon 	/* Initialize structures */
37*79629b1aSNicolas Le Bayon 	ddrphy_phyinit_initstruct(config, &mb_ddr_1d);
38*79629b1aSNicolas Le Bayon 
39*79629b1aSNicolas Le Bayon 	/* Re-calculate Firmware Message Block input based on final user input */
40*79629b1aSNicolas Le Bayon 	ret = ddrphy_phyinit_calcmb(config, &mb_ddr_1d);
41*79629b1aSNicolas Le Bayon 	if (ret != 0) {
42*79629b1aSNicolas Le Bayon 		return ret;
43*79629b1aSNicolas Le Bayon 	}
44*79629b1aSNicolas Le Bayon 
45*79629b1aSNicolas Le Bayon 	/* (A) Bring up VDD, VDDQ, and VAA */
46*79629b1aSNicolas Le Bayon 	/* ddrphy_phyinit_usercustom_a_bringuppower(); */
47*79629b1aSNicolas Le Bayon 
48*79629b1aSNicolas Le Bayon 	/* (B) Start Clocks and Reset the PHY */
49*79629b1aSNicolas Le Bayon 	/* ddrphy_phyinit_usercustom_b_startclockresetphy(); */
50*79629b1aSNicolas Le Bayon 
51*79629b1aSNicolas Le Bayon 	/* (C) Initialize PHY Configuration */
52*79629b1aSNicolas Le Bayon 	ret = ddrphy_phyinit_c_initphyconfig(config, &mb_ddr_1d, &ardptrinitval);
53*79629b1aSNicolas Le Bayon 	if (ret != 0) {
54*79629b1aSNicolas Le Bayon 		return ret;
55*79629b1aSNicolas Le Bayon 	}
56*79629b1aSNicolas Le Bayon 	/*
57*79629b1aSNicolas Le Bayon 	 * Customize any register write desired; This can include any CSR not covered by PhyInit
58*79629b1aSNicolas Le Bayon 	 * or user wish to override values calculated in step_C.
59*79629b1aSNicolas Le Bayon 	 */
60*79629b1aSNicolas Le Bayon 	ddrphy_phyinit_usercustom_custompretrain(config);
61*79629b1aSNicolas Le Bayon 
62*79629b1aSNicolas Le Bayon 	/* Stop retention register tracking for training firmware related registers */
63*79629b1aSNicolas Le Bayon 	ret = ddrphy_phyinit_reginterface(STOPTRACK, 0U, 0U);
64*79629b1aSNicolas Le Bayon 	if (ret != 0) {
65*79629b1aSNicolas Le Bayon 		return ret;
66*79629b1aSNicolas Le Bayon 	}
67*79629b1aSNicolas Le Bayon 
68*79629b1aSNicolas Le Bayon 	if (skip_training) {
69*79629b1aSNicolas Le Bayon 		/* Skip running training firmware entirely */
70*79629b1aSNicolas Le Bayon 		ddrphy_phyinit_progcsrskiptrain(config, &mb_ddr_1d, ardptrinitval);
71*79629b1aSNicolas Le Bayon 	} else {
72*79629b1aSNicolas Le Bayon 		/* (D) Load the IMEM Memory for 1D training */
73*79629b1aSNicolas Le Bayon 		ddrphy_phyinit_d_loadimem();
74*79629b1aSNicolas Le Bayon 
75*79629b1aSNicolas Le Bayon 		/* (E) Set the PHY input clocks to the desired frequency */
76*79629b1aSNicolas Le Bayon 		/* ddrphy_phyinit_usercustom_e_setdficlk(pstate); */
77*79629b1aSNicolas Le Bayon 
78*79629b1aSNicolas Le Bayon 		/* (F) Write the Message Block parameters for the training firmware */
79*79629b1aSNicolas Le Bayon 		ret = ddrphy_phyinit_f_loaddmem(config, &mb_ddr_1d);
80*79629b1aSNicolas Le Bayon 		if (ret != 0) {
81*79629b1aSNicolas Le Bayon 			return ret;
82*79629b1aSNicolas Le Bayon 		}
83*79629b1aSNicolas Le Bayon 
84*79629b1aSNicolas Le Bayon 		/* (G) Execute the Training Firmware */
85*79629b1aSNicolas Le Bayon 		ret = ddrphy_phyinit_g_execfw();
86*79629b1aSNicolas Le Bayon 		if (ret != 0) {
87*79629b1aSNicolas Le Bayon 			return ret;
88*79629b1aSNicolas Le Bayon 		}
89*79629b1aSNicolas Le Bayon 
90*79629b1aSNicolas Le Bayon 		/* (H) Read the Message Block results */
91*79629b1aSNicolas Le Bayon 		/* ddrphy_phyinit_h_readmsgblock(); */
92*79629b1aSNicolas Le Bayon 	}
93*79629b1aSNicolas Le Bayon 
94*79629b1aSNicolas Le Bayon 	/* Start retention register tracking for training firmware related registers */
95*79629b1aSNicolas Le Bayon 	ret = ddrphy_phyinit_reginterface(STARTTRACK, 0U, 0U);
96*79629b1aSNicolas Le Bayon 	if (ret != 0) {
97*79629b1aSNicolas Le Bayon 		return ret;
98*79629b1aSNicolas Le Bayon 	}
99*79629b1aSNicolas Le Bayon 
100*79629b1aSNicolas Le Bayon 	/* (I) Load PHY Init Engine Image */
101*79629b1aSNicolas Le Bayon 	ddrphy_phyinit_i_loadpieimage(config, skip_training);
102*79629b1aSNicolas Le Bayon 
103*79629b1aSNicolas Le Bayon 	/*
104*79629b1aSNicolas Le Bayon 	 * Customize any CSR write desired to override values programmed by firmware or
105*79629b1aSNicolas Le Bayon 	 * ddrphy_phyinit_i_loadpieimage()
106*79629b1aSNicolas Le Bayon 	 */
107*79629b1aSNicolas Le Bayon 	/* ddrphy_phyinit_usercustom_customposttrain(); */
108*79629b1aSNicolas Le Bayon 
109*79629b1aSNicolas Le Bayon 	if (reten) {
110*79629b1aSNicolas Le Bayon 		/* Save value of tracked registers for retention restore sequence. */
111*79629b1aSNicolas Le Bayon 		ret = ddrphy_phyinit_usercustom_saveretregs(config);
112*79629b1aSNicolas Le Bayon 		if (ret != 0) {
113*79629b1aSNicolas Le Bayon 			return ret;
114*79629b1aSNicolas Le Bayon 		}
115*79629b1aSNicolas Le Bayon 	}
116*79629b1aSNicolas Le Bayon 
117*79629b1aSNicolas Le Bayon 	/* (J) Initialize the PHY to Mission Mode through DFI Initialization */
118*79629b1aSNicolas Le Bayon 	/* ddrphy_phyinit_usercustom_j_entermissionmode(); */
119*79629b1aSNicolas Le Bayon 
120*79629b1aSNicolas Le Bayon 	return 0;
121*79629b1aSNicolas Le Bayon }
122