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