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