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