xref: /rk3399_ARM-atf/services/std_svc/lfa/lfa_main.c (revision 3f7b28626636d45bb0e695db9a5d4bbe3af82329)
1cf48f49fSManish V Badarkhe /*
2cf48f49fSManish V Badarkhe  * Copyright (c) 2025, Arm Limited. All rights reserved.
3cf48f49fSManish V Badarkhe  *
4cf48f49fSManish V Badarkhe  * SPDX-License-Identifier: BSD-3-Clause
5cf48f49fSManish V Badarkhe  */
6cf48f49fSManish V Badarkhe 
7b9dee50cSManish V Badarkhe #include <plat/common/platform.h>
8b9dee50cSManish V Badarkhe #include <services/bl31_lfa.h>
9cf48f49fSManish V Badarkhe #include <services/lfa_svc.h>
10b9dee50cSManish V Badarkhe #include <services/rmmd_rmm_lfa.h>
11cf48f49fSManish V Badarkhe #include <smccc_helpers.h>
12cf48f49fSManish V Badarkhe 
13b9dee50cSManish V Badarkhe static uint32_t lfa_component_count;
14b9dee50cSManish V Badarkhe static plat_lfa_component_info_t *lfa_components;
15b9dee50cSManish V Badarkhe static struct lfa_component_status current_activation;
16b9dee50cSManish V Badarkhe static bool is_lfa_initialized;
17b9dee50cSManish V Badarkhe 
18b9dee50cSManish V Badarkhe void lfa_reset_activation(void)
19b9dee50cSManish V Badarkhe {
20b9dee50cSManish V Badarkhe 	current_activation.component_id = LFA_INVALID_COMPONENT;
21b9dee50cSManish V Badarkhe 	current_activation.prime_status = PRIME_NONE;
22b9dee50cSManish V Badarkhe }
23b9dee50cSManish V Badarkhe 
24b9dee50cSManish V Badarkhe static bool lfa_initialize_components(void)
25b9dee50cSManish V Badarkhe {
26b9dee50cSManish V Badarkhe 	lfa_component_count = plat_lfa_get_components(&lfa_components);
27b9dee50cSManish V Badarkhe 
28b9dee50cSManish V Badarkhe 	if (lfa_component_count == 0U || lfa_components == NULL) {
29b9dee50cSManish V Badarkhe 		/* unlikely to reach here */
30b9dee50cSManish V Badarkhe 		ERROR("Invalid LFA component setup: count = 0 or components are NULL");
31b9dee50cSManish V Badarkhe 		return false;
32b9dee50cSManish V Badarkhe 	}
33b9dee50cSManish V Badarkhe 
34b9dee50cSManish V Badarkhe 	return true;
35b9dee50cSManish V Badarkhe }
36b9dee50cSManish V Badarkhe 
3706a6f296SManish V Badarkhe static uint64_t get_fw_activation_flags(uint32_t fw_seq_id)
3806a6f296SManish V Badarkhe {
3906a6f296SManish V Badarkhe 	const plat_lfa_component_info_t *comp =
4006a6f296SManish V Badarkhe 				&lfa_components[fw_seq_id];
4106a6f296SManish V Badarkhe 	uint64_t flags = 0ULL;
4206a6f296SManish V Badarkhe 
4306a6f296SManish V Badarkhe 	flags |= ((comp->activator == NULL ? 0ULL : 1ULL)
4406a6f296SManish V Badarkhe 		 << LFA_ACTIVATION_CAPABLE_SHIFT);
4506a6f296SManish V Badarkhe 	flags |= (uint64_t)(comp->activation_pending)
4606a6f296SManish V Badarkhe 		 << LFA_ACTIVATION_PENDING_SHIFT;
4706a6f296SManish V Badarkhe 
4806a6f296SManish V Badarkhe 	if (comp->activator != NULL) {
4906a6f296SManish V Badarkhe 		flags |= ((comp->activator->may_reset_cpu ? 1ULL : 0ULL)
5006a6f296SManish V Badarkhe 			 << LFA_MAY_RESET_CPU_SHIFT);
5106a6f296SManish V Badarkhe 		flags |= ((comp->activator->cpu_rendezvous_required ? 0ULL : 1ULL)
5206a6f296SManish V Badarkhe 			 << LFA_CPU_RENDEZVOUS_OPTIONAL_SHIFT);
5306a6f296SManish V Badarkhe 	}
5406a6f296SManish V Badarkhe 
5506a6f296SManish V Badarkhe 	return flags;
5606a6f296SManish V Badarkhe }
5706a6f296SManish V Badarkhe 
58*3f7b2862SManish V Badarkhe static int lfa_cancel(uint32_t component_id)
59*3f7b2862SManish V Badarkhe {
60*3f7b2862SManish V Badarkhe 	int ret = LFA_SUCCESS;
61*3f7b2862SManish V Badarkhe 
62*3f7b2862SManish V Badarkhe 	if (lfa_component_count == 0U) {
63*3f7b2862SManish V Badarkhe 		return LFA_WRONG_STATE;
64*3f7b2862SManish V Badarkhe 	}
65*3f7b2862SManish V Badarkhe 
66*3f7b2862SManish V Badarkhe 	/* Check if component ID is in range. */
67*3f7b2862SManish V Badarkhe 	if ((component_id >= lfa_component_count) ||
68*3f7b2862SManish V Badarkhe 	    (component_id != current_activation.component_id)) {
69*3f7b2862SManish V Badarkhe 		return LFA_INVALID_PARAMETERS;
70*3f7b2862SManish V Badarkhe 	}
71*3f7b2862SManish V Badarkhe 
72*3f7b2862SManish V Badarkhe 	ret = plat_lfa_cancel(component_id);
73*3f7b2862SManish V Badarkhe 	if (ret != LFA_SUCCESS) {
74*3f7b2862SManish V Badarkhe 		return LFA_BUSY;
75*3f7b2862SManish V Badarkhe 	}
76*3f7b2862SManish V Badarkhe 
77*3f7b2862SManish V Badarkhe 	/* TODO: add proper termination prime and activate phases */
78*3f7b2862SManish V Badarkhe 	lfa_reset_activation();
79*3f7b2862SManish V Badarkhe 
80*3f7b2862SManish V Badarkhe 	return ret;
81*3f7b2862SManish V Badarkhe }
82*3f7b2862SManish V Badarkhe 
83cf48f49fSManish V Badarkhe int lfa_setup(void)
84cf48f49fSManish V Badarkhe {
85b9dee50cSManish V Badarkhe 	is_lfa_initialized = lfa_initialize_components();
86b9dee50cSManish V Badarkhe 	if (!is_lfa_initialized) {
87b9dee50cSManish V Badarkhe 		return -1;
88b9dee50cSManish V Badarkhe 	}
89b9dee50cSManish V Badarkhe 
90b9dee50cSManish V Badarkhe 	lfa_reset_activation();
91b9dee50cSManish V Badarkhe 
92b9dee50cSManish V Badarkhe 	return 0;
93cf48f49fSManish V Badarkhe }
94cf48f49fSManish V Badarkhe 
95cf48f49fSManish V Badarkhe uint64_t lfa_smc_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2,
96cf48f49fSManish V Badarkhe 			 u_register_t x3, u_register_t x4, void *cookie,
97cf48f49fSManish V Badarkhe 			 void *handle, u_register_t flags)
98cf48f49fSManish V Badarkhe {
9906a6f296SManish V Badarkhe 	uint64_t retx1, retx2;
10006a6f296SManish V Badarkhe 	uint8_t *uuid_p;
10106a6f296SManish V Badarkhe 	uint32_t fw_seq_id = (uint32_t)x1;
102*3f7b2862SManish V Badarkhe 	int ret;
10306a6f296SManish V Badarkhe 
104cf48f49fSManish V Badarkhe 	/**
105cf48f49fSManish V Badarkhe 	 * TODO: Acquire serialization lock.
106cf48f49fSManish V Badarkhe 	 */
107b9dee50cSManish V Badarkhe 
108b9dee50cSManish V Badarkhe 	if (!is_lfa_initialized) {
109b9dee50cSManish V Badarkhe 		return LFA_NOT_SUPPORTED;
110b9dee50cSManish V Badarkhe 	}
111b9dee50cSManish V Badarkhe 
112cf48f49fSManish V Badarkhe 	switch (smc_fid) {
113cf48f49fSManish V Badarkhe 	case LFA_VERSION:
114cf48f49fSManish V Badarkhe 		SMC_RET1(handle, LFA_VERSION_VAL);
115cf48f49fSManish V Badarkhe 		break;
116cf48f49fSManish V Badarkhe 
117cf48f49fSManish V Badarkhe 	case LFA_FEATURES:
118cf48f49fSManish V Badarkhe 		SMC_RET1(handle, is_lfa_fid(x1) ? LFA_SUCCESS : LFA_NOT_SUPPORTED);
119cf48f49fSManish V Badarkhe 		break;
120cf48f49fSManish V Badarkhe 
121cf48f49fSManish V Badarkhe 	case LFA_GET_INFO:
122b9dee50cSManish V Badarkhe 		/**
123b9dee50cSManish V Badarkhe 		 * The current specification limits this input parameter to be zero for
124b9dee50cSManish V Badarkhe 		 * version 1.0 of LFA
125b9dee50cSManish V Badarkhe 		 */
126b9dee50cSManish V Badarkhe 		if (x1 == 0ULL) {
127b9dee50cSManish V Badarkhe 			SMC_RET3(handle, LFA_SUCCESS, lfa_component_count, 0);
128b9dee50cSManish V Badarkhe 		} else {
129b9dee50cSManish V Badarkhe 			SMC_RET1(handle, LFA_INVALID_PARAMETERS);
130b9dee50cSManish V Badarkhe 		}
131cf48f49fSManish V Badarkhe 		break;
132cf48f49fSManish V Badarkhe 
133cf48f49fSManish V Badarkhe 	case LFA_GET_INVENTORY:
13406a6f296SManish V Badarkhe 		if (lfa_component_count == 0U) {
13506a6f296SManish V Badarkhe 			SMC_RET1(handle, LFA_WRONG_STATE);
13606a6f296SManish V Badarkhe 		}
13706a6f296SManish V Badarkhe 
13806a6f296SManish V Badarkhe 		/*
13906a6f296SManish V Badarkhe 		 * Check if fw_seq_id is in range. LFA_GET_INFO must be called first to scan
14006a6f296SManish V Badarkhe 		 * platform firmware and create a valid number of firmware components.
14106a6f296SManish V Badarkhe 		 */
14206a6f296SManish V Badarkhe 		if (fw_seq_id >= lfa_component_count) {
14306a6f296SManish V Badarkhe 			SMC_RET1(handle, LFA_INVALID_PARAMETERS);
14406a6f296SManish V Badarkhe 		}
14506a6f296SManish V Badarkhe 
14606a6f296SManish V Badarkhe 		/*
14706a6f296SManish V Badarkhe 		 * grab the UUID of asked fw_seq_id and set the return UUID
14806a6f296SManish V Badarkhe 		 * variables
14906a6f296SManish V Badarkhe 		 */
15006a6f296SManish V Badarkhe 		uuid_p = (uint8_t *)&lfa_components[fw_seq_id].uuid;
15106a6f296SManish V Badarkhe 		memcpy(&retx1, uuid_p, sizeof(uint64_t));
15206a6f296SManish V Badarkhe 		memcpy(&retx2, uuid_p + sizeof(uint64_t), sizeof(uint64_t));
15306a6f296SManish V Badarkhe 
15406a6f296SManish V Badarkhe 		/*
15506a6f296SManish V Badarkhe 		 * check the given fw_seq_id's update available
15606a6f296SManish V Badarkhe 		 * and accordingly set the active_pending flag
15706a6f296SManish V Badarkhe 		 */
15806a6f296SManish V Badarkhe 		lfa_components[fw_seq_id].activation_pending =
15906a6f296SManish V Badarkhe 				is_plat_lfa_activation_pending(fw_seq_id);
16006a6f296SManish V Badarkhe 
16106a6f296SManish V Badarkhe 		INFO("Component %lu %s live activation:\n", x1,
16206a6f296SManish V Badarkhe 		      lfa_components[fw_seq_id].activator ? "supports" :
16306a6f296SManish V Badarkhe 		      "does not support");
16406a6f296SManish V Badarkhe 
16506a6f296SManish V Badarkhe 		if (lfa_components[fw_seq_id].activator != NULL) {
16606a6f296SManish V Badarkhe 			INFO("Activation pending: %s\n",
16706a6f296SManish V Badarkhe 			      lfa_components[fw_seq_id].activation_pending ? "true" : "false");
16806a6f296SManish V Badarkhe 		}
16906a6f296SManish V Badarkhe 
17006a6f296SManish V Badarkhe 		INFO("x1 = 0x%016lx, x2 = 0x%016lx\n", retx1, retx2);
17106a6f296SManish V Badarkhe 
17206a6f296SManish V Badarkhe 		SMC_RET4(handle, LFA_SUCCESS, retx1, retx2, get_fw_activation_flags(fw_seq_id));
17306a6f296SManish V Badarkhe 
174cf48f49fSManish V Badarkhe 		break;
175cf48f49fSManish V Badarkhe 
176cf48f49fSManish V Badarkhe 	case LFA_PRIME:
177cf48f49fSManish V Badarkhe 		break;
178cf48f49fSManish V Badarkhe 
179cf48f49fSManish V Badarkhe 	case LFA_ACTIVATE:
180cf48f49fSManish V Badarkhe 		break;
181cf48f49fSManish V Badarkhe 
182cf48f49fSManish V Badarkhe 	case LFA_CANCEL:
183*3f7b2862SManish V Badarkhe 		ret = lfa_cancel(x1);
184*3f7b2862SManish V Badarkhe 		SMC_RET1(handle, ret);
185cf48f49fSManish V Badarkhe 		break;
186cf48f49fSManish V Badarkhe 
187cf48f49fSManish V Badarkhe 	default:
188cf48f49fSManish V Badarkhe 		WARN("Unimplemented LFA Service Call: 0x%x\n", smc_fid);
189cf48f49fSManish V Badarkhe 		SMC_RET1(handle, SMC_UNK);
190cf48f49fSManish V Badarkhe 		break; /* unreachable */
191cf48f49fSManish V Badarkhe 
192cf48f49fSManish V Badarkhe 	}
193cf48f49fSManish V Badarkhe 
194cf48f49fSManish V Badarkhe 	SMC_RET1(handle, SMC_UNK);
195cf48f49fSManish V Badarkhe 
196cf48f49fSManish V Badarkhe 	return 0;
197cf48f49fSManish V Badarkhe }
198