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