1*478af8d3SJacky Bai /* 2*478af8d3SJacky Bai * Copyright 2021-2024 NXP 3*478af8d3SJacky Bai * 4*478af8d3SJacky Bai * SPDX-License-Identifier: BSD-3-Clause 5*478af8d3SJacky Bai */ 6*478af8d3SJacky Bai 7*478af8d3SJacky Bai #include <assert.h> 8*478af8d3SJacky Bai #include <stdbool.h> 9*478af8d3SJacky Bai 10*478af8d3SJacky Bai #include <lib/mmio.h> 11*478af8d3SJacky Bai #include <platform_def.h> 12*478af8d3SJacky Bai 13*478af8d3SJacky Bai #include <upower_api.h> 14*478af8d3SJacky Bai 15*478af8d3SJacky Bai #define PHY_FREQ_SEL_INDEX(x) ((x) << 16) 16*478af8d3SJacky Bai #define PHY_FREQ_MULTICAST_EN(x) ((x) << 8) 17*478af8d3SJacky Bai #define DENALI_PHY_1537 U(0x5804) 18*478af8d3SJacky Bai 19*478af8d3SJacky Bai #define IMX_DDRC_BASE U(0x2E060000) 20*478af8d3SJacky Bai #define SAVED_DRAM_DATA_BASE U(0x20055000) 21*478af8d3SJacky Bai #define DENALI_CTL_144 0x240 22*478af8d3SJacky Bai #define LPI_WAKEUP_EN_SHIFT U(8) 23*478af8d3SJacky Bai #define IMX_LPAV_SIM_BASE 0x2DA50000 24*478af8d3SJacky Bai #define LPDDR_CTRL 0x14 25*478af8d3SJacky Bai #define LPDDR_AUTO_LP_MODE_DISABLE BIT(24) 26*478af8d3SJacky Bai #define SOC_LP_CMD_SHIFT U(15) 27*478af8d3SJacky Bai #define LPDDR_CTRL2 0x18 28*478af8d3SJacky Bai 29*478af8d3SJacky Bai #define DENALI_CTL_00 U(0x0) 30*478af8d3SJacky Bai #define DENALI_CTL_23 U(0x5c) 31*478af8d3SJacky Bai #define DFIBUS_FREQ_INIT_SHIFT U(24) 32*478af8d3SJacky Bai #define TSREF2PHYMSTR_SHIFT U(8) 33*478af8d3SJacky Bai #define TSREF2PHYMSTR_MASK GENMASK(13, 8) 34*478af8d3SJacky Bai 35*478af8d3SJacky Bai #define DENALI_CTL_24 U(0x60) 36*478af8d3SJacky Bai #define DENALI_CTL_25 U(0x64) 37*478af8d3SJacky Bai 38*478af8d3SJacky Bai #define DENALI_CTL_93 U(0x174) 39*478af8d3SJacky Bai #define PWRUP_SREFRESH_EXIT BIT(0) 40*478af8d3SJacky Bai 41*478af8d3SJacky Bai #define DENALI_CTL_127 U(0x1fc) 42*478af8d3SJacky Bai #define PHYMSTR_TRAIN_AFTER_INIT_COMPLETE BIT(16) 43*478af8d3SJacky Bai 44*478af8d3SJacky Bai #define DENALI_CTL_147 U(0x24c) 45*478af8d3SJacky Bai #define DENALI_CTL_153 U(0x264) 46*478af8d3SJacky Bai #define PCPCS_PD_EN BIT(8) 47*478af8d3SJacky Bai 48*478af8d3SJacky Bai #define DENALI_CTL_249 U(0x3E4) 49*478af8d3SJacky Bai #define DENALI_CTL_266 U(0x428) 50*478af8d3SJacky Bai 51*478af8d3SJacky Bai #define DENALI_PHY_1547 U(0x582c) 52*478af8d3SJacky Bai #define PHY_LP4_BOOT_DISABLE BIT(8) 53*478af8d3SJacky Bai 54*478af8d3SJacky Bai #define DENALI_PHY_1559 U(0x585c) 55*478af8d3SJacky Bai #define DENALI_PHY_1590 U(0x58D8) 56*478af8d3SJacky Bai 57*478af8d3SJacky Bai #define DENALI_PI_00 U(0x2000) 58*478af8d3SJacky Bai #define DENALI_PI_04 U(0x2010) 59*478af8d3SJacky Bai #define DENALI_PI_52 U(0x20D0) 60*478af8d3SJacky Bai #define DENALI_PI_26 U(0x2068) 61*478af8d3SJacky Bai #define DENALI_PI_33 U(0x2084) 62*478af8d3SJacky Bai #define DENALI_PI_65 U(0x2104) 63*478af8d3SJacky Bai #define DENALI_PI_77 U(0x2134) 64*478af8d3SJacky Bai #define DENALI_PI_134 U(0x2218) 65*478af8d3SJacky Bai #define DENALI_PI_131 U(0x220C) 66*478af8d3SJacky Bai #define DENALI_PI_132 U(0x2210) 67*478af8d3SJacky Bai #define DENALI_PI_134 U(0x2218) 68*478af8d3SJacky Bai #define DENALI_PI_137 U(0x2224) 69*478af8d3SJacky Bai #define DENALI_PI_174 U(0x22B8) 70*478af8d3SJacky Bai #define DENALI_PI_175 U(0x22BC) 71*478af8d3SJacky Bai #define DENALI_PI_181 U(0x22D4) 72*478af8d3SJacky Bai #define DENALI_PI_182 U(0x22D8) 73*478af8d3SJacky Bai #define DENALI_PI_191 U(0x22FC) 74*478af8d3SJacky Bai #define DENALI_PI_192 U(0x2300) 75*478af8d3SJacky Bai #define DENALI_PI_212 U(0x2350) 76*478af8d3SJacky Bai #define DENALI_PI_214 U(0x2358) 77*478af8d3SJacky Bai #define DENALI_PI_217 U(0x2364) 78*478af8d3SJacky Bai 79*478af8d3SJacky Bai #define LPDDR3_TYPE U(0x7) 80*478af8d3SJacky Bai #define LPDDR4_TYPE U(0xB) 81*478af8d3SJacky Bai 82*478af8d3SJacky Bai extern void upower_wait_resp(void); 83*478af8d3SJacky Bai 84*478af8d3SJacky Bai struct dram_cfg_param { 85*478af8d3SJacky Bai uint32_t reg; 86*478af8d3SJacky Bai uint32_t val; 87*478af8d3SJacky Bai }; 88*478af8d3SJacky Bai 89*478af8d3SJacky Bai struct dram_timing_info { 90*478af8d3SJacky Bai /* ddr controller config */ 91*478af8d3SJacky Bai struct dram_cfg_param *ctl_cfg; 92*478af8d3SJacky Bai unsigned int ctl_cfg_num; 93*478af8d3SJacky Bai /* pi config */ 94*478af8d3SJacky Bai struct dram_cfg_param *pi_cfg; 95*478af8d3SJacky Bai unsigned int pi_cfg_num; 96*478af8d3SJacky Bai /* phy freq1 config */ 97*478af8d3SJacky Bai struct dram_cfg_param *phy_f1_cfg; 98*478af8d3SJacky Bai unsigned int phy_f1_cfg_num; 99*478af8d3SJacky Bai /* phy freq2 config */ 100*478af8d3SJacky Bai struct dram_cfg_param *phy_f2_cfg; 101*478af8d3SJacky Bai unsigned int phy_f2_cfg_num; 102*478af8d3SJacky Bai /* initialized drate table */ 103*478af8d3SJacky Bai unsigned int fsp_table[3]; 104*478af8d3SJacky Bai }; 105*478af8d3SJacky Bai 106*478af8d3SJacky Bai #define CTL_NUM U(680) 107*478af8d3SJacky Bai #define PI_NUM U(298) 108*478af8d3SJacky Bai #define PHY_NUM U(1654) 109*478af8d3SJacky Bai #define PHY_DIFF_NUM U(49) 110*478af8d3SJacky Bai struct dram_cfg { 111*478af8d3SJacky Bai uint32_t ctl_cfg[CTL_NUM]; 112*478af8d3SJacky Bai uint32_t pi_cfg[PI_NUM]; 113*478af8d3SJacky Bai uint32_t phy_full[PHY_NUM]; 114*478af8d3SJacky Bai uint32_t phy_diff[PHY_DIFF_NUM]; 115*478af8d3SJacky Bai }; 116*478af8d3SJacky Bai 117*478af8d3SJacky Bai struct dram_timing_info *info; 118*478af8d3SJacky Bai struct dram_cfg *dram_timing_cfg; 119*478af8d3SJacky Bai 120*478af8d3SJacky Bai /* mark if dram cfg is already saved */ 121*478af8d3SJacky Bai static bool dram_cfg_saved; 122*478af8d3SJacky Bai static uint32_t dram_class; 123*478af8d3SJacky Bai 124*478af8d3SJacky Bai /* PHY register index for frequency diff */ 125*478af8d3SJacky Bai uint32_t freq_specific_reg_array[PHY_DIFF_NUM] = { 126*478af8d3SJacky Bai 90, 92, 93, 96, 97, 100, 101, 102, 103, 104, 114, 127*478af8d3SJacky Bai 346, 348, 349, 352, 353, 356, 357, 358, 359, 360, 128*478af8d3SJacky Bai 370, 602, 604, 605, 608, 609, 612, 613, 614, 615, 129*478af8d3SJacky Bai 616, 626, 858, 860, 861, 864, 865, 868, 869, 870, 130*478af8d3SJacky Bai 871, 872, 882, 1063, 1319, 1566, 1624, 1625 131*478af8d3SJacky Bai }; 132*478af8d3SJacky Bai 133*478af8d3SJacky Bai static void ddr_init(void) 134*478af8d3SJacky Bai { 135*478af8d3SJacky Bai unsigned int i; 136*478af8d3SJacky Bai 137*478af8d3SJacky Bai /* restore the ddr ctl config */ 138*478af8d3SJacky Bai for (i = 0U; i < CTL_NUM; i++) { 139*478af8d3SJacky Bai mmio_write_32(IMX_DDRC_BASE + i * 4, dram_timing_cfg->ctl_cfg[i]); 140*478af8d3SJacky Bai } 141*478af8d3SJacky Bai 142*478af8d3SJacky Bai /* load the PI registers */ 143*478af8d3SJacky Bai for (i = 0U; i < PI_NUM; i++) { 144*478af8d3SJacky Bai mmio_write_32(IMX_DDRC_BASE + 0x2000 + i * 4, dram_timing_cfg->pi_cfg[i]); 145*478af8d3SJacky Bai } 146*478af8d3SJacky Bai 147*478af8d3SJacky Bai 148*478af8d3SJacky Bai /* restore all PHY registers for all the fsp. */ 149*478af8d3SJacky Bai mmio_write_32(IMX_DDRC_BASE + DENALI_PHY_1537, 0x100); 150*478af8d3SJacky Bai /* restore all the phy configs */ 151*478af8d3SJacky Bai for (i = 0U; i < PHY_NUM; i++) { 152*478af8d3SJacky Bai /* skip the reserved registers space */ 153*478af8d3SJacky Bai if (i >= 121U && i <= 255U) { 154*478af8d3SJacky Bai continue; 155*478af8d3SJacky Bai } 156*478af8d3SJacky Bai if (i >= 377U && i <= 511U) { 157*478af8d3SJacky Bai continue; 158*478af8d3SJacky Bai } 159*478af8d3SJacky Bai if (i >= 633U && i <= 767U) { 160*478af8d3SJacky Bai continue; 161*478af8d3SJacky Bai } 162*478af8d3SJacky Bai if (i >= 889U && i <= 1023U) { 163*478af8d3SJacky Bai continue; 164*478af8d3SJacky Bai } 165*478af8d3SJacky Bai if (i >= 1065U && i <= 1279U) { 166*478af8d3SJacky Bai continue; 167*478af8d3SJacky Bai } 168*478af8d3SJacky Bai if (i >= 1321U && i <= 1535U) { 169*478af8d3SJacky Bai continue; 170*478af8d3SJacky Bai } 171*478af8d3SJacky Bai mmio_write_32(IMX_DDRC_BASE + 0x4000 + i * 4, dram_timing_cfg->phy_full[i]); 172*478af8d3SJacky Bai } 173*478af8d3SJacky Bai 174*478af8d3SJacky Bai if (dram_class == LPDDR4_TYPE) { 175*478af8d3SJacky Bai /* restore only the diff. */ 176*478af8d3SJacky Bai mmio_write_32(IMX_DDRC_BASE + DENALI_PHY_1537, 0x0); 177*478af8d3SJacky Bai for (i = 0U; i < PHY_DIFF_NUM; i++) { 178*478af8d3SJacky Bai mmio_write_32(IMX_DDRC_BASE + 0x4000 + freq_specific_reg_array[i] * 4, 179*478af8d3SJacky Bai dram_timing_cfg->phy_diff[i]); 180*478af8d3SJacky Bai } 181*478af8d3SJacky Bai } 182*478af8d3SJacky Bai 183*478af8d3SJacky Bai /* Re-enable MULTICAST mode */ 184*478af8d3SJacky Bai mmio_write_32(IMX_DDRC_BASE + DENALI_PHY_1537, PHY_FREQ_MULTICAST_EN(1)); 185*478af8d3SJacky Bai } 186*478af8d3SJacky Bai 187*478af8d3SJacky Bai void dram_enter_retention(void) 188*478af8d3SJacky Bai { 189*478af8d3SJacky Bai unsigned int i; 190*478af8d3SJacky Bai 191*478af8d3SJacky Bai /* 1. config the PCC_LPDDR4[SSADO] to 2b'11 for ACK domain 0/1's STOP */ 192*478af8d3SJacky Bai mmio_setbits_32(IMX_PCC5_BASE + 0x108, 0x2 << 22); 193*478af8d3SJacky Bai 194*478af8d3SJacky Bai /* 195*478af8d3SJacky Bai * 2. Make sure the DENALI_CTL_144[LPI_WAKEUP_EN[5:0]] has the bit 196*478af8d3SJacky Bai * LPI_WAKEUP_EN[3] = 1b'1. This enables the option 'self-refresh 197*478af8d3SJacky Bai * long with mem and ctlr clk gating or self-refresh power-down 198*478af8d3SJacky Bai * long with mem and ctlr clk gating' 199*478af8d3SJacky Bai */ 200*478af8d3SJacky Bai mmio_setbits_32(IMX_DDRC_BASE + DENALI_CTL_144, BIT(3) << LPI_WAKEUP_EN_SHIFT); 201*478af8d3SJacky Bai 202*478af8d3SJacky Bai /* 203*478af8d3SJacky Bai * 3a. Config SIM_LPAV LPDDR_CTRL[LPDDR_AUTO_LP_MODE_DISABLE] to 1b'0(enable 204*478af8d3SJacky Bai * the logic to automatic handles low power entry/exit. This is the recommended 205*478af8d3SJacky Bai * option over handling through software. 206*478af8d3SJacky Bai * 3b. Config the SIM_LPAV LPDDR_CTRL[SOC_LP_CMD] to 6b'101001(encoding for 207*478af8d3SJacky Bai * self_refresh with both DDR controller and DRAM clock gate. THis is mandatory 208*478af8d3SJacky Bai * since LPPDR logic will be power gated). 209*478af8d3SJacky Bai */ 210*478af8d3SJacky Bai mmio_clrbits_32(IMX_LPAV_SIM_BASE + LPDDR_CTRL, LPDDR_AUTO_LP_MODE_DISABLE); 211*478af8d3SJacky Bai mmio_clrsetbits_32(IMX_LPAV_SIM_BASE + LPDDR_CTRL, 212*478af8d3SJacky Bai 0x3f << SOC_LP_CMD_SHIFT, 0x29 << SOC_LP_CMD_SHIFT); 213*478af8d3SJacky Bai 214*478af8d3SJacky Bai /* Save DDR Controller & PHY config. 215*478af8d3SJacky Bai * Set PHY_FREQ_SEL_MULTICAST_EN=0 & PHY_FREQ_SEL_INDEX=1. Read and store all 216*478af8d3SJacky Bai * the PHY registers for F2 into phy_f1_cfg, then read/store the diff between 217*478af8d3SJacky Bai * F1 & F2 into phy_f2_cfg. 218*478af8d3SJacky Bai */ 219*478af8d3SJacky Bai if (!dram_cfg_saved) { 220*478af8d3SJacky Bai info = (struct dram_timing_info *)SAVED_DRAM_DATA_BASE; 221*478af8d3SJacky Bai dram_timing_cfg = (struct dram_cfg *)(SAVED_DRAM_DATA_BASE + 222*478af8d3SJacky Bai sizeof(struct dram_timing_info)); 223*478af8d3SJacky Bai 224*478af8d3SJacky Bai /* get the dram type */ 225*478af8d3SJacky Bai dram_class = mmio_read_32(IMX_DDRC_BASE + DENALI_CTL_00); 226*478af8d3SJacky Bai dram_class = (dram_class >> 8) & 0xf; 227*478af8d3SJacky Bai 228*478af8d3SJacky Bai /* save the ctl registers */ 229*478af8d3SJacky Bai for (i = 0U; i < CTL_NUM; i++) { 230*478af8d3SJacky Bai dram_timing_cfg->ctl_cfg[i] = mmio_read_32(IMX_DDRC_BASE + i * 4); 231*478af8d3SJacky Bai } 232*478af8d3SJacky Bai dram_timing_cfg->ctl_cfg[0] = dram_timing_cfg->ctl_cfg[0] & 0xFFFFFFFE; 233*478af8d3SJacky Bai 234*478af8d3SJacky Bai /* save the PI registers */ 235*478af8d3SJacky Bai for (i = 0U; i < PI_NUM; i++) { 236*478af8d3SJacky Bai dram_timing_cfg->pi_cfg[i] = mmio_read_32(IMX_DDRC_BASE + 0x2000 + i * 4); 237*478af8d3SJacky Bai } 238*478af8d3SJacky Bai dram_timing_cfg->pi_cfg[0] = dram_timing_cfg->pi_cfg[0] & 0xFFFFFFFE; 239*478af8d3SJacky Bai 240*478af8d3SJacky Bai /* 241*478af8d3SJacky Bai * Read and store all PHY registers. full array is a full 242*478af8d3SJacky Bai * copy for all the setpoint 243*478af8d3SJacky Bai */ 244*478af8d3SJacky Bai if (dram_class == LPDDR4_TYPE) { 245*478af8d3SJacky Bai mmio_write_32(IMX_DDRC_BASE + DENALI_PHY_1537, 0x10000); 246*478af8d3SJacky Bai for (i = 0U; i < PHY_NUM; i++) { 247*478af8d3SJacky Bai /* Make sure MULTICASE is enabled */ 248*478af8d3SJacky Bai if (i == 1537U) { 249*478af8d3SJacky Bai dram_timing_cfg->phy_full[i] = 0x100; 250*478af8d3SJacky Bai } else { 251*478af8d3SJacky Bai dram_timing_cfg->phy_full[i] = mmio_read_32(IMX_DDRC_BASE + 0x4000 + i * 4); 252*478af8d3SJacky Bai } 253*478af8d3SJacky Bai } 254*478af8d3SJacky Bai 255*478af8d3SJacky Bai /* 256*478af8d3SJacky Bai * set PHY_FREQ_SEL_MULTICAST_EN=0 & PHY_FREQ_SEL_INDEX=0. 257*478af8d3SJacky Bai * Read and store only the diff. 258*478af8d3SJacky Bai */ 259*478af8d3SJacky Bai mmio_write_32(IMX_DDRC_BASE + DENALI_PHY_1537, 0x0); 260*478af8d3SJacky Bai /* save only the frequency based diff config to save memory */ 261*478af8d3SJacky Bai for (i = 0U; i < PHY_DIFF_NUM; i++) { 262*478af8d3SJacky Bai dram_timing_cfg->phy_diff[i] = mmio_read_32(IMX_DDRC_BASE + 0x4000 + 263*478af8d3SJacky Bai freq_specific_reg_array[i] * 4); 264*478af8d3SJacky Bai } 265*478af8d3SJacky Bai } else { 266*478af8d3SJacky Bai /* LPDDR3, only f1 need to save */ 267*478af8d3SJacky Bai for (i = 0U; i < info->phy_f1_cfg_num; i++) { 268*478af8d3SJacky Bai info->phy_f1_cfg[i].val = mmio_read_32(info->phy_f1_cfg[i].reg); 269*478af8d3SJacky Bai } 270*478af8d3SJacky Bai } 271*478af8d3SJacky Bai 272*478af8d3SJacky Bai dram_cfg_saved = true; 273*478af8d3SJacky Bai } 274*478af8d3SJacky Bai } 275*478af8d3SJacky Bai 276*478af8d3SJacky Bai void dram_exit_retention(void) 277*478af8d3SJacky Bai { 278*478af8d3SJacky Bai uint32_t val; 279*478af8d3SJacky Bai 280*478af8d3SJacky Bai /* 1. Config the LPAV PLL4 and DDR clock for the desired LPDDR operating frequency. */ 281*478af8d3SJacky Bai mmio_setbits_32(IMX_PCC5_BASE + 0x108, BIT(30)); 282*478af8d3SJacky Bai 283*478af8d3SJacky Bai /* 2. Write PCC5.PCC_LPDDR4[SWRST] to 1b'1 to release LPDDR from reset. */ 284*478af8d3SJacky Bai mmio_setbits_32(IMX_PCC5_BASE + 0x108, BIT(28)); 285*478af8d3SJacky Bai 286*478af8d3SJacky Bai /* 3. Reload the LPDDR CTL/PI/PHY register */ 287*478af8d3SJacky Bai ddr_init(); 288*478af8d3SJacky Bai 289*478af8d3SJacky Bai if (dram_class == LPDDR4_TYPE) { 290*478af8d3SJacky Bai /* 4a. FIXME Set PHY_SET_DFI_INPUT_N parameters to 4'h1. LPDDR4 only */ 291*478af8d3SJacky Bai mmio_write_32(IMX_DDRC_BASE + DENALI_PHY_1559, 0x01010101); 292*478af8d3SJacky Bai 293*478af8d3SJacky Bai /* 294*478af8d3SJacky Bai * 4b. CTL PWRUP_SREFRESH_EXIT=1'b0 for disabling self refresh exit 295*478af8d3SJacky Bai * from controller. 296*478af8d3SJacky Bai */ 297*478af8d3SJacky Bai /* 298*478af8d3SJacky Bai * 4c. PI_PWRUP_SELF_REF_EXIT=1, PI_MC_PWRUP_SELF_REF_EXIT=0 for enabling 299*478af8d3SJacky Bai * self refresh exit from PI 300*478af8d3SJacky Bai */ 301*478af8d3SJacky Bai /* 4c. PI_INT_LVL_EN=0 to skip Initialization trainings. */ 302*478af8d3SJacky Bai /* 303*478af8d3SJacky Bai * 4d. PI_WRLVL_EN_F0/1/2= PI_CALVL_EN_F0/1/2= PI_RDLVL_EN_F0/1/2= 304*478af8d3SJacky Bai * PI_RDLVL_GATE_EN_F0/1/2= PI_WDQLVL_EN_F0/1/2=0x2. 305*478af8d3SJacky Bai * Enable non initialization trainings. 306*478af8d3SJacky Bai */ 307*478af8d3SJacky Bai /* 4e. PI_PWRUP_SREFRESH_EXIT_CS=0xF */ 308*478af8d3SJacky Bai /* 4f. PI_DLL_RESET=0x1 */ 309*478af8d3SJacky Bai mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_137, 0x1); 310*478af8d3SJacky Bai /* PI_PWRUP_SELF_REF_EXIT = 1 */ 311*478af8d3SJacky Bai mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_132, 0x01000000); 312*478af8d3SJacky Bai /* PI_MC_PWRUP_SELF_REF_EXIT = 0 */ 313*478af8d3SJacky Bai mmio_clrbits_32(IMX_DDRC_BASE + DENALI_PI_132, BIT(16)); 314*478af8d3SJacky Bai /* PI_INT_LVL_EN = 0 */ 315*478af8d3SJacky Bai mmio_clrbits_32(IMX_DDRC_BASE + DENALI_PI_04, BIT(0)); 316*478af8d3SJacky Bai /* PI_WRLVL_EN_F0 = 3, PI_WRLVL_EN_F1 = 3 */ 317*478af8d3SJacky Bai mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_174, 0x03030000); 318*478af8d3SJacky Bai /* PI_WRLVL_EN_F2 = 3 */ 319*478af8d3SJacky Bai mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_175, 0x03); 320*478af8d3SJacky Bai /* PI_CALVL_EN_F0 = 3, PI_CALVL_EN_F1 = 3 */ 321*478af8d3SJacky Bai mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_191, 0x03030000); 322*478af8d3SJacky Bai /* PI_CALVL_EN_F2 = 3 */ 323*478af8d3SJacky Bai mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_192, 0x03); 324*478af8d3SJacky Bai /* PI_WDQLVL_EN_F0 = 3 */ 325*478af8d3SJacky Bai mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_212, 0x300); 326*478af8d3SJacky Bai /* PI_WDQLVL_EN_F1 = 3 */ 327*478af8d3SJacky Bai mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_214, 0x03000000); 328*478af8d3SJacky Bai /* PI_WDQLVL_EN_F2 = 3 */ 329*478af8d3SJacky Bai mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_217, 0x300); 330*478af8d3SJacky Bai /* PI_EDLVL_EN_F0 = 3, PI_EDLVL_GATE_EN_F0 = 3 */ 331*478af8d3SJacky Bai mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_181, 0x03030000); 332*478af8d3SJacky Bai /* 333*478af8d3SJacky Bai * PI_RDLVL_EN_F1 = 3, PI_RDLVL_GATE_EN_F1 = 3, 334*478af8d3SJacky Bai * PI_RDLVL_EN_F2 = 3, PI_RDLVL_GATE_EN_F2 = 3 335*478af8d3SJacky Bai */ 336*478af8d3SJacky Bai mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_182, 0x03030303); 337*478af8d3SJacky Bai /* PI_PWRUP_SREFRESH_EXIT_CS = 0xF */ 338*478af8d3SJacky Bai mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_134, 0x000F0000); 339*478af8d3SJacky Bai } else { 340*478af8d3SJacky Bai /* PI_DLL_RESET=1 */ 341*478af8d3SJacky Bai mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_137, 0x1); 342*478af8d3SJacky Bai /* PI_PWRUP_SELF_REF_EXIT=1 */ 343*478af8d3SJacky Bai mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_132, 0x01000000); 344*478af8d3SJacky Bai /* PI_MC_PWRUP_SELF_REF_EXIT=0 */ 345*478af8d3SJacky Bai mmio_clrbits_32(IMX_DDRC_BASE + DENALI_PI_132, BIT(16)); 346*478af8d3SJacky Bai /* PI_INT_LVL_EN=0 */ 347*478af8d3SJacky Bai mmio_clrbits_32(IMX_DDRC_BASE + DENALI_PI_04, BIT(0)); 348*478af8d3SJacky Bai /* PI_WRLVL_EN_F0=3 */ 349*478af8d3SJacky Bai mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_174, 0x00030000); 350*478af8d3SJacky Bai /* PI_CALVL_EN_F0=3 */ 351*478af8d3SJacky Bai mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_191, 0x00030000); 352*478af8d3SJacky Bai /* PI_RDLVL_EN_F0=3,PI_RDLVL_GATE_EN_F0=3 */ 353*478af8d3SJacky Bai mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_181, 0x03030000); 354*478af8d3SJacky Bai /* PI_PWRUP_SREFRESH_EXIT_CS=0xF */ 355*478af8d3SJacky Bai mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_134, 0x000F0000); 356*478af8d3SJacky Bai } 357*478af8d3SJacky Bai 358*478af8d3SJacky Bai mmio_write_32(IMX_DDRC_BASE + DENALI_CTL_144, 0x00002D00); 359*478af8d3SJacky Bai 360*478af8d3SJacky Bai /* Force in-order AXI read data */ 361*478af8d3SJacky Bai mmio_write_32(IMX_DDRC_BASE + DENALI_CTL_144, 0x1); 362*478af8d3SJacky Bai 363*478af8d3SJacky Bai /* 364*478af8d3SJacky Bai * Disable special R/W group switches so that R/W group placement 365*478af8d3SJacky Bai * is always at END of R/W group. 366*478af8d3SJacky Bai */ 367*478af8d3SJacky Bai mmio_write_32(IMX_DDRC_BASE + DENALI_CTL_249, 0x0); 368*478af8d3SJacky Bai 369*478af8d3SJacky Bai /* Reduce time for IO pad calibration */ 370*478af8d3SJacky Bai mmio_write_32(IMX_DDRC_BASE + DENALI_PHY_1590, 0x01000000); 371*478af8d3SJacky Bai 372*478af8d3SJacky Bai mmio_write_32(IMX_DDRC_BASE + DENALI_CTL_25, 0x00020100); 373*478af8d3SJacky Bai 374*478af8d3SJacky Bai /* PD disable */ 375*478af8d3SJacky Bai mmio_write_32(IMX_DDRC_BASE + DENALI_CTL_153, 0x04040000); 376*478af8d3SJacky Bai /* 377*478af8d3SJacky Bai * 5. Disable automatic LP entry and PCPCS modes LP_AUTO_ENTRY_EN 378*478af8d3SJacky Bai * to 1b'0, PCPCS_PD_EN to 1b'0 379*478af8d3SJacky Bai */ 380*478af8d3SJacky Bai 381*478af8d3SJacky Bai upwr_xcp_set_ddr_retention(APD_DOMAIN, 0, NULL); 382*478af8d3SJacky Bai upower_wait_resp(); 383*478af8d3SJacky Bai 384*478af8d3SJacky Bai if (dram_class == LPDDR4_TYPE) { 385*478af8d3SJacky Bai /* 7. Write PI START parameter to 1'b1 */ 386*478af8d3SJacky Bai mmio_write_32(IMX_DDRC_BASE + DENALI_PI_00, 0x00000b01); 387*478af8d3SJacky Bai 388*478af8d3SJacky Bai /* 8. Write CTL START parameter to 1'b1 */ 389*478af8d3SJacky Bai mmio_write_32(IMX_DDRC_BASE + DENALI_CTL_00, 0x00000b01); 390*478af8d3SJacky Bai } else { 391*478af8d3SJacky Bai /* 7. Write PI START parameter to 1'b1 */ 392*478af8d3SJacky Bai mmio_write_32(IMX_DDRC_BASE + DENALI_PI_00, 0x00000701); 393*478af8d3SJacky Bai 394*478af8d3SJacky Bai /* 8. Write CTL START parameter to 1'b1 */ 395*478af8d3SJacky Bai mmio_write_32(IMX_DDRC_BASE + DENALI_CTL_00, 0x00000701); 396*478af8d3SJacky Bai } 397*478af8d3SJacky Bai 398*478af8d3SJacky Bai /* 9. DENALI_CTL_266: Wait for INT_STATUS_INIT=0x2 */ 399*478af8d3SJacky Bai do { 400*478af8d3SJacky Bai val = (mmio_read_32(IMX_DDRC_BASE + DENALI_CTL_266) >> 8) & 0xFF; 401*478af8d3SJacky Bai } while (val != 0x2); 402*478af8d3SJacky Bai 403*478af8d3SJacky Bai /* 404*478af8d3SJacky Bai * 10. Run SW trainings by setting PI_CALVL_REQ,PI_WRLVL_REQ,PI_RDLVL_GATE_REQ, 405*478af8d3SJacky Bai * PI_RDLVL_REQ,PI_WDQLVL_REQ(NA for LPDDR3) in same order. 406*478af8d3SJacky Bai */ 407*478af8d3SJacky Bai if (dram_class == LPDDR4_TYPE) { 408*478af8d3SJacky Bai mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_52, 0x10000); /* CALVL */ 409*478af8d3SJacky Bai mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_26, 0x100); /* WRLVL */ 410*478af8d3SJacky Bai mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_33, 0x10000); /* RDGATE */ 411*478af8d3SJacky Bai mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_33, 0x100); /* RDQLVL */ 412*478af8d3SJacky Bai mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_65, 0x10000); /* WDQLVL */ 413*478af8d3SJacky Bai 414*478af8d3SJacky Bai /* 11. Wait for trainings to get complete by polling PI_INT_STATUS */ 415*478af8d3SJacky Bai while ((mmio_read_32(IMX_DDRC_BASE + DENALI_PI_77) & 0x07E00000) != 0x07E00000) { 416*478af8d3SJacky Bai ; 417*478af8d3SJacky Bai } 418*478af8d3SJacky Bai } else { 419*478af8d3SJacky Bai mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_52, 0x10000); /* CALVL */ 420*478af8d3SJacky Bai mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_26, 0x100); /* WRLVL */ 421*478af8d3SJacky Bai mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_33, 0x10000); /* RDGATE */ 422*478af8d3SJacky Bai mmio_setbits_32(IMX_DDRC_BASE + DENALI_PI_33, 0x100); /* RDQLVL */ 423*478af8d3SJacky Bai while ((mmio_read_32(IMX_DDRC_BASE + DENALI_PI_77) & 0x05E00000) != 0x05E00000) { 424*478af8d3SJacky Bai ; 425*478af8d3SJacky Bai } 426*478af8d3SJacky Bai } 427*478af8d3SJacky Bai } 428