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