blob: d98a37ee9d08fd9d41bbf05295a1f8e1a5b9e232 [file] [log] [blame]
Jacky Bai9a6f62f2019-11-25 14:43:26 +08001/*
Jacky Baidde85e02020-05-08 17:37:24 +08002 * Copyright 2018-2023 NXP
Jacky Bai9a6f62f2019-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>
Jacky Bai7512abc2020-03-23 15:54:01 +080011#include <gpc_reg.h>
Jacky Bai9a6f62f2019-11-25 14:43:26 +080012#include <platform_def.h>
13
14#define SRC_DDR1_RCR (IMX_SRC_BASE + 0x1000)
15#define SRC_DDR2_RCR (IMX_SRC_BASE + 0x1004)
16
Jacky Bai9a6f62f2019-11-25 14:43:26 +080017#define CCM_SRC_CTRL_OFFSET (IMX_CCM_BASE + 0x800)
18#define CCM_CCGR_OFFSET (IMX_CCM_BASE + 0x4000)
Jacky Bai469c2cc2020-10-22 14:35:12 +080019#define CCM_TARGET_ROOT_OFFSET (IMX_CCM_BASE + 0x8000)
Jacky Bai9a6f62f2019-11-25 14:43:26 +080020#define CCM_SRC_CTRL(n) (CCM_SRC_CTRL_OFFSET + 0x10 * (n))
21#define CCM_CCGR(n) (CCM_CCGR_OFFSET + 0x10 * (n))
Jacky Bai469c2cc2020-10-22 14:35:12 +080022#define CCM_TARGET_ROOT(n) (CCM_TARGET_ROOT_OFFSET + 0x80 * (n))
Jacky Bai9a6f62f2019-11-25 14:43:26 +080023
Jacky Bai9a6f62f2019-11-25 14:43:26 +080024#define DBGCAM_EMPTY 0x36000000
25
Jacky Baidde85e02020-05-08 17:37:24 +080026static void rank_setting_update(void)
27{
28 uint32_t i, offset;
29 uint32_t pstate_num = dram_info.num_fsp;
30
Jacky Baiff820ba2020-09-08 09:55:59 +080031 /* only support maximum 3 setpoints */
32 pstate_num = (pstate_num > MAX_FSP_NUM) ? MAX_FSP_NUM : pstate_num;
33
Jacky Baidde85e02020-05-08 17:37:24 +080034 for (i = 0U; i < pstate_num; i++) {
35 offset = i ? (i + 1) * 0x1000 : 0U;
36 mmio_write_32(DDRC_DRAMTMG2(0) + offset, dram_info.rank_setting[i][0]);
37 if (dram_info.dram_type != DDRC_LPDDR4) {
38 mmio_write_32(DDRC_DRAMTMG9(0) + offset, dram_info.rank_setting[i][1]);
39 }
40
41#if !defined(PLAT_imx8mq)
42 mmio_write_32(DDRC_RANKCTL(0) + offset,
43 dram_info.rank_setting[i][2]);
44#endif
45 }
46#if defined(PLAT_imx8mq)
47 mmio_write_32(DDRC_RANKCTL(0), dram_info.rank_setting[0][2]);
48#endif
49}
50
Jacky Bai9a6f62f2019-11-25 14:43:26 +080051void dram_enter_retention(void)
52{
53 /* Wait DBGCAM to be empty */
54 while (mmio_read_32(DDRC_DBGCAM(0)) != DBGCAM_EMPTY) {
55 ;
56 }
57
58 /* Block AXI ports from taking anymore transactions */
59 mmio_write_32(DDRC_PCTRL_0(0), 0x0);
60 /* Wait until all AXI ports are idle */
61 while (mmio_read_32(DDRC_PSTAT(0)) & 0x10001) {
62 ;
63 }
64
65 /* Enter self refresh */
66 mmio_write_32(DDRC_PWRCTL(0), 0xaa);
67
68 /* LPDDR4 & DDR4/DDR3L need to check different status */
69 if (dram_info.dram_type == DDRC_LPDDR4) {
70 while (0x223 != (mmio_read_32(DDRC_STAT(0)) & 0x33f)) {
71 ;
72 }
73 } else {
74 while (0x23 != (mmio_read_32(DDRC_STAT(0)) & 0x3f)) {
75 ;
76 }
77 }
78
79 mmio_write_32(DDRC_DFIMISC(0), 0x0);
80 mmio_write_32(DDRC_SWCTL(0), 0x0);
81 mmio_write_32(DDRC_DFIMISC(0), 0x1f00);
82 mmio_write_32(DDRC_DFIMISC(0), 0x1f20);
83
84 while (mmio_read_32(DDRC_DFISTAT(0)) & 0x1) {
85 ;
86 }
87
88 mmio_write_32(DDRC_DFIMISC(0), 0x1f00);
89 /* wait DFISTAT.dfi_init_complete to 1 */
90 while (!(mmio_read_32(DDRC_DFISTAT(0)) & 0x1)) {
91 ;
92 }
93
94 mmio_write_32(DDRC_SWCTL(0), 0x1);
95
96 /* should check PhyInLP3 pub reg */
97 dwc_ddrphy_apb_wr(0xd0000, 0x0);
98 if (!(dwc_ddrphy_apb_rd(0x90028) & 0x1)) {
99 INFO("PhyInLP3 = 1\n");
100 }
101 dwc_ddrphy_apb_wr(0xd0000, 0x1);
102
Jacky Bai9a6f62f2019-11-25 14:43:26 +0800103 /* pwrdnreqn_async adbm/adbs of ddr */
Jacky Bai7512abc2020-03-23 15:54:01 +0800104 mmio_clrbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, DDRMIX_ADB400_SYNC);
105 while (mmio_read_32(IMX_GPC_BASE + GPC_PU_PWRHSK) & DDRMIX_ADB400_ACK)
Jacky Bai9a6f62f2019-11-25 14:43:26 +0800106 ;
Jacky Bai7512abc2020-03-23 15:54:01 +0800107 mmio_setbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, DDRMIX_ADB400_SYNC);
108
Jacky Bai9a6f62f2019-11-25 14:43:26 +0800109 /* remove PowerOk */
110 mmio_write_32(SRC_DDR1_RCR, 0x8F000008);
111
112 mmio_write_32(CCM_CCGR(5), 0);
113 mmio_write_32(CCM_SRC_CTRL(15), 2);
114
115 /* enable the phy iso */
Jacky Bai7512abc2020-03-23 15:54:01 +0800116 mmio_setbits_32(IMX_GPC_BASE + DDRMIX_PGC, 1);
117 mmio_setbits_32(IMX_GPC_BASE + PU_PGC_DN_TRG, DDRMIX_PWR_REQ);
Jacky Bai9a6f62f2019-11-25 14:43:26 +0800118
119 VERBOSE("dram enter retention\n");
120}
121
122void dram_exit_retention(void)
123{
124 VERBOSE("dram exit retention\n");
125 /* assert all reset */
126#if defined(PLAT_imx8mq)
127 mmio_write_32(SRC_DDR2_RCR, 0x8F000003);
128 mmio_write_32(SRC_DDR1_RCR, 0x8F00000F);
129 mmio_write_32(SRC_DDR2_RCR, 0x8F000000);
130#else
131 mmio_write_32(SRC_DDR1_RCR, 0x8F00001F);
132 mmio_write_32(SRC_DDR1_RCR, 0x8F00000F);
133#endif
134 mmio_write_32(CCM_CCGR(5), 2);
135 mmio_write_32(CCM_SRC_CTRL(15), 2);
136
Jacky Bai469c2cc2020-10-22 14:35:12 +0800137 /* change the clock source of dram_apb_clk_root */
138 mmio_write_32(CCM_TARGET_ROOT(65) + 0x8, (0x7 << 24) | (0x7 << 16));
139 mmio_write_32(CCM_TARGET_ROOT(65) + 0x4, (0x4 << 24) | (0x3 << 16));
140
Jacky Bai9a6f62f2019-11-25 14:43:26 +0800141 /* disable iso */
Jacky Bai7512abc2020-03-23 15:54:01 +0800142 mmio_setbits_32(IMX_GPC_BASE + PU_PGC_UP_TRG, DDRMIX_PWR_REQ);
Jacky Bai9a6f62f2019-11-25 14:43:26 +0800143 mmio_write_32(SRC_DDR1_RCR, 0x8F000006);
144
145 /* wait dram pll locked */
146 while (!(mmio_read_32(DRAM_PLL_CTRL) & BIT(31))) {
147 ;
148 }
149
150 /* ddrc re-init */
151 dram_umctl2_init(dram_info.timing_info);
152
153 /*
154 * Skips the DRAM init routine and starts up in selfrefresh mode
155 * Program INIT0.skip_dram_init = 2'b11
156 */
157 mmio_setbits_32(DDRC_INIT0(0), 0xc0000000);
158 /* Keeps the controller in self-refresh mode */
159 mmio_write_32(DDRC_PWRCTL(0), 0xaa);
160 mmio_write_32(DDRC_DBG1(0), 0x0);
161 mmio_write_32(SRC_DDR1_RCR, 0x8F000004);
162 mmio_write_32(SRC_DDR1_RCR, 0x8F000000);
163
164 /* before write Dynamic reg, sw_done should be 0 */
165 mmio_write_32(DDRC_SWCTL(0), 0x0);
Jacky Baicf7a1402019-12-03 10:38:11 +0800166
167#if !PLAT_imx8mn
Jacky Bai9a6f62f2019-11-25 14:43:26 +0800168 if (dram_info.dram_type == DDRC_LPDDR4) {
169 mmio_write_32(DDRC_DDR_SS_GPR0, 0x01); /*LPDDR4 mode */
170 }
Jacky Baicf7a1402019-12-03 10:38:11 +0800171#endif /* !PLAT_imx8mn */
172
Jacky Bai9a6f62f2019-11-25 14:43:26 +0800173 mmio_write_32(DDRC_DFIMISC(0), 0x0);
174
175 /* dram phy re-init */
176 dram_phy_init(dram_info.timing_info);
177
Jacky Baidde85e02020-05-08 17:37:24 +0800178 /* workaround for rank-to-rank issue */
179 rank_setting_update();
180
Jacky Bai9a6f62f2019-11-25 14:43:26 +0800181 /* DWC_DDRPHYA_APBONLY0_MicroContMuxSel */
182 dwc_ddrphy_apb_wr(0xd0000, 0x0);
183 while (dwc_ddrphy_apb_rd(0x20097)) {
184 ;
185 }
186 dwc_ddrphy_apb_wr(0xd0000, 0x1);
187
188 /* before write Dynamic reg, sw_done should be 0 */
189 mmio_write_32(DDRC_SWCTL(0), 0x0);
190 mmio_write_32(DDRC_DFIMISC(0), 0x20);
191 /* wait DFISTAT.dfi_init_complete to 1 */
192 while (!(mmio_read_32(DDRC_DFISTAT(0)) & 0x1)) {
193 ;
194 }
195
196 /* clear DFIMISC.dfi_init_start */
197 mmio_write_32(DDRC_DFIMISC(0), 0x0);
198 /* set DFIMISC.dfi_init_complete_en */
199 mmio_write_32(DDRC_DFIMISC(0), 0x1);
200
201 /* set SWCTL.sw_done to enable quasi-dynamic register programming */
202 mmio_write_32(DDRC_SWCTL(0), 0x1);
203 /* wait SWSTAT.sw_done_ack to 1 */
204 while (!(mmio_read_32(DDRC_SWSTAT(0)) & 0x1)) {
205 ;
206 }
207
208 mmio_write_32(DDRC_PWRCTL(0), 0x88);
209 /* wait STAT to normal state */
210 while (0x1 != (mmio_read_32(DDRC_STAT(0)) & 0x7)) {
211 ;
212 }
213
214 mmio_write_32(DDRC_PCTRL_0(0), 0x1);
215 /* dis_auto-refresh is set to 0 */
216 mmio_write_32(DDRC_RFSHCTL3(0), 0x0);
217
218 /* should check PhyInLP3 pub reg */
219 dwc_ddrphy_apb_wr(0xd0000, 0x0);
220 if (!(dwc_ddrphy_apb_rd(0x90028) & 0x1)) {
221 VERBOSE("PHYInLP3 = 0\n");
222 }
223 dwc_ddrphy_apb_wr(0xd0000, 0x1);
224}