blob: 72eb6d7d155426e3270a136a48ca0af3270e2570 [file] [log] [blame]
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +01001/*
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
139typedef uint8_t sdei_state_t;
140
141/* Runtime data of SDEI event */
142typedef 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 */
153typedef 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 unsigned int reg_count; /* Registration count */
158 spinlock_t lock; /* Per-event lock */
159} sdei_ev_map_t;
160
161typedef 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 */
167uint64_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
176void sdei_init(void);
177
178#endif /* __SDEI_H__ */