xref: /rk3399_ARM-atf/services/spd/tlkd/tlkd_pm.c (revision 09d40e0e08283a249e7dce0e106c07c5141f9b7e)
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