1 /* 2 * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * Redistributions of source code must retain the above copyright notice, this 8 * list of conditions and the following disclaimer. 9 * 10 * Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * Neither the name of ARM nor the names of its contributors may be used 15 * to endorse or promote products derived from this software without specific 16 * prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <arch_helpers.h> 32 #include <arm_def.h> 33 #include <arm_gic.h> 34 #include <assert.h> 35 #include <console.h> 36 #include <errno.h> 37 #include <plat_arm.h> 38 #include <platform_def.h> 39 #include <psci.h> 40 41 /* Allow ARM Standard platforms to override this function */ 42 #pragma weak plat_arm_psci_override_pm_ops 43 44 /* Standard ARM platforms are expected to export plat_arm_psci_pm_ops */ 45 extern plat_psci_ops_t plat_arm_psci_pm_ops; 46 47 #if ARM_RECOM_STATE_ID_ENC 48 extern unsigned int arm_pm_idle_states[]; 49 #endif /* __ARM_RECOM_STATE_ID_ENC__ */ 50 51 #if !ARM_RECOM_STATE_ID_ENC 52 /******************************************************************************* 53 * ARM standard platform handler called to check the validity of the power state 54 * parameter. 55 ******************************************************************************/ 56 int arm_validate_power_state(unsigned int power_state, 57 psci_power_state_t *req_state) 58 { 59 int pstate = psci_get_pstate_type(power_state); 60 int pwr_lvl = psci_get_pstate_pwrlvl(power_state); 61 int i; 62 63 assert(req_state); 64 65 if (pwr_lvl > PLAT_MAX_PWR_LVL) 66 return PSCI_E_INVALID_PARAMS; 67 68 /* Sanity check the requested state */ 69 if (pstate == PSTATE_TYPE_STANDBY) { 70 /* 71 * It's possible to enter standby only on power level 0 72 * Ignore any other power level. 73 */ 74 if (pwr_lvl != ARM_PWR_LVL0) 75 return PSCI_E_INVALID_PARAMS; 76 77 req_state->pwr_domain_state[ARM_PWR_LVL0] = 78 ARM_LOCAL_STATE_RET; 79 } else { 80 for (i = ARM_PWR_LVL0; i <= pwr_lvl; i++) 81 req_state->pwr_domain_state[i] = 82 ARM_LOCAL_STATE_OFF; 83 } 84 85 /* 86 * We expect the 'state id' to be zero. 87 */ 88 if (psci_get_pstate_id(power_state)) 89 return PSCI_E_INVALID_PARAMS; 90 91 return PSCI_E_SUCCESS; 92 } 93 94 #else 95 /******************************************************************************* 96 * ARM standard platform handler called to check the validity of the power 97 * state parameter. The power state parameter has to be a composite power 98 * state. 99 ******************************************************************************/ 100 int arm_validate_power_state(unsigned int power_state, 101 psci_power_state_t *req_state) 102 { 103 unsigned int state_id; 104 int i; 105 106 assert(req_state); 107 108 /* 109 * Currently we are using a linear search for finding the matching 110 * entry in the idle power state array. This can be made a binary 111 * search if the number of entries justify the additional complexity. 112 */ 113 for (i = 0; !!arm_pm_idle_states[i]; i++) { 114 if (power_state == arm_pm_idle_states[i]) 115 break; 116 } 117 118 /* Return error if entry not found in the idle state array */ 119 if (!arm_pm_idle_states[i]) 120 return PSCI_E_INVALID_PARAMS; 121 122 i = 0; 123 state_id = psci_get_pstate_id(power_state); 124 125 /* Parse the State ID and populate the state info parameter */ 126 while (state_id) { 127 req_state->pwr_domain_state[i++] = state_id & 128 ARM_LOCAL_PSTATE_MASK; 129 state_id >>= ARM_LOCAL_PSTATE_WIDTH; 130 } 131 132 return PSCI_E_SUCCESS; 133 } 134 #endif /* __ARM_RECOM_STATE_ID_ENC__ */ 135 136 /******************************************************************************* 137 * ARM standard platform handler called to check the validity of the non secure 138 * entrypoint. 139 ******************************************************************************/ 140 int arm_validate_ns_entrypoint(uintptr_t entrypoint) 141 { 142 /* 143 * Check if the non secure entrypoint lies within the non 144 * secure DRAM. 145 */ 146 if ((entrypoint >= ARM_NS_DRAM1_BASE) && (entrypoint < 147 (ARM_NS_DRAM1_BASE + ARM_NS_DRAM1_SIZE))) 148 return PSCI_E_SUCCESS; 149 if ((entrypoint >= ARM_DRAM2_BASE) && (entrypoint < 150 (ARM_DRAM2_BASE + ARM_DRAM2_SIZE))) 151 return PSCI_E_SUCCESS; 152 153 return PSCI_E_INVALID_ADDRESS; 154 } 155 156 /****************************************************************************** 157 * Default definition on ARM standard platforms to override the plat_psci_ops. 158 *****************************************************************************/ 159 const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops) 160 { 161 return ops; 162 } 163 164 /****************************************************************************** 165 * Helper function to resume the platform from system suspend. Reinitialize 166 * the system components which are not in the Always ON power domain. 167 * TODO: Unify the platform setup when waking up from cold boot and system 168 * resume in arm_bl31_platform_setup(). 169 *****************************************************************************/ 170 void arm_system_pwr_domain_resume(void) 171 { 172 console_init(PLAT_ARM_BL31_RUN_UART_BASE, PLAT_ARM_BL31_RUN_UART_CLK_IN_HZ, 173 ARM_CONSOLE_BAUDRATE); 174 175 /* Assert system power domain is available on the platform */ 176 assert(PLAT_MAX_PWR_LVL >= ARM_PWR_LVL2); 177 178 /* 179 * TODO: On GICv3 systems, figure out whether the core that wakes up 180 * first from system suspend need to initialize the re-distributor 181 * interface of all the other suspended cores. 182 */ 183 plat_arm_gic_init(); 184 plat_arm_security_setup(); 185 arm_configure_sys_timer(); 186 } 187 188 /******************************************************************************* 189 * Private function to program the mailbox for a cpu before it is released 190 * from reset. This function assumes that the Trusted mail box base is within 191 * the ARM_SHARED_RAM region 192 ******************************************************************************/ 193 void arm_program_trusted_mailbox(uintptr_t address) 194 { 195 uintptr_t *mailbox = (void *) PLAT_ARM_TRUSTED_MAILBOX_BASE; 196 197 *mailbox = address; 198 199 /* 200 * Ensure that the PLAT_ARM_TRUSTED_MAILBOX_BASE is within 201 * ARM_SHARED_RAM region. 202 */ 203 assert((PLAT_ARM_TRUSTED_MAILBOX_BASE >= ARM_SHARED_RAM_BASE) && 204 ((PLAT_ARM_TRUSTED_MAILBOX_BASE + sizeof(*mailbox)) <= \ 205 (ARM_SHARED_RAM_BASE + ARM_SHARED_RAM_SIZE))); 206 } 207 208 /******************************************************************************* 209 * The ARM Standard platform definition of platform porting API 210 * `plat_setup_psci_ops`. 211 ******************************************************************************/ 212 int plat_setup_psci_ops(uintptr_t sec_entrypoint, 213 const plat_psci_ops_t **psci_ops) 214 { 215 *psci_ops = plat_arm_psci_override_pm_ops(&plat_arm_psci_pm_ops); 216 217 /* Setup mailbox with entry point. */ 218 arm_program_trusted_mailbox(sec_entrypoint); 219 return 0; 220 } 221