1 /* 2 * Copyright (c) 2015, 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 /* Standard ARM platforms are expected to export plat_arm_psci_pm_ops */ 42 extern const plat_psci_ops_t plat_arm_psci_pm_ops; 43 44 #if ARM_RECOM_STATE_ID_ENC 45 extern unsigned int arm_pm_idle_states[]; 46 #endif /* __ARM_RECOM_STATE_ID_ENC__ */ 47 48 #if !ARM_RECOM_STATE_ID_ENC 49 /******************************************************************************* 50 * ARM standard platform handler called to check the validity of the power state 51 * parameter. 52 ******************************************************************************/ 53 int arm_validate_power_state(unsigned int power_state, 54 psci_power_state_t *req_state) 55 { 56 int pstate = psci_get_pstate_type(power_state); 57 int pwr_lvl = psci_get_pstate_pwrlvl(power_state); 58 int i; 59 60 assert(req_state); 61 62 if (pwr_lvl > PLAT_MAX_PWR_LVL) 63 return PSCI_E_INVALID_PARAMS; 64 65 /* Sanity check the requested state */ 66 if (pstate == PSTATE_TYPE_STANDBY) { 67 /* 68 * It's possible to enter standby only on power level 0 69 * Ignore any other power level. 70 */ 71 if (pwr_lvl != ARM_PWR_LVL0) 72 return PSCI_E_INVALID_PARAMS; 73 74 req_state->pwr_domain_state[ARM_PWR_LVL0] = 75 ARM_LOCAL_STATE_RET; 76 } else { 77 for (i = ARM_PWR_LVL0; i <= pwr_lvl; i++) 78 req_state->pwr_domain_state[i] = 79 ARM_LOCAL_STATE_OFF; 80 } 81 82 /* 83 * We expect the 'state id' to be zero. 84 */ 85 if (psci_get_pstate_id(power_state)) 86 return PSCI_E_INVALID_PARAMS; 87 88 return PSCI_E_SUCCESS; 89 } 90 91 #else 92 /******************************************************************************* 93 * ARM standard platform handler called to check the validity of the power 94 * state parameter. The power state parameter has to be a composite power 95 * state. 96 ******************************************************************************/ 97 int arm_validate_power_state(unsigned int power_state, 98 psci_power_state_t *req_state) 99 { 100 unsigned int state_id; 101 int i; 102 103 assert(req_state); 104 105 /* 106 * Currently we are using a linear search for finding the matching 107 * entry in the idle power state array. This can be made a binary 108 * search if the number of entries justify the additional complexity. 109 */ 110 for (i = 0; !!arm_pm_idle_states[i]; i++) { 111 if (power_state == arm_pm_idle_states[i]) 112 break; 113 } 114 115 /* Return error if entry not found in the idle state array */ 116 if (!arm_pm_idle_states[i]) 117 return PSCI_E_INVALID_PARAMS; 118 119 i = 0; 120 state_id = psci_get_pstate_id(power_state); 121 122 /* Parse the State ID and populate the state info parameter */ 123 while (state_id) { 124 req_state->pwr_domain_state[i++] = state_id & 125 ARM_LOCAL_PSTATE_MASK; 126 state_id >>= ARM_LOCAL_PSTATE_WIDTH; 127 } 128 129 return PSCI_E_SUCCESS; 130 } 131 #endif /* __ARM_RECOM_STATE_ID_ENC__ */ 132 133 /******************************************************************************* 134 * ARM standard platform handler called to check the validity of the non secure 135 * entrypoint. 136 ******************************************************************************/ 137 int arm_validate_ns_entrypoint(uintptr_t entrypoint) 138 { 139 /* 140 * Check if the non secure entrypoint lies within the non 141 * secure DRAM. 142 */ 143 if ((entrypoint >= ARM_NS_DRAM1_BASE) && (entrypoint < 144 (ARM_NS_DRAM1_BASE + ARM_NS_DRAM1_SIZE))) 145 return PSCI_E_SUCCESS; 146 if ((entrypoint >= ARM_DRAM2_BASE) && (entrypoint < 147 (ARM_DRAM2_BASE + ARM_DRAM2_SIZE))) 148 return PSCI_E_SUCCESS; 149 150 return PSCI_E_INVALID_ADDRESS; 151 } 152 153 /****************************************************************************** 154 * Helper function to resume the platform from system suspend. Reinitialize 155 * the system components which are not in the Always ON power domain. 156 * TODO: Unify the platform setup when waking up from cold boot and system 157 * resume in arm_bl31_platform_setup(). 158 *****************************************************************************/ 159 void arm_system_pwr_domain_resume(void) 160 { 161 console_init(PLAT_ARM_BL31_RUN_UART_BASE, PLAT_ARM_BL31_RUN_UART_CLK_IN_HZ, 162 ARM_CONSOLE_BAUDRATE); 163 164 /* Assert system power domain is available on the platform */ 165 assert(PLAT_MAX_PWR_LVL >= ARM_PWR_LVL2); 166 167 /* 168 * TODO: On GICv3 systems, figure out whether the core that wakes up 169 * first from system suspend need to initialize the re-distributor 170 * interface of all the other suspended cores. 171 */ 172 plat_arm_gic_init(); 173 plat_arm_security_setup(); 174 arm_configure_sys_timer(); 175 } 176 177 /******************************************************************************* 178 * Private function to program the mailbox for a cpu before it is released 179 * from reset. This function assumes that the Trusted mail box base is within 180 * the ARM_SHARED_RAM region 181 ******************************************************************************/ 182 void arm_program_trusted_mailbox(uintptr_t address) 183 { 184 uintptr_t *mailbox = (void *) PLAT_ARM_TRUSTED_MAILBOX_BASE; 185 186 *mailbox = address; 187 188 /* 189 * Ensure that the PLAT_ARM_TRUSTED_MAILBOX_BASE is within 190 * ARM_SHARED_RAM region. 191 */ 192 assert((PLAT_ARM_TRUSTED_MAILBOX_BASE >= ARM_SHARED_RAM_BASE) && 193 ((PLAT_ARM_TRUSTED_MAILBOX_BASE + sizeof(*mailbox)) <= \ 194 (ARM_SHARED_RAM_BASE + ARM_SHARED_RAM_SIZE))); 195 196 /* Flush data cache if the mail box shared RAM is cached */ 197 #if PLAT_ARM_SHARED_RAM_CACHED 198 flush_dcache_range((uintptr_t) mailbox, sizeof(*mailbox)); 199 #endif 200 } 201 202 /******************************************************************************* 203 * The ARM Standard platform definition of platform porting API 204 * `plat_setup_psci_ops`. 205 ******************************************************************************/ 206 int plat_setup_psci_ops(uintptr_t sec_entrypoint, 207 const plat_psci_ops_t **psci_ops) 208 { 209 *psci_ops = &plat_arm_psci_pm_ops; 210 211 /* Setup mailbox with entry point. */ 212 arm_program_trusted_mailbox(sec_entrypoint); 213 return 0; 214 } 215