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