aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m68knommu/platform/5272
diff options
context:
space:
mode:
authorGreg Ungerer <gerg@uclinux.org>2009-07-06 19:39:11 -0400
committerGreg Ungerer <gerg@uclinux.org>2009-09-15 19:43:54 -0400
commit9075216d2c8761c91dc268125f6580af3ffc58b5 (patch)
tree95df9112cacda86d5fc7603b0e83bd88abdfde45 /arch/m68knommu/platform/5272
parentda3601a5fa664c8d51383fe916d96bd4fbce84b8 (diff)
m68knommu: create a speciailized ColdFire 5272 interrupt controller
The ColdFire 5272 CPU has a very different interrupt controller than any of the other ColdFire parts. It needs its own controller code to correctly setup and ack interrupts. Signed-off-by: Greg Ungerer <gerg@uclinux.org>
Diffstat (limited to 'arch/m68knommu/platform/5272')
-rw-r--r--arch/m68knommu/platform/5272/Makefile2
-rw-r--r--arch/m68knommu/platform/5272/intc.c138
2 files changed, 139 insertions, 1 deletions
diff --git a/arch/m68knommu/platform/5272/Makefile b/arch/m68knommu/platform/5272/Makefile
index 3d90e6d92459..93673ef8e2c1 100644
--- a/arch/m68knommu/platform/5272/Makefile
+++ b/arch/m68knommu/platform/5272/Makefile
@@ -14,5 +14,5 @@
14 14
15asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1 15asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
16 16
17obj-y := config.o gpio.o 17obj-y := config.o gpio.o intc.o
18 18
diff --git a/arch/m68knommu/platform/5272/intc.c b/arch/m68knommu/platform/5272/intc.c
new file mode 100644
index 000000000000..7081e0a9720e
--- /dev/null
+++ b/arch/m68knommu/platform/5272/intc.c
@@ -0,0 +1,138 @@
1/*
2 * intc.c -- interrupt controller or ColdFire 5272 SoC
3 *
4 * (C) Copyright 2009, Greg Ungerer <gerg@snapgear.com>
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive
8 * for more details.
9 */
10
11#include <linux/types.h>
12#include <linux/init.h>
13#include <linux/kernel.h>
14#include <linux/interrupt.h>
15#include <linux/irq.h>
16#include <linux/io.h>
17#include <asm/coldfire.h>
18#include <asm/mcfsim.h>
19#include <asm/traps.h>
20
21/*
22 * The 5272 ColdFire interrupt controller is nothing like any other
23 * ColdFire interrupt controller - it truly is completely different.
24 * Given its age it is unlikely to be used on any other ColdFire CPU.
25 */
26
27/*
28 * The masking and priproty setting of interrupts on the 5272 is done
29 * via a set of 4 "Interrupt Controller Registers" (ICR). There is a
30 * loose mapping of vector number to register and internal bits, but
31 * a table is the easiest and quickest way to map them.
32 */
33struct irqmap {
34 unsigned char icr;
35 unsigned char index;
36 unsigned char ack;
37};
38
39static struct irqmap intc_irqmap[MCFINT_VECMAX - MCFINT_VECBASE] = {
40 /*MCF_IRQ_SPURIOUS*/ { .icr = 0, .index = 0, .ack = 0, },
41 /*MCF_IRQ_EINT1*/ { .icr = MCFSIM_ICR1, .index = 28, .ack = 1, },
42 /*MCF_IRQ_EINT2*/ { .icr = MCFSIM_ICR1, .index = 24, .ack = 1, },
43 /*MCF_IRQ_EINT3*/ { .icr = MCFSIM_ICR1, .index = 20, .ack = 1, },
44 /*MCF_IRQ_EINT4*/ { .icr = MCFSIM_ICR1, .index = 16, .ack = 1, },
45 /*MCF_IRQ_TIMER1*/ { .icr = MCFSIM_ICR1, .index = 12, .ack = 0, },
46 /*MCF_IRQ_TIMER2*/ { .icr = MCFSIM_ICR1, .index = 8, .ack = 0, },
47 /*MCF_IRQ_TIMER3*/ { .icr = MCFSIM_ICR1, .index = 4, .ack = 0, },
48 /*MCF_IRQ_TIMER4*/ { .icr = MCFSIM_ICR1, .index = 0, .ack = 0, },
49 /*MCF_IRQ_UART1*/ { .icr = MCFSIM_ICR2, .index = 28, .ack = 0, },
50 /*MCF_IRQ_UART2*/ { .icr = MCFSIM_ICR2, .index = 24, .ack = 0, },
51 /*MCF_IRQ_PLIP*/ { .icr = MCFSIM_ICR2, .index = 20, .ack = 0, },
52 /*MCF_IRQ_PLIA*/ { .icr = MCFSIM_ICR2, .index = 16, .ack = 0, },
53 /*MCF_IRQ_USB0*/ { .icr = MCFSIM_ICR2, .index = 12, .ack = 0, },
54 /*MCF_IRQ_USB1*/ { .icr = MCFSIM_ICR2, .index = 8, .ack = 0, },
55 /*MCF_IRQ_USB2*/ { .icr = MCFSIM_ICR2, .index = 4, .ack = 0, },
56 /*MCF_IRQ_USB3*/ { .icr = MCFSIM_ICR2, .index = 0, .ack = 0, },
57 /*MCF_IRQ_USB4*/ { .icr = MCFSIM_ICR3, .index = 28, .ack = 0, },
58 /*MCF_IRQ_USB5*/ { .icr = MCFSIM_ICR3, .index = 24, .ack = 0, },
59 /*MCF_IRQ_USB6*/ { .icr = MCFSIM_ICR3, .index = 20, .ack = 0, },
60 /*MCF_IRQ_USB7*/ { .icr = MCFSIM_ICR3, .index = 16, .ack = 0, },
61 /*MCF_IRQ_DMA*/ { .icr = MCFSIM_ICR3, .index = 12, .ack = 0, },
62 /*MCF_IRQ_ERX*/ { .icr = MCFSIM_ICR3, .index = 8, .ack = 0, },
63 /*MCF_IRQ_ETX*/ { .icr = MCFSIM_ICR3, .index = 4, .ack = 0, },
64 /*MCF_IRQ_ENTC*/ { .icr = MCFSIM_ICR3, .index = 0, .ack = 0, },
65 /*MCF_IRQ_QSPI*/ { .icr = MCFSIM_ICR4, .index = 28, .ack = 0, },
66 /*MCF_IRQ_EINT5*/ { .icr = MCFSIM_ICR4, .index = 24, .ack = 1, },
67 /*MCF_IRQ_EINT6*/ { .icr = MCFSIM_ICR4, .index = 20, .ack = 1, },
68 /*MCF_IRQ_SWTO*/ { .icr = MCFSIM_ICR4, .index = 16, .ack = 0, },
69};
70
71static void intc_irq_mask(unsigned int irq)
72{
73 if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECMAX)) {
74 u32 v;
75 irq -= MCFINT_VECBASE;
76 v = 0x8 << intc_irqmap[irq].index;
77 writel(v, MCF_MBAR + intc_irqmap[irq].icr);
78 }
79}
80
81static void intc_irq_unmask(unsigned int irq)
82{
83 if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECMAX)) {
84 u32 v;
85 irq -= MCFINT_VECBASE;
86 v = 0xd << intc_irqmap[irq].index;
87 writel(v, MCF_MBAR + intc_irqmap[irq].icr);
88 }
89}
90
91static void intc_irq_ack(unsigned int irq)
92{
93 /* Only external interrupts are acked */
94 if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECMAX)) {
95 irq -= MCFINT_VECBASE;
96 if (intc_irqmap[irq].ack) {
97 u32 v;
98 v = 0xd << intc_irqmap[irq].index;
99 writel(v, MCF_MBAR + intc_irqmap[irq].icr);
100 }
101 }
102}
103
104static int intc_irq_set_type(unsigned int irq, unsigned int type)
105{
106 /* We can set the edge type here for external interrupts */
107 return 0;
108}
109
110static struct irq_chip intc_irq_chip = {
111 .name = "CF-INTC",
112 .mask = intc_irq_mask,
113 .unmask = intc_irq_unmask,
114 .ack = intc_irq_ack,
115 .set_type = intc_irq_set_type,
116};
117
118void __init init_IRQ(void)
119{
120 int irq;
121
122 init_vectors();
123
124 /* Mask all interrupt sources */
125 writel(0x88888888, MCF_MBAR + MCFSIM_ICR1);
126 writel(0x88888888, MCF_MBAR + MCFSIM_ICR2);
127 writel(0x88888888, MCF_MBAR + MCFSIM_ICR3);
128 writel(0x88888888, MCF_MBAR + MCFSIM_ICR4);
129
130 for (irq = 0; (irq < NR_IRQS); irq++) {
131 irq_desc[irq].status = IRQ_DISABLED;
132 irq_desc[irq].action = NULL;
133 irq_desc[irq].depth = 1;
134 irq_desc[irq].chip = &intc_irq_chip;
135 intc_irq_set_type(irq, 0);
136 }
137}
138