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 18 static uintptr_t secure_entrypoint; 19 20 #define CORE_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL0]) 21 #define CLUSTER_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL1]) 22 #define SYSTEM_PWR_STATE(state) ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL]) 23 24 #define RVBARADDRx(c) (IMX_SIM1_BASE + 0x5c + 0x4 * (c)) 25 #define WKPUx(c) (IMX_SIM1_BASE + 0x3c + 0x4 * (c)) 26 #define AD_COREx_LPMODE(c) (IMX_CMC1_BASE + 0x50 + 0x4 * (c)) 27 28 static int imx_pwr_set_cpu_entry(unsigned int cpu, unsigned int entry) 29 { 30 mmio_write_32(RVBARADDRx(cpu), entry); 31 32 /* set update bit */ 33 mmio_write_32(IMX_SIM1_BASE + 0x8, mmio_read_32(IMX_SIM1_BASE + 0x8) | BIT_32(24 + cpu)); 34 /* wait for ack */ 35 while (!(mmio_read_32(IMX_SIM1_BASE + 0x8) & BIT_32(26 + cpu))) { 36 } 37 38 /* clear update bit */ 39 mmio_write_32(IMX_SIM1_BASE + 0x8, mmio_read_32(IMX_SIM1_BASE + 0x8) & ~BIT_32(24 + cpu)); 40 /* clear ack bit */ 41 mmio_write_32(IMX_SIM1_BASE + 0x8, mmio_read_32(IMX_SIM1_BASE + 0x8) | BIT_32(26 + cpu)); 42 43 return 0; 44 } 45 46 int imx_pwr_domain_on(u_register_t mpidr) 47 { 48 unsigned int cpu = MPIDR_AFFLVL0_VAL(mpidr); 49 50 imx_pwr_set_cpu_entry(cpu, secure_entrypoint); 51 52 mmio_write_32(IMX_CMC1_BASE + 0x18, 0x3f); 53 mmio_write_32(IMX_CMC1_BASE + 0x50 + 0x4 * cpu, 0); 54 55 /* enable wku wakeup for idle */ 56 mmio_write_32(IMX_SIM1_BASE + 0x3c + 0x4 * cpu, 0xffffffff); 57 58 return PSCI_E_SUCCESS; 59 } 60 61 void imx_pwr_domain_on_finish(const psci_power_state_t *target_state) 62 { 63 imx_pwr_set_cpu_entry(0, IMX_ROM_ENTRY); 64 plat_gic_pcpu_init(); 65 plat_gic_cpuif_enable(); 66 } 67 68 int imx_validate_ns_entrypoint(uintptr_t ns_entrypoint) 69 { 70 return PSCI_E_SUCCESS; 71 } 72 73 void imx_pwr_domain_off(const psci_power_state_t *target_state) 74 { 75 unsigned int cpu = MPIDR_AFFLVL0_VAL(read_mpidr_el1()); 76 77 plat_gic_cpuif_disable(); 78 79 /* disable wakeup */ 80 mmio_write_32(WKPUx(cpu), 0); 81 82 mmio_write_32(AD_COREx_LPMODE(cpu), 0x3); 83 } 84 85 void __dead2 imx8ulp_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state) 86 { 87 while (1) { 88 wfi(); 89 } 90 } 91 92 void __dead2 imx8ulp_system_reset(void) 93 { 94 imx_pwr_set_cpu_entry(0, IMX_ROM_ENTRY); 95 96 /* Write invalid command to WDOG CNT to trigger reset */ 97 mmio_write_32(IMX_WDOG3_BASE + 0x4, 0x12345678); 98 99 while (true) { 100 wfi(); 101 } 102 } 103 104 static const plat_psci_ops_t imx_plat_psci_ops = { 105 .pwr_domain_on = imx_pwr_domain_on, 106 .pwr_domain_on_finish = imx_pwr_domain_on_finish, 107 .validate_ns_entrypoint = imx_validate_ns_entrypoint, 108 .system_reset = imx8ulp_system_reset, 109 .pwr_domain_off = imx_pwr_domain_off, 110 .pwr_domain_pwr_down_wfi = imx8ulp_pwr_domain_pwr_down_wfi, 111 }; 112 113 int plat_setup_psci_ops(uintptr_t sec_entrypoint, 114 const plat_psci_ops_t **psci_ops) 115 { 116 secure_entrypoint = sec_entrypoint; 117 imx_pwr_set_cpu_entry(0, sec_entrypoint); 118 *psci_ops = &imx_plat_psci_ops; 119 120 mmio_write_32(IMX_CMC1_BASE + 0x18, 0x3f); 121 mmio_write_32(IMX_SIM1_BASE + 0x3c, 0xffffffff); 122 123 return 0; 124 } 125