1 /* 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 139 typedef uint8_t sdei_state_t; 140 141 /* Runtime data of SDEI event */ 142 typedef 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 */ 153 typedef 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 int reg_count; /* Registration count */ 158 spinlock_t lock; /* Per-event lock */ 159 } sdei_ev_map_t; 160 161 typedef 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 */ 167 uint64_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 176 void sdei_init(void); 177 178 /* Public API to dispatch an event to Normal world */ 179 int sdei_dispatch_event(int ev_num, unsigned int preempted_sec_state); 180 181 #endif /* __SDEI_H__ */ 182