1 /* 2 * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #ifndef GICV5_H 8 #define GICV5_H 9 10 #ifndef __ASSEMBLER__ 11 #include <stdbool.h> 12 #include <stdint.h> 13 14 #include <lib/mmio.h> 15 #endif 16 17 #include <lib/utils_def.h> 18 19 /* Interrupt Domain definitions */ 20 #define INTDMN_S 0 21 #define INTDMN_NS 1 22 #define INTDMN_EL3 2 23 #define INTDMN_RL 3 24 25 /* Trigger modes */ 26 #define TM_EDGE 0 27 #define TM_LEVEL 1 28 29 /* Architected PPI numbers */ 30 #define PPI_TRBIRQ 31 31 #define PPI_CNTP 30 32 #define PPI_CNTPS 29 33 #define PPI_CNTHV 28 34 #define PPI_CNTV 27 35 #define PPI_CNTHP 26 36 #define PPI_GICMNT 25 37 #define PPI_CTIIRQ 24 38 #define PPI_PMUIRQ 23 39 #define PPI_COMMIRQ 22 40 #define PPI_PMBIRQ 21 41 #define PPI_CNTHPS 20 42 #define PPI_CNTHVS 19 43 #define PPI_DB_NS 2 44 #define PPI_DB_RL 1 45 #define PPI_DB_S 0 46 47 /* IRS register fields */ 48 #define IRS_IDR6_SPI_IRS_RANGE_SHIFT 0 49 #define IRS_IDR6_SPI_IRS_RANGE_WIDTH 24 50 #define IRS_IDR7_SPI_BASE_SHIFT 0 51 #define IRS_IDR7_SPI_BASE_WIDTH 24 52 53 #define IRS_SPI_STATUSR_IDLE_BIT BIT(0) 54 #define IRS_SPI_STATUSR_V_BIT BIT(1) 55 56 /* IWB register fields */ 57 #define IWB_IDR0_DOMAINS_SHIFT 11 58 #define IWB_IDR0_DOMAINS_WIDTH 4 59 #define IWB_IDR0_IWRANGE_SHIFT 0 60 #define IWB_IDR0_IWRANGE_WIDTH 10 61 62 #define IWB_CR0_IWBEN_BIT BIT(0) 63 #define IWB_CR0_IDLE_BIT BIT(1) 64 65 #define IWB_WENABLE_STATUSR_IDLE_BIT BIT(0) 66 #define IWB_WDOMAIN_STATUSR_IDLE_BIT BIT(0) 67 68 #define IWB_WDOMAINR_DOMAINX_MASK 0x3 69 70 #ifndef __ASSEMBLER__ 71 72 #define _PPI_FIELD_SHIFT(_REG, _ppi_id) \ 73 ((_ppi_id % (ICC_PPI_##_REG##_COUNT)) * (64 / ICC_PPI_##_REG##_COUNT)) 74 75 #define write_icc_ppi_domainr(_var, _ppi_id, _value) \ 76 do { \ 77 _var |= (uint64_t)_value << _PPI_FIELD_SHIFT(DOMAINR, _ppi_id);\ 78 } while (false) 79 80 81 #define DEFINE_GICV5_MMIO_WRITE_FUNC(_name, _offset) \ 82 static inline void write_##_name(uintptr_t base, uint32_t val) \ 83 { \ 84 mmio_write_32(base + _offset, val); \ 85 } 86 87 #define DEFINE_GICV5_MMIO_READ_FUNC(_name, _offset) \ 88 static inline uint32_t read_##_name(uintptr_t base) \ 89 { \ 90 return mmio_read_32(base + _offset); \ 91 } 92 93 #define DEFINE_GICV5_MMIO_WRITE_INDEXED_FUNC(_name, _offset) \ 94 static inline void write_##_name(uintptr_t base, uint16_t index, uint32_t val) \ 95 { \ 96 mmio_write_32(base + _offset + (index * sizeof(uint32_t)), val); \ 97 } 98 99 #define DEFINE_GICV5_MMIO_READ_INDEXED_FUNC(_name, _offset) \ 100 static inline uint32_t read_##_name(uintptr_t base, uint16_t index) \ 101 { \ 102 return mmio_read_32(base + _offset + (index * sizeof(uint32_t))); \ 103 } 104 105 #define DEFINE_GICV5_MMIO_RW_FUNCS(_name, _offset) \ 106 DEFINE_GICV5_MMIO_READ_FUNC(_name, _offset) \ 107 DEFINE_GICV5_MMIO_WRITE_FUNC(_name, _offset) 108 109 #define DEFINE_GICV5_MMIO_RW_INDEXED_FUNCS(_name, _offset) \ 110 DEFINE_GICV5_MMIO_READ_INDEXED_FUNC(_name, _offset) \ 111 DEFINE_GICV5_MMIO_WRITE_INDEXED_FUNC(_name, _offset) 112 113 DEFINE_GICV5_MMIO_READ_FUNC(iwb_idr0, 0x00) 114 DEFINE_GICV5_MMIO_RW_FUNCS( iwb_cr0, 0x80) 115 DEFINE_GICV5_MMIO_READ_FUNC(iwb_wenable_statusr, 0xc0) 116 DEFINE_GICV5_MMIO_READ_FUNC(iwb_wdomain_statusr, 0xc4) 117 DEFINE_GICV5_MMIO_RW_INDEXED_FUNCS(iwb_wenabler, 0x2000) 118 DEFINE_GICV5_MMIO_RW_INDEXED_FUNCS(iwb_wtmr, 0x4000) 119 DEFINE_GICV5_MMIO_RW_INDEXED_FUNCS(iwb_wdomainr, 0x6000) 120 121 DEFINE_GICV5_MMIO_READ_FUNC(irs_idr6, 0x0018) 122 DEFINE_GICV5_MMIO_READ_FUNC(irs_idr7, 0x001c) 123 DEFINE_GICV5_MMIO_RW_FUNCS( irs_spi_selr, 0x0108) 124 DEFINE_GICV5_MMIO_RW_FUNCS( irs_spi_domainr, 0x010c) 125 DEFINE_GICV5_MMIO_RW_FUNCS( irs_spi_cfgr, 0x0114) 126 DEFINE_GICV5_MMIO_READ_FUNC(irs_spi_statusr, 0x0118) 127 128 #define WAIT_FOR_IDLE(base, reg, reg_up) \ 129 do { \ 130 while ((read_##reg(base) & reg_up##_IDLE_BIT) == 0U) {} \ 131 } while (0) 132 133 /* wait for IDLE but also check the V bit was set */ 134 #define WAIT_FOR_VIDLE(base, reg, reg_up) \ 135 do { \ 136 uint32_t val; \ 137 while (((val = read_##reg(base)) & reg_up##_IDLE_BIT) == 0U) {} \ 138 assert((val & reg##_V_BIT) != 0U); \ 139 } while (0) 140 141 #define WAIT_FOR_VIDLE_IRS_SPI_STATUSR(base) \ 142 WAIT_FOR_IDLE(base, irs_spi_statusr, IRS_SPI_STATUSR) 143 144 #define WAIT_FOR_IDLE_IWB_WENABLE_STATUSR(base) \ 145 WAIT_FOR_IDLE(base, iwb_wenable_statusr, IWB_WENABLE_STATUSR) 146 #define WAIT_FOR_IDLE_IWB_WDOMAIN_STATUSR(base) \ 147 WAIT_FOR_IDLE(base, iwb_wdomain_statusr, IWB_WDOMAIN_STATUSR) 148 #define WAIT_FOR_IDLE_IWB_CR0(base) \ 149 WAIT_FOR_IDLE(base, iwb_cr0, IWB_CR0) 150 151 struct gicv5_wire_props { 152 /* continuous wire ID as seen by the attached component */ 153 uint32_t id; 154 /* use the INTDMN_XYZ macros */ 155 uint8_t domain:2; 156 /* use the TM_XYZ (eg. TM_EDGE) macros */ 157 uint8_t tm:1; 158 }; 159 160 /* to describe every IRS in the system */ 161 struct gicv5_irs { 162 /* mapped device nGnRnE by the platform*/ 163 uintptr_t el3_config_frame; 164 struct gicv5_wire_props *spis; 165 uint32_t num_spis; 166 }; 167 168 /* 169 * to describe every IWB in the system where EL3 is the MPPAS. IWBs that have 170 * another world as an MPPAS need not be included 171 */ 172 struct gicv5_iwb { 173 /* mapped device nGnRnE by the platform*/ 174 uintptr_t config_frame; 175 struct gicv5_wire_props *wires; 176 uint32_t num_wires; 177 }; 178 179 struct gicv5_driver_data { 180 struct gicv5_irs *irss; 181 struct gicv5_iwb *iwbs; 182 uint32_t num_irss; 183 uint32_t num_iwbs; 184 }; 185 186 extern const struct gicv5_driver_data plat_gicv5_driver_data; 187 188 void gicv5_driver_init(); 189 uint8_t gicv5_get_pending_interrupt_type(void); 190 bool gicv5_has_interrupt_type(unsigned int type); 191 void gicv5_enable_ppis(); 192 #endif /* __ASSEMBLER__ */ 193 #endif /* GICV5_H */ 194