1 /* 2 * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <arch_helpers.h> 8 #include <arm_def.h> 9 #include <arm_gic.h> 10 #include <assert.h> 11 #include <console.h> 12 #include <errno.h> 13 #include <plat_arm.h> 14 #include <platform_def.h> 15 #include <psci.h> 16 17 /* Allow ARM Standard platforms to override this function */ 18 #pragma weak plat_arm_psci_override_pm_ops 19 20 /* Standard ARM platforms are expected to export plat_arm_psci_pm_ops */ 21 extern plat_psci_ops_t plat_arm_psci_pm_ops; 22 23 #if ARM_RECOM_STATE_ID_ENC 24 extern unsigned int arm_pm_idle_states[]; 25 #endif /* __ARM_RECOM_STATE_ID_ENC__ */ 26 27 #if !ARM_RECOM_STATE_ID_ENC 28 /******************************************************************************* 29 * ARM standard platform handler called to check the validity of the power state 30 * parameter. 31 ******************************************************************************/ 32 int arm_validate_power_state(unsigned int power_state, 33 psci_power_state_t *req_state) 34 { 35 int pstate = psci_get_pstate_type(power_state); 36 int pwr_lvl = psci_get_pstate_pwrlvl(power_state); 37 int i; 38 39 assert(req_state); 40 41 if (pwr_lvl > PLAT_MAX_PWR_LVL) 42 return PSCI_E_INVALID_PARAMS; 43 44 /* Sanity check the requested state */ 45 if (pstate == PSTATE_TYPE_STANDBY) { 46 /* 47 * It's possible to enter standby only on power level 0 48 * Ignore any other power level. 49 */ 50 if (pwr_lvl != ARM_PWR_LVL0) 51 return PSCI_E_INVALID_PARAMS; 52 53 req_state->pwr_domain_state[ARM_PWR_LVL0] = 54 ARM_LOCAL_STATE_RET; 55 } else { 56 for (i = ARM_PWR_LVL0; i <= pwr_lvl; i++) 57 req_state->pwr_domain_state[i] = 58 ARM_LOCAL_STATE_OFF; 59 } 60 61 /* 62 * We expect the 'state id' to be zero. 63 */ 64 if (psci_get_pstate_id(power_state)) 65 return PSCI_E_INVALID_PARAMS; 66 67 return PSCI_E_SUCCESS; 68 } 69 70 #else 71 /******************************************************************************* 72 * ARM standard platform handler called to check the validity of the power 73 * state parameter. The power state parameter has to be a composite power 74 * state. 75 ******************************************************************************/ 76 int arm_validate_power_state(unsigned int power_state, 77 psci_power_state_t *req_state) 78 { 79 unsigned int state_id; 80 int i; 81 82 assert(req_state); 83 84 /* 85 * Currently we are using a linear search for finding the matching 86 * entry in the idle power state array. This can be made a binary 87 * search if the number of entries justify the additional complexity. 88 */ 89 for (i = 0; !!arm_pm_idle_states[i]; i++) { 90 if (power_state == arm_pm_idle_states[i]) 91 break; 92 } 93 94 /* Return error if entry not found in the idle state array */ 95 if (!arm_pm_idle_states[i]) 96 return PSCI_E_INVALID_PARAMS; 97 98 i = 0; 99 state_id = psci_get_pstate_id(power_state); 100 101 /* Parse the State ID and populate the state info parameter */ 102 while (state_id) { 103 req_state->pwr_domain_state[i++] = state_id & 104 ARM_LOCAL_PSTATE_MASK; 105 state_id >>= ARM_LOCAL_PSTATE_WIDTH; 106 } 107 108 return PSCI_E_SUCCESS; 109 } 110 #endif /* __ARM_RECOM_STATE_ID_ENC__ */ 111 112 /******************************************************************************* 113 * ARM standard platform handler called to check the validity of the non secure 114 * entrypoint. 115 ******************************************************************************/ 116 int arm_validate_ns_entrypoint(uintptr_t entrypoint) 117 { 118 /* 119 * Check if the non secure entrypoint lies within the non 120 * secure DRAM. 121 */ 122 if ((entrypoint >= ARM_NS_DRAM1_BASE) && (entrypoint < 123 (ARM_NS_DRAM1_BASE + ARM_NS_DRAM1_SIZE))) 124 return PSCI_E_SUCCESS; 125 if ((entrypoint >= ARM_DRAM2_BASE) && (entrypoint < 126 (ARM_DRAM2_BASE + ARM_DRAM2_SIZE))) 127 return PSCI_E_SUCCESS; 128 129 return PSCI_E_INVALID_ADDRESS; 130 } 131 132 /****************************************************************************** 133 * Default definition on ARM standard platforms to override the plat_psci_ops. 134 *****************************************************************************/ 135 const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops) 136 { 137 return ops; 138 } 139 140 /****************************************************************************** 141 * Helper function to resume the platform from system suspend. Reinitialize 142 * the system components which are not in the Always ON power domain. 143 * TODO: Unify the platform setup when waking up from cold boot and system 144 * resume in arm_bl31_platform_setup(). 145 *****************************************************************************/ 146 void arm_system_pwr_domain_resume(void) 147 { 148 console_init(PLAT_ARM_BL31_RUN_UART_BASE, PLAT_ARM_BL31_RUN_UART_CLK_IN_HZ, 149 ARM_CONSOLE_BAUDRATE); 150 151 /* Assert system power domain is available on the platform */ 152 assert(PLAT_MAX_PWR_LVL >= ARM_PWR_LVL2); 153 154 /* 155 * TODO: On GICv3 systems, figure out whether the core that wakes up 156 * first from system suspend need to initialize the re-distributor 157 * interface of all the other suspended cores. 158 */ 159 plat_arm_gic_init(); 160 plat_arm_security_setup(); 161 arm_configure_sys_timer(); 162 } 163 164 /******************************************************************************* 165 * Private function to program the mailbox for a cpu before it is released 166 * from reset. This function assumes that the Trusted mail box base is within 167 * the ARM_SHARED_RAM region 168 ******************************************************************************/ 169 void arm_program_trusted_mailbox(uintptr_t address) 170 { 171 uintptr_t *mailbox = (void *) PLAT_ARM_TRUSTED_MAILBOX_BASE; 172 173 *mailbox = address; 174 175 /* 176 * Ensure that the PLAT_ARM_TRUSTED_MAILBOX_BASE is within 177 * ARM_SHARED_RAM region. 178 */ 179 assert((PLAT_ARM_TRUSTED_MAILBOX_BASE >= ARM_SHARED_RAM_BASE) && 180 ((PLAT_ARM_TRUSTED_MAILBOX_BASE + sizeof(*mailbox)) <= \ 181 (ARM_SHARED_RAM_BASE + ARM_SHARED_RAM_SIZE))); 182 } 183 184 /******************************************************************************* 185 * The ARM Standard platform definition of platform porting API 186 * `plat_setup_psci_ops`. 187 ******************************************************************************/ 188 int plat_setup_psci_ops(uintptr_t sec_entrypoint, 189 const plat_psci_ops_t **psci_ops) 190 { 191 *psci_ops = plat_arm_psci_override_pm_ops(&plat_arm_psci_pm_ops); 192 193 /* Setup mailbox with entry point. */ 194 arm_program_trusted_mailbox(sec_entrypoint); 195 return 0; 196 } 197