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