• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #ifndef SDEI_H
8 #define SDEI_H
9 
10 #include <lib/spinlock.h>
11 #include <lib/utils_def.h>
12 
13 /* Range 0xC4000020 - 0xC400003F reserved for SDE 64bit smc calls */
14 #define SDEI_VERSION				0xC4000020U
15 #define SDEI_EVENT_REGISTER			0xC4000021U
16 #define SDEI_EVENT_ENABLE			0xC4000022U
17 #define SDEI_EVENT_DISABLE			0xC4000023U
18 #define SDEI_EVENT_CONTEXT			0xC4000024U
19 #define SDEI_EVENT_COMPLETE			0xC4000025U
20 #define SDEI_EVENT_COMPLETE_AND_RESUME		0xC4000026U
21 
22 #define SDEI_EVENT_UNREGISTER			0xC4000027U
23 #define SDEI_EVENT_STATUS			0xC4000028U
24 #define SDEI_EVENT_GET_INFO			0xC4000029U
25 #define SDEI_EVENT_ROUTING_SET			0xC400002AU
26 #define SDEI_PE_MASK				0xC400002BU
27 #define SDEI_PE_UNMASK				0xC400002CU
28 
29 #define SDEI_INTERRUPT_BIND			0xC400002DU
30 #define SDEI_INTERRUPT_RELEASE			0xC400002EU
31 #define SDEI_EVENT_SIGNAL			0xC400002FU
32 #define SDEI_FEATURES				0xC4000030U
33 #define SDEI_PRIVATE_RESET			0xC4000031U
34 #define SDEI_SHARED_RESET			0xC4000032U
35 
36 /* SDEI_EVENT_REGISTER flags */
37 #define SDEI_REGF_RM_ANY	0ULL
38 #define SDEI_REGF_RM_PE		1ULL
39 
40 /* SDEI_EVENT_COMPLETE status flags */
41 #define SDEI_EV_HANDLED		0U
42 #define SDEI_EV_FAILED		1U
43 
44 /* Internal: SDEI flag bit positions */
45 #define SDEI_MAPF_DYNAMIC_SHIFT_	1U
46 #define SDEI_MAPF_BOUND_SHIFT_		2U
47 #define SDEI_MAPF_SIGNALABLE_SHIFT_	3U
48 #define SDEI_MAPF_PRIVATE_SHIFT_	4U
49 #define SDEI_MAPF_CRITICAL_SHIFT_	5U
50 #define SDEI_MAPF_EXPLICIT_SHIFT_	6U
51 
52 /* SDEI event 0 */
53 #define SDEI_EVENT_0	0
54 
55 /* Placeholder interrupt for dynamic mapping */
56 #define SDEI_DYN_IRQ	0U
57 
58 /* SDEI flags */
59 
60 /*
61  * These flags determine whether or not an event can be associated with an
62  * interrupt. Static events are permanently associated with an interrupt, and
63  * can't be changed at runtime.  Association of dynamic events with interrupts
64  * can be changed at run time using the SDEI_INTERRUPT_BIND and
65  * SDEI_INTERRUPT_RELEASE calls.
66  *
67  * SDEI_MAPF_DYNAMIC only indicates run time configurability, where as
68  * SDEI_MAPF_BOUND indicates interrupt association. For example:
69  *
70  *  - Calling SDEI_INTERRUPT_BIND on a dynamic event will have both
71  *    SDEI_MAPF_DYNAMIC and SDEI_MAPF_BOUND set.
72  *
73  *  - Statically-bound events will always have SDEI_MAPF_BOUND set, and neither
74  *    SDEI_INTERRUPT_BIND nor SDEI_INTERRUPT_RELEASE can be called on them.
75  *
76  * See also the is_map_bound() macro.
77  */
78 #define SDEI_MAPF_DYNAMIC	BIT(SDEI_MAPF_DYNAMIC_SHIFT_)
79 #define SDEI_MAPF_BOUND		BIT(SDEI_MAPF_BOUND_SHIFT_)
80 #define SDEI_MAPF_EXPLICIT	BIT(SDEI_MAPF_EXPLICIT_SHIFT_)
81 
82 #define SDEI_MAPF_SIGNALABLE	BIT(SDEI_MAPF_SIGNALABLE_SHIFT_)
83 #define SDEI_MAPF_PRIVATE	BIT(SDEI_MAPF_PRIVATE_SHIFT_)
84 
85 #define SDEI_MAPF_NORMAL	0
86 #define SDEI_MAPF_CRITICAL	BIT(SDEI_MAPF_CRITICAL_SHIFT_)
87 
88 /* Indices of private and shared mappings */
89 #define SDEI_MAP_IDX_PRIV_	0U
90 #define SDEI_MAP_IDX_SHRD_	1U
91 #define SDEI_MAP_IDX_MAX_	2U
92 
93 /* The macros below are used to identify SDEI calls from the SMC function ID */
94 #define SDEI_FID_MASK		U(0xffe0)
95 #define SDEI_FID_VALUE		U(0x20)
96 #define is_sdei_fid(_fid) \
97 	((((_fid) & SDEI_FID_MASK) == SDEI_FID_VALUE) && \
98 	 (((_fid >> FUNCID_CC_SHIFT) & FUNCID_CC_MASK) == SMC_64))
99 
100 #define SDEI_EVENT_MAP(_event, _intr, _flags) \
101 	{ \
102 		.ev_num = (_event), \
103 		.intr = (_intr), \
104 		.map_flags = (_flags) \
105 	}
106 
107 #define SDEI_SHARED_EVENT(_event, _intr, _flags) \
108 	SDEI_EVENT_MAP(_event, _intr, _flags)
109 
110 #define SDEI_PRIVATE_EVENT(_event, _intr, _flags) \
111 	SDEI_EVENT_MAP(_event, _intr, (_flags) | SDEI_MAPF_PRIVATE)
112 
113 #define SDEI_DEFINE_EVENT_0(_intr) \
114 	SDEI_PRIVATE_EVENT(SDEI_EVENT_0, (_intr), SDEI_MAPF_SIGNALABLE)
115 
116 #define SDEI_EXPLICIT_EVENT(_event, _pri) \
117 	SDEI_EVENT_MAP((_event), 0, (_pri) | SDEI_MAPF_EXPLICIT | SDEI_MAPF_PRIVATE)
118 
119 /*
120  * Declare shared and private entries for each core. Also declare a global
121  * structure containing private and share entries.
122  *
123  * This macro must be used in the same file as the platform SDEI mappings are
124  * declared. Only then would ARRAY_SIZE() yield a meaningful value.
125  */
126 #define REGISTER_SDEI_MAP(_private, _shared) \
127 	sdei_entry_t sdei_private_event_table \
128 		[PLATFORM_CORE_COUNT * ARRAY_SIZE(_private)]; \
129 	sdei_entry_t sdei_shared_event_table[ARRAY_SIZE(_shared)]; \
130 	const sdei_mapping_t sdei_global_mappings[] = { \
131 		[SDEI_MAP_IDX_PRIV_] = { \
132 			.map = (_private), \
133 			.num_maps = ARRAY_SIZE(_private) \
134 		}, \
135 		[SDEI_MAP_IDX_SHRD_] = { \
136 			.map = (_shared), \
137 			.num_maps = ARRAY_SIZE(_shared) \
138 		}, \
139 	}
140 
141 typedef uint8_t sdei_state_t;
142 
143 /* Runtime data of SDEI event */
144 typedef struct sdei_entry {
145 	uint64_t ep;		/* Entry point */
146 	uint64_t arg;		/* Entry point argument */
147 	uint64_t affinity;	/* Affinity of shared event */
148 	unsigned int reg_flags;	/* Registration flags */
149 
150 	/* Event handler states: registered, enabled, running */
151 	sdei_state_t state;
152 } sdei_entry_t;
153 
154 /* Mapping of SDEI events to interrupts, and associated data */
155 typedef struct sdei_ev_map {
156 	int32_t ev_num;		/* Event number */
157 	unsigned int intr;	/* Physical interrupt number for a bound map */
158 	unsigned int map_flags;	/* Mapping flags, see SDEI_MAPF_* */
159 	int reg_count;		/* Registration count */
160 	spinlock_t lock;	/* Per-event lock */
161 } sdei_ev_map_t;
162 
163 typedef struct sdei_mapping {
164 	sdei_ev_map_t *map;
165 	size_t num_maps;
166 } sdei_mapping_t;
167 
168 /* Handler to be called to handle SDEI smc calls */
169 uint64_t sdei_smc_handler(uint32_t smc_fid,
170 		uint64_t x1,
171 		uint64_t x2,
172 		uint64_t x3,
173 		uint64_t x4,
174 		void *cookie,
175 		void *handle,
176 		uint64_t flags);
177 
178 void sdei_init(void);
179 
180 /* Public API to dispatch an event to Normal world */
181 int sdei_dispatch_event(int ev_num);
182 
183 #endif /* SDEI_H */
184