xref: /rk3399_ARM-atf/services/std_svc/firme/firme_granule_management_service.c (revision 430f246e58d146949d399d72294f56403672bee0)
1 /*
2  * Copyright (c) 2026, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <errno.h>
8 #include <stdint.h>
9 
10 #include <arch.h>
11 #include <arch_features.h>
12 #include <common/debug.h>
13 #include <lib/gpt_rme/gpt_rme.h>
14 #include <lib/smccc.h>
15 #include <services/firme_svc.h>
16 #include <smccc_helpers.h>
17 
18 /* Only supported ABI is GPI_SET for now. */
19 #define FEAT_REG_0_DEFAULT (FIRME_GM_GPI_SET_BIT)
20 
21 /* Reg 1 is built at runtime based on hardware config. */
22 #define FEAT_REG_1_DEFAULT 0
23 
24 static firme_service_info_t granule_mgmt_info = {
25 	.version = FIRME_VERSION(FIRME_GRANULE_MGMT_VERSION_MAJOR,
26 				 FIRME_GRANULE_MGMT_VERSION_MINOR),
27 #if ENABLE_RMM
28 	.instance_support =
29 		(BIT(FIRME_SECURE) | BIT(FIRME_NONSECURE) | BIT(FIRME_REALM)),
30 #else
31 	.instance_support = (BIT(FIRME_SECURE) | BIT(FIRME_NONSECURE)),
32 #endif
33 	.num_feature_regs = 2,
34 	.feature_reg = { FEAT_REG_0_DEFAULT, FEAT_REG_1_DEFAULT },
35 };
36 
firme_granule_mgmt_service_get_info(void)37 firme_service_info_t *firme_granule_mgmt_service_get_info(void)
38 {
39 	/* Build feat reg 1 value from GPCCR value. */
40 	uint64_t gpccr;
41 
42 	if (!is_feat_rme_supported()) {
43 		return NULL;
44 	}
45 
46 	/*
47 	 * todo: FIRME must have a init routine to perform one time
48 	 * initialization during boot for all supported services.
49 	 */
50 	gpccr = read_gpccr_el3();
51 
52 	granule_mgmt_info.feature_reg[1] |=
53 		((gpccr >> GPCCR_PGS_SHIFT) & GPCCR_PGS_MASK)
54 		<< FIRME_GM_PGS_SHIFT;
55 	granule_mgmt_info.feature_reg[1] |=
56 		((gpccr >> GPCCR_L0GPTSZ_SHIFT) & GPCCR_L0GPTSZ_MASK)
57 		<< FIRME_GM_L0GPTSZ_SHIFT;
58 	granule_mgmt_info.feature_reg[1] |=
59 		((gpccr >> GPCCR_PPS_SHIFT) & GPCCR_PPS_MASK)
60 		<< FIRME_GM_PPS_SHIFT;
61 
62 	return &granule_mgmt_info;
63 }
64 
firme_granule_mgmt_service_handler(firme_instance_e instance,uint32_t smc_fid,uint64_t x1,uint64_t x2,uint64_t x3,uint64_t x4,void * cookie,void * handle,uint64_t flags)65 u_register_t firme_granule_mgmt_service_handler(firme_instance_e instance,
66 						uint32_t smc_fid, uint64_t x1,
67 						uint64_t x2, uint64_t x3,
68 						uint64_t x4, void *cookie,
69 						void *handle, uint64_t flags)
70 {
71 	if (!is_feat_rme_supported()) {
72 		SMC_RET1(handle, FIRME_NOT_SUPPORTED);
73 	}
74 
75 	switch (smc_fid) {
76 	case FIRME_GM_GPI_SET_FID:
77 		/* Extract target GPI value from attributes in x3. */
78 		uint8_t target_gpi = (x3 >> FIRME_GM_GPI_SET_TGT_GPI_SHIFT) &
79 				     FIRME_GM_GPI_SET_TGT_GPI_MASK;
80 		/*
81 		 * Granule count is the number of granules to transition, and
82 		 * will be overwritten to contain the number of granules
83 		 * actually transitioned by gpt_transition_pas.
84 		 */
85 		uint64_t granule_count = x2;
86 		uint32_t ret = gpt_transition_pas(x1, &granule_count,
87 						  target_gpi,
88 						  caller_sec_state(flags));
89 
90 		switch (ret) {
91 		case 0:
92 			SMC_RET2(handle, FIRME_SUCCESS, granule_count);
93 		case -EINVAL:
94 			SMC_RET2(handle, FIRME_INVALID_PARAMETERS, 0);
95 		case -EPERM:
96 			SMC_RET2(handle, FIRME_DENIED, 0);
97 		default:
98 			SMC_RET2(handle, FIRME_NOT_SUPPORTED, 0);
99 		}
100 		break;
101 	default:
102 		ERROR("FIRME Granule Management Service FID 0x%X not implemented\n",
103 		      smc_fid);
104 		SMC_RET1(handle, FIRME_NOT_SUPPORTED);
105 	}
106 }
107