xref: /rk3399_ARM-atf/plat/imx/imx8m/ddr/dram_retention.c (revision c71793c6476fa2828f866b8d7b272289f0d9a15c)
1*c71793c6SJacky Bai /*
2*c71793c6SJacky Bai  * Copyright 2018-2022 NXP
3*c71793c6SJacky Bai  *
4*c71793c6SJacky Bai  * SPDX-License-Identifier: BSD-3-Clause
5*c71793c6SJacky Bai  */
6*c71793c6SJacky Bai 
7*c71793c6SJacky Bai #include <stdbool.h>
8*c71793c6SJacky Bai #include <lib/mmio.h>
9*c71793c6SJacky Bai 
10*c71793c6SJacky Bai #include <dram.h>
11*c71793c6SJacky Bai #include <platform_def.h>
12*c71793c6SJacky Bai 
13*c71793c6SJacky Bai #define SRC_DDR1_RCR		(IMX_SRC_BASE + 0x1000)
14*c71793c6SJacky Bai #define SRC_DDR2_RCR		(IMX_SRC_BASE + 0x1004)
15*c71793c6SJacky Bai 
16*c71793c6SJacky Bai #define PU_PGC_UP_TRG		0xf8
17*c71793c6SJacky Bai #define PU_PGC_DN_TRG		0x104
18*c71793c6SJacky Bai #define GPC_PU_PWRHSK		(IMX_GPC_BASE + 0x01FC)
19*c71793c6SJacky Bai #define CCM_SRC_CTRL_OFFSET     (IMX_CCM_BASE + 0x800)
20*c71793c6SJacky Bai #define CCM_CCGR_OFFSET         (IMX_CCM_BASE + 0x4000)
21*c71793c6SJacky Bai #define CCM_SRC_CTRL(n)		(CCM_SRC_CTRL_OFFSET + 0x10 * (n))
22*c71793c6SJacky Bai #define CCM_CCGR(n)		(CCM_CCGR_OFFSET + 0x10 * (n))
23*c71793c6SJacky Bai 
24*c71793c6SJacky Bai #define DRAM_PLL_CTRL		(IMX_ANAMIX_BASE + 0x50)
25*c71793c6SJacky Bai 
26*c71793c6SJacky Bai #define DBGCAM_EMPTY		0x36000000
27*c71793c6SJacky Bai 
28*c71793c6SJacky Bai void dram_enter_retention(void)
29*c71793c6SJacky Bai {
30*c71793c6SJacky Bai 	/* Wait DBGCAM to be empty */
31*c71793c6SJacky Bai 	while (mmio_read_32(DDRC_DBGCAM(0)) != DBGCAM_EMPTY) {
32*c71793c6SJacky Bai 		;
33*c71793c6SJacky Bai 	}
34*c71793c6SJacky Bai 
35*c71793c6SJacky Bai 	/* Block AXI ports from taking anymore transactions */
36*c71793c6SJacky Bai 	mmio_write_32(DDRC_PCTRL_0(0), 0x0);
37*c71793c6SJacky Bai 	/* Wait until all AXI ports are idle */
38*c71793c6SJacky Bai 	while (mmio_read_32(DDRC_PSTAT(0)) & 0x10001) {
39*c71793c6SJacky Bai 		;
40*c71793c6SJacky Bai 	}
41*c71793c6SJacky Bai 
42*c71793c6SJacky Bai 	/* Enter self refresh */
43*c71793c6SJacky Bai 	mmio_write_32(DDRC_PWRCTL(0), 0xaa);
44*c71793c6SJacky Bai 
45*c71793c6SJacky Bai 	/* LPDDR4 & DDR4/DDR3L need to check different status */
46*c71793c6SJacky Bai 	if (dram_info.dram_type == DDRC_LPDDR4) {
47*c71793c6SJacky Bai 		while (0x223 != (mmio_read_32(DDRC_STAT(0)) & 0x33f)) {
48*c71793c6SJacky Bai 			;
49*c71793c6SJacky Bai 		}
50*c71793c6SJacky Bai 	} else {
51*c71793c6SJacky Bai 		while (0x23 != (mmio_read_32(DDRC_STAT(0)) & 0x3f)) {
52*c71793c6SJacky Bai 			;
53*c71793c6SJacky Bai 		}
54*c71793c6SJacky Bai 	}
55*c71793c6SJacky Bai 
56*c71793c6SJacky Bai 	mmio_write_32(DDRC_DFIMISC(0), 0x0);
57*c71793c6SJacky Bai 	mmio_write_32(DDRC_SWCTL(0), 0x0);
58*c71793c6SJacky Bai 	mmio_write_32(DDRC_DFIMISC(0), 0x1f00);
59*c71793c6SJacky Bai 	mmio_write_32(DDRC_DFIMISC(0), 0x1f20);
60*c71793c6SJacky Bai 
61*c71793c6SJacky Bai 	while (mmio_read_32(DDRC_DFISTAT(0)) & 0x1) {
62*c71793c6SJacky Bai 		;
63*c71793c6SJacky Bai 	}
64*c71793c6SJacky Bai 
65*c71793c6SJacky Bai 	mmio_write_32(DDRC_DFIMISC(0), 0x1f00);
66*c71793c6SJacky Bai 	/* wait DFISTAT.dfi_init_complete to 1 */
67*c71793c6SJacky Bai 	while (!(mmio_read_32(DDRC_DFISTAT(0)) & 0x1)) {
68*c71793c6SJacky Bai 		;
69*c71793c6SJacky Bai 	}
70*c71793c6SJacky Bai 
71*c71793c6SJacky Bai 	mmio_write_32(DDRC_SWCTL(0), 0x1);
72*c71793c6SJacky Bai 
73*c71793c6SJacky Bai 	/* should check PhyInLP3 pub reg */
74*c71793c6SJacky Bai 	dwc_ddrphy_apb_wr(0xd0000, 0x0);
75*c71793c6SJacky Bai 	if (!(dwc_ddrphy_apb_rd(0x90028) & 0x1)) {
76*c71793c6SJacky Bai 		INFO("PhyInLP3 = 1\n");
77*c71793c6SJacky Bai 	}
78*c71793c6SJacky Bai 	dwc_ddrphy_apb_wr(0xd0000, 0x1);
79*c71793c6SJacky Bai 
80*c71793c6SJacky Bai #if defined(PLAT_imx8mq)
81*c71793c6SJacky Bai 	/* pwrdnreqn_async adbm/adbs of ddr */
82*c71793c6SJacky Bai 	mmio_clrbits_32(GPC_PU_PWRHSK, BIT(1));
83*c71793c6SJacky Bai 	while (mmio_read_32(GPC_PU_PWRHSK) & BIT(18)) {
84*c71793c6SJacky Bai 		;
85*c71793c6SJacky Bai 	}
86*c71793c6SJacky Bai 	mmio_setbits_32(GPC_PU_PWRHSK, BIT(1));
87*c71793c6SJacky Bai #else
88*c71793c6SJacky Bai 	/* pwrdnreqn_async adbm/adbs of ddr */
89*c71793c6SJacky Bai 	mmio_clrbits_32(GPC_PU_PWRHSK, BIT(2));
90*c71793c6SJacky Bai 	while (mmio_read_32(GPC_PU_PWRHSK) & BIT(20)) {
91*c71793c6SJacky Bai 		;
92*c71793c6SJacky Bai 	}
93*c71793c6SJacky Bai 	mmio_setbits_32(GPC_PU_PWRHSK, BIT(2));
94*c71793c6SJacky Bai #endif
95*c71793c6SJacky Bai 	/* remove PowerOk */
96*c71793c6SJacky Bai 	mmio_write_32(SRC_DDR1_RCR, 0x8F000008);
97*c71793c6SJacky Bai 
98*c71793c6SJacky Bai 	mmio_write_32(CCM_CCGR(5), 0);
99*c71793c6SJacky Bai 	mmio_write_32(CCM_SRC_CTRL(15), 2);
100*c71793c6SJacky Bai 
101*c71793c6SJacky Bai 	/* enable the phy iso */
102*c71793c6SJacky Bai 	mmio_setbits_32(IMX_GPC_BASE + 0xd40, 1);
103*c71793c6SJacky Bai 	mmio_setbits_32(IMX_GPC_BASE + PU_PGC_DN_TRG, BIT(5));
104*c71793c6SJacky Bai 
105*c71793c6SJacky Bai 	VERBOSE("dram enter retention\n");
106*c71793c6SJacky Bai }
107*c71793c6SJacky Bai 
108*c71793c6SJacky Bai void dram_exit_retention(void)
109*c71793c6SJacky Bai {
110*c71793c6SJacky Bai 	VERBOSE("dram exit retention\n");
111*c71793c6SJacky Bai 	/* assert all reset */
112*c71793c6SJacky Bai #if defined(PLAT_imx8mq)
113*c71793c6SJacky Bai 	mmio_write_32(SRC_DDR2_RCR, 0x8F000003);
114*c71793c6SJacky Bai 	mmio_write_32(SRC_DDR1_RCR, 0x8F00000F);
115*c71793c6SJacky Bai 	mmio_write_32(SRC_DDR2_RCR, 0x8F000000);
116*c71793c6SJacky Bai #else
117*c71793c6SJacky Bai 	mmio_write_32(SRC_DDR1_RCR, 0x8F00001F);
118*c71793c6SJacky Bai 	mmio_write_32(SRC_DDR1_RCR, 0x8F00000F);
119*c71793c6SJacky Bai #endif
120*c71793c6SJacky Bai 	mmio_write_32(CCM_CCGR(5), 2);
121*c71793c6SJacky Bai 	mmio_write_32(CCM_SRC_CTRL(15), 2);
122*c71793c6SJacky Bai 
123*c71793c6SJacky Bai 	/* disable iso */
124*c71793c6SJacky Bai 	mmio_setbits_32(IMX_GPC_BASE + PU_PGC_UP_TRG, BIT(5));
125*c71793c6SJacky Bai 	mmio_write_32(SRC_DDR1_RCR, 0x8F000006);
126*c71793c6SJacky Bai 
127*c71793c6SJacky Bai 	/* wait dram pll locked */
128*c71793c6SJacky Bai 	while (!(mmio_read_32(DRAM_PLL_CTRL) & BIT(31))) {
129*c71793c6SJacky Bai 		;
130*c71793c6SJacky Bai 	}
131*c71793c6SJacky Bai 
132*c71793c6SJacky Bai 	/* ddrc re-init */
133*c71793c6SJacky Bai 	dram_umctl2_init(dram_info.timing_info);
134*c71793c6SJacky Bai 
135*c71793c6SJacky Bai 	/*
136*c71793c6SJacky Bai 	 * Skips the DRAM init routine and starts up in selfrefresh mode
137*c71793c6SJacky Bai 	 * Program INIT0.skip_dram_init = 2'b11
138*c71793c6SJacky Bai 	 */
139*c71793c6SJacky Bai 	mmio_setbits_32(DDRC_INIT0(0), 0xc0000000);
140*c71793c6SJacky Bai 	/* Keeps the controller in self-refresh mode */
141*c71793c6SJacky Bai 	mmio_write_32(DDRC_PWRCTL(0), 0xaa);
142*c71793c6SJacky Bai 	mmio_write_32(DDRC_DBG1(0), 0x0);
143*c71793c6SJacky Bai 	mmio_write_32(SRC_DDR1_RCR, 0x8F000004);
144*c71793c6SJacky Bai 	mmio_write_32(SRC_DDR1_RCR, 0x8F000000);
145*c71793c6SJacky Bai 
146*c71793c6SJacky Bai 	/* before write Dynamic reg, sw_done should be 0 */
147*c71793c6SJacky Bai 	mmio_write_32(DDRC_SWCTL(0), 0x0);
148*c71793c6SJacky Bai 	if (dram_info.dram_type == DDRC_LPDDR4) {
149*c71793c6SJacky Bai 		mmio_write_32(DDRC_DDR_SS_GPR0, 0x01); /*LPDDR4 mode */
150*c71793c6SJacky Bai 	}
151*c71793c6SJacky Bai 	mmio_write_32(DDRC_DFIMISC(0), 0x0);
152*c71793c6SJacky Bai 
153*c71793c6SJacky Bai 	/* dram phy re-init */
154*c71793c6SJacky Bai 	dram_phy_init(dram_info.timing_info);
155*c71793c6SJacky Bai 
156*c71793c6SJacky Bai 	/* DWC_DDRPHYA_APBONLY0_MicroContMuxSel */
157*c71793c6SJacky Bai 	dwc_ddrphy_apb_wr(0xd0000, 0x0);
158*c71793c6SJacky Bai 	while (dwc_ddrphy_apb_rd(0x20097)) {
159*c71793c6SJacky Bai 		;
160*c71793c6SJacky Bai 	}
161*c71793c6SJacky Bai 	dwc_ddrphy_apb_wr(0xd0000, 0x1);
162*c71793c6SJacky Bai 
163*c71793c6SJacky Bai 	/* before write Dynamic reg, sw_done should be 0 */
164*c71793c6SJacky Bai 	mmio_write_32(DDRC_SWCTL(0), 0x0);
165*c71793c6SJacky Bai 	mmio_write_32(DDRC_DFIMISC(0), 0x20);
166*c71793c6SJacky Bai 	/* wait DFISTAT.dfi_init_complete to 1 */
167*c71793c6SJacky Bai 	while (!(mmio_read_32(DDRC_DFISTAT(0)) & 0x1)) {
168*c71793c6SJacky Bai 		;
169*c71793c6SJacky Bai 	}
170*c71793c6SJacky Bai 
171*c71793c6SJacky Bai 	/* clear DFIMISC.dfi_init_start */
172*c71793c6SJacky Bai 	mmio_write_32(DDRC_DFIMISC(0), 0x0);
173*c71793c6SJacky Bai 	/* set DFIMISC.dfi_init_complete_en */
174*c71793c6SJacky Bai 	mmio_write_32(DDRC_DFIMISC(0), 0x1);
175*c71793c6SJacky Bai 
176*c71793c6SJacky Bai 	/* set SWCTL.sw_done to enable quasi-dynamic register programming */
177*c71793c6SJacky Bai 	mmio_write_32(DDRC_SWCTL(0), 0x1);
178*c71793c6SJacky Bai 	/* wait SWSTAT.sw_done_ack to 1 */
179*c71793c6SJacky Bai 	while (!(mmio_read_32(DDRC_SWSTAT(0)) & 0x1)) {
180*c71793c6SJacky Bai 		;
181*c71793c6SJacky Bai 	}
182*c71793c6SJacky Bai 
183*c71793c6SJacky Bai 	mmio_write_32(DDRC_PWRCTL(0), 0x88);
184*c71793c6SJacky Bai 	/* wait STAT to normal state */
185*c71793c6SJacky Bai 	while (0x1 != (mmio_read_32(DDRC_STAT(0)) & 0x7)) {
186*c71793c6SJacky Bai 		;
187*c71793c6SJacky Bai 	}
188*c71793c6SJacky Bai 
189*c71793c6SJacky Bai 	mmio_write_32(DDRC_PCTRL_0(0), 0x1);
190*c71793c6SJacky Bai 	 /* dis_auto-refresh is set to 0 */
191*c71793c6SJacky Bai 	mmio_write_32(DDRC_RFSHCTL3(0), 0x0);
192*c71793c6SJacky Bai 
193*c71793c6SJacky Bai 	/* should check PhyInLP3 pub reg */
194*c71793c6SJacky Bai 	dwc_ddrphy_apb_wr(0xd0000, 0x0);
195*c71793c6SJacky Bai 	if (!(dwc_ddrphy_apb_rd(0x90028) & 0x1)) {
196*c71793c6SJacky Bai 		VERBOSE("PHYInLP3 = 0\n");
197*c71793c6SJacky Bai 	}
198*c71793c6SJacky Bai 	dwc_ddrphy_apb_wr(0xd0000, 0x1);
199*c71793c6SJacky Bai }
200