aboutsummaryrefslogtreecommitdiffstats
path: root/arch
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
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')
-rw-r--r--arch/m68k/include/asm/m5272sim.h37
-rw-r--r--arch/m68knommu/platform/5272/Makefile2
-rw-r--r--arch/m68knommu/platform/5272/intc.c138
-rw-r--r--arch/m68knommu/platform/coldfire/Makefile2
4 files changed, 174 insertions, 5 deletions
diff --git a/arch/m68k/include/asm/m5272sim.h b/arch/m68k/include/asm/m5272sim.h
index 469686ffc4af..df3332c2317d 100644
--- a/arch/m68k/include/asm/m5272sim.h
+++ b/arch/m68k/include/asm/m5272sim.h
@@ -12,7 +12,6 @@
12#define m5272sim_h 12#define m5272sim_h
13/****************************************************************************/ 13/****************************************************************************/
14 14
15
16/* 15/*
17 * Define the 5272 SIM register set addresses. 16 * Define the 5272 SIM register set addresses.
18 */ 17 */
@@ -76,8 +75,40 @@
76/* 75/*
77 * Define system peripheral IRQ usage. 76 * Define system peripheral IRQ usage.
78 */ 77 */
79#define MCF_IRQ_TIMER 69 /* Timer0, Level 6 */ 78#define MCFINT_VECBASE 64 /* Base of interrupts */
80#define MCF_IRQ_PROFILER 70 /* Timer1, Level 7 */ 79#define MCF_IRQ_SPURIOUS 64 /* User Spurious */
80#define MCF_IRQ_EINT1 65 /* External Interrupt 1 */
81#define MCF_IRQ_EINT2 66 /* External Interrupt 2 */
82#define MCF_IRQ_EINT3 67 /* External Interrupt 3 */
83#define MCF_IRQ_EINT4 68 /* External Interrupt 4 */
84#define MCF_IRQ_TIMER1 69 /* Timer 1 */
85#define MCF_IRQ_TIMER2 70 /* Timer 2 */
86#define MCF_IRQ_TIMER3 71 /* Timer 3 */
87#define MCF_IRQ_TIMER4 72 /* Timer 4 */
88#define MCF_IRQ_UART1 73 /* UART 1 */
89#define MCF_IRQ_UART2 74 /* UART 2 */
90#define MCF_IRQ_PLIP 75 /* PLIC 2Khz Periodic */
91#define MCF_IRQ_PLIA 76 /* PLIC Asynchronous */
92#define MCF_IRQ_USB0 77 /* USB Endpoint 0 */
93#define MCF_IRQ_USB1 78 /* USB Endpoint 1 */
94#define MCF_IRQ_USB2 79 /* USB Endpoint 2 */
95#define MCF_IRQ_USB3 80 /* USB Endpoint 3 */
96#define MCF_IRQ_USB4 81 /* USB Endpoint 4 */
97#define MCF_IRQ_USB5 82 /* USB Endpoint 5 */
98#define MCF_IRQ_USB6 83 /* USB Endpoint 6 */
99#define MCF_IRQ_USB7 84 /* USB Endpoint 7 */
100#define MCF_IRQ_DMA 85 /* DMA Controller */
101#define MCF_IRQ_ERX 86 /* Ethernet Receiver */
102#define MCF_IRQ_ETX 87 /* Ethernet Transmitter */
103#define MCF_IRQ_ENTC 88 /* Ethernet Non-Time Critical */
104#define MCF_IRQ_QSPI 89 /* Queued Serial Interface */
105#define MCF_IRQ_EINT5 90 /* External Interrupt 5 */
106#define MCF_IRQ_EINT6 91 /* External Interrupt 6 */
107#define MCF_IRQ_SWTO 92 /* Software Watchdog */
108#define MCFINT_VECMAX 95 /* Maxmum interrupt */
109
110#define MCF_IRQ_TIMER MCF_IRQ_TIMER1
111#define MCF_IRQ_PROFILER MCF_IRQ_TIMER2
81 112
82/* 113/*
83 * Generic GPIO support 114 * Generic GPIO support
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
diff --git a/arch/m68knommu/platform/coldfire/Makefile b/arch/m68knommu/platform/coldfire/Makefile
index 24ea95a23128..f72a0e5d9996 100644
--- a/arch/m68knommu/platform/coldfire/Makefile
+++ b/arch/m68knommu/platform/coldfire/Makefile
@@ -21,7 +21,7 @@ obj-$(CONFIG_M520x) += pit.o intc-simr.o
21obj-$(CONFIG_M523x) += pit.o dma_timer.o intc-2.o 21obj-$(CONFIG_M523x) += pit.o dma_timer.o intc-2.o
22obj-$(CONFIG_M5249) += timers.o intc.o 22obj-$(CONFIG_M5249) += timers.o intc.o
23obj-$(CONFIG_M527x) += pit.o intc-2.o 23obj-$(CONFIG_M527x) += pit.o intc-2.o
24obj-$(CONFIG_M5272) += timers.o intc.o 24obj-$(CONFIG_M5272) += timers.o
25obj-$(CONFIG_M528x) += pit.o intc-2.o 25obj-$(CONFIG_M528x) += pit.o intc-2.o
26obj-$(CONFIG_M5307) += timers.o intc.o 26obj-$(CONFIG_M5307) += timers.o intc.o
27obj-$(CONFIG_M532x) += timers.o intc-simr.o 27obj-$(CONFIG_M532x) += timers.o intc-simr.o