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