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