xref: /rk3399_ARM-atf/drivers/st/ddr/stm32mp2_ddr.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 <errno.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 #include <drivers/delay_timer.h>
14*79629b1aSNicolas Le Bayon #include <drivers/st/stm32mp2_ddr_helpers.h>
15*79629b1aSNicolas Le Bayon #include <drivers/st/stm32mp2_ddr_regs.h>
16*79629b1aSNicolas Le Bayon #include <drivers/st/stm32mp_ddr.h>
17*79629b1aSNicolas Le Bayon 
18*79629b1aSNicolas Le Bayon #include <lib/mmio.h>
19*79629b1aSNicolas Le Bayon 
20*79629b1aSNicolas Le Bayon #include <platform_def.h>
21*79629b1aSNicolas Le Bayon 
22*79629b1aSNicolas Le Bayon #define DDRDBG_FRAC_PLL_LOCK	U(0x10)
23*79629b1aSNicolas Le Bayon 
24*79629b1aSNicolas Le Bayon #define DDRCTL_REG(x, y, z)					\
25*79629b1aSNicolas Le Bayon 	{							\
26*79629b1aSNicolas Le Bayon 		.offset = offsetof(struct stm32mp_ddrctl, x),	\
27*79629b1aSNicolas Le Bayon 		.par_offset = offsetof(struct y, x),		\
28*79629b1aSNicolas Le Bayon 		.qd = z						\
29*79629b1aSNicolas Le Bayon 	}
30*79629b1aSNicolas Le Bayon 
31*79629b1aSNicolas Le Bayon /*
32*79629b1aSNicolas Le Bayon  * PARAMETERS: value get from device tree :
33*79629b1aSNicolas Le Bayon  *             size / order need to be aligned with binding
34*79629b1aSNicolas Le Bayon  *             modification NOT ALLOWED !!!
35*79629b1aSNicolas Le Bayon  */
36*79629b1aSNicolas Le Bayon #define DDRCTL_REG_REG_SIZE	48	/* st,ctl-reg */
37*79629b1aSNicolas Le Bayon #define DDRCTL_REG_TIMING_SIZE	20	/* st,ctl-timing */
38*79629b1aSNicolas Le Bayon #define DDRCTL_REG_MAP_SIZE	12	/* st,ctl-map */
39*79629b1aSNicolas Le Bayon #if STM32MP_DDR_DUAL_AXI_PORT
40*79629b1aSNicolas Le Bayon #define DDRCTL_REG_PERF_SIZE	21	/* st,ctl-perf */
41*79629b1aSNicolas Le Bayon #else /* !STM32MP_DDR_DUAL_AXI_PORT */
42*79629b1aSNicolas Le Bayon #define DDRCTL_REG_PERF_SIZE	14	/* st,ctl-perf */
43*79629b1aSNicolas Le Bayon #endif /* STM32MP_DDR_DUAL_AXI_PORT */
44*79629b1aSNicolas Le Bayon 
45*79629b1aSNicolas Le Bayon #define DDRPHY_REG_REG_SIZE	0	/* st,phy-reg */
46*79629b1aSNicolas Le Bayon #define	DDRPHY_REG_TIMING_SIZE	0	/* st,phy-timing */
47*79629b1aSNicolas Le Bayon 
48*79629b1aSNicolas Le Bayon #define DDRCTL_REG_REG(x, z)	DDRCTL_REG(x, stm32mp2_ddrctrl_reg, z)
49*79629b1aSNicolas Le Bayon static const struct stm32mp_ddr_reg_desc ddr_reg[DDRCTL_REG_REG_SIZE] = {
50*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(mstr, true),
51*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(mrctrl0, false),
52*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(mrctrl1, false),
53*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(mrctrl2, false),
54*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(derateen, true),
55*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(derateint, false),
56*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(deratectl, false),
57*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(pwrctl, false),
58*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(pwrtmg, true),
59*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(hwlpctl, true),
60*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(rfshctl0, false),
61*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(rfshctl1, false),
62*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(rfshctl3, true),
63*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(crcparctl0, false),
64*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(crcparctl1, false),
65*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(init0, true),
66*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(init1, false),
67*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(init2, false),
68*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(init3, true),
69*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(init4, true),
70*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(init5, false),
71*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(init6, true),
72*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(init7, true),
73*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(dimmctl, false),
74*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(rankctl, true),
75*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(rankctl1, true),
76*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(zqctl0, true),
77*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(zqctl1, false),
78*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(zqctl2, false),
79*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(dfitmg0, true),
80*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(dfitmg1, true),
81*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(dfilpcfg0, false),
82*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(dfilpcfg1, false),
83*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(dfiupd0, true),
84*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(dfiupd1, false),
85*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(dfiupd2, false),
86*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(dfimisc, true),
87*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(dfitmg2, true),
88*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(dfitmg3, false),
89*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(dbictl, true),
90*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(dfiphymstr, false),
91*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(dbg0, false),
92*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(dbg1, false),
93*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(dbgcmd, false),
94*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(swctl, false), /* forced qd value */
95*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(swctlstatic, false),
96*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(poisoncfg, false),
97*79629b1aSNicolas Le Bayon 	DDRCTL_REG_REG(pccfg, false),
98*79629b1aSNicolas Le Bayon };
99*79629b1aSNicolas Le Bayon 
100*79629b1aSNicolas Le Bayon #define DDRCTL_REG_TIMING(x, z)	DDRCTL_REG(x, stm32mp2_ddrctrl_timing, z)
101*79629b1aSNicolas Le Bayon static const struct stm32mp_ddr_reg_desc ddr_timing[DDRCTL_REG_TIMING_SIZE] = {
102*79629b1aSNicolas Le Bayon 	DDRCTL_REG_TIMING(rfshtmg, false),
103*79629b1aSNicolas Le Bayon 	DDRCTL_REG_TIMING(rfshtmg1, false),
104*79629b1aSNicolas Le Bayon 	DDRCTL_REG_TIMING(dramtmg0, true),
105*79629b1aSNicolas Le Bayon 	DDRCTL_REG_TIMING(dramtmg1, true),
106*79629b1aSNicolas Le Bayon 	DDRCTL_REG_TIMING(dramtmg2, true),
107*79629b1aSNicolas Le Bayon 	DDRCTL_REG_TIMING(dramtmg3, true),
108*79629b1aSNicolas Le Bayon 	DDRCTL_REG_TIMING(dramtmg4, true),
109*79629b1aSNicolas Le Bayon 	DDRCTL_REG_TIMING(dramtmg5, true),
110*79629b1aSNicolas Le Bayon 	DDRCTL_REG_TIMING(dramtmg6, true),
111*79629b1aSNicolas Le Bayon 	DDRCTL_REG_TIMING(dramtmg7, true),
112*79629b1aSNicolas Le Bayon 	DDRCTL_REG_TIMING(dramtmg8, true),
113*79629b1aSNicolas Le Bayon 	DDRCTL_REG_TIMING(dramtmg9, true),
114*79629b1aSNicolas Le Bayon 	DDRCTL_REG_TIMING(dramtmg10, true),
115*79629b1aSNicolas Le Bayon 	DDRCTL_REG_TIMING(dramtmg11, true),
116*79629b1aSNicolas Le Bayon 	DDRCTL_REG_TIMING(dramtmg12, true),
117*79629b1aSNicolas Le Bayon 	DDRCTL_REG_TIMING(dramtmg13, true),
118*79629b1aSNicolas Le Bayon 	DDRCTL_REG_TIMING(dramtmg14, true),
119*79629b1aSNicolas Le Bayon 	DDRCTL_REG_TIMING(dramtmg15, true),
120*79629b1aSNicolas Le Bayon 	DDRCTL_REG_TIMING(odtcfg, true),
121*79629b1aSNicolas Le Bayon 	DDRCTL_REG_TIMING(odtmap, false),
122*79629b1aSNicolas Le Bayon };
123*79629b1aSNicolas Le Bayon 
124*79629b1aSNicolas Le Bayon #define DDRCTL_REG_MAP(x)	DDRCTL_REG(x, stm32mp2_ddrctrl_map, false)
125*79629b1aSNicolas Le Bayon static const struct stm32mp_ddr_reg_desc ddr_map[DDRCTL_REG_MAP_SIZE] = {
126*79629b1aSNicolas Le Bayon 	DDRCTL_REG_MAP(addrmap0),
127*79629b1aSNicolas Le Bayon 	DDRCTL_REG_MAP(addrmap1),
128*79629b1aSNicolas Le Bayon 	DDRCTL_REG_MAP(addrmap2),
129*79629b1aSNicolas Le Bayon 	DDRCTL_REG_MAP(addrmap3),
130*79629b1aSNicolas Le Bayon 	DDRCTL_REG_MAP(addrmap4),
131*79629b1aSNicolas Le Bayon 	DDRCTL_REG_MAP(addrmap5),
132*79629b1aSNicolas Le Bayon 	DDRCTL_REG_MAP(addrmap6),
133*79629b1aSNicolas Le Bayon 	DDRCTL_REG_MAP(addrmap7),
134*79629b1aSNicolas Le Bayon 	DDRCTL_REG_MAP(addrmap8),
135*79629b1aSNicolas Le Bayon 	DDRCTL_REG_MAP(addrmap9),
136*79629b1aSNicolas Le Bayon 	DDRCTL_REG_MAP(addrmap10),
137*79629b1aSNicolas Le Bayon 	DDRCTL_REG_MAP(addrmap11),
138*79629b1aSNicolas Le Bayon };
139*79629b1aSNicolas Le Bayon 
140*79629b1aSNicolas Le Bayon #define DDRCTL_REG_PERF(x, z)	DDRCTL_REG(x, stm32mp2_ddrctrl_perf, z)
141*79629b1aSNicolas Le Bayon static const struct stm32mp_ddr_reg_desc ddr_perf[DDRCTL_REG_PERF_SIZE] = {
142*79629b1aSNicolas Le Bayon 	DDRCTL_REG_PERF(sched, true),
143*79629b1aSNicolas Le Bayon 	DDRCTL_REG_PERF(sched1, false),
144*79629b1aSNicolas Le Bayon 	DDRCTL_REG_PERF(perfhpr1, true),
145*79629b1aSNicolas Le Bayon 	DDRCTL_REG_PERF(perflpr1, true),
146*79629b1aSNicolas Le Bayon 	DDRCTL_REG_PERF(perfwr1, true),
147*79629b1aSNicolas Le Bayon 	DDRCTL_REG_PERF(sched3, false),
148*79629b1aSNicolas Le Bayon 	DDRCTL_REG_PERF(sched4, false),
149*79629b1aSNicolas Le Bayon 	DDRCTL_REG_PERF(pcfgr_0, false),
150*79629b1aSNicolas Le Bayon 	DDRCTL_REG_PERF(pcfgw_0, false),
151*79629b1aSNicolas Le Bayon 	DDRCTL_REG_PERF(pctrl_0, false),
152*79629b1aSNicolas Le Bayon 	DDRCTL_REG_PERF(pcfgqos0_0, true),
153*79629b1aSNicolas Le Bayon 	DDRCTL_REG_PERF(pcfgqos1_0, true),
154*79629b1aSNicolas Le Bayon 	DDRCTL_REG_PERF(pcfgwqos0_0, true),
155*79629b1aSNicolas Le Bayon 	DDRCTL_REG_PERF(pcfgwqos1_0, true),
156*79629b1aSNicolas Le Bayon #if STM32MP_DDR_DUAL_AXI_PORT
157*79629b1aSNicolas Le Bayon 	DDRCTL_REG_PERF(pcfgr_1, false),
158*79629b1aSNicolas Le Bayon 	DDRCTL_REG_PERF(pcfgw_1, false),
159*79629b1aSNicolas Le Bayon 	DDRCTL_REG_PERF(pctrl_1, false),
160*79629b1aSNicolas Le Bayon 	DDRCTL_REG_PERF(pcfgqos0_1, true),
161*79629b1aSNicolas Le Bayon 	DDRCTL_REG_PERF(pcfgqos1_1, true),
162*79629b1aSNicolas Le Bayon 	DDRCTL_REG_PERF(pcfgwqos0_1, true),
163*79629b1aSNicolas Le Bayon 	DDRCTL_REG_PERF(pcfgwqos1_1, true),
164*79629b1aSNicolas Le Bayon #endif /* STM32MP_DDR_DUAL_AXI_PORT */
165*79629b1aSNicolas Le Bayon };
166*79629b1aSNicolas Le Bayon 
167*79629b1aSNicolas Le Bayon static const struct stm32mp_ddr_reg_desc ddrphy_reg[DDRPHY_REG_REG_SIZE] = {};
168*79629b1aSNicolas Le Bayon 
169*79629b1aSNicolas Le Bayon static const struct stm32mp_ddr_reg_desc ddrphy_timing[DDRPHY_REG_TIMING_SIZE] = {};
170*79629b1aSNicolas Le Bayon 
171*79629b1aSNicolas Le Bayon /*
172*79629b1aSNicolas Le Bayon  * REGISTERS ARRAY: used to parse device tree and interactive mode
173*79629b1aSNicolas Le Bayon  */
174*79629b1aSNicolas Le Bayon static const struct stm32mp_ddr_reg_info ddr_registers[REG_TYPE_NB] __unused = {
175*79629b1aSNicolas Le Bayon 	[REG_REG] = {
176*79629b1aSNicolas Le Bayon 		.name = "static",
177*79629b1aSNicolas Le Bayon 		.desc = ddr_reg,
178*79629b1aSNicolas Le Bayon 		.size = DDRCTL_REG_REG_SIZE,
179*79629b1aSNicolas Le Bayon 		.base = DDR_BASE
180*79629b1aSNicolas Le Bayon 	},
181*79629b1aSNicolas Le Bayon 	[REG_TIMING] = {
182*79629b1aSNicolas Le Bayon 		.name = "timing",
183*79629b1aSNicolas Le Bayon 		.desc = ddr_timing,
184*79629b1aSNicolas Le Bayon 		.size = DDRCTL_REG_TIMING_SIZE,
185*79629b1aSNicolas Le Bayon 		.base = DDR_BASE
186*79629b1aSNicolas Le Bayon 	},
187*79629b1aSNicolas Le Bayon 	[REG_PERF] = {
188*79629b1aSNicolas Le Bayon 		.name = "perf",
189*79629b1aSNicolas Le Bayon 		.desc = ddr_perf,
190*79629b1aSNicolas Le Bayon 		.size = DDRCTL_REG_PERF_SIZE,
191*79629b1aSNicolas Le Bayon 		.base = DDR_BASE
192*79629b1aSNicolas Le Bayon 	},
193*79629b1aSNicolas Le Bayon 	[REG_MAP] = {
194*79629b1aSNicolas Le Bayon 		.name = "map",
195*79629b1aSNicolas Le Bayon 		.desc = ddr_map,
196*79629b1aSNicolas Le Bayon 		.size = DDRCTL_REG_MAP_SIZE,
197*79629b1aSNicolas Le Bayon 		.base = DDR_BASE
198*79629b1aSNicolas Le Bayon 	},
199*79629b1aSNicolas Le Bayon 	[REGPHY_REG] = {
200*79629b1aSNicolas Le Bayon 		.name = "static",
201*79629b1aSNicolas Le Bayon 		.desc = ddrphy_reg,
202*79629b1aSNicolas Le Bayon 		.size = DDRPHY_REG_REG_SIZE,
203*79629b1aSNicolas Le Bayon 		.base = DDRPHY_BASE
204*79629b1aSNicolas Le Bayon 	},
205*79629b1aSNicolas Le Bayon 	[REGPHY_TIMING] = {
206*79629b1aSNicolas Le Bayon 		.name = "timing",
207*79629b1aSNicolas Le Bayon 		.desc = ddrphy_timing,
208*79629b1aSNicolas Le Bayon 		.size = DDRPHY_REG_TIMING_SIZE,
209*79629b1aSNicolas Le Bayon 		.base = DDRPHY_BASE
210*79629b1aSNicolas Le Bayon 	},
211*79629b1aSNicolas Le Bayon };
212*79629b1aSNicolas Le Bayon 
ddr_reset(struct stm32mp_ddr_priv * priv)213*79629b1aSNicolas Le Bayon static void ddr_reset(struct stm32mp_ddr_priv *priv)
214*79629b1aSNicolas Le Bayon {
215*79629b1aSNicolas Le Bayon 	udelay(DDR_DELAY_1US);
216*79629b1aSNicolas Le Bayon 
217*79629b1aSNicolas Le Bayon 	mmio_setbits_32(priv->rcc + RCC_DDRITFCFGR, RCC_DDRITFCFGR_DDRRST);
218*79629b1aSNicolas Le Bayon 	mmio_write_32(priv->rcc + RCC_DDRPHYCAPBCFGR,
219*79629b1aSNicolas Le Bayon 		      RCC_DDRPHYCAPBCFGR_DDRPHYCAPBEN | RCC_DDRPHYCAPBCFGR_DDRPHYCAPBLPEN |
220*79629b1aSNicolas Le Bayon 		      RCC_DDRPHYCAPBCFGR_DDRPHYCAPBRST);
221*79629b1aSNicolas Le Bayon 	mmio_write_32(priv->rcc + RCC_DDRCAPBCFGR,
222*79629b1aSNicolas Le Bayon 		      RCC_DDRCAPBCFGR_DDRCAPBEN | RCC_DDRCAPBCFGR_DDRCAPBLPEN |
223*79629b1aSNicolas Le Bayon 		      RCC_DDRCAPBCFGR_DDRCAPBRST);
224*79629b1aSNicolas Le Bayon 	mmio_write_32(priv->rcc + RCC_DDRCFGR,
225*79629b1aSNicolas Le Bayon 		      RCC_DDRCFGR_DDRCFGEN | RCC_DDRCFGR_DDRCFGLPEN | RCC_DDRCFGR_DDRCFGRST);
226*79629b1aSNicolas Le Bayon 
227*79629b1aSNicolas Le Bayon 	udelay(DDR_DELAY_1US);
228*79629b1aSNicolas Le Bayon 
229*79629b1aSNicolas Le Bayon 	mmio_setbits_32(priv->rcc + RCC_DDRITFCFGR, RCC_DDRITFCFGR_DDRRST);
230*79629b1aSNicolas Le Bayon 	mmio_write_32(priv->rcc + RCC_DDRPHYCAPBCFGR,
231*79629b1aSNicolas Le Bayon 		      RCC_DDRPHYCAPBCFGR_DDRPHYCAPBEN | RCC_DDRPHYCAPBCFGR_DDRPHYCAPBLPEN);
232*79629b1aSNicolas Le Bayon 	mmio_write_32(priv->rcc + RCC_DDRCAPBCFGR,
233*79629b1aSNicolas Le Bayon 		      RCC_DDRCAPBCFGR_DDRCAPBEN | RCC_DDRCAPBCFGR_DDRCAPBLPEN);
234*79629b1aSNicolas Le Bayon 	mmio_write_32(priv->rcc + RCC_DDRCFGR, RCC_DDRCFGR_DDRCFGEN | RCC_DDRCFGR_DDRCFGLPEN);
235*79629b1aSNicolas Le Bayon 
236*79629b1aSNicolas Le Bayon 	udelay(DDR_DELAY_1US);
237*79629b1aSNicolas Le Bayon }
238*79629b1aSNicolas Le Bayon 
ddr_standby_reset(struct stm32mp_ddr_priv * priv)239*79629b1aSNicolas Le Bayon static void ddr_standby_reset(struct stm32mp_ddr_priv *priv)
240*79629b1aSNicolas Le Bayon {
241*79629b1aSNicolas Le Bayon 	udelay(DDR_DELAY_1US);
242*79629b1aSNicolas Le Bayon 
243*79629b1aSNicolas Le Bayon 	mmio_write_32(priv->rcc + RCC_DDRCPCFGR,
244*79629b1aSNicolas Le Bayon 		      RCC_DDRCPCFGR_DDRCPEN | RCC_DDRCPCFGR_DDRCPLPEN | RCC_DDRCPCFGR_DDRCPRST);
245*79629b1aSNicolas Le Bayon 	mmio_setbits_32(priv->rcc + RCC_DDRITFCFGR, RCC_DDRITFCFGR_DDRRST);
246*79629b1aSNicolas Le Bayon 	mmio_write_32(priv->rcc + RCC_DDRPHYCAPBCFGR,
247*79629b1aSNicolas Le Bayon 		      RCC_DDRPHYCAPBCFGR_DDRPHYCAPBEN | RCC_DDRPHYCAPBCFGR_DDRPHYCAPBLPEN |
248*79629b1aSNicolas Le Bayon 		      RCC_DDRPHYCAPBCFGR_DDRPHYCAPBRST);
249*79629b1aSNicolas Le Bayon 	mmio_write_32(priv->rcc + RCC_DDRCAPBCFGR,
250*79629b1aSNicolas Le Bayon 		      RCC_DDRCAPBCFGR_DDRCAPBEN | RCC_DDRCAPBCFGR_DDRCAPBLPEN |
251*79629b1aSNicolas Le Bayon 		      RCC_DDRCAPBCFGR_DDRCAPBRST);
252*79629b1aSNicolas Le Bayon 
253*79629b1aSNicolas Le Bayon 	mmio_clrbits_32(priv->rcc + RCC_DDRITFCFGR, RCC_DDRITFCFGR_DDRPHYDLP);
254*79629b1aSNicolas Le Bayon 	mmio_setbits_32(priv->rcc + RCC_DDRPHYCCFGR, RCC_DDRPHYCCFGR_DDRPHYCEN);
255*79629b1aSNicolas Le Bayon 
256*79629b1aSNicolas Le Bayon 	udelay(DDR_DELAY_1US);
257*79629b1aSNicolas Le Bayon }
258*79629b1aSNicolas Le Bayon 
ddr_standby_reset_release(struct stm32mp_ddr_priv * priv)259*79629b1aSNicolas Le Bayon static void ddr_standby_reset_release(struct stm32mp_ddr_priv *priv)
260*79629b1aSNicolas Le Bayon {
261*79629b1aSNicolas Le Bayon 	udelay(DDR_DELAY_1US);
262*79629b1aSNicolas Le Bayon 
263*79629b1aSNicolas Le Bayon 	mmio_write_32(priv->rcc + RCC_DDRCPCFGR, RCC_DDRCPCFGR_DDRCPEN | RCC_DDRCPCFGR_DDRCPLPEN);
264*79629b1aSNicolas Le Bayon 	mmio_clrbits_32(priv->rcc + RCC_DDRITFCFGR, RCC_DDRITFCFGR_DDRRST);
265*79629b1aSNicolas Le Bayon 	mmio_clrbits_32(priv->rcc + RCC_DDRPHYCAPBCFGR, RCC_DDRPHYCAPBCFGR_DDRPHYCAPBRST);
266*79629b1aSNicolas Le Bayon 	mmio_write_32(priv->rcc + RCC_DDRCFGR, RCC_DDRCFGR_DDRCFGEN | RCC_DDRCFGR_DDRCFGLPEN);
267*79629b1aSNicolas Le Bayon 
268*79629b1aSNicolas Le Bayon 	udelay(DDR_DELAY_1US);
269*79629b1aSNicolas Le Bayon }
270*79629b1aSNicolas Le Bayon 
ddr_sysconf_configuration(struct stm32mp_ddr_priv * priv,struct stm32mp_ddr_config * config)271*79629b1aSNicolas Le Bayon static void ddr_sysconf_configuration(struct stm32mp_ddr_priv *priv,
272*79629b1aSNicolas Le Bayon 				      struct stm32mp_ddr_config *config)
273*79629b1aSNicolas Le Bayon {
274*79629b1aSNicolas Le Bayon 	mmio_write_32(stm32_ddrdbg_get_base() + DDRDBG_LP_DISABLE,
275*79629b1aSNicolas Le Bayon 		      DDRDBG_LP_DISABLE_LPI_XPI_DISABLE | DDRDBG_LP_DISABLE_LPI_DDRC_DISABLE);
276*79629b1aSNicolas Le Bayon 
277*79629b1aSNicolas Le Bayon 	mmio_write_32(stm32_ddrdbg_get_base() + DDRDBG_BYPASS_PCLKEN,
278*79629b1aSNicolas Le Bayon 		      (uint32_t)config->uib.pllbypass);
279*79629b1aSNicolas Le Bayon 
280*79629b1aSNicolas Le Bayon 	mmio_write_32(priv->rcc + RCC_DDRPHYCCFGR, RCC_DDRPHYCCFGR_DDRPHYCEN);
281*79629b1aSNicolas Le Bayon 	mmio_setbits_32(priv->rcc + RCC_DDRITFCFGR, RCC_DDRITFCFGR_DDRRST);
282*79629b1aSNicolas Le Bayon 
283*79629b1aSNicolas Le Bayon 	udelay(DDR_DELAY_1US);
284*79629b1aSNicolas Le Bayon }
285*79629b1aSNicolas Le Bayon 
set_dfi_init_complete_en(struct stm32mp_ddrctl * ctl,bool phy_init_done)286*79629b1aSNicolas Le Bayon static void set_dfi_init_complete_en(struct stm32mp_ddrctl *ctl, bool phy_init_done)
287*79629b1aSNicolas Le Bayon {
288*79629b1aSNicolas Le Bayon 	/*
289*79629b1aSNicolas Le Bayon 	 * Manage quasi-dynamic registers modification
290*79629b1aSNicolas Le Bayon 	 * dfimisc.dfi_init_complete_en : Group 3
291*79629b1aSNicolas Le Bayon 	 */
292*79629b1aSNicolas Le Bayon 	stm32mp_ddr_set_qd3_update_conditions(ctl);
293*79629b1aSNicolas Le Bayon 
294*79629b1aSNicolas Le Bayon 	udelay(DDR_DELAY_1US);
295*79629b1aSNicolas Le Bayon 
296*79629b1aSNicolas Le Bayon 	if (phy_init_done) {
297*79629b1aSNicolas Le Bayon 		/* Indicates to controller that PHY has completed initialization */
298*79629b1aSNicolas Le Bayon 		mmio_setbits_32((uintptr_t)&ctl->dfimisc, DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN);
299*79629b1aSNicolas Le Bayon 	} else {
300*79629b1aSNicolas Le Bayon 		/* PHY not initialized yet, wait for completion */
301*79629b1aSNicolas Le Bayon 		mmio_clrbits_32((uintptr_t)&ctl->dfimisc, DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN);
302*79629b1aSNicolas Le Bayon 	}
303*79629b1aSNicolas Le Bayon 
304*79629b1aSNicolas Le Bayon 	udelay(DDR_DELAY_1US);
305*79629b1aSNicolas Le Bayon 
306*79629b1aSNicolas Le Bayon 	stm32mp_ddr_unset_qd3_update_conditions(ctl);
307*79629b1aSNicolas Le Bayon 
308*79629b1aSNicolas Le Bayon }
309*79629b1aSNicolas Le Bayon 
disable_refresh(struct stm32mp_ddrctl * ctl)310*79629b1aSNicolas Le Bayon static void disable_refresh(struct stm32mp_ddrctl *ctl)
311*79629b1aSNicolas Le Bayon {
312*79629b1aSNicolas Le Bayon 	mmio_setbits_32((uintptr_t)&ctl->rfshctl3, DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH);
313*79629b1aSNicolas Le Bayon 
314*79629b1aSNicolas Le Bayon 	stm32mp_ddr_wait_refresh_update_done_ack(ctl);
315*79629b1aSNicolas Le Bayon 
316*79629b1aSNicolas Le Bayon 	udelay(DDR_DELAY_1US);
317*79629b1aSNicolas Le Bayon 
318*79629b1aSNicolas Le Bayon 	mmio_clrbits_32((uintptr_t)&ctl->pwrctl,
319*79629b1aSNicolas Le Bayon 			DDRCTRL_PWRCTL_POWERDOWN_EN | DDRCTRL_PWRCTL_SELFREF_EN);
320*79629b1aSNicolas Le Bayon 
321*79629b1aSNicolas Le Bayon 	udelay(DDR_DELAY_1US);
322*79629b1aSNicolas Le Bayon 
323*79629b1aSNicolas Le Bayon 	set_dfi_init_complete_en(ctl, false);
324*79629b1aSNicolas Le Bayon }
325*79629b1aSNicolas Le Bayon 
restore_refresh(struct stm32mp_ddrctl * ctl,uint32_t rfshctl3,uint32_t pwrctl)326*79629b1aSNicolas Le Bayon static void restore_refresh(struct stm32mp_ddrctl *ctl, uint32_t rfshctl3, uint32_t pwrctl)
327*79629b1aSNicolas Le Bayon {
328*79629b1aSNicolas Le Bayon 	if ((rfshctl3 & DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH) == 0U) {
329*79629b1aSNicolas Le Bayon 		mmio_clrbits_32((uintptr_t)&ctl->rfshctl3, DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH);
330*79629b1aSNicolas Le Bayon 
331*79629b1aSNicolas Le Bayon 		stm32mp_ddr_wait_refresh_update_done_ack(ctl);
332*79629b1aSNicolas Le Bayon 
333*79629b1aSNicolas Le Bayon 		udelay(DDR_DELAY_1US);
334*79629b1aSNicolas Le Bayon 	}
335*79629b1aSNicolas Le Bayon 
336*79629b1aSNicolas Le Bayon 	if ((pwrctl & DDRCTRL_PWRCTL_SELFREF_SW) != 0U) {
337*79629b1aSNicolas Le Bayon 		mmio_clrbits_32((uintptr_t)&ctl->pwrctl, DDRCTRL_PWRCTL_SELFREF_SW);
338*79629b1aSNicolas Le Bayon 
339*79629b1aSNicolas Le Bayon 		udelay(DDR_DELAY_1US);
340*79629b1aSNicolas Le Bayon 	}
341*79629b1aSNicolas Le Bayon 
342*79629b1aSNicolas Le Bayon 	if ((pwrctl & DDRCTRL_PWRCTL_POWERDOWN_EN) != 0U) {
343*79629b1aSNicolas Le Bayon 		mmio_setbits_32((uintptr_t)&ctl->pwrctl, DDRCTRL_PWRCTL_POWERDOWN_EN);
344*79629b1aSNicolas Le Bayon 
345*79629b1aSNicolas Le Bayon 		udelay(DDR_DELAY_1US);
346*79629b1aSNicolas Le Bayon 	}
347*79629b1aSNicolas Le Bayon 
348*79629b1aSNicolas Le Bayon 	if ((pwrctl & DDRCTRL_PWRCTL_SELFREF_EN) != 0U) {
349*79629b1aSNicolas Le Bayon 		mmio_setbits_32((uintptr_t)&ctl->pwrctl, DDRCTRL_PWRCTL_SELFREF_EN);
350*79629b1aSNicolas Le Bayon 
351*79629b1aSNicolas Le Bayon 		udelay(DDR_DELAY_1US);
352*79629b1aSNicolas Le Bayon 	}
353*79629b1aSNicolas Le Bayon 
354*79629b1aSNicolas Le Bayon 	set_dfi_init_complete_en(ctl, true);
355*79629b1aSNicolas Le Bayon }
356*79629b1aSNicolas Le Bayon 
stm32mp2_ddr_init(struct stm32mp_ddr_priv * priv,struct stm32mp_ddr_config * config)357*79629b1aSNicolas Le Bayon void stm32mp2_ddr_init(struct stm32mp_ddr_priv *priv,
358*79629b1aSNicolas Le Bayon 		       struct stm32mp_ddr_config *config)
359*79629b1aSNicolas Le Bayon {
360*79629b1aSNicolas Le Bayon 	int ret = -EINVAL;
361*79629b1aSNicolas Le Bayon 	uint32_t ddr_retdis;
362*79629b1aSNicolas Le Bayon 	enum ddr_type ddr_type;
363*79629b1aSNicolas Le Bayon 
364*79629b1aSNicolas Le Bayon 	if ((config->c_reg.mstr & DDRCTRL_MSTR_DDR3) != 0U) {
365*79629b1aSNicolas Le Bayon 		ddr_type = STM32MP_DDR3;
366*79629b1aSNicolas Le Bayon 	} else if ((config->c_reg.mstr & DDRCTRL_MSTR_DDR4) != 0U) {
367*79629b1aSNicolas Le Bayon 		ddr_type = STM32MP_DDR4;
368*79629b1aSNicolas Le Bayon 	} else if ((config->c_reg.mstr & DDRCTRL_MSTR_LPDDR4) != 0U) {
369*79629b1aSNicolas Le Bayon 		ddr_type = STM32MP_LPDDR4;
370*79629b1aSNicolas Le Bayon 	} else {
371*79629b1aSNicolas Le Bayon 		ERROR("DDR type not supported\n");
372*79629b1aSNicolas Le Bayon 		panic();
373*79629b1aSNicolas Le Bayon 	}
374*79629b1aSNicolas Le Bayon 
375*79629b1aSNicolas Le Bayon 	VERBOSE("name = %s\n", config->info.name);
376*79629b1aSNicolas Le Bayon 	VERBOSE("speed = %u kHz\n", config->info.speed);
377*79629b1aSNicolas Le Bayon 	VERBOSE("size  = 0x%zx\n", config->info.size);
378*79629b1aSNicolas Le Bayon 	if (config->self_refresh) {
379*79629b1aSNicolas Le Bayon 		VERBOSE("sel-refresh exit (zdata = 0x%x)\n", config->zdata);
380*79629b1aSNicolas Le Bayon 	}
381*79629b1aSNicolas Le Bayon 
382*79629b1aSNicolas Le Bayon 	/* Check DDR PHY pads retention */
383*79629b1aSNicolas Le Bayon 	ddr_retdis = mmio_read_32(priv->pwr + PWR_CR11) & PWR_CR11_DDRRETDIS;
384*79629b1aSNicolas Le Bayon 	if (config->self_refresh) {
385*79629b1aSNicolas Le Bayon 		if (ddr_retdis == PWR_CR11_DDRRETDIS) {
386*79629b1aSNicolas Le Bayon 			VERBOSE("self-refresh aborted: no retention\n");
387*79629b1aSNicolas Le Bayon 			config->self_refresh = false;
388*79629b1aSNicolas Le Bayon 		}
389*79629b1aSNicolas Le Bayon 	}
390*79629b1aSNicolas Le Bayon 
391*79629b1aSNicolas Le Bayon 	if (config->self_refresh) {
392*79629b1aSNicolas Le Bayon 		ddr_standby_reset(priv);
393*79629b1aSNicolas Le Bayon 
394*79629b1aSNicolas Le Bayon 		VERBOSE("disable DDR PHY retention\n");
395*79629b1aSNicolas Le Bayon 		mmio_setbits_32(priv->pwr + PWR_CR11, PWR_CR11_DDRRETDIS);
396*79629b1aSNicolas Le Bayon 
397*79629b1aSNicolas Le Bayon 		udelay(DDR_DELAY_1US);
398*79629b1aSNicolas Le Bayon 
399*79629b1aSNicolas Le Bayon 		mmio_clrbits_32(priv->rcc + RCC_DDRCAPBCFGR, RCC_DDRCAPBCFGR_DDRCAPBRST);
400*79629b1aSNicolas Le Bayon 
401*79629b1aSNicolas Le Bayon 		udelay(DDR_DELAY_1US);
402*79629b1aSNicolas Le Bayon 
403*79629b1aSNicolas Le Bayon 	} else {
404*79629b1aSNicolas Le Bayon 		if (stm32mp_board_ddr_power_init(ddr_type) != 0) {
405*79629b1aSNicolas Le Bayon 			ERROR("DDR power init failed\n");
406*79629b1aSNicolas Le Bayon 			panic();
407*79629b1aSNicolas Le Bayon 		}
408*79629b1aSNicolas Le Bayon 
409*79629b1aSNicolas Le Bayon 		VERBOSE("disable DDR PHY retention\n");
410*79629b1aSNicolas Le Bayon 		mmio_setbits_32(priv->pwr + PWR_CR11, PWR_CR11_DDRRETDIS);
411*79629b1aSNicolas Le Bayon 
412*79629b1aSNicolas Le Bayon 		ddr_reset(priv);
413*79629b1aSNicolas Le Bayon 
414*79629b1aSNicolas Le Bayon 		ddr_sysconf_configuration(priv, config);
415*79629b1aSNicolas Le Bayon 	}
416*79629b1aSNicolas Le Bayon 
417*79629b1aSNicolas Le Bayon #if STM32MP_LPDDR4_TYPE
418*79629b1aSNicolas Le Bayon 	/*
419*79629b1aSNicolas Le Bayon 	 * Enable PWRCTL.SELFREF_SW to ensure correct setting of PWRCTL.LPDDR4_SR_ALLOWED.
420*79629b1aSNicolas Le Bayon 	 * Later disabled in restore_refresh().
421*79629b1aSNicolas Le Bayon 	 */
422*79629b1aSNicolas Le Bayon 	config->c_reg.pwrctl |= DDRCTRL_PWRCTL_SELFREF_SW;
423*79629b1aSNicolas Le Bayon #endif /* STM32MP_LPDDR4_TYPE */
424*79629b1aSNicolas Le Bayon 
425*79629b1aSNicolas Le Bayon 	stm32mp_ddr_set_reg(priv, REG_REG, &config->c_reg, ddr_registers);
426*79629b1aSNicolas Le Bayon 	stm32mp_ddr_set_reg(priv, REG_TIMING, &config->c_timing, ddr_registers);
427*79629b1aSNicolas Le Bayon 	stm32mp_ddr_set_reg(priv, REG_MAP, &config->c_map, ddr_registers);
428*79629b1aSNicolas Le Bayon 	stm32mp_ddr_set_reg(priv, REG_PERF, &config->c_perf, ddr_registers);
429*79629b1aSNicolas Le Bayon 
430*79629b1aSNicolas Le Bayon 	if (!config->self_refresh) {
431*79629b1aSNicolas Le Bayon 		/*  DDR core and PHY reset de-assert */
432*79629b1aSNicolas Le Bayon 		mmio_clrbits_32(priv->rcc + RCC_DDRITFCFGR, RCC_DDRITFCFGR_DDRRST);
433*79629b1aSNicolas Le Bayon 
434*79629b1aSNicolas Le Bayon 		disable_refresh(priv->ctl);
435*79629b1aSNicolas Le Bayon 	}
436*79629b1aSNicolas Le Bayon 
437*79629b1aSNicolas Le Bayon 	if (config->self_refresh) {
438*79629b1aSNicolas Le Bayon 		ddr_standby_reset_release(priv);
439*79629b1aSNicolas Le Bayon 
440*79629b1aSNicolas Le Bayon 		/* Initialize DDR by skipping training and disabling result saving */
441*79629b1aSNicolas Le Bayon 		ret = ddrphy_phyinit_sequence(config, true, false);
442*79629b1aSNicolas Le Bayon 
443*79629b1aSNicolas Le Bayon 		if (ret == 0) {
444*79629b1aSNicolas Le Bayon 			ret = ddrphy_phyinit_restore_sequence();
445*79629b1aSNicolas Le Bayon 		}
446*79629b1aSNicolas Le Bayon 
447*79629b1aSNicolas Le Bayon 		/* Poll on ddrphy_initeng0_phyinlpx.phyinlp3 = 0 */
448*79629b1aSNicolas Le Bayon 		ddr_wait_lp3_mode(false);
449*79629b1aSNicolas Le Bayon 	} else {
450*79629b1aSNicolas Le Bayon 		/* Initialize DDR including training and result saving */
451*79629b1aSNicolas Le Bayon 		ret = ddrphy_phyinit_sequence(config, false, true);
452*79629b1aSNicolas Le Bayon 	}
453*79629b1aSNicolas Le Bayon 
454*79629b1aSNicolas Le Bayon 	if (ret != 0) {
455*79629b1aSNicolas Le Bayon 		ERROR("DDR PHY init: Error %d\n", ret);
456*79629b1aSNicolas Le Bayon 		panic();
457*79629b1aSNicolas Le Bayon 	}
458*79629b1aSNicolas Le Bayon 
459*79629b1aSNicolas Le Bayon 	ddr_activate_controller(priv->ctl, false);
460*79629b1aSNicolas Le Bayon 
461*79629b1aSNicolas Le Bayon 	if (config->self_refresh) {
462*79629b1aSNicolas Le Bayon 		struct stm32mp_ddrctl *ctl = priv->ctl;
463*79629b1aSNicolas Le Bayon 
464*79629b1aSNicolas Le Bayon 		/* SW self refresh exit prequested */
465*79629b1aSNicolas Le Bayon 		mmio_clrbits_32((uintptr_t)&ctl->pwrctl, DDRCTRL_PWRCTL_SELFREF_SW);
466*79629b1aSNicolas Le Bayon 
467*79629b1aSNicolas Le Bayon 		if (ddr_sr_exit_loop() != 0) {
468*79629b1aSNicolas Le Bayon 			ERROR("DDR Standby exit error\n");
469*79629b1aSNicolas Le Bayon 			panic();
470*79629b1aSNicolas Le Bayon 		}
471*79629b1aSNicolas Le Bayon 
472*79629b1aSNicolas Le Bayon 		/* Re-enable DFI low-power interface */
473*79629b1aSNicolas Le Bayon 		mmio_clrbits_32((uintptr_t)&ctl->dfilpcfg0, DDRCTRL_DFILPCFG0_DFI_LP_EN_SR);
474*79629b1aSNicolas Le Bayon 	} else {
475*79629b1aSNicolas Le Bayon 		restore_refresh(priv->ctl, config->c_reg.rfshctl3, config->c_reg.pwrctl);
476*79629b1aSNicolas Le Bayon 	}
477*79629b1aSNicolas Le Bayon 
478*79629b1aSNicolas Le Bayon 	stm32mp_ddr_enable_axi_port(priv->ctl);
479*79629b1aSNicolas Le Bayon }
480