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