blob: 79d1d065d3a90483a09bf82f2e34fb14cde2de1d [file] [log] [blame]
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +01001/*
Jeenu Viswambharan34392302018-01-17 12:30:11 +00002 * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +01003 *
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
Jeenu Viswambharan34392302018-01-17 12:30:11 +000055#define _SDEI_MAPF_EXPLICIT_SHIFT 6
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +010056
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)
Jeenu Viswambharan34392302018-01-17 12:30:11 +000085#define SDEI_MAPF_EXPLICIT BIT(_SDEI_MAPF_EXPLICIT_SHIFT)
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +010086
87#define SDEI_MAPF_SIGNALABLE BIT(_SDEI_MAPF_SIGNALABLE_SHIFT)
88#define SDEI_MAPF_PRIVATE BIT(_SDEI_MAPF_PRIVATE_SHIFT)
Jeenu Viswambharan34392302018-01-17 12:30:11 +000089
90#define SDEI_MAPF_NORMAL 0
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +010091#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
Jeenu Viswambharan34392302018-01-17 12:30:11 +0000121#define SDEI_EXPLICIT_EVENT(_event, _pri) \
122 SDEI_EVENT_MAP(_event, 0, _pri | SDEI_MAPF_EXPLICIT | SDEI_MAPF_PRIVATE)
123
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100124/*
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
146typedef uint8_t sdei_state_t;
147
148/* Runtime data of SDEI event */
149typedef 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 */
160typedef 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_* */
Jeenu Viswambharan2b4054d2017-11-14 15:35:41 +0000164 int reg_count; /* Registration count */
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100165 spinlock_t lock; /* Per-event lock */
166} sdei_ev_map_t;
167
168typedef 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 */
174uint64_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
183void sdei_init(void);
184
Jeenu Viswambharancf1f2212017-10-02 12:10:54 +0100185/* Public API to dispatch an event to Normal world */
Jeenu Viswambharan8b7e6bc2018-02-16 12:07:48 +0000186int sdei_dispatch_event(int ev_num);
Jeenu Viswambharancf1f2212017-10-02 12:10:54 +0100187
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100188#endif /* __SDEI_H__ */