1 /* 2 * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved. 3 * Copyright (c) 2023, NVIDIA Corporation. All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 */ 7 8 #include <assert.h> 9 #include <string.h> 10 11 #include <arch.h> 12 #include <arch_helpers.h> 13 #include <common/debug.h> 14 #include <drivers/arm/gic.h> 15 #include <lib/pmf/pmf.h> 16 #include <lib/runtime_instr.h> 17 #include <plat/common/platform.h> 18 19 #include "psci_private.h" 20 21 /****************************************************************************** 22 * Construct the psci_power_state to request power OFF at all power levels. 23 ******************************************************************************/ 24 static void psci_set_power_off_state(psci_power_state_t *state_info) 25 { 26 unsigned int lvl; 27 28 for (lvl = PSCI_CPU_PWR_LVL; lvl <= PLAT_MAX_PWR_LVL; lvl++) { 29 state_info->pwr_domain_state[lvl] = PLAT_MAX_OFF_STATE; 30 } 31 } 32 33 /****************************************************************************** 34 * Top level handler which is called when a cpu wants to power itself down. 35 * It's assumed that along with turning the cpu power domain off, power 36 * domains at higher levels will be turned off as far as possible. It finds 37 * the highest level where a domain has to be powered off by traversing the 38 * node information and then performs generic, architectural, platform setup 39 * and state management required to turn OFF that power domain and domains 40 * below it. e.g. For a cpu that's to be powered OFF, it could mean programming 41 * the power controller whereas for a cluster that's to be powered off, it will 42 * call the platform specific code which will disable coherency at the 43 * interconnect level if the cpu is the last in the cluster and also the 44 * program the power controller. 45 ******************************************************************************/ 46 int psci_do_cpu_off(unsigned int end_pwrlvl) 47 { 48 int rc = PSCI_E_SUCCESS; 49 unsigned int idx = plat_my_core_pos(); 50 psci_power_state_t state_info; 51 unsigned int parent_nodes[PLAT_MAX_PWR_LVL] = {0}; 52 53 /* 54 * This function must only be called on platforms where the 55 * CPU_OFF platform hooks have been implemented. 56 */ 57 assert(psci_plat_pm_ops->pwr_domain_off != NULL); 58 59 /* Construct the psci_power_state for CPU_OFF */ 60 psci_set_power_off_state(&state_info); 61 62 /* 63 * Call the platform provided early CPU_OFF handler to allow 64 * platforms to perform any housekeeping activities before 65 * actually powering the CPU off. PSCI_E_DENIED indicates that 66 * the CPU off sequence should be aborted at this time. 67 */ 68 if (psci_plat_pm_ops->pwr_domain_off_early) { 69 rc = psci_plat_pm_ops->pwr_domain_off_early(&state_info); 70 if (rc == PSCI_E_DENIED) { 71 return rc; 72 } 73 } 74 75 /* 76 * Get the parent nodes here, this is important to do before we 77 * initiate the power down sequence as after that point the core may 78 * have exited coherency and its cache may be disabled, any access to 79 * shared memory after that (such as the parent node lookup in 80 * psci_cpu_pd_nodes) can cause coherency issues on some platforms. 81 */ 82 psci_get_parent_pwr_domain_nodes(idx, end_pwrlvl, parent_nodes); 83 84 /* 85 * This function acquires the lock corresponding to each power 86 * level so that by the time all locks are taken, the system topology 87 * is snapshot and state management can be done safely. 88 */ 89 psci_acquire_pwr_domain_locks(end_pwrlvl, parent_nodes); 90 91 /* 92 * Call the cpu off handler registered by the Secure Payload Dispatcher 93 * to let it do any bookkeeping. Assume that the SPD always reports an 94 * E_DENIED error if SP refuse to power down 95 */ 96 if ((psci_spd_pm != NULL) && (psci_spd_pm->svc_off != NULL)) { 97 rc = psci_spd_pm->svc_off(0); 98 if (rc != PSCI_E_SUCCESS) { 99 goto off_exit; 100 } 101 } 102 103 /* 104 * This function is passed the requested state info and 105 * it returns the negotiated state info for each power level upto 106 * the end level specified. 107 */ 108 psci_do_state_coordination(idx, end_pwrlvl, &state_info); 109 110 /* Update the target state in the power domain nodes */ 111 psci_set_target_local_pwr_states(idx, end_pwrlvl, &state_info); 112 113 #if ENABLE_PSCI_STAT 114 /* Update the last cpu for each level till end_pwrlvl */ 115 psci_stats_update_pwr_down(idx, end_pwrlvl, &state_info); 116 #endif 117 118 /* 119 * Arch. management. Initiate power down sequence. 120 */ 121 psci_pwrdown_cpu_start(psci_find_max_off_lvl(&state_info)); 122 123 #if USE_GIC_DRIVER 124 /* turn the GIC off before we hand off to the platform */ 125 gic_cpuif_disable(idx); 126 /* we don't want any wakeups until explicitly turned on */ 127 gic_pcpu_off(idx); 128 #endif /* USE_GIC_DRIVER */ 129 130 /* 131 * Plat. management: Perform platform specific actions to turn this 132 * cpu off e.g. exit cpu coherency, program the power controller etc. 133 */ 134 psci_plat_pm_ops->pwr_domain_off(&state_info); 135 136 #if ENABLE_PSCI_STAT 137 plat_psci_stat_accounting_start(&state_info); 138 #endif 139 140 off_exit: 141 /* 142 * Release the locks corresponding to each power level in the 143 * reverse order to which they were acquired. 144 */ 145 psci_release_pwr_domain_locks(end_pwrlvl, parent_nodes); 146 147 /* 148 * Check if all actions needed to safely power down this cpu have 149 * successfully completed. 150 */ 151 if (rc == PSCI_E_SUCCESS) { 152 /* 153 * Set the affinity info state to OFF. When caches are disabled, 154 * this writes directly to main memory, so cache maintenance is 155 * required to ensure that later cached reads of aff_info_state 156 * return AFF_STATE_OFF. A dsbish() ensures ordering of the 157 * update to the affinity info state prior to cache line 158 * invalidation. 159 */ 160 psci_flush_cpu_data(psci_svc_cpu_data.aff_info_state); 161 psci_set_aff_info_state(AFF_STATE_OFF); 162 psci_dsbish(); 163 psci_inv_cpu_data(psci_svc_cpu_data.aff_info_state); 164 165 #if ENABLE_RUNTIME_INSTRUMENTATION 166 /* 167 * Update the timestamp with cache off. We assume this 168 * timestamp can only be read from the current CPU and the 169 * timestamp cache line will be flushed before return to 170 * normal world on wakeup. 171 */ 172 PMF_CAPTURE_TIMESTAMP(rt_instr_svc, 173 RT_INSTR_ENTER_HW_LOW_PWR, 174 PMF_NO_CACHE_MAINT); 175 #endif 176 if (psci_plat_pm_ops->pwr_domain_pwr_down != NULL) { 177 /* This function may not return */ 178 psci_plat_pm_ops->pwr_domain_pwr_down(&state_info); 179 } 180 181 psci_pwrdown_cpu_end_terminal(); 182 } 183 184 return rc; 185 } 186