summaryrefslogtreecommitdiff
path: root/include/lib/power_management.h
blob: 15d80ae651ec23f40cf65bb01a24509987dc5435 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
/*
 * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of ARM nor the names of its contributors may be used
 * to endorse or promote products derived from this software without specific
 * prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef __POWER_MANAGEMENT_H__
#define __POWER_MANAGEMENT_H__

#include <platform_def.h>
#include <psci.h>
#include <spinlock.h>
#include <stdint.h>

/* Set of states of an affinity node as seen by the Test Framework */
typedef enum {
	TFTF_AFFINITY_STATE_OFF = 0,
	TFTF_AFFINITY_STATE_ON_PENDING,
	TFTF_AFFINITY_STATE_ON,
} tftf_affinity_info_t;

/* Structure for keeping track of CPU state */
typedef struct {
	tftf_affinity_info_t state;
	spinlock_t lock;
} __aligned(CACHE_WRITEBACK_GRANULE) tftf_cpu_state_t;

/*
 * Suspend information passed to the TFTF suspend helpers.
 */
typedef struct suspend_info {
	/* The power state parameter to be passed to PSCI_CPU_SUSPEND */
	unsigned int power_state;
	/* SMC function ID of the PSCI suspend call */
	unsigned int psci_api;
	/* Whether the system context needs to be saved and restored */
	unsigned int save_system_context;
} suspend_info_t;

/*
 * Power up a core.
 * This uses the PSCI CPU_ON API, which means it relies on the EL3 firmware's
 * runtime services capabilities.
 * The core will be boostrapped by the framework before handing it over
 * to the entry point specified as the 2nd argument.
 *
 *    target_cpu: MPID of the CPU to power up
 *    entrypoint: Address where the CPU will jump once the framework has
 *                initialised it
 *    context_id: Context identifier as defined by the PSCI specification
 *
 *    Return: Return code of the PSCI CPU_ON call
 *            (refer to the PSCI specification for details)
 */
int32_t tftf_cpu_on(uint64_t	target_cpu,
		    uint64_t	entrypoint,
		    uint64_t	context_id);

/*
 * Tries to power up a core.
 * This API is similar to tftf_cpu_on API with the difference being it
 * does a SMC call to EL3 firmware without checking the status of the
 * core with respect to the framework.
 *
 * A caller is expected to handle the return code given by the EL3 firmware.
 *
 *    target_cpu: MPID of the CPU to power up
 *    entrypoint: Address where the CPU will jump once the framework has
 *                initialised it
 *    context_id: Context identifier as defined by the PSCI specification
 *
 *    Return: Return code of the PSCI CPU_ON call
 *            (refer to the PSCI specification for details)
 */
int32_t tftf_try_cpu_on(uint64_t target_cpu,
			uint64_t entrypoint,
			uint64_t context_id);

/*
 * Power down the calling core.
 * This uses the PSCI CPU_OFF API, which means it relies on the EL3 firmware's
 * runtime services capabilities.
 *
 *    Return: This function does not return when successful.
 *            Otherwise, return the same error code as the PSCI CPU_OFF call
 *            (refer to the PSCI specification for details)
 */
int32_t tftf_cpu_off(void);

/*
 * It is an Api used to enter a suspend state. It does the following:
 * - Allocates space for saving architectural and non-architectural CPU state on
 *   stack
 * - Saves architecture state of the CPU in the space allocated which consists:
 *      a. Callee registers
 *      b. System control registers. ex: MMU, SCTLR_EL1
 * - Depending on the state of `save_system_context` flag in suspend_info
 *   saves the context of system peripherals like GIC, timer etc.
 * - Sets context ID to the base of the stack allocated for saving context
 * - Calls Secure Platform Firmware to enter suspend
 * - If suspend fails, It restores the callee registers
 *     power state: PSCI power state to be sent via SMC
 *     Returns: PSCI_E_SUCCESS or PSCI_E_INVALID_PARAMS
 *
 * Note: This api might not test all use cases, as the context ID and resume
 * entrypoint is in the control of the framework.
 */
int tftf_suspend(const suspend_info_t *info);


/* ----------------------------------------------------------------------------
 * The above APIs might not be suitable in all test scenarios.
 * A test case could want to bypass those APIs i.e. call the PSCI APIs
 * directly. In this case, it is the responsibility of the test case to preserve
 * the state of the framework. The below APIs are provided to this end.
 * ----------------------------------------------------------------------------
 */

/*
 * The 3 following functions are used to manipulate the reference count tracking
 * the number of CPUs participating in a test.
 */

/*
 * Increment the reference count.
 * Return the new, incremented value.
 */
unsigned int tftf_inc_ref_cnt(void);

/*
 * Decrement the reference count.
 * Return the new, decremented value.
 */
unsigned int tftf_dec_ref_cnt(void);

/* Return the current reference count value */
unsigned int tftf_get_ref_cnt(void);

/*
 * Set the calling CPU online/offline. This only adjusts the view of the core
 * from the framework's point of view, it doesn't actually power up/down the
 * core.
 */
void tftf_set_cpu_online(void);
void tftf_init_cpus_status_map(void);
void tftf_set_cpu_offline(void);

/*
 * Query the state of a core.
 *   Return: 1 if the core is online, 0 otherwise.
 */
unsigned int tftf_is_cpu_online(unsigned int mpid);

unsigned int tftf_is_core_pos_online(unsigned int core_pos);

/* TFTF Suspend helpers */
static inline int tftf_cpu_suspend(unsigned int pwr_state)
{
	suspend_info_t info = {
		.power_state = pwr_state,
		.save_system_context = 0,
		.psci_api = SMC_PSCI_CPU_SUSPEND_AARCH64,
	};

	return tftf_suspend(&info);
}

static inline int tftf_cpu_suspend_save_sys_ctx(unsigned int pwr_state)
{
	suspend_info_t info = {
		.power_state = pwr_state,
		.save_system_context = 1,
		.psci_api = SMC_PSCI_CPU_SUSPEND_AARCH64,
	};

	return tftf_suspend(&info);
}


static inline int tftf_system_suspend(void)
{
	suspend_info_t info = {
		.power_state = 0,
		.save_system_context = 1,
		.psci_api = SMC_PSCI_SYSTEM_SUSPEND64,
	};

	return tftf_suspend(&info);
}

#endif /* __POWER_MANAGEMENT_H__ */