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