1 /* 2 * Copyright 2018-2023 NXP 3 * 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 28 static 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 50 void 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 130 void 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); 170 171 #if !PLAT_imx8mn 172 if (dram_info.dram_type == DDRC_LPDDR4) { 173 mmio_write_32(DDRC_DDR_SS_GPR0, 0x01); /*LPDDR4 mode */ 174 } 175 #endif /* !PLAT_imx8mn */ 176 177 mmio_write_32(DDRC_DFIMISC(0), 0x0); 178 179 /* dram phy re-init */ 180 dram_phy_init(dram_info.timing_info); 181 182 /* workaround for rank-to-rank issue */ 183 rank_setting_update(); 184 185 /* 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 } 229