1 /* 2 * Copyright (c) 2015-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 <arm_def.h> 9 #include <arm_gic.h> 10 #include <assert.h> 11 #include <errno.h> 12 #include <plat_arm.h> 13 #include <platform.h> 14 #include <platform_def.h> 15 #include <psci.h> 16 17 /* Allow ARM Standard platforms to override these functions */ 18 #pragma weak plat_arm_psci_override_pm_ops 19 #pragma weak plat_arm_program_trusted_mailbox 20 21 #if ARM_RECOM_STATE_ID_ENC 22 extern unsigned int arm_pm_idle_states[]; 23 #endif /* __ARM_RECOM_STATE_ID_ENC__ */ 24 25 #if !ARM_RECOM_STATE_ID_ENC 26 /******************************************************************************* 27 * ARM standard platform handler called to check the validity of the power state 28 * parameter. 29 ******************************************************************************/ 30 int arm_validate_power_state(unsigned int power_state, 31 psci_power_state_t *req_state) 32 { 33 int pstate = psci_get_pstate_type(power_state); 34 int pwr_lvl = psci_get_pstate_pwrlvl(power_state); 35 int i; 36 37 assert(req_state); 38 39 if (pwr_lvl > PLAT_MAX_PWR_LVL) 40 return PSCI_E_INVALID_PARAMS; 41 42 /* Sanity check the requested state */ 43 if (pstate == PSTATE_TYPE_STANDBY) { 44 /* 45 * It's possible to enter standby only on power level 0 46 * Ignore any other power level. 47 */ 48 if (pwr_lvl != ARM_PWR_LVL0) 49 return PSCI_E_INVALID_PARAMS; 50 51 req_state->pwr_domain_state[ARM_PWR_LVL0] = 52 ARM_LOCAL_STATE_RET; 53 } else { 54 for (i = ARM_PWR_LVL0; i <= pwr_lvl; i++) 55 req_state->pwr_domain_state[i] = 56 ARM_LOCAL_STATE_OFF; 57 } 58 59 /* 60 * We expect the 'state id' to be zero. 61 */ 62 if (psci_get_pstate_id(power_state)) 63 return PSCI_E_INVALID_PARAMS; 64 65 return PSCI_E_SUCCESS; 66 } 67 68 #else 69 /******************************************************************************* 70 * ARM standard platform handler called to check the validity of the power 71 * state parameter. The power state parameter has to be a composite power 72 * state. 73 ******************************************************************************/ 74 int arm_validate_power_state(unsigned int power_state, 75 psci_power_state_t *req_state) 76 { 77 unsigned int state_id; 78 int i; 79 80 assert(req_state); 81 82 /* 83 * Currently we are using a linear search for finding the matching 84 * entry in the idle power state array. This can be made a binary 85 * search if the number of entries justify the additional complexity. 86 */ 87 for (i = 0; !!arm_pm_idle_states[i]; i++) { 88 if (power_state == arm_pm_idle_states[i]) 89 break; 90 } 91 92 /* Return error if entry not found in the idle state array */ 93 if (!arm_pm_idle_states[i]) 94 return PSCI_E_INVALID_PARAMS; 95 96 i = 0; 97 state_id = psci_get_pstate_id(power_state); 98 99 /* Parse the State ID and populate the state info parameter */ 100 while (state_id) { 101 req_state->pwr_domain_state[i++] = state_id & 102 ARM_LOCAL_PSTATE_MASK; 103 state_id >>= ARM_LOCAL_PSTATE_WIDTH; 104 } 105 106 return PSCI_E_SUCCESS; 107 } 108 #endif /* __ARM_RECOM_STATE_ID_ENC__ */ 109 110 /******************************************************************************* 111 * ARM standard platform handler called to check the validity of the non secure 112 * entrypoint. Returns 0 if the entrypoint is valid, or -1 otherwise. 113 ******************************************************************************/ 114 int arm_validate_ns_entrypoint(uintptr_t entrypoint) 115 { 116 /* 117 * Check if the non secure entrypoint lies within the non 118 * secure DRAM. 119 */ 120 if ((entrypoint >= ARM_NS_DRAM1_BASE) && (entrypoint < 121 (ARM_NS_DRAM1_BASE + ARM_NS_DRAM1_SIZE))) { 122 return 0; 123 } 124 #ifndef AARCH32 125 if ((entrypoint >= ARM_DRAM2_BASE) && (entrypoint < 126 (ARM_DRAM2_BASE + ARM_DRAM2_SIZE))) { 127 return 0; 128 } 129 #endif 130 131 return -1; 132 } 133 134 int arm_validate_psci_entrypoint(uintptr_t entrypoint) 135 { 136 return arm_validate_ns_entrypoint(entrypoint) == 0 ? PSCI_E_SUCCESS : 137 PSCI_E_INVALID_ADDRESS; 138 } 139 140 /****************************************************************************** 141 * Default definition on ARM standard platforms to override the plat_psci_ops. 142 *****************************************************************************/ 143 const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops) 144 { 145 return ops; 146 } 147 148 /****************************************************************************** 149 * Helper function to save the platform state before a system suspend. Save the 150 * state of the system components which are not in the Always ON power domain. 151 *****************************************************************************/ 152 void arm_system_pwr_domain_save(void) 153 { 154 /* Assert system power domain is available on the platform */ 155 assert(PLAT_MAX_PWR_LVL >= ARM_PWR_LVL2); 156 157 plat_arm_gic_save(); 158 159 /* 160 * Unregister console now so that it is not registered for a second 161 * time during resume. 162 */ 163 arm_console_runtime_end(); 164 165 /* 166 * All the other peripheral which are configured by ARM TF are 167 * re-initialized on resume from system suspend. Hence we 168 * don't save their state here. 169 */ 170 } 171 172 /****************************************************************************** 173 * Helper function to resume the platform from system suspend. Reinitialize 174 * the system components which are not in the Always ON power domain. 175 * TODO: Unify the platform setup when waking up from cold boot and system 176 * resume in arm_bl31_platform_setup(). 177 *****************************************************************************/ 178 void arm_system_pwr_domain_resume(void) 179 { 180 /* Initialize the console */ 181 arm_console_runtime_init(); 182 183 /* Assert system power domain is available on the platform */ 184 assert(PLAT_MAX_PWR_LVL >= ARM_PWR_LVL2); 185 186 plat_arm_gic_resume(); 187 188 plat_arm_security_setup(); 189 arm_configure_sys_timer(); 190 } 191 192 /******************************************************************************* 193 * ARM platform function to program the mailbox for a cpu before it is released 194 * from reset. This function assumes that the Trusted mail box base is within 195 * the ARM_SHARED_RAM region 196 ******************************************************************************/ 197 void plat_arm_program_trusted_mailbox(uintptr_t address) 198 { 199 uintptr_t *mailbox = (void *) PLAT_ARM_TRUSTED_MAILBOX_BASE; 200 201 *mailbox = address; 202 203 /* 204 * Ensure that the PLAT_ARM_TRUSTED_MAILBOX_BASE is within 205 * ARM_SHARED_RAM region. 206 */ 207 assert((PLAT_ARM_TRUSTED_MAILBOX_BASE >= ARM_SHARED_RAM_BASE) && 208 ((PLAT_ARM_TRUSTED_MAILBOX_BASE + sizeof(*mailbox)) <= \ 209 (ARM_SHARED_RAM_BASE + ARM_SHARED_RAM_SIZE))); 210 } 211 212 /******************************************************************************* 213 * The ARM Standard platform definition of platform porting API 214 * `plat_setup_psci_ops`. 215 ******************************************************************************/ 216 int plat_setup_psci_ops(uintptr_t sec_entrypoint, 217 const plat_psci_ops_t **psci_ops) 218 { 219 *psci_ops = plat_arm_psci_override_pm_ops(&plat_arm_psci_pm_ops); 220 221 /* Setup mailbox with entry point. */ 222 plat_arm_program_trusted_mailbox(sec_entrypoint); 223 return 0; 224 } 225