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