2 * arch/ppc/syslib/cpc700_pic.c
4 * Interrupt controller support for IBM Spruce
6 * Authors: Mark Greer, Matt Porter, and Johnnie Peters
11 * 2001-2002 (c) MontaVista, Software, Inc. This file is licensed under
12 * the terms of the GNU General Public License version 2. This program
13 * is licensed "as is" without any warranty of any kind, whether express
17 #include <linux/stddef.h>
18 #include <linux/init.h>
19 #include <linux/sched.h>
20 #include <linux/signal.h>
21 #include <linux/irq.h>
24 #include <asm/system.h>
30 cpc700_unmask_irq(unsigned int irq
)
35 * IRQ 31 is largest IRQ supported.
36 * IRQs 17-19 are reserved.
38 if ((irq
<= 31) && ((irq
< 17) || (irq
> 19))) {
39 tr_bits
= CPC700_IN_32(CPC700_UIC_UICTR
);
41 if ((tr_bits
& (1 << (31 - irq
))) == 0) {
42 /* level trigger interrupt, clear bit in status
44 CPC700_OUT_32(CPC700_UIC_UICSR
, 1 << (31 - irq
));
47 /* Know IRQ fits in entry 0 of ppc_cached_irq_mask[] */
48 ppc_cached_irq_mask
[0] |= CPC700_UIC_IRQ_BIT(irq
);
50 CPC700_OUT_32(CPC700_UIC_UICER
, ppc_cached_irq_mask
[0]);
56 cpc700_mask_irq(unsigned int irq
)
59 * IRQ 31 is largest IRQ supported.
60 * IRQs 17-19 are reserved.
62 if ((irq
<= 31) && ((irq
< 17) || (irq
> 19))) {
63 /* Know IRQ fits in entry 0 of ppc_cached_irq_mask[] */
64 ppc_cached_irq_mask
[0] &=
65 ~CPC700_UIC_IRQ_BIT(irq
);
67 CPC700_OUT_32(CPC700_UIC_UICER
, ppc_cached_irq_mask
[0]);
73 cpc700_mask_and_ack_irq(unsigned int irq
)
78 * IRQ 31 is largest IRQ supported.
79 * IRQs 17-19 are reserved.
81 if ((irq
<= 31) && ((irq
< 17) || (irq
> 19))) {
82 /* Know IRQ fits in entry 0 of ppc_cached_irq_mask[] */
83 bit
= CPC700_UIC_IRQ_BIT(irq
);
85 ppc_cached_irq_mask
[0] &= ~bit
;
86 CPC700_OUT_32(CPC700_UIC_UICER
, ppc_cached_irq_mask
[0]);
87 CPC700_OUT_32(CPC700_UIC_UICSR
, bit
); /* Write 1 clears IRQ */
92 static struct hw_interrupt_type cpc700_pic
= {
93 .typename
= "CPC700 PIC",
94 .enable
= cpc700_unmask_irq
,
95 .disable
= cpc700_mask_irq
,
96 .ack
= cpc700_mask_and_ack_irq
,
100 cpc700_pic_init_irq(unsigned int irq
)
104 /* Set interrupt sense */
105 tmp
= CPC700_IN_32(CPC700_UIC_UICTR
);
106 if (cpc700_irq_assigns
[irq
][0] == 0) {
107 tmp
&= ~CPC700_UIC_IRQ_BIT(irq
);
109 tmp
|= CPC700_UIC_IRQ_BIT(irq
);
111 CPC700_OUT_32(CPC700_UIC_UICTR
, tmp
);
113 /* Set interrupt polarity */
114 tmp
= CPC700_IN_32(CPC700_UIC_UICPR
);
115 if (cpc700_irq_assigns
[irq
][1]) {
116 tmp
|= CPC700_UIC_IRQ_BIT(irq
);
118 tmp
&= ~CPC700_UIC_IRQ_BIT(irq
);
120 CPC700_OUT_32(CPC700_UIC_UICPR
, tmp
);
122 /* Set interrupt critical */
123 tmp
= CPC700_IN_32(CPC700_UIC_UICCR
);
124 tmp
|= CPC700_UIC_IRQ_BIT(irq
);
125 CPC700_OUT_32(CPC700_UIC_UICCR
, tmp
);
131 cpc700_init_IRQ(void)
135 ppc_cached_irq_mask
[0] = 0;
136 CPC700_OUT_32(CPC700_UIC_UICER
, 0x00000000); /* Disable all irq's */
137 CPC700_OUT_32(CPC700_UIC_UICSR
, 0xffffffff); /* Clear cur intrs */
138 CPC700_OUT_32(CPC700_UIC_UICCR
, 0xffffffff); /* Gen INT not MCP */
139 CPC700_OUT_32(CPC700_UIC_UICPR
, 0x00000000); /* Active low */
140 CPC700_OUT_32(CPC700_UIC_UICTR
, 0x00000000); /* Level Sensitive */
141 CPC700_OUT_32(CPC700_UIC_UICVR
, CPC700_UIC_UICVCR_0_HI
);
142 /* IRQ 0 is highest */
144 for (i
= 0; i
< 17; i
++) {
145 irq_desc
[i
].handler
= &cpc700_pic
;
146 cpc700_pic_init_irq(i
);
149 for (i
= 20; i
< 32; i
++) {
150 irq_desc
[i
].handler
= &cpc700_pic
;
151 cpc700_pic_init_irq(i
);
160 * Find the highest IRQ that generating an interrupt, if any.
163 cpc700_get_irq(struct pt_regs
*regs
)
166 u_int irq_status
, irq_test
= 1;
168 irq_status
= CPC700_IN_32(CPC700_UIC_UICMSR
);
172 if (irq_status
& irq_test
)
176 } while (irq
< NR_IRQS
);