blob: 4d0fd3fd34ace9209ab27e0e341b05427fdf0fe3 [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
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +01007#ifndef SDEI_H
8#define SDEI_H
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +01009
10#include <spinlock.h>
11#include <utils_def.h>
12
13/* Range 0xC4000020 - 0xC400003F reserved for SDE 64bit smc calls */
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +010014#define SDEI_VERSION 0xC4000020U
15#define SDEI_EVENT_REGISTER 0xC4000021U
16#define SDEI_EVENT_ENABLE 0xC4000022U
17#define SDEI_EVENT_DISABLE 0xC4000023U
18#define SDEI_EVENT_CONTEXT 0xC4000024U
19#define SDEI_EVENT_COMPLETE 0xC4000025U
20#define SDEI_EVENT_COMPLETE_AND_RESUME 0xC4000026U
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +010021
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +010022#define SDEI_EVENT_UNREGISTER 0xC4000027U
23#define SDEI_EVENT_STATUS 0xC4000028U
24#define SDEI_EVENT_GET_INFO 0xC4000029U
25#define SDEI_EVENT_ROUTING_SET 0xC400002AU
26#define SDEI_PE_MASK 0xC400002BU
27#define SDEI_PE_UNMASK 0xC400002CU
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +010028
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +010029#define SDEI_INTERRUPT_BIND 0xC400002DU
30#define SDEI_INTERRUPT_RELEASE 0xC400002EU
31#define SDEI_EVENT_SIGNAL 0xC400002FU
32#define SDEI_FEATURES 0xC4000030U
33#define SDEI_PRIVATE_RESET 0xC4000031U
34#define SDEI_SHARED_RESET 0xC4000032U
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +010035
36/* SDEI_EVENT_REGISTER flags */
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +010037#define SDEI_REGF_RM_ANY 0ULL
38#define SDEI_REGF_RM_PE 1ULL
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +010039
40/* SDEI_EVENT_COMPLETE status flags */
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +010041#define SDEI_EV_HANDLED 0U
42#define SDEI_EV_FAILED 1U
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +010043
44/* Internal: SDEI flag bit positions */
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +010045#define SDEI_MAPF_DYNAMIC_SHIFT_ 1U
46#define SDEI_MAPF_BOUND_SHIFT_ 2U
47#define SDEI_MAPF_SIGNALABLE_SHIFT_ 3U
48#define SDEI_MAPF_PRIVATE_SHIFT_ 4U
49#define SDEI_MAPF_CRITICAL_SHIFT_ 5U
50#define SDEI_MAPF_EXPLICIT_SHIFT_ 6U
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +010051
52/* SDEI event 0 */
53#define SDEI_EVENT_0 0
54
55/* Placeholder interrupt for dynamic mapping */
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +010056#define SDEI_DYN_IRQ 0U
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +010057
58/* SDEI flags */
59
60/*
61 * These flags determine whether or not an event can be associated with an
62 * interrupt. Static events are permanently associated with an interrupt, and
63 * can't be changed at runtime. Association of dynamic events with interrupts
64 * can be changed at run time using the SDEI_INTERRUPT_BIND and
65 * SDEI_INTERRUPT_RELEASE calls.
66 *
67 * SDEI_MAPF_DYNAMIC only indicates run time configurability, where as
68 * SDEI_MAPF_BOUND indicates interrupt association. For example:
69 *
70 * - Calling SDEI_INTERRUPT_BIND on a dynamic event will have both
71 * SDEI_MAPF_DYNAMIC and SDEI_MAPF_BOUND set.
72 *
73 * - Statically-bound events will always have SDEI_MAPF_BOUND set, and neither
74 * SDEI_INTERRUPT_BIND nor SDEI_INTERRUPT_RELEASE can be called on them.
75 *
76 * See also the is_map_bound() macro.
77 */
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +010078#define SDEI_MAPF_DYNAMIC BIT(SDEI_MAPF_DYNAMIC_SHIFT_)
79#define SDEI_MAPF_BOUND BIT(SDEI_MAPF_BOUND_SHIFT_)
80#define SDEI_MAPF_EXPLICIT BIT(SDEI_MAPF_EXPLICIT_SHIFT_)
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +010081
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +010082#define SDEI_MAPF_SIGNALABLE BIT(SDEI_MAPF_SIGNALABLE_SHIFT_)
83#define SDEI_MAPF_PRIVATE BIT(SDEI_MAPF_PRIVATE_SHIFT_)
Jeenu Viswambharan34392302018-01-17 12:30:11 +000084
85#define SDEI_MAPF_NORMAL 0
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +010086#define SDEI_MAPF_CRITICAL BIT(SDEI_MAPF_CRITICAL_SHIFT_)
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +010087
88/* Indices of private and shared mappings */
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +010089#define SDEI_MAP_IDX_PRIV_ 0U
90#define SDEI_MAP_IDX_SHRD_ 1U
91#define SDEI_MAP_IDX_MAX_ 2U
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +010092
93/* The macros below are used to identify SDEI calls from the SMC function ID */
94#define SDEI_FID_MASK U(0xffe0)
95#define SDEI_FID_VALUE U(0x20)
96#define is_sdei_fid(_fid) \
97 ((((_fid) & SDEI_FID_MASK) == SDEI_FID_VALUE) && \
98 (((_fid >> FUNCID_CC_SHIFT) & FUNCID_CC_MASK) == SMC_64))
99
100#define SDEI_EVENT_MAP(_event, _intr, _flags) \
101 { \
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +0100102 .ev_num = (_event), \
103 .intr = (_intr), \
104 .map_flags = (_flags) \
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100105 }
106
107#define SDEI_SHARED_EVENT(_event, _intr, _flags) \
108 SDEI_EVENT_MAP(_event, _intr, _flags)
109
110#define SDEI_PRIVATE_EVENT(_event, _intr, _flags) \
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +0100111 SDEI_EVENT_MAP(_event, _intr, (_flags) | SDEI_MAPF_PRIVATE)
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100112
113#define SDEI_DEFINE_EVENT_0(_intr) \
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +0100114 SDEI_PRIVATE_EVENT(SDEI_EVENT_0, (_intr), SDEI_MAPF_SIGNALABLE)
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100115
Jeenu Viswambharan34392302018-01-17 12:30:11 +0000116#define SDEI_EXPLICIT_EVENT(_event, _pri) \
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +0100117 SDEI_EVENT_MAP((_event), 0, (_pri) | SDEI_MAPF_EXPLICIT | SDEI_MAPF_PRIVATE)
Jeenu Viswambharan34392302018-01-17 12:30:11 +0000118
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100119/*
120 * Declare shared and private entries for each core. Also declare a global
121 * structure containing private and share entries.
122 *
123 * This macro must be used in the same file as the platform SDEI mappings are
124 * declared. Only then would ARRAY_SIZE() yield a meaningful value.
125 */
126#define REGISTER_SDEI_MAP(_private, _shared) \
127 sdei_entry_t sdei_private_event_table \
128 [PLATFORM_CORE_COUNT * ARRAY_SIZE(_private)]; \
129 sdei_entry_t sdei_shared_event_table[ARRAY_SIZE(_shared)]; \
130 const sdei_mapping_t sdei_global_mappings[] = { \
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +0100131 [SDEI_MAP_IDX_PRIV_] = { \
132 .map = (_private), \
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100133 .num_maps = ARRAY_SIZE(_private) \
134 }, \
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +0100135 [SDEI_MAP_IDX_SHRD_] = { \
136 .map = (_shared), \
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100137 .num_maps = ARRAY_SIZE(_shared) \
138 }, \
139 }
140
141typedef uint8_t sdei_state_t;
142
143/* Runtime data of SDEI event */
144typedef struct sdei_entry {
145 uint64_t ep; /* Entry point */
146 uint64_t arg; /* Entry point argument */
147 uint64_t affinity; /* Affinity of shared event */
148 unsigned int reg_flags; /* Registration flags */
149
150 /* Event handler states: registered, enabled, running */
151 sdei_state_t state;
152} sdei_entry_t;
153
154/* Mapping of SDEI events to interrupts, and associated data */
155typedef struct sdei_ev_map {
156 int32_t ev_num; /* Event number */
157 unsigned int intr; /* Physical interrupt number for a bound map */
158 unsigned int map_flags; /* Mapping flags, see SDEI_MAPF_* */
Jeenu Viswambharan2b4054d2017-11-14 15:35:41 +0000159 int reg_count; /* Registration count */
Jeenu Viswambharan04e3a7f2017-10-16 08:43:14 +0100160 spinlock_t lock; /* Per-event lock */
161} sdei_ev_map_t;
162
163typedef struct sdei_mapping {
164 sdei_ev_map_t *map;
165 size_t num_maps;
166} sdei_mapping_t;
167
168/* Handler to be called to handle SDEI smc calls */
169uint64_t sdei_smc_handler(uint32_t smc_fid,
170 uint64_t x1,
171 uint64_t x2,
172 uint64_t x3,
173 uint64_t x4,
174 void *cookie,
175 void *handle,
176 uint64_t flags);
177
178void sdei_init(void);
179
Jeenu Viswambharancf1f2212017-10-02 12:10:54 +0100180/* Public API to dispatch an event to Normal world */
Jeenu Viswambharan8b7e6bc2018-02-16 12:07:48 +0000181int sdei_dispatch_event(int ev_num);
Jeenu Viswambharancf1f2212017-10-02 12:10:54 +0100182
Jeenu Viswambharan32ceef52018-08-02 10:14:12 +0100183#endif /* SDEI_H */