xref: /rk3399_ARM-atf/services/std_svc/spmd/spmd_pm.c (revision f0d743dbcd43c4bc5972210a117c5c6d2a4b6d1b)
1b058f20aSOlivier Deprez /*
2b058f20aSOlivier Deprez  * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
3b058f20aSOlivier Deprez  *
4b058f20aSOlivier Deprez  * SPDX-License-Identifier: BSD-3-Clause
5b058f20aSOlivier Deprez  */
6b058f20aSOlivier Deprez 
7b058f20aSOlivier Deprez #include <assert.h>
8*f0d743dbSOlivier Deprez #include <errno.h>
9b058f20aSOlivier Deprez #include "spmd_private.h"
10b058f20aSOlivier Deprez 
11*f0d743dbSOlivier Deprez struct spmd_pm_secondary_ep_t {
12*f0d743dbSOlivier Deprez 	uintptr_t entry_point;
13*f0d743dbSOlivier Deprez 	uintptr_t context;
14*f0d743dbSOlivier Deprez 	bool locked;
15*f0d743dbSOlivier Deprez };
16*f0d743dbSOlivier Deprez 
17*f0d743dbSOlivier Deprez static struct spmd_pm_secondary_ep_t spmd_pm_secondary_ep[PLATFORM_CORE_COUNT];
18*f0d743dbSOlivier Deprez 
19*f0d743dbSOlivier Deprez /*******************************************************************************
20*f0d743dbSOlivier Deprez  * spmd_pm_secondary_core_set_ep
21*f0d743dbSOlivier Deprez  ******************************************************************************/
22*f0d743dbSOlivier Deprez int32_t spmd_pm_secondary_core_set_ep(uint64_t mpidr, uintptr_t entry_point,
23*f0d743dbSOlivier Deprez 				      uint64_t context)
24*f0d743dbSOlivier Deprez {
25*f0d743dbSOlivier Deprez 	int id = plat_core_pos_by_mpidr(mpidr);
26*f0d743dbSOlivier Deprez 
27*f0d743dbSOlivier Deprez 	if ((id < 0) || (id >= PLATFORM_CORE_COUNT)) {
28*f0d743dbSOlivier Deprez 		ERROR("%s inconsistent MPIDR (%llx)\n", __func__, mpidr);
29*f0d743dbSOlivier Deprez 		return -EINVAL;
30*f0d743dbSOlivier Deprez 	}
31*f0d743dbSOlivier Deprez 
32*f0d743dbSOlivier Deprez 	if (spmd_pm_secondary_ep[id].locked) {
33*f0d743dbSOlivier Deprez 		ERROR("%s entry locked (%llx)\n", __func__, mpidr);
34*f0d743dbSOlivier Deprez 		return -EINVAL;
35*f0d743dbSOlivier Deprez 	}
36*f0d743dbSOlivier Deprez 
37*f0d743dbSOlivier Deprez 	/*
38*f0d743dbSOlivier Deprez 	 * Check entry_point address is a PA within
39*f0d743dbSOlivier Deprez 	 * load_address <= entry_point < load_address + binary_size
40*f0d743dbSOlivier Deprez 	 */
41*f0d743dbSOlivier Deprez 	if (!spmd_check_address_in_binary_image(entry_point)) {
42*f0d743dbSOlivier Deprez 		ERROR("%s entry point is not within image boundaries (%llx)\n",
43*f0d743dbSOlivier Deprez 		      __func__, mpidr);
44*f0d743dbSOlivier Deprez 		return -EINVAL;
45*f0d743dbSOlivier Deprez 	}
46*f0d743dbSOlivier Deprez 
47*f0d743dbSOlivier Deprez 	/* Fill new entry to corresponding secondary core id and lock it */
48*f0d743dbSOlivier Deprez 	spmd_pm_secondary_ep[id].entry_point = entry_point;
49*f0d743dbSOlivier Deprez 	spmd_pm_secondary_ep[id].context = context;
50*f0d743dbSOlivier Deprez 	spmd_pm_secondary_ep[id].locked = true;
51*f0d743dbSOlivier Deprez 
52*f0d743dbSOlivier Deprez 	VERBOSE("%s %d %llx %lx %llx\n",
53*f0d743dbSOlivier Deprez 		__func__, id, mpidr, entry_point, context);
54*f0d743dbSOlivier Deprez 
55*f0d743dbSOlivier Deprez 	return 0;
56*f0d743dbSOlivier Deprez }
57*f0d743dbSOlivier Deprez 
58b058f20aSOlivier Deprez /*******************************************************************************
59b058f20aSOlivier Deprez  * This CPU has been turned on. Enter SPMC to initialise S-EL1 or S-EL2. As part
60b058f20aSOlivier Deprez  * of the SPMC initialization path, they will initialize any SPs that they
61b058f20aSOlivier Deprez  * manage. Entry into SPMC is done after initialising minimal architectural
62b058f20aSOlivier Deprez  * state that guarantees safe execution.
63b058f20aSOlivier Deprez  ******************************************************************************/
64b058f20aSOlivier Deprez static void spmd_cpu_on_finish_handler(u_register_t unused)
65b058f20aSOlivier Deprez {
66b058f20aSOlivier Deprez 	unsigned int linear_id = plat_my_core_pos();
67b058f20aSOlivier Deprez 	spmd_spm_core_context_t *ctx = spmd_get_context();
68b058f20aSOlivier Deprez 	int rc;
69b058f20aSOlivier Deprez 
70b058f20aSOlivier Deprez 	assert(ctx->state != SPMC_STATE_ON);
71b058f20aSOlivier Deprez 
72b058f20aSOlivier Deprez 	rc = spmd_spm_core_sync_entry(ctx);
73b058f20aSOlivier Deprez 	if (rc != 0) {
74b058f20aSOlivier Deprez 		ERROR("SPMC initialisation failed (%d) on CPU%u\n", rc,
75b058f20aSOlivier Deprez 		      linear_id);
76b058f20aSOlivier Deprez 		ctx->state = SPMC_STATE_OFF;
77b058f20aSOlivier Deprez 		return;
78b058f20aSOlivier Deprez 	}
79b058f20aSOlivier Deprez 
80b058f20aSOlivier Deprez 	ctx->state = SPMC_STATE_ON;
81b058f20aSOlivier Deprez }
82b058f20aSOlivier Deprez 
83b058f20aSOlivier Deprez /*******************************************************************************
84b058f20aSOlivier Deprez  * Structure populated by the SPM Dispatcher to perform any bookkeeping before
85b058f20aSOlivier Deprez  * PSCI executes a power mgmt. operation.
86b058f20aSOlivier Deprez  ******************************************************************************/
87b058f20aSOlivier Deprez const spd_pm_ops_t spmd_pm = {
88b058f20aSOlivier Deprez 	.svc_on_finish = spmd_cpu_on_finish_handler,
89b058f20aSOlivier Deprez };
90