1 /*
2  * Copyright (c) 2017-2020, 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 #include <services/sdei_flags.h>
13 
14 /* Range 0xC4000020 - 0xC400003F reserved for SDE 64bit smc calls */
15 #define SDEI_VERSION				0xC4000020U
16 #define SDEI_EVENT_REGISTER			0xC4000021U
17 #define SDEI_EVENT_ENABLE			0xC4000022U
18 #define SDEI_EVENT_DISABLE			0xC4000023U
19 #define SDEI_EVENT_CONTEXT			0xC4000024U
20 #define SDEI_EVENT_COMPLETE			0xC4000025U
21 #define SDEI_EVENT_COMPLETE_AND_RESUME		0xC4000026U
22 
23 #define SDEI_EVENT_UNREGISTER			0xC4000027U
24 #define SDEI_EVENT_STATUS			0xC4000028U
25 #define SDEI_EVENT_GET_INFO			0xC4000029U
26 #define SDEI_EVENT_ROUTING_SET			0xC400002AU
27 #define SDEI_PE_MASK				0xC400002BU
28 #define SDEI_PE_UNMASK				0xC400002CU
29 
30 #define SDEI_INTERRUPT_BIND			0xC400002DU
31 #define SDEI_INTERRUPT_RELEASE			0xC400002EU
32 #define SDEI_EVENT_SIGNAL			0xC400002FU
33 #define SDEI_FEATURES				0xC4000030U
34 #define SDEI_PRIVATE_RESET			0xC4000031U
35 #define SDEI_SHARED_RESET			0xC4000032U
36 
37 /* SDEI_EVENT_REGISTER flags */
38 #define SDEI_REGF_RM_ANY	0ULL
39 #define SDEI_REGF_RM_PE		1ULL
40 
41 /* SDEI_EVENT_COMPLETE status flags */
42 #define SDEI_EV_HANDLED		0U
43 #define SDEI_EV_FAILED		1U
44 
45 /* Indices of private and shared mappings */
46 #define SDEI_MAP_IDX_PRIV_	0U
47 #define SDEI_MAP_IDX_SHRD_	1U
48 #define SDEI_MAP_IDX_MAX_	2U
49 
50 /* The macros below are used to identify SDEI calls from the SMC function ID */
51 #define SDEI_FID_MASK		U(0xffe0)
52 #define SDEI_FID_VALUE		U(0x20)
53 #define is_sdei_fid(_fid) \
54 	((((_fid) & SDEI_FID_MASK) == SDEI_FID_VALUE) && \
55 	 (((_fid >> FUNCID_CC_SHIFT) & FUNCID_CC_MASK) == SMC_64))
56 
57 #define SDEI_EVENT_MAP(_event, _intr, _flags) \
58 	{ \
59 		.ev_num = (_event), \
60 		.intr = (_intr), \
61 		.map_flags = (_flags) \
62 	}
63 
64 #define SDEI_SHARED_EVENT(_event, _intr, _flags) \
65 	SDEI_EVENT_MAP(_event, _intr, _flags)
66 
67 #define SDEI_PRIVATE_EVENT(_event, _intr, _flags) \
68 	SDEI_EVENT_MAP(_event, _intr, (_flags) | SDEI_MAPF_PRIVATE)
69 
70 #define SDEI_DEFINE_EVENT_0(_intr) \
71 	SDEI_PRIVATE_EVENT(SDEI_EVENT_0, (_intr), SDEI_MAPF_SIGNALABLE)
72 
73 #define SDEI_EXPLICIT_EVENT(_event, _pri) \
74 	SDEI_EVENT_MAP((_event), 0, (_pri) | SDEI_MAPF_EXPLICIT | SDEI_MAPF_PRIVATE)
75 
76 /*
77  * Declare shared and private entries for each core. Also declare a global
78  * structure containing private and share entries.
79  *
80  * This macro must be used in the same file as the platform SDEI mappings are
81  * declared. Only then would ARRAY_SIZE() yield a meaningful value.
82  */
83 #define REGISTER_SDEI_MAP(_private, _shared) \
84 	sdei_entry_t sdei_private_event_table \
85 		[PLATFORM_CORE_COUNT * ARRAY_SIZE(_private)]; \
86 	sdei_entry_t sdei_shared_event_table[ARRAY_SIZE(_shared)]; \
87 	const sdei_mapping_t sdei_global_mappings[] = { \
88 		[SDEI_MAP_IDX_PRIV_] = { \
89 			.map = (_private), \
90 			.num_maps = ARRAY_SIZE(_private) \
91 		}, \
92 		[SDEI_MAP_IDX_SHRD_] = { \
93 			.map = (_shared), \
94 			.num_maps = ARRAY_SIZE(_shared) \
95 		}, \
96 	}
97 
98 typedef uint8_t sdei_state_t;
99 
100 /* Runtime data of SDEI event */
101 typedef struct sdei_entry {
102 	uint64_t ep;		/* Entry point */
103 	uint64_t arg;		/* Entry point argument */
104 	uint64_t affinity;	/* Affinity of shared event */
105 	unsigned int reg_flags;	/* Registration flags */
106 
107 	/* Event handler states: registered, enabled, running */
108 	sdei_state_t state;
109 } sdei_entry_t;
110 
111 /* Mapping of SDEI events to interrupts, and associated data */
112 typedef struct sdei_ev_map {
113 	int32_t ev_num;		/* Event number */
114 	unsigned int intr;	/* Physical interrupt number for a bound map */
115 	unsigned int map_flags;	/* Mapping flags, see SDEI_MAPF_* */
116 	int reg_count;		/* Registration count */
117 	spinlock_t lock;	/* Per-event lock */
118 } sdei_ev_map_t;
119 
120 typedef struct sdei_mapping {
121 	sdei_ev_map_t *map;
122 	size_t num_maps;
123 } sdei_mapping_t;
124 
125 /* Handler to be called to handle SDEI smc calls */
126 uint64_t sdei_smc_handler(uint32_t smc_fid,
127 		uint64_t x1,
128 		uint64_t x2,
129 		uint64_t x3,
130 		uint64_t x4,
131 		void *cookie,
132 		void *handle,
133 		uint64_t flags);
134 
135 void sdei_init(void);
136 
137 /* Public API to dispatch an event to Normal world */
138 int sdei_dispatch_event(int ev_num);
139 
140 #endif /* SDEI_H */
141