1 /* The CPM2 internal interrupt controller. It is usually
2 * the only interrupt controller.
3 * There are two 32-bit registers (high/low) for up to 64
6 * Now, the fun starts.....Interrupt Numbers DO NOT MAP
7 * in a simple arithmetic fashion to mask or pending registers.
8 * That is, interrupt 4 does not map to bit position 4.
9 * We create two tables, indexed by vector number, to indicate
10 * which register to use and which bit in the register to use.
13 #include <linux/stddef.h>
14 #include <linux/init.h>
15 #include <linux/sched.h>
16 #include <linux/signal.h>
17 #include <linux/irq.h>
19 #include <asm/immap_cpm2.h>
20 #include <asm/mpc8260.h>
24 static u_char irq_to_siureg
[] = {
25 1, 1, 1, 1, 1, 1, 1, 1,
26 1, 1, 1, 1, 1, 1, 1, 1,
27 0, 0, 0, 0, 0, 0, 0, 0,
28 0, 0, 0, 0, 0, 0, 0, 0,
29 1, 1, 1, 1, 1, 1, 1, 1,
30 1, 1, 1, 1, 1, 1, 1, 1,
31 0, 0, 0, 0, 0, 0, 0, 0,
32 0, 0, 0, 0, 0, 0, 0, 0
35 /* bit numbers do not match the docs, these are precomputed so the bit for
36 * a given irq is (1 << irq_to_siubit[irq]) */
37 static u_char irq_to_siubit
[] = {
38 0, 15, 14, 13, 12, 11, 10, 9,
39 8, 7, 6, 5, 4, 3, 2, 1,
40 2, 1, 15, 14, 13, 12, 11, 10,
41 9, 8, 7, 6, 5, 4, 3, 0,
42 31, 30, 29, 28, 27, 26, 25, 24,
43 23, 22, 21, 20, 19, 18, 17, 16,
44 16, 17, 18, 19, 20, 21, 22, 23,
45 24, 25, 26, 27, 28, 29, 30, 31,
48 static void cpm2_mask_irq(unsigned int irq_nr
)
53 irq_nr
-= CPM_IRQ_OFFSET
;
55 bit
= irq_to_siubit
[irq_nr
];
56 word
= irq_to_siureg
[irq_nr
];
58 simr
= &(cpm2_immr
->im_intctl
.ic_simrh
);
59 ppc_cached_irq_mask
[word
] &= ~(1 << bit
);
60 simr
[word
] = ppc_cached_irq_mask
[word
];
63 static void cpm2_unmask_irq(unsigned int irq_nr
)
68 irq_nr
-= CPM_IRQ_OFFSET
;
70 bit
= irq_to_siubit
[irq_nr
];
71 word
= irq_to_siureg
[irq_nr
];
73 simr
= &(cpm2_immr
->im_intctl
.ic_simrh
);
74 ppc_cached_irq_mask
[word
] |= 1 << bit
;
75 simr
[word
] = ppc_cached_irq_mask
[word
];
78 static void cpm2_mask_and_ack(unsigned int irq_nr
)
81 volatile uint
*simr
, *sipnr
;
83 irq_nr
-= CPM_IRQ_OFFSET
;
85 bit
= irq_to_siubit
[irq_nr
];
86 word
= irq_to_siureg
[irq_nr
];
88 simr
= &(cpm2_immr
->im_intctl
.ic_simrh
);
89 sipnr
= &(cpm2_immr
->im_intctl
.ic_sipnrh
);
90 ppc_cached_irq_mask
[word
] &= ~(1 << bit
);
91 simr
[word
] = ppc_cached_irq_mask
[word
];
92 sipnr
[word
] = 1 << bit
;
95 static void cpm2_end_irq(unsigned int irq_nr
)
100 if (!(irq_desc
[irq_nr
].status
& (IRQ_DISABLED
|IRQ_INPROGRESS
))
101 && irq_desc
[irq_nr
].action
) {
103 irq_nr
-= CPM_IRQ_OFFSET
;
104 bit
= irq_to_siubit
[irq_nr
];
105 word
= irq_to_siureg
[irq_nr
];
107 simr
= &(cpm2_immr
->im_intctl
.ic_simrh
);
108 ppc_cached_irq_mask
[word
] |= 1 << bit
;
109 simr
[word
] = ppc_cached_irq_mask
[word
];
111 * Work around large numbers of spurious IRQs on PowerPC 82xx
118 static struct hw_interrupt_type cpm2_pic
= {
119 .typename
= " CPM2 SIU ",
120 .enable
= cpm2_unmask_irq
,
121 .disable
= cpm2_mask_irq
,
122 .ack
= cpm2_mask_and_ack
,
126 int cpm2_get_irq(struct pt_regs
*regs
)
131 /* For CPM2, read the SIVEC register and shift the bits down
132 * to get the irq number. */
133 bits
= cpm2_immr
->im_intctl
.ic_sivec
;
138 return irq
+CPM_IRQ_OFFSET
;
141 void cpm2_init_IRQ(void)
145 /* Clear the CPM IRQ controller, in case it has any bits set
146 * from the bootloader
149 /* Mask out everything */
150 cpm2_immr
->im_intctl
.ic_simrh
= 0x00000000;
151 cpm2_immr
->im_intctl
.ic_simrl
= 0x00000000;
155 cpm2_immr
->im_intctl
.ic_sipnrh
= 0xffffffff;
156 cpm2_immr
->im_intctl
.ic_sipnrl
= 0xffffffff;
159 /* Dummy read of the vector */
160 i
= cpm2_immr
->im_intctl
.ic_sivec
;
163 /* Initialize the default interrupt mapping priorities,
164 * in case the boot rom changed something on us.
166 cpm2_immr
->im_intctl
.ic_sicr
= 0;
167 cpm2_immr
->im_intctl
.ic_scprrh
= 0x05309770;
168 cpm2_immr
->im_intctl
.ic_scprrl
= 0x05309770;
171 /* Enable chaining to OpenPIC, and make everything level
173 for (i
= 0; i
< NR_CPM_INTS
; i
++) {
174 irq_desc
[i
+CPM_IRQ_OFFSET
].handler
= &cpm2_pic
;
175 irq_desc
[i
+CPM_IRQ_OFFSET
].status
|= IRQ_LEVEL
;