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