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