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