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