1*753701ccSSumit Garg /* 2*753701ccSSumit Garg * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. 3*753701ccSSumit Garg * 4*753701ccSSumit Garg * SPDX-License-Identifier: BSD-3-Clause 5*753701ccSSumit Garg */ 6*753701ccSSumit Garg 7*753701ccSSumit Garg #include <arch_helpers.h> 8*753701ccSSumit Garg #include <assert.h> 9*753701ccSSumit Garg #include <cassert.h> 10*753701ccSSumit Garg #include <debug.h> 11*753701ccSSumit Garg #include <delay_timer.h> 12*753701ccSSumit Garg #include <errno.h> 13*753701ccSSumit Garg #include <generic_delay_timer.h> 14*753701ccSSumit Garg #include <platform_def.h> 15*753701ccSSumit Garg #include <sq_common.h> 16*753701ccSSumit Garg #include "sq_scpi.h" 17*753701ccSSumit Garg #include <psci.h> 18*753701ccSSumit Garg 19*753701ccSSumit Garg /* Macros to read the SQ power domain state */ 20*753701ccSSumit Garg #define SQ_PWR_LVL0 MPIDR_AFFLVL0 21*753701ccSSumit Garg #define SQ_PWR_LVL1 MPIDR_AFFLVL1 22*753701ccSSumit Garg #define SQ_PWR_LVL2 MPIDR_AFFLVL2 23*753701ccSSumit Garg 24*753701ccSSumit Garg #define SQ_CORE_PWR_STATE(state) (state)->pwr_domain_state[SQ_PWR_LVL0] 25*753701ccSSumit Garg #define SQ_CLUSTER_PWR_STATE(state) (state)->pwr_domain_state[SQ_PWR_LVL1] 26*753701ccSSumit Garg #define SQ_SYSTEM_PWR_STATE(state) ((PLAT_MAX_PWR_LVL > SQ_PWR_LVL1) ?\ 27*753701ccSSumit Garg (state)->pwr_domain_state[SQ_PWR_LVL2] : 0) 28*753701ccSSumit Garg 29*753701ccSSumit Garg uintptr_t sq_sec_entrypoint; 30*753701ccSSumit Garg 31*753701ccSSumit Garg int sq_pwr_domain_on(u_register_t mpidr) 32*753701ccSSumit Garg { 33*753701ccSSumit Garg /* 34*753701ccSSumit Garg * SCP takes care of powering up parent power domains so we 35*753701ccSSumit Garg * only need to care about level 0 36*753701ccSSumit Garg */ 37*753701ccSSumit Garg scpi_set_sq_power_state(mpidr, scpi_power_on, scpi_power_on, 38*753701ccSSumit Garg scpi_power_on); 39*753701ccSSumit Garg 40*753701ccSSumit Garg return PSCI_E_SUCCESS; 41*753701ccSSumit Garg } 42*753701ccSSumit Garg 43*753701ccSSumit Garg static void sq_pwr_domain_on_finisher_common( 44*753701ccSSumit Garg const psci_power_state_t *target_state) 45*753701ccSSumit Garg { 46*753701ccSSumit Garg assert(SQ_CORE_PWR_STATE(target_state) == SQ_LOCAL_STATE_OFF); 47*753701ccSSumit Garg 48*753701ccSSumit Garg /* 49*753701ccSSumit Garg * Perform the common cluster specific operations i.e enable coherency 50*753701ccSSumit Garg * if this cluster was off. 51*753701ccSSumit Garg */ 52*753701ccSSumit Garg if (SQ_CLUSTER_PWR_STATE(target_state) == SQ_LOCAL_STATE_OFF) 53*753701ccSSumit Garg plat_sq_interconnect_enter_coherency(); 54*753701ccSSumit Garg } 55*753701ccSSumit Garg 56*753701ccSSumit Garg void sq_pwr_domain_on_finish(const psci_power_state_t *target_state) 57*753701ccSSumit Garg { 58*753701ccSSumit Garg /* Assert that the system power domain need not be initialized */ 59*753701ccSSumit Garg assert(SQ_SYSTEM_PWR_STATE(target_state) == SQ_LOCAL_STATE_RUN); 60*753701ccSSumit Garg 61*753701ccSSumit Garg sq_pwr_domain_on_finisher_common(target_state); 62*753701ccSSumit Garg 63*753701ccSSumit Garg /* Program the gic per-cpu distributor or re-distributor interface */ 64*753701ccSSumit Garg sq_gic_pcpu_init(); 65*753701ccSSumit Garg 66*753701ccSSumit Garg /* Enable the gic cpu interface */ 67*753701ccSSumit Garg sq_gic_cpuif_enable(); 68*753701ccSSumit Garg } 69*753701ccSSumit Garg 70*753701ccSSumit Garg static void sq_power_down_common(const psci_power_state_t *target_state) 71*753701ccSSumit Garg { 72*753701ccSSumit Garg uint32_t cluster_state = scpi_power_on; 73*753701ccSSumit Garg uint32_t system_state = scpi_power_on; 74*753701ccSSumit Garg 75*753701ccSSumit Garg /* Prevent interrupts from spuriously waking up this cpu */ 76*753701ccSSumit Garg sq_gic_cpuif_disable(); 77*753701ccSSumit Garg 78*753701ccSSumit Garg /* Check if power down at system power domain level is requested */ 79*753701ccSSumit Garg if (SQ_SYSTEM_PWR_STATE(target_state) == SQ_LOCAL_STATE_OFF) 80*753701ccSSumit Garg system_state = scpi_power_retention; 81*753701ccSSumit Garg 82*753701ccSSumit Garg /* Cluster is to be turned off, so disable coherency */ 83*753701ccSSumit Garg if (SQ_CLUSTER_PWR_STATE(target_state) == SQ_LOCAL_STATE_OFF) { 84*753701ccSSumit Garg plat_sq_interconnect_exit_coherency(); 85*753701ccSSumit Garg cluster_state = scpi_power_off; 86*753701ccSSumit Garg } 87*753701ccSSumit Garg 88*753701ccSSumit Garg /* 89*753701ccSSumit Garg * Ask the SCP to power down the appropriate components depending upon 90*753701ccSSumit Garg * their state. 91*753701ccSSumit Garg */ 92*753701ccSSumit Garg scpi_set_sq_power_state(read_mpidr_el1(), 93*753701ccSSumit Garg scpi_power_off, 94*753701ccSSumit Garg cluster_state, 95*753701ccSSumit Garg system_state); 96*753701ccSSumit Garg } 97*753701ccSSumit Garg 98*753701ccSSumit Garg void sq_pwr_domain_off(const psci_power_state_t *target_state) 99*753701ccSSumit Garg { 100*753701ccSSumit Garg sq_power_down_common(target_state); 101*753701ccSSumit Garg } 102*753701ccSSumit Garg 103*753701ccSSumit Garg void __dead2 sq_system_off(void) 104*753701ccSSumit Garg { 105*753701ccSSumit Garg volatile uint32_t *gpio = (uint32_t *)PLAT_SQ_GPIO_BASE; 106*753701ccSSumit Garg 107*753701ccSSumit Garg /* set PD[9] high to power off the system */ 108*753701ccSSumit Garg gpio[5] |= 0x2; /* set output */ 109*753701ccSSumit Garg gpio[1] |= 0x2; /* set high */ 110*753701ccSSumit Garg dmbst(); 111*753701ccSSumit Garg 112*753701ccSSumit Garg generic_delay_timer_init(); 113*753701ccSSumit Garg 114*753701ccSSumit Garg mdelay(1); 115*753701ccSSumit Garg 116*753701ccSSumit Garg while (1) { 117*753701ccSSumit Garg gpio[1] &= ~0x2; /* set low */ 118*753701ccSSumit Garg dmbst(); 119*753701ccSSumit Garg 120*753701ccSSumit Garg mdelay(1); 121*753701ccSSumit Garg 122*753701ccSSumit Garg gpio[1] |= 0x2; /* set high */ 123*753701ccSSumit Garg dmbst(); 124*753701ccSSumit Garg 125*753701ccSSumit Garg mdelay(100); 126*753701ccSSumit Garg } 127*753701ccSSumit Garg 128*753701ccSSumit Garg wfi(); 129*753701ccSSumit Garg ERROR("SQ System Off: operation not handled.\n"); 130*753701ccSSumit Garg panic(); 131*753701ccSSumit Garg } 132*753701ccSSumit Garg 133*753701ccSSumit Garg void __dead2 sq_system_reset(void) 134*753701ccSSumit Garg { 135*753701ccSSumit Garg uint32_t response; 136*753701ccSSumit Garg 137*753701ccSSumit Garg /* Send the system reset request to the SCP */ 138*753701ccSSumit Garg response = scpi_sys_power_state(scpi_system_reboot); 139*753701ccSSumit Garg 140*753701ccSSumit Garg if (response != SCP_OK) { 141*753701ccSSumit Garg ERROR("SQ System Reset: SCP error %u.\n", response); 142*753701ccSSumit Garg panic(); 143*753701ccSSumit Garg } 144*753701ccSSumit Garg wfi(); 145*753701ccSSumit Garg ERROR("SQ System Reset: operation not handled.\n"); 146*753701ccSSumit Garg panic(); 147*753701ccSSumit Garg } 148*753701ccSSumit Garg 149*753701ccSSumit Garg void sq_cpu_standby(plat_local_state_t cpu_state) 150*753701ccSSumit Garg { 151*753701ccSSumit Garg unsigned int scr; 152*753701ccSSumit Garg 153*753701ccSSumit Garg assert(cpu_state == SQ_LOCAL_STATE_RET); 154*753701ccSSumit Garg 155*753701ccSSumit Garg scr = read_scr_el3(); 156*753701ccSSumit Garg /* Enable PhysicalIRQ bit for NS world to wake the CPU */ 157*753701ccSSumit Garg write_scr_el3(scr | SCR_IRQ_BIT); 158*753701ccSSumit Garg isb(); 159*753701ccSSumit Garg dsb(); 160*753701ccSSumit Garg wfi(); 161*753701ccSSumit Garg 162*753701ccSSumit Garg /* 163*753701ccSSumit Garg * Restore SCR to the original value, synchronisation of scr_el3 is 164*753701ccSSumit Garg * done by eret while el3_exit to save some execution cycles. 165*753701ccSSumit Garg */ 166*753701ccSSumit Garg write_scr_el3(scr); 167*753701ccSSumit Garg } 168*753701ccSSumit Garg 169*753701ccSSumit Garg const plat_psci_ops_t sq_psci_ops = { 170*753701ccSSumit Garg .pwr_domain_on = sq_pwr_domain_on, 171*753701ccSSumit Garg .pwr_domain_off = sq_pwr_domain_off, 172*753701ccSSumit Garg .pwr_domain_on_finish = sq_pwr_domain_on_finish, 173*753701ccSSumit Garg .cpu_standby = sq_cpu_standby, 174*753701ccSSumit Garg .system_off = sq_system_off, 175*753701ccSSumit Garg .system_reset = sq_system_reset, 176*753701ccSSumit Garg }; 177*753701ccSSumit Garg 178*753701ccSSumit Garg int plat_setup_psci_ops(uintptr_t sec_entrypoint, 179*753701ccSSumit Garg const struct plat_psci_ops **psci_ops) 180*753701ccSSumit Garg { 181*753701ccSSumit Garg sq_sec_entrypoint = sec_entrypoint; 182*753701ccSSumit Garg flush_dcache_range((uint64_t)&sq_sec_entrypoint, 183*753701ccSSumit Garg sizeof(sq_sec_entrypoint)); 184*753701ccSSumit Garg 185*753701ccSSumit Garg *psci_ops = &sq_psci_ops; 186*753701ccSSumit Garg 187*753701ccSSumit Garg return 0; 188*753701ccSSumit Garg } 189