1 /* 2 * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <stdbool.h> 9 10 #include <arch_helpers.h> 11 #include <common/debug.h> 12 #include <lib/el3_runtime/cpu_data.h> 13 #include <lib/psci/psci.h> 14 #include <plat/common/platform.h> 15 16 #include <ti_sci_protocol.h> 17 #include <k3_gicv3.h> 18 #include <ti_sci.h> 19 20 #define CORE_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL0]) 21 #define CLUSTER_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL1]) 22 #define SYSTEM_PWR_STATE(state) ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL]) 23 24 uintptr_t k3_sec_entrypoint; 25 26 static void k3_cpu_standby(plat_local_state_t cpu_state) 27 { 28 u_register_t scr; 29 30 scr = read_scr_el3(); 31 /* Enable the Non secure interrupt to wake the CPU */ 32 write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT); 33 isb(); 34 /* dsb is good practice before using wfi to enter low power states */ 35 dsb(); 36 /* Enter standby state */ 37 wfi(); 38 /* Restore SCR */ 39 write_scr_el3(scr); 40 } 41 42 static int k3_pwr_domain_on(u_register_t mpidr) 43 { 44 int core, proc_id, device_id, ret; 45 46 core = plat_core_pos_by_mpidr(mpidr); 47 if (core < 0) { 48 ERROR("Could not get target core id: %d\n", core); 49 return PSCI_E_INTERN_FAIL; 50 } 51 52 proc_id = PLAT_PROC_START_ID + core; 53 device_id = PLAT_PROC_DEVICE_START_ID + core; 54 55 ret = ti_sci_proc_request(proc_id); 56 if (ret) { 57 ERROR("Request for processor failed: %d\n", ret); 58 return PSCI_E_INTERN_FAIL; 59 } 60 61 ret = ti_sci_proc_set_boot_cfg(proc_id, k3_sec_entrypoint, 0, 0); 62 if (ret) { 63 ERROR("Request to set core boot address failed: %d\n", ret); 64 return PSCI_E_INTERN_FAIL; 65 } 66 67 /* sanity check these are off before starting a core */ 68 ret = ti_sci_proc_set_boot_ctrl(proc_id, 69 0, PROC_BOOT_CTRL_FLAG_ARMV8_L2FLUSHREQ | 70 PROC_BOOT_CTRL_FLAG_ARMV8_AINACTS | 71 PROC_BOOT_CTRL_FLAG_ARMV8_ACINACTM); 72 if (ret) { 73 ERROR("Request to clear boot configuration failed: %d\n", ret); 74 return PSCI_E_INTERN_FAIL; 75 } 76 77 ret = ti_sci_device_get(device_id); 78 if (ret) { 79 ERROR("Request to start core failed: %d\n", ret); 80 return PSCI_E_INTERN_FAIL; 81 } 82 83 return PSCI_E_SUCCESS; 84 } 85 86 void k3_pwr_domain_off(const psci_power_state_t *target_state) 87 { 88 int core, cluster, proc_id, device_id, cluster_id, ret; 89 90 /* At very least the local core should be powering down */ 91 assert(CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE); 92 93 /* Prevent interrupts from spuriously waking up this cpu */ 94 k3_gic_cpuif_disable(); 95 96 core = plat_my_core_pos(); 97 cluster = MPIDR_AFFLVL1_VAL(read_mpidr_el1()); 98 proc_id = PLAT_PROC_START_ID + core; 99 device_id = PLAT_PROC_DEVICE_START_ID + core; 100 cluster_id = PLAT_CLUSTER_DEVICE_START_ID + (cluster * 2); 101 102 /* 103 * If we are the last core in the cluster then we take a reference to 104 * the cluster device so that it does not get shutdown before we 105 * execute the entire cluster L2 cleaning sequence below. 106 */ 107 if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) { 108 ret = ti_sci_device_get(cluster_id); 109 if (ret) { 110 ERROR("Request to get cluster failed: %d\n", ret); 111 return; 112 } 113 } 114 115 /* Start by sending wait for WFI command */ 116 ret = ti_sci_proc_wait_boot_status_no_wait(proc_id, 117 /* 118 * Wait maximum time to give us the best chance to get 119 * to WFI before this command timeouts 120 */ 121 UINT8_MAX, 100, UINT8_MAX, UINT8_MAX, 122 /* Wait for WFI */ 123 PROC_BOOT_STATUS_FLAG_ARMV8_WFI, 0, 0, 0); 124 if (ret) { 125 ERROR("Sending wait for WFI failed (%d)\n", ret); 126 return; 127 } 128 129 /* Now queue up the core shutdown request */ 130 ret = ti_sci_device_put_no_wait(device_id); 131 if (ret) { 132 ERROR("Sending core shutdown message failed (%d)\n", ret); 133 return; 134 } 135 136 /* If our cluster is not going down we stop here */ 137 if (CLUSTER_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE) 138 return; 139 140 /* set AINACTS */ 141 ret = ti_sci_proc_set_boot_ctrl_no_wait(proc_id, 142 PROC_BOOT_CTRL_FLAG_ARMV8_AINACTS, 0); 143 if (ret) { 144 ERROR("Sending set control message failed (%d)\n", ret); 145 return; 146 } 147 148 /* set L2FLUSHREQ */ 149 ret = ti_sci_proc_set_boot_ctrl_no_wait(proc_id, 150 PROC_BOOT_CTRL_FLAG_ARMV8_L2FLUSHREQ, 0); 151 if (ret) { 152 ERROR("Sending set control message failed (%d)\n", ret); 153 return; 154 } 155 156 /* wait for L2FLUSHDONE*/ 157 ret = ti_sci_proc_wait_boot_status_no_wait(proc_id, 158 UINT8_MAX, 2, UINT8_MAX, UINT8_MAX, 159 PROC_BOOT_STATUS_FLAG_ARMV8_L2F_DONE, 0, 0, 0); 160 if (ret) { 161 ERROR("Sending wait message failed (%d)\n", ret); 162 return; 163 } 164 165 /* clear L2FLUSHREQ */ 166 ret = ti_sci_proc_set_boot_ctrl_no_wait(proc_id, 167 0, PROC_BOOT_CTRL_FLAG_ARMV8_L2FLUSHREQ); 168 if (ret) { 169 ERROR("Sending set control message failed (%d)\n", ret); 170 return; 171 } 172 173 /* set ACINACTM */ 174 ret = ti_sci_proc_set_boot_ctrl_no_wait(proc_id, 175 PROC_BOOT_CTRL_FLAG_ARMV8_ACINACTM, 0); 176 if (ret) { 177 ERROR("Sending set control message failed (%d)\n", ret); 178 return; 179 } 180 181 /* wait for STANDBYWFIL2 */ 182 ret = ti_sci_proc_wait_boot_status_no_wait(proc_id, 183 UINT8_MAX, 2, UINT8_MAX, UINT8_MAX, 184 PROC_BOOT_STATUS_FLAG_ARMV8_STANDBYWFIL2, 0, 0, 0); 185 if (ret) { 186 ERROR("Sending wait message failed (%d)\n", ret); 187 return; 188 } 189 190 /* Now queue up the cluster shutdown request */ 191 ret = ti_sci_device_put_no_wait(cluster_id); 192 if (ret) { 193 ERROR("Sending cluster shutdown message failed (%d)\n", ret); 194 return; 195 } 196 } 197 198 void k3_pwr_domain_on_finish(const psci_power_state_t *target_state) 199 { 200 /* TODO: Indicate to System firmware about completion */ 201 202 k3_gic_pcpu_init(); 203 k3_gic_cpuif_enable(); 204 } 205 206 static void __dead2 k3_system_off(void) 207 { 208 int ret; 209 210 /* Queue up the system shutdown request */ 211 ret = ti_sci_device_put_no_wait(PLAT_BOARD_DEVICE_ID); 212 if (ret != 0) { 213 ERROR("Sending system shutdown message failed (%d)\n", ret); 214 } 215 216 while (true) 217 wfi(); 218 } 219 220 static void __dead2 k3_system_reset(void) 221 { 222 /* Send the system reset request to system firmware */ 223 ti_sci_core_reboot(); 224 225 while (true) 226 wfi(); 227 } 228 229 static int k3_validate_power_state(unsigned int power_state, psci_power_state_t *req_state) 230 { 231 unsigned int pwr_lvl = psci_get_pstate_pwrlvl(power_state); 232 unsigned int pstate = psci_get_pstate_type(power_state); 233 234 if (pwr_lvl > PLAT_MAX_PWR_LVL) 235 return PSCI_E_INVALID_PARAMS; 236 237 if (pstate == PSTATE_TYPE_STANDBY) { 238 /* 239 * It's possible to enter standby only on power level 0 240 * Ignore any other power level. 241 */ 242 if (pwr_lvl != MPIDR_AFFLVL0) 243 return PSCI_E_INVALID_PARAMS; 244 245 CORE_PWR_STATE(req_state) = PLAT_MAX_RET_STATE; 246 } 247 248 return PSCI_E_SUCCESS; 249 } 250 251 static void k3_pwr_domain_suspend_to_mode(const psci_power_state_t *target_state, uint8_t mode) 252 { 253 unsigned int core, proc_id; 254 255 core = plat_my_core_pos(); 256 proc_id = PLAT_PROC_START_ID + core; 257 258 /* Prevent interrupts from spuriously waking up this cpu */ 259 k3_gic_cpuif_disable(); 260 k3_gic_save_context(); 261 262 k3_pwr_domain_off(target_state); 263 264 ti_sci_enter_sleep(proc_id, mode, k3_sec_entrypoint); 265 } 266 267 static void k3_pwr_domain_suspend_dm_managed(const psci_power_state_t *target_state) 268 { 269 uint8_t mode = MSG_VALUE_SLEEP_MODE_DEEP_SLEEP; 270 int ret; 271 272 ret = ti_sci_lpm_get_next_sys_mode(&mode); 273 if (ret != 0) { 274 ERROR("Failed to fetch next system mode\n"); 275 } 276 277 k3_pwr_domain_suspend_to_mode(target_state, mode); 278 } 279 280 static void k3_pwr_domain_suspend(const psci_power_state_t *target_state) 281 { 282 k3_pwr_domain_suspend_to_mode(target_state, MSG_VALUE_SLEEP_MODE_DEEP_SLEEP); 283 } 284 285 static void k3_pwr_domain_suspend_finish(const psci_power_state_t *target_state) 286 { 287 k3_gic_restore_context(); 288 k3_gic_cpuif_enable(); 289 } 290 291 static void k3_get_sys_suspend_power_state(psci_power_state_t *req_state) 292 { 293 unsigned int i; 294 295 /* CPU & cluster off, system in retention */ 296 for (i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++) { 297 req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; 298 } 299 } 300 301 static plat_psci_ops_t k3_plat_psci_ops = { 302 .cpu_standby = k3_cpu_standby, 303 .pwr_domain_on = k3_pwr_domain_on, 304 .pwr_domain_off = k3_pwr_domain_off, 305 .pwr_domain_on_finish = k3_pwr_domain_on_finish, 306 .pwr_domain_suspend = k3_pwr_domain_suspend, 307 .pwr_domain_suspend_finish = k3_pwr_domain_suspend_finish, 308 .get_sys_suspend_power_state = k3_get_sys_suspend_power_state, 309 .system_off = k3_system_off, 310 .system_reset = k3_system_reset, 311 .validate_power_state = k3_validate_power_state, 312 }; 313 314 int plat_setup_psci_ops(uintptr_t sec_entrypoint, 315 const plat_psci_ops_t **psci_ops) 316 { 317 uint64_t fw_caps = 0; 318 int ret; 319 320 k3_sec_entrypoint = sec_entrypoint; 321 322 ret = ti_sci_query_fw_caps(&fw_caps); 323 if (ret) { 324 ERROR("Unable to query firmware capabilities (%d)\n", ret); 325 } 326 327 /* If firmware does not support any known suspend mode */ 328 if (!(fw_caps & (MSG_FLAG_CAPS_LPM_DEEP_SLEEP | 329 MSG_FLAG_CAPS_LPM_MCU_ONLY | 330 MSG_FLAG_CAPS_LPM_STANDBY | 331 MSG_FLAG_CAPS_LPM_PARTIAL_IO))) { 332 /* Disable PSCI suspend support */ 333 k3_plat_psci_ops.pwr_domain_suspend = NULL; 334 k3_plat_psci_ops.pwr_domain_suspend_finish = NULL; 335 k3_plat_psci_ops.get_sys_suspend_power_state = NULL; 336 } else if (fw_caps & MSG_FLAG_CAPS_LPM_DM_MANAGED) { 337 k3_plat_psci_ops.pwr_domain_suspend = k3_pwr_domain_suspend_dm_managed; 338 } 339 340 *psci_ops = &k3_plat_psci_ops; 341 342 return 0; 343 } 344