18cef63d6SBoyan Karatotev /* 28cef63d6SBoyan Karatotev * Copyright (c) 2025, Arm Limited and Contributors. All rights reserved. 38cef63d6SBoyan Karatotev * 48cef63d6SBoyan Karatotev * SPDX-License-Identifier: BSD-3-Clause 58cef63d6SBoyan Karatotev */ 68cef63d6SBoyan Karatotev 78cef63d6SBoyan Karatotev #ifndef GICV5_H 88cef63d6SBoyan Karatotev #define GICV5_H 913b62814SBoyan Karatotev 1013b62814SBoyan Karatotev #ifndef __ASSEMBLER__ 1113b62814SBoyan Karatotev #include <stdbool.h> 1213b62814SBoyan Karatotev #include <stdint.h> 13dfb37a2dSBoyan Karatotev 14dfb37a2dSBoyan Karatotev #include <lib/mmio.h> 1513b62814SBoyan Karatotev #endif 1613b62814SBoyan Karatotev 1713b62814SBoyan Karatotev #include <lib/utils_def.h> 1813b62814SBoyan Karatotev 1913b62814SBoyan Karatotev /* Interrupt Domain definitions */ 2013b62814SBoyan Karatotev #define INTDMN_S 0 2113b62814SBoyan Karatotev #define INTDMN_NS 1 2213b62814SBoyan Karatotev #define INTDMN_EL3 2 2313b62814SBoyan Karatotev #define INTDMN_RL 3 2413b62814SBoyan Karatotev 2513b62814SBoyan Karatotev /* Trigger modes */ 2613b62814SBoyan Karatotev #define TM_EDGE 0 2713b62814SBoyan Karatotev #define TM_LEVEL 1 2813b62814SBoyan Karatotev 2982b228baSBoyan Karatotev /* Architected PPI numbers */ 3082b228baSBoyan Karatotev #define PPI_TRBIRQ 31 3182b228baSBoyan Karatotev #define PPI_CNTP 30 3282b228baSBoyan Karatotev #define PPI_CNTPS 29 3382b228baSBoyan Karatotev #define PPI_CNTHV 28 3482b228baSBoyan Karatotev #define PPI_CNTV 27 3582b228baSBoyan Karatotev #define PPI_CNTHP 26 3682b228baSBoyan Karatotev #define PPI_GICMNT 25 3782b228baSBoyan Karatotev #define PPI_CTIIRQ 24 3882b228baSBoyan Karatotev #define PPI_PMUIRQ 23 3982b228baSBoyan Karatotev #define PPI_COMMIRQ 22 4082b228baSBoyan Karatotev #define PPI_PMBIRQ 21 4182b228baSBoyan Karatotev #define PPI_CNTHPS 20 4282b228baSBoyan Karatotev #define PPI_CNTHVS 19 4382b228baSBoyan Karatotev #define PPI_DB_NS 2 4482b228baSBoyan Karatotev #define PPI_DB_RL 1 4582b228baSBoyan Karatotev #define PPI_DB_S 0 4682b228baSBoyan Karatotev 474db6bf9fSBoyan Karatotev /* Register fields common to all IRI components. 484db6bf9fSBoyan Karatotev * They have the same name and offset in every config frame */ 494db6bf9fSBoyan Karatotev #define IRI_AIDR_COMPONENT_SHIFT 8 504db6bf9fSBoyan Karatotev #define IRI_AIDR_COMPONENT_WIDTH 4 514db6bf9fSBoyan Karatotev #define IRI_AIDR_COMPONENT_IRS 0 524db6bf9fSBoyan Karatotev #define IRI_AIDR_COMPONENT_ITS 1 534db6bf9fSBoyan Karatotev #define IRI_AIDR_COMPONENT_IWB 2 544db6bf9fSBoyan Karatotev #define IRI_AIDR_ARCH_MAJOR_SHIFT 4 554db6bf9fSBoyan Karatotev #define IRI_AIDR_ARCH_MAJOR_WIDTH 4 564db6bf9fSBoyan Karatotev #define IRI_AIDR_ARCH_MAJOR_V5 0 574db6bf9fSBoyan Karatotev #define IRI_AIDR_ARCH_MINOR_SHIFT 0 584db6bf9fSBoyan Karatotev #define IRI_AIDR_ARCH_MINOR_WIDTH 4 594db6bf9fSBoyan Karatotev #define IRI_AIDR_ARCH_MINOR_P0 0 604db6bf9fSBoyan Karatotev 61dfb37a2dSBoyan Karatotev /* IRS register fields */ 62dfb37a2dSBoyan Karatotev #define IRS_IDR6_SPI_IRS_RANGE_SHIFT 0 63dfb37a2dSBoyan Karatotev #define IRS_IDR6_SPI_IRS_RANGE_WIDTH 24 64dfb37a2dSBoyan Karatotev #define IRS_IDR7_SPI_BASE_SHIFT 0 65dfb37a2dSBoyan Karatotev #define IRS_IDR7_SPI_BASE_WIDTH 24 66dfb37a2dSBoyan Karatotev 67dfb37a2dSBoyan Karatotev #define IRS_SPI_STATUSR_IDLE_BIT BIT(0) 68dfb37a2dSBoyan Karatotev #define IRS_SPI_STATUSR_V_BIT BIT(1) 69dfb37a2dSBoyan Karatotev 7071799209SBoyan Karatotev /* IWB register fields */ 7171799209SBoyan Karatotev #define IWB_IDR0_DOMAINS_SHIFT 11 7271799209SBoyan Karatotev #define IWB_IDR0_DOMAINS_WIDTH 4 7371799209SBoyan Karatotev #define IWB_IDR0_IWRANGE_SHIFT 0 7471799209SBoyan Karatotev #define IWB_IDR0_IWRANGE_WIDTH 10 7571799209SBoyan Karatotev 7671799209SBoyan Karatotev #define IWB_CR0_IWBEN_BIT BIT(0) 7771799209SBoyan Karatotev #define IWB_CR0_IDLE_BIT BIT(1) 7871799209SBoyan Karatotev 7971799209SBoyan Karatotev #define IWB_WENABLE_STATUSR_IDLE_BIT BIT(0) 8071799209SBoyan Karatotev #define IWB_WDOMAIN_STATUSR_IDLE_BIT BIT(0) 8171799209SBoyan Karatotev 8271799209SBoyan Karatotev #define IWB_WDOMAINR_DOMAINX_MASK 0x3 8371799209SBoyan Karatotev 8413b62814SBoyan Karatotev #ifndef __ASSEMBLER__ 8513b62814SBoyan Karatotev 8682b228baSBoyan Karatotev #define _PPI_FIELD_SHIFT(_REG, _ppi_id) \ 8782b228baSBoyan Karatotev ((_ppi_id % (ICC_PPI_##_REG##_COUNT)) * (64 / ICC_PPI_##_REG##_COUNT)) 8882b228baSBoyan Karatotev 8982b228baSBoyan Karatotev #define write_icc_ppi_domainr(_var, _ppi_id, _value) \ 9082b228baSBoyan Karatotev do { \ 9182b228baSBoyan Karatotev _var |= (uint64_t)_value << _PPI_FIELD_SHIFT(DOMAINR, _ppi_id);\ 9282b228baSBoyan Karatotev } while (false) 9382b228baSBoyan Karatotev 94dfb37a2dSBoyan Karatotev 95dfb37a2dSBoyan Karatotev #define DEFINE_GICV5_MMIO_WRITE_FUNC(_name, _offset) \ 96dfb37a2dSBoyan Karatotev static inline void write_##_name(uintptr_t base, uint32_t val) \ 97dfb37a2dSBoyan Karatotev { \ 98dfb37a2dSBoyan Karatotev mmio_write_32(base + _offset, val); \ 99dfb37a2dSBoyan Karatotev } 100dfb37a2dSBoyan Karatotev 101dfb37a2dSBoyan Karatotev #define DEFINE_GICV5_MMIO_READ_FUNC(_name, _offset) \ 102dfb37a2dSBoyan Karatotev static inline uint32_t read_##_name(uintptr_t base) \ 103dfb37a2dSBoyan Karatotev { \ 104dfb37a2dSBoyan Karatotev return mmio_read_32(base + _offset); \ 105dfb37a2dSBoyan Karatotev } 106dfb37a2dSBoyan Karatotev 10771799209SBoyan Karatotev #define DEFINE_GICV5_MMIO_WRITE_INDEXED_FUNC(_name, _offset) \ 10871799209SBoyan Karatotev static inline void write_##_name(uintptr_t base, uint16_t index, uint32_t val) \ 10971799209SBoyan Karatotev { \ 11071799209SBoyan Karatotev mmio_write_32(base + _offset + (index * sizeof(uint32_t)), val); \ 11171799209SBoyan Karatotev } 11271799209SBoyan Karatotev 11371799209SBoyan Karatotev #define DEFINE_GICV5_MMIO_READ_INDEXED_FUNC(_name, _offset) \ 11471799209SBoyan Karatotev static inline uint32_t read_##_name(uintptr_t base, uint16_t index) \ 11571799209SBoyan Karatotev { \ 11671799209SBoyan Karatotev return mmio_read_32(base + _offset + (index * sizeof(uint32_t))); \ 11771799209SBoyan Karatotev } 11871799209SBoyan Karatotev 119dfb37a2dSBoyan Karatotev #define DEFINE_GICV5_MMIO_RW_FUNCS(_name, _offset) \ 120dfb37a2dSBoyan Karatotev DEFINE_GICV5_MMIO_READ_FUNC(_name, _offset) \ 121dfb37a2dSBoyan Karatotev DEFINE_GICV5_MMIO_WRITE_FUNC(_name, _offset) 122dfb37a2dSBoyan Karatotev 12371799209SBoyan Karatotev #define DEFINE_GICV5_MMIO_RW_INDEXED_FUNCS(_name, _offset) \ 12471799209SBoyan Karatotev DEFINE_GICV5_MMIO_READ_INDEXED_FUNC(_name, _offset) \ 12571799209SBoyan Karatotev DEFINE_GICV5_MMIO_WRITE_INDEXED_FUNC(_name, _offset) 12671799209SBoyan Karatotev 1274db6bf9fSBoyan Karatotev DEFINE_GICV5_MMIO_READ_FUNC(iri_aidr, 0x44) 1284db6bf9fSBoyan Karatotev 12971799209SBoyan Karatotev DEFINE_GICV5_MMIO_READ_FUNC(iwb_idr0, 0x00) 13071799209SBoyan Karatotev DEFINE_GICV5_MMIO_RW_FUNCS( iwb_cr0, 0x80) 13171799209SBoyan Karatotev DEFINE_GICV5_MMIO_READ_FUNC(iwb_wenable_statusr, 0xc0) 13271799209SBoyan Karatotev DEFINE_GICV5_MMIO_READ_FUNC(iwb_wdomain_statusr, 0xc4) 13371799209SBoyan Karatotev DEFINE_GICV5_MMIO_RW_INDEXED_FUNCS(iwb_wenabler, 0x2000) 13471799209SBoyan Karatotev DEFINE_GICV5_MMIO_RW_INDEXED_FUNCS(iwb_wtmr, 0x4000) 135*a6d29969SBoyan Karatotev DEFINE_GICV5_MMIO_RW_INDEXED_FUNCS(iwb_wdomainr, 0x8000) 13671799209SBoyan Karatotev 137dfb37a2dSBoyan Karatotev DEFINE_GICV5_MMIO_READ_FUNC(irs_idr6, 0x0018) 138dfb37a2dSBoyan Karatotev DEFINE_GICV5_MMIO_READ_FUNC(irs_idr7, 0x001c) 139dfb37a2dSBoyan Karatotev DEFINE_GICV5_MMIO_RW_FUNCS( irs_spi_selr, 0x0108) 140dfb37a2dSBoyan Karatotev DEFINE_GICV5_MMIO_RW_FUNCS( irs_spi_domainr, 0x010c) 141dfb37a2dSBoyan Karatotev DEFINE_GICV5_MMIO_RW_FUNCS( irs_spi_cfgr, 0x0114) 142dfb37a2dSBoyan Karatotev DEFINE_GICV5_MMIO_READ_FUNC(irs_spi_statusr, 0x0118) 143dfb37a2dSBoyan Karatotev 144dfb37a2dSBoyan Karatotev #define WAIT_FOR_IDLE(base, reg, reg_up) \ 145dfb37a2dSBoyan Karatotev do { \ 146dfb37a2dSBoyan Karatotev while ((read_##reg(base) & reg_up##_IDLE_BIT) == 0U) {} \ 147dfb37a2dSBoyan Karatotev } while (0) 148dfb37a2dSBoyan Karatotev 149dfb37a2dSBoyan Karatotev /* wait for IDLE but also check the V bit was set */ 150dfb37a2dSBoyan Karatotev #define WAIT_FOR_VIDLE(base, reg, reg_up) \ 151dfb37a2dSBoyan Karatotev do { \ 152dfb37a2dSBoyan Karatotev uint32_t val; \ 153dfb37a2dSBoyan Karatotev while (((val = read_##reg(base)) & reg_up##_IDLE_BIT) == 0U) {} \ 154dfb37a2dSBoyan Karatotev assert((val & reg##_V_BIT) != 0U); \ 155dfb37a2dSBoyan Karatotev } while (0) 156dfb37a2dSBoyan Karatotev 157dfb37a2dSBoyan Karatotev #define WAIT_FOR_VIDLE_IRS_SPI_STATUSR(base) \ 158dfb37a2dSBoyan Karatotev WAIT_FOR_IDLE(base, irs_spi_statusr, IRS_SPI_STATUSR) 159dfb37a2dSBoyan Karatotev 16071799209SBoyan Karatotev #define WAIT_FOR_IDLE_IWB_WENABLE_STATUSR(base) \ 16171799209SBoyan Karatotev WAIT_FOR_IDLE(base, iwb_wenable_statusr, IWB_WENABLE_STATUSR) 16271799209SBoyan Karatotev #define WAIT_FOR_IDLE_IWB_WDOMAIN_STATUSR(base) \ 16371799209SBoyan Karatotev WAIT_FOR_IDLE(base, iwb_wdomain_statusr, IWB_WDOMAIN_STATUSR) 16471799209SBoyan Karatotev #define WAIT_FOR_IDLE_IWB_CR0(base) \ 16571799209SBoyan Karatotev WAIT_FOR_IDLE(base, iwb_cr0, IWB_CR0) 16671799209SBoyan Karatotev 167e2e90fa1SBoyan Karatotev #define WIRE_PROP_DESC(_id, _domain, _tm) \ 168e2e90fa1SBoyan Karatotev { \ 169e2e90fa1SBoyan Karatotev .id = (_id), \ 170e2e90fa1SBoyan Karatotev .domain = (_domain), \ 171e2e90fa1SBoyan Karatotev .tm = (_tm), \ 172e2e90fa1SBoyan Karatotev } 173e2e90fa1SBoyan Karatotev 174dfb37a2dSBoyan Karatotev struct gicv5_wire_props { 175dfb37a2dSBoyan Karatotev /* continuous wire ID as seen by the attached component */ 176dfb37a2dSBoyan Karatotev uint32_t id; 177dfb37a2dSBoyan Karatotev /* use the INTDMN_XYZ macros */ 178dfb37a2dSBoyan Karatotev uint8_t domain:2; 179dfb37a2dSBoyan Karatotev /* use the TM_XYZ (eg. TM_EDGE) macros */ 180dfb37a2dSBoyan Karatotev uint8_t tm:1; 181dfb37a2dSBoyan Karatotev }; 182dfb37a2dSBoyan Karatotev 183dfb37a2dSBoyan Karatotev /* to describe every IRS in the system */ 184dfb37a2dSBoyan Karatotev struct gicv5_irs { 185dfb37a2dSBoyan Karatotev /* mapped device nGnRnE by the platform*/ 186dfb37a2dSBoyan Karatotev uintptr_t el3_config_frame; 187dfb37a2dSBoyan Karatotev struct gicv5_wire_props *spis; 188dfb37a2dSBoyan Karatotev uint32_t num_spis; 189dfb37a2dSBoyan Karatotev }; 190dfb37a2dSBoyan Karatotev 19171799209SBoyan Karatotev /* 19271799209SBoyan Karatotev * to describe every IWB in the system where EL3 is the MPPAS. IWBs that have 19371799209SBoyan Karatotev * another world as an MPPAS need not be included 19471799209SBoyan Karatotev */ 19571799209SBoyan Karatotev struct gicv5_iwb { 19671799209SBoyan Karatotev /* mapped device nGnRnE by the platform*/ 19771799209SBoyan Karatotev uintptr_t config_frame; 19871799209SBoyan Karatotev struct gicv5_wire_props *wires; 19971799209SBoyan Karatotev uint32_t num_wires; 20071799209SBoyan Karatotev }; 20171799209SBoyan Karatotev 20213b62814SBoyan Karatotev struct gicv5_driver_data { 203dfb37a2dSBoyan Karatotev struct gicv5_irs *irss; 20471799209SBoyan Karatotev struct gicv5_iwb *iwbs; 205dfb37a2dSBoyan Karatotev uint32_t num_irss; 20671799209SBoyan Karatotev uint32_t num_iwbs; 20713b62814SBoyan Karatotev }; 20813b62814SBoyan Karatotev 20913b62814SBoyan Karatotev extern const struct gicv5_driver_data plat_gicv5_driver_data; 21013b62814SBoyan Karatotev 21113b62814SBoyan Karatotev void gicv5_driver_init(); 21213b62814SBoyan Karatotev uint8_t gicv5_get_pending_interrupt_type(void); 21313b62814SBoyan Karatotev bool gicv5_has_interrupt_type(unsigned int type); 21482b228baSBoyan Karatotev void gicv5_enable_ppis(); 21513b62814SBoyan Karatotev #endif /* __ASSEMBLER__ */ 2168cef63d6SBoyan Karatotev #endif /* GICV5_H */ 217