1 /* 2 * Copyright (c) 2015, 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) 73 { 74 gp_regs_t *gp_regs; 75 int cpu = read_mpidr() & MPIDR_CPU_MASK; 76 int32_t rc = 0; 77 78 /* 79 * TLK runs only on CPU0 and resumes its Trusted Apps during 80 * SYSTEM_SUSPEND exit. It has no role to play during CPU_SUSPEND 81 * exit. 82 */ 83 if ((cpu != 0) || (suspend_level != PLAT_MAX_PWR_LVL)) 84 return; 85 86 /* pass system resume event to TLK */ 87 gp_regs = get_gpregs_ctx(&tlk_ctx.cpu_ctx); 88 write_ctx_reg(gp_regs, CTX_GPREG_X0, TLK_SYSTEM_RESUME); 89 90 /* Program the entry point and enter TLK */ 91 rc = tlkd_synchronous_sp_entry(&tlk_ctx); 92 93 /* 94 * Read the response from TLK. A non-zero return means that 95 * something went wrong while communicating with it. 96 */ 97 if (rc != 0) 98 panic(); 99 } 100 101 /******************************************************************************* 102 * Structure populated by the Dispatcher to be given a chance to perform any 103 * bookkeeping before PSCI executes a power mgmt. operation. 104 ******************************************************************************/ 105 const spd_pm_ops_t tlkd_pm_ops = { 106 .svc_migrate_info = cpu_migrate_info, 107 .svc_suspend = cpu_suspend_handler, 108 .svc_suspend_finish = cpu_resume_handler, 109 }; 110