1b4315306SDan Handley /* 2*5486a965SSoby Mathew * Copyright (c) 2015-2016, 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 41*5486a965SSoby Mathew /* Allow ARM Standard platforms to override this function */ 42*5486a965SSoby Mathew #pragma weak plat_arm_psci_override_pm_ops 43*5486a965SSoby Mathew 44785fb92bSSoby Mathew /* Standard ARM platforms are expected to export plat_arm_psci_pm_ops */ 45*5486a965SSoby Mathew extern plat_psci_ops_t plat_arm_psci_pm_ops; 46785fb92bSSoby Mathew 472204afdeSSoby Mathew #if ARM_RECOM_STATE_ID_ENC 482204afdeSSoby Mathew extern unsigned int arm_pm_idle_states[]; 492204afdeSSoby Mathew #endif /* __ARM_RECOM_STATE_ID_ENC__ */ 502204afdeSSoby Mathew 512204afdeSSoby Mathew #if !ARM_RECOM_STATE_ID_ENC 52b4315306SDan Handley /******************************************************************************* 53b4315306SDan Handley * ARM standard platform handler called to check the validity of the power state 54b4315306SDan Handley * parameter. 55b4315306SDan Handley ******************************************************************************/ 5638dce70fSSoby Mathew int arm_validate_power_state(unsigned int power_state, 5738dce70fSSoby Mathew psci_power_state_t *req_state) 58b4315306SDan Handley { 5938dce70fSSoby Mathew int pstate = psci_get_pstate_type(power_state); 6038dce70fSSoby Mathew int pwr_lvl = psci_get_pstate_pwrlvl(power_state); 6138dce70fSSoby Mathew int i; 6238dce70fSSoby Mathew 6338dce70fSSoby Mathew assert(req_state); 6438dce70fSSoby Mathew 6538dce70fSSoby Mathew if (pwr_lvl > PLAT_MAX_PWR_LVL) 66b4315306SDan Handley return PSCI_E_INVALID_PARAMS; 6738dce70fSSoby Mathew 6838dce70fSSoby Mathew /* Sanity check the requested state */ 6938dce70fSSoby Mathew if (pstate == PSTATE_TYPE_STANDBY) { 7038dce70fSSoby Mathew /* 7138dce70fSSoby Mathew * It's possible to enter standby only on power level 0 7238dce70fSSoby Mathew * Ignore any other power level. 7338dce70fSSoby Mathew */ 7438dce70fSSoby Mathew if (pwr_lvl != ARM_PWR_LVL0) 7538dce70fSSoby Mathew return PSCI_E_INVALID_PARAMS; 7638dce70fSSoby Mathew 7738dce70fSSoby Mathew req_state->pwr_domain_state[ARM_PWR_LVL0] = 7838dce70fSSoby Mathew ARM_LOCAL_STATE_RET; 7938dce70fSSoby Mathew } else { 8038dce70fSSoby Mathew for (i = ARM_PWR_LVL0; i <= pwr_lvl; i++) 8138dce70fSSoby Mathew req_state->pwr_domain_state[i] = 8238dce70fSSoby Mathew ARM_LOCAL_STATE_OFF; 83b4315306SDan Handley } 84b4315306SDan Handley 85b4315306SDan Handley /* 86b4315306SDan Handley * We expect the 'state id' to be zero. 87b4315306SDan Handley */ 88b4315306SDan Handley if (psci_get_pstate_id(power_state)) 89b4315306SDan Handley return PSCI_E_INVALID_PARAMS; 90b4315306SDan Handley 91b4315306SDan Handley return PSCI_E_SUCCESS; 92b4315306SDan Handley } 932204afdeSSoby Mathew 942204afdeSSoby Mathew #else 952204afdeSSoby Mathew /******************************************************************************* 962204afdeSSoby Mathew * ARM standard platform handler called to check the validity of the power 972204afdeSSoby Mathew * state parameter. The power state parameter has to be a composite power 982204afdeSSoby Mathew * state. 992204afdeSSoby Mathew ******************************************************************************/ 1002204afdeSSoby Mathew int arm_validate_power_state(unsigned int power_state, 1012204afdeSSoby Mathew psci_power_state_t *req_state) 1022204afdeSSoby Mathew { 1032204afdeSSoby Mathew unsigned int state_id; 1042204afdeSSoby Mathew int i; 1052204afdeSSoby Mathew 1062204afdeSSoby Mathew assert(req_state); 1072204afdeSSoby Mathew 1082204afdeSSoby Mathew /* 1092204afdeSSoby Mathew * Currently we are using a linear search for finding the matching 1102204afdeSSoby Mathew * entry in the idle power state array. This can be made a binary 1112204afdeSSoby Mathew * search if the number of entries justify the additional complexity. 1122204afdeSSoby Mathew */ 1132204afdeSSoby Mathew for (i = 0; !!arm_pm_idle_states[i]; i++) { 1142204afdeSSoby Mathew if (power_state == arm_pm_idle_states[i]) 1152204afdeSSoby Mathew break; 1162204afdeSSoby Mathew } 1172204afdeSSoby Mathew 1182204afdeSSoby Mathew /* Return error if entry not found in the idle state array */ 1192204afdeSSoby Mathew if (!arm_pm_idle_states[i]) 1202204afdeSSoby Mathew return PSCI_E_INVALID_PARAMS; 1212204afdeSSoby Mathew 1222204afdeSSoby Mathew i = 0; 1232204afdeSSoby Mathew state_id = psci_get_pstate_id(power_state); 1242204afdeSSoby Mathew 1252204afdeSSoby Mathew /* Parse the State ID and populate the state info parameter */ 1262204afdeSSoby Mathew while (state_id) { 1272204afdeSSoby Mathew req_state->pwr_domain_state[i++] = state_id & 1282204afdeSSoby Mathew ARM_LOCAL_PSTATE_MASK; 1292204afdeSSoby Mathew state_id >>= ARM_LOCAL_PSTATE_WIDTH; 1302204afdeSSoby Mathew } 1312204afdeSSoby Mathew 1322204afdeSSoby Mathew return PSCI_E_SUCCESS; 1332204afdeSSoby Mathew } 1342204afdeSSoby Mathew #endif /* __ARM_RECOM_STATE_ID_ENC__ */ 135f9e858b1SSoby Mathew 136f9e858b1SSoby Mathew /******************************************************************************* 137f9e858b1SSoby Mathew * ARM standard platform handler called to check the validity of the non secure 138f9e858b1SSoby Mathew * entrypoint. 139f9e858b1SSoby Mathew ******************************************************************************/ 140f9e858b1SSoby Mathew int arm_validate_ns_entrypoint(uintptr_t entrypoint) 141f9e858b1SSoby Mathew { 142f9e858b1SSoby Mathew /* 143f9e858b1SSoby Mathew * Check if the non secure entrypoint lies within the non 144f9e858b1SSoby Mathew * secure DRAM. 145f9e858b1SSoby Mathew */ 146f9e858b1SSoby Mathew if ((entrypoint >= ARM_NS_DRAM1_BASE) && (entrypoint < 147f9e858b1SSoby Mathew (ARM_NS_DRAM1_BASE + ARM_NS_DRAM1_SIZE))) 148f9e858b1SSoby Mathew return PSCI_E_SUCCESS; 149f9e858b1SSoby Mathew if ((entrypoint >= ARM_DRAM2_BASE) && (entrypoint < 150f9e858b1SSoby Mathew (ARM_DRAM2_BASE + ARM_DRAM2_SIZE))) 151f9e858b1SSoby Mathew return PSCI_E_SUCCESS; 152f9e858b1SSoby Mathew 153f9e858b1SSoby Mathew return PSCI_E_INVALID_ADDRESS; 154f9e858b1SSoby Mathew } 155785fb92bSSoby Mathew 156c1bb8a05SSoby Mathew /****************************************************************************** 157*5486a965SSoby Mathew * Default definition on ARM standard platforms to override the plat_psci_ops. 158*5486a965SSoby Mathew *****************************************************************************/ 159*5486a965SSoby Mathew const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops) 160*5486a965SSoby Mathew { 161*5486a965SSoby Mathew return ops; 162*5486a965SSoby Mathew } 163*5486a965SSoby Mathew 164*5486a965SSoby Mathew /****************************************************************************** 165c1bb8a05SSoby Mathew * Helper function to resume the platform from system suspend. Reinitialize 166c1bb8a05SSoby Mathew * the system components which are not in the Always ON power domain. 167c1bb8a05SSoby Mathew * TODO: Unify the platform setup when waking up from cold boot and system 168c1bb8a05SSoby Mathew * resume in arm_bl31_platform_setup(). 169c1bb8a05SSoby Mathew *****************************************************************************/ 170c1bb8a05SSoby Mathew void arm_system_pwr_domain_resume(void) 171c1bb8a05SSoby Mathew { 172080225daSSoby Mathew console_init(PLAT_ARM_BL31_RUN_UART_BASE, PLAT_ARM_BL31_RUN_UART_CLK_IN_HZ, 173c1bb8a05SSoby Mathew ARM_CONSOLE_BAUDRATE); 174c1bb8a05SSoby Mathew 175c1bb8a05SSoby Mathew /* Assert system power domain is available on the platform */ 176c1bb8a05SSoby Mathew assert(PLAT_MAX_PWR_LVL >= ARM_PWR_LVL2); 177c1bb8a05SSoby Mathew 17827573c59SAchin Gupta /* 17927573c59SAchin Gupta * TODO: On GICv3 systems, figure out whether the core that wakes up 18027573c59SAchin Gupta * first from system suspend need to initialize the re-distributor 18127573c59SAchin Gupta * interface of all the other suspended cores. 18227573c59SAchin Gupta */ 18327573c59SAchin Gupta plat_arm_gic_init(); 184c1bb8a05SSoby Mathew plat_arm_security_setup(); 185c1bb8a05SSoby Mathew arm_configure_sys_timer(); 186c1bb8a05SSoby Mathew } 187c1bb8a05SSoby Mathew 188785fb92bSSoby Mathew /******************************************************************************* 189785fb92bSSoby Mathew * Private function to program the mailbox for a cpu before it is released 190785fb92bSSoby Mathew * from reset. This function assumes that the Trusted mail box base is within 191785fb92bSSoby Mathew * the ARM_SHARED_RAM region 192785fb92bSSoby Mathew ******************************************************************************/ 1934c117f6cSSandrine Bailleux void arm_program_trusted_mailbox(uintptr_t address) 194785fb92bSSoby Mathew { 195785fb92bSSoby Mathew uintptr_t *mailbox = (void *) PLAT_ARM_TRUSTED_MAILBOX_BASE; 196785fb92bSSoby Mathew 197785fb92bSSoby Mathew *mailbox = address; 198785fb92bSSoby Mathew 199785fb92bSSoby Mathew /* 200785fb92bSSoby Mathew * Ensure that the PLAT_ARM_TRUSTED_MAILBOX_BASE is within 201785fb92bSSoby Mathew * ARM_SHARED_RAM region. 202785fb92bSSoby Mathew */ 203785fb92bSSoby Mathew assert((PLAT_ARM_TRUSTED_MAILBOX_BASE >= ARM_SHARED_RAM_BASE) && 204785fb92bSSoby Mathew ((PLAT_ARM_TRUSTED_MAILBOX_BASE + sizeof(*mailbox)) <= \ 205785fb92bSSoby Mathew (ARM_SHARED_RAM_BASE + ARM_SHARED_RAM_SIZE))); 206785fb92bSSoby Mathew } 207785fb92bSSoby Mathew 208785fb92bSSoby Mathew /******************************************************************************* 209785fb92bSSoby Mathew * The ARM Standard platform definition of platform porting API 210785fb92bSSoby Mathew * `plat_setup_psci_ops`. 211785fb92bSSoby Mathew ******************************************************************************/ 212785fb92bSSoby Mathew int plat_setup_psci_ops(uintptr_t sec_entrypoint, 213785fb92bSSoby Mathew const plat_psci_ops_t **psci_ops) 214785fb92bSSoby Mathew { 215*5486a965SSoby Mathew *psci_ops = plat_arm_psci_override_pm_ops(&plat_arm_psci_pm_ops); 216785fb92bSSoby Mathew 217785fb92bSSoby Mathew /* Setup mailbox with entry point. */ 218785fb92bSSoby Mathew arm_program_trusted_mailbox(sec_entrypoint); 219785fb92bSSoby Mathew return 0; 220785fb92bSSoby Mathew } 221