1 /* 2 * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * Redistributions of source code must retain the above copyright notice, this 8 * list of conditions and the following disclaimer. 9 * 10 * Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * Neither the name of ARM nor the names of its contributors may be used 15 * to endorse or promote products derived from this software without specific 16 * prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <arch_helpers.h> 32 #include <assert.h> 33 #include <bl_common.h> 34 #include <context_mgmt.h> 35 #include <debug.h> 36 #include <psci.h> 37 #include <tlk.h> 38 39 #include "tlkd_private.h" 40 41 extern tlk_context_t tlk_ctx; 42 43 #define MPIDR_CPU0 0x80000000 44 45 /******************************************************************************* 46 * Return the type of payload TLKD is dealing with. Report the current 47 * resident cpu (mpidr format) if it is a UP/UP migratable payload. 48 ******************************************************************************/ 49 static int32_t cpu_migrate_info(uint64_t *resident_cpu) 50 { 51 /* the payload runs only on CPU0 */ 52 *resident_cpu = MPIDR_CPU0; 53 54 /* Uniprocessor, not migrate capable payload */ 55 return PSCI_TOS_NOT_UP_MIG_CAP; 56 } 57 58 /******************************************************************************* 59 * This cpu is being suspended. Inform TLK of the SYSTEM_SUSPEND event, so 60 * that it can pass this information to its Trusted Apps. 61 ******************************************************************************/ 62 static void cpu_suspend_handler(uint64_t suspend_level) 63 { 64 gp_regs_t *gp_regs; 65 int cpu = read_mpidr() & MPIDR_CPU_MASK; 66 int32_t rc = 0; 67 68 /* 69 * TLK runs only on CPU0 and suspends its Trusted Apps during 70 * SYSTEM_SUSPEND. It has no role to play during CPU_SUSPEND. 71 */ 72 if ((cpu != 0) || (suspend_level != PLAT_MAX_PWR_LVL)) 73 return; 74 75 /* pass system suspend event to TLK */ 76 gp_regs = get_gpregs_ctx(&tlk_ctx.cpu_ctx); 77 write_ctx_reg(gp_regs, CTX_GPREG_X0, TLK_SYSTEM_SUSPEND); 78 79 /* Program the entry point and enter TLK */ 80 rc = tlkd_synchronous_sp_entry(&tlk_ctx); 81 82 /* 83 * Read the response from TLK. A non-zero return means that 84 * something went wrong while communicating with it. 85 */ 86 if (rc != 0) 87 panic(); 88 } 89 90 /******************************************************************************* 91 * This cpu is being resumed. Inform TLK of the SYSTEM_SUSPEND exit, so 92 * that it can pass this information to its Trusted Apps. 93 ******************************************************************************/ 94 static void cpu_resume_handler(uint64_t suspend_level) 95 { 96 gp_regs_t *gp_regs; 97 int cpu = read_mpidr() & MPIDR_CPU_MASK; 98 int32_t rc = 0; 99 100 /* 101 * TLK runs only on CPU0 and resumes its Trusted Apps during 102 * SYSTEM_SUSPEND exit. It has no role to play during CPU_SUSPEND 103 * exit. 104 */ 105 if ((cpu != 0) || (suspend_level != PLAT_MAX_PWR_LVL)) 106 return; 107 108 /* pass system resume event to TLK */ 109 gp_regs = get_gpregs_ctx(&tlk_ctx.cpu_ctx); 110 write_ctx_reg(gp_regs, CTX_GPREG_X0, TLK_SYSTEM_RESUME); 111 112 /* Program the entry point and enter TLK */ 113 rc = tlkd_synchronous_sp_entry(&tlk_ctx); 114 115 /* 116 * Read the response from TLK. A non-zero return means that 117 * something went wrong while communicating with it. 118 */ 119 if (rc != 0) 120 panic(); 121 } 122 123 /******************************************************************************* 124 * System is about to be reset. Inform the SP to allow any book-keeping 125 ******************************************************************************/ 126 static void system_off_handler(void) 127 { 128 int cpu = read_mpidr() & MPIDR_CPU_MASK; 129 gp_regs_t *gp_regs; 130 131 /* TLK runs only on CPU0 */ 132 if (cpu != 0) 133 return; 134 135 /* pass system off/reset events to TLK */ 136 gp_regs = get_gpregs_ctx(&tlk_ctx.cpu_ctx); 137 write_ctx_reg(gp_regs, CTX_GPREG_X0, TLK_SYSTEM_OFF); 138 139 /* 140 * Enter the SP. We do not care about the return value because we 141 * must continue with the shutdown anyway. 142 */ 143 (void)tlkd_synchronous_sp_entry(&tlk_ctx); 144 } 145 146 /******************************************************************************* 147 * Structure populated by the Dispatcher to be given a chance to perform any 148 * bookkeeping before PSCI executes a power mgmt. operation. 149 ******************************************************************************/ 150 const spd_pm_ops_t tlkd_pm_ops = { 151 .svc_migrate_info = cpu_migrate_info, 152 .svc_suspend = cpu_suspend_handler, 153 .svc_suspend_finish = cpu_resume_handler, 154 .svc_system_off = system_off_handler, 155 .svc_system_reset = system_off_handler 156 }; 157