xref: /rk3399_ARM-atf/include/services/sdei.h (revision ff2743e544f0f82381ebb9dff8f14eacb837d2e0)
1 /*
2  * Copyright (c) 2017, 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 
56 /* SDEI event 0 */
57 #define SDEI_EVENT_0	0
58 
59 /* Placeholder interrupt for dynamic mapping */
60 #define SDEI_DYN_IRQ	0
61 
62 /* SDEI flags */
63 
64 /*
65  * These flags determine whether or not an event can be associated with an
66  * interrupt. Static events are permanently associated with an interrupt, and
67  * can't be changed at runtime.  Association of dynamic events with interrupts
68  * can be changed at run time using the SDEI_INTERRUPT_BIND and
69  * SDEI_INTERRUPT_RELEASE calls.
70  *
71  * SDEI_MAPF_DYNAMIC only indicates run time configurability, where as
72  * SDEI_MAPF_BOUND indicates interrupt association. For example:
73  *
74  *  - Calling SDEI_INTERRUPT_BIND on a dynamic event will have both
75  *    SDEI_MAPF_DYNAMIC and SDEI_MAPF_BOUND set.
76  *
77  *  - Statically-bound events will always have SDEI_MAPF_BOUND set, and neither
78  *    SDEI_INTERRUPT_BIND nor SDEI_INTERRUPT_RELEASE can be called on them.
79  *
80  * See also the is_map_bound() macro.
81  */
82 #define SDEI_MAPF_DYNAMIC	BIT(_SDEI_MAPF_DYNAMIC_SHIFT)
83 #define SDEI_MAPF_BOUND		BIT(_SDEI_MAPF_BOUND_SHIFT)
84 
85 #define SDEI_MAPF_SIGNALABLE	BIT(_SDEI_MAPF_SIGNALABLE_SHIFT)
86 #define SDEI_MAPF_PRIVATE	BIT(_SDEI_MAPF_PRIVATE_SHIFT)
87 #define SDEI_MAPF_CRITICAL	BIT(_SDEI_MAPF_CRITICAL_SHIFT)
88 
89 /* Indices of private and shared mappings */
90 #define _SDEI_MAP_IDX_PRIV	0
91 #define _SDEI_MAP_IDX_SHRD	1
92 #define _SDEI_MAP_IDX_MAX	2
93 
94 /* The macros below are used to identify SDEI calls from the SMC function ID */
95 #define SDEI_FID_MASK		U(0xffe0)
96 #define SDEI_FID_VALUE		U(0x20)
97 #define is_sdei_fid(_fid) \
98 	((((_fid) & SDEI_FID_MASK) == SDEI_FID_VALUE) && \
99 	 (((_fid >> FUNCID_CC_SHIFT) & FUNCID_CC_MASK) == SMC_64))
100 
101 #define SDEI_EVENT_MAP(_event, _intr, _flags) \
102 	{ \
103 		.ev_num = _event, \
104 		.intr = _intr, \
105 		.map_flags = _flags \
106 	}
107 
108 #define SDEI_SHARED_EVENT(_event, _intr, _flags) \
109 	SDEI_EVENT_MAP(_event, _intr, _flags)
110 
111 #define SDEI_PRIVATE_EVENT(_event, _intr, _flags) \
112 	SDEI_EVENT_MAP(_event, _intr, _flags | SDEI_MAPF_PRIVATE)
113 
114 #define SDEI_DEFINE_EVENT_0(_intr) \
115 	SDEI_PRIVATE_EVENT(SDEI_EVENT_0, _intr, SDEI_MAPF_SIGNALABLE)
116 
117 /*
118  * Declare shared and private entries for each core. Also declare a global
119  * structure containing private and share entries.
120  *
121  * This macro must be used in the same file as the platform SDEI mappings are
122  * declared. Only then would ARRAY_SIZE() yield a meaningful value.
123  */
124 #define REGISTER_SDEI_MAP(_private, _shared) \
125 	sdei_entry_t sdei_private_event_table \
126 		[PLATFORM_CORE_COUNT * ARRAY_SIZE(_private)]; \
127 	sdei_entry_t sdei_shared_event_table[ARRAY_SIZE(_shared)]; \
128 	const sdei_mapping_t sdei_global_mappings[] = { \
129 		[_SDEI_MAP_IDX_PRIV] = { \
130 			.map = _private, \
131 			.num_maps = ARRAY_SIZE(_private) \
132 		}, \
133 		[_SDEI_MAP_IDX_SHRD] = { \
134 			.map = _shared, \
135 			.num_maps = ARRAY_SIZE(_shared) \
136 		}, \
137 	}
138 
139 typedef uint8_t sdei_state_t;
140 
141 /* Runtime data of SDEI event */
142 typedef struct sdei_entry {
143 	uint64_t ep;		/* Entry point */
144 	uint64_t arg;		/* Entry point argument */
145 	uint64_t affinity;	/* Affinity of shared event */
146 	unsigned int reg_flags;	/* Registration flags */
147 
148 	/* Event handler states: registered, enabled, running */
149 	sdei_state_t state;
150 } sdei_entry_t;
151 
152 /* Mapping of SDEI events to interrupts, and associated data */
153 typedef struct sdei_ev_map {
154 	int32_t ev_num;		/* Event number */
155 	unsigned int intr;	/* Physical interrupt number for a bound map */
156 	unsigned int map_flags;	/* Mapping flags, see SDEI_MAPF_* */
157 	int reg_count;		/* Registration count */
158 	spinlock_t lock;	/* Per-event lock */
159 } sdei_ev_map_t;
160 
161 typedef struct sdei_mapping {
162 	sdei_ev_map_t *map;
163 	size_t num_maps;
164 } sdei_mapping_t;
165 
166 /* Handler to be called to handle SDEI smc calls */
167 uint64_t sdei_smc_handler(uint32_t smc_fid,
168 		uint64_t x1,
169 		uint64_t x2,
170 		uint64_t x3,
171 		uint64_t x4,
172 		void *cookie,
173 		void *handle,
174 		uint64_t flags);
175 
176 void sdei_init(void);
177 
178 /* Public API to dispatch an event to Normal world */
179 int sdei_dispatch_event(int ev_num, unsigned int preempted_sec_state);
180 
181 #endif /* __SDEI_H__ */
182