psci_common.c 35.9 KB
Newer Older
1
/*
Zelalem's avatar
Zelalem committed
2
 * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
3
 *
dp-arm's avatar
dp-arm committed
4
 * SPDX-License-Identifier: BSD-3-Clause
5
6
 */

7
8
9
#include <assert.h>
#include <string.h>

10
#include <arch.h>
11
#include <arch_helpers.h>
12
13
#include <common/bl_common.h>
#include <common/debug.h>
14
#include <context.h>
15
#include <drivers/delay_timer.h>
16
17
18
19
#include <lib/el3_runtime/context_mgmt.h>
#include <lib/utils.h>
#include <plat/common/platform.h>

20
#include "psci_private.h"
21

22
/*
23
24
 * SPD power management operations, expected to be supplied by the registered
 * SPD on successful SP initialization
25
 */
26
const spd_pm_ops_t *psci_spd_pm;
27

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/*
 * PSCI requested local power state map. This array is used to store the local
 * power states requested by a CPU for power levels from level 1 to
 * PLAT_MAX_PWR_LVL. It does not store the requested local power state for power
 * level 0 (PSCI_CPU_PWR_LVL) as the requested and the target power state for a
 * CPU are the same.
 *
 * During state coordination, the platform is passed an array containing the
 * local states requested for a particular non cpu power domain by each cpu
 * within the domain.
 *
 * TODO: Dense packing of the requested states will cause cache thrashing
 * when multiple power domains write to it. If we allocate the requested
 * states at each power level in a cache-line aligned per-domain memory,
 * the cache thrashing can be avoided.
 */
static plat_local_state_t
	psci_req_local_pwr_states[PLAT_MAX_PWR_LVL][PLATFORM_CORE_COUNT];

47
unsigned int psci_plat_core_count;
48

49
/*******************************************************************************
50
51
52
53
54
 * Arrays that hold the platform's power domain tree information for state
 * management of power domains.
 * Each node in the array 'psci_non_cpu_pd_nodes' corresponds to a power domain
 * which is an ancestor of a CPU power domain.
 * Each node in the array 'psci_cpu_pd_nodes' corresponds to a cpu power domain
55
 ******************************************************************************/
56
non_cpu_pd_node_t psci_non_cpu_pd_nodes[PSCI_NUM_NON_CPU_PWR_DOMAINS]
57
#if USE_COHERENT_MEM
58
__section("tzfw_coherent_mem")
59
60
#endif
;
61

62
63
/* Lock for PSCI state coordination */
DEFINE_PSCI_LOCK(psci_locks[PSCI_NUM_NON_CPU_PWR_DOMAINS]);
64

65
66
cpu_pd_node_t psci_cpu_pd_nodes[PLATFORM_CORE_COUNT];

67
68
69
/*******************************************************************************
 * Pointer to functions exported by the platform to complete power mgmt. ops
 ******************************************************************************/
70
const plat_psci_ops_t *psci_plat_pm_ops;
71

72
73
74
/******************************************************************************
 * Check that the maximum power level supported by the platform makes sense
 *****************************************************************************/
75
76
77
CASSERT((PLAT_MAX_PWR_LVL <= PSCI_MAX_PWR_LVL) &&
	(PLAT_MAX_PWR_LVL >= PSCI_CPU_PWR_LVL),
	assert_platform_max_pwrlvl_check);
78

79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/*
 * The plat_local_state used by the platform is one of these types: RUN,
 * RETENTION and OFF. The platform can define further sub-states for each type
 * apart from RUN. This categorization is done to verify the sanity of the
 * psci_power_state passed by the platform and to print debug information. The
 * categorization is done on the basis of the following conditions:
 *
 * 1. If (plat_local_state == 0) then the category is STATE_TYPE_RUN.
 *
 * 2. If (0 < plat_local_state <= PLAT_MAX_RET_STATE), then the category is
 *    STATE_TYPE_RETN.
 *
 * 3. If (plat_local_state > PLAT_MAX_RET_STATE), then the category is
 *    STATE_TYPE_OFF.
 */
typedef enum plat_local_state_type {
	STATE_TYPE_RUN = 0,
	STATE_TYPE_RETN,
	STATE_TYPE_OFF
} plat_local_state_type_t;

100
101
102
103
104
105
106
107
108
109
110
111
112
/* Function used to categorize plat_local_state. */
static plat_local_state_type_t find_local_state_type(plat_local_state_t state)
{
	if (state != 0U) {
		if (state > PLAT_MAX_RET_STATE) {
			return STATE_TYPE_OFF;
		} else {
			return STATE_TYPE_RETN;
		}
	} else {
		return STATE_TYPE_RUN;
	}
}
113
114
115
116
117

/******************************************************************************
 * Check that the maximum retention level supported by the platform is less
 * than the maximum off level.
 *****************************************************************************/
118
CASSERT(PLAT_MAX_RET_STATE < PLAT_MAX_OFF_STATE,
119
120
121
122
123
124
125
126
		assert_platform_max_off_and_retn_state_check);

/******************************************************************************
 * This function ensures that the power state parameter in a CPU_SUSPEND request
 * is valid. If so, it returns the requested states for each power level.
 *****************************************************************************/
int psci_validate_power_state(unsigned int power_state,
			      psci_power_state_t *state_info)
127
{
128
	/* Check SBZ bits in power state are zero */
129
	if (psci_check_power_state(power_state) != 0U)
130
		return PSCI_E_INVALID_PARAMS;
131

132
	assert(psci_plat_pm_ops->validate_power_state != NULL);
133

134
135
136
137
138
139
140
141
142
143
144
145
146
147
	/* Validate the power_state using platform pm_ops */
	return psci_plat_pm_ops->validate_power_state(power_state, state_info);
}

/******************************************************************************
 * This function retrieves the `psci_power_state_t` for system suspend from
 * the platform.
 *****************************************************************************/
void psci_query_sys_suspend_pwrstate(psci_power_state_t *state_info)
{
	/*
	 * Assert that the required pm_ops hook is implemented to ensure that
	 * the capability detected during psci_setup() is valid.
	 */
148
	assert(psci_plat_pm_ops->get_sys_suspend_power_state != NULL);
149

150
151
152
153
	/*
	 * Query the platform for the power_state required for system suspend
	 */
	psci_plat_pm_ops->get_sys_suspend_power_state(state_info);
154
155
}

156
157
158
159
160
161
162
163
/*******************************************************************************
 * This function verifies that the all the other cores in the system have been
 * turned OFF and the current CPU is the last running CPU in the system.
 * Returns 1 (true) if the current CPU is the last ON CPU or 0 (false)
 * otherwise.
 ******************************************************************************/
unsigned int psci_is_last_on_cpu(void)
{
164
	unsigned int cpu_idx, my_idx = plat_my_core_pos();
165

166
	for (cpu_idx = 0; cpu_idx < psci_plat_core_count;
167
			cpu_idx++) {
168
169
		if (cpu_idx == my_idx) {
			assert(psci_get_aff_info_state() == AFF_STATE_ON);
170
171
172
			continue;
		}

173
		if (psci_get_aff_info_state_by_idx(cpu_idx) != AFF_STATE_OFF)
174
175
176
177
178
179
			return 0;
	}

	return 1;
}

180
/*******************************************************************************
181
182
183
 * Routine to return the maximum power level to traverse to after a cpu has
 * been physically powered up. It is expected to be called immediately after
 * reset from assembler code.
184
 ******************************************************************************/
185
static unsigned int get_power_on_target_pwrlvl(void)
186
{
187
	unsigned int pwrlvl;
188
189

	/*
190
191
192
193
	 * Assume that this cpu was suspended and retrieve its target power
	 * level. If it is invalid then it could only have been turned off
	 * earlier. PLAT_MAX_PWR_LVL will be the highest power level a
	 * cpu can be turned off to.
194
	 */
195
	pwrlvl = psci_get_suspend_pwrlvl();
196
	if (pwrlvl == PSCI_INVALID_PWR_LVL)
197
		pwrlvl = PLAT_MAX_PWR_LVL;
198
	assert(pwrlvl < PSCI_INVALID_PWR_LVL);
199
	return pwrlvl;
200
201
}

202
203
204
/******************************************************************************
 * Helper function to update the requested local power state array. This array
 * does not store the requested state for the CPU power level. Hence an
205
 * assertion is added to prevent us from accessing the CPU power level.
206
207
208
209
 *****************************************************************************/
static void psci_set_req_local_pwr_state(unsigned int pwrlvl,
					 unsigned int cpu_idx,
					 plat_local_state_t req_pwr_state)
210
{
211
	assert(pwrlvl > PSCI_CPU_PWR_LVL);
212
	if ((pwrlvl > PSCI_CPU_PWR_LVL) && (pwrlvl <= PLAT_MAX_PWR_LVL) &&
213
			(cpu_idx < psci_plat_core_count)) {
214
215
		psci_req_local_pwr_states[pwrlvl - 1U][cpu_idx] = req_pwr_state;
	}
216
217
}

218
219
220
/******************************************************************************
 * This function initializes the psci_req_local_pwr_states.
 *****************************************************************************/
221
void __init psci_init_req_local_pwr_states(void)
222
{
223
	/* Initialize the requested state of all non CPU power domains as OFF */
224
	unsigned int pwrlvl;
225
	unsigned int core;
226
227

	for (pwrlvl = 0U; pwrlvl < PLAT_MAX_PWR_LVL; pwrlvl++) {
228
		for (core = 0; core < psci_plat_core_count; core++) {
229
230
231
232
			psci_req_local_pwr_states[pwrlvl][core] =
				PLAT_MAX_OFF_STATE;
		}
	}
233
}
234

235
236
237
238
239
240
241
242
/******************************************************************************
 * Helper function to return a reference to an array containing the local power
 * states requested by each cpu for a power domain at 'pwrlvl'. The size of the
 * array will be the number of cpu power domains of which this power domain is
 * an ancestor. These requested states will be used to determine a suitable
 * target state for this power domain during psci state coordination. An
 * assertion is added to prevent us from accessing the CPU power level.
 *****************************************************************************/
243
static plat_local_state_t *psci_get_req_local_pwr_states(unsigned int pwrlvl,
244
							 unsigned int cpu_idx)
245
246
{
	assert(pwrlvl > PSCI_CPU_PWR_LVL);
247

248
	if ((pwrlvl > PSCI_CPU_PWR_LVL) && (pwrlvl <= PLAT_MAX_PWR_LVL) &&
249
			(cpu_idx < psci_plat_core_count)) {
250
251
252
		return &psci_req_local_pwr_states[pwrlvl - 1U][cpu_idx];
	} else
		return NULL;
253
}
254

255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
/*
 * psci_non_cpu_pd_nodes can be placed either in normal memory or coherent
 * memory.
 *
 * With !USE_COHERENT_MEM, psci_non_cpu_pd_nodes is placed in normal memory,
 * it's accessed by both cached and non-cached participants. To serve the common
 * minimum, perform a cache flush before read and after write so that non-cached
 * participants operate on latest data in main memory.
 *
 * When USE_COHERENT_MEM is used, psci_non_cpu_pd_nodes is placed in coherent
 * memory. With HW_ASSISTED_COHERENCY, all PSCI participants are cache-coherent.
 * In both cases, no cache operations are required.
 */

/*
 * Retrieve local state of non-CPU power domain node from a non-cached CPU,
 * after any required cache maintenance operation.
 */
static plat_local_state_t get_non_cpu_pd_node_local_state(
		unsigned int parent_idx)
{
276
#if !(USE_COHERENT_MEM || HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY)
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
	flush_dcache_range(
			(uintptr_t) &psci_non_cpu_pd_nodes[parent_idx],
			sizeof(psci_non_cpu_pd_nodes[parent_idx]));
#endif
	return psci_non_cpu_pd_nodes[parent_idx].local_state;
}

/*
 * Update local state of non-CPU power domain node from a cached CPU; perform
 * any required cache maintenance operation afterwards.
 */
static void set_non_cpu_pd_node_local_state(unsigned int parent_idx,
		plat_local_state_t state)
{
	psci_non_cpu_pd_nodes[parent_idx].local_state = state;
292
#if !(USE_COHERENT_MEM || HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY)
293
294
295
296
297
298
	flush_dcache_range(
			(uintptr_t) &psci_non_cpu_pd_nodes[parent_idx],
			sizeof(psci_non_cpu_pd_nodes[parent_idx]));
#endif
}

299
300
301
302
303
304
/******************************************************************************
 * Helper function to return the current local power state of each power domain
 * from the current cpu power domain to its ancestor at the 'end_pwrlvl'. This
 * function will be called after a cpu is powered on to find the local state
 * each power domain has emerged from.
 *****************************************************************************/
305
306
void psci_get_target_local_pwr_states(unsigned int end_pwrlvl,
				      psci_power_state_t *target_state)
307
{
308
	unsigned int parent_idx, lvl;
309
310
311
312
313
314
	plat_local_state_t *pd_state = target_state->pwr_domain_state;

	pd_state[PSCI_CPU_PWR_LVL] = psci_get_cpu_local_state();
	parent_idx = psci_cpu_pd_nodes[plat_my_core_pos()].parent_node;

	/* Copy the local power state from node to state_info */
315
	for (lvl = PSCI_CPU_PWR_LVL + 1U; lvl <= end_pwrlvl; lvl++) {
316
		pd_state[lvl] = get_non_cpu_pd_node_local_state(parent_idx);
317
318
319
320
321
322
323
324
325
326
327
328
329
330
		parent_idx = psci_non_cpu_pd_nodes[parent_idx].parent_node;
	}

	/* Set the the higher levels to RUN */
	for (; lvl <= PLAT_MAX_PWR_LVL; lvl++)
		target_state->pwr_domain_state[lvl] = PSCI_LOCAL_STATE_RUN;
}

/******************************************************************************
 * Helper function to set the target local power state that each power domain
 * from the current cpu power domain to its ancestor at the 'end_pwrlvl' will
 * enter. This function will be called after coordination of requested power
 * states has been done for each power level.
 *****************************************************************************/
331
static void psci_set_target_local_pwr_states(unsigned int end_pwrlvl,
332
333
					const psci_power_state_t *target_state)
{
334
	unsigned int parent_idx, lvl;
335
336
337
	const plat_local_state_t *pd_state = target_state->pwr_domain_state;

	psci_set_cpu_local_state(pd_state[PSCI_CPU_PWR_LVL]);
338

339
	/*
340
	 * Need to flush as local_state might be accessed with Data Cache
341
	 * disabled during power on
342
	 */
343
	psci_flush_cpu_data(psci_svc_cpu_data.local_state);
344
345
346
347

	parent_idx = psci_cpu_pd_nodes[plat_my_core_pos()].parent_node;

	/* Copy the local_state from state_info */
348
	for (lvl = 1U; lvl <= end_pwrlvl; lvl++) {
349
		set_non_cpu_pd_node_local_state(parent_idx, pd_state[lvl]);
350
351
		parent_idx = psci_non_cpu_pd_nodes[parent_idx].parent_node;
	}
352
353
}

354

355
/*******************************************************************************
356
 * PSCI helper function to get the parent nodes corresponding to a cpu_index.
357
 ******************************************************************************/
358
void psci_get_parent_pwr_domain_nodes(unsigned int cpu_idx,
359
				      unsigned int end_lvl,
360
				      unsigned int *node_index)
361
362
{
	unsigned int parent_node = psci_cpu_pd_nodes[cpu_idx].parent_node;
363
	unsigned int i;
364
	unsigned int *node = node_index;
365

366
367
368
	for (i = PSCI_CPU_PWR_LVL + 1U; i <= end_lvl; i++) {
		*node = parent_node;
		node++;
369
370
371
372
373
374
375
376
377
		parent_node = psci_non_cpu_pd_nodes[parent_node].parent_node;
	}
}

/******************************************************************************
 * This function is invoked post CPU power up and initialization. It sets the
 * affinity info state, target power state and requested power state for the
 * current CPU and all its ancestor power domains to RUN.
 *****************************************************************************/
378
void psci_set_pwr_domains_to_run(unsigned int end_pwrlvl)
379
{
380
	unsigned int parent_idx, cpu_idx = plat_my_core_pos(), lvl;
381
382
383
	parent_idx = psci_cpu_pd_nodes[cpu_idx].parent_node;

	/* Reset the local_state to RUN for the non cpu power domains. */
384
	for (lvl = PSCI_CPU_PWR_LVL + 1U; lvl <= end_pwrlvl; lvl++) {
385
386
		set_non_cpu_pd_node_local_state(parent_idx,
				PSCI_LOCAL_STATE_RUN);
387
388
389
390
391
392
393
394
395
396
		psci_set_req_local_pwr_state(lvl,
					     cpu_idx,
					     PSCI_LOCAL_STATE_RUN);
		parent_idx = psci_non_cpu_pd_nodes[parent_idx].parent_node;
	}

	/* Set the affinity info state to ON */
	psci_set_aff_info_state(AFF_STATE_ON);

	psci_set_cpu_local_state(PSCI_LOCAL_STATE_RUN);
397
	psci_flush_cpu_data(psci_svc_cpu_data);
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
}

/******************************************************************************
 * This function is passed the local power states requested for each power
 * domain (state_info) between the current CPU domain and its ancestors until
 * the target power level (end_pwrlvl). It updates the array of requested power
 * states with this information.
 *
 * Then, for each level (apart from the CPU level) until the 'end_pwrlvl', it
 * retrieves the states requested by all the cpus of which the power domain at
 * that level is an ancestor. It passes this information to the platform to
 * coordinate and return the target power state. If the target state for a level
 * is RUN then subsequent levels are not considered. At the CPU level, state
 * coordination is not required. Hence, the requested and the target states are
 * the same.
 *
 * The 'state_info' is updated with the target state for each level between the
 * CPU and the 'end_pwrlvl' and returned to the caller.
 *
 * This function will only be invoked with data cache enabled and while
 * powering down a core.
 *****************************************************************************/
420
421
void psci_do_state_coordination(unsigned int end_pwrlvl,
				psci_power_state_t *state_info)
422
{
423
	unsigned int lvl, parent_idx, cpu_idx = plat_my_core_pos();
424
	unsigned int start_idx;
425
	unsigned int ncpus;
426
427
	plat_local_state_t target_state, *req_states;

428
	assert(end_pwrlvl <= PLAT_MAX_PWR_LVL);
429
	parent_idx = psci_cpu_pd_nodes[cpu_idx].parent_node;
430

431
432
	/* For level 0, the requested state will be equivalent
	   to target state */
433
	for (lvl = PSCI_CPU_PWR_LVL + 1U; lvl <= end_pwrlvl; lvl++) {
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454

		/* First update the requested power state */
		psci_set_req_local_pwr_state(lvl, cpu_idx,
					     state_info->pwr_domain_state[lvl]);

		/* Get the requested power states for this power level */
		start_idx = psci_non_cpu_pd_nodes[parent_idx].cpu_start_idx;
		req_states = psci_get_req_local_pwr_states(lvl, start_idx);

		/*
		 * Let the platform coordinate amongst the requested states at
		 * this power level and return the target local power state.
		 */
		ncpus = psci_non_cpu_pd_nodes[parent_idx].ncpus;
		target_state = plat_get_target_pwr_state(lvl,
							 req_states,
							 ncpus);

		state_info->pwr_domain_state[lvl] = target_state;

		/* Break early if the negotiated target power state is RUN */
455
		if (is_local_state_run(state_info->pwr_domain_state[lvl]) != 0)
456
457
458
459
			break;

		parent_idx = psci_non_cpu_pd_nodes[parent_idx].parent_node;
	}
460
461

	/*
462
463
464
465
	 * This is for cases when we break out of the above loop early because
	 * the target power state is RUN at a power level < end_pwlvl.
	 * We update the requested power state from state_info and then
	 * set the target state as RUN.
466
	 */
467
	for (lvl = lvl + 1U; lvl <= end_pwrlvl; lvl++) {
468
469
470
		psci_set_req_local_pwr_state(lvl, cpu_idx,
					     state_info->pwr_domain_state[lvl]);
		state_info->pwr_domain_state[lvl] = PSCI_LOCAL_STATE_RUN;
471

472
	}
473

474
475
	/* Update the target state in the power domain nodes */
	psci_set_target_local_pwr_states(end_pwrlvl, state_info);
476
477
}

478
479
480
481
482
483
484
485
486
487
488
489
490
/******************************************************************************
 * This function validates a suspend request by making sure that if a standby
 * state is requested then no power level is turned off and the highest power
 * level is placed in a standby/retention state.
 *
 * It also ensures that the state level X will enter is not shallower than the
 * state level X + 1 will enter.
 *
 * This validation will be enabled only for DEBUG builds as the platform is
 * expected to perform these validations as well.
 *****************************************************************************/
int psci_validate_suspend_req(const psci_power_state_t *state_info,
			      unsigned int is_power_down_state)
491
{
492
493
494
495
496
497
498
	unsigned int max_off_lvl, target_lvl, max_retn_lvl;
	plat_local_state_t state;
	plat_local_state_type_t req_state_type, deepest_state_type;
	int i;

	/* Find the target suspend power level */
	target_lvl = psci_find_target_suspend_lvl(state_info);
499
	if (target_lvl == PSCI_INVALID_PWR_LVL)
500
501
		return PSCI_E_INVALID_PARAMS;

502
503
	/* All power domain levels are in a RUN state to begin with */
	deepest_state_type = STATE_TYPE_RUN;
504

505
	for (i = (int) target_lvl; i >= (int) PSCI_CPU_PWR_LVL; i--) {
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
		state = state_info->pwr_domain_state[i];
		req_state_type = find_local_state_type(state);

		/*
		 * While traversing from the highest power level to the lowest,
		 * the state requested for lower levels has to be the same or
		 * deeper i.e. equal to or greater than the state at the higher
		 * levels. If this condition is true, then the requested state
		 * becomes the deepest state encountered so far.
		 */
		if (req_state_type < deepest_state_type)
			return PSCI_E_INVALID_PARAMS;
		deepest_state_type = req_state_type;
	}

	/* Find the highest off power level */
	max_off_lvl = psci_find_max_off_lvl(state_info);

	/* The target_lvl is either equal to the max_off_lvl or max_retn_lvl */
525
	max_retn_lvl = PSCI_INVALID_PWR_LVL;
526
527
528
529
530
531
532
533
	if (target_lvl != max_off_lvl)
		max_retn_lvl = target_lvl;

	/*
	 * If this is not a request for a power down state then max off level
	 * has to be invalid and max retention level has to be a valid power
	 * level.
	 */
534
535
536
	if ((is_power_down_state == 0U) &&
			((max_off_lvl != PSCI_INVALID_PWR_LVL) ||
			 (max_retn_lvl == PSCI_INVALID_PWR_LVL)))
537
538
539
540
541
		return PSCI_E_INVALID_PARAMS;

	return PSCI_E_SUCCESS;
}

542
543
544
545
546
/******************************************************************************
 * This function finds the highest power level which will be powered down
 * amongst all the power levels specified in the 'state_info' structure
 *****************************************************************************/
unsigned int psci_find_max_off_lvl(const psci_power_state_t *state_info)
547
{
548
	int i;
549

550
551
552
	for (i = (int) PLAT_MAX_PWR_LVL; i >= (int) PSCI_CPU_PWR_LVL; i--) {
		if (is_local_state_off(state_info->pwr_domain_state[i]) != 0)
			return (unsigned int) i;
553
554
	}

555
	return PSCI_INVALID_PWR_LVL;
556
557
558
559
560
561
562
563
564
565
}

/******************************************************************************
 * This functions finds the level of the highest power domain which will be
 * placed in a low power state during a suspend operation.
 *****************************************************************************/
unsigned int psci_find_target_suspend_lvl(const psci_power_state_t *state_info)
{
	int i;

566
567
568
	for (i = (int) PLAT_MAX_PWR_LVL; i >= (int) PSCI_CPU_PWR_LVL; i--) {
		if (is_local_state_run(state_info->pwr_domain_state[i]) == 0)
			return (unsigned int) i;
569
	}
570

571
	return PSCI_INVALID_PWR_LVL;
572
573
}

574
/*******************************************************************************
575
576
577
578
 * This function is passed the highest level in the topology tree that the
 * operation should be applied to and a list of node indexes. It picks up locks
 * from the node index list in order of increasing power domain level in the
 * range specified.
579
 ******************************************************************************/
580
581
void psci_acquire_pwr_domain_locks(unsigned int end_pwrlvl,
				   const unsigned int *parent_nodes)
582
{
583
	unsigned int parent_idx;
584
	unsigned int level;
585

586
	/* No locking required for level 0. Hence start locking from level 1 */
587
	for (level = PSCI_CPU_PWR_LVL + 1U; level <= end_pwrlvl; level++) {
588
		parent_idx = parent_nodes[level - 1U];
589
		psci_lock_get(&psci_non_cpu_pd_nodes[parent_idx]);
590
591
592
593
	}
}

/*******************************************************************************
594
595
596
 * This function is passed the highest level in the topology tree that the
 * operation should be applied to and a list of node indexes. It releases the
 * locks in order of decreasing power domain level in the range specified.
597
 ******************************************************************************/
598
599
void psci_release_pwr_domain_locks(unsigned int end_pwrlvl,
				   const unsigned int *parent_nodes)
600
{
601
	unsigned int parent_idx;
602
	unsigned int level;
603

604
	/* Unlock top down. No unlocking required for level 0. */
Zelalem's avatar
Zelalem committed
605
	for (level = end_pwrlvl; level >= (PSCI_CPU_PWR_LVL + 1U); level--) {
606
		parent_idx = parent_nodes[level - 1U];
607
		psci_lock_release(&psci_non_cpu_pd_nodes[parent_idx]);
608
609
610
	}
}

611
/*******************************************************************************
612
 * Simple routine to determine whether a mpidr is valid or not.
613
 ******************************************************************************/
614
int psci_validate_mpidr(u_register_t mpidr)
615
{
616
	if (plat_core_pos_by_mpidr(mpidr) < 0)
617
		return PSCI_E_INVALID_PARAMS;
618
619

	return PSCI_E_SUCCESS;
620
621
622
}

/*******************************************************************************
623
 * This function determines the full entrypoint information for the requested
624
 * PSCI entrypoint on power on/resume and returns it.
625
 ******************************************************************************/
626
#ifdef __aarch64__
627
static int psci_get_ns_ep_info(entry_point_info_t *ep,
628
629
			       uintptr_t entrypoint,
			       u_register_t context_id)
630
{
631
	u_register_t ep_attr, sctlr;
632
	unsigned int daif, ee, mode;
633
634
	u_register_t ns_scr_el3 = read_scr_el3();
	u_register_t ns_sctlr_el1 = read_sctlr_el1();
635

636
637
	sctlr = ((ns_scr_el3 & SCR_HCE_BIT) != 0U) ?
		read_sctlr_el2() : ns_sctlr_el1;
638
	ee = 0;
639

640
	ep_attr = NON_SECURE | EP_ST_DISABLE;
641
	if ((sctlr & SCTLR_EE_BIT) != 0U) {
642
643
644
		ep_attr |= EP_EE_BIG;
		ee = 1;
	}
645
	SET_PARAM_HEAD(ep, PARAM_EP, VERSION_1, ep_attr);
646

647
	ep->pc = entrypoint;
648
	zeromem(&ep->args, sizeof(ep->args));
649
	ep->args.arg0 = context_id;
650
651
652
653
654

	/*
	 * Figure out whether the cpu enters the non-secure address space
	 * in aarch32 or aarch64
	 */
655
	if ((ns_scr_el3 & SCR_RW_BIT) != 0U) {
656
657
658
659
660

		/*
		 * Check whether a Thumb entry point has been provided for an
		 * aarch64 EL
		 */
661
		if ((entrypoint & 0x1UL) != 0UL)
662
			return PSCI_E_INVALID_ADDRESS;
663

664
		mode = ((ns_scr_el3 & SCR_HCE_BIT) != 0U) ? MODE_EL2 : MODE_EL1;
665

666
		ep->spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
667
668
	} else {

669
670
		mode = ((ns_scr_el3 & SCR_HCE_BIT) != 0U) ?
			MODE32_hyp : MODE32_svc;
671
672
673
674
675

		/*
		 * TODO: Choose async. exception bits if HYP mode is not
		 * implemented according to the values of SCR.{AW, FW} bits
		 */
676
677
		daif = DAIF_ABT_BIT | DAIF_IRQ_BIT | DAIF_FIQ_BIT;

678
		ep->spsr = SPSR_MODE32(mode, entrypoint & 0x1, ee, daif);
679
680
	}

681
	return PSCI_E_SUCCESS;
682
}
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
#else /* !__aarch64__ */
static int psci_get_ns_ep_info(entry_point_info_t *ep,
			       uintptr_t entrypoint,
			       u_register_t context_id)
{
	u_register_t ep_attr;
	unsigned int aif, ee, mode;
	u_register_t scr = read_scr();
	u_register_t ns_sctlr, sctlr;

	/* Switch to non secure state */
	write_scr(scr | SCR_NS_BIT);
	isb();
	ns_sctlr = read_sctlr();

	sctlr = scr & SCR_HCE_BIT ? read_hsctlr() : ns_sctlr;

	/* Return to original state */
	write_scr(scr);
	isb();
	ee = 0;

	ep_attr = NON_SECURE | EP_ST_DISABLE;
	if (sctlr & SCTLR_EE_BIT) {
		ep_attr |= EP_EE_BIG;
		ee = 1;
	}
	SET_PARAM_HEAD(ep, PARAM_EP, VERSION_1, ep_attr);

	ep->pc = entrypoint;
	zeromem(&ep->args, sizeof(ep->args));
	ep->args.arg0 = context_id;

	mode = scr & SCR_HCE_BIT ? MODE32_hyp : MODE32_svc;

	/*
	 * TODO: Choose async. exception bits if HYP mode is not
	 * implemented according to the values of SCR.{AW, FW} bits
	 */
	aif = SPSR_ABT_BIT | SPSR_IRQ_BIT | SPSR_FIQ_BIT;

	ep->spsr = SPSR_MODE32(mode, entrypoint & 0x1, ee, aif);

	return PSCI_E_SUCCESS;
}

#endif /* __aarch64__ */
730

731
732
733
734
735
736
/*******************************************************************************
 * This function validates the entrypoint with the platform layer if the
 * appropriate pm_ops hook is exported by the platform and returns the
 * 'entry_point_info'.
 ******************************************************************************/
int psci_validate_entry_point(entry_point_info_t *ep,
737
738
			      uintptr_t entrypoint,
			      u_register_t context_id)
739
740
741
742
{
	int rc;

	/* Validate the entrypoint using platform psci_ops */
743
	if (psci_plat_pm_ops->validate_ns_entrypoint != NULL) {
744
745
746
747
748
749
750
751
752
753
754
755
756
757
		rc = psci_plat_pm_ops->validate_ns_entrypoint(entrypoint);
		if (rc != PSCI_E_SUCCESS)
			return PSCI_E_INVALID_ADDRESS;
	}

	/*
	 * Verify and derive the re-entry information for
	 * the non-secure world from the non-secure state from
	 * where this call originated.
	 */
	rc = psci_get_ns_ep_info(ep, entrypoint, context_id);
	return rc;
}

758
759
/*******************************************************************************
 * Generic handler which is called when a cpu is physically powered on. It
760
761
762
763
764
765
 * traverses the node information and finds the highest power level powered
 * off and performs generic, architectural, platform setup and state management
 * to power on that power level and power levels below it.
 * e.g. For a cpu that's been powered on, it will call the platform specific
 * code to enable the gic cpu interface and for a cluster it will enable
 * coherency at the interconnect level in addition to gic cpu interface.
766
 ******************************************************************************/
Soby Mathew's avatar
Soby Mathew committed
767
void psci_warmboot_entrypoint(void)
768
{
769
	unsigned int end_pwrlvl;
770
	unsigned int cpu_idx = plat_my_core_pos();
771
	unsigned int parent_nodes[PLAT_MAX_PWR_LVL] = {0};
772
	psci_power_state_t state_info = { {PSCI_LOCAL_STATE_RUN} };
773
774

	/*
775
776
	 * Verify that we have been explicitly turned ON or resumed from
	 * suspend.
777
	 */
778
	if (psci_get_aff_info_state() == AFF_STATE_OFF) {
Andrew Walbran's avatar
Andrew Walbran committed
779
		ERROR("Unexpected affinity info state.\n");
780
		panic();
781
	}
782
783

	/*
784
785
	 * Get the maximum power domain level to traverse to after this cpu
	 * has been physically powered up.
786
	 */
787
	end_pwrlvl = get_power_on_target_pwrlvl();
788

789
790
791
	/* Get the parent nodes */
	psci_get_parent_pwr_domain_nodes(cpu_idx, end_pwrlvl, parent_nodes);

792
	/*
793
794
795
	 * This function acquires the lock corresponding to each power level so
	 * that by the time all locks are taken, the system topology is snapshot
	 * and state management can be done safely.
796
	 */
797
	psci_acquire_pwr_domain_locks(end_pwrlvl, parent_nodes);
798

799
800
	psci_get_target_local_pwr_states(end_pwrlvl, &state_info);

801
#if ENABLE_PSCI_STAT
802
	plat_psci_stat_accounting_stop(&state_info);
803
804
#endif

805
	/*
806
807
808
809
810
811
812
813
814
815
	 * This CPU could be resuming from suspend or it could have just been
	 * turned on. To distinguish between these 2 cases, we examine the
	 * affinity state of the CPU:
	 *  - If the affinity state is ON_PENDING then it has just been
	 *    turned on.
	 *  - Else it is resuming from suspend.
	 *
	 * Depending on the type of warm reset identified, choose the right set
	 * of power management handler and perform the generic, architecture
	 * and platform specific handling.
816
	 */
817
818
819
820
	if (psci_get_aff_info_state() == AFF_STATE_ON_PENDING)
		psci_cpu_on_finish(cpu_idx, &state_info);
	else
		psci_cpu_suspend_finish(cpu_idx, &state_info);
821

822
	/*
823
824
	 * Set the requested and target state of this CPU and all the higher
	 * power domains which are ancestors of this CPU to run.
825
	 */
826
	psci_set_pwr_domains_to_run(end_pwrlvl);
827

828
829
830
831
832
833
834
#if ENABLE_PSCI_STAT
	/*
	 * Update PSCI stats.
	 * Caches are off when writing stats data on the power down path.
	 * Since caches are now enabled, it's necessary to do cache
	 * maintenance before reading that same data.
	 */
835
	psci_stats_update_pwr_up(end_pwrlvl, &state_info);
836
837
#endif

838
	/*
839
	 * This loop releases the lock corresponding to each power level
840
841
	 * in the reverse order to which they were acquired.
	 */
842
	psci_release_pwr_domain_locks(end_pwrlvl, parent_nodes);
843
}
844
845
846
847
848
849

/*******************************************************************************
 * This function initializes the set of hooks that PSCI invokes as part of power
 * management operation. The power management hooks are expected to be provided
 * by the SPD, after it finishes all its initialization
 ******************************************************************************/
850
void psci_register_spd_pm_hook(const spd_pm_ops_t *pm)
851
{
852
	assert(pm != NULL);
853
	psci_spd_pm = pm;
Soby Mathew's avatar
Soby Mathew committed
854

855
	if (pm->svc_migrate != NULL)
Soby Mathew's avatar
Soby Mathew committed
856
857
		psci_caps |= define_psci_cap(PSCI_MIG_AARCH64);

858
	if (pm->svc_migrate_info != NULL)
Soby Mathew's avatar
Soby Mathew committed
859
860
		psci_caps |= define_psci_cap(PSCI_MIG_INFO_UP_CPU_AARCH64)
				| define_psci_cap(PSCI_MIG_INFO_TYPE);
861
}
862

Soby Mathew's avatar
Soby Mathew committed
863
864
865
866
867
868
869
/*******************************************************************************
 * This function invokes the migrate info hook in the spd_pm_ops. It performs
 * the necessary return value validation. If the Secure Payload is UP and
 * migrate capable, it returns the mpidr of the CPU on which the Secure payload
 * is resident through the mpidr parameter. Else the value of the parameter on
 * return is undefined.
 ******************************************************************************/
870
int psci_spd_migrate_info(u_register_t *mpidr)
Soby Mathew's avatar
Soby Mathew committed
871
872
873
{
	int rc;

874
	if ((psci_spd_pm == NULL) || (psci_spd_pm->svc_migrate_info == NULL))
Soby Mathew's avatar
Soby Mathew committed
875
876
877
878
		return PSCI_E_NOT_SUPPORTED;

	rc = psci_spd_pm->svc_migrate_info(mpidr);

879
880
	assert((rc == PSCI_TOS_UP_MIG_CAP) || (rc == PSCI_TOS_NOT_UP_MIG_CAP) ||
	       (rc == PSCI_TOS_NOT_PRESENT_MP) || (rc == PSCI_E_NOT_SUPPORTED));
Soby Mathew's avatar
Soby Mathew committed
881
882
883
884
885

	return rc;
}


886
/*******************************************************************************
887
 * This function prints the state of all power domains present in the
888
889
 * system
 ******************************************************************************/
890
void psci_print_power_domain_map(void)
891
892
{
#if LOG_LEVEL >= LOG_LEVEL_INFO
893
	unsigned int idx;
894
895
896
	plat_local_state_t state;
	plat_local_state_type_t state_type;

897
	/* This array maps to the PSCI_STATE_X definitions in psci.h */
Soby Mathew's avatar
Soby Mathew committed
898
	static const char * const psci_state_type_str[] = {
899
		"ON",
900
		"RETENTION",
901
902
903
		"OFF",
	};

904
	INFO("PSCI Power Domain Map:\n");
905
	for (idx = 0; idx < (PSCI_NUM_PWR_DOMAINS - psci_plat_core_count);
906
907
908
909
910
911
912
913
914
915
916
							idx++) {
		state_type = find_local_state_type(
				psci_non_cpu_pd_nodes[idx].local_state);
		INFO("  Domain Node : Level %u, parent_node %d,"
				" State %s (0x%x)\n",
				psci_non_cpu_pd_nodes[idx].level,
				psci_non_cpu_pd_nodes[idx].parent_node,
				psci_state_type_str[state_type],
				psci_non_cpu_pd_nodes[idx].local_state);
	}

917
	for (idx = 0; idx < psci_plat_core_count; idx++) {
918
919
		state = psci_get_cpu_local_state_by_idx(idx);
		state_type = find_local_state_type(state);
920
		INFO("  CPU Node : MPID 0x%llx, parent_node %d,"
921
				" State %s (0x%x)\n",
922
				(unsigned long long)psci_cpu_pd_nodes[idx].mpidr,
923
924
925
				psci_cpu_pd_nodes[idx].parent_node,
				psci_state_type_str[state_type],
				psci_get_cpu_local_state_by_idx(idx));
926
927
928
	}
#endif
}
929

930
931
932
933
934
935
936
937
938
/******************************************************************************
 * Return whether any secondaries were powered up with CPU_ON call. A CPU that
 * have ever been powered up would have set its MPDIR value to something other
 * than PSCI_INVALID_MPIDR. Note that MPDIR isn't reset back to
 * PSCI_INVALID_MPIDR when a CPU is powered down later, so the return value is
 * meaningful only when called on the primary CPU during early boot.
 *****************************************************************************/
int psci_secondaries_brought_up(void)
{
939
	unsigned int idx, n_valid = 0U;
940

941
	for (idx = 0U; idx < ARRAY_SIZE(psci_cpu_pd_nodes); idx++) {
942
943
944
945
		if (psci_cpu_pd_nodes[idx].mpidr != PSCI_INVALID_MPIDR)
			n_valid++;
	}

946
	assert(n_valid > 0U);
947

948
	return (n_valid > 1U) ? 1 : 0;
949
950
}

951
952
953
954
955
956
957
958
959
960
/*******************************************************************************
 * Initiate power down sequence, by calling power down operations registered for
 * this CPU.
 ******************************************************************************/
void psci_do_pwrdown_sequence(unsigned int power_level)
{
#if HW_ASSISTED_COHERENCY
	/*
	 * With hardware-assisted coherency, the CPU drivers only initiate the
	 * power down sequence, without performing cache-maintenance operations
961
	 * in software. Data caches enabled both before and after this call.
962
963
964
965
966
	 */
	prepare_cpu_pwr_dwn(power_level);
#else
	/*
	 * Without hardware-assisted coherency, the CPU drivers disable data
967
	 * caches, then perform cache-maintenance operations in software.
968
	 *
969
970
971
972
	 * This also calls prepare_cpu_pwr_dwn() to initiate power down
	 * sequence, but that function will return with data caches disabled.
	 * We must ensure that the stack memory is flushed out to memory before
	 * we start popping from it again.
973
974
975
976
	 */
	psci_do_pwrdown_cache_maintenance(power_level);
#endif
}
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022

/*******************************************************************************
 * This function invokes the callback 'stop_func()' with the 'mpidr' of each
 * online PE. Caller can pass suitable method to stop a remote core.
 *
 * 'wait_ms' is the timeout value in milliseconds for the other cores to
 * transition to power down state. Passing '0' makes it non-blocking.
 *
 * The function returns 'PSCI_E_DENIED' if some cores failed to stop within the
 * given timeout.
 ******************************************************************************/
int psci_stop_other_cores(unsigned int wait_ms,
				   void (*stop_func)(u_register_t mpidr))
{
	unsigned int idx, this_cpu_idx;

	this_cpu_idx = plat_my_core_pos();

	/* Invoke stop_func for each core */
	for (idx = 0U; idx < psci_plat_core_count; idx++) {
		/* skip current CPU */
		if (idx == this_cpu_idx) {
			continue;
		}

		/* Check if the CPU is ON */
		if (psci_get_aff_info_state_by_idx(idx) == AFF_STATE_ON) {
			(*stop_func)(psci_cpu_pd_nodes[idx].mpidr);
		}
	}

	/* Need to wait for other cores to shutdown */
	if (wait_ms != 0U) {
		while ((wait_ms-- != 0U) && (psci_is_last_on_cpu() != 0U)) {
			mdelay(1U);
		}

		if (psci_is_last_on_cpu() != 0U) {
			WARN("Failed to stop all cores!\n");
			psci_print_power_domain_map();
			return PSCI_E_DENIED;
		}
	}

	return PSCI_E_SUCCESS;
}