aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-davinci/irq.c
diff options
context:
space:
mode:
authorKevin Hilman <khilman@mvista.com>2007-04-30 14:37:19 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2007-05-11 12:26:55 -0400
commit7c6337e225364870e9bf02a3ae277d9fdea483f8 (patch)
tree1ba5819dfc424beea0086cd3b855839be29370dd /arch/arm/mach-davinci/irq.c
parent7fdc7849d2f9f926cbaec224bbcbacb164b07b23 (diff)
[ARM] 4303/3: base kernel support for TI DaVinci
Add base kernel support for the TI DaVinci platform. This patch only includes interrupts, timers, CPU identification, serial support and basic power and sleep controller init. More drivers to come. Signed-off-by: Kevin Hilman <khilman@mvista.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-davinci/irq.c')
-rw-r--r--arch/arm/mach-davinci/irq.c226
1 files changed, 226 insertions, 0 deletions
diff --git a/arch/arm/mach-davinci/irq.c b/arch/arm/mach-davinci/irq.c
new file mode 100644
index 000000000000..1333d84d2e45
--- /dev/null
+++ b/arch/arm/mach-davinci/irq.c
@@ -0,0 +1,226 @@
1/*
2 * Interrupt handler for DaVinci boards.
3 *
4 * Copyright (C) 2006 Texas Instruments.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 */
21#include <linux/kernel.h>
22#include <linux/init.h>
23#include <linux/interrupt.h>
24#include <linux/irq.h>
25
26#include <asm/hardware.h>
27#include <asm/io.h>
28#include <asm/mach/irq.h>
29
30#define IRQ_BIT(irq) ((irq) & 0x1f)
31
32#define FIQ_REG0_OFFSET 0x0000
33#define FIQ_REG1_OFFSET 0x0004
34#define IRQ_REG0_OFFSET 0x0008
35#define IRQ_REG1_OFFSET 0x000C
36#define IRQ_ENT_REG0_OFFSET 0x0018
37#define IRQ_ENT_REG1_OFFSET 0x001C
38#define IRQ_INCTL_REG_OFFSET 0x0020
39#define IRQ_EABASE_REG_OFFSET 0x0024
40#define IRQ_INTPRI0_REG_OFFSET 0x0030
41#define IRQ_INTPRI7_REG_OFFSET 0x004C
42
43static inline unsigned int davinci_irq_readl(int offset)
44{
45 return davinci_readl(DAVINCI_ARM_INTC_BASE + offset);
46}
47
48static inline void davinci_irq_writel(unsigned long value, int offset)
49{
50 davinci_writel(value, DAVINCI_ARM_INTC_BASE + offset);
51}
52
53/* Disable interrupt */
54static void davinci_mask_irq(unsigned int irq)
55{
56 unsigned int mask;
57 u32 l;
58
59 mask = 1 << IRQ_BIT(irq);
60
61 if (irq > 31) {
62 l = davinci_irq_readl(IRQ_ENT_REG1_OFFSET);
63 l &= ~mask;
64 davinci_irq_writel(l, IRQ_ENT_REG1_OFFSET);
65 } else {
66 l = davinci_irq_readl(IRQ_ENT_REG0_OFFSET);
67 l &= ~mask;
68 davinci_irq_writel(l, IRQ_ENT_REG0_OFFSET);
69 }
70}
71
72/* Enable interrupt */
73static void davinci_unmask_irq(unsigned int irq)
74{
75 unsigned int mask;
76 u32 l;
77
78 mask = 1 << IRQ_BIT(irq);
79
80 if (irq > 31) {
81 l = davinci_irq_readl(IRQ_ENT_REG1_OFFSET);
82 l |= mask;
83 davinci_irq_writel(l, IRQ_ENT_REG1_OFFSET);
84 } else {
85 l = davinci_irq_readl(IRQ_ENT_REG0_OFFSET);
86 l |= mask;
87 davinci_irq_writel(l, IRQ_ENT_REG0_OFFSET);
88 }
89}
90
91/* EOI interrupt */
92static void davinci_ack_irq(unsigned int irq)
93{
94 unsigned int mask;
95
96 mask = 1 << IRQ_BIT(irq);
97
98 if (irq > 31)
99 davinci_irq_writel(mask, IRQ_REG1_OFFSET);
100 else
101 davinci_irq_writel(mask, IRQ_REG0_OFFSET);
102}
103
104static struct irq_chip davinci_irq_chip_0 = {
105 .name = "AINTC",
106 .ack = davinci_ack_irq,
107 .mask = davinci_mask_irq,
108 .unmask = davinci_unmask_irq,
109};
110
111
112/* FIQ are pri 0-1; otherwise 2-7, with 7 lowest priority */
113static const u8 default_priorities[DAVINCI_N_AINTC_IRQ] __initdata = {
114 [IRQ_VDINT0] = 2,
115 [IRQ_VDINT1] = 6,
116 [IRQ_VDINT2] = 6,
117 [IRQ_HISTINT] = 6,
118 [IRQ_H3AINT] = 6,
119 [IRQ_PRVUINT] = 6,
120 [IRQ_RSZINT] = 6,
121 [7] = 7,
122 [IRQ_VENCINT] = 6,
123 [IRQ_ASQINT] = 6,
124 [IRQ_IMXINT] = 6,
125 [IRQ_VLCDINT] = 6,
126 [IRQ_USBINT] = 4,
127 [IRQ_EMACINT] = 4,
128 [14] = 7,
129 [15] = 7,
130 [IRQ_CCINT0] = 5, /* dma */
131 [IRQ_CCERRINT] = 5, /* dma */
132 [IRQ_TCERRINT0] = 5, /* dma */
133 [IRQ_TCERRINT] = 5, /* dma */
134 [IRQ_PSCIN] = 7,
135 [21] = 7,
136 [IRQ_IDE] = 4,
137 [23] = 7,
138 [IRQ_MBXINT] = 7,
139 [IRQ_MBRINT] = 7,
140 [IRQ_MMCINT] = 7,
141 [IRQ_SDIOINT] = 7,
142 [28] = 7,
143 [IRQ_DDRINT] = 7,
144 [IRQ_AEMIFINT] = 7,
145 [IRQ_VLQINT] = 4,
146 [IRQ_TINT0_TINT12] = 2, /* clockevent */
147 [IRQ_TINT0_TINT34] = 2, /* clocksource */
148 [IRQ_TINT1_TINT12] = 7, /* DSP timer */
149 [IRQ_TINT1_TINT34] = 7, /* system tick */
150 [IRQ_PWMINT0] = 7,
151 [IRQ_PWMINT1] = 7,
152 [IRQ_PWMINT2] = 7,
153 [IRQ_I2C] = 3,
154 [IRQ_UARTINT0] = 3,
155 [IRQ_UARTINT1] = 3,
156 [IRQ_UARTINT2] = 3,
157 [IRQ_SPINT0] = 3,
158 [IRQ_SPINT1] = 3,
159 [45] = 7,
160 [IRQ_DSP2ARM0] = 4,
161 [IRQ_DSP2ARM1] = 4,
162 [IRQ_GPIO0] = 7,
163 [IRQ_GPIO1] = 7,
164 [IRQ_GPIO2] = 7,
165 [IRQ_GPIO3] = 7,
166 [IRQ_GPIO4] = 7,
167 [IRQ_GPIO5] = 7,
168 [IRQ_GPIO6] = 7,
169 [IRQ_GPIO7] = 7,
170 [IRQ_GPIOBNK0] = 7,
171 [IRQ_GPIOBNK1] = 7,
172 [IRQ_GPIOBNK2] = 7,
173 [IRQ_GPIOBNK3] = 7,
174 [IRQ_GPIOBNK4] = 7,
175 [IRQ_COMMTX] = 7,
176 [IRQ_COMMRX] = 7,
177 [IRQ_EMUINT] = 7,
178};
179
180/* ARM Interrupt Controller Initialization */
181void __init davinci_irq_init(void)
182{
183 unsigned i;
184 const u8 *priority = default_priorities;
185
186 /* Clear all interrupt requests */
187 davinci_irq_writel(~0x0, FIQ_REG0_OFFSET);
188 davinci_irq_writel(~0x0, FIQ_REG1_OFFSET);
189 davinci_irq_writel(~0x0, IRQ_REG0_OFFSET);
190 davinci_irq_writel(~0x0, IRQ_REG1_OFFSET);
191
192 /* Disable all interrupts */
193 davinci_irq_writel(0x0, IRQ_ENT_REG0_OFFSET);
194 davinci_irq_writel(0x0, IRQ_ENT_REG1_OFFSET);
195
196 /* Interrupts disabled immediately, IRQ entry reflects all */
197 davinci_irq_writel(0x0, IRQ_INCTL_REG_OFFSET);
198
199 /* we don't use the hardware vector table, just its entry addresses */
200 davinci_irq_writel(0, IRQ_EABASE_REG_OFFSET);
201
202 /* Clear all interrupt requests */
203 davinci_irq_writel(~0x0, FIQ_REG0_OFFSET);
204 davinci_irq_writel(~0x0, FIQ_REG1_OFFSET);
205 davinci_irq_writel(~0x0, IRQ_REG0_OFFSET);
206 davinci_irq_writel(~0x0, IRQ_REG1_OFFSET);
207
208 for (i = IRQ_INTPRI0_REG_OFFSET; i <= IRQ_INTPRI7_REG_OFFSET; i += 4) {
209 unsigned j;
210 u32 pri;
211
212 for (j = 0, pri = 0; j < 32; j += 4, priority++)
213 pri |= (*priority & 0x07) << j;
214 davinci_irq_writel(pri, i);
215 }
216
217 /* set up genirq dispatch for ARM INTC */
218 for (i = 0; i < DAVINCI_N_AINTC_IRQ; i++) {
219 set_irq_chip(i, &davinci_irq_chip_0);
220 set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
221 if (i != IRQ_TINT1_TINT34)
222 set_irq_handler(i, handle_edge_irq);
223 else
224 set_irq_handler(i, handle_level_irq);
225 }
226}