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