xref: /rk3399_ARM-atf/drivers/st/ddr/stm32mp_ddr.c (revision d596023bff6780b8c33e33923f356b7e71b79e56)
106e55dc8SNicolas Le Bayon /*
247e62314SPatrick Delaunay  * Copyright (C) 2022-2024, STMicroelectronics - All Rights Reserved
306e55dc8SNicolas Le Bayon  *
406e55dc8SNicolas Le Bayon  * SPDX-License-Identifier: BSD-3-Clause
506e55dc8SNicolas Le Bayon  */
606e55dc8SNicolas Le Bayon 
715ca2c5eSYann Gautier #include <common/debug.h>
806e55dc8SNicolas Le Bayon #include <drivers/delay_timer.h>
906e55dc8SNicolas Le Bayon #include <drivers/st/stm32mp_ddr.h>
1006e55dc8SNicolas Le Bayon #include <drivers/st/stm32mp_ddrctrl_regs.h>
1106e55dc8SNicolas Le Bayon #include <lib/mmio.h>
1206e55dc8SNicolas Le Bayon 
1306e55dc8SNicolas Le Bayon #include <platform_def.h>
1406e55dc8SNicolas Le Bayon 
1506e55dc8SNicolas Le Bayon #define INVALID_OFFSET	0xFFU
1606e55dc8SNicolas Le Bayon 
17*d596023bSNicolas Le Bayon static bool axi_port_reenable_request;
18*d596023bSNicolas Le Bayon static bool host_interface_reenable_request;
19*d596023bSNicolas Le Bayon 
2006e55dc8SNicolas Le Bayon static uintptr_t get_base_addr(const struct stm32mp_ddr_priv *priv, enum stm32mp_ddr_base_type base)
2106e55dc8SNicolas Le Bayon {
2206e55dc8SNicolas Le Bayon 	if (base == DDRPHY_BASE) {
2306e55dc8SNicolas Le Bayon 		return (uintptr_t)priv->phy;
2406e55dc8SNicolas Le Bayon 	} else {
2506e55dc8SNicolas Le Bayon 		return (uintptr_t)priv->ctl;
2606e55dc8SNicolas Le Bayon 	}
2706e55dc8SNicolas Le Bayon }
2806e55dc8SNicolas Le Bayon 
2906e55dc8SNicolas Le Bayon void stm32mp_ddr_set_reg(const struct stm32mp_ddr_priv *priv, enum stm32mp_ddr_reg_type type,
3006e55dc8SNicolas Le Bayon 			 const void *param, const struct stm32mp_ddr_reg_info *ddr_registers)
3106e55dc8SNicolas Le Bayon {
3206e55dc8SNicolas Le Bayon 	unsigned int i;
3306e55dc8SNicolas Le Bayon 	unsigned int value;
3406e55dc8SNicolas Le Bayon 	enum stm32mp_ddr_base_type base = ddr_registers[type].base;
3506e55dc8SNicolas Le Bayon 	uintptr_t base_addr = get_base_addr(priv, base);
3606e55dc8SNicolas Le Bayon 	const struct stm32mp_ddr_reg_desc *desc = ddr_registers[type].desc;
3706e55dc8SNicolas Le Bayon 
3806e55dc8SNicolas Le Bayon 	VERBOSE("init %s\n", ddr_registers[type].name);
3906e55dc8SNicolas Le Bayon 	for (i = 0; i < ddr_registers[type].size; i++) {
4006e55dc8SNicolas Le Bayon 		uintptr_t ptr = base_addr + desc[i].offset;
4106e55dc8SNicolas Le Bayon 
4206e55dc8SNicolas Le Bayon 		if (desc[i].par_offset == INVALID_OFFSET) {
431483b3c3SYann Gautier 			ERROR("invalid parameter offset for %s - index %u",
441483b3c3SYann Gautier 			      ddr_registers[type].name, i);
4506e55dc8SNicolas Le Bayon 			panic();
4606e55dc8SNicolas Le Bayon 		} else {
4706e55dc8SNicolas Le Bayon 			value = *((uint32_t *)((uintptr_t)param +
4806e55dc8SNicolas Le Bayon 					       desc[i].par_offset));
4906e55dc8SNicolas Le Bayon 			mmio_write_32(ptr, value);
5006e55dc8SNicolas Le Bayon 		}
5106e55dc8SNicolas Le Bayon 	}
5206e55dc8SNicolas Le Bayon }
5306e55dc8SNicolas Le Bayon 
5406e55dc8SNicolas Le Bayon /* Start quasi dynamic register update */
5506e55dc8SNicolas Le Bayon void stm32mp_ddr_start_sw_done(struct stm32mp_ddrctl *ctl)
5606e55dc8SNicolas Le Bayon {
5706e55dc8SNicolas Le Bayon 	mmio_clrbits_32((uintptr_t)&ctl->swctl, DDRCTRL_SWCTL_SW_DONE);
5806e55dc8SNicolas Le Bayon 	VERBOSE("[0x%lx] swctl = 0x%x\n",
5906e55dc8SNicolas Le Bayon 		(uintptr_t)&ctl->swctl,  mmio_read_32((uintptr_t)&ctl->swctl));
6006e55dc8SNicolas Le Bayon }
6106e55dc8SNicolas Le Bayon 
6206e55dc8SNicolas Le Bayon /* Wait quasi dynamic register update */
6306e55dc8SNicolas Le Bayon void stm32mp_ddr_wait_sw_done_ack(struct stm32mp_ddrctl *ctl)
6406e55dc8SNicolas Le Bayon {
6506e55dc8SNicolas Le Bayon 	uint64_t timeout;
6606e55dc8SNicolas Le Bayon 	uint32_t swstat;
6706e55dc8SNicolas Le Bayon 
6806e55dc8SNicolas Le Bayon 	mmio_setbits_32((uintptr_t)&ctl->swctl, DDRCTRL_SWCTL_SW_DONE);
6906e55dc8SNicolas Le Bayon 	VERBOSE("[0x%lx] swctl = 0x%x\n",
7006e55dc8SNicolas Le Bayon 		(uintptr_t)&ctl->swctl, mmio_read_32((uintptr_t)&ctl->swctl));
7106e55dc8SNicolas Le Bayon 
72066a5958SYann Gautier 	timeout = timeout_init_us(DDR_TIMEOUT_US_1S);
7306e55dc8SNicolas Le Bayon 	do {
7406e55dc8SNicolas Le Bayon 		swstat = mmio_read_32((uintptr_t)&ctl->swstat);
7506e55dc8SNicolas Le Bayon 		VERBOSE("[0x%lx] swstat = 0x%x ",
7606e55dc8SNicolas Le Bayon 			(uintptr_t)&ctl->swstat, swstat);
7706e55dc8SNicolas Le Bayon 		if (timeout_elapsed(timeout)) {
7806e55dc8SNicolas Le Bayon 			panic();
7906e55dc8SNicolas Le Bayon 		}
8006e55dc8SNicolas Le Bayon 	} while ((swstat & DDRCTRL_SWSTAT_SW_DONE_ACK) == 0U);
8106e55dc8SNicolas Le Bayon 
8206e55dc8SNicolas Le Bayon 	VERBOSE("[0x%lx] swstat = 0x%x\n",
8306e55dc8SNicolas Le Bayon 		(uintptr_t)&ctl->swstat, swstat);
8406e55dc8SNicolas Le Bayon }
8506e55dc8SNicolas Le Bayon 
8606e55dc8SNicolas Le Bayon void stm32mp_ddr_enable_axi_port(struct stm32mp_ddrctl *ctl)
8706e55dc8SNicolas Le Bayon {
8806e55dc8SNicolas Le Bayon 	/* Enable uMCTL2 AXI port 0 */
8906e55dc8SNicolas Le Bayon 	mmio_setbits_32((uintptr_t)&ctl->pctrl_0, DDRCTRL_PCTRL_N_PORT_EN);
9006e55dc8SNicolas Le Bayon 	VERBOSE("[0x%lx] pctrl_0 = 0x%x\n", (uintptr_t)&ctl->pctrl_0,
9106e55dc8SNicolas Le Bayon 		mmio_read_32((uintptr_t)&ctl->pctrl_0));
9206e55dc8SNicolas Le Bayon 
9306e55dc8SNicolas Le Bayon #if STM32MP_DDR_DUAL_AXI_PORT
9406e55dc8SNicolas Le Bayon 	/* Enable uMCTL2 AXI port 1 */
9506e55dc8SNicolas Le Bayon 	mmio_setbits_32((uintptr_t)&ctl->pctrl_1, DDRCTRL_PCTRL_N_PORT_EN);
9606e55dc8SNicolas Le Bayon 	VERBOSE("[0x%lx] pctrl_1 = 0x%x\n", (uintptr_t)&ctl->pctrl_1,
9706e55dc8SNicolas Le Bayon 		mmio_read_32((uintptr_t)&ctl->pctrl_1));
9806e55dc8SNicolas Le Bayon #endif
99*d596023bSNicolas Le Bayon }
10006e55dc8SNicolas Le Bayon 
101*d596023bSNicolas Le Bayon int stm32mp_ddr_disable_axi_port(struct stm32mp_ddrctl *ctl)
102*d596023bSNicolas Le Bayon {
103*d596023bSNicolas Le Bayon 	uint64_t timeout;
104*d596023bSNicolas Le Bayon 	uint32_t pstat;
105*d596023bSNicolas Le Bayon 
106*d596023bSNicolas Le Bayon 	/* Disable uMCTL2 AXI port 0 */
107*d596023bSNicolas Le Bayon 	mmio_clrbits_32((uintptr_t)&ctl->pctrl_0, DDRCTRL_PCTRL_N_PORT_EN);
108*d596023bSNicolas Le Bayon 	VERBOSE("[0x%lx] pctrl_0 = 0x%x\n", (uintptr_t)&ctl->pctrl_0,
109*d596023bSNicolas Le Bayon 		mmio_read_32((uintptr_t)&ctl->pctrl_0));
110*d596023bSNicolas Le Bayon 
111*d596023bSNicolas Le Bayon #if STM32MP_DDR_DUAL_AXI_PORT
112*d596023bSNicolas Le Bayon 	/* Disable uMCTL2 AXI port 1 */
113*d596023bSNicolas Le Bayon 	mmio_clrbits_32((uintptr_t)&ctl->pctrl_1, DDRCTRL_PCTRL_N_PORT_EN);
114*d596023bSNicolas Le Bayon 	VERBOSE("[0x%lx] pctrl_1 = 0x%x\n", (uintptr_t)&ctl->pctrl_1,
115*d596023bSNicolas Le Bayon 		mmio_read_32((uintptr_t)&ctl->pctrl_1));
116*d596023bSNicolas Le Bayon #endif
117*d596023bSNicolas Le Bayon 
118*d596023bSNicolas Le Bayon 	/*
119*d596023bSNicolas Le Bayon 	 * Waits until all AXI ports are idle
120*d596023bSNicolas Le Bayon 	 * Poll PSTAT.rd_port_busy_n = 0
121*d596023bSNicolas Le Bayon 	 * Poll PSTAT.wr_port_busy_n = 0
122*d596023bSNicolas Le Bayon 	 */
123*d596023bSNicolas Le Bayon 	timeout = timeout_init_us(DDR_TIMEOUT_US_1S);
124*d596023bSNicolas Le Bayon 	do {
125*d596023bSNicolas Le Bayon 		pstat = mmio_read_32((uintptr_t)&ctl->pstat);
126*d596023bSNicolas Le Bayon 		VERBOSE("[0x%lx] pstat = 0x%x ",
127*d596023bSNicolas Le Bayon 			(uintptr_t)&ctl->pstat, pstat);
128*d596023bSNicolas Le Bayon 		if (timeout_elapsed(timeout)) {
129*d596023bSNicolas Le Bayon 			return -1;
130*d596023bSNicolas Le Bayon 		}
131*d596023bSNicolas Le Bayon 	} while (pstat != 0U);
132*d596023bSNicolas Le Bayon 
133*d596023bSNicolas Le Bayon 	return 0;
134*d596023bSNicolas Le Bayon }
135*d596023bSNicolas Le Bayon 
136*d596023bSNicolas Le Bayon static bool ddr_is_axi_port_enabled(struct stm32mp_ddrctl *ctl)
137*d596023bSNicolas Le Bayon {
138*d596023bSNicolas Le Bayon 	return (mmio_read_32((uintptr_t)&ctl->pctrl_0) & DDRCTRL_PCTRL_N_PORT_EN) != 0U;
139*d596023bSNicolas Le Bayon }
140*d596023bSNicolas Le Bayon 
141*d596023bSNicolas Le Bayon void stm32mp_ddr_enable_host_interface(struct stm32mp_ddrctl *ctl)
142*d596023bSNicolas Le Bayon {
143*d596023bSNicolas Le Bayon 	mmio_clrbits_32((uintptr_t)&ctl->dbg1, DDRCTRL_DBG1_DIS_HIF);
144*d596023bSNicolas Le Bayon 	VERBOSE("[0x%lx] dbg1 = 0x%x\n",
145*d596023bSNicolas Le Bayon 		(uintptr_t)&ctl->dbg1,
146*d596023bSNicolas Le Bayon 		mmio_read_32((uintptr_t)&ctl->dbg1));
147*d596023bSNicolas Le Bayon }
148*d596023bSNicolas Le Bayon 
149*d596023bSNicolas Le Bayon void stm32mp_ddr_disable_host_interface(struct stm32mp_ddrctl *ctl)
150*d596023bSNicolas Le Bayon {
151*d596023bSNicolas Le Bayon 	uint64_t timeout;
152*d596023bSNicolas Le Bayon 	uint32_t dbgcam;
153*d596023bSNicolas Le Bayon 	int count = 0;
154*d596023bSNicolas Le Bayon 
155*d596023bSNicolas Le Bayon 	mmio_setbits_32((uintptr_t)&ctl->dbg1, DDRCTRL_DBG1_DIS_HIF);
156*d596023bSNicolas Le Bayon 	VERBOSE("[0x%lx] dbg1 = 0x%x\n",
157*d596023bSNicolas Le Bayon 		(uintptr_t)&ctl->dbg1,
158*d596023bSNicolas Le Bayon 		mmio_read_32((uintptr_t)&ctl->dbg1));
159*d596023bSNicolas Le Bayon 
160*d596023bSNicolas Le Bayon 	/*
161*d596023bSNicolas Le Bayon 	 * Waits until all queues and pipelines are empty
162*d596023bSNicolas Le Bayon 	 * Poll DBGCAM.dbg_wr_q_empty = 1
163*d596023bSNicolas Le Bayon 	 * Poll DBGCAM.dbg_rd_q_empty = 1
164*d596023bSNicolas Le Bayon 	 * Poll DBGCAM.dbg_wr_data_pipeline_empty = 1
165*d596023bSNicolas Le Bayon 	 * Poll DBGCAM.dbg_rd_data_pipeline_empty = 1
166*d596023bSNicolas Le Bayon 	 *
167*d596023bSNicolas Le Bayon 	 * data_pipeline fields must be polled twice to ensure
168*d596023bSNicolas Le Bayon 	 * value propoagation, so count is added to loop condition.
169*d596023bSNicolas Le Bayon 	 */
170*d596023bSNicolas Le Bayon 	timeout = timeout_init_us(DDR_TIMEOUT_US_1S);
171*d596023bSNicolas Le Bayon 	do {
172*d596023bSNicolas Le Bayon 		dbgcam = mmio_read_32((uintptr_t)&ctl->dbgcam);
173*d596023bSNicolas Le Bayon 		VERBOSE("[0x%lx] dbgcam = 0x%x ",
174*d596023bSNicolas Le Bayon 			(uintptr_t)&ctl->dbgcam, dbgcam);
175*d596023bSNicolas Le Bayon 		if (timeout_elapsed(timeout)) {
176*d596023bSNicolas Le Bayon 			panic();
177*d596023bSNicolas Le Bayon 		}
178*d596023bSNicolas Le Bayon 		count++;
179*d596023bSNicolas Le Bayon 	} while (((dbgcam & DDRCTRL_DBG_Q_AND_DATA_PIPELINE_EMPTY) !=
180*d596023bSNicolas Le Bayon 		  DDRCTRL_DBG_Q_AND_DATA_PIPELINE_EMPTY) || (count < 2));
181*d596023bSNicolas Le Bayon }
182*d596023bSNicolas Le Bayon 
183*d596023bSNicolas Le Bayon static bool ddr_is_host_interface_enabled(struct stm32mp_ddrctl *ctl)
184*d596023bSNicolas Le Bayon {
185*d596023bSNicolas Le Bayon 	return (mmio_read_32((uintptr_t)&ctl->dbg1) & DDRCTRL_DBG1_DIS_HIF) == 0U;
186*d596023bSNicolas Le Bayon }
187*d596023bSNicolas Le Bayon 
188*d596023bSNicolas Le Bayon int stm32mp_ddr_sw_selfref_entry(struct stm32mp_ddrctl *ctl)
189*d596023bSNicolas Le Bayon {
190*d596023bSNicolas Le Bayon 	uint64_t timeout;
191*d596023bSNicolas Le Bayon 	uint32_t stat;
192*d596023bSNicolas Le Bayon 	uint32_t operating_mode;
193*d596023bSNicolas Le Bayon 	uint32_t selref_type;
194*d596023bSNicolas Le Bayon 
195*d596023bSNicolas Le Bayon 	mmio_setbits_32((uintptr_t)&ctl->pwrctl, DDRCTRL_PWRCTL_SELFREF_SW);
196*d596023bSNicolas Le Bayon 	VERBOSE("[0x%lx] pwrctl = 0x%x\n",
197*d596023bSNicolas Le Bayon 		(uintptr_t)&ctl->pwrctl,
198*d596023bSNicolas Le Bayon 		mmio_read_32((uintptr_t)&ctl->pwrctl));
199*d596023bSNicolas Le Bayon 
200*d596023bSNicolas Le Bayon 	/*
201*d596023bSNicolas Le Bayon 	 * Wait operating mode change in self-refresh mode
202*d596023bSNicolas Le Bayon 	 * with STAT.operating_mode[1:0]==11.
203*d596023bSNicolas Le Bayon 	 * Ensure transition to self-refresh was due to software
204*d596023bSNicolas Le Bayon 	 * by checking also that STAT.selfref_type[1:0]=2.
205*d596023bSNicolas Le Bayon 	 */
206*d596023bSNicolas Le Bayon 	timeout = timeout_init_us(DDR_TIMEOUT_500US);
207*d596023bSNicolas Le Bayon 	while (!timeout_elapsed(timeout)) {
208*d596023bSNicolas Le Bayon 		stat = mmio_read_32((uintptr_t)&ctl->stat);
209*d596023bSNicolas Le Bayon 		operating_mode = stat & DDRCTRL_STAT_OPERATING_MODE_MASK;
210*d596023bSNicolas Le Bayon 		selref_type = stat & DDRCTRL_STAT_SELFREF_TYPE_MASK;
211*d596023bSNicolas Le Bayon 
212*d596023bSNicolas Le Bayon 		if ((operating_mode == DDRCTRL_STAT_OPERATING_MODE_SR) &&
213*d596023bSNicolas Le Bayon 		    (selref_type == DDRCTRL_STAT_SELFREF_TYPE_SR)) {
214*d596023bSNicolas Le Bayon 			return 0;
215*d596023bSNicolas Le Bayon 		}
216*d596023bSNicolas Le Bayon 	}
217*d596023bSNicolas Le Bayon 
218*d596023bSNicolas Le Bayon 	return -1;
219*d596023bSNicolas Le Bayon }
220*d596023bSNicolas Le Bayon 
221*d596023bSNicolas Le Bayon void stm32mp_ddr_sw_selfref_exit(struct stm32mp_ddrctl *ctl)
222*d596023bSNicolas Le Bayon {
223*d596023bSNicolas Le Bayon 	mmio_clrbits_32((uintptr_t)&ctl->pwrctl, DDRCTRL_PWRCTL_SELFREF_SW);
224*d596023bSNicolas Le Bayon 	VERBOSE("[0x%lx] pwrctl = 0x%x\n",
225*d596023bSNicolas Le Bayon 		(uintptr_t)&ctl->pwrctl,
226*d596023bSNicolas Le Bayon 		mmio_read_32((uintptr_t)&ctl->pwrctl));
227*d596023bSNicolas Le Bayon }
228*d596023bSNicolas Le Bayon 
229*d596023bSNicolas Le Bayon void stm32mp_ddr_set_qd3_update_conditions(struct stm32mp_ddrctl *ctl)
230*d596023bSNicolas Le Bayon {
231*d596023bSNicolas Le Bayon 	if (ddr_is_axi_port_enabled(ctl)) {
232*d596023bSNicolas Le Bayon 		if (stm32mp_ddr_disable_axi_port(ctl) != 0) {
233*d596023bSNicolas Le Bayon 			panic();
234*d596023bSNicolas Le Bayon 		}
235*d596023bSNicolas Le Bayon 		axi_port_reenable_request = true;
236*d596023bSNicolas Le Bayon 	}
237*d596023bSNicolas Le Bayon 
238*d596023bSNicolas Le Bayon 	if (ddr_is_host_interface_enabled(ctl)) {
239*d596023bSNicolas Le Bayon 		stm32mp_ddr_disable_host_interface(ctl);
240*d596023bSNicolas Le Bayon 		host_interface_reenable_request = true;
241*d596023bSNicolas Le Bayon 	}
242*d596023bSNicolas Le Bayon 
243*d596023bSNicolas Le Bayon 	stm32mp_ddr_start_sw_done(ctl);
244*d596023bSNicolas Le Bayon }
245*d596023bSNicolas Le Bayon 
246*d596023bSNicolas Le Bayon void stm32mp_ddr_unset_qd3_update_conditions(struct stm32mp_ddrctl *ctl)
247*d596023bSNicolas Le Bayon {
248*d596023bSNicolas Le Bayon 	stm32mp_ddr_wait_sw_done_ack(ctl);
249*d596023bSNicolas Le Bayon 
250*d596023bSNicolas Le Bayon 	if (host_interface_reenable_request) {
251*d596023bSNicolas Le Bayon 		stm32mp_ddr_enable_host_interface(ctl);
252*d596023bSNicolas Le Bayon 		host_interface_reenable_request = false;
253*d596023bSNicolas Le Bayon 	}
254*d596023bSNicolas Le Bayon 
255*d596023bSNicolas Le Bayon 	if (axi_port_reenable_request) {
256*d596023bSNicolas Le Bayon 		stm32mp_ddr_enable_axi_port(ctl);
257*d596023bSNicolas Le Bayon 		axi_port_reenable_request = false;
258*d596023bSNicolas Le Bayon 	}
259*d596023bSNicolas Le Bayon }
260*d596023bSNicolas Le Bayon 
261*d596023bSNicolas Le Bayon void stm32mp_ddr_wait_refresh_update_done_ack(struct stm32mp_ddrctl *ctl)
262*d596023bSNicolas Le Bayon {
263*d596023bSNicolas Le Bayon 	uint64_t timeout;
264*d596023bSNicolas Le Bayon 	uint32_t rfshctl3;
265*d596023bSNicolas Le Bayon 	uint32_t refresh_update_level = DDRCTRL_RFSHCTL3_REFRESH_UPDATE_LEVEL;
266*d596023bSNicolas Le Bayon 
267*d596023bSNicolas Le Bayon 	/* Toggle rfshctl3.refresh_update_level */
268*d596023bSNicolas Le Bayon 	rfshctl3 = mmio_read_32((uintptr_t)&ctl->rfshctl3);
269*d596023bSNicolas Le Bayon 	if ((rfshctl3 & refresh_update_level) == refresh_update_level) {
270*d596023bSNicolas Le Bayon 		mmio_setbits_32((uintptr_t)&ctl->rfshctl3, refresh_update_level);
271*d596023bSNicolas Le Bayon 	} else {
272*d596023bSNicolas Le Bayon 		mmio_clrbits_32((uintptr_t)&ctl->rfshctl3, refresh_update_level);
273*d596023bSNicolas Le Bayon 		refresh_update_level = 0U;
274*d596023bSNicolas Le Bayon 	}
275*d596023bSNicolas Le Bayon 
276*d596023bSNicolas Le Bayon 	VERBOSE("[0x%lx] rfshctl3 = 0x%x\n",
277*d596023bSNicolas Le Bayon 		(uintptr_t)&ctl->rfshctl3, mmio_read_32((uintptr_t)&ctl->rfshctl3));
278*d596023bSNicolas Le Bayon 
279*d596023bSNicolas Le Bayon 	timeout = timeout_init_us(DDR_TIMEOUT_US_1S);
280*d596023bSNicolas Le Bayon 	do {
281*d596023bSNicolas Le Bayon 		rfshctl3 = mmio_read_32((uintptr_t)&ctl->rfshctl3);
282*d596023bSNicolas Le Bayon 		VERBOSE("[0x%lx] rfshctl3 = 0x%x ", (uintptr_t)&ctl->rfshctl3, rfshctl3);
283*d596023bSNicolas Le Bayon 		if (timeout_elapsed(timeout)) {
284*d596023bSNicolas Le Bayon 			panic();
285*d596023bSNicolas Le Bayon 		}
286*d596023bSNicolas Le Bayon 	} while ((rfshctl3 & DDRCTRL_RFSHCTL3_REFRESH_UPDATE_LEVEL) != refresh_update_level);
287*d596023bSNicolas Le Bayon 
288*d596023bSNicolas Le Bayon 	VERBOSE("[0x%lx] rfshctl3 = 0x%x\n", (uintptr_t)&ctl->rfshctl3, rfshctl3);
28906e55dc8SNicolas Le Bayon }
290