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