Index: kernel/arch/arm32/src/mach/beagleboardxm/beagleboardxm.c
===================================================================
--- kernel/arch/arm32/src/mach/beagleboardxm/beagleboardxm.c	(revision 5b08d7506fa0a7bbf6c9ccbfd674f4bca498b5b1)
+++ kernel/arch/arm32/src/mach/beagleboardxm/beagleboardxm.c	(revision 4cdcd2b7c4b90fb7a1d3ddd4db3df6f153104450)
@@ -60,5 +60,5 @@
 
 static struct beagleboard {
-	amdm37x_irc_regs_t *irc_addr;
+	omap_irc_regs_t *irc_addr;
 	omap_uart_t uart;
 	amdm37x_gpt_t timer;
@@ -103,5 +103,5 @@
 	    PAGE_NOT_CACHEABLE);
 	ASSERT(beagleboard.irc_addr);
-	amdm37x_irc_init(beagleboard.irc_addr);
+	omap_irc_init(beagleboard.irc_addr);
 
 	/* Initialize timer. Use timer1, because it is in WKUP power domain
@@ -123,5 +123,5 @@
 
 	/* Enable timer interrupt */
-	amdm37x_irc_enable(beagleboard.irc_addr, AMDM37x_GPT1_IRQ);
+	omap_irc_enable(beagleboard.irc_addr, AMDM37x_GPT1_IRQ);
 
 	/* Start timer here */
@@ -147,5 +147,5 @@
 static void bbxm_irq_exception(unsigned int exc_no, istate_t *istate)
 {
-	const unsigned inum = amdm37x_irc_inum_get(beagleboard.irc_addr);
+	const unsigned inum = omap_irc_inum_get(beagleboard.irc_addr);
 
 	irq_t *irq = irq_dispatch_and_lock(inum);
@@ -161,5 +161,5 @@
 	/** amdm37x manual ch. 12.5.2 (p. 2428) places irc ack at the end
 	 * of ISR. DO this to avoid strange behavior. */
-	amdm37x_irc_irq_ack(beagleboard.irc_addr);
+	omap_irc_irq_ack(beagleboard.irc_addr);
 }
 
@@ -188,5 +188,5 @@
 		indev_t *srln = srln_wire(srln_instance, sink);
 		omap_uart_input_wire(&beagleboard.uart, srln);
-		amdm37x_irc_enable(beagleboard.irc_addr, AMDM37x_UART3_IRQ);
+		omap_irc_enable(beagleboard.irc_addr, AMDM37x_UART3_IRQ);
 	}
 #endif
Index: kernel/arch/arm32/src/mach/beaglebone/beaglebone.c
===================================================================
--- kernel/arch/arm32/src/mach/beaglebone/beaglebone.c	(revision 5b08d7506fa0a7bbf6c9ccbfd674f4bca498b5b1)
+++ kernel/arch/arm32/src/mach/beaglebone/beaglebone.c	(revision 4cdcd2b7c4b90fb7a1d3ddd4db3df6f153104450)
@@ -63,5 +63,5 @@
 
 static struct beaglebone {
-	am335x_irc_regs_t *irc_addr;
+	omap_irc_regs_t *irc_addr;
 	am335x_cm_per_regs_t *cm_per_addr;
 	am335x_cm_dpll_regs_t *cm_dpll_addr;
@@ -104,5 +104,5 @@
 
 	/* Initialize the interrupt controller */
-	am335x_irc_init(bbone.irc_addr);
+	omap_irc_init(bbone.irc_addr);
 }
 
@@ -153,5 +153,5 @@
 	}
 	/* Enable the interrupt */
-	am335x_irc_enable(bbone.irc_addr, AM335x_DMTIMER2_IRQ);
+	omap_irc_enable(bbone.irc_addr, AM335x_DMTIMER2_IRQ);
 	/* Start the timer */
 	am335x_timer_start(&bbone.timer);
@@ -176,5 +176,5 @@
 static void bbone_irq_exception(unsigned int exc_no, istate_t *istate)
 {
-	const unsigned inum = am335x_irc_inum_get(bbone.irc_addr);
+	const unsigned inum = omap_irc_inum_get(bbone.irc_addr);
 
 	irq_t *irq = irq_dispatch_and_lock(inum);
@@ -187,5 +187,5 @@
 	}
 
-	am335x_irc_irq_ack(bbone.irc_addr);
+	omap_irc_irq_ack(bbone.irc_addr);
 }
 
@@ -214,5 +214,5 @@
 		indev_t *srln = srln_wire(srln_instance, sink);
 		omap_uart_input_wire(&bbone.uart, srln);
-		am335x_irc_enable(bbone.irc_addr, AM335x_UART0_IRQ);
+		omap_irc_enable(bbone.irc_addr, AM335x_UART0_IRQ);
 	}
 #endif
Index: kernel/genarch/include/genarch/drivers/am335x/irc.h
===================================================================
--- kernel/genarch/include/genarch/drivers/am335x/irc.h	(revision 5b08d7506fa0a7bbf6c9ccbfd674f4bca498b5b1)
+++ kernel/genarch/include/genarch/drivers/am335x/irc.h	(revision 4cdcd2b7c4b90fb7a1d3ddd4db3df6f153104450)
@@ -38,214 +38,14 @@
 #define KERN_AM335x_IRQC_H_
 
-#define AM335x_IRC_BASE_ADDRESS 0x48200000
-#define AM335x_IRC_SIZE         4096
+#define AM335x_IRC_BASE_ADDRESS     0x48200000
+#define AM335x_IRC_SIZE             4096
 
-#define AM335x_IRC_IRQ_COUNT    128
+#define AM335x_IRC_IRQ_COUNT        128
+#define AM335x_IRC_IRQ_GROUPS_COUNT 4
 
-#include <typedefs.h>
+#define OMAP_IRC_IRQ_COUNT        AM335x_IRC_IRQ_COUNT
+#define OMAP_IRC_IRQ_GROUPS_COUNT AM335x_IRC_IRQ_GROUPS_COUNT
 
-typedef struct {
-	const ioport32_t revision;
-#define AM335x_IRC_REV_MASK 0xFF
-
-	const uint8_t padd0[12];
-
-	/* This register controls the various parameters
-	 * of the OCP interface.
-	 */
-	ioport32_t sysconfig;
-#define AM335x_IRC_SYSCONFIG_AUTOIDLE_FLAG   (1 << 0)
-#define AM335x_IRC_SYSCONFIG_SOFTRESET_FLAG  (1 << 1)
-
-	/* This register provides status information about the module */
-	const ioport32_t sysstatus;
-#define AM335x_IRC_SYSSTATUS_RESET_DONE_FLAG (1 << 0)
-
-	const uint8_t padd1[40];
-
-	/* This register supplies the currently active IRQ interrupt number */
-	ioport32_t sir_irq;
-#define AM335x_IRC_SIR_IRQ_ACTIVEIRQ_MASK       0x7F
-#define AM335x_IRC_SIR_IRQ_SPURIOUSIRQFLAG_MASK 0xFFFFFFF8
-
-	/* This register supplies the currently active FIQ interrupt number */
-	const ioport32_t sir_fiq;
-#define AM335x_IRC_FIQ_IRQ_ACTIVEFIQ_MASK       0x7F
-#define AM335x_IRC_FIQ_IRQ_SPURIOUSFIQFLAG_MASK 0xFFFFFFF8
-
-	/* This register contains the new interrupt agreement bits */
-	ioport32_t control;
-#define AM335x_IRC_CONTROL_NEWIRQAGR_FLAG       (1 << 0)
-#define AM335x_IRC_CONTROL_NEWFIQAGR_FLAG       (1 << 1)
-
-	/* This register controls protection of the other registers.
-	 * This register can only be accessed in priviledged mode, regardless
-	 * of the current value of the protection bit.
-	 */
-	ioport32_t protection;
-#define AM335x_IRC_PROTECTION_FLAG              (1 << 0)
-
-	/* This register controls the clock auto-idle for the functional
-	 * clock and the input synchronizers.
-	 */
-	ioport32_t idle;
-#define AM335x_IRC_IDLE_FUNCIDLE_FLAG           (1 << 0)
-#define AM335x_IRC_IDLE_TURBO_FLAG              (1 << 1)
-
-	const uint8_t padd2[12];
-
-	/* This register supplies the currently active IRQ priority level */
-	const ioport32_t irq_priority;
-#define AM335x_IRC_IRQ_PRIORITY_IRQPRIORITY_MASK     0x7F
-#define AM335x_IRC_IRQ_PRIORITY_SPURIOUSIRQFLAG_MASK 0xFFFFFFF8
-
-	/* This register supplies the currently active FIQ priority level */
-	const ioport32_t fiq_priority;
-#define AM335x_IRC_FIQ_PRIORITY_FIQPRIORITY_MASK     0x7F
-#define AM335x_IRC_FIQ_PRIORITY_SPURIOUSIRQFLAG_MASK 0xFFFFFFF8
-
-	/* This register sets the priority threshold */
-	ioport32_t threshold;
-#define AM335x_IRC_THRESHOLD_PRIORITYTHRESHOLD_MASK     0xFF
-#define AM335x_IRC_THRESHOLD_PRIORITYTHRESHOLD_ENABLED  0x00
-#define AM335x_IRC_THRESHOLD_PRIORITYTHRESHOLD_DISABLED 0xFF
-
-	const uint8_t padd[20];
-
-	struct {
-		/* Raw interrupt input status before masking */
-		const ioport32_t itr;
-
-		/* Interrupt mask */
-		ioport32_t mir;
-
-		/* This register is used to clear the interrupt mask bits,
-		 * Write 1 clears the mask bit to 0.
-		 */
-		ioport32_t mir_clear;
-
-		/* This register is used to set the interrupt mask bits,
-		 * Write 1 sets the mask bit to 1.
-		 */
-		ioport32_t mir_set;
-
-		/* This register is used to set the software interrupt bits,
-		 * it is also used to read the current active software
-		 * interrupts.
-		 * Write 1 sets the software interrups bits to 1.
-		 */
-		ioport32_t isr_set;
-
-		/* This register is used to clear the software interrups bits.
-		 * Write 1 clears the software interrupt bits to 0.
-		 */
-		ioport32_t isr_clear;
-
-		/* This register contains the IRQ status after masking. */
-		const ioport32_t pending_irq;
-
-		/* This register contains the FIQ status after masking. */
-		const ioport32_t pending_fiq;
-	} interrupts[4];
-
-	/* These registers contain the priority for the interrups and
-	 * the FIQ/IRQ steering.
-	 */
-	ioport32_t ilr[AM335x_IRC_IRQ_COUNT];
-/* 0 = Interrupt routed to IRQ, 1 = interrupt routed to FIQ */
-#define AM335x_IRC_ILR_FIQNIRQ_FLAG    (1 << 0)
-#define AM335x_IRC_ILR_PRIORITY_MASK   0x3F
-#define AM335x_IRC_ILR_PRIORITY_SHIFT  2
-
-} am335x_irc_regs_t;
-
-static inline void am335x_irc_init(am335x_irc_regs_t *regs)
-{
-	int i;
-
-	/* Initialization sequence */
-
-	/* 1 - Program the SYSCONFIG register: if necessary, enable the
-	 *     autogating by setting the AUTOIDLE bit.
-	 */
-	regs->sysconfig &= ~AM335x_IRC_SYSCONFIG_AUTOIDLE_FLAG;
-
-	/* 2 - Program the IDLE register: if necessary, disable functional
-	 *     clock autogating or enable synchronizer autogating by setting
-	 *     the FUNCIDLE bit or the TURBO bit accordingly.
-	 */
-	regs->idle &= ~AM335x_IRC_IDLE_FUNCIDLE_FLAG;
-	regs->idle &= ~AM335x_IRC_IDLE_TURBO_FLAG;
-
-	/* 3 - Program ILRm register for each interrupt line: Assign a
-	 *     priority level and set the FIQNIRQ bit for an FIQ interrupt
-	 *     (by default, interrupts are mapped to IRQ and
-	 *     priority is 0 (highest).
-	 */
-
-	for (i = 0; i < AM335x_IRC_IRQ_COUNT; ++i)
-		regs->ilr[i] = 0;
-
-	/* 4 - Program the MIRn register: Enable interrupts (by default,
-	 *     all interrupt lines are masked).
-	 */
-	for (i = 0; i < 4; ++i)
-		regs->interrupts[i].mir_set = 0xFFFFFFFF;
-}
-
-/** Get the currently active IRQ interrupt number
- *
- * @param regs     Pointer to the irc memory mapped registers
- *
- * @return         The active IRQ interrupt number
- */
-static inline unsigned am335x_irc_inum_get(am335x_irc_regs_t *regs)
-{
-	return regs->sir_irq & AM335x_IRC_SIR_IRQ_ACTIVEIRQ_MASK;
-}
-
-/** Reset IRQ output and enable new IRQ generation
- *
- * @param regs    Pointer to the irc memory mapped registers
- */
-static inline void am335x_irc_irq_ack(am335x_irc_regs_t *regs)
-{
-	regs->control = AM335x_IRC_CONTROL_NEWIRQAGR_FLAG;
-}
-
-/** Reset FIQ output and enable new FIQ generation
- *
- * @param regs    Pointer to the irc memory mapped registers
- */
-static inline void am335x_irc_fiq_ack(am335x_irc_regs_t *regs)
-{
-	regs->control = AM335x_IRC_CONTROL_NEWFIQAGR_FLAG;
-}
-
-/** Clear an interrupt mask bit
- *
- * @param regs    Pointer to the irc memory mapped registers
- * @param inum    The interrupt to be enabled
- */
-static inline void am335x_irc_enable(am335x_irc_regs_t *regs, unsigned inum)
-{
-	ASSERT(inum < AM335x_IRC_IRQ_COUNT);
-	const unsigned set = inum / 32;
-	const unsigned pos = inum % 32;
-	regs->interrupts[set].mir_clear = (1 << pos);
-}
-
-/** Set an interrupt mask bit
- *
- * @param regs    Pointer to the irc memory mapped registers
- * @param inum    The interrupt to be disabled
- */
-static inline void am335x_irc_disable(am335x_irc_regs_t *regs, unsigned inum)
-{
-	ASSERT(inum < AM335x_IRC_IRQ_COUNT);
-	const unsigned set = inum / 32;
-	const unsigned pos = inum % 32;
-	regs->interrupts[set].mir_set = (1 << pos);
-}
+#include <genarch/drivers/omap/irc.h>
 
 #endif
Index: kernel/genarch/include/genarch/drivers/amdm37x/irc.h
===================================================================
--- kernel/genarch/include/genarch/drivers/amdm37x/irc.h	(revision 5b08d7506fa0a7bbf6c9ccbfd674f4bca498b5b1)
+++ kernel/genarch/include/genarch/drivers/amdm37x/irc.h	(revision 4cdcd2b7c4b90fb7a1d3ddd4db3df6f153104450)
@@ -38,165 +38,14 @@
 
 /* AMDM37x TRM p. 1079 */
-#define AMDM37x_IRC_BASE_ADDRESS 0x48200000
-#define AMDM37x_IRC_SIZE 4096
+#define AMDM37x_IRC_BASE_ADDRESS     0x48200000
+#define AMDM37x_IRC_SIZE             4096
 
-#define AMDM37x_IRC_IRQ_COUNT 96
+#define AMDM37x_IRC_IRQ_COUNT        96
+#define AMDM37x_IRC_IRQ_GROUPS_COUNT 3
 
-#include <typedefs.h>
+#define OMAP_IRC_IRQ_COUNT        AMDM37x_IRC_IRQ_COUNT
+#define OMAP_IRC_IRQ_GROUPS_COUNT AMDM37x_IRC_IRQ_GROUPS_COUNT
 
-typedef struct {
-	const ioport32_t revision; /**< Revision */
-#define AMDM37x_IRC_REV_MASK (0xff)
-
-	uint8_t padd0_[12];
-
-	ioport32_t sysconfig; /**< SYS config */
-#define AMDM37x_IRC_SYSCONFIG_AUTOIDLE_FLAG (1 << 0)
-#define AMDM37x_IRC_SYSCONFIG_SOFTRESET_FLAG (1 << 1)
-
-	const ioport32_t sysstatus; /**< SYS status */
-#define AMDM37x_IRC_SYSSTATUS_RESET_DONE_FLAG (1 << 0)
-
-	uint8_t padd1_[40];
-
-	const ioport32_t sir_irq;   /**< Currently active irq number */
-#define AMDM37x_IRC_SIR_IRQ_ACTIVEIRQ_MASK (0x7f)
-#define AMDM37x_IRC_SIR_IRQ_SPURIOUSIRQFLAG_MASK (0xfffffff8)
-
-	const ioport32_t sir_fiq;
-#define AMDM37x_IRC_SIR_FIQ_ACTIVEIRQ_MASK (0x7f)
-#define AMDM37x_IRC_SIR_FIQ_SPURIOUSIRQFLAG_MASK (0xfffffff8)
-
-	ioport32_t control;   /**< New interrupt agreement. */
-#define AMDM37x_IRC_CONTROL_NEWIRQAGR_FLAG (1 << 0)
-#define AMDM37x_IRC_CONTROL_NEWFIQAGR_FLAG (1 << 1)
-
-	ioport32_t protection;  /**< Protect other registers. */
-#define AMDM37x_IRC_PROTECTION_PROETCTION_FLAG (1 << 0)
-
-	ioport32_t idle;   /**< Idle and autogating */
-#define AMDM37x_IRC_IDLE_FUNCIDLE_FLAG (1 << 0)
-#define AMDM37x_IRC_IDLE_TURBO_FLAG (1 << 1)
-
-	uint8_t padd2_[12];
-
-	ioport32_t irq_priority; /**< Active IRQ priority */
-#define AMDM37x_IRC_IRQ_PRIORITY_IRQPRIORITY_MASK (0x7f)
-#define AMDM37x_IRC_IRQ_PRIORITY_SPURIOUSIRQFLAG_MASK (0xfffffff8)
-
-	ioport32_t fiq_priority; /**< Active FIQ priority */
-#define AMDM37x_IRC_FIQ_PRIORITY_FIQPRIORITY_MASK (0x7f)
-#define AMDM37x_IRC_FIQ_PRIORITY_SPURIOUSFIQFLAG_MASK (0xfffffff8)
-
-	ioport32_t threshold; /**< Priority threshold */
-#define AMDM37x_IRC_THRESHOLD_PRIORITYTHRESHOLD_MASK (0xff)
-#define AMDM37x_IRC_THRESHOLD_PRIORITYTHRESHOLD_ENABLED (0x00)
-#define AMDM37x_IRC_THRESHOLD_PRIORITYTHRESHOLD_DISABLED (0xff)
-
-	uint8_t padd3__[20];
-
-	struct {
-		const ioport32_t itr;   /**< Interrupt input status before masking */
-		ioport32_t mir;   /**< Interrupt mask */
-		ioport32_t mir_clear; /**< Clear mir mask bits */
-		ioport32_t mir_set;   /**< Set mir mask bits */
-		ioport32_t isr_set;   /**< Set software interrupt bits */
-		ioport32_t isr_clear; /**< Clear software interrupt bits */
-		const ioport32_t pending_irq; /**< IRQ status after masking */
-		const ioport32_t pending_fiq; /**< FIQ status after masking */
-	} interrupts[3];
-
-	uint8_t padd4_[32];
-
-	ioport32_t ilr[96];   /**< FIQ/IRQ steering */
-#define AMDM37x_IRC_ILR_FIQNIRQ (1 << 0)
-#define AMDM37x_IRC_ILR_PRIORITY_MASK (0x3f)
-#define AMDM37x_IRC_ILR_PRIORITY_SHIFT (2)
-
-} amdm37x_irc_regs_t;
-
-static inline void amdm37x_irc_dump(amdm37x_irc_regs_t *regs)
-{
-#define DUMP_REG(name) \
-	printf("%s %p(%x).\n", #name, &regs->name, regs->name);
-
-	DUMP_REG(revision);
-	DUMP_REG(sysconfig);
-	DUMP_REG(sysstatus);
-	DUMP_REG(sir_irq);
-	DUMP_REG(sir_fiq);
-	DUMP_REG(control);
-	DUMP_REG(protection);
-	DUMP_REG(idle);
-	DUMP_REG(irq_priority);
-	DUMP_REG(fiq_priority);
-	DUMP_REG(threshold);
-
-	for (int i = 0; i < 3; ++i) {
-		DUMP_REG(interrupts[i].itr);
-		DUMP_REG(interrupts[i].mir);
-		DUMP_REG(interrupts[i].isr_set);
-		DUMP_REG(interrupts[i].pending_irq);
-		DUMP_REG(interrupts[i].pending_fiq);
-	}
-	for (int i = 0; i < AMDM37x_IRC_IRQ_COUNT; ++i) {
-		DUMP_REG(ilr[i]);
-	}
-
-#undef DUMP_REG
-}
-
-static inline void amdm37x_irc_init(amdm37x_irc_regs_t *regs)
-{
-	/* AMDM37x TRM sec 12.5.1 p. 2425 */
-	/* Program system config register */
-	//TODO enable this when you know the meaning
-	//regs->sysconfig |= AMDM37x_IRC_SYSCONFIG_AUTOIDLE_FLAG;
-
-	/* Program idle register */
-	//TODO enable this when you know the meaning
-	//regs->sysconfig |= AMDM37x_IRC_IDLE_TURBO_FLAG;
-
-	/* Program ilr[m] assign priority, decide fiq */
-	for (unsigned i = 0; i < AMDM37x_IRC_IRQ_COUNT; ++i) {
-		regs->ilr[i] = 0; /* highest prio(default) route to irq */
-	}
-
-	/* Disable all interrupts */
-	regs->interrupts[0].mir_set = 0xffffffff;
-	regs->interrupts[1].mir_set = 0xffffffff;
-	regs->interrupts[2].mir_set = 0xffffffff;
-}
-
-static inline unsigned amdm37x_irc_inum_get(amdm37x_irc_regs_t *regs)
-{
-	return regs->sir_irq & AMDM37x_IRC_SIR_IRQ_ACTIVEIRQ_MASK;
-}
-
-static inline void amdm37x_irc_irq_ack(amdm37x_irc_regs_t *regs)
-{
-	regs->control = AMDM37x_IRC_CONTROL_NEWIRQAGR_FLAG;
-}
-
-static inline void amdm37x_irc_fiq_ack(amdm37x_irc_regs_t *regs)
-{
-	regs->control = AMDM37x_IRC_CONTROL_NEWFIQAGR_FLAG;
-}
-
-static inline void amdm37x_irc_enable(amdm37x_irc_regs_t *regs, unsigned inum)
-{
-	ASSERT(inum < AMDM37x_IRC_IRQ_COUNT);
-	const unsigned set = inum / 32;
-	const unsigned pos = inum % 32;
-	regs->interrupts[set].mir_clear = (1 << pos);
-}
-
-static inline void amdm37x_irc_disable(amdm37x_irc_regs_t *regs, unsigned inum)
-{
-	ASSERT(inum < AMDM37x_IRC_IRQ_COUNT);
-	const unsigned set = inum / 32;
-	const unsigned pos = inum % 32;
-	regs->interrupts[set].mir_set = (1 << pos);
-}
+#include <genarch/drivers/omap/irc.h>
 
 #endif
Index: kernel/genarch/include/genarch/drivers/omap/irc.h
===================================================================
--- kernel/genarch/include/genarch/drivers/omap/irc.h	(revision 4cdcd2b7c4b90fb7a1d3ddd4db3df6f153104450)
+++ kernel/genarch/include/genarch/drivers/omap/irc.h	(revision 4cdcd2b7c4b90fb7a1d3ddd4db3df6f153104450)
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2012 Maurizio Lombardi
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** @addtogroup genarch
+ * @{
+ */
+
+/**
+ * @file
+ * @brief Texas Instruments OMAP on-chip interrupt controller driver.
+ */
+
+#ifndef KERN_OMAP_IRQC_H_
+#define KERN_OMAP_IRQC_H_
+
+#include <typedefs.h>
+
+#define OMAP_IRC_IRQ_GROUPS_PAD (4 - OMAP_IRC_IRQ_GROUPS_COUNT)
+
+typedef struct {
+	const ioport32_t revision;
+#define OMAP_IRC_REV_MASK 0xFF
+
+	const uint8_t padd0[12];
+
+	/* This register controls the various parameters
+	 * of the OCP interface.
+	 */
+	ioport32_t sysconfig;
+#define OMAP_IRC_SYSCONFIG_AUTOIDLE_FLAG   (1 << 0)
+#define OMAP_IRC_SYSCONFIG_SOFTRESET_FLAG  (1 << 1)
+
+	/* This register provides status information about the module */
+	const ioport32_t sysstatus;
+#define OMAP_IRC_SYSSTATUS_RESET_DONE_FLAG (1 << 0)
+
+	const uint8_t padd1[40];
+
+	/* This register supplies the currently active IRQ interrupt number */
+	ioport32_t sir_irq;
+#define OMAP_IRC_SIR_IRQ_ACTIVEIRQ_MASK       0x7F
+#define OMAP_IRC_SIR_IRQ_SPURIOUSIRQFLAG_MASK 0xFFFFFFF8
+
+	/* This register supplies the currently active FIQ interrupt number */
+	const ioport32_t sir_fiq;
+#define OMAP_IRC_FIQ_IRQ_ACTIVEFIQ_MASK       0x7F
+#define OMAP_IRC_FIQ_IRQ_SPURIOUSFIQFLAG_MASK 0xFFFFFFF8
+
+	/* This register contains the new interrupt agreement bits */
+	ioport32_t control;
+#define OMAP_IRC_CONTROL_NEWIRQAGR_FLAG       (1 << 0)
+#define OMAP_IRC_CONTROL_NEWFIQAGR_FLAG       (1 << 1)
+
+	/* This register controls protection of the other registers.
+	 * This register can only be accessed in priviledged mode, regardless
+	 * of the current value of the protection bit.
+	 */
+	ioport32_t protection;
+#define OMAP_IRC_PROTECTION_FLAG              (1 << 0)
+
+	/* This register controls the clock auto-idle for the functional
+	 * clock and the input synchronizers.
+	 */
+	ioport32_t idle;
+#define OMAP_IRC_IDLE_FUNCIDLE_FLAG           (1 << 0)
+#define OMAP_IRC_IDLE_TURBO_FLAG              (1 << 1)
+
+	const uint8_t padd2[12];
+
+	/* This register supplies the currently active IRQ priority level */
+	const ioport32_t irq_priority;
+#define OMAP_IRC_IRQ_PRIORITY_IRQPRIORITY_MASK     0x7F
+#define OMAP_IRC_IRQ_PRIORITY_SPURIOUSIRQFLAG_MASK 0xFFFFFFF8
+
+	/* This register supplies the currently active FIQ priority level */
+	const ioport32_t fiq_priority;
+#define OMAP_IRC_FIQ_PRIORITY_FIQPRIORITY_MASK     0x7F
+#define OMAP_IRC_FIQ_PRIORITY_SPURIOUSIRQFLAG_MASK 0xFFFFFFF8
+
+	/* This register sets the priority threshold */
+	ioport32_t threshold;
+#define OMAP_IRC_THRESHOLD_PRIORITYTHRESHOLD_MASK     0xFF
+#define OMAP_IRC_THRESHOLD_PRIORITYTHRESHOLD_ENABLED  0x00
+#define OMAP_IRC_THRESHOLD_PRIORITYTHRESHOLD_DISABLED 0xFF
+
+	const uint8_t padd3[20];
+
+	struct {
+		/* Raw interrupt input status before masking */
+		const ioport32_t itr;
+
+		/* Interrupt mask */
+		ioport32_t mir;
+
+		/* This register is used to clear the interrupt mask bits,
+		 * Write 1 clears the mask bit to 0.
+		 */
+		ioport32_t mir_clear;
+
+		/* This register is used to set the interrupt mask bits,
+		 * Write 1 sets the mask bit to 1.
+		 */
+		ioport32_t mir_set;
+
+		/* This register is used to set the software interrupt bits,
+		 * it is also used to read the current active software
+		 * interrupts.
+		 * Write 1 sets the software interrups bits to 1.
+		 */
+		ioport32_t isr_set;
+
+		/* This register is used to clear the software interrups bits.
+		 * Write 1 clears the software interrupt bits to 0.
+		 */
+		ioport32_t isr_clear;
+
+		/* This register contains the IRQ status after masking. */
+		const ioport32_t pending_irq;
+
+		/* This register contains the FIQ status after masking. */
+		const ioport32_t pending_fiq;
+	} interrupts[OMAP_IRC_IRQ_GROUPS_COUNT];
+
+	const uint32_t padd4[32 * OMAP_IRC_IRQ_GROUPS_PAD];
+
+	/* These registers contain the priority for the interrups and
+	 * the FIQ/IRQ steering.
+	 */
+	ioport32_t ilr[OMAP_IRC_IRQ_COUNT];
+/* 0 = Interrupt routed to IRQ, 1 = interrupt routed to FIQ */
+#define OMAP_IRC_ILR_FIQNIRQ_FLAG    (1 << 0)
+#define OMAP_IRC_ILR_PRIORITY_MASK   0x3F
+#define OMAP_IRC_ILR_PRIORITY_SHIFT  2
+
+} omap_irc_regs_t;
+
+static inline void omap_irc_init(omap_irc_regs_t *regs)
+{
+	int i;
+
+	/* Initialization sequence */
+
+	/* 1 - Program the SYSCONFIG register: if necessary, enable the
+	 *     autogating by setting the AUTOIDLE bit.
+	 */
+	regs->sysconfig &= ~OMAP_IRC_SYSCONFIG_AUTOIDLE_FLAG;
+
+	/* 2 - Program the IDLE register: if necessary, disable functional
+	 *     clock autogating or enable synchronizer autogating by setting
+	 *     the FUNCIDLE bit or the TURBO bit accordingly.
+	 */
+	regs->idle &= ~OMAP_IRC_IDLE_FUNCIDLE_FLAG;
+	regs->idle &= ~OMAP_IRC_IDLE_TURBO_FLAG;
+
+	/* 3 - Program ILRm register for each interrupt line: Assign a
+	 *     priority level and set the FIQNIRQ bit for an FIQ interrupt
+	 *     (by default, interrupts are mapped to IRQ and
+	 *     priority is 0 (highest).
+	 */
+
+	for (i = 0; i < OMAP_IRC_IRQ_COUNT; ++i)
+		regs->ilr[i] = 0;
+
+	/* 4 - Program the MIRn register: Enable interrupts (by default,
+	 *     all interrupt lines are masked).
+	 */
+	for (i = 0; i < OMAP_IRC_IRQ_GROUPS_COUNT; ++i)
+		regs->interrupts[i].mir_set = 0xFFFFFFFF;
+}
+
+/** Get the currently active IRQ interrupt number
+ *
+ * @param regs     Pointer to the irc memory mapped registers
+ *
+ * @return         The active IRQ interrupt number
+ */
+static inline unsigned omap_irc_inum_get(omap_irc_regs_t *regs)
+{
+	return regs->sir_irq & OMAP_IRC_SIR_IRQ_ACTIVEIRQ_MASK;
+}
+
+/** Reset IRQ output and enable new IRQ generation
+ *
+ * @param regs    Pointer to the irc memory mapped registers
+ */
+static inline void omap_irc_irq_ack(omap_irc_regs_t *regs)
+{
+	regs->control = OMAP_IRC_CONTROL_NEWIRQAGR_FLAG;
+}
+
+/** Reset FIQ output and enable new FIQ generation
+ *
+ * @param regs    Pointer to the irc memory mapped registers
+ */
+static inline void omap_irc_fiq_ack(omap_irc_regs_t *regs)
+{
+	regs->control = OMAP_IRC_CONTROL_NEWFIQAGR_FLAG;
+}
+
+/** Clear an interrupt mask bit
+ *
+ * @param regs    Pointer to the irc memory mapped registers
+ * @param inum    The interrupt to be enabled
+ */
+static inline void omap_irc_enable(omap_irc_regs_t *regs, unsigned inum)
+{
+	ASSERT(inum < OMAP_IRC_IRQ_COUNT);
+	const unsigned set = inum / 32;
+	const unsigned pos = inum % 32;
+	regs->interrupts[set].mir_clear = (1 << pos);
+}
+
+/** Set an interrupt mask bit
+ *
+ * @param regs    Pointer to the irc memory mapped registers
+ * @param inum    The interrupt to be disabled
+ */
+static inline void omap_irc_disable(omap_irc_regs_t *regs, unsigned inum)
+{
+	ASSERT(inum < OMAP_IRC_IRQ_COUNT);
+	const unsigned set = inum / 32;
+	const unsigned pos = inum % 32;
+	regs->interrupts[set].mir_set = (1 << pos);
+}
+
+static inline void omap_irc_dump(omap_irc_regs_t *regs)
+{
+#define DUMP_REG(name) \
+	printf("%s %p(%x).\n", #name, &regs->name, regs->name);
+
+	DUMP_REG(revision);
+	DUMP_REG(sysconfig);
+	DUMP_REG(sysstatus);
+	DUMP_REG(sir_irq);
+	DUMP_REG(sir_fiq);
+	DUMP_REG(control);
+	DUMP_REG(protection);
+	DUMP_REG(idle);
+	DUMP_REG(irq_priority);
+	DUMP_REG(fiq_priority);
+	DUMP_REG(threshold);
+
+	for (int i = 0; i < OMAP_IRC_IRQ_GROUPS_COUNT; ++i) {
+		DUMP_REG(interrupts[i].itr);
+		DUMP_REG(interrupts[i].mir);
+		DUMP_REG(interrupts[i].isr_set);
+		DUMP_REG(interrupts[i].pending_irq);
+		DUMP_REG(interrupts[i].pending_fiq);
+	}
+	for (int i = 0; i < OMAP_IRC_IRQ_COUNT; ++i) {
+		DUMP_REG(ilr[i]);
+	}
+
+#undef DUMP_REG
+}
+
+#endif
+
+/**
+ * @}
+ */
