1*964dfee1SYann Gautier /* 2*964dfee1SYann Gautier * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. 3*964dfee1SYann Gautier * 4*964dfee1SYann Gautier * SPDX-License-Identifier: BSD-3-Clause 5*964dfee1SYann Gautier */ 6*964dfee1SYann Gautier 7*964dfee1SYann Gautier #include <arch_helpers.h> 8*964dfee1SYann Gautier #include <assert.h> 9*964dfee1SYann Gautier #include <boot_api.h> 10*964dfee1SYann Gautier #include <debug.h> 11*964dfee1SYann Gautier #include <dt-bindings/clock/stm32mp1-clks.h> 12*964dfee1SYann Gautier #include <errno.h> 13*964dfee1SYann Gautier #include <gic_common.h> 14*964dfee1SYann Gautier #include <gicv2.h> 15*964dfee1SYann Gautier #include <mmio.h> 16*964dfee1SYann Gautier #include <platform_def.h> 17*964dfee1SYann Gautier #include <platform.h> 18*964dfee1SYann Gautier #include <psci.h> 19*964dfee1SYann Gautier #include <stm32mp1_clk.h> 20*964dfee1SYann Gautier #include <stm32mp1_private.h> 21*964dfee1SYann Gautier #include <stm32mp1_rcc.h> 22*964dfee1SYann Gautier 23*964dfee1SYann Gautier static uint32_t stm32_sec_entrypoint; 24*964dfee1SYann Gautier static uint32_t cntfrq_core0; 25*964dfee1SYann Gautier 26*964dfee1SYann Gautier #define SEND_SECURE_IT_TO_CORE_1 0x20000U 27*964dfee1SYann Gautier 28*964dfee1SYann Gautier /******************************************************************************* 29*964dfee1SYann Gautier * STM32MP1 handler called when a CPU is about to enter standby. 30*964dfee1SYann Gautier * call by core 1 to enter in wfi 31*964dfee1SYann Gautier ******************************************************************************/ 32*964dfee1SYann Gautier static void stm32_cpu_standby(plat_local_state_t cpu_state) 33*964dfee1SYann Gautier { 34*964dfee1SYann Gautier uint32_t interrupt = GIC_SPURIOUS_INTERRUPT; 35*964dfee1SYann Gautier 36*964dfee1SYann Gautier assert(cpu_state == ARM_LOCAL_STATE_RET); 37*964dfee1SYann Gautier 38*964dfee1SYann Gautier /* 39*964dfee1SYann Gautier * Enter standby state 40*964dfee1SYann Gautier * dsb is good practice before using wfi to enter low power states 41*964dfee1SYann Gautier */ 42*964dfee1SYann Gautier dsb(); 43*964dfee1SYann Gautier while (interrupt == GIC_SPURIOUS_INTERRUPT) { 44*964dfee1SYann Gautier wfi(); 45*964dfee1SYann Gautier 46*964dfee1SYann Gautier /* Acknoledge IT */ 47*964dfee1SYann Gautier interrupt = gicv2_acknowledge_interrupt(); 48*964dfee1SYann Gautier /* If Interrupt == 1022 it will be acknowledged by non secure */ 49*964dfee1SYann Gautier if ((interrupt != PENDING_G1_INTID) && 50*964dfee1SYann Gautier (interrupt != GIC_SPURIOUS_INTERRUPT)) { 51*964dfee1SYann Gautier gicv2_end_of_interrupt(interrupt); 52*964dfee1SYann Gautier } 53*964dfee1SYann Gautier } 54*964dfee1SYann Gautier } 55*964dfee1SYann Gautier 56*964dfee1SYann Gautier /******************************************************************************* 57*964dfee1SYann Gautier * STM32MP1 handler called when a power domain is about to be turned on. The 58*964dfee1SYann Gautier * mpidr determines the CPU to be turned on. 59*964dfee1SYann Gautier * call by core 0 to activate core 1 60*964dfee1SYann Gautier ******************************************************************************/ 61*964dfee1SYann Gautier static int stm32_pwr_domain_on(u_register_t mpidr) 62*964dfee1SYann Gautier { 63*964dfee1SYann Gautier unsigned long current_cpu_mpidr = read_mpidr_el1(); 64*964dfee1SYann Gautier uint32_t tamp_clk_off = 0; 65*964dfee1SYann Gautier uint32_t bkpr_core1_addr = 66*964dfee1SYann Gautier tamp_bkpr(BOOT_API_CORE1_BRANCH_ADDRESS_TAMP_BCK_REG_IDX); 67*964dfee1SYann Gautier uint32_t bkpr_core1_magic = 68*964dfee1SYann Gautier tamp_bkpr(BOOT_API_CORE1_MAGIC_NUMBER_TAMP_BCK_REG_IDX); 69*964dfee1SYann Gautier 70*964dfee1SYann Gautier if (mpidr == current_cpu_mpidr) { 71*964dfee1SYann Gautier return PSCI_E_INVALID_PARAMS; 72*964dfee1SYann Gautier } 73*964dfee1SYann Gautier 74*964dfee1SYann Gautier if ((stm32_sec_entrypoint < STM32MP1_SRAM_BASE) || 75*964dfee1SYann Gautier (stm32_sec_entrypoint > (STM32MP1_SRAM_BASE + 76*964dfee1SYann Gautier (STM32MP1_SRAM_SIZE - 1)))) { 77*964dfee1SYann Gautier return PSCI_E_INVALID_ADDRESS; 78*964dfee1SYann Gautier } 79*964dfee1SYann Gautier 80*964dfee1SYann Gautier if (!stm32mp1_clk_is_enabled(RTCAPB)) { 81*964dfee1SYann Gautier tamp_clk_off = 1; 82*964dfee1SYann Gautier if (stm32mp1_clk_enable(RTCAPB) != 0) { 83*964dfee1SYann Gautier panic(); 84*964dfee1SYann Gautier } 85*964dfee1SYann Gautier } 86*964dfee1SYann Gautier 87*964dfee1SYann Gautier cntfrq_core0 = read_cntfrq_el0(); 88*964dfee1SYann Gautier 89*964dfee1SYann Gautier /* Write entrypoint in backup RAM register */ 90*964dfee1SYann Gautier mmio_write_32(bkpr_core1_addr, stm32_sec_entrypoint); 91*964dfee1SYann Gautier 92*964dfee1SYann Gautier /* Write magic number in backup register */ 93*964dfee1SYann Gautier mmio_write_32(bkpr_core1_magic, BOOT_API_A7_CORE1_MAGIC_NUMBER); 94*964dfee1SYann Gautier 95*964dfee1SYann Gautier if (tamp_clk_off != 0U) { 96*964dfee1SYann Gautier if (stm32mp1_clk_disable(RTCAPB) != 0) { 97*964dfee1SYann Gautier panic(); 98*964dfee1SYann Gautier } 99*964dfee1SYann Gautier } 100*964dfee1SYann Gautier 101*964dfee1SYann Gautier /* Generate an IT to core 1 */ 102*964dfee1SYann Gautier mmio_write_32(STM32MP1_GICD_BASE + GICD_SGIR, 103*964dfee1SYann Gautier SEND_SECURE_IT_TO_CORE_1 | ARM_IRQ_SEC_SGI_0); 104*964dfee1SYann Gautier 105*964dfee1SYann Gautier return PSCI_E_SUCCESS; 106*964dfee1SYann Gautier } 107*964dfee1SYann Gautier 108*964dfee1SYann Gautier /******************************************************************************* 109*964dfee1SYann Gautier * STM32MP1 handler called when a power domain is about to be turned off. The 110*964dfee1SYann Gautier * target_state encodes the power state that each level should transition to. 111*964dfee1SYann Gautier ******************************************************************************/ 112*964dfee1SYann Gautier static void stm32_pwr_domain_off(const psci_power_state_t *target_state) 113*964dfee1SYann Gautier { 114*964dfee1SYann Gautier /* Nothing to do */ 115*964dfee1SYann Gautier } 116*964dfee1SYann Gautier 117*964dfee1SYann Gautier /******************************************************************************* 118*964dfee1SYann Gautier * STM32MP1 handler called when a power domain is about to be suspended. The 119*964dfee1SYann Gautier * target_state encodes the power state that each level should transition to. 120*964dfee1SYann Gautier ******************************************************************************/ 121*964dfee1SYann Gautier static void stm32_pwr_domain_suspend(const psci_power_state_t *target_state) 122*964dfee1SYann Gautier { 123*964dfee1SYann Gautier /* Nothing to do, power domain is not disabled */ 124*964dfee1SYann Gautier } 125*964dfee1SYann Gautier 126*964dfee1SYann Gautier /******************************************************************************* 127*964dfee1SYann Gautier * STM32MP1 handler called when a power domain has just been powered on after 128*964dfee1SYann Gautier * being turned off earlier. The target_state encodes the low power state that 129*964dfee1SYann Gautier * each level has woken up from. 130*964dfee1SYann Gautier * call by core 1 just after wake up 131*964dfee1SYann Gautier ******************************************************************************/ 132*964dfee1SYann Gautier static void stm32_pwr_domain_on_finish(const psci_power_state_t *target_state) 133*964dfee1SYann Gautier { 134*964dfee1SYann Gautier stm32mp1_gic_pcpu_init(); 135*964dfee1SYann Gautier 136*964dfee1SYann Gautier write_cntfrq_el0(cntfrq_core0); 137*964dfee1SYann Gautier } 138*964dfee1SYann Gautier 139*964dfee1SYann Gautier /******************************************************************************* 140*964dfee1SYann Gautier * STM32MP1 handler called when a power domain has just been powered on after 141*964dfee1SYann Gautier * having been suspended earlier. The target_state encodes the low power state 142*964dfee1SYann Gautier * that each level has woken up from. 143*964dfee1SYann Gautier ******************************************************************************/ 144*964dfee1SYann Gautier static void stm32_pwr_domain_suspend_finish(const psci_power_state_t 145*964dfee1SYann Gautier *target_state) 146*964dfee1SYann Gautier { 147*964dfee1SYann Gautier /* Nothing to do, power domain is not disabled */ 148*964dfee1SYann Gautier } 149*964dfee1SYann Gautier 150*964dfee1SYann Gautier static void __dead2 stm32_pwr_domain_pwr_down_wfi(const psci_power_state_t 151*964dfee1SYann Gautier *target_state) 152*964dfee1SYann Gautier { 153*964dfee1SYann Gautier ERROR("stm32mpu1 Power Down WFI: operation not handled.\n"); 154*964dfee1SYann Gautier panic(); 155*964dfee1SYann Gautier } 156*964dfee1SYann Gautier 157*964dfee1SYann Gautier static void __dead2 stm32_system_off(void) 158*964dfee1SYann Gautier { 159*964dfee1SYann Gautier ERROR("stm32mpu1 System Off: operation not handled.\n"); 160*964dfee1SYann Gautier panic(); 161*964dfee1SYann Gautier } 162*964dfee1SYann Gautier 163*964dfee1SYann Gautier static void __dead2 stm32_system_reset(void) 164*964dfee1SYann Gautier { 165*964dfee1SYann Gautier mmio_setbits_32(RCC_BASE + RCC_MP_GRSTCSETR, RCC_MP_GRSTCSETR_MPSYSRST); 166*964dfee1SYann Gautier 167*964dfee1SYann Gautier /* Loop in case system reset is not immediately caught */ 168*964dfee1SYann Gautier for ( ; ; ) { 169*964dfee1SYann Gautier ; 170*964dfee1SYann Gautier } 171*964dfee1SYann Gautier } 172*964dfee1SYann Gautier 173*964dfee1SYann Gautier static int stm32_validate_power_state(unsigned int power_state, 174*964dfee1SYann Gautier psci_power_state_t *req_state) 175*964dfee1SYann Gautier { 176*964dfee1SYann Gautier int pstate = psci_get_pstate_type(power_state); 177*964dfee1SYann Gautier 178*964dfee1SYann Gautier if (pstate != 0) { 179*964dfee1SYann Gautier return PSCI_E_INVALID_PARAMS; 180*964dfee1SYann Gautier } 181*964dfee1SYann Gautier 182*964dfee1SYann Gautier if (psci_get_pstate_pwrlvl(power_state)) { 183*964dfee1SYann Gautier return PSCI_E_INVALID_PARAMS; 184*964dfee1SYann Gautier } 185*964dfee1SYann Gautier 186*964dfee1SYann Gautier if (psci_get_pstate_id(power_state)) { 187*964dfee1SYann Gautier return PSCI_E_INVALID_PARAMS; 188*964dfee1SYann Gautier } 189*964dfee1SYann Gautier 190*964dfee1SYann Gautier req_state->pwr_domain_state[0] = ARM_LOCAL_STATE_RET; 191*964dfee1SYann Gautier req_state->pwr_domain_state[1] = ARM_LOCAL_STATE_RUN; 192*964dfee1SYann Gautier 193*964dfee1SYann Gautier return PSCI_E_SUCCESS; 194*964dfee1SYann Gautier } 195*964dfee1SYann Gautier 196*964dfee1SYann Gautier static int stm32_validate_ns_entrypoint(uintptr_t entrypoint) 197*964dfee1SYann Gautier { 198*964dfee1SYann Gautier /* The non-secure entry point must be in DDR */ 199*964dfee1SYann Gautier if (entrypoint < STM32MP1_DDR_BASE) { 200*964dfee1SYann Gautier return PSCI_E_INVALID_ADDRESS; 201*964dfee1SYann Gautier } 202*964dfee1SYann Gautier 203*964dfee1SYann Gautier return PSCI_E_SUCCESS; 204*964dfee1SYann Gautier } 205*964dfee1SYann Gautier 206*964dfee1SYann Gautier static int stm32_node_hw_state(u_register_t target_cpu, 207*964dfee1SYann Gautier unsigned int power_level) 208*964dfee1SYann Gautier { 209*964dfee1SYann Gautier /* 210*964dfee1SYann Gautier * The format of 'power_level' is implementation-defined, but 0 must 211*964dfee1SYann Gautier * mean a CPU. Only allow level 0. 212*964dfee1SYann Gautier */ 213*964dfee1SYann Gautier if (power_level != MPIDR_AFFLVL0) { 214*964dfee1SYann Gautier return PSCI_E_INVALID_PARAMS; 215*964dfee1SYann Gautier } 216*964dfee1SYann Gautier 217*964dfee1SYann Gautier /* 218*964dfee1SYann Gautier * From psci view the CPU 0 is always ON, 219*964dfee1SYann Gautier * CPU 1 can be SUSPEND or RUNNING. 220*964dfee1SYann Gautier * Therefore do not manage POWER OFF state and always return HW_ON. 221*964dfee1SYann Gautier */ 222*964dfee1SYann Gautier 223*964dfee1SYann Gautier return (int)HW_ON; 224*964dfee1SYann Gautier } 225*964dfee1SYann Gautier 226*964dfee1SYann Gautier /******************************************************************************* 227*964dfee1SYann Gautier * Export the platform handlers. The ARM Standard platform layer will take care 228*964dfee1SYann Gautier * of registering the handlers with PSCI. 229*964dfee1SYann Gautier ******************************************************************************/ 230*964dfee1SYann Gautier static const plat_psci_ops_t stm32_psci_ops = { 231*964dfee1SYann Gautier .cpu_standby = stm32_cpu_standby, 232*964dfee1SYann Gautier .pwr_domain_on = stm32_pwr_domain_on, 233*964dfee1SYann Gautier .pwr_domain_off = stm32_pwr_domain_off, 234*964dfee1SYann Gautier .pwr_domain_suspend = stm32_pwr_domain_suspend, 235*964dfee1SYann Gautier .pwr_domain_on_finish = stm32_pwr_domain_on_finish, 236*964dfee1SYann Gautier .pwr_domain_suspend_finish = stm32_pwr_domain_suspend_finish, 237*964dfee1SYann Gautier .pwr_domain_pwr_down_wfi = stm32_pwr_domain_pwr_down_wfi, 238*964dfee1SYann Gautier .system_off = stm32_system_off, 239*964dfee1SYann Gautier .system_reset = stm32_system_reset, 240*964dfee1SYann Gautier .validate_power_state = stm32_validate_power_state, 241*964dfee1SYann Gautier .validate_ns_entrypoint = stm32_validate_ns_entrypoint, 242*964dfee1SYann Gautier .get_node_hw_state = stm32_node_hw_state 243*964dfee1SYann Gautier }; 244*964dfee1SYann Gautier 245*964dfee1SYann Gautier /******************************************************************************* 246*964dfee1SYann Gautier * Export the platform specific power ops. 247*964dfee1SYann Gautier ******************************************************************************/ 248*964dfee1SYann Gautier int plat_setup_psci_ops(uintptr_t sec_entrypoint, 249*964dfee1SYann Gautier const plat_psci_ops_t **psci_ops) 250*964dfee1SYann Gautier { 251*964dfee1SYann Gautier stm32_sec_entrypoint = sec_entrypoint; 252*964dfee1SYann Gautier *psci_ops = &stm32_psci_ops; 253*964dfee1SYann Gautier 254*964dfee1SYann Gautier return 0; 255*964dfee1SYann Gautier } 256