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 */
ddrphy_phyinit_sequence(struct stm32mp_ddr_config * config,bool skip_training,bool reten)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