2 * Copyright 2001 MontaVista Software Inc.
3 * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
5 * arch/mips/ddb5xxx/ddb5477/irq_5477.c
6 * This file defines the irq handler for Vrc5477.
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
16 * Vrc5477 defines 32 IRQs.
18 * This file exports one function:
19 * vrc5477_irq_init(u32 irq_base);
22 #include <linux/interrupt.h>
23 #include <linux/types.h>
24 #include <linux/ptrace.h>
26 #include <asm/debug.h>
28 #include <asm/ddb5xxx/ddb5xxx.h>
30 /* number of total irqs supported by Vrc5477 */
31 #define NUM_5477_IRQ 32
33 static int vrc5477_irq_base
= -1;
37 vrc5477_irq_enable(unsigned int irq
)
39 db_assert(vrc5477_irq_base
!= -1);
40 db_assert(irq
>= vrc5477_irq_base
);
41 db_assert(irq
< vrc5477_irq_base
+ NUM_5477_IRQ
);
43 ll_vrc5477_irq_enable(irq
- vrc5477_irq_base
);
47 vrc5477_irq_disable(unsigned int irq
)
49 db_assert(vrc5477_irq_base
!= -1);
50 db_assert(irq
>= vrc5477_irq_base
);
51 db_assert(irq
< vrc5477_irq_base
+ NUM_5477_IRQ
);
53 ll_vrc5477_irq_disable(irq
- vrc5477_irq_base
);
57 vrc5477_irq_ack(unsigned int irq
)
59 db_assert(vrc5477_irq_base
!= -1);
60 db_assert(irq
>= vrc5477_irq_base
);
61 db_assert(irq
< vrc5477_irq_base
+ NUM_5477_IRQ
);
63 /* clear the interrupt bit */
64 /* some irqs require the driver to clear the sources */
65 ddb_out32(DDB_INTCLR32
, 1 << (irq
- vrc5477_irq_base
));
67 /* disable interrupt - some handler will re-enable the irq
68 * and if the interrupt is leveled, we will have infinite loop
70 ll_vrc5477_irq_disable(irq
- vrc5477_irq_base
);
74 vrc5477_irq_end(unsigned int irq
)
76 db_assert(vrc5477_irq_base
!= -1);
77 db_assert(irq
>= vrc5477_irq_base
);
78 db_assert(irq
< vrc5477_irq_base
+ NUM_5477_IRQ
);
80 if(!(irq_desc
[irq
].status
& (IRQ_DISABLED
| IRQ_INPROGRESS
)))
81 ll_vrc5477_irq_enable( irq
- vrc5477_irq_base
);
84 struct irq_chip vrc5477_irq_controller
= {
85 .name
= "vrc5477_irq",
86 .ack
= vrc5477_irq_ack
,
87 .mask
= vrc5477_irq_disable
,
88 .mask_ack
= vrc5477_irq_ack
,
89 .unmask
= vrc5477_irq_enable
,
90 .end
= vrc5477_irq_end
93 void __init
vrc5477_irq_init(u32 irq_base
)
97 for (i
= irq_base
; i
< irq_base
+ NUM_5477_IRQ
; i
++)
98 set_irq_chip(i
, &vrc5477_irq_controller
);
100 vrc5477_irq_base
= irq_base
;
103 void ll_vrc5477_irq_route(int vrc5477_irq
, int ip
)
109 db_assert(vrc5477_irq
>= 0);
110 db_assert(vrc5477_irq
< NUM_5477_IRQ
);
112 db_assert((ip
< 5) || (ip
== 6));
114 reg_index
= DDB_INTCTRL0
+ vrc5477_irq
/8*4;
115 reg_value
= ddb_in32(reg_index
);
116 reg_bitmask
= 7 << (vrc5477_irq
% 8 * 4);
117 reg_value
&= ~reg_bitmask
;
118 reg_value
|= ip
<< (vrc5477_irq
% 8 * 4);
119 ddb_out32(reg_index
, reg_value
);
122 void ll_vrc5477_irq_enable(int vrc5477_irq
)
128 db_assert(vrc5477_irq
>= 0);
129 db_assert(vrc5477_irq
< NUM_5477_IRQ
);
131 reg_index
= DDB_INTCTRL0
+ vrc5477_irq
/8*4;
132 reg_value
= ddb_in32(reg_index
);
133 reg_bitmask
= 8 << (vrc5477_irq
% 8 * 4);
134 db_assert((reg_value
& reg_bitmask
) == 0);
135 ddb_out32(reg_index
, reg_value
| reg_bitmask
);
138 void ll_vrc5477_irq_disable(int vrc5477_irq
)
144 db_assert(vrc5477_irq
>= 0);
145 db_assert(vrc5477_irq
< NUM_5477_IRQ
);
147 reg_index
= DDB_INTCTRL0
+ vrc5477_irq
/8*4;
148 reg_value
= ddb_in32(reg_index
);
149 reg_bitmask
= 8 << (vrc5477_irq
% 8 * 4);
151 /* we assert that the interrupt is enabled (perhaps over-zealous) */
152 db_assert( (reg_value
& reg_bitmask
) != 0);
153 ddb_out32(reg_index
, reg_value
& ~reg_bitmask
);