4 * (C) Copyright 2009, Greg Ungerer <gerg@snapgear.com>
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
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>
17 #include <asm/coldfire.h>
18 #include <asm/mcfsim.h>
19 #include <asm/traps.h>
22 * Each vector needs a unique priority and level asscoiated with it.
23 * We don't really care so much what they are, we don't rely on the
24 * tranditional priority interrupt scheme of the m68k/ColdFire.
26 static u8 intc_intpri
= 0x36;
28 static void intc_irq_mask(unsigned int irq
)
30 if ((irq
>= MCFINT_VECBASE
) && (irq
<= MCFINT_VECBASE
+ 128)) {
31 unsigned long imraddr
;
34 irq
-= MCFINT_VECBASE
;
36 imraddr
+= (irq
& 0x40) ? MCFICM_INTC1
: MCFICM_INTC0
;
37 imraddr
+= (irq
& 0x20) ? MCFINTC_IMRH
: MCFINTC_IMRL
;
38 imrbit
= 0x1 << (irq
& 0x1f);
40 val
= __raw_readl(imraddr
);
41 __raw_writel(val
| imrbit
, imraddr
);
45 static void intc_irq_unmask(unsigned int irq
)
47 if ((irq
>= MCFINT_VECBASE
) && (irq
<= MCFINT_VECBASE
+ 128)) {
48 unsigned long intaddr
, imraddr
, icraddr
;
51 irq
-= MCFINT_VECBASE
;
53 intaddr
+= (irq
& 0x40) ? MCFICM_INTC1
: MCFICM_INTC0
;
54 imraddr
= intaddr
+ ((irq
& 0x20) ? MCFINTC_IMRH
: MCFINTC_IMRL
);
55 icraddr
= intaddr
+ MCFINTC_ICR0
+ (irq
& 0x3f);
56 imrbit
= 0x1 << (irq
& 0x1f);
58 /* Don't set the "maskall" bit! */
59 if ((irq
& 0x20) == 0)
62 if (__raw_readb(icraddr
) == 0)
63 __raw_writeb(intc_intpri
--, icraddr
);
65 val
= __raw_readl(imraddr
);
66 __raw_writel(val
& ~imrbit
, imraddr
);
70 static struct irq_chip intc_irq_chip
= {
72 .mask
= intc_irq_mask
,
73 .unmask
= intc_irq_unmask
,
76 void __init
init_IRQ(void)
82 /* Mask all interrupt sources */
83 __raw_writel(0x1, MCF_IPSBAR
+ MCFICM_INTC0
+ MCFINTC_IMRL
);
84 __raw_writel(0x1, MCF_IPSBAR
+ MCFICM_INTC1
+ MCFINTC_IMRL
);
86 for (irq
= 0; (irq
< NR_IRQS
); irq
++) {
87 irq_desc
[irq
].status
= IRQ_DISABLED
;
88 irq_desc
[irq
].action
= NULL
;
89 irq_desc
[irq
].depth
= 1;
90 irq_desc
[irq
].chip
= &intc_irq_chip
;