aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/irq.c
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2005-11-10 09:26:51 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2005-11-10 09:26:51 -0500
commit1dbae815a724303b46ab4663b5fc23c13e9d9690 (patch)
tree7979efc3eb2bc5c2f969020354b8c9b2954470f0 /arch/arm/mach-omap2/irq.c
parent1a8bfa1eb998af6e650ad26201f7cae9f2a2fdc8 (diff)
[ARM] 3145/1: OMAP 3a/5: Add support for omap24xx
Patch from Tony Lindgren This patch adds support for omap24xx series of processors. The files live in arch/arm/mach-omap2, and share common files with omap15xx and omap16xx processors in arch/arm/plat-omap. Omap24xx support was originally added for 2.6.9 by TI. This code was then improved and integrated to share common code with omap15xx and omap16xx processors by various omap developers, such as Paul Mundt, Juha Yrjola, Imre Deak, Tony Lindgren, Richard Woodruff, Nishant Menon, Komal Shah et al. Signed-off-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-omap2/irq.c')
-rw-r--r--arch/arm/mach-omap2/irq.c149
1 files changed, 149 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c
new file mode 100644
index 000000000000..d7baff675cfe
--- /dev/null
+++ b/arch/arm/mach-omap2/irq.c
@@ -0,0 +1,149 @@
1/*
2 * linux/arch/arm/mach-omap/omap2/irq.c
3 *
4 * Interrupt handler for OMAP2 boards.
5 *
6 * Copyright (C) 2005 Nokia Corporation
7 * Author: Paul Mundt <paul.mundt@nokia.com>
8 *
9 * This file is subject to the terms and conditions of the GNU General Public
10 * License. See the file "COPYING" in the main directory of this archive
11 * for more details.
12 */
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/config.h>
16#include <linux/interrupt.h>
17#include <asm/hardware.h>
18#include <asm/mach/irq.h>
19#include <asm/irq.h>
20#include <asm/io.h>
21
22#define INTC_REVISION 0x0000
23#define INTC_SYSCONFIG 0x0010
24#define INTC_SYSSTATUS 0x0014
25#define INTC_CONTROL 0x0048
26#define INTC_MIR_CLEAR0 0x0088
27#define INTC_MIR_SET0 0x008c
28
29/*
30 * OMAP2 has a number of different interrupt controllers, each interrupt
31 * controller is identified as its own "bank". Register definitions are
32 * fairly consistent for each bank, but not all registers are implemented
33 * for each bank.. when in doubt, consult the TRM.
34 */
35static struct omap_irq_bank {
36 unsigned long base_reg;
37 unsigned int nr_irqs;
38} __attribute__ ((aligned(4))) irq_banks[] = {
39 {
40 /* MPU INTC */
41 .base_reg = OMAP24XX_IC_BASE,
42 .nr_irqs = 96,
43 }, {
44 /* XXX: DSP INTC */
45
46#if 0
47 /*
48 * Commented out for now until we fix the IVA clocking
49 */
50#ifdef CONFIG_ARCH_OMAP2420
51 }, {
52 /* IVA INTC (2420 only) */
53 .base_reg = OMAP24XX_IVA_INTC_BASE,
54 .nr_irqs = 16, /* Actually 32, but only 16 are used */
55#endif
56#endif
57 }
58};
59
60/* XXX: FIQ and additional INTC support (only MPU at the moment) */
61static void omap_ack_irq(unsigned int irq)
62{
63 omap_writel(0x1, irq_banks[0].base_reg + INTC_CONTROL);
64}
65
66static void omap_mask_irq(unsigned int irq)
67{
68 int offset = (irq >> 5) << 5;
69
70 if (irq >= 64) {
71 irq %= 64;
72 } else if (irq >= 32) {
73 irq %= 32;
74 }
75
76 omap_writel(1 << irq, irq_banks[0].base_reg + INTC_MIR_SET0 + offset);
77}
78
79static void omap_unmask_irq(unsigned int irq)
80{
81 int offset = (irq >> 5) << 5;
82
83 if (irq >= 64) {
84 irq %= 64;
85 } else if (irq >= 32) {
86 irq %= 32;
87 }
88
89 omap_writel(1 << irq, irq_banks[0].base_reg + INTC_MIR_CLEAR0 + offset);
90}
91
92static void omap_mask_ack_irq(unsigned int irq)
93{
94 omap_mask_irq(irq);
95 omap_ack_irq(irq);
96}
97
98static struct irqchip omap_irq_chip = {
99 .ack = omap_mask_ack_irq,
100 .mask = omap_mask_irq,
101 .unmask = omap_unmask_irq,
102};
103
104static void __init omap_irq_bank_init_one(struct omap_irq_bank *bank)
105{
106 unsigned long tmp;
107
108 tmp = omap_readl(bank->base_reg + INTC_REVISION) & 0xff;
109 printk(KERN_INFO "IRQ: Found an INTC at 0x%08lx "
110 "(revision %ld.%ld) with %d interrupts\n",
111 bank->base_reg, tmp >> 4, tmp & 0xf, bank->nr_irqs);
112
113 tmp = omap_readl(bank->base_reg + INTC_SYSCONFIG);
114 tmp |= 1 << 1; /* soft reset */
115 omap_writel(tmp, bank->base_reg + INTC_SYSCONFIG);
116
117 while (!(omap_readl(bank->base_reg + INTC_SYSSTATUS) & 0x1))
118 /* Wait for reset to complete */;
119}
120
121void __init omap_init_irq(void)
122{
123 unsigned long nr_irqs = 0;
124 unsigned int nr_banks = 0;
125 int i;
126
127 for (i = 0; i < ARRAY_SIZE(irq_banks); i++) {
128 struct omap_irq_bank *bank = irq_banks + i;
129
130 /* XXX */
131 if (!bank->base_reg)
132 continue;
133
134 omap_irq_bank_init_one(bank);
135
136 nr_irqs += bank->nr_irqs;
137 nr_banks++;
138 }
139
140 printk(KERN_INFO "Total of %ld interrupts on %d active controller%s\n",
141 nr_irqs, nr_banks, nr_banks > 1 ? "s" : "");
142
143 for (i = 0; i < nr_irqs; i++) {
144 set_irq_chip(i, &omap_irq_chip);
145 set_irq_handler(i, do_level_IRQ);
146 set_irq_flags(i, IRQF_VALID);
147 }
148}
149