1b4315306SDan Handley /* 2b4315306SDan Handley * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. 3b4315306SDan Handley * 4b4315306SDan Handley * Redistribution and use in source and binary forms, with or without 5b4315306SDan Handley * modification, are permitted provided that the following conditions are met: 6b4315306SDan Handley * 7b4315306SDan Handley * Redistributions of source code must retain the above copyright notice, this 8b4315306SDan Handley * list of conditions and the following disclaimer. 9b4315306SDan Handley * 10b4315306SDan Handley * Redistributions in binary form must reproduce the above copyright notice, 11b4315306SDan Handley * this list of conditions and the following disclaimer in the documentation 12b4315306SDan Handley * and/or other materials provided with the distribution. 13b4315306SDan Handley * 14b4315306SDan Handley * Neither the name of ARM nor the names of its contributors may be used 15b4315306SDan Handley * to endorse or promote products derived from this software without specific 16b4315306SDan Handley * prior written permission. 17b4315306SDan Handley * 18b4315306SDan Handley * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19b4315306SDan Handley * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20b4315306SDan Handley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21b4315306SDan Handley * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22b4315306SDan Handley * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23b4315306SDan Handley * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24b4315306SDan Handley * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25b4315306SDan Handley * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26b4315306SDan Handley * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27b4315306SDan Handley * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28b4315306SDan Handley * POSSIBILITY OF SUCH DAMAGE. 29b4315306SDan Handley */ 30b4315306SDan Handley 31b4315306SDan Handley #include <arch_helpers.h> 32f9e858b1SSoby Mathew #include <arm_def.h> 33c1bb8a05SSoby Mathew #include <arm_gic.h> 34b4315306SDan Handley #include <assert.h> 35c1bb8a05SSoby Mathew #include <console.h> 36b4315306SDan Handley #include <errno.h> 372204afdeSSoby Mathew #include <plat_arm.h> 38785fb92bSSoby Mathew #include <platform_def.h> 39b4315306SDan Handley #include <psci.h> 40b4315306SDan Handley 41785fb92bSSoby Mathew /* Standard ARM platforms are expected to export plat_arm_psci_pm_ops */ 42785fb92bSSoby Mathew extern const plat_psci_ops_t plat_arm_psci_pm_ops; 43785fb92bSSoby Mathew 442204afdeSSoby Mathew #if ARM_RECOM_STATE_ID_ENC 452204afdeSSoby Mathew extern unsigned int arm_pm_idle_states[]; 462204afdeSSoby Mathew #endif /* __ARM_RECOM_STATE_ID_ENC__ */ 472204afdeSSoby Mathew 482204afdeSSoby Mathew #if !ARM_RECOM_STATE_ID_ENC 49b4315306SDan Handley /******************************************************************************* 50b4315306SDan Handley * ARM standard platform handler called to check the validity of the power state 51b4315306SDan Handley * parameter. 52b4315306SDan Handley ******************************************************************************/ 5338dce70fSSoby Mathew int arm_validate_power_state(unsigned int power_state, 5438dce70fSSoby Mathew psci_power_state_t *req_state) 55b4315306SDan Handley { 5638dce70fSSoby Mathew int pstate = psci_get_pstate_type(power_state); 5738dce70fSSoby Mathew int pwr_lvl = psci_get_pstate_pwrlvl(power_state); 5838dce70fSSoby Mathew int i; 5938dce70fSSoby Mathew 6038dce70fSSoby Mathew assert(req_state); 6138dce70fSSoby Mathew 6238dce70fSSoby Mathew if (pwr_lvl > PLAT_MAX_PWR_LVL) 63b4315306SDan Handley return PSCI_E_INVALID_PARAMS; 6438dce70fSSoby Mathew 6538dce70fSSoby Mathew /* Sanity check the requested state */ 6638dce70fSSoby Mathew if (pstate == PSTATE_TYPE_STANDBY) { 6738dce70fSSoby Mathew /* 6838dce70fSSoby Mathew * It's possible to enter standby only on power level 0 6938dce70fSSoby Mathew * Ignore any other power level. 7038dce70fSSoby Mathew */ 7138dce70fSSoby Mathew if (pwr_lvl != ARM_PWR_LVL0) 7238dce70fSSoby Mathew return PSCI_E_INVALID_PARAMS; 7338dce70fSSoby Mathew 7438dce70fSSoby Mathew req_state->pwr_domain_state[ARM_PWR_LVL0] = 7538dce70fSSoby Mathew ARM_LOCAL_STATE_RET; 7638dce70fSSoby Mathew } else { 7738dce70fSSoby Mathew for (i = ARM_PWR_LVL0; i <= pwr_lvl; i++) 7838dce70fSSoby Mathew req_state->pwr_domain_state[i] = 7938dce70fSSoby Mathew ARM_LOCAL_STATE_OFF; 80b4315306SDan Handley } 81b4315306SDan Handley 82b4315306SDan Handley /* 83b4315306SDan Handley * We expect the 'state id' to be zero. 84b4315306SDan Handley */ 85b4315306SDan Handley if (psci_get_pstate_id(power_state)) 86b4315306SDan Handley return PSCI_E_INVALID_PARAMS; 87b4315306SDan Handley 88b4315306SDan Handley return PSCI_E_SUCCESS; 89b4315306SDan Handley } 902204afdeSSoby Mathew 912204afdeSSoby Mathew #else 922204afdeSSoby Mathew /******************************************************************************* 932204afdeSSoby Mathew * ARM standard platform handler called to check the validity of the power 942204afdeSSoby Mathew * state parameter. The power state parameter has to be a composite power 952204afdeSSoby Mathew * state. 962204afdeSSoby Mathew ******************************************************************************/ 972204afdeSSoby Mathew int arm_validate_power_state(unsigned int power_state, 982204afdeSSoby Mathew psci_power_state_t *req_state) 992204afdeSSoby Mathew { 1002204afdeSSoby Mathew unsigned int state_id; 1012204afdeSSoby Mathew int i; 1022204afdeSSoby Mathew 1032204afdeSSoby Mathew assert(req_state); 1042204afdeSSoby Mathew 1052204afdeSSoby Mathew /* 1062204afdeSSoby Mathew * Currently we are using a linear search for finding the matching 1072204afdeSSoby Mathew * entry in the idle power state array. This can be made a binary 1082204afdeSSoby Mathew * search if the number of entries justify the additional complexity. 1092204afdeSSoby Mathew */ 1102204afdeSSoby Mathew for (i = 0; !!arm_pm_idle_states[i]; i++) { 1112204afdeSSoby Mathew if (power_state == arm_pm_idle_states[i]) 1122204afdeSSoby Mathew break; 1132204afdeSSoby Mathew } 1142204afdeSSoby Mathew 1152204afdeSSoby Mathew /* Return error if entry not found in the idle state array */ 1162204afdeSSoby Mathew if (!arm_pm_idle_states[i]) 1172204afdeSSoby Mathew return PSCI_E_INVALID_PARAMS; 1182204afdeSSoby Mathew 1192204afdeSSoby Mathew i = 0; 1202204afdeSSoby Mathew state_id = psci_get_pstate_id(power_state); 1212204afdeSSoby Mathew 1222204afdeSSoby Mathew /* Parse the State ID and populate the state info parameter */ 1232204afdeSSoby Mathew while (state_id) { 1242204afdeSSoby Mathew req_state->pwr_domain_state[i++] = state_id & 1252204afdeSSoby Mathew ARM_LOCAL_PSTATE_MASK; 1262204afdeSSoby Mathew state_id >>= ARM_LOCAL_PSTATE_WIDTH; 1272204afdeSSoby Mathew } 1282204afdeSSoby Mathew 1292204afdeSSoby Mathew return PSCI_E_SUCCESS; 1302204afdeSSoby Mathew } 1312204afdeSSoby Mathew #endif /* __ARM_RECOM_STATE_ID_ENC__ */ 132f9e858b1SSoby Mathew 133f9e858b1SSoby Mathew /******************************************************************************* 134f9e858b1SSoby Mathew * ARM standard platform handler called to check the validity of the non secure 135f9e858b1SSoby Mathew * entrypoint. 136f9e858b1SSoby Mathew ******************************************************************************/ 137f9e858b1SSoby Mathew int arm_validate_ns_entrypoint(uintptr_t entrypoint) 138f9e858b1SSoby Mathew { 139f9e858b1SSoby Mathew /* 140f9e858b1SSoby Mathew * Check if the non secure entrypoint lies within the non 141f9e858b1SSoby Mathew * secure DRAM. 142f9e858b1SSoby Mathew */ 143f9e858b1SSoby Mathew if ((entrypoint >= ARM_NS_DRAM1_BASE) && (entrypoint < 144f9e858b1SSoby Mathew (ARM_NS_DRAM1_BASE + ARM_NS_DRAM1_SIZE))) 145f9e858b1SSoby Mathew return PSCI_E_SUCCESS; 146f9e858b1SSoby Mathew if ((entrypoint >= ARM_DRAM2_BASE) && (entrypoint < 147f9e858b1SSoby Mathew (ARM_DRAM2_BASE + ARM_DRAM2_SIZE))) 148f9e858b1SSoby Mathew return PSCI_E_SUCCESS; 149f9e858b1SSoby Mathew 150f9e858b1SSoby Mathew return PSCI_E_INVALID_ADDRESS; 151f9e858b1SSoby Mathew } 152785fb92bSSoby Mathew 153c1bb8a05SSoby Mathew /****************************************************************************** 154c1bb8a05SSoby Mathew * Helper function to resume the platform from system suspend. Reinitialize 155c1bb8a05SSoby Mathew * the system components which are not in the Always ON power domain. 156c1bb8a05SSoby Mathew * TODO: Unify the platform setup when waking up from cold boot and system 157c1bb8a05SSoby Mathew * resume in arm_bl31_platform_setup(). 158c1bb8a05SSoby Mathew *****************************************************************************/ 159c1bb8a05SSoby Mathew void arm_system_pwr_domain_resume(void) 160c1bb8a05SSoby Mathew { 161*080225daSSoby Mathew console_init(PLAT_ARM_BL31_RUN_UART_BASE, PLAT_ARM_BL31_RUN_UART_CLK_IN_HZ, 162c1bb8a05SSoby Mathew ARM_CONSOLE_BAUDRATE); 163c1bb8a05SSoby Mathew 164c1bb8a05SSoby Mathew /* Assert system power domain is available on the platform */ 165c1bb8a05SSoby Mathew assert(PLAT_MAX_PWR_LVL >= ARM_PWR_LVL2); 166c1bb8a05SSoby Mathew 167c1bb8a05SSoby Mathew arm_gic_setup(); 168c1bb8a05SSoby Mathew plat_arm_security_setup(); 169c1bb8a05SSoby Mathew 170c1bb8a05SSoby Mathew arm_configure_sys_timer(); 171c1bb8a05SSoby Mathew } 172c1bb8a05SSoby Mathew 173785fb92bSSoby Mathew /******************************************************************************* 174785fb92bSSoby Mathew * Private function to program the mailbox for a cpu before it is released 175785fb92bSSoby Mathew * from reset. This function assumes that the Trusted mail box base is within 176785fb92bSSoby Mathew * the ARM_SHARED_RAM region 177785fb92bSSoby Mathew ******************************************************************************/ 1784c117f6cSSandrine Bailleux void arm_program_trusted_mailbox(uintptr_t address) 179785fb92bSSoby Mathew { 180785fb92bSSoby Mathew uintptr_t *mailbox = (void *) PLAT_ARM_TRUSTED_MAILBOX_BASE; 181785fb92bSSoby Mathew 182785fb92bSSoby Mathew *mailbox = address; 183785fb92bSSoby Mathew 184785fb92bSSoby Mathew /* 185785fb92bSSoby Mathew * Ensure that the PLAT_ARM_TRUSTED_MAILBOX_BASE is within 186785fb92bSSoby Mathew * ARM_SHARED_RAM region. 187785fb92bSSoby Mathew */ 188785fb92bSSoby Mathew assert((PLAT_ARM_TRUSTED_MAILBOX_BASE >= ARM_SHARED_RAM_BASE) && 189785fb92bSSoby Mathew ((PLAT_ARM_TRUSTED_MAILBOX_BASE + sizeof(*mailbox)) <= \ 190785fb92bSSoby Mathew (ARM_SHARED_RAM_BASE + ARM_SHARED_RAM_SIZE))); 191785fb92bSSoby Mathew 192785fb92bSSoby Mathew /* Flush data cache if the mail box shared RAM is cached */ 193785fb92bSSoby Mathew #if PLAT_ARM_SHARED_RAM_CACHED 194785fb92bSSoby Mathew flush_dcache_range((uintptr_t) mailbox, sizeof(*mailbox)); 195785fb92bSSoby Mathew #endif 196785fb92bSSoby Mathew } 197785fb92bSSoby Mathew 198785fb92bSSoby Mathew /******************************************************************************* 199785fb92bSSoby Mathew * The ARM Standard platform definition of platform porting API 200785fb92bSSoby Mathew * `plat_setup_psci_ops`. 201785fb92bSSoby Mathew ******************************************************************************/ 202785fb92bSSoby Mathew int plat_setup_psci_ops(uintptr_t sec_entrypoint, 203785fb92bSSoby Mathew const plat_psci_ops_t **psci_ops) 204785fb92bSSoby Mathew { 205785fb92bSSoby Mathew *psci_ops = &plat_arm_psci_pm_ops; 206785fb92bSSoby Mathew 207785fb92bSSoby Mathew /* Setup mailbox with entry point. */ 208785fb92bSSoby Mathew arm_program_trusted_mailbox(sec_entrypoint); 209785fb92bSSoby Mathew return 0; 210785fb92bSSoby Mathew } 211