seL4/include/drivers/irq/omap3.h
Gerwin Klein ec918cf123 arm,irq: use UNREACHBLE in unimplemented functions
UNREACHABLE instead of halt means the compiler can elide the function
from the binary.

Signed-off-by: Gerwin Klein <gerwin.klein@proofcraft.systems>
2025-10-10 14:36:43 +11:00

124 lines
3 KiB
C

/*
* Copyright 2014, General Dynamics C4 Systems
*
* SPDX-License-Identifier: GPL-2.0-only
*/
#pragma once
#include <config.h>
#include <types.h>
#include <machine/io.h>
#include <kernel/vspace.h>
#include <arch/kernel/vspace.h>
#include <linker.h>
#include <armv/machine.h>
#include <machine/interrupt.h>
/* No SGIs on this platform. */
#define NUM_SGIS 0
#define INTCPS_SIR_IRQ_SPURIOUSIRQFLAG 0xFF0000
static const irq_t irqInvalid = 255;
/*
* The struct below is used to discourage the compiler from generating literals
* for every single address we might access.
*/
volatile struct INTC_map {
uint32_t padding[4];
uint32_t intcps_sysconfig;
uint32_t intcps_sysstatus;
uint32_t padding2[10];
uint32_t intcps_sir_irq;
uint32_t intcps_sir_fiq;
uint32_t intcps_control;
uint32_t intcps_protection;
uint32_t intcps_idle;
uint32_t padding3[3];
uint32_t intcps_irq_priority;
uint32_t intcps_fiq_priority;
uint32_t intcps_threshold;
uint32_t padding4[5];
struct {
uint32_t intcps_itr;
uint32_t intcps_mir;
uint32_t intcps_mir_clear;
uint32_t intcps_mir_set;
uint32_t intcps_isr_set;
uint32_t intcps_isr_clear;
uint32_t intcps_pending_irq;
uint32_t intcps_pending_fiq;
} intcps_n[3];
uint32_t padding5[8];
uint32_t intcps_ilr[96];
} *intc = (volatile void *)INTC_PPTR;
static inline irq_t getActiveIRQ(void)
{
uint32_t intcps_sir_irq = intc->intcps_sir_irq;
irq_t irq = (irq_t)(intcps_sir_irq & 0x7f);
/* Ignore spurious interrupts. */
if ((intcps_sir_irq & INTCPS_SIR_IRQ_SPURIOUSIRQFLAG) == 0) {
assert(irq <= maxIRQ);
if (intc->intcps_n[irq / 32].intcps_pending_irq & (1 << (irq & 31))) {
return irq;
}
}
/* No interrupt. */
return irqInvalid;
}
/* Check for pending IRQ */
static inline bool_t isIRQPending(void)
{
return getActiveIRQ() != irqInvalid;
}
/* Enable or disable irq according to the 'disable' flag. */
static inline void maskInterrupt(bool_t disable, irq_t irq)
{
if (likely(irq < maxIRQ)) {
if (disable) {
intc->intcps_n[irq / 32].intcps_mir_set = 1 << (irq & 31);
} else {
intc->intcps_n[irq / 32].intcps_mir_clear = 1 << (irq & 31);
}
}
}
static inline void ackInterrupt(irq_t irq)
{
intc->intcps_control = 1;
/* Ensure the ack has hit the interrupt controller before potentially
* re-enabling interrupts. */
dsb();
}
static inline void handleSpuriousIRQ(void)
{
/* Reset and re-enable IRQs. */
intc->intcps_control = 1;
dsb();
}
void setIRQTrigger(irq_t irq, bool_t trigger)
{
/* Unreachable; not supported on this platform. */
UNREACHABLE();
}
static inline void plat_sendSGI(word_t irq, word_t target)
{
/* Unreachable; not supported on this platform. */
UNREACHABLE();
}
static inline bool_t plat_SGITargetValid(word_t target)
{
/* no SGIs on this platform */
return false;
}