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 <basic_types.h> 10 11 12 13 /** 14 * irq_t is an identifier that represents a hardware interrupt. 15 * irq handler capabilities refer to an irq_t which is then used by the 16 * kernel to track irq state. An irq_t is also used to interface with an 17 * interrupt controller driver using the functions below. 18 * For most configurations an irq_t is a word_t type and the irq_t values 19 * directly map to harware irq numbers and are also used as indexes into the 20 * kernel's irq cnode that it uses for tracking state. 21 * However on SMP configurations where there can be multiple irq_t identifiers 22 * for a single hardware irq number, such as when there are core local interrupts, 23 * irq_t cannot be assumed to be only a hardware irq number. 24 * In this case, irq_t can be defined as a struct containing additional information. 25 * 26 * Macros are provided to hide this structural difference across configurations: 27 * CORE_IRQ_TO_IRQT: converts from a core id and hw irq number to an irq_t 28 * IRQT_TO_IDX: converts an irq_t to an index in the irq cnode. It is also used 29 * to encode the irq_t as a single word_t type for sending over IPIs. 30 * IDX_TO_IRQT: converts an index in the irq cnode to an irq_t 31 * IRQT_TO_CORE: extracts the core out of an irq_t 32 * IRQT_TO_IRQL extracts a hw irq out of an irq_t. 33 * 34 * It is expected that interrupt controller drivers that support SMP provide 35 * implementations of these Macros. 36 * Currently only Arm SMP configurations use this scheme. 37 */ 38 #if defined(ENABLE_SMP_SUPPORT) && defined(CONFIG_ARCH_ARM) 39 typedef struct { 40 word_t irq; 41 word_t target_core; 42 } irq_t; 43 #else 44 typedef word_t irq_t; 45 #define CORE_IRQ_TO_IRQT(tgt, irq) (irq) 46 #define IRQT_TO_IDX(irq) (irq) 47 #define IDX_TO_IRQT(idx) (idx) 48 #define IRQT_TO_CORE(irqt) 0 49 #define IRQT_TO_IRQ(irqt) (irqt) 50 #endif 51 52 /** 53 * Return a currently pending IRQ. 54 * 55 * This function can be called multiple times and needs to return the same IRQ 56 * until ackInterrupt is called. getActiveIRQ returns irqInvalid if no interrupt 57 * is pending. It is assumed that if isIRQPending is true, then getActiveIRQ 58 * will not return irqInvalid. irqInvalid is a per platform constant that cannot 59 * correspond to an actual IRQ raised by the platform. 60 * 61 * @return The active IRQ. irqInvalid if no IRQ is pending. 62 */ 63 static inline irq_t getActiveIRQ(void); 64 65 /** 66 * Checks if an IRQ is currently pending in the hardware. 67 * 68 * isIRQPending is used to determine whether to preempt long running operations 69 * at various preemption points throughout the kernel. If this returns true, it 70 * means that if the Kernel were to return to user mode, it would then 71 * immediately take an interrupt. 72 * 73 * @return True if irq pending, False otherwise. 74 */ 75 static inline bool_t isIRQPending(void); 76 77 /** 78 * maskInterrupt disables and enables IRQs. 79 * 80 * When an IRQ is disabled, it should not raise an interrupt on the processor. 81 * 82 * @param[in] disable True to disable IRQ, False to enable IRQ 83 * @param[in] irq The irq to modify 84 */ 85 static inline void maskInterrupt(bool_t disable, irq_t irq); 86 87 /** 88 * Acks the interrupt 89 * 90 * ackInterrupt is used by the kernel to indicate it has processed the interrupt 91 * delivery and getActiveIRQ is now able to return a different IRQ number. Note 92 * that this is called after a notification has been signalled to user level, 93 * but before user level has handled the cause and does not imply that the cause 94 * of the interrupt has been handled. 95 * 96 * @param[in] irq irq to ack 97 */ 98 static inline void ackInterrupt(irq_t irq); 99 100 /** 101 * Called when getActiveIRQ returns irqInvalid while the kernel is handling an 102 * interrupt entry. An implementation is not required to do anything here, but 103 * can report the spurious IRQ or try prevent it from reoccuring. 104 */ 105 static inline void handleSpuriousIRQ(void); 106 107 /** 108 * Handle a platform-reserved IRQ. 109 * 110 * Platform specific implementation for handling IRQs for interrupts that are 111 * reserved and not made available to user-level. Will be called if getActiveIRQ 112 * returns an IRQ number that is reserved. After this function returns, 113 * ackInterrupt will likely be immediately called after. 114 * 115 * @param[in] irq The irq 116 */ 117 static inline void handleReservedIRQ(irq_t irq); 118 119