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