xref: /arm-trusted-firmware/include/services/sdei.h (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2017-2022, Arm Limited and Contributors. All rights reserved.
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #ifndef SDEI_H
8*91f16700Schasinglulu #define SDEI_H
9*91f16700Schasinglulu 
10*91f16700Schasinglulu #include <lib/spinlock.h>
11*91f16700Schasinglulu #include <lib/utils_def.h>
12*91f16700Schasinglulu #include <services/sdei_flags.h>
13*91f16700Schasinglulu 
14*91f16700Schasinglulu /* Range 0xC4000020 - 0xC400003F reserved for SDE 64bit smc calls */
15*91f16700Schasinglulu #define SDEI_VERSION				0xC4000020U
16*91f16700Schasinglulu #define SDEI_EVENT_REGISTER			0xC4000021U
17*91f16700Schasinglulu #define SDEI_EVENT_ENABLE			0xC4000022U
18*91f16700Schasinglulu #define SDEI_EVENT_DISABLE			0xC4000023U
19*91f16700Schasinglulu #define SDEI_EVENT_CONTEXT			0xC4000024U
20*91f16700Schasinglulu #define SDEI_EVENT_COMPLETE			0xC4000025U
21*91f16700Schasinglulu #define SDEI_EVENT_COMPLETE_AND_RESUME		0xC4000026U
22*91f16700Schasinglulu 
23*91f16700Schasinglulu #define SDEI_EVENT_UNREGISTER			0xC4000027U
24*91f16700Schasinglulu #define SDEI_EVENT_STATUS			0xC4000028U
25*91f16700Schasinglulu #define SDEI_EVENT_GET_INFO			0xC4000029U
26*91f16700Schasinglulu #define SDEI_EVENT_ROUTING_SET			0xC400002AU
27*91f16700Schasinglulu #define SDEI_PE_MASK				0xC400002BU
28*91f16700Schasinglulu #define SDEI_PE_UNMASK				0xC400002CU
29*91f16700Schasinglulu 
30*91f16700Schasinglulu #define SDEI_INTERRUPT_BIND			0xC400002DU
31*91f16700Schasinglulu #define SDEI_INTERRUPT_RELEASE			0xC400002EU
32*91f16700Schasinglulu #define SDEI_EVENT_SIGNAL			0xC400002FU
33*91f16700Schasinglulu #define SDEI_FEATURES				0xC4000030U
34*91f16700Schasinglulu #define SDEI_PRIVATE_RESET			0xC4000031U
35*91f16700Schasinglulu #define SDEI_SHARED_RESET			0xC4000032U
36*91f16700Schasinglulu 
37*91f16700Schasinglulu /* SDEI_EVENT_REGISTER flags */
38*91f16700Schasinglulu #define SDEI_REGF_RM_ANY	0ULL
39*91f16700Schasinglulu #define SDEI_REGF_RM_PE		1ULL
40*91f16700Schasinglulu 
41*91f16700Schasinglulu /* SDEI_EVENT_COMPLETE status flags */
42*91f16700Schasinglulu #define SDEI_EV_HANDLED		0U
43*91f16700Schasinglulu #define SDEI_EV_FAILED		1U
44*91f16700Schasinglulu 
45*91f16700Schasinglulu /* Indices of private and shared mappings */
46*91f16700Schasinglulu #define SDEI_MAP_IDX_PRIV_	0U
47*91f16700Schasinglulu #define SDEI_MAP_IDX_SHRD_	1U
48*91f16700Schasinglulu #define SDEI_MAP_IDX_MAX_	2U
49*91f16700Schasinglulu 
50*91f16700Schasinglulu /* The macros below are used to identify SDEI calls from the SMC function ID */
51*91f16700Schasinglulu #define SDEI_FID_MASK		U(0xffe0)
52*91f16700Schasinglulu #define SDEI_FID_VALUE		U(0x20)
53*91f16700Schasinglulu #define is_sdei_fid(_fid) \
54*91f16700Schasinglulu 	((((_fid) & SDEI_FID_MASK) == SDEI_FID_VALUE) && \
55*91f16700Schasinglulu 	 (((_fid >> FUNCID_CC_SHIFT) & FUNCID_CC_MASK) == SMC_64))
56*91f16700Schasinglulu 
57*91f16700Schasinglulu #define SDEI_EVENT_MAP(_event, _intr, _flags) \
58*91f16700Schasinglulu 	{ \
59*91f16700Schasinglulu 		.ev_num = (_event), \
60*91f16700Schasinglulu 		.intr = (_intr), \
61*91f16700Schasinglulu 		.map_flags = (_flags) \
62*91f16700Schasinglulu 	}
63*91f16700Schasinglulu 
64*91f16700Schasinglulu #define SDEI_SHARED_EVENT(_event, _intr, _flags) \
65*91f16700Schasinglulu 	SDEI_EVENT_MAP(_event, _intr, _flags)
66*91f16700Schasinglulu 
67*91f16700Schasinglulu #define SDEI_PRIVATE_EVENT(_event, _intr, _flags) \
68*91f16700Schasinglulu 	SDEI_EVENT_MAP(_event, _intr, (_flags) | SDEI_MAPF_PRIVATE)
69*91f16700Schasinglulu 
70*91f16700Schasinglulu #define SDEI_DEFINE_EVENT_0(_intr) \
71*91f16700Schasinglulu 	SDEI_PRIVATE_EVENT(SDEI_EVENT_0, (_intr), SDEI_MAPF_SIGNALABLE)
72*91f16700Schasinglulu 
73*91f16700Schasinglulu #define SDEI_EXPLICIT_EVENT(_event, _pri) \
74*91f16700Schasinglulu 	SDEI_EVENT_MAP((_event), 0, (_pri) | SDEI_MAPF_EXPLICIT | SDEI_MAPF_PRIVATE)
75*91f16700Schasinglulu 
76*91f16700Schasinglulu /*
77*91f16700Schasinglulu  * Declare shared and private entries for each core. Also declare a global
78*91f16700Schasinglulu  * structure containing private and share entries.
79*91f16700Schasinglulu  *
80*91f16700Schasinglulu  * This macro must be used in the same file as the platform SDEI mappings are
81*91f16700Schasinglulu  * declared. Only then would ARRAY_SIZE() yield a meaningful value.
82*91f16700Schasinglulu  */
83*91f16700Schasinglulu #define REGISTER_SDEI_MAP(_private, _shared) \
84*91f16700Schasinglulu 	sdei_entry_t sdei_private_event_table \
85*91f16700Schasinglulu 		[PLATFORM_CORE_COUNT * ARRAY_SIZE(_private)]; \
86*91f16700Schasinglulu 	sdei_entry_t sdei_shared_event_table[ARRAY_SIZE(_shared)]; \
87*91f16700Schasinglulu 	const sdei_mapping_t sdei_global_mappings[] = { \
88*91f16700Schasinglulu 		[SDEI_MAP_IDX_PRIV_] = { \
89*91f16700Schasinglulu 			.map = (_private), \
90*91f16700Schasinglulu 			.num_maps = ARRAY_SIZE(_private) \
91*91f16700Schasinglulu 		}, \
92*91f16700Schasinglulu 		[SDEI_MAP_IDX_SHRD_] = { \
93*91f16700Schasinglulu 			.map = (_shared), \
94*91f16700Schasinglulu 			.num_maps = ARRAY_SIZE(_shared) \
95*91f16700Schasinglulu 		}, \
96*91f16700Schasinglulu 	}
97*91f16700Schasinglulu 
98*91f16700Schasinglulu typedef uint8_t sdei_state_t;
99*91f16700Schasinglulu 
100*91f16700Schasinglulu /* Runtime data of SDEI event */
101*91f16700Schasinglulu typedef struct sdei_entry {
102*91f16700Schasinglulu 	uint64_t ep;		/* Entry point */
103*91f16700Schasinglulu 	uint64_t arg;		/* Entry point argument */
104*91f16700Schasinglulu 	uint64_t affinity;	/* Affinity of shared event */
105*91f16700Schasinglulu 	unsigned int reg_flags;	/* Registration flags */
106*91f16700Schasinglulu 
107*91f16700Schasinglulu 	/* Event handler states: registered, enabled, running */
108*91f16700Schasinglulu 	sdei_state_t state;
109*91f16700Schasinglulu } sdei_entry_t;
110*91f16700Schasinglulu 
111*91f16700Schasinglulu /* Mapping of SDEI events to interrupts, and associated data */
112*91f16700Schasinglulu typedef struct sdei_ev_map {
113*91f16700Schasinglulu 	int32_t ev_num;		/* Event number */
114*91f16700Schasinglulu 	unsigned int intr;	/* Physical interrupt number for a bound map */
115*91f16700Schasinglulu 	unsigned int map_flags;	/* Mapping flags, see SDEI_MAPF_* */
116*91f16700Schasinglulu 	int reg_count;		/* Registration count */
117*91f16700Schasinglulu 	spinlock_t lock;	/* Per-event lock */
118*91f16700Schasinglulu } sdei_ev_map_t;
119*91f16700Schasinglulu 
120*91f16700Schasinglulu typedef struct sdei_mapping {
121*91f16700Schasinglulu 	sdei_ev_map_t *map;
122*91f16700Schasinglulu 	size_t num_maps;
123*91f16700Schasinglulu } sdei_mapping_t;
124*91f16700Schasinglulu 
125*91f16700Schasinglulu /* Handler to be called to handle SDEI smc calls */
126*91f16700Schasinglulu uint64_t sdei_smc_handler(uint32_t smc_fid,
127*91f16700Schasinglulu 		uint64_t x1,
128*91f16700Schasinglulu 		uint64_t x2,
129*91f16700Schasinglulu 		uint64_t x3,
130*91f16700Schasinglulu 		uint64_t x4,
131*91f16700Schasinglulu 		void *cookie,
132*91f16700Schasinglulu 		void *handle,
133*91f16700Schasinglulu 		uint64_t flags);
134*91f16700Schasinglulu 
135*91f16700Schasinglulu void sdei_init(void);
136*91f16700Schasinglulu 
137*91f16700Schasinglulu /* Public API to dispatch an event to Normal world */
138*91f16700Schasinglulu int sdei_dispatch_event(int ev_num);
139*91f16700Schasinglulu 
140*91f16700Schasinglulu /* Public API to check how many SDEI events are registered. */
141*91f16700Schasinglulu int sdei_get_registered_event_count(void);
142*91f16700Schasinglulu 
143*91f16700Schasinglulu #endif /* SDEI_H */
144