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 <gpc_reg.h> 12 #include <platform_def.h> 13 14 #define SRC_DDR1_RCR (IMX_SRC_BASE + 0x1000) 15 #define SRC_DDR2_RCR (IMX_SRC_BASE + 0x1004) 16 17 #define CCM_SRC_CTRL_OFFSET (IMX_CCM_BASE + 0x800) 18 #define CCM_CCGR_OFFSET (IMX_CCM_BASE + 0x4000) 19 #define CCM_TARGET_ROOT_OFFSET (IMX_CCM_BASE + 0x8000) 20 #define CCM_SRC_CTRL(n) (CCM_SRC_CTRL_OFFSET + 0x10 * (n)) 21 #define CCM_CCGR(n) (CCM_CCGR_OFFSET + 0x10 * (n)) 22 #define CCM_TARGET_ROOT(n) (CCM_TARGET_ROOT_OFFSET + 0x80 * (n)) 23 24 #define DBGCAM_EMPTY 0x36000000 25 26 static void rank_setting_update(void) 27 { 28 uint32_t i, offset; 29 uint32_t pstate_num = dram_info.num_fsp; 30 31 /* only support maximum 3 setpoints */ 32 pstate_num = (pstate_num > MAX_FSP_NUM) ? MAX_FSP_NUM : pstate_num; 33 34 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 51 void 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 103 /* pwrdnreqn_async adbm/adbs of ddr */ 104 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) 106 ; 107 mmio_setbits_32(IMX_GPC_BASE + GPC_PU_PWRHSK, DDRMIX_ADB400_SYNC); 108 109 /* 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 */ 116 mmio_setbits_32(IMX_GPC_BASE + DDRMIX_PGC, 1); 117 mmio_setbits_32(IMX_GPC_BASE + PU_PGC_DN_TRG, DDRMIX_PWR_REQ); 118 119 VERBOSE("dram enter retention\n"); 120 } 121 122 void 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 137 /* 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 141 /* disable iso */ 142 mmio_setbits_32(IMX_GPC_BASE + PU_PGC_UP_TRG, DDRMIX_PWR_REQ); 143 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); 166 167 #if !PLAT_imx8mn 168 if (dram_info.dram_type == DDRC_LPDDR4) { 169 mmio_write_32(DDRC_DDR_SS_GPR0, 0x01); /*LPDDR4 mode */ 170 } 171 #endif /* !PLAT_imx8mn */ 172 173 mmio_write_32(DDRC_DFIMISC(0), 0x0); 174 175 /* dram phy re-init */ 176 dram_phy_init(dram_info.timing_info); 177 178 /* workaround for rank-to-rank issue */ 179 rank_setting_update(); 180 181 /* 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 } 225