1b4315306SDan Handley /* 25486a965SSoby Mathew * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. 3b4315306SDan Handley * 482cb2c1aSdp-arm * SPDX-License-Identifier: BSD-3-Clause 5b4315306SDan Handley */ 6b4315306SDan Handley 7b4315306SDan Handley #include <arch_helpers.h> 8f9e858b1SSoby Mathew #include <arm_def.h> 9c1bb8a05SSoby Mathew #include <arm_gic.h> 10b4315306SDan Handley #include <assert.h> 11c1bb8a05SSoby Mathew #include <console.h> 12b4315306SDan Handley #include <errno.h> 132204afdeSSoby Mathew #include <plat_arm.h> 14785fb92bSSoby Mathew #include <platform_def.h> 15b4315306SDan Handley #include <psci.h> 16b4315306SDan Handley 175486a965SSoby Mathew /* Allow ARM Standard platforms to override this function */ 185486a965SSoby Mathew #pragma weak plat_arm_psci_override_pm_ops 195486a965SSoby Mathew 20785fb92bSSoby Mathew /* Standard ARM platforms are expected to export plat_arm_psci_pm_ops */ 215486a965SSoby Mathew extern plat_psci_ops_t plat_arm_psci_pm_ops; 22785fb92bSSoby Mathew 232204afdeSSoby Mathew #if ARM_RECOM_STATE_ID_ENC 242204afdeSSoby Mathew extern unsigned int arm_pm_idle_states[]; 252204afdeSSoby Mathew #endif /* __ARM_RECOM_STATE_ID_ENC__ */ 262204afdeSSoby Mathew 272204afdeSSoby Mathew #if !ARM_RECOM_STATE_ID_ENC 28b4315306SDan Handley /******************************************************************************* 29b4315306SDan Handley * ARM standard platform handler called to check the validity of the power state 30b4315306SDan Handley * parameter. 31b4315306SDan Handley ******************************************************************************/ 3238dce70fSSoby Mathew int arm_validate_power_state(unsigned int power_state, 3338dce70fSSoby Mathew psci_power_state_t *req_state) 34b4315306SDan Handley { 3538dce70fSSoby Mathew int pstate = psci_get_pstate_type(power_state); 3638dce70fSSoby Mathew int pwr_lvl = psci_get_pstate_pwrlvl(power_state); 3738dce70fSSoby Mathew int i; 3838dce70fSSoby Mathew 3938dce70fSSoby Mathew assert(req_state); 4038dce70fSSoby Mathew 4138dce70fSSoby Mathew if (pwr_lvl > PLAT_MAX_PWR_LVL) 42b4315306SDan Handley return PSCI_E_INVALID_PARAMS; 4338dce70fSSoby Mathew 4438dce70fSSoby Mathew /* Sanity check the requested state */ 4538dce70fSSoby Mathew if (pstate == PSTATE_TYPE_STANDBY) { 4638dce70fSSoby Mathew /* 4738dce70fSSoby Mathew * It's possible to enter standby only on power level 0 4838dce70fSSoby Mathew * Ignore any other power level. 4938dce70fSSoby Mathew */ 5038dce70fSSoby Mathew if (pwr_lvl != ARM_PWR_LVL0) 5138dce70fSSoby Mathew return PSCI_E_INVALID_PARAMS; 5238dce70fSSoby Mathew 5338dce70fSSoby Mathew req_state->pwr_domain_state[ARM_PWR_LVL0] = 5438dce70fSSoby Mathew ARM_LOCAL_STATE_RET; 5538dce70fSSoby Mathew } else { 5638dce70fSSoby Mathew for (i = ARM_PWR_LVL0; i <= pwr_lvl; i++) 5738dce70fSSoby Mathew req_state->pwr_domain_state[i] = 5838dce70fSSoby Mathew ARM_LOCAL_STATE_OFF; 59b4315306SDan Handley } 60b4315306SDan Handley 61b4315306SDan Handley /* 62b4315306SDan Handley * We expect the 'state id' to be zero. 63b4315306SDan Handley */ 64b4315306SDan Handley if (psci_get_pstate_id(power_state)) 65b4315306SDan Handley return PSCI_E_INVALID_PARAMS; 66b4315306SDan Handley 67b4315306SDan Handley return PSCI_E_SUCCESS; 68b4315306SDan Handley } 692204afdeSSoby Mathew 702204afdeSSoby Mathew #else 712204afdeSSoby Mathew /******************************************************************************* 722204afdeSSoby Mathew * ARM standard platform handler called to check the validity of the power 732204afdeSSoby Mathew * state parameter. The power state parameter has to be a composite power 742204afdeSSoby Mathew * state. 752204afdeSSoby Mathew ******************************************************************************/ 762204afdeSSoby Mathew int arm_validate_power_state(unsigned int power_state, 772204afdeSSoby Mathew psci_power_state_t *req_state) 782204afdeSSoby Mathew { 792204afdeSSoby Mathew unsigned int state_id; 802204afdeSSoby Mathew int i; 812204afdeSSoby Mathew 822204afdeSSoby Mathew assert(req_state); 832204afdeSSoby Mathew 842204afdeSSoby Mathew /* 852204afdeSSoby Mathew * Currently we are using a linear search for finding the matching 862204afdeSSoby Mathew * entry in the idle power state array. This can be made a binary 872204afdeSSoby Mathew * search if the number of entries justify the additional complexity. 882204afdeSSoby Mathew */ 892204afdeSSoby Mathew for (i = 0; !!arm_pm_idle_states[i]; i++) { 902204afdeSSoby Mathew if (power_state == arm_pm_idle_states[i]) 912204afdeSSoby Mathew break; 922204afdeSSoby Mathew } 932204afdeSSoby Mathew 942204afdeSSoby Mathew /* Return error if entry not found in the idle state array */ 952204afdeSSoby Mathew if (!arm_pm_idle_states[i]) 962204afdeSSoby Mathew return PSCI_E_INVALID_PARAMS; 972204afdeSSoby Mathew 982204afdeSSoby Mathew i = 0; 992204afdeSSoby Mathew state_id = psci_get_pstate_id(power_state); 1002204afdeSSoby Mathew 1012204afdeSSoby Mathew /* Parse the State ID and populate the state info parameter */ 1022204afdeSSoby Mathew while (state_id) { 1032204afdeSSoby Mathew req_state->pwr_domain_state[i++] = state_id & 1042204afdeSSoby Mathew ARM_LOCAL_PSTATE_MASK; 1052204afdeSSoby Mathew state_id >>= ARM_LOCAL_PSTATE_WIDTH; 1062204afdeSSoby Mathew } 1072204afdeSSoby Mathew 1082204afdeSSoby Mathew return PSCI_E_SUCCESS; 1092204afdeSSoby Mathew } 1102204afdeSSoby Mathew #endif /* __ARM_RECOM_STATE_ID_ENC__ */ 111f9e858b1SSoby Mathew 112f9e858b1SSoby Mathew /******************************************************************************* 113f9e858b1SSoby Mathew * ARM standard platform handler called to check the validity of the non secure 114f9e858b1SSoby Mathew * entrypoint. 115f9e858b1SSoby Mathew ******************************************************************************/ 116f9e858b1SSoby Mathew int arm_validate_ns_entrypoint(uintptr_t entrypoint) 117f9e858b1SSoby Mathew { 118f9e858b1SSoby Mathew /* 119f9e858b1SSoby Mathew * Check if the non secure entrypoint lies within the non 120f9e858b1SSoby Mathew * secure DRAM. 121f9e858b1SSoby Mathew */ 122f9e858b1SSoby Mathew if ((entrypoint >= ARM_NS_DRAM1_BASE) && (entrypoint < 123f9e858b1SSoby Mathew (ARM_NS_DRAM1_BASE + ARM_NS_DRAM1_SIZE))) 124f9e858b1SSoby Mathew return PSCI_E_SUCCESS; 125*7c7dffd8Sdp-arm #ifndef AARCH32 126f9e858b1SSoby Mathew if ((entrypoint >= ARM_DRAM2_BASE) && (entrypoint < 127f9e858b1SSoby Mathew (ARM_DRAM2_BASE + ARM_DRAM2_SIZE))) 128f9e858b1SSoby Mathew return PSCI_E_SUCCESS; 129*7c7dffd8Sdp-arm #endif 130f9e858b1SSoby Mathew 131f9e858b1SSoby Mathew return PSCI_E_INVALID_ADDRESS; 132f9e858b1SSoby Mathew } 133785fb92bSSoby Mathew 134c1bb8a05SSoby Mathew /****************************************************************************** 1355486a965SSoby Mathew * Default definition on ARM standard platforms to override the plat_psci_ops. 1365486a965SSoby Mathew *****************************************************************************/ 1375486a965SSoby Mathew const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops) 1385486a965SSoby Mathew { 1395486a965SSoby Mathew return ops; 1405486a965SSoby Mathew } 1415486a965SSoby Mathew 1425486a965SSoby Mathew /****************************************************************************** 143c1bb8a05SSoby Mathew * Helper function to resume the platform from system suspend. Reinitialize 144c1bb8a05SSoby Mathew * the system components which are not in the Always ON power domain. 145c1bb8a05SSoby Mathew * TODO: Unify the platform setup when waking up from cold boot and system 146c1bb8a05SSoby Mathew * resume in arm_bl31_platform_setup(). 147c1bb8a05SSoby Mathew *****************************************************************************/ 148c1bb8a05SSoby Mathew void arm_system_pwr_domain_resume(void) 149c1bb8a05SSoby Mathew { 150080225daSSoby Mathew console_init(PLAT_ARM_BL31_RUN_UART_BASE, PLAT_ARM_BL31_RUN_UART_CLK_IN_HZ, 151c1bb8a05SSoby Mathew ARM_CONSOLE_BAUDRATE); 152c1bb8a05SSoby Mathew 153c1bb8a05SSoby Mathew /* Assert system power domain is available on the platform */ 154c1bb8a05SSoby Mathew assert(PLAT_MAX_PWR_LVL >= ARM_PWR_LVL2); 155c1bb8a05SSoby Mathew 15627573c59SAchin Gupta /* 15727573c59SAchin Gupta * TODO: On GICv3 systems, figure out whether the core that wakes up 15827573c59SAchin Gupta * first from system suspend need to initialize the re-distributor 15927573c59SAchin Gupta * interface of all the other suspended cores. 16027573c59SAchin Gupta */ 16127573c59SAchin Gupta plat_arm_gic_init(); 162c1bb8a05SSoby Mathew plat_arm_security_setup(); 163c1bb8a05SSoby Mathew arm_configure_sys_timer(); 164c1bb8a05SSoby Mathew } 165c1bb8a05SSoby Mathew 166785fb92bSSoby Mathew /******************************************************************************* 167785fb92bSSoby Mathew * Private function to program the mailbox for a cpu before it is released 168785fb92bSSoby Mathew * from reset. This function assumes that the Trusted mail box base is within 169785fb92bSSoby Mathew * the ARM_SHARED_RAM region 170785fb92bSSoby Mathew ******************************************************************************/ 1714c117f6cSSandrine Bailleux void arm_program_trusted_mailbox(uintptr_t address) 172785fb92bSSoby Mathew { 173785fb92bSSoby Mathew uintptr_t *mailbox = (void *) PLAT_ARM_TRUSTED_MAILBOX_BASE; 174785fb92bSSoby Mathew 175785fb92bSSoby Mathew *mailbox = address; 176785fb92bSSoby Mathew 177785fb92bSSoby Mathew /* 178785fb92bSSoby Mathew * Ensure that the PLAT_ARM_TRUSTED_MAILBOX_BASE is within 179785fb92bSSoby Mathew * ARM_SHARED_RAM region. 180785fb92bSSoby Mathew */ 181785fb92bSSoby Mathew assert((PLAT_ARM_TRUSTED_MAILBOX_BASE >= ARM_SHARED_RAM_BASE) && 182785fb92bSSoby Mathew ((PLAT_ARM_TRUSTED_MAILBOX_BASE + sizeof(*mailbox)) <= \ 183785fb92bSSoby Mathew (ARM_SHARED_RAM_BASE + ARM_SHARED_RAM_SIZE))); 184785fb92bSSoby Mathew } 185785fb92bSSoby Mathew 186785fb92bSSoby Mathew /******************************************************************************* 187785fb92bSSoby Mathew * The ARM Standard platform definition of platform porting API 188785fb92bSSoby Mathew * `plat_setup_psci_ops`. 189785fb92bSSoby Mathew ******************************************************************************/ 190785fb92bSSoby Mathew int plat_setup_psci_ops(uintptr_t sec_entrypoint, 191785fb92bSSoby Mathew const plat_psci_ops_t **psci_ops) 192785fb92bSSoby Mathew { 1935486a965SSoby Mathew *psci_ops = plat_arm_psci_override_pm_ops(&plat_arm_psci_pm_ops); 194785fb92bSSoby Mathew 195785fb92bSSoby Mathew /* Setup mailbox with entry point. */ 196785fb92bSSoby Mathew arm_program_trusted_mailbox(sec_entrypoint); 197785fb92bSSoby Mathew return 0; 198785fb92bSSoby Mathew } 199