1*4549e789STom Rini // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
2e70f70aaSPatrick Delaunay /*
3e70f70aaSPatrick Delaunay  * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
4e70f70aaSPatrick Delaunay  */
5e70f70aaSPatrick Delaunay 
6e70f70aaSPatrick Delaunay #include <common.h>
7e70f70aaSPatrick Delaunay #include <clk.h>
8e70f70aaSPatrick Delaunay #include <ram.h>
9e70f70aaSPatrick Delaunay #include <reset.h>
10e70f70aaSPatrick Delaunay #include <timer.h>
11e70f70aaSPatrick Delaunay #include <asm/io.h>
12e70f70aaSPatrick Delaunay #include <asm/arch/ddr.h>
13e70f70aaSPatrick Delaunay #include <linux/iopoll.h>
14e70f70aaSPatrick Delaunay #include "stm32mp1_ddr.h"
15e70f70aaSPatrick Delaunay #include "stm32mp1_ddr_regs.h"
16e70f70aaSPatrick Delaunay 
17e70f70aaSPatrick Delaunay #define RCC_DDRITFCR		0xD8
18e70f70aaSPatrick Delaunay 
19e70f70aaSPatrick Delaunay #define RCC_DDRITFCR_DDRCAPBRST		(BIT(14))
20e70f70aaSPatrick Delaunay #define RCC_DDRITFCR_DDRCAXIRST		(BIT(15))
21e70f70aaSPatrick Delaunay #define RCC_DDRITFCR_DDRCORERST		(BIT(16))
22e70f70aaSPatrick Delaunay #define RCC_DDRITFCR_DPHYAPBRST		(BIT(17))
23e70f70aaSPatrick Delaunay #define RCC_DDRITFCR_DPHYRST		(BIT(18))
24e70f70aaSPatrick Delaunay #define RCC_DDRITFCR_DPHYCTLRST		(BIT(19))
25e70f70aaSPatrick Delaunay 
26e70f70aaSPatrick Delaunay struct reg_desc {
27e70f70aaSPatrick Delaunay 	const char *name;
28e70f70aaSPatrick Delaunay 	u16 offset;	/* offset for base address */
29e70f70aaSPatrick Delaunay 	u8 par_offset;	/* offset for parameter array */
30e70f70aaSPatrick Delaunay };
31e70f70aaSPatrick Delaunay 
32e70f70aaSPatrick Delaunay #define INVALID_OFFSET	0xFF
33e70f70aaSPatrick Delaunay 
34e70f70aaSPatrick Delaunay #define DDRCTL_REG(x, y) \
35e70f70aaSPatrick Delaunay 	{#x,\
36e70f70aaSPatrick Delaunay 	 offsetof(struct stm32mp1_ddrctl, x),\
37e70f70aaSPatrick Delaunay 	 offsetof(struct y, x)}
38e70f70aaSPatrick Delaunay 
39e70f70aaSPatrick Delaunay #define DDRPHY_REG(x, y) \
40e70f70aaSPatrick Delaunay 	{#x,\
41e70f70aaSPatrick Delaunay 	 offsetof(struct stm32mp1_ddrphy, x),\
42e70f70aaSPatrick Delaunay 	 offsetof(struct y, x)}
43e70f70aaSPatrick Delaunay 
44e70f70aaSPatrick Delaunay #define DDRCTL_REG_REG(x)	DDRCTL_REG(x, stm32mp1_ddrctrl_reg)
45e70f70aaSPatrick Delaunay static const struct reg_desc ddr_reg[] = {
46e70f70aaSPatrick Delaunay 	DDRCTL_REG_REG(mstr),
47e70f70aaSPatrick Delaunay 	DDRCTL_REG_REG(mrctrl0),
48e70f70aaSPatrick Delaunay 	DDRCTL_REG_REG(mrctrl1),
49e70f70aaSPatrick Delaunay 	DDRCTL_REG_REG(derateen),
50e70f70aaSPatrick Delaunay 	DDRCTL_REG_REG(derateint),
51e70f70aaSPatrick Delaunay 	DDRCTL_REG_REG(pwrctl),
52e70f70aaSPatrick Delaunay 	DDRCTL_REG_REG(pwrtmg),
53e70f70aaSPatrick Delaunay 	DDRCTL_REG_REG(hwlpctl),
54e70f70aaSPatrick Delaunay 	DDRCTL_REG_REG(rfshctl0),
55e70f70aaSPatrick Delaunay 	DDRCTL_REG_REG(rfshctl3),
56e70f70aaSPatrick Delaunay 	DDRCTL_REG_REG(crcparctl0),
57e70f70aaSPatrick Delaunay 	DDRCTL_REG_REG(zqctl0),
58e70f70aaSPatrick Delaunay 	DDRCTL_REG_REG(dfitmg0),
59e70f70aaSPatrick Delaunay 	DDRCTL_REG_REG(dfitmg1),
60e70f70aaSPatrick Delaunay 	DDRCTL_REG_REG(dfilpcfg0),
61e70f70aaSPatrick Delaunay 	DDRCTL_REG_REG(dfiupd0),
62e70f70aaSPatrick Delaunay 	DDRCTL_REG_REG(dfiupd1),
63e70f70aaSPatrick Delaunay 	DDRCTL_REG_REG(dfiupd2),
64e70f70aaSPatrick Delaunay 	DDRCTL_REG_REG(dfiphymstr),
65e70f70aaSPatrick Delaunay 	DDRCTL_REG_REG(odtmap),
66e70f70aaSPatrick Delaunay 	DDRCTL_REG_REG(dbg0),
67e70f70aaSPatrick Delaunay 	DDRCTL_REG_REG(dbg1),
68e70f70aaSPatrick Delaunay 	DDRCTL_REG_REG(dbgcmd),
69e70f70aaSPatrick Delaunay 	DDRCTL_REG_REG(poisoncfg),
70e70f70aaSPatrick Delaunay 	DDRCTL_REG_REG(pccfg),
71e70f70aaSPatrick Delaunay };
72e70f70aaSPatrick Delaunay 
73e70f70aaSPatrick Delaunay #define DDRCTL_REG_TIMING(x)	DDRCTL_REG(x, stm32mp1_ddrctrl_timing)
74e70f70aaSPatrick Delaunay static const struct reg_desc ddr_timing[] = {
75e70f70aaSPatrick Delaunay 	DDRCTL_REG_TIMING(rfshtmg),
76e70f70aaSPatrick Delaunay 	DDRCTL_REG_TIMING(dramtmg0),
77e70f70aaSPatrick Delaunay 	DDRCTL_REG_TIMING(dramtmg1),
78e70f70aaSPatrick Delaunay 	DDRCTL_REG_TIMING(dramtmg2),
79e70f70aaSPatrick Delaunay 	DDRCTL_REG_TIMING(dramtmg3),
80e70f70aaSPatrick Delaunay 	DDRCTL_REG_TIMING(dramtmg4),
81e70f70aaSPatrick Delaunay 	DDRCTL_REG_TIMING(dramtmg5),
82e70f70aaSPatrick Delaunay 	DDRCTL_REG_TIMING(dramtmg6),
83e70f70aaSPatrick Delaunay 	DDRCTL_REG_TIMING(dramtmg7),
84e70f70aaSPatrick Delaunay 	DDRCTL_REG_TIMING(dramtmg8),
85e70f70aaSPatrick Delaunay 	DDRCTL_REG_TIMING(dramtmg14),
86e70f70aaSPatrick Delaunay 	DDRCTL_REG_TIMING(odtcfg),
87e70f70aaSPatrick Delaunay };
88e70f70aaSPatrick Delaunay 
89e70f70aaSPatrick Delaunay #define DDRCTL_REG_MAP(x)	DDRCTL_REG(x, stm32mp1_ddrctrl_map)
90e70f70aaSPatrick Delaunay static const struct reg_desc ddr_map[] = {
91e70f70aaSPatrick Delaunay 	DDRCTL_REG_MAP(addrmap1),
92e70f70aaSPatrick Delaunay 	DDRCTL_REG_MAP(addrmap2),
93e70f70aaSPatrick Delaunay 	DDRCTL_REG_MAP(addrmap3),
94e70f70aaSPatrick Delaunay 	DDRCTL_REG_MAP(addrmap4),
95e70f70aaSPatrick Delaunay 	DDRCTL_REG_MAP(addrmap5),
96e70f70aaSPatrick Delaunay 	DDRCTL_REG_MAP(addrmap6),
97e70f70aaSPatrick Delaunay 	DDRCTL_REG_MAP(addrmap9),
98e70f70aaSPatrick Delaunay 	DDRCTL_REG_MAP(addrmap10),
99e70f70aaSPatrick Delaunay 	DDRCTL_REG_MAP(addrmap11),
100e70f70aaSPatrick Delaunay };
101e70f70aaSPatrick Delaunay 
102e70f70aaSPatrick Delaunay #define DDRCTL_REG_PERF(x)	DDRCTL_REG(x, stm32mp1_ddrctrl_perf)
103e70f70aaSPatrick Delaunay static const struct reg_desc ddr_perf[] = {
104e70f70aaSPatrick Delaunay 	DDRCTL_REG_PERF(sched),
105e70f70aaSPatrick Delaunay 	DDRCTL_REG_PERF(sched1),
106e70f70aaSPatrick Delaunay 	DDRCTL_REG_PERF(perfhpr1),
107e70f70aaSPatrick Delaunay 	DDRCTL_REG_PERF(perflpr1),
108e70f70aaSPatrick Delaunay 	DDRCTL_REG_PERF(perfwr1),
109e70f70aaSPatrick Delaunay 	DDRCTL_REG_PERF(pcfgr_0),
110e70f70aaSPatrick Delaunay 	DDRCTL_REG_PERF(pcfgw_0),
111e70f70aaSPatrick Delaunay 	DDRCTL_REG_PERF(pcfgqos0_0),
112e70f70aaSPatrick Delaunay 	DDRCTL_REG_PERF(pcfgqos1_0),
113e70f70aaSPatrick Delaunay 	DDRCTL_REG_PERF(pcfgwqos0_0),
114e70f70aaSPatrick Delaunay 	DDRCTL_REG_PERF(pcfgwqos1_0),
115e70f70aaSPatrick Delaunay 	DDRCTL_REG_PERF(pcfgr_1),
116e70f70aaSPatrick Delaunay 	DDRCTL_REG_PERF(pcfgw_1),
117e70f70aaSPatrick Delaunay 	DDRCTL_REG_PERF(pcfgqos0_1),
118e70f70aaSPatrick Delaunay 	DDRCTL_REG_PERF(pcfgqos1_1),
119e70f70aaSPatrick Delaunay 	DDRCTL_REG_PERF(pcfgwqos0_1),
120e70f70aaSPatrick Delaunay 	DDRCTL_REG_PERF(pcfgwqos1_1),
121e70f70aaSPatrick Delaunay };
122e70f70aaSPatrick Delaunay 
123e70f70aaSPatrick Delaunay #define DDRPHY_REG_REG(x)	DDRPHY_REG(x, stm32mp1_ddrphy_reg)
124e70f70aaSPatrick Delaunay static const struct reg_desc ddrphy_reg[] = {
125e70f70aaSPatrick Delaunay 	DDRPHY_REG_REG(pgcr),
126e70f70aaSPatrick Delaunay 	DDRPHY_REG_REG(aciocr),
127e70f70aaSPatrick Delaunay 	DDRPHY_REG_REG(dxccr),
128e70f70aaSPatrick Delaunay 	DDRPHY_REG_REG(dsgcr),
129e70f70aaSPatrick Delaunay 	DDRPHY_REG_REG(dcr),
130e70f70aaSPatrick Delaunay 	DDRPHY_REG_REG(odtcr),
131e70f70aaSPatrick Delaunay 	DDRPHY_REG_REG(zq0cr1),
132e70f70aaSPatrick Delaunay 	DDRPHY_REG_REG(dx0gcr),
133e70f70aaSPatrick Delaunay 	DDRPHY_REG_REG(dx1gcr),
134e70f70aaSPatrick Delaunay 	DDRPHY_REG_REG(dx2gcr),
135e70f70aaSPatrick Delaunay 	DDRPHY_REG_REG(dx3gcr),
136e70f70aaSPatrick Delaunay };
137e70f70aaSPatrick Delaunay 
138e70f70aaSPatrick Delaunay #define DDRPHY_REG_TIMING(x)	DDRPHY_REG(x, stm32mp1_ddrphy_timing)
139e70f70aaSPatrick Delaunay static const struct reg_desc ddrphy_timing[] = {
140e70f70aaSPatrick Delaunay 	DDRPHY_REG_TIMING(ptr0),
141e70f70aaSPatrick Delaunay 	DDRPHY_REG_TIMING(ptr1),
142e70f70aaSPatrick Delaunay 	DDRPHY_REG_TIMING(ptr2),
143e70f70aaSPatrick Delaunay 	DDRPHY_REG_TIMING(dtpr0),
144e70f70aaSPatrick Delaunay 	DDRPHY_REG_TIMING(dtpr1),
145e70f70aaSPatrick Delaunay 	DDRPHY_REG_TIMING(dtpr2),
146e70f70aaSPatrick Delaunay 	DDRPHY_REG_TIMING(mr0),
147e70f70aaSPatrick Delaunay 	DDRPHY_REG_TIMING(mr1),
148e70f70aaSPatrick Delaunay 	DDRPHY_REG_TIMING(mr2),
149e70f70aaSPatrick Delaunay 	DDRPHY_REG_TIMING(mr3),
150e70f70aaSPatrick Delaunay };
151e70f70aaSPatrick Delaunay 
152e70f70aaSPatrick Delaunay #define DDRPHY_REG_CAL(x)	DDRPHY_REG(x, stm32mp1_ddrphy_cal)
153e70f70aaSPatrick Delaunay static const struct reg_desc ddrphy_cal[] = {
154e70f70aaSPatrick Delaunay 	DDRPHY_REG_CAL(dx0dllcr),
155e70f70aaSPatrick Delaunay 	DDRPHY_REG_CAL(dx0dqtr),
156e70f70aaSPatrick Delaunay 	DDRPHY_REG_CAL(dx0dqstr),
157e70f70aaSPatrick Delaunay 	DDRPHY_REG_CAL(dx1dllcr),
158e70f70aaSPatrick Delaunay 	DDRPHY_REG_CAL(dx1dqtr),
159e70f70aaSPatrick Delaunay 	DDRPHY_REG_CAL(dx1dqstr),
160e70f70aaSPatrick Delaunay 	DDRPHY_REG_CAL(dx2dllcr),
161e70f70aaSPatrick Delaunay 	DDRPHY_REG_CAL(dx2dqtr),
162e70f70aaSPatrick Delaunay 	DDRPHY_REG_CAL(dx2dqstr),
163e70f70aaSPatrick Delaunay 	DDRPHY_REG_CAL(dx3dllcr),
164e70f70aaSPatrick Delaunay 	DDRPHY_REG_CAL(dx3dqtr),
165e70f70aaSPatrick Delaunay 	DDRPHY_REG_CAL(dx3dqstr),
166e70f70aaSPatrick Delaunay };
167e70f70aaSPatrick Delaunay 
168e70f70aaSPatrick Delaunay enum reg_type {
169e70f70aaSPatrick Delaunay 	REG_REG,
170e70f70aaSPatrick Delaunay 	REG_TIMING,
171e70f70aaSPatrick Delaunay 	REG_PERF,
172e70f70aaSPatrick Delaunay 	REG_MAP,
173e70f70aaSPatrick Delaunay 	REGPHY_REG,
174e70f70aaSPatrick Delaunay 	REGPHY_TIMING,
175e70f70aaSPatrick Delaunay 	REGPHY_CAL,
176e70f70aaSPatrick Delaunay 	REG_TYPE_NB
177e70f70aaSPatrick Delaunay };
178e70f70aaSPatrick Delaunay 
179e70f70aaSPatrick Delaunay enum base_type {
180e70f70aaSPatrick Delaunay 	DDR_BASE,
181e70f70aaSPatrick Delaunay 	DDRPHY_BASE,
182e70f70aaSPatrick Delaunay 	NONE_BASE
183e70f70aaSPatrick Delaunay };
184e70f70aaSPatrick Delaunay 
185e70f70aaSPatrick Delaunay struct ddr_reg_info {
186e70f70aaSPatrick Delaunay 	const char *name;
187e70f70aaSPatrick Delaunay 	const struct reg_desc *desc;
188e70f70aaSPatrick Delaunay 	u8 size;
189e70f70aaSPatrick Delaunay 	enum base_type base;
190e70f70aaSPatrick Delaunay };
191e70f70aaSPatrick Delaunay 
192e70f70aaSPatrick Delaunay #define DDRPHY_REG_CAL(x)	DDRPHY_REG(x, stm32mp1_ddrphy_cal)
193e70f70aaSPatrick Delaunay 
194e70f70aaSPatrick Delaunay const struct ddr_reg_info ddr_registers[REG_TYPE_NB] = {
195e70f70aaSPatrick Delaunay [REG_REG] = {
196e70f70aaSPatrick Delaunay 	"static", ddr_reg, ARRAY_SIZE(ddr_reg), DDR_BASE},
197e70f70aaSPatrick Delaunay [REG_TIMING] = {
198e70f70aaSPatrick Delaunay 	"timing", ddr_timing, ARRAY_SIZE(ddr_timing), DDR_BASE},
199e70f70aaSPatrick Delaunay [REG_PERF] = {
200e70f70aaSPatrick Delaunay 	"perf", ddr_perf, ARRAY_SIZE(ddr_perf), DDR_BASE},
201e70f70aaSPatrick Delaunay [REG_MAP] = {
202e70f70aaSPatrick Delaunay 	"map", ddr_map, ARRAY_SIZE(ddr_map), DDR_BASE},
203e70f70aaSPatrick Delaunay [REGPHY_REG] = {
204e70f70aaSPatrick Delaunay 	"static", ddrphy_reg, ARRAY_SIZE(ddrphy_reg), DDRPHY_BASE},
205e70f70aaSPatrick Delaunay [REGPHY_TIMING] = {
206e70f70aaSPatrick Delaunay 	"timing", ddrphy_timing, ARRAY_SIZE(ddrphy_timing), DDRPHY_BASE},
207e70f70aaSPatrick Delaunay [REGPHY_CAL] = {
208e70f70aaSPatrick Delaunay 	"cal", ddrphy_cal, ARRAY_SIZE(ddrphy_cal), DDRPHY_BASE},
209e70f70aaSPatrick Delaunay };
210e70f70aaSPatrick Delaunay 
211e70f70aaSPatrick Delaunay const char *base_name[] = {
212e70f70aaSPatrick Delaunay 	[DDR_BASE] = "ctl",
213e70f70aaSPatrick Delaunay 	[DDRPHY_BASE] = "phy",
214e70f70aaSPatrick Delaunay };
215e70f70aaSPatrick Delaunay 
get_base_addr(const struct ddr_info * priv,enum base_type base)216e70f70aaSPatrick Delaunay static u32 get_base_addr(const struct ddr_info *priv, enum base_type base)
217e70f70aaSPatrick Delaunay {
218e70f70aaSPatrick Delaunay 	if (base == DDRPHY_BASE)
219e70f70aaSPatrick Delaunay 		return (u32)priv->phy;
220e70f70aaSPatrick Delaunay 	else
221e70f70aaSPatrick Delaunay 		return (u32)priv->ctl;
222e70f70aaSPatrick Delaunay }
223e70f70aaSPatrick Delaunay 
set_reg(const struct ddr_info * priv,enum reg_type type,const void * param)224e70f70aaSPatrick Delaunay static void set_reg(const struct ddr_info *priv,
225e70f70aaSPatrick Delaunay 		    enum reg_type type,
226e70f70aaSPatrick Delaunay 		    const void *param)
227e70f70aaSPatrick Delaunay {
228e70f70aaSPatrick Delaunay 	unsigned int i;
229e70f70aaSPatrick Delaunay 	unsigned int *ptr, value;
230e70f70aaSPatrick Delaunay 	enum base_type base = ddr_registers[type].base;
231e70f70aaSPatrick Delaunay 	u32 base_addr = get_base_addr(priv, base);
232e70f70aaSPatrick Delaunay 	const struct reg_desc *desc = ddr_registers[type].desc;
233e70f70aaSPatrick Delaunay 
234e70f70aaSPatrick Delaunay 	debug("init %s\n", ddr_registers[type].name);
235e70f70aaSPatrick Delaunay 	for (i = 0; i < ddr_registers[type].size; i++) {
236e70f70aaSPatrick Delaunay 		ptr = (unsigned int *)(base_addr + desc[i].offset);
237e70f70aaSPatrick Delaunay 		if (desc[i].par_offset == INVALID_OFFSET) {
238e70f70aaSPatrick Delaunay 			pr_err("invalid parameter offset for %s", desc[i].name);
239e70f70aaSPatrick Delaunay 		} else {
240e70f70aaSPatrick Delaunay 			value = *((u32 *)((u32)param +
241e70f70aaSPatrick Delaunay 					       desc[i].par_offset));
242e70f70aaSPatrick Delaunay 			writel(value, ptr);
243e70f70aaSPatrick Delaunay 			debug("[0x%x] %s= 0x%08x\n",
244e70f70aaSPatrick Delaunay 			      (u32)ptr, desc[i].name, value);
245e70f70aaSPatrick Delaunay 		}
246e70f70aaSPatrick Delaunay 	}
247e70f70aaSPatrick Delaunay }
248e70f70aaSPatrick Delaunay 
ddrphy_idone_wait(struct stm32mp1_ddrphy * phy)249e70f70aaSPatrick Delaunay static void ddrphy_idone_wait(struct stm32mp1_ddrphy *phy)
250e70f70aaSPatrick Delaunay {
251e70f70aaSPatrick Delaunay 	u32 pgsr;
252e70f70aaSPatrick Delaunay 	int ret;
253e70f70aaSPatrick Delaunay 
254e70f70aaSPatrick Delaunay 	ret = readl_poll_timeout(&phy->pgsr, pgsr,
255e70f70aaSPatrick Delaunay 				 pgsr & (DDRPHYC_PGSR_IDONE |
256e70f70aaSPatrick Delaunay 					 DDRPHYC_PGSR_DTERR |
257e70f70aaSPatrick Delaunay 					 DDRPHYC_PGSR_DTIERR |
258e70f70aaSPatrick Delaunay 					 DDRPHYC_PGSR_DFTERR |
259e70f70aaSPatrick Delaunay 					 DDRPHYC_PGSR_RVERR |
260e70f70aaSPatrick Delaunay 					 DDRPHYC_PGSR_RVEIRR),
261e70f70aaSPatrick Delaunay 				1000000);
262e70f70aaSPatrick Delaunay 	debug("\n[0x%08x] pgsr = 0x%08x ret=%d\n",
263e70f70aaSPatrick Delaunay 	      (u32)&phy->pgsr, pgsr, ret);
264e70f70aaSPatrick Delaunay }
265e70f70aaSPatrick Delaunay 
stm32mp1_ddrphy_init(struct stm32mp1_ddrphy * phy,u32 pir)266e70f70aaSPatrick Delaunay void stm32mp1_ddrphy_init(struct stm32mp1_ddrphy *phy, u32 pir)
267e70f70aaSPatrick Delaunay {
268e70f70aaSPatrick Delaunay 	pir |= DDRPHYC_PIR_INIT;
269e70f70aaSPatrick Delaunay 	writel(pir, &phy->pir);
270e70f70aaSPatrick Delaunay 	debug("[0x%08x] pir = 0x%08x -> 0x%08x\n",
271e70f70aaSPatrick Delaunay 	      (u32)&phy->pir, pir, readl(&phy->pir));
272e70f70aaSPatrick Delaunay 
273e70f70aaSPatrick Delaunay 	/* need to wait 10 configuration clock before start polling */
274e70f70aaSPatrick Delaunay 	udelay(10);
275e70f70aaSPatrick Delaunay 
276e70f70aaSPatrick Delaunay 	/* Wait DRAM initialization and Gate Training Evaluation complete */
277e70f70aaSPatrick Delaunay 	ddrphy_idone_wait(phy);
278e70f70aaSPatrick Delaunay }
279e70f70aaSPatrick Delaunay 
280e70f70aaSPatrick Delaunay /* start quasi dynamic register update */
start_sw_done(struct stm32mp1_ddrctl * ctl)281e70f70aaSPatrick Delaunay static void start_sw_done(struct stm32mp1_ddrctl *ctl)
282e70f70aaSPatrick Delaunay {
283e70f70aaSPatrick Delaunay 	clrbits_le32(&ctl->swctl, DDRCTRL_SWCTL_SW_DONE);
284e70f70aaSPatrick Delaunay }
285e70f70aaSPatrick Delaunay 
286e70f70aaSPatrick Delaunay /* wait quasi dynamic register update */
wait_sw_done_ack(struct stm32mp1_ddrctl * ctl)287e70f70aaSPatrick Delaunay static void wait_sw_done_ack(struct stm32mp1_ddrctl *ctl)
288e70f70aaSPatrick Delaunay {
289e70f70aaSPatrick Delaunay 	int ret;
290e70f70aaSPatrick Delaunay 	u32 swstat;
291e70f70aaSPatrick Delaunay 
292e70f70aaSPatrick Delaunay 	setbits_le32(&ctl->swctl, DDRCTRL_SWCTL_SW_DONE);
293e70f70aaSPatrick Delaunay 
294e70f70aaSPatrick Delaunay 	ret = readl_poll_timeout(&ctl->swstat, swstat,
295e70f70aaSPatrick Delaunay 				 swstat & DDRCTRL_SWSTAT_SW_DONE_ACK,
296e70f70aaSPatrick Delaunay 				 1000000);
297e70f70aaSPatrick Delaunay 	if (ret)
298e70f70aaSPatrick Delaunay 		panic("Timeout initialising DRAM : DDR->swstat = %x\n",
299e70f70aaSPatrick Delaunay 		      swstat);
300e70f70aaSPatrick Delaunay 
301e70f70aaSPatrick Delaunay 	debug("[0x%08x] swstat = 0x%08x\n", (u32)&ctl->swstat, swstat);
302e70f70aaSPatrick Delaunay }
303e70f70aaSPatrick Delaunay 
304e70f70aaSPatrick Delaunay /* wait quasi dynamic register update */
wait_operating_mode(struct ddr_info * priv,int mode)305e70f70aaSPatrick Delaunay static void wait_operating_mode(struct ddr_info *priv, int mode)
306e70f70aaSPatrick Delaunay {
307e70f70aaSPatrick Delaunay 	u32 stat, val, mask, val2 = 0, mask2 = 0;
308e70f70aaSPatrick Delaunay 	int ret;
309e70f70aaSPatrick Delaunay 
310e70f70aaSPatrick Delaunay 	mask = DDRCTRL_STAT_OPERATING_MODE_MASK;
311e70f70aaSPatrick Delaunay 	val = mode;
312e70f70aaSPatrick Delaunay 	/* self-refresh due to software => check also STAT.selfref_type */
313e70f70aaSPatrick Delaunay 	if (mode == DDRCTRL_STAT_OPERATING_MODE_SR) {
314e70f70aaSPatrick Delaunay 		mask |= DDRCTRL_STAT_SELFREF_TYPE_MASK;
315e70f70aaSPatrick Delaunay 		stat |= DDRCTRL_STAT_SELFREF_TYPE_SR;
316e70f70aaSPatrick Delaunay 	} else if (mode == DDRCTRL_STAT_OPERATING_MODE_NORMAL) {
317e70f70aaSPatrick Delaunay 		/* normal mode: handle also automatic self refresh */
318e70f70aaSPatrick Delaunay 		mask2 = DDRCTRL_STAT_OPERATING_MODE_MASK |
319e70f70aaSPatrick Delaunay 			DDRCTRL_STAT_SELFREF_TYPE_MASK;
320e70f70aaSPatrick Delaunay 		val2 = DDRCTRL_STAT_OPERATING_MODE_SR |
321e70f70aaSPatrick Delaunay 		       DDRCTRL_STAT_SELFREF_TYPE_ASR;
322e70f70aaSPatrick Delaunay 	}
323e70f70aaSPatrick Delaunay 
324e70f70aaSPatrick Delaunay 	ret = readl_poll_timeout(&priv->ctl->stat, stat,
325e70f70aaSPatrick Delaunay 				 ((stat & mask) == val) ||
326e70f70aaSPatrick Delaunay 				 (mask2 && ((stat & mask2) == val2)),
327e70f70aaSPatrick Delaunay 				 1000000);
328e70f70aaSPatrick Delaunay 
329e70f70aaSPatrick Delaunay 	if (ret)
330e70f70aaSPatrick Delaunay 		panic("Timeout DRAM : DDR->stat = %x\n", stat);
331e70f70aaSPatrick Delaunay 
332e70f70aaSPatrick Delaunay 	debug("[0x%08x] stat = 0x%08x\n", (u32)&priv->ctl->stat, stat);
333e70f70aaSPatrick Delaunay }
334e70f70aaSPatrick Delaunay 
stm32mp1_refresh_disable(struct stm32mp1_ddrctl * ctl)335e70f70aaSPatrick Delaunay void stm32mp1_refresh_disable(struct stm32mp1_ddrctl *ctl)
336e70f70aaSPatrick Delaunay {
337e70f70aaSPatrick Delaunay 	start_sw_done(ctl);
338e70f70aaSPatrick Delaunay 	/* quasi-dynamic register update*/
339e70f70aaSPatrick Delaunay 	setbits_le32(&ctl->rfshctl3, DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH);
340e70f70aaSPatrick Delaunay 	clrbits_le32(&ctl->pwrctl, DDRCTRL_PWRCTL_POWERDOWN_EN);
341e70f70aaSPatrick Delaunay 	clrbits_le32(&ctl->dfimisc, DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN);
342e70f70aaSPatrick Delaunay 	wait_sw_done_ack(ctl);
343e70f70aaSPatrick Delaunay }
344e70f70aaSPatrick Delaunay 
stm32mp1_refresh_restore(struct stm32mp1_ddrctl * ctl,u32 rfshctl3,u32 pwrctl)345e70f70aaSPatrick Delaunay void stm32mp1_refresh_restore(struct stm32mp1_ddrctl *ctl,
346e70f70aaSPatrick Delaunay 			      u32 rfshctl3, u32 pwrctl)
347e70f70aaSPatrick Delaunay {
348e70f70aaSPatrick Delaunay 	start_sw_done(ctl);
349e70f70aaSPatrick Delaunay 	if (!(rfshctl3 & DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH))
350e70f70aaSPatrick Delaunay 		clrbits_le32(&ctl->rfshctl3, DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH);
351e70f70aaSPatrick Delaunay 	if (pwrctl & DDRCTRL_PWRCTL_POWERDOWN_EN)
352e70f70aaSPatrick Delaunay 		setbits_le32(&ctl->pwrctl, DDRCTRL_PWRCTL_POWERDOWN_EN);
353e70f70aaSPatrick Delaunay 	setbits_le32(&ctl->dfimisc, DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN);
354e70f70aaSPatrick Delaunay 	wait_sw_done_ack(ctl);
355e70f70aaSPatrick Delaunay }
356e70f70aaSPatrick Delaunay 
357e70f70aaSPatrick Delaunay /* board-specific DDR power initializations. */
board_ddr_power_init(void)358e70f70aaSPatrick Delaunay __weak int board_ddr_power_init(void)
359e70f70aaSPatrick Delaunay {
360e70f70aaSPatrick Delaunay 	return 0;
361e70f70aaSPatrick Delaunay }
362e70f70aaSPatrick Delaunay 
363e70f70aaSPatrick Delaunay __maybe_unused
stm32mp1_ddr_init(struct ddr_info * priv,const struct stm32mp1_ddr_config * config)364e70f70aaSPatrick Delaunay void stm32mp1_ddr_init(struct ddr_info *priv,
365e70f70aaSPatrick Delaunay 		       const struct stm32mp1_ddr_config *config)
366e70f70aaSPatrick Delaunay {
367e70f70aaSPatrick Delaunay 	u32 pir;
368e70f70aaSPatrick Delaunay 	int ret;
369e70f70aaSPatrick Delaunay 
370e70f70aaSPatrick Delaunay 	ret = board_ddr_power_init();
371e70f70aaSPatrick Delaunay 
372e70f70aaSPatrick Delaunay 	if (ret)
373e70f70aaSPatrick Delaunay 		panic("ddr power init failed\n");
374e70f70aaSPatrick Delaunay 
375e70f70aaSPatrick Delaunay 	debug("name = %s\n", config->info.name);
376e70f70aaSPatrick Delaunay 	debug("speed = %d MHz\n", config->info.speed);
377e70f70aaSPatrick Delaunay 	debug("size  = 0x%x\n", config->info.size);
378e70f70aaSPatrick Delaunay /*
379e70f70aaSPatrick Delaunay  * 1. Program the DWC_ddr_umctl2 registers
380e70f70aaSPatrick Delaunay  * 1.1 RESETS: presetn, core_ddrc_rstn, aresetn
381e70f70aaSPatrick Delaunay  */
382e70f70aaSPatrick Delaunay 	/* Assert All DDR part */
383e70f70aaSPatrick Delaunay 	setbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAPBRST);
384e70f70aaSPatrick Delaunay 	setbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAXIRST);
385e70f70aaSPatrick Delaunay 	setbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCORERST);
386e70f70aaSPatrick Delaunay 	setbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYAPBRST);
387e70f70aaSPatrick Delaunay 	setbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYRST);
388e70f70aaSPatrick Delaunay 	setbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYCTLRST);
389e70f70aaSPatrick Delaunay 
390e70f70aaSPatrick Delaunay /* 1.2. start CLOCK */
391e70f70aaSPatrick Delaunay 	if (stm32mp1_ddr_clk_enable(priv, config->info.speed))
392e70f70aaSPatrick Delaunay 		panic("invalid DRAM clock : %d MHz\n",
393e70f70aaSPatrick Delaunay 		      config->info.speed);
394e70f70aaSPatrick Delaunay 
395e70f70aaSPatrick Delaunay /* 1.3. deassert reset */
396e70f70aaSPatrick Delaunay 	/* de-assert PHY rstn and ctl_rstn via DPHYRST and DPHYCTLRST */
397e70f70aaSPatrick Delaunay 	clrbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYRST);
398e70f70aaSPatrick Delaunay 	clrbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYCTLRST);
399e70f70aaSPatrick Delaunay 	/* De-assert presetn once the clocks are active
400e70f70aaSPatrick Delaunay 	 * and stable via DDRCAPBRST bit
401e70f70aaSPatrick Delaunay 	 */
402e70f70aaSPatrick Delaunay 	clrbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAPBRST);
403e70f70aaSPatrick Delaunay 
404e70f70aaSPatrick Delaunay /* 1.4. wait 4 cycles for synchronization */
405e70f70aaSPatrick Delaunay 	asm(" nop");
406e70f70aaSPatrick Delaunay 	asm(" nop");
407e70f70aaSPatrick Delaunay 	asm(" nop");
408e70f70aaSPatrick Delaunay 	asm(" nop");
409e70f70aaSPatrick Delaunay 
410e70f70aaSPatrick Delaunay /* 1.5. initialize registers ddr_umctl2 */
411e70f70aaSPatrick Delaunay 	/* Stop uMCTL2 before PHY is ready */
412e70f70aaSPatrick Delaunay 	clrbits_le32(&priv->ctl->dfimisc, DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN);
413e70f70aaSPatrick Delaunay 	debug("[0x%08x] dfimisc = 0x%08x\n",
414e70f70aaSPatrick Delaunay 	      (u32)&priv->ctl->dfimisc, readl(&priv->ctl->dfimisc));
415e70f70aaSPatrick Delaunay 
416e70f70aaSPatrick Delaunay 	set_reg(priv, REG_REG, &config->c_reg);
417e70f70aaSPatrick Delaunay 	set_reg(priv, REG_TIMING, &config->c_timing);
418e70f70aaSPatrick Delaunay 	set_reg(priv, REG_MAP, &config->c_map);
419e70f70aaSPatrick Delaunay 
420e70f70aaSPatrick Delaunay 	/* skip CTRL init, SDRAM init is done by PHY PUBL */
421e70f70aaSPatrick Delaunay 	clrsetbits_le32(&priv->ctl->init0,
422e70f70aaSPatrick Delaunay 			DDRCTRL_INIT0_SKIP_DRAM_INIT_MASK,
423e70f70aaSPatrick Delaunay 			DDRCTRL_INIT0_SKIP_DRAM_INIT_NORMAL);
424e70f70aaSPatrick Delaunay 
425e70f70aaSPatrick Delaunay 	set_reg(priv, REG_PERF, &config->c_perf);
426e70f70aaSPatrick Delaunay 
427e70f70aaSPatrick Delaunay /*  2. deassert reset signal core_ddrc_rstn, aresetn and presetn */
428e70f70aaSPatrick Delaunay 	clrbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCORERST);
429e70f70aaSPatrick Delaunay 	clrbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAXIRST);
430e70f70aaSPatrick Delaunay 	clrbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYAPBRST);
431e70f70aaSPatrick Delaunay 
432e70f70aaSPatrick Delaunay /*  3. start PHY init by accessing relevant PUBL registers
433e70f70aaSPatrick Delaunay  *    (DXGCR, DCR, PTR*, MR*, DTPR*)
434e70f70aaSPatrick Delaunay  */
435e70f70aaSPatrick Delaunay 	set_reg(priv, REGPHY_REG, &config->p_reg);
436e70f70aaSPatrick Delaunay 	set_reg(priv, REGPHY_TIMING, &config->p_timing);
437e70f70aaSPatrick Delaunay 	set_reg(priv, REGPHY_CAL, &config->p_cal);
438e70f70aaSPatrick Delaunay 
439e70f70aaSPatrick Delaunay /*  4. Monitor PHY init status by polling PUBL register PGSR.IDONE
440e70f70aaSPatrick Delaunay  *     Perform DDR PHY DRAM initialization and Gate Training Evaluation
441e70f70aaSPatrick Delaunay  */
442e70f70aaSPatrick Delaunay 	ddrphy_idone_wait(priv->phy);
443e70f70aaSPatrick Delaunay 
444e70f70aaSPatrick Delaunay /*  5. Indicate to PUBL that controller performs SDRAM initialization
445e70f70aaSPatrick Delaunay  *     by setting PIR.INIT and PIR CTLDINIT and pool PGSR.IDONE
446e70f70aaSPatrick Delaunay  *     DRAM init is done by PHY, init0.skip_dram.init = 1
447e70f70aaSPatrick Delaunay  */
448e70f70aaSPatrick Delaunay 	pir = DDRPHYC_PIR_DLLSRST | DDRPHYC_PIR_DLLLOCK | DDRPHYC_PIR_ZCAL |
449e70f70aaSPatrick Delaunay 	      DDRPHYC_PIR_ITMSRST | DDRPHYC_PIR_DRAMINIT | DDRPHYC_PIR_ICPC;
450e70f70aaSPatrick Delaunay 
451e70f70aaSPatrick Delaunay 	if (config->c_reg.mstr & DDRCTRL_MSTR_DDR3)
452e70f70aaSPatrick Delaunay 		pir |= DDRPHYC_PIR_DRAMRST; /* only for DDR3 */
453e70f70aaSPatrick Delaunay 
454e70f70aaSPatrick Delaunay 	stm32mp1_ddrphy_init(priv->phy, pir);
455e70f70aaSPatrick Delaunay 
456e70f70aaSPatrick Delaunay /*  6. SET DFIMISC.dfi_init_complete_en to 1 */
457e70f70aaSPatrick Delaunay 	/* Enable quasi-dynamic register programming*/
458e70f70aaSPatrick Delaunay 	start_sw_done(priv->ctl);
459e70f70aaSPatrick Delaunay 	setbits_le32(&priv->ctl->dfimisc, DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN);
460e70f70aaSPatrick Delaunay 	wait_sw_done_ack(priv->ctl);
461e70f70aaSPatrick Delaunay 
462e70f70aaSPatrick Delaunay /*  7. Wait for DWC_ddr_umctl2 to move to normal operation mode
463e70f70aaSPatrick Delaunay  *     by monitoring STAT.operating_mode signal
464e70f70aaSPatrick Delaunay  */
465e70f70aaSPatrick Delaunay 	/* wait uMCTL2 ready */
466e70f70aaSPatrick Delaunay 
467e70f70aaSPatrick Delaunay 	wait_operating_mode(priv, DDRCTRL_STAT_OPERATING_MODE_NORMAL);
468e70f70aaSPatrick Delaunay 
469e70f70aaSPatrick Delaunay 	debug("DDR DQS training : ");
470e70f70aaSPatrick Delaunay /*  8. Disable Auto refresh and power down by setting
471e70f70aaSPatrick Delaunay  *    - RFSHCTL3.dis_au_refresh = 1
472e70f70aaSPatrick Delaunay  *    - PWRCTL.powerdown_en = 0
473e70f70aaSPatrick Delaunay  *    - DFIMISC.dfiinit_complete_en = 0
474e70f70aaSPatrick Delaunay  */
475e70f70aaSPatrick Delaunay 	stm32mp1_refresh_disable(priv->ctl);
476e70f70aaSPatrick Delaunay 
477e70f70aaSPatrick Delaunay /*  9. Program PUBL PGCR to enable refresh during training and rank to train
478e70f70aaSPatrick Delaunay  *     not done => keep the programed value in PGCR
479e70f70aaSPatrick Delaunay  */
480e70f70aaSPatrick Delaunay 
481e70f70aaSPatrick Delaunay /* 10. configure PUBL PIR register to specify which training step to run */
482e70f70aaSPatrick Delaunay 	/* warning : RVTRN  is not supported by this PUBL */
483e70f70aaSPatrick Delaunay 	stm32mp1_ddrphy_init(priv->phy, DDRPHYC_PIR_QSTRN);
484e70f70aaSPatrick Delaunay 
485e70f70aaSPatrick Delaunay /* 11. monitor PUB PGSR.IDONE to poll cpmpletion of training sequence */
486e70f70aaSPatrick Delaunay 	ddrphy_idone_wait(priv->phy);
487e70f70aaSPatrick Delaunay 
488e70f70aaSPatrick Delaunay /* 12. set back registers in step 8 to the orginal values if desidered */
489e70f70aaSPatrick Delaunay 	stm32mp1_refresh_restore(priv->ctl, config->c_reg.rfshctl3,
490e70f70aaSPatrick Delaunay 				 config->c_reg.pwrctl);
491e70f70aaSPatrick Delaunay 
492e70f70aaSPatrick Delaunay 	/* enable uMCTL2 AXI port 0 and 1 */
493e70f70aaSPatrick Delaunay 	setbits_le32(&priv->ctl->pctrl_0, DDRCTRL_PCTRL_N_PORT_EN);
494e70f70aaSPatrick Delaunay 	setbits_le32(&priv->ctl->pctrl_1, DDRCTRL_PCTRL_N_PORT_EN);
495e70f70aaSPatrick Delaunay }
496