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