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