xref: /rk3399_ARM-atf/services/std_svc/sdei/sdei_private.h (revision b7cb133e5c56f149024a56873216f0c198aa9635)
1*b7cb133eSJeenu Viswambharan /*
2*b7cb133eSJeenu Viswambharan  * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
3*b7cb133eSJeenu Viswambharan  *
4*b7cb133eSJeenu Viswambharan  * SPDX-License-Identifier: BSD-3-Clause
5*b7cb133eSJeenu Viswambharan  */
6*b7cb133eSJeenu Viswambharan 
7*b7cb133eSJeenu Viswambharan #ifndef __SDEI_PRIVATE_H__
8*b7cb133eSJeenu Viswambharan #define __SDEI_PRIVATE_H__
9*b7cb133eSJeenu Viswambharan 
10*b7cb133eSJeenu Viswambharan #include <arch_helpers.h>
11*b7cb133eSJeenu Viswambharan #include <debug.h>
12*b7cb133eSJeenu Viswambharan #include <errno.h>
13*b7cb133eSJeenu Viswambharan #include <interrupt_mgmt.h>
14*b7cb133eSJeenu Viswambharan #include <platform.h>
15*b7cb133eSJeenu Viswambharan #include <sdei.h>
16*b7cb133eSJeenu Viswambharan #include <spinlock.h>
17*b7cb133eSJeenu Viswambharan #include <stdbool.h>
18*b7cb133eSJeenu Viswambharan #include <types.h>
19*b7cb133eSJeenu Viswambharan #include <utils_def.h>
20*b7cb133eSJeenu Viswambharan 
21*b7cb133eSJeenu Viswambharan #ifdef AARCH32
22*b7cb133eSJeenu Viswambharan # error SDEI is implemented only for AArch64 systems
23*b7cb133eSJeenu Viswambharan #endif
24*b7cb133eSJeenu Viswambharan 
25*b7cb133eSJeenu Viswambharan #ifndef PLAT_SDEI_CRITICAL_PRI
26*b7cb133eSJeenu Viswambharan # error Platform must define SDEI critical priority value
27*b7cb133eSJeenu Viswambharan #endif
28*b7cb133eSJeenu Viswambharan 
29*b7cb133eSJeenu Viswambharan #ifndef PLAT_SDEI_NORMAL_PRI
30*b7cb133eSJeenu Viswambharan # error Platform must define SDEI normal priority value
31*b7cb133eSJeenu Viswambharan #endif
32*b7cb133eSJeenu Viswambharan 
33*b7cb133eSJeenu Viswambharan /* Output SDEI logs as verbose */
34*b7cb133eSJeenu Viswambharan #define SDEI_LOG(...)	VERBOSE("SDEI: " __VA_ARGS__)
35*b7cb133eSJeenu Viswambharan 
36*b7cb133eSJeenu Viswambharan /* SDEI handler unregistered state. This is the default state. */
37*b7cb133eSJeenu Viswambharan #define SDEI_STATE_UNREGISTERED		0
38*b7cb133eSJeenu Viswambharan 
39*b7cb133eSJeenu Viswambharan /* SDE event status values in bit position */
40*b7cb133eSJeenu Viswambharan #define SDEI_STATF_REGISTERED		0
41*b7cb133eSJeenu Viswambharan #define SDEI_STATF_ENABLED		1
42*b7cb133eSJeenu Viswambharan #define SDEI_STATF_RUNNING		2
43*b7cb133eSJeenu Viswambharan 
44*b7cb133eSJeenu Viswambharan /* SDEI SMC error codes */
45*b7cb133eSJeenu Viswambharan #define	SDEI_EINVAL	(-2)
46*b7cb133eSJeenu Viswambharan #define	SDEI_EDENY	(-3)
47*b7cb133eSJeenu Viswambharan #define	SDEI_EPEND	(-5)
48*b7cb133eSJeenu Viswambharan #define	SDEI_ENOMEM	(-10)
49*b7cb133eSJeenu Viswambharan 
50*b7cb133eSJeenu Viswambharan /*
51*b7cb133eSJeenu Viswambharan  * 'info' parameter to SDEI_EVENT_GET_INFO SMC.
52*b7cb133eSJeenu Viswambharan  *
53*b7cb133eSJeenu Viswambharan  * Note that the SDEI v1.0 speification mistakenly enumerates the
54*b7cb133eSJeenu Viswambharan  * SDEI_INFO_EV_SIGNALED as SDEI_INFO_SIGNALED. This will be corrected in a
55*b7cb133eSJeenu Viswambharan  * future version.
56*b7cb133eSJeenu Viswambharan  */
57*b7cb133eSJeenu Viswambharan #define SDEI_INFO_EV_TYPE		0
58*b7cb133eSJeenu Viswambharan #define SDEI_INFO_EV_NOT_SIGNALED	1
59*b7cb133eSJeenu Viswambharan #define SDEI_INFO_EV_PRIORITY		2
60*b7cb133eSJeenu Viswambharan #define SDEI_INFO_EV_ROUTING_MODE	3
61*b7cb133eSJeenu Viswambharan #define SDEI_INFO_EV_ROUTING_AFF	4
62*b7cb133eSJeenu Viswambharan 
63*b7cb133eSJeenu Viswambharan #define SDEI_PRIVATE_MAPPING()	(&sdei_global_mappings[_SDEI_MAP_IDX_PRIV])
64*b7cb133eSJeenu Viswambharan #define SDEI_SHARED_MAPPING()	(&sdei_global_mappings[_SDEI_MAP_IDX_SHRD])
65*b7cb133eSJeenu Viswambharan 
66*b7cb133eSJeenu Viswambharan #define for_each_mapping_type(_i, _mapping) \
67*b7cb133eSJeenu Viswambharan 	for (_i = 0, _mapping = &sdei_global_mappings[i]; \
68*b7cb133eSJeenu Viswambharan 			_i < _SDEI_MAP_IDX_MAX; \
69*b7cb133eSJeenu Viswambharan 			_i++, _mapping = &sdei_global_mappings[i])
70*b7cb133eSJeenu Viswambharan 
71*b7cb133eSJeenu Viswambharan #define iterate_mapping(_mapping, _i, _map) \
72*b7cb133eSJeenu Viswambharan 	for (_map = (_mapping)->map, _i = 0; \
73*b7cb133eSJeenu Viswambharan 			_i < (_mapping)->num_maps; \
74*b7cb133eSJeenu Viswambharan 			_i++, _map++)
75*b7cb133eSJeenu Viswambharan 
76*b7cb133eSJeenu Viswambharan #define for_each_private_map(_i, _map) \
77*b7cb133eSJeenu Viswambharan 	iterate_mapping(SDEI_PRIVATE_MAPPING(), _i, _map)
78*b7cb133eSJeenu Viswambharan 
79*b7cb133eSJeenu Viswambharan #define for_each_shared_map(_i, _map) \
80*b7cb133eSJeenu Viswambharan 	iterate_mapping(SDEI_SHARED_MAPPING(), _i, _map)
81*b7cb133eSJeenu Viswambharan 
82*b7cb133eSJeenu Viswambharan /* SDEI_FEATURES */
83*b7cb133eSJeenu Viswambharan #define SDEI_FEATURE_BIND_SLOTS		0
84*b7cb133eSJeenu Viswambharan #define BIND_SLOTS_MASK			0xffff
85*b7cb133eSJeenu Viswambharan #define FEATURES_SHARED_SLOTS_SHIFT	16
86*b7cb133eSJeenu Viswambharan #define FEATURES_PRIVATE_SLOTS_SHIFT	0
87*b7cb133eSJeenu Viswambharan #define FEATURE_BIND_SLOTS(_priv, _shrd) \
88*b7cb133eSJeenu Viswambharan 	((((_priv) & BIND_SLOTS_MASK) << FEATURES_PRIVATE_SLOTS_SHIFT) | \
89*b7cb133eSJeenu Viswambharan 	 (((_shrd) & BIND_SLOTS_MASK) << FEATURES_SHARED_SLOTS_SHIFT))
90*b7cb133eSJeenu Viswambharan 
91*b7cb133eSJeenu Viswambharan #define GET_EV_STATE(_e, _s)	get_ev_state_bit(_e, SDEI_STATF_##_s)
92*b7cb133eSJeenu Viswambharan #define SET_EV_STATE(_e, _s)	clr_ev_state_bit(_e->state, SDEI_STATF_##_s)
93*b7cb133eSJeenu Viswambharan 
94*b7cb133eSJeenu Viswambharan static inline int is_event_private(sdei_ev_map_t *map)
95*b7cb133eSJeenu Viswambharan {
96*b7cb133eSJeenu Viswambharan 	return ((map->map_flags & BIT(_SDEI_MAPF_PRIVATE_SHIFT)) != 0);
97*b7cb133eSJeenu Viswambharan }
98*b7cb133eSJeenu Viswambharan 
99*b7cb133eSJeenu Viswambharan static inline int is_event_shared(sdei_ev_map_t *map)
100*b7cb133eSJeenu Viswambharan {
101*b7cb133eSJeenu Viswambharan 	return !is_event_private(map);
102*b7cb133eSJeenu Viswambharan }
103*b7cb133eSJeenu Viswambharan 
104*b7cb133eSJeenu Viswambharan static inline int is_event_critical(sdei_ev_map_t *map)
105*b7cb133eSJeenu Viswambharan {
106*b7cb133eSJeenu Viswambharan 	return ((map->map_flags & BIT(_SDEI_MAPF_CRITICAL_SHIFT)) != 0);
107*b7cb133eSJeenu Viswambharan }
108*b7cb133eSJeenu Viswambharan 
109*b7cb133eSJeenu Viswambharan static inline int is_event_normal(sdei_ev_map_t *map)
110*b7cb133eSJeenu Viswambharan {
111*b7cb133eSJeenu Viswambharan 	return !is_event_critical(map);
112*b7cb133eSJeenu Viswambharan }
113*b7cb133eSJeenu Viswambharan 
114*b7cb133eSJeenu Viswambharan static inline int is_event_signalable(sdei_ev_map_t *map)
115*b7cb133eSJeenu Viswambharan {
116*b7cb133eSJeenu Viswambharan 	return ((map->map_flags & BIT(_SDEI_MAPF_SIGNALABLE_SHIFT)) != 0);
117*b7cb133eSJeenu Viswambharan }
118*b7cb133eSJeenu Viswambharan 
119*b7cb133eSJeenu Viswambharan static inline int is_map_dynamic(sdei_ev_map_t *map)
120*b7cb133eSJeenu Viswambharan {
121*b7cb133eSJeenu Viswambharan 	return ((map->map_flags & BIT(_SDEI_MAPF_DYNAMIC_SHIFT)) != 0);
122*b7cb133eSJeenu Viswambharan }
123*b7cb133eSJeenu Viswambharan 
124*b7cb133eSJeenu Viswambharan /*
125*b7cb133eSJeenu Viswambharan  * Checks whether an event is associated with an interrupt. Static events always
126*b7cb133eSJeenu Viswambharan  * return true, and dynamic events return whether SDEI_INTERRUPT_BIND had been
127*b7cb133eSJeenu Viswambharan  * called on them. This can be used on both static or dynamic events to check
128*b7cb133eSJeenu Viswambharan  * for an associated interrupt.
129*b7cb133eSJeenu Viswambharan  */
130*b7cb133eSJeenu Viswambharan static inline int is_map_bound(sdei_ev_map_t *map)
131*b7cb133eSJeenu Viswambharan {
132*b7cb133eSJeenu Viswambharan 	return ((map->map_flags & BIT(_SDEI_MAPF_BOUND_SHIFT)) != 0);
133*b7cb133eSJeenu Viswambharan }
134*b7cb133eSJeenu Viswambharan 
135*b7cb133eSJeenu Viswambharan static inline void set_map_bound(sdei_ev_map_t *map)
136*b7cb133eSJeenu Viswambharan {
137*b7cb133eSJeenu Viswambharan 	map->map_flags |= BIT(_SDEI_MAPF_BOUND_SHIFT);
138*b7cb133eSJeenu Viswambharan }
139*b7cb133eSJeenu Viswambharan 
140*b7cb133eSJeenu Viswambharan static inline void clr_map_bound(sdei_ev_map_t *map)
141*b7cb133eSJeenu Viswambharan {
142*b7cb133eSJeenu Viswambharan 	map->map_flags &= ~(BIT(_SDEI_MAPF_BOUND_SHIFT));
143*b7cb133eSJeenu Viswambharan }
144*b7cb133eSJeenu Viswambharan 
145*b7cb133eSJeenu Viswambharan static inline int is_secure_sgi(unsigned int intr)
146*b7cb133eSJeenu Viswambharan {
147*b7cb133eSJeenu Viswambharan 	return (plat_ic_is_sgi(intr) &&
148*b7cb133eSJeenu Viswambharan 			(plat_ic_get_interrupt_type(intr) == INTR_TYPE_EL3));
149*b7cb133eSJeenu Viswambharan }
150*b7cb133eSJeenu Viswambharan 
151*b7cb133eSJeenu Viswambharan /*
152*b7cb133eSJeenu Viswambharan  * Determine EL of the client. If EL2 is implemented (hence the enabled HCE
153*b7cb133eSJeenu Viswambharan  * bit), deem EL2; otherwise, deem EL1.
154*b7cb133eSJeenu Viswambharan  */
155*b7cb133eSJeenu Viswambharan static inline unsigned int sdei_client_el(void)
156*b7cb133eSJeenu Viswambharan {
157*b7cb133eSJeenu Viswambharan 	return read_scr_el3() & SCR_HCE_BIT ? MODE_EL2 : MODE_EL1;
158*b7cb133eSJeenu Viswambharan }
159*b7cb133eSJeenu Viswambharan 
160*b7cb133eSJeenu Viswambharan static inline unsigned int sdei_event_priority(sdei_ev_map_t *map)
161*b7cb133eSJeenu Viswambharan {
162*b7cb133eSJeenu Viswambharan 	return is_event_critical(map) ? PLAT_SDEI_CRITICAL_PRI :
163*b7cb133eSJeenu Viswambharan 		PLAT_SDEI_NORMAL_PRI;
164*b7cb133eSJeenu Viswambharan }
165*b7cb133eSJeenu Viswambharan 
166*b7cb133eSJeenu Viswambharan static inline int get_ev_state_bit(sdei_entry_t *se, unsigned int bit_no)
167*b7cb133eSJeenu Viswambharan {
168*b7cb133eSJeenu Viswambharan 	return ((se->state & BIT(bit_no)) != 0);
169*b7cb133eSJeenu Viswambharan }
170*b7cb133eSJeenu Viswambharan 
171*b7cb133eSJeenu Viswambharan static inline void clr_ev_state_bit(sdei_entry_t *se, unsigned int bit_no)
172*b7cb133eSJeenu Viswambharan {
173*b7cb133eSJeenu Viswambharan 	se->state &= ~BIT(bit_no);
174*b7cb133eSJeenu Viswambharan }
175*b7cb133eSJeenu Viswambharan 
176*b7cb133eSJeenu Viswambharan /* SDEI actions for state transition */
177*b7cb133eSJeenu Viswambharan typedef enum {
178*b7cb133eSJeenu Viswambharan 	/*
179*b7cb133eSJeenu Viswambharan 	 * Actions resulting from client requests. These directly map to SMC
180*b7cb133eSJeenu Viswambharan 	 * calls. Note that the state table columns are listed in this order
181*b7cb133eSJeenu Viswambharan 	 * too.
182*b7cb133eSJeenu Viswambharan 	 */
183*b7cb133eSJeenu Viswambharan 	DO_REGISTER = 0,
184*b7cb133eSJeenu Viswambharan 	DO_RELEASE = 1,
185*b7cb133eSJeenu Viswambharan 	DO_ENABLE = 2,
186*b7cb133eSJeenu Viswambharan 	DO_DISABLE = 3,
187*b7cb133eSJeenu Viswambharan 	DO_UNREGISTER = 4,
188*b7cb133eSJeenu Viswambharan 	DO_ROUTING = 5,
189*b7cb133eSJeenu Viswambharan 	DO_CONTEXT = 6,
190*b7cb133eSJeenu Viswambharan 	DO_COMPLETE = 7,
191*b7cb133eSJeenu Viswambharan 	DO_COMPLETE_RESUME = 8,
192*b7cb133eSJeenu Viswambharan 
193*b7cb133eSJeenu Viswambharan 	/* Action for event dispatch */
194*b7cb133eSJeenu Viswambharan 	DO_DISPATCH = 9,
195*b7cb133eSJeenu Viswambharan 
196*b7cb133eSJeenu Viswambharan 	DO_MAX,
197*b7cb133eSJeenu Viswambharan } sdei_action_t;
198*b7cb133eSJeenu Viswambharan 
199*b7cb133eSJeenu Viswambharan typedef enum {
200*b7cb133eSJeenu Viswambharan 	SDEI_NORMAL,
201*b7cb133eSJeenu Viswambharan 	SDEI_CRITICAL
202*b7cb133eSJeenu Viswambharan } sdei_class_t;
203*b7cb133eSJeenu Viswambharan 
204*b7cb133eSJeenu Viswambharan static inline void sdei_map_lock(sdei_ev_map_t *map)
205*b7cb133eSJeenu Viswambharan {
206*b7cb133eSJeenu Viswambharan 	spin_lock(&map->lock);
207*b7cb133eSJeenu Viswambharan }
208*b7cb133eSJeenu Viswambharan 
209*b7cb133eSJeenu Viswambharan static inline void sdei_map_unlock(sdei_ev_map_t *map)
210*b7cb133eSJeenu Viswambharan {
211*b7cb133eSJeenu Viswambharan 	spin_unlock(&map->lock);
212*b7cb133eSJeenu Viswambharan }
213*b7cb133eSJeenu Viswambharan 
214*b7cb133eSJeenu Viswambharan extern const sdei_mapping_t sdei_global_mappings[];
215*b7cb133eSJeenu Viswambharan extern sdei_entry_t sdei_private_event_table[];
216*b7cb133eSJeenu Viswambharan extern sdei_entry_t sdei_shared_event_table[];
217*b7cb133eSJeenu Viswambharan 
218*b7cb133eSJeenu Viswambharan void init_sdei_state(void);
219*b7cb133eSJeenu Viswambharan 
220*b7cb133eSJeenu Viswambharan sdei_ev_map_t *find_event_map_by_intr(int intr_num, int shared);
221*b7cb133eSJeenu Viswambharan sdei_ev_map_t *find_event_map(int ev_num);
222*b7cb133eSJeenu Viswambharan sdei_entry_t *get_event_entry(sdei_ev_map_t *map);
223*b7cb133eSJeenu Viswambharan 
224*b7cb133eSJeenu Viswambharan int sdei_event_context(void *handle, unsigned int param);
225*b7cb133eSJeenu Viswambharan int sdei_event_complete(int resume, uint64_t arg);
226*b7cb133eSJeenu Viswambharan 
227*b7cb133eSJeenu Viswambharan void sdei_pe_unmask(void);
228*b7cb133eSJeenu Viswambharan unsigned int sdei_pe_mask(void);
229*b7cb133eSJeenu Viswambharan 
230*b7cb133eSJeenu Viswambharan int sdei_intr_handler(uint32_t intr, uint32_t flags, void *handle,
231*b7cb133eSJeenu Viswambharan 		void *cookie);
232*b7cb133eSJeenu Viswambharan bool can_sdei_state_trans(sdei_entry_t *se, sdei_action_t act);
233*b7cb133eSJeenu Viswambharan 
234*b7cb133eSJeenu Viswambharan #endif /* __SDEI_PRIVATE_H__ */
235