1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/init.h>
3 #include <linux/list.h>
6 #include <asm/mach/irq.h>
7 #include <asm/hardware/iomd.h>
11 // These are offsets from the stat register for each IRQ bank
17 static const u8 irq_prio_h
[256] = {
18 0, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10,
19 12, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10,
20 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
21 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
22 14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10,
23 14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10,
24 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
25 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
26 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10,
27 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10,
28 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
29 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
30 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10,
31 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10,
32 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
33 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
36 static const u8 irq_prio_d
[256] = {
37 0,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
38 20,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
39 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
40 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
41 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
42 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
43 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
44 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
45 23,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
46 23,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
47 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
48 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
49 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
50 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
51 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
52 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
55 static const u8 irq_prio_l
[256] = {
56 0, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
57 4, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
58 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
59 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
60 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3,
61 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3,
62 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
63 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
64 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
65 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
66 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
67 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
68 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
69 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
70 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
71 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
74 static int iomd_get_irq_nr(void)
79 /* get highest priority first */
80 reg
= readb(IOC_BASE
+ IOMD_IRQREQB
);
81 irq
= irq_prio_h
[reg
];
86 reg
= readb(IOC_BASE
+ IOMD_DMAREQ
);
87 irq
= irq_prio_d
[reg
];
91 /* get low priority */
92 reg
= readb(IOC_BASE
+ IOMD_IRQREQA
);
93 irq
= irq_prio_l
[reg
];
99 static void iomd_handle_irq(struct pt_regs
*regs
)
104 irq
= iomd_get_irq_nr();
106 generic_handle_irq(irq
);
110 static void __iomem
*iomd_get_base(struct irq_data
*d
)
112 void *cd
= irq_data_get_irq_chip_data(d
);
114 return (void __iomem
*)(unsigned long)cd
;
117 static void iomd_set_base_mask(unsigned int irq
, void __iomem
*base
, u32 mask
)
119 struct irq_data
*d
= irq_get_irq_data(irq
);
122 irq_set_chip_data(irq
, (void *)(unsigned long)base
);
125 static void iomd_irq_mask_ack(struct irq_data
*d
)
127 void __iomem
*base
= iomd_get_base(d
);
128 unsigned int val
, mask
= d
->mask
;
130 val
= readb(base
+ MASK
);
131 writeb(val
& ~mask
, base
+ MASK
);
132 writeb(mask
, base
+ CLR
);
135 static void iomd_irq_mask(struct irq_data
*d
)
137 void __iomem
*base
= iomd_get_base(d
);
138 unsigned int val
, mask
= d
->mask
;
140 val
= readb(base
+ MASK
);
141 writeb(val
& ~mask
, base
+ MASK
);
144 static void iomd_irq_unmask(struct irq_data
*d
)
146 void __iomem
*base
= iomd_get_base(d
);
147 unsigned int val
, mask
= d
->mask
;
149 val
= readb(base
+ MASK
);
150 writeb(val
| mask
, base
+ MASK
);
153 static struct irq_chip iomd_chip_clr
= {
154 .irq_mask_ack
= iomd_irq_mask_ack
,
155 .irq_mask
= iomd_irq_mask
,
156 .irq_unmask
= iomd_irq_unmask
,
159 static struct irq_chip iomd_chip_noclr
= {
160 .irq_mask
= iomd_irq_mask
,
161 .irq_unmask
= iomd_irq_unmask
,
164 extern unsigned char rpc_default_fiq_start
, rpc_default_fiq_end
;
166 void __init
rpc_init_irq(void)
168 unsigned int irq
, clr
, set
;
170 iomd_writeb(0, IOMD_IRQMASKA
);
171 iomd_writeb(0, IOMD_IRQMASKB
);
172 iomd_writeb(0, IOMD_FIQMASK
);
173 iomd_writeb(0, IOMD_DMAMASK
);
175 set_fiq_handler(&rpc_default_fiq_start
,
176 &rpc_default_fiq_end
- &rpc_default_fiq_start
);
178 set_handle_irq(iomd_handle_irq
);
180 for (irq
= 0; irq
< NR_IRQS
; irq
++) {
184 if (irq
<= 6 || (irq
>= 9 && irq
<= 15))
187 if (irq
== 21 || (irq
>= 16 && irq
<= 19) ||
188 irq
== IRQ_KEYBOARDTX
)
193 irq_set_chip_and_handler(irq
, &iomd_chip_clr
,
195 irq_modify_status(irq
, clr
, set
);
196 iomd_set_base_mask(irq
, IOMD_BASE
+ IOMD_IRQSTATA
,
201 irq_set_chip_and_handler(irq
, &iomd_chip_noclr
,
203 irq_modify_status(irq
, clr
, set
);
204 iomd_set_base_mask(irq
, IOMD_BASE
+ IOMD_IRQSTATB
,
209 irq_set_chip_and_handler(irq
, &iomd_chip_noclr
,
211 irq_modify_status(irq
, clr
, set
);
212 iomd_set_base_mask(irq
, IOMD_BASE
+ IOMD_DMASTAT
,
217 irq_set_chip(irq
, &iomd_chip_noclr
);
218 irq_modify_status(irq
, clr
, set
);
219 iomd_set_base_mask(irq
, IOMD_BASE
+ IOMD_FIQSTAT
,