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 /* PD */ 135 [PD_PWR_MODE] = { 136 .swt_board_offs = 0x170, 137 .swt_mem_offs = 0x178, 138 .pmic_cfg = PMIC_CFG(0x23, 0x2, 0x2), 139 .pad_cfg = PAD_CFG(0x0, 0x0, 0x01e80a00), 140 .bias_cfg = BIAS_CFG(0x0, 0x2, 0x2, 0x0), 141 }, 142 143 [ADMA_PWR_MODE] = { 144 .swt_board_offs = 0x120, 145 .swt_mem_offs = 0x128, 146 .pmic_cfg = PMIC_CFG(0x23, 0x0, 0x2), 147 .pad_cfg = PAD_CFG(0x0, 0x0, 0x0deb7a00), 148 .bias_cfg = BIAS_CFG(0x0, 0x2, 0x2, 0x0), 149 }, 150 151 [ACT_PWR_MODE] = { 152 .swt_board_offs = 0x110, 153 .swt_mem_offs = 0x118, 154 .pmic_cfg = PMIC_CFG(0x23, 0x2, 0x2), 155 .pad_cfg = PAD_CFG(0x0, 0x0, 0x0deb7a00), 156 .bias_cfg = BIAS_CFG(0x0, 0x2, 0x2, 0x0), 157 }, 158 }; 159 160 /* APD power switch config */ 161 ps_apd_swt_cfgs_t apd_swt_cfgs = { 162 [PD_PWR_MODE] = { 163 .swt_board[0] = SWT_BOARD(0x00060003, 0x00001e74), 164 .swt_mem[0] = SWT_MEM(0x00010c00, 0x0, 0x1ffff), 165 .swt_mem[1] = SWT_MEM(0x003fffff, 0x003f0000, 0x0), 166 }, 167 168 [ADMA_PWR_MODE] = { 169 .swt_board[0] = SWT_BOARD(0x0006ff77, 0x0006ff7c), 170 .swt_mem[0] = SWT_MEM(0x0001fffd, 0x0001fffd, 0x1ffff), 171 .swt_mem[1] = SWT_MEM(0x003fffff, 0x003fffff, 0x0), 172 }, 173 174 [ACT_PWR_MODE] = { 175 .swt_board[0] = SWT_BOARD(0x0006ff77, 0x0000ff7c), 176 .swt_mem[0] = SWT_MEM(0x0001fffd, 0x0001fffd, 0x1ffff), 177 .swt_mem[1] = SWT_MEM(0x003fffff, 0x003fffff, 0x0), 178 }, 179 }; 180 181 struct ps_pwr_mode_cfg_t *pwr_sys_cfg = (struct ps_pwr_mode_cfg_t *)UPWR_DRAM_SHARED_BASE_ADDR; 182 183 void imx_set_pwr_mode_cfg(abs_pwr_mode_t mode) 184 { 185 if (mode >= NUM_PWR_MODES) { 186 return; 187 } 188 189 /* apd power mode config */ 190 memcpy(&pwr_sys_cfg->ps_apd_pwr_mode_cfg[mode], &apd_pwr_mode_cfgs[mode], 191 sizeof(struct ps_apd_pwr_mode_cfg_t)); 192 193 /* apd power switch config */ 194 memcpy(&pwr_sys_cfg->ps_apd_swt_cfg[mode], &apd_swt_cfgs[mode], sizeof(swt_config_t)); 195 } 196 197 void imx_domain_suspend(const psci_power_state_t *target_state) 198 { 199 unsigned int cpu = MPIDR_AFFLVL0_VAL(read_mpidr_el1()); 200 201 if (is_local_state_off(CORE_PWR_STATE(target_state))) { 202 plat_gic_cpuif_disable(); 203 imx_pwr_set_cpu_entry(cpu, secure_entrypoint); 204 /* core put into power down */ 205 mmio_write_32(IMX_CMC1_BASE + 0x50 + 0x4 * cpu, 0x3); 206 /* FIXME config wakeup interrupt in WKPU */ 207 mmio_write_32(IMX_SIM1_BASE + 0x3c + 0x4 * cpu, 0x7fffffe3); 208 } else { 209 /* for core standby/retention mode */ 210 mmio_write_32(IMX_CMC1_BASE + 0x50 + 0x4 * cpu, 0x1); 211 mmio_write_32(IMX_SIM1_BASE + 0x3c + 0x4 * cpu, 0x7fffffe3); 212 dsb(); 213 write_scr_el3(read_scr_el3() | SCR_FIQ_BIT); 214 isb(); 215 } 216 217 if (is_local_state_retn(CLUSTER_PWR_STATE(target_state))) { 218 /* 219 * just for sleep mode for now, need to update to 220 * support more modes, same for suspend finish call back. 221 */ 222 mmio_write_32(IMX_CMC1_BASE + 0x10, 0x1); 223 mmio_write_32(IMX_CMC1_BASE + 0x20, 0x1); 224 225 } else if (is_local_state_off(CLUSTER_PWR_STATE(target_state))) { 226 /* 227 * for cluster off state, put cluster into power down mode, 228 * config the cluster clock to be off. 229 */ 230 mmio_write_32(IMX_CMC1_BASE + 0x10, 0x7); 231 mmio_write_32(IMX_CMC1_BASE + 0x20, 0xf); 232 } 233 234 if (is_local_state_off(SYSTEM_PWR_STATE(target_state))) { 235 /* 236 * low power mode config info used by upower 237 * to do low power mode transition. 238 */ 239 imx_set_pwr_mode_cfg(ADMA_PWR_MODE); 240 imx_set_pwr_mode_cfg(ACT_PWR_MODE); 241 imx_set_pwr_mode_cfg(PD_PWR_MODE); 242 243 /* clear the upower wakeup */ 244 upwr_xcp_set_rtd_apd_llwu(APD_DOMAIN, 0, NULL); 245 upower_wait_resp(); 246 247 /* enable the USB wakeup */ 248 usb_wakeup_enable(true); 249 250 /* config the WUU to enabled the wakeup source */ 251 mmio_write_32(IMX_PCC3_BASE + 0x98, 0xc0800000); 252 253 /* !!! clear all the pad wakeup pending event */ 254 mmio_write_32(IMX_WUU1_BASE + 0x20, 0xffffffff); 255 256 /* enable upower usb phy wakeup by default */ 257 mmio_setbits_32(IMX_WUU1_BASE + 0x18, BIT(4) | BIT(1) | BIT(0)); 258 259 /* enabled all pad wakeup by default */ 260 mmio_write_32(IMX_WUU1_BASE + 0x8, 0xffffffff); 261 262 /* save the AD domain context before entering PD mode */ 263 imx_apd_ctx_save(cpu); 264 } 265 } 266 267 extern void imx8ulp_init_scmi_server(void); 268 void imx_domain_suspend_finish(const psci_power_state_t *target_state) 269 { 270 unsigned int cpu = MPIDR_AFFLVL0_VAL(read_mpidr_el1()); 271 272 if (is_local_state_off(SYSTEM_PWR_STATE(target_state))) { 273 /* restore the ap domain context */ 274 imx_apd_ctx_restore(cpu); 275 276 /* clear the upower wakeup */ 277 upwr_xcp_set_rtd_apd_llwu(APD_DOMAIN, 0, NULL); 278 upower_wait_resp(); 279 280 /* disable all pad wakeup */ 281 mmio_write_32(IMX_WUU1_BASE + 0x8, 0x0); 282 283 /* clear all the pad wakeup pending event */ 284 mmio_write_32(IMX_WUU1_BASE + 0x20, 0xffffffff); 285 286 /* 287 * disable the usb wakeup after resume to make sure the pending 288 * usb wakeup in WUU can be cleared successfully, otherwise, 289 * APD will resume failed in next PD mode. 290 */ 291 usb_wakeup_enable(false); 292 293 /* re-init the SCMI channel */ 294 imx8ulp_init_scmi_server(); 295 } 296 297 /* clear cluster's LPM setting. */ 298 mmio_write_32(IMX_CMC1_BASE + 0x20, 0x0); 299 mmio_write_32(IMX_CMC1_BASE + 0x10, 0x0); 300 301 /* clear core's LPM setting */ 302 mmio_write_32(IMX_CMC1_BASE + 0x50 + 0x4 * cpu, 0x0); 303 mmio_write_32(IMX_SIM1_BASE + 0x3c + 0x4 * cpu, 0x0); 304 305 if (is_local_state_off(CORE_PWR_STATE(target_state))) { 306 imx_pwr_set_cpu_entry(0, IMX_ROM_ENTRY); 307 plat_gic_cpuif_enable(); 308 } else { 309 dsb(); 310 write_scr_el3(read_scr_el3() & (~SCR_FIQ_BIT)); 311 isb(); 312 } 313 } 314 315 void __dead2 imx8ulp_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state) 316 { 317 while (1) { 318 wfi(); 319 } 320 } 321 322 void __dead2 imx8ulp_system_reset(void) 323 { 324 imx_pwr_set_cpu_entry(0, IMX_ROM_ENTRY); 325 326 /* Write invalid command to WDOG CNT to trigger reset */ 327 mmio_write_32(IMX_WDOG3_BASE + 0x4, 0x12345678); 328 329 while (true) { 330 wfi(); 331 } 332 } 333 334 int imx_validate_power_state(unsigned int power_state, 335 psci_power_state_t *req_state) 336 { 337 int pwr_lvl = psci_get_pstate_pwrlvl(power_state); 338 int pwr_type = psci_get_pstate_type(power_state); 339 340 if (pwr_lvl > PLAT_MAX_PWR_LVL) { 341 return PSCI_E_INVALID_PARAMS; 342 } 343 344 if (pwr_type == PSTATE_TYPE_STANDBY) { 345 CORE_PWR_STATE(req_state) = PLAT_MAX_RET_STATE; 346 CLUSTER_PWR_STATE(req_state) = PLAT_MAX_RET_STATE; 347 } 348 349 /* No power down state support */ 350 if (pwr_type == PSTATE_TYPE_POWERDOWN) { 351 return PSCI_E_INVALID_PARAMS; 352 } 353 354 return PSCI_E_SUCCESS; 355 } 356 357 void imx_get_sys_suspend_power_state(psci_power_state_t *req_state) 358 { 359 unsigned int i; 360 361 for (i = IMX_PWR_LVL0; i <= PLAT_MAX_PWR_LVL; i++) { 362 req_state->pwr_domain_state[i] = PLAT_POWER_DOWN_OFF_STATE; 363 } 364 } 365 366 static const plat_psci_ops_t imx_plat_psci_ops = { 367 .pwr_domain_on = imx_pwr_domain_on, 368 .pwr_domain_on_finish = imx_pwr_domain_on_finish, 369 .validate_ns_entrypoint = imx_validate_ns_entrypoint, 370 .system_reset = imx8ulp_system_reset, 371 .pwr_domain_off = imx_pwr_domain_off, 372 .pwr_domain_suspend = imx_domain_suspend, 373 .pwr_domain_suspend_finish = imx_domain_suspend_finish, 374 .get_sys_suspend_power_state = imx_get_sys_suspend_power_state, 375 .validate_power_state = imx_validate_power_state, 376 .pwr_domain_pwr_down_wfi = imx8ulp_pwr_domain_pwr_down_wfi, 377 }; 378 379 int plat_setup_psci_ops(uintptr_t sec_entrypoint, 380 const plat_psci_ops_t **psci_ops) 381 { 382 secure_entrypoint = sec_entrypoint; 383 imx_pwr_set_cpu_entry(0, sec_entrypoint); 384 *psci_ops = &imx_plat_psci_ops; 385 386 mmio_write_32(IMX_CMC1_BASE + 0x18, 0x3f); 387 mmio_write_32(IMX_SIM1_BASE + 0x3c, 0xffffffff); 388 389 return 0; 390 } 391