#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/interrupt.h>
-#include <asm/hardware.h>
-#include <asm/mach/irq.h>
-#include <linux/irq.h>
#include <linux/io.h>
+#include <mach/hardware.h>
+#include <asm/mach/irq.h>
+
/* selected INTC register offsets */
-#define INTC_REVISION 0x0000
-#define INTC_SYSCONFIG 0x0010
-#define INTC_SYSSTATUS 0x0014
-#define INTC_CONTROL 0x0048
-#define INTC_MIR_CLEAR0 0x0088
-#define INTC_MIR_SET0 0x008c
+#define INTC_REVISION 0x0000
+#define INTC_SYSCONFIG 0x0010
+#define INTC_SYSSTATUS 0x0014
+#define INTC_CONTROL 0x0048
+#define INTC_MIR_CLEAR0 0x0088
+#define INTC_MIR_SET0 0x008c
+#define INTC_PENDING_IRQ0 0x0098
+
+/* Number of IRQ state bits in each MIR register */
+#define IRQ_BITS_PER_REG 32
/*
* OMAP2 has a number of different interrupt controllers, each interrupt
* for each bank.. when in doubt, consult the TRM.
*/
static struct omap_irq_bank {
- unsigned long base_reg;
+ void __iomem *base_reg;
unsigned int nr_irqs;
} __attribute__ ((aligned(4))) irq_banks[] = {
{
static void intc_bank_write_reg(u32 val, struct omap_irq_bank *bank, u16 reg)
{
- pr_debug("intc_write_reg: writing 0x%0x to 0x%0x\n", val,
- (__force u32)(bank->base_reg + reg));
-
- omap_writel(val, bank->base_reg + reg);
+ __raw_writel(val, bank->base_reg + reg);
}
static u32 intc_bank_read_reg(struct omap_irq_bank *bank, u16 reg)
{
- return omap_readl(bank->base_reg + reg);
+ return __raw_readl(bank->base_reg + reg);
}
/* XXX: FIQ and additional INTC support (only MPU at the moment) */
static void omap_mask_irq(unsigned int irq)
{
- int offset = (irq >> 5) << 5;
+ int offset = irq & (~(IRQ_BITS_PER_REG - 1));
- if (irq >= 64)
- irq %= 64;
- else if (irq >= 32)
- irq %= 32;
+ irq &= (IRQ_BITS_PER_REG - 1);
intc_bank_write_reg(1 << irq, &irq_banks[0], INTC_MIR_SET0 + offset);
}
static void omap_unmask_irq(unsigned int irq)
{
- int offset = (irq >> 5) << 5;
+ int offset = irq & (~(IRQ_BITS_PER_REG - 1));
- if (irq >= 64)
- irq %= 64;
- else if (irq >= 32)
- irq %= 32;
+ irq &= (IRQ_BITS_PER_REG - 1);
intc_bank_write_reg(1 << irq, &irq_banks[0], INTC_MIR_CLEAR0 + offset);
}
unsigned long tmp;
tmp = intc_bank_read_reg(bank, INTC_REVISION) & 0xff;
- printk(KERN_INFO "IRQ: Found an INTC at 0x%08lx "
+ printk(KERN_INFO "IRQ: Found an INTC at 0x%p "
"(revision %ld.%ld) with %d interrupts\n",
bank->base_reg, tmp >> 4, tmp & 0xf, bank->nr_irqs);
intc_bank_write_reg(1 << 0, bank, INTC_SYSCONFIG);
}
+int omap_irq_pending(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(irq_banks); i++) {
+ struct omap_irq_bank *bank = irq_banks + i;
+ int irq;
+
+ for (irq = 0; irq < bank->nr_irqs; irq += IRQ_BITS_PER_REG) {
+ int offset = irq & (~(IRQ_BITS_PER_REG - 1));
+
+ if (intc_bank_read_reg(bank, (INTC_PENDING_IRQ0 +
+ offset)))
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
void __init omap_init_irq(void)
{
unsigned long nr_irqs = 0;
struct omap_irq_bank *bank = irq_banks + i;
if (cpu_is_omap24xx())
- bank->base_reg = OMAP24XX_IC_BASE;
+ bank->base_reg = OMAP2_IO_ADDRESS(OMAP24XX_IC_BASE);
else if (cpu_is_omap34xx())
- bank->base_reg = OMAP34XX_IC_BASE;
+ bank->base_reg = OMAP2_IO_ADDRESS(OMAP34XX_IC_BASE);
omap_irq_bank_init_one(bank);