1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2017-2022, Arm Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #ifndef SDEI_H 8*91f16700Schasinglulu #define SDEI_H 9*91f16700Schasinglulu 10*91f16700Schasinglulu #include <lib/spinlock.h> 11*91f16700Schasinglulu #include <lib/utils_def.h> 12*91f16700Schasinglulu #include <services/sdei_flags.h> 13*91f16700Schasinglulu 14*91f16700Schasinglulu /* Range 0xC4000020 - 0xC400003F reserved for SDE 64bit smc calls */ 15*91f16700Schasinglulu #define SDEI_VERSION 0xC4000020U 16*91f16700Schasinglulu #define SDEI_EVENT_REGISTER 0xC4000021U 17*91f16700Schasinglulu #define SDEI_EVENT_ENABLE 0xC4000022U 18*91f16700Schasinglulu #define SDEI_EVENT_DISABLE 0xC4000023U 19*91f16700Schasinglulu #define SDEI_EVENT_CONTEXT 0xC4000024U 20*91f16700Schasinglulu #define SDEI_EVENT_COMPLETE 0xC4000025U 21*91f16700Schasinglulu #define SDEI_EVENT_COMPLETE_AND_RESUME 0xC4000026U 22*91f16700Schasinglulu 23*91f16700Schasinglulu #define SDEI_EVENT_UNREGISTER 0xC4000027U 24*91f16700Schasinglulu #define SDEI_EVENT_STATUS 0xC4000028U 25*91f16700Schasinglulu #define SDEI_EVENT_GET_INFO 0xC4000029U 26*91f16700Schasinglulu #define SDEI_EVENT_ROUTING_SET 0xC400002AU 27*91f16700Schasinglulu #define SDEI_PE_MASK 0xC400002BU 28*91f16700Schasinglulu #define SDEI_PE_UNMASK 0xC400002CU 29*91f16700Schasinglulu 30*91f16700Schasinglulu #define SDEI_INTERRUPT_BIND 0xC400002DU 31*91f16700Schasinglulu #define SDEI_INTERRUPT_RELEASE 0xC400002EU 32*91f16700Schasinglulu #define SDEI_EVENT_SIGNAL 0xC400002FU 33*91f16700Schasinglulu #define SDEI_FEATURES 0xC4000030U 34*91f16700Schasinglulu #define SDEI_PRIVATE_RESET 0xC4000031U 35*91f16700Schasinglulu #define SDEI_SHARED_RESET 0xC4000032U 36*91f16700Schasinglulu 37*91f16700Schasinglulu /* SDEI_EVENT_REGISTER flags */ 38*91f16700Schasinglulu #define SDEI_REGF_RM_ANY 0ULL 39*91f16700Schasinglulu #define SDEI_REGF_RM_PE 1ULL 40*91f16700Schasinglulu 41*91f16700Schasinglulu /* SDEI_EVENT_COMPLETE status flags */ 42*91f16700Schasinglulu #define SDEI_EV_HANDLED 0U 43*91f16700Schasinglulu #define SDEI_EV_FAILED 1U 44*91f16700Schasinglulu 45*91f16700Schasinglulu /* Indices of private and shared mappings */ 46*91f16700Schasinglulu #define SDEI_MAP_IDX_PRIV_ 0U 47*91f16700Schasinglulu #define SDEI_MAP_IDX_SHRD_ 1U 48*91f16700Schasinglulu #define SDEI_MAP_IDX_MAX_ 2U 49*91f16700Schasinglulu 50*91f16700Schasinglulu /* The macros below are used to identify SDEI calls from the SMC function ID */ 51*91f16700Schasinglulu #define SDEI_FID_MASK U(0xffe0) 52*91f16700Schasinglulu #define SDEI_FID_VALUE U(0x20) 53*91f16700Schasinglulu #define is_sdei_fid(_fid) \ 54*91f16700Schasinglulu ((((_fid) & SDEI_FID_MASK) == SDEI_FID_VALUE) && \ 55*91f16700Schasinglulu (((_fid >> FUNCID_CC_SHIFT) & FUNCID_CC_MASK) == SMC_64)) 56*91f16700Schasinglulu 57*91f16700Schasinglulu #define SDEI_EVENT_MAP(_event, _intr, _flags) \ 58*91f16700Schasinglulu { \ 59*91f16700Schasinglulu .ev_num = (_event), \ 60*91f16700Schasinglulu .intr = (_intr), \ 61*91f16700Schasinglulu .map_flags = (_flags) \ 62*91f16700Schasinglulu } 63*91f16700Schasinglulu 64*91f16700Schasinglulu #define SDEI_SHARED_EVENT(_event, _intr, _flags) \ 65*91f16700Schasinglulu SDEI_EVENT_MAP(_event, _intr, _flags) 66*91f16700Schasinglulu 67*91f16700Schasinglulu #define SDEI_PRIVATE_EVENT(_event, _intr, _flags) \ 68*91f16700Schasinglulu SDEI_EVENT_MAP(_event, _intr, (_flags) | SDEI_MAPF_PRIVATE) 69*91f16700Schasinglulu 70*91f16700Schasinglulu #define SDEI_DEFINE_EVENT_0(_intr) \ 71*91f16700Schasinglulu SDEI_PRIVATE_EVENT(SDEI_EVENT_0, (_intr), SDEI_MAPF_SIGNALABLE) 72*91f16700Schasinglulu 73*91f16700Schasinglulu #define SDEI_EXPLICIT_EVENT(_event, _pri) \ 74*91f16700Schasinglulu SDEI_EVENT_MAP((_event), 0, (_pri) | SDEI_MAPF_EXPLICIT | SDEI_MAPF_PRIVATE) 75*91f16700Schasinglulu 76*91f16700Schasinglulu /* 77*91f16700Schasinglulu * Declare shared and private entries for each core. Also declare a global 78*91f16700Schasinglulu * structure containing private and share entries. 79*91f16700Schasinglulu * 80*91f16700Schasinglulu * This macro must be used in the same file as the platform SDEI mappings are 81*91f16700Schasinglulu * declared. Only then would ARRAY_SIZE() yield a meaningful value. 82*91f16700Schasinglulu */ 83*91f16700Schasinglulu #define REGISTER_SDEI_MAP(_private, _shared) \ 84*91f16700Schasinglulu sdei_entry_t sdei_private_event_table \ 85*91f16700Schasinglulu [PLATFORM_CORE_COUNT * ARRAY_SIZE(_private)]; \ 86*91f16700Schasinglulu sdei_entry_t sdei_shared_event_table[ARRAY_SIZE(_shared)]; \ 87*91f16700Schasinglulu const sdei_mapping_t sdei_global_mappings[] = { \ 88*91f16700Schasinglulu [SDEI_MAP_IDX_PRIV_] = { \ 89*91f16700Schasinglulu .map = (_private), \ 90*91f16700Schasinglulu .num_maps = ARRAY_SIZE(_private) \ 91*91f16700Schasinglulu }, \ 92*91f16700Schasinglulu [SDEI_MAP_IDX_SHRD_] = { \ 93*91f16700Schasinglulu .map = (_shared), \ 94*91f16700Schasinglulu .num_maps = ARRAY_SIZE(_shared) \ 95*91f16700Schasinglulu }, \ 96*91f16700Schasinglulu } 97*91f16700Schasinglulu 98*91f16700Schasinglulu typedef uint8_t sdei_state_t; 99*91f16700Schasinglulu 100*91f16700Schasinglulu /* Runtime data of SDEI event */ 101*91f16700Schasinglulu typedef struct sdei_entry { 102*91f16700Schasinglulu uint64_t ep; /* Entry point */ 103*91f16700Schasinglulu uint64_t arg; /* Entry point argument */ 104*91f16700Schasinglulu uint64_t affinity; /* Affinity of shared event */ 105*91f16700Schasinglulu unsigned int reg_flags; /* Registration flags */ 106*91f16700Schasinglulu 107*91f16700Schasinglulu /* Event handler states: registered, enabled, running */ 108*91f16700Schasinglulu sdei_state_t state; 109*91f16700Schasinglulu } sdei_entry_t; 110*91f16700Schasinglulu 111*91f16700Schasinglulu /* Mapping of SDEI events to interrupts, and associated data */ 112*91f16700Schasinglulu typedef struct sdei_ev_map { 113*91f16700Schasinglulu int32_t ev_num; /* Event number */ 114*91f16700Schasinglulu unsigned int intr; /* Physical interrupt number for a bound map */ 115*91f16700Schasinglulu unsigned int map_flags; /* Mapping flags, see SDEI_MAPF_* */ 116*91f16700Schasinglulu int reg_count; /* Registration count */ 117*91f16700Schasinglulu spinlock_t lock; /* Per-event lock */ 118*91f16700Schasinglulu } sdei_ev_map_t; 119*91f16700Schasinglulu 120*91f16700Schasinglulu typedef struct sdei_mapping { 121*91f16700Schasinglulu sdei_ev_map_t *map; 122*91f16700Schasinglulu size_t num_maps; 123*91f16700Schasinglulu } sdei_mapping_t; 124*91f16700Schasinglulu 125*91f16700Schasinglulu /* Handler to be called to handle SDEI smc calls */ 126*91f16700Schasinglulu uint64_t sdei_smc_handler(uint32_t smc_fid, 127*91f16700Schasinglulu uint64_t x1, 128*91f16700Schasinglulu uint64_t x2, 129*91f16700Schasinglulu uint64_t x3, 130*91f16700Schasinglulu uint64_t x4, 131*91f16700Schasinglulu void *cookie, 132*91f16700Schasinglulu void *handle, 133*91f16700Schasinglulu uint64_t flags); 134*91f16700Schasinglulu 135*91f16700Schasinglulu void sdei_init(void); 136*91f16700Schasinglulu 137*91f16700Schasinglulu /* Public API to dispatch an event to Normal world */ 138*91f16700Schasinglulu int sdei_dispatch_event(int ev_num); 139*91f16700Schasinglulu 140*91f16700Schasinglulu /* Public API to check how many SDEI events are registered. */ 141*91f16700Schasinglulu int sdei_get_registered_event_count(void); 142*91f16700Schasinglulu 143*91f16700Schasinglulu #endif /* SDEI_H */ 144