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