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