1 /* 2 * Copyright 2021-2024 NXP 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <stdbool.h> 8 9 #include <arch.h> 10 #include <arch_helpers.h> 11 #include <common/debug.h> 12 #include <drivers/arm/gicv3.h> 13 #include <lib/mmio.h> 14 #include <lib/psci/psci.h> 15 16 #include <plat_imx8.h> 17 #include <upower_api.h> 18 19 extern void cgc1_save(void); 20 extern void cgc1_restore(void); 21 extern void imx_apd_ctx_save(unsigned int cpu); 22 extern void imx_apd_ctx_restore(unsigned int cpu); 23 extern void usb_wakeup_enable(bool enable); 24 25 static uintptr_t secure_entrypoint; 26 27 #define CORE_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL0]) 28 #define CLUSTER_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL1]) 29 #define SYSTEM_PWR_STATE(state) ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL]) 30 31 #define RVBARADDRx(c) (IMX_SIM1_BASE + 0x5c + 0x4 * (c)) 32 #define WKPUx(c) (IMX_SIM1_BASE + 0x3c + 0x4 * (c)) 33 #define AD_COREx_LPMODE(c) (IMX_CMC1_BASE + 0x50 + 0x4 * (c)) 34 35 #define PMIC_CFG(v, m, msk) \ 36 { \ 37 .volt = (v), \ 38 .mode = (m), \ 39 .mode_msk = (msk), \ 40 } 41 42 #define PAD_CFG(c, r, t) \ 43 { \ 44 .pad_close = (c), \ 45 .pad_reset = (r), \ 46 .pad_tqsleep = (t) \ 47 } 48 49 #define BIAS_CFG(m, n, p, mbias) \ 50 { \ 51 .dombias_cfg = { \ 52 .mode = (m), \ 53 .rbbn = (n), \ 54 .rbbp = (p), \ 55 }, \ 56 .membias_cfg = {mbias}, \ 57 } 58 59 #define SWT_BOARD(swt_on, msk) \ 60 { \ 61 .on = (swt_on), \ 62 .mask = (msk), \ 63 } 64 65 #define SWT_MEM(a, p, m) \ 66 { \ 67 .array = (a), \ 68 .perif = (p), \ 69 .mask = (m), \ 70 } 71 72 extern void upower_wait_resp(void); 73 74 static int imx_pwr_set_cpu_entry(unsigned int cpu, unsigned int entry) 75 { 76 mmio_write_32(RVBARADDRx(cpu), entry); 77 78 /* set update bit */ 79 mmio_write_32(IMX_SIM1_BASE + 0x8, mmio_read_32(IMX_SIM1_BASE + 0x8) | BIT_32(24 + cpu)); 80 /* wait for ack */ 81 while (!(mmio_read_32(IMX_SIM1_BASE + 0x8) & BIT_32(26 + cpu))) { 82 } 83 84 /* clear update bit */ 85 mmio_write_32(IMX_SIM1_BASE + 0x8, mmio_read_32(IMX_SIM1_BASE + 0x8) & ~BIT_32(24 + cpu)); 86 /* clear ack bit */ 87 mmio_write_32(IMX_SIM1_BASE + 0x8, mmio_read_32(IMX_SIM1_BASE + 0x8) | BIT_32(26 + cpu)); 88 89 return 0; 90 } 91 92 int imx_pwr_domain_on(u_register_t mpidr) 93 { 94 unsigned int cpu = MPIDR_AFFLVL0_VAL(mpidr); 95 96 imx_pwr_set_cpu_entry(cpu, secure_entrypoint); 97 98 mmio_write_32(IMX_CMC1_BASE + 0x18, 0x3f); 99 mmio_write_32(IMX_CMC1_BASE + 0x50 + 0x4 * cpu, 0); 100 101 /* enable wku wakeup for idle */ 102 mmio_write_32(IMX_SIM1_BASE + 0x3c + 0x4 * cpu, 0xffffffff); 103 104 return PSCI_E_SUCCESS; 105 } 106 107 void imx_pwr_domain_on_finish(const psci_power_state_t *target_state) 108 { 109 imx_pwr_set_cpu_entry(0, IMX_ROM_ENTRY); 110 plat_gic_pcpu_init(); 111 plat_gic_cpuif_enable(); 112 } 113 114 int imx_validate_ns_entrypoint(uintptr_t ns_entrypoint) 115 { 116 return PSCI_E_SUCCESS; 117 } 118 119 void imx_pwr_domain_off(const psci_power_state_t *target_state) 120 { 121 unsigned int cpu = MPIDR_AFFLVL0_VAL(read_mpidr_el1()); 122 123 plat_gic_cpuif_disable(); 124 125 /* disable wakeup */ 126 mmio_write_32(WKPUx(cpu), 0); 127 128 /* set core power mode to PD */ 129 mmio_write_32(AD_COREx_LPMODE(cpu), 0x3); 130 } 131 132 /* APD power mode config */ 133 ps_apd_pwr_mode_cfgs_t apd_pwr_mode_cfgs = { 134 [DPD_PWR_MODE] = { 135 .swt_board_offs = 0x180, 136 .swt_mem_offs = 0x188, 137 .pmic_cfg = PMIC_CFG(0x23, 0xa, 0x2), 138 .pad_cfg = PAD_CFG(0xc, 0x0, 0x01e80a02), 139 .bias_cfg = BIAS_CFG(0x0, 0x2, 0x2, 0x0), 140 }, 141 142 /* PD */ 143 [PD_PWR_MODE] = { 144 .swt_board_offs = 0x170, 145 .swt_mem_offs = 0x178, 146 .pmic_cfg = PMIC_CFG(0x23, 0x2, 0x2), 147 .pad_cfg = PAD_CFG(0x0, 0x0, 0x01e80a00), 148 .bias_cfg = BIAS_CFG(0x0, 0x2, 0x2, 0x0), 149 }, 150 151 [ADMA_PWR_MODE] = { 152 .swt_board_offs = 0x120, 153 .swt_mem_offs = 0x128, 154 .pmic_cfg = PMIC_CFG(0x23, 0x0, 0x2), 155 .pad_cfg = PAD_CFG(0x0, 0x0, 0x0deb7a00), 156 .bias_cfg = BIAS_CFG(0x0, 0x2, 0x2, 0x0), 157 }, 158 159 [ACT_PWR_MODE] = { 160 .swt_board_offs = 0x110, 161 .swt_mem_offs = 0x118, 162 .pmic_cfg = PMIC_CFG(0x23, 0x2, 0x2), 163 .pad_cfg = PAD_CFG(0x0, 0x0, 0x0deb7a00), 164 .bias_cfg = BIAS_CFG(0x0, 0x2, 0x2, 0x0), 165 }, 166 }; 167 168 /* APD power switch config */ 169 ps_apd_swt_cfgs_t apd_swt_cfgs = { 170 [DPD_PWR_MODE] = { 171 .swt_board[0] = SWT_BOARD(0x00060003, 0x7c), 172 .swt_mem[0] = SWT_MEM(0x0, 0x0, 0x1ffff), 173 .swt_mem[1] = SWT_MEM(0x003fffff, 0x003fffff, 0x0), 174 }, 175 176 [PD_PWR_MODE] = { 177 .swt_board[0] = SWT_BOARD(0x00060003, 0x00001e74), 178 .swt_mem[0] = SWT_MEM(0x00010c00, 0x0, 0x1ffff), 179 .swt_mem[1] = SWT_MEM(0x003fffff, 0x003f0000, 0x0), 180 }, 181 182 [ADMA_PWR_MODE] = { 183 .swt_board[0] = SWT_BOARD(0x0006ff77, 0x0006ff7c), 184 .swt_mem[0] = SWT_MEM(0x0001fffd, 0x0001fffd, 0x1ffff), 185 .swt_mem[1] = SWT_MEM(0x003fffff, 0x003fffff, 0x0), 186 }, 187 188 [ACT_PWR_MODE] = { 189 .swt_board[0] = SWT_BOARD(0x0006ff77, 0x0000ff7c), 190 .swt_mem[0] = SWT_MEM(0x0001fffd, 0x0001fffd, 0x1ffff), 191 .swt_mem[1] = SWT_MEM(0x003fffff, 0x003fffff, 0x0), 192 }, 193 }; 194 195 struct ps_pwr_mode_cfg_t *pwr_sys_cfg = (struct ps_pwr_mode_cfg_t *)UPWR_DRAM_SHARED_BASE_ADDR; 196 197 void imx_set_pwr_mode_cfg(abs_pwr_mode_t mode) 198 { 199 if (mode >= NUM_PWR_MODES) { 200 return; 201 } 202 203 /* apd power mode config */ 204 memcpy(&pwr_sys_cfg->ps_apd_pwr_mode_cfg[mode], &apd_pwr_mode_cfgs[mode], 205 sizeof(struct ps_apd_pwr_mode_cfg_t)); 206 207 /* apd power switch config */ 208 memcpy(&pwr_sys_cfg->ps_apd_swt_cfg[mode], &apd_swt_cfgs[mode], sizeof(swt_config_t)); 209 } 210 211 void imx_domain_suspend(const psci_power_state_t *target_state) 212 { 213 unsigned int cpu = MPIDR_AFFLVL0_VAL(read_mpidr_el1()); 214 215 if (is_local_state_off(CORE_PWR_STATE(target_state))) { 216 plat_gic_cpuif_disable(); 217 imx_pwr_set_cpu_entry(cpu, secure_entrypoint); 218 /* core put into power down */ 219 mmio_write_32(IMX_CMC1_BASE + 0x50 + 0x4 * cpu, 0x3); 220 /* FIXME config wakeup interrupt in WKPU */ 221 mmio_write_32(IMX_SIM1_BASE + 0x3c + 0x4 * cpu, 0x7fffffe3); 222 } else { 223 /* for core standby/retention mode */ 224 mmio_write_32(IMX_CMC1_BASE + 0x50 + 0x4 * cpu, 0x1); 225 mmio_write_32(IMX_SIM1_BASE + 0x3c + 0x4 * cpu, 0x7fffffe3); 226 dsb(); 227 write_scr_el3(read_scr_el3() | SCR_FIQ_BIT); 228 isb(); 229 } 230 231 if (is_local_state_retn(CLUSTER_PWR_STATE(target_state))) { 232 /* 233 * just for sleep mode for now, need to update to 234 * support more modes, same for suspend finish call back. 235 */ 236 mmio_write_32(IMX_CMC1_BASE + 0x10, 0x1); 237 mmio_write_32(IMX_CMC1_BASE + 0x20, 0x1); 238 239 } else if (is_local_state_off(CLUSTER_PWR_STATE(target_state))) { 240 /* 241 * for cluster off state, put cluster into power down mode, 242 * config the cluster clock to be off. 243 */ 244 mmio_write_32(IMX_CMC1_BASE + 0x10, 0x7); 245 mmio_write_32(IMX_CMC1_BASE + 0x20, 0xf); 246 } 247 248 if (is_local_state_off(SYSTEM_PWR_STATE(target_state))) { 249 /* 250 * low power mode config info used by upower 251 * to do low power mode transition. 252 */ 253 imx_set_pwr_mode_cfg(ADMA_PWR_MODE); 254 imx_set_pwr_mode_cfg(ACT_PWR_MODE); 255 imx_set_pwr_mode_cfg(PD_PWR_MODE); 256 257 /* clear the upower wakeup */ 258 upwr_xcp_set_rtd_apd_llwu(APD_DOMAIN, 0, NULL); 259 upower_wait_resp(); 260 261 /* enable the USB wakeup */ 262 usb_wakeup_enable(true); 263 264 /* config the WUU to enabled the wakeup source */ 265 mmio_write_32(IMX_PCC3_BASE + 0x98, 0xc0800000); 266 267 /* !!! clear all the pad wakeup pending event */ 268 mmio_write_32(IMX_WUU1_BASE + 0x20, 0xffffffff); 269 270 /* enable upower usb phy wakeup by default */ 271 mmio_setbits_32(IMX_WUU1_BASE + 0x18, BIT(4) | BIT(1) | BIT(0)); 272 273 /* enabled all pad wakeup by default */ 274 mmio_write_32(IMX_WUU1_BASE + 0x8, 0xffffffff); 275 276 /* save the AD domain context before entering PD mode */ 277 imx_apd_ctx_save(cpu); 278 } 279 } 280 281 extern void imx8ulp_init_scmi_server(void); 282 void imx_domain_suspend_finish(const psci_power_state_t *target_state) 283 { 284 unsigned int cpu = MPIDR_AFFLVL0_VAL(read_mpidr_el1()); 285 286 if (is_local_state_off(SYSTEM_PWR_STATE(target_state))) { 287 /* restore the ap domain context */ 288 imx_apd_ctx_restore(cpu); 289 290 /* clear the upower wakeup */ 291 upwr_xcp_set_rtd_apd_llwu(APD_DOMAIN, 0, NULL); 292 upower_wait_resp(); 293 294 /* disable all pad wakeup */ 295 mmio_write_32(IMX_WUU1_BASE + 0x8, 0x0); 296 297 /* clear all the pad wakeup pending event */ 298 mmio_write_32(IMX_WUU1_BASE + 0x20, 0xffffffff); 299 300 /* 301 * disable the usb wakeup after resume to make sure the pending 302 * usb wakeup in WUU can be cleared successfully, otherwise, 303 * APD will resume failed in next PD mode. 304 */ 305 usb_wakeup_enable(false); 306 307 /* re-init the SCMI channel */ 308 imx8ulp_init_scmi_server(); 309 } 310 311 /* clear cluster's LPM setting. */ 312 mmio_write_32(IMX_CMC1_BASE + 0x20, 0x0); 313 mmio_write_32(IMX_CMC1_BASE + 0x10, 0x0); 314 315 /* clear core's LPM setting */ 316 mmio_write_32(IMX_CMC1_BASE + 0x50 + 0x4 * cpu, 0x0); 317 mmio_write_32(IMX_SIM1_BASE + 0x3c + 0x4 * cpu, 0x0); 318 319 if (is_local_state_off(CORE_PWR_STATE(target_state))) { 320 imx_pwr_set_cpu_entry(0, IMX_ROM_ENTRY); 321 plat_gic_cpuif_enable(); 322 } else { 323 dsb(); 324 write_scr_el3(read_scr_el3() & (~SCR_FIQ_BIT)); 325 isb(); 326 } 327 } 328 329 void __dead2 imx8ulp_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state) 330 { 331 while (1) { 332 wfi(); 333 } 334 } 335 336 void __dead2 imx8ulp_system_reset(void) 337 { 338 imx_pwr_set_cpu_entry(0, IMX_ROM_ENTRY); 339 340 /* Write invalid command to WDOG CNT to trigger reset */ 341 mmio_write_32(IMX_WDOG3_BASE + 0x4, 0x12345678); 342 343 while (true) { 344 wfi(); 345 } 346 } 347 348 int imx_validate_power_state(unsigned int power_state, 349 psci_power_state_t *req_state) 350 { 351 int pwr_lvl = psci_get_pstate_pwrlvl(power_state); 352 int pwr_type = psci_get_pstate_type(power_state); 353 354 if (pwr_lvl > PLAT_MAX_PWR_LVL) { 355 return PSCI_E_INVALID_PARAMS; 356 } 357 358 if (pwr_type == PSTATE_TYPE_STANDBY) { 359 CORE_PWR_STATE(req_state) = PLAT_MAX_RET_STATE; 360 CLUSTER_PWR_STATE(req_state) = PLAT_MAX_RET_STATE; 361 } 362 363 /* No power down state support */ 364 if (pwr_type == PSTATE_TYPE_POWERDOWN) { 365 return PSCI_E_INVALID_PARAMS; 366 } 367 368 return PSCI_E_SUCCESS; 369 } 370 371 void imx_get_sys_suspend_power_state(psci_power_state_t *req_state) 372 { 373 unsigned int i; 374 375 for (i = IMX_PWR_LVL0; i <= PLAT_MAX_PWR_LVL; i++) { 376 req_state->pwr_domain_state[i] = PLAT_POWER_DOWN_OFF_STATE; 377 } 378 } 379 380 void __dead2 imx_system_off(void) 381 { 382 unsigned int i; 383 384 /* config the all the core into OFF mode and IRQ masked. */ 385 for (i = 0U; i < PLATFORM_CORE_COUNT; i++) { 386 /* disable wakeup from wkpu */ 387 mmio_write_32(WKPUx(i), 0x0); 388 389 /* reset the core reset entry to 0x1000 */ 390 imx_pwr_set_cpu_entry(i, 0x1000); 391 392 /* config the core power mode to off */ 393 mmio_write_32(AD_COREx_LPMODE(i), 0x3); 394 } 395 396 plat_gic_cpuif_disable(); 397 398 /* Config the power mode info for entering DPD mode and ACT mode */ 399 imx_set_pwr_mode_cfg(ADMA_PWR_MODE); 400 imx_set_pwr_mode_cfg(ACT_PWR_MODE); 401 imx_set_pwr_mode_cfg(DPD_PWR_MODE); 402 403 /* Set the APD domain into DPD mode */ 404 mmio_write_32(IMX_CMC1_BASE + 0x10, 0x7); 405 mmio_write_32(IMX_CMC1_BASE + 0x20, 0x1f); 406 407 /* make sure no pending upower wakeup */ 408 upwr_xcp_set_rtd_apd_llwu(APD_DOMAIN, 0, NULL); 409 upower_wait_resp(); 410 411 /* enable the upower wakeup from wuu, act as APD boot up method */ 412 mmio_write_32(IMX_PCC3_BASE + 0x98, 0xc0800000); 413 mmio_setbits_32(IMX_WUU1_BASE + 0x18, BIT(4)); 414 415 /* make sure no pad wakeup event is pending */ 416 mmio_write_32(IMX_WUU1_BASE + 0x20, 0xffffffff); 417 418 wfi(); 419 420 ERROR("power off failed.\n"); 421 panic(); 422 } 423 424 static const plat_psci_ops_t imx_plat_psci_ops = { 425 .pwr_domain_on = imx_pwr_domain_on, 426 .pwr_domain_on_finish = imx_pwr_domain_on_finish, 427 .validate_ns_entrypoint = imx_validate_ns_entrypoint, 428 .system_off = imx_system_off, 429 .system_reset = imx8ulp_system_reset, 430 .pwr_domain_off = imx_pwr_domain_off, 431 .pwr_domain_suspend = imx_domain_suspend, 432 .pwr_domain_suspend_finish = imx_domain_suspend_finish, 433 .get_sys_suspend_power_state = imx_get_sys_suspend_power_state, 434 .validate_power_state = imx_validate_power_state, 435 .pwr_domain_pwr_down_wfi = imx8ulp_pwr_domain_pwr_down_wfi, 436 }; 437 438 int plat_setup_psci_ops(uintptr_t sec_entrypoint, 439 const plat_psci_ops_t **psci_ops) 440 { 441 secure_entrypoint = sec_entrypoint; 442 imx_pwr_set_cpu_entry(0, sec_entrypoint); 443 *psci_ops = &imx_plat_psci_ops; 444 445 mmio_write_32(IMX_CMC1_BASE + 0x18, 0x3f); 446 mmio_write_32(IMX_SIM1_BASE + 0x3c, 0xffffffff); 447 448 return 0; 449 } 450