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