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