1 /* 2 * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <platform_def.h> 9 10 #include <arch_helpers.h> 11 #include <common/debug.h> 12 #include <lib/psci/psci.h> 13 #include <lib/semihosting.h> 14 #include <plat/common/platform.h> 15 16 #include "qemu_private.h" 17 18 #define ADP_STOPPED_APPLICATION_EXIT 0x20026 19 20 /* 21 * The secure entry point to be used on warm reset. 22 */ 23 static unsigned long secure_entrypoint; 24 25 /* Make composite power state parameter till power level 0 */ 26 #if PSCI_EXTENDED_STATE_ID 27 28 #define qemu_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \ 29 (((lvl0_state) << PSTATE_ID_SHIFT) | \ 30 ((type) << PSTATE_TYPE_SHIFT)) 31 #else 32 #define qemu_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \ 33 (((lvl0_state) << PSTATE_ID_SHIFT) | \ 34 ((pwr_lvl) << PSTATE_PWR_LVL_SHIFT) | \ 35 ((type) << PSTATE_TYPE_SHIFT)) 36 #endif /* PSCI_EXTENDED_STATE_ID */ 37 38 39 #define qemu_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type) \ 40 (((lvl1_state) << PLAT_LOCAL_PSTATE_WIDTH) | \ 41 qemu_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type)) 42 43 44 45 /* 46 * The table storing the valid idle power states. Ensure that the 47 * array entries are populated in ascending order of state-id to 48 * enable us to use binary search during power state validation. 49 * The table must be terminated by a NULL entry. 50 */ 51 static const unsigned int qemu_pm_idle_states[] = { 52 /* State-id - 0x01 */ 53 qemu_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_RET, 54 MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY), 55 /* State-id - 0x02 */ 56 qemu_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_OFF, 57 MPIDR_AFFLVL0, PSTATE_TYPE_POWERDOWN), 58 /* State-id - 0x22 */ 59 qemu_make_pwrstate_lvl1(PLAT_LOCAL_STATE_OFF, PLAT_LOCAL_STATE_OFF, 60 MPIDR_AFFLVL1, PSTATE_TYPE_POWERDOWN), 61 0, 62 }; 63 64 /******************************************************************************* 65 * Platform handler called to check the validity of the power state 66 * parameter. The power state parameter has to be a composite power state. 67 ******************************************************************************/ 68 static int qemu_validate_power_state(unsigned int power_state, 69 psci_power_state_t *req_state) 70 { 71 unsigned int state_id; 72 int i; 73 74 assert(req_state); 75 76 /* 77 * Currently we are using a linear search for finding the matching 78 * entry in the idle power state array. This can be made a binary 79 * search if the number of entries justify the additional complexity. 80 */ 81 for (i = 0; !!qemu_pm_idle_states[i]; i++) { 82 if (power_state == qemu_pm_idle_states[i]) 83 break; 84 } 85 86 /* Return error if entry not found in the idle state array */ 87 if (!qemu_pm_idle_states[i]) 88 return PSCI_E_INVALID_PARAMS; 89 90 i = 0; 91 state_id = psci_get_pstate_id(power_state); 92 93 /* Parse the State ID and populate the state info parameter */ 94 while (state_id) { 95 req_state->pwr_domain_state[i++] = state_id & 96 PLAT_LOCAL_PSTATE_MASK; 97 state_id >>= PLAT_LOCAL_PSTATE_WIDTH; 98 } 99 100 return PSCI_E_SUCCESS; 101 } 102 103 /******************************************************************************* 104 * Platform handler called to check the validity of the non secure 105 * entrypoint. 106 ******************************************************************************/ 107 static int qemu_validate_ns_entrypoint(uintptr_t entrypoint) 108 { 109 /* 110 * Check if the non secure entrypoint lies within the non 111 * secure DRAM. 112 */ 113 if ((entrypoint >= NS_DRAM0_BASE) && 114 (entrypoint < (NS_DRAM0_BASE + NS_DRAM0_SIZE))) 115 return PSCI_E_SUCCESS; 116 return PSCI_E_INVALID_ADDRESS; 117 } 118 119 /******************************************************************************* 120 * Platform handler called when a CPU is about to enter standby. 121 ******************************************************************************/ 122 static void qemu_cpu_standby(plat_local_state_t cpu_state) 123 { 124 125 assert(cpu_state == PLAT_LOCAL_STATE_RET); 126 127 /* 128 * Enter standby state 129 * dsb is good practice before using wfi to enter low power states 130 */ 131 dsb(); 132 wfi(); 133 } 134 135 /******************************************************************************* 136 * Platform handler called when a power domain is about to be turned on. The 137 * mpidr determines the CPU to be turned on. 138 ******************************************************************************/ 139 static int qemu_pwr_domain_on(u_register_t mpidr) 140 { 141 int rc = PSCI_E_SUCCESS; 142 unsigned pos = plat_core_pos_by_mpidr(mpidr); 143 uint64_t *hold_base = (uint64_t *)PLAT_QEMU_HOLD_BASE; 144 145 hold_base[pos] = PLAT_QEMU_HOLD_STATE_GO; 146 sev(); 147 148 return rc; 149 } 150 151 /******************************************************************************* 152 * Platform handler called when a power domain is about to be turned off. The 153 * target_state encodes the power state that each level should transition to. 154 ******************************************************************************/ 155 static void qemu_pwr_domain_off(const psci_power_state_t *target_state) 156 { 157 qemu_pwr_gic_off(); 158 } 159 160 void __dead2 plat_secondary_cold_boot_setup(void); 161 162 static void __dead2 163 qemu_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state) 164 { 165 disable_mmu_el3(); 166 plat_secondary_cold_boot_setup(); 167 } 168 169 /******************************************************************************* 170 * Platform handler called when a power domain is about to be suspended. The 171 * target_state encodes the power state that each level should transition to. 172 ******************************************************************************/ 173 void qemu_pwr_domain_suspend(const psci_power_state_t *target_state) 174 { 175 assert(0); 176 } 177 178 /******************************************************************************* 179 * Platform handler called when a power domain has just been powered on after 180 * being turned off earlier. The target_state encodes the low power state that 181 * each level has woken up from. 182 ******************************************************************************/ 183 void qemu_pwr_domain_on_finish(const psci_power_state_t *target_state) 184 { 185 assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] == 186 PLAT_LOCAL_STATE_OFF); 187 188 qemu_pwr_gic_on_finish(); 189 } 190 191 /******************************************************************************* 192 * Platform handler called when a power domain has just been powered on after 193 * having been suspended earlier. The target_state encodes the low power state 194 * that each level has woken up from. 195 ******************************************************************************/ 196 void qemu_pwr_domain_suspend_finish(const psci_power_state_t *target_state) 197 { 198 assert(0); 199 } 200 201 /******************************************************************************* 202 * Platform handlers to shutdown/reboot the system 203 ******************************************************************************/ 204 static void __dead2 qemu_system_off(void) 205 { 206 semihosting_exit(ADP_STOPPED_APPLICATION_EXIT, 0); 207 ERROR("QEMU System Off: semihosting call unexpectedly returned.\n"); 208 panic(); 209 } 210 211 static void __dead2 qemu_system_reset(void) 212 { 213 ERROR("QEMU System Reset: operation not handled.\n"); 214 panic(); 215 } 216 217 static const plat_psci_ops_t plat_qemu_psci_pm_ops = { 218 .cpu_standby = qemu_cpu_standby, 219 .pwr_domain_on = qemu_pwr_domain_on, 220 .pwr_domain_off = qemu_pwr_domain_off, 221 .pwr_domain_pwr_down_wfi = qemu_pwr_domain_pwr_down_wfi, 222 .pwr_domain_suspend = qemu_pwr_domain_suspend, 223 .pwr_domain_on_finish = qemu_pwr_domain_on_finish, 224 .pwr_domain_suspend_finish = qemu_pwr_domain_suspend_finish, 225 .system_off = qemu_system_off, 226 .system_reset = qemu_system_reset, 227 .validate_power_state = qemu_validate_power_state, 228 .validate_ns_entrypoint = qemu_validate_ns_entrypoint 229 }; 230 231 int plat_setup_psci_ops(uintptr_t sec_entrypoint, 232 const plat_psci_ops_t **psci_ops) 233 { 234 uintptr_t *mailbox = (void *) PLAT_QEMU_TRUSTED_MAILBOX_BASE; 235 236 *mailbox = sec_entrypoint; 237 secure_entrypoint = (unsigned long) sec_entrypoint; 238 *psci_ops = &plat_qemu_psci_pm_ops; 239 240 return 0; 241 } 242