1/* 2 * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) 3 * 4 * SPDX-License-Identifier: GPL-2.0-only 5 */ 6 7#pragma once 8 9#include <autoconf.h> 10#include <stdint.h> 11#include <machine/interrupt.h> 12 13/* Shift positions for GICD_SGIR register */ 14#define GICD_SGIR_SGIINTID_SHIFT 0 15#define GICD_SGIR_CPUTARGETLIST_SHIFT 16 16#define GICD_SGIR_TARGETLISTFILTER_SHIFT 24 17 18/* Special IRQ's */ 19#define SPECIAL_IRQ_START 1020u 20#define IRQ_NONE 1023u 21 22/* CPU specific IRQ's */ 23#define SGI_START 0u 24#define PPI_START 16u 25 26/* Shared Peripheral Interrupts */ 27#define SPI_START 32u 28 29#define NUM_PPI SPI_START 30#define HW_IRQ_IS_SGI(irq) ((irq) < PPI_START) 31#define HW_IRQ_IS_PPI(irq) ((irq) < NUM_PPI) 32 33#if defined ENABLE_SMP_SUPPORT 34/* In this case irq_t is a struct with an hw irq field and target core field. 35 * The following macros convert between (target_core, hw_irq) <-> irq_t <-> cnode index. 36 * IRQ_IS_PPI returns true if hw_irq < 32 which is a property of the GIC. 37 * The layout of IRQs into the CNode are all of PPI's for each core first, followed 38 * by the global interrupts. Examples: 39 * core: 0, irq: 12 -> index 12. 40 * core: 2, irq: 16 -> (2 * 32) + 12 41 * core: 1, irq: 33, (4 total cores) -> (4 * 32) + (33-32). 42 */ 43#define IRQ_IS_PPI(_irq) (HW_IRQ_IS_PPI(_irq.irq)) 44#define CORE_IRQ_TO_IRQT(tgt, _irq) ((irq_t){.irq = (_irq), .target_core = (tgt)}) 45#define IRQT_TO_IDX(_irq) (HW_IRQ_IS_PPI(_irq.irq) ? \ 46 (irq.target_core)*NUM_PPI + (_irq.irq) : \ 47 (CONFIG_MAX_NUM_NODES-1)*NUM_PPI + (_irq.irq)) 48 49#define IDX_TO_IRQT(idx) (((idx) < NUM_PPI*CONFIG_MAX_NUM_NODES) ? \ 50 CORE_IRQ_TO_IRQT((idx) / NUM_PPI, (idx) - ((idx)/NUM_PPI)*NUM_PPI): \ 51 CORE_IRQ_TO_IRQT(0, (idx) - (CONFIG_MAX_NUM_NODES-1)*NUM_PPI)) 52#define IRQT_TO_CORE(irqt) (irqt.target_core) 53#define IRQT_TO_IRQ(irqt) (irqt.irq) 54irq_t irqInvalid = CORE_IRQ_TO_IRQT(-1, -1); 55 56#else 57#define IRQ_IS_PPI(irq) HW_IRQ_IS_PPI(irq) 58irq_t irqInvalid = (uint16_t) -1; 59#endif 60 61/* Setters/getters helpers for hardware irqs */ 62#define IRQ_REG(IRQ) ((IRQ) >> 5u) 63#define IRQ_BIT(IRQ) ((IRQ) & 0x1f) 64#define IS_IRQ_VALID(X) (((X) & IRQ_MASK) < SPECIAL_IRQ_START) 65 66/* 67 * The only sane way to get an GIC IRQ number that can be properly 68 * ACKED later is through the int_ack register. Unfortunately, reading 69 * this register changes the interrupt state to pending so future 70 * reads will not return the same value For this reason, we have a 71 * global variable to store the IRQ number. 72 */ 73extern word_t active_irq[CONFIG_MAX_NUM_NODES]; 74 75static inline void handleSpuriousIRQ(void) 76{ 77} 78 79void initIRQController(void); 80 81 82