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