1 /* 2 * Copyright (c) 2015-2025, Arm Limited and Contributors. All rights reserved. 3 * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 */ 7 8 #include <assert.h> 9 10 #include <arch_helpers.h> 11 #include <bl32/payloads/tlk.h> 12 #include <common/bl_common.h> 13 #include <common/debug.h> 14 #include <lib/el3_runtime/context_mgmt.h> 15 #include <lib/psci/psci.h> 16 17 #include "tlkd_private.h" 18 19 extern tlk_context_t tlk_ctx; 20 21 #define MPIDR_CPU0 0x80000000 22 23 /******************************************************************************* 24 * Return the type of payload TLKD is dealing with. Report the current 25 * resident cpu (mpidr format) if it is a UP/UP migratable payload. 26 ******************************************************************************/ 27 static int32_t cpu_migrate_info(u_register_t *resident_cpu) 28 { 29 /* the payload runs only on CPU0 */ 30 *resident_cpu = MPIDR_CPU0; 31 32 /* Uniprocessor, not migrate capable payload */ 33 return PSCI_TOS_NOT_UP_MIG_CAP; 34 } 35 36 /******************************************************************************* 37 * This cpu is being suspended. Inform TLK of the SYSTEM_SUSPEND event, so 38 * that it can pass this information to its Trusted Apps. 39 ******************************************************************************/ 40 static void cpu_suspend_handler(u_register_t suspend_level) 41 { 42 gp_regs_t *gp_regs; 43 int cpu = read_mpidr() & MPIDR_CPU_MASK; 44 int32_t rc = 0; 45 46 /* 47 * TLK runs only on CPU0 and suspends its Trusted Apps during 48 * SYSTEM_SUSPEND. It has no role to play during CPU_SUSPEND. 49 */ 50 if ((cpu != 0) || (suspend_level != PLAT_MAX_PWR_LVL)) 51 return; 52 53 /* pass system suspend event to TLK */ 54 gp_regs = get_gpregs_ctx(&tlk_ctx.cpu_ctx); 55 write_ctx_reg(gp_regs, CTX_GPREG_X0, TLK_SYSTEM_SUSPEND); 56 57 /* Program the entry point and enter TLK */ 58 rc = tlkd_synchronous_sp_entry(&tlk_ctx); 59 60 /* 61 * Read the response from TLK. A non-zero return means that 62 * something went wrong while communicating with it. 63 */ 64 if (rc != 0) 65 panic(); 66 } 67 68 /******************************************************************************* 69 * This cpu is being resumed. Inform TLK of the SYSTEM_SUSPEND exit, so 70 * that it can pass this information to its Trusted Apps. 71 ******************************************************************************/ 72 static void cpu_resume_handler(u_register_t suspend_level, bool abandon) 73 { 74 gp_regs_t *gp_regs; 75 int cpu = read_mpidr() & MPIDR_CPU_MASK; 76 int32_t rc = 0; 77 78 /* tlkd is not expected to be used on platforms with pabandon */ 79 assert(!abandon); 80 81 /* 82 * TLK runs only on CPU0 and resumes its Trusted Apps during 83 * SYSTEM_SUSPEND exit. It has no role to play during CPU_SUSPEND 84 * exit. 85 */ 86 if ((cpu != 0) || (suspend_level != PLAT_MAX_PWR_LVL)) 87 return; 88 89 /* pass system resume event to TLK */ 90 gp_regs = get_gpregs_ctx(&tlk_ctx.cpu_ctx); 91 write_ctx_reg(gp_regs, CTX_GPREG_X0, TLK_SYSTEM_RESUME); 92 93 /* Program the entry point and enter TLK */ 94 rc = tlkd_synchronous_sp_entry(&tlk_ctx); 95 96 /* 97 * Read the response from TLK. A non-zero return means that 98 * something went wrong while communicating with it. 99 */ 100 if (rc != 0) 101 panic(); 102 } 103 104 /******************************************************************************* 105 * Structure populated by the Dispatcher to be given a chance to perform any 106 * bookkeeping before PSCI executes a power mgmt. operation. 107 ******************************************************************************/ 108 const spd_pm_ops_t tlkd_pm_ops = { 109 .svc_migrate_info = cpu_migrate_info, 110 .svc_suspend = cpu_suspend_handler, 111 .svc_suspend_finish = cpu_resume_handler, 112 }; 113