1#include <linux/init.h>
2#include <linux/list.h>
3#include <linux/io.h>
4
5#include <asm/mach/irq.h>
6#include <asm/hardware/iomd.h>
7#include <asm/irq.h>
8#include <asm/fiq.h>
9
10static void iomd_ack_irq_a(struct irq_data *d)
11{
12	unsigned int val, mask;
13
14	mask = 1 << d->irq;
15	val = iomd_readb(IOMD_IRQMASKA);
16	iomd_writeb(val & ~mask, IOMD_IRQMASKA);
17	iomd_writeb(mask, IOMD_IRQCLRA);
18}
19
20static void iomd_mask_irq_a(struct irq_data *d)
21{
22	unsigned int val, mask;
23
24	mask = 1 << d->irq;
25	val = iomd_readb(IOMD_IRQMASKA);
26	iomd_writeb(val & ~mask, IOMD_IRQMASKA);
27}
28
29static void iomd_unmask_irq_a(struct irq_data *d)
30{
31	unsigned int val, mask;
32
33	mask = 1 << d->irq;
34	val = iomd_readb(IOMD_IRQMASKA);
35	iomd_writeb(val | mask, IOMD_IRQMASKA);
36}
37
38static struct irq_chip iomd_a_chip = {
39	.irq_ack	= iomd_ack_irq_a,
40	.irq_mask	= iomd_mask_irq_a,
41	.irq_unmask	= iomd_unmask_irq_a,
42};
43
44static void iomd_mask_irq_b(struct irq_data *d)
45{
46	unsigned int val, mask;
47
48	mask = 1 << (d->irq & 7);
49	val = iomd_readb(IOMD_IRQMASKB);
50	iomd_writeb(val & ~mask, IOMD_IRQMASKB);
51}
52
53static void iomd_unmask_irq_b(struct irq_data *d)
54{
55	unsigned int val, mask;
56
57	mask = 1 << (d->irq & 7);
58	val = iomd_readb(IOMD_IRQMASKB);
59	iomd_writeb(val | mask, IOMD_IRQMASKB);
60}
61
62static struct irq_chip iomd_b_chip = {
63	.irq_ack	= iomd_mask_irq_b,
64	.irq_mask	= iomd_mask_irq_b,
65	.irq_unmask	= iomd_unmask_irq_b,
66};
67
68static void iomd_mask_irq_dma(struct irq_data *d)
69{
70	unsigned int val, mask;
71
72	mask = 1 << (d->irq & 7);
73	val = iomd_readb(IOMD_DMAMASK);
74	iomd_writeb(val & ~mask, IOMD_DMAMASK);
75}
76
77static void iomd_unmask_irq_dma(struct irq_data *d)
78{
79	unsigned int val, mask;
80
81	mask = 1 << (d->irq & 7);
82	val = iomd_readb(IOMD_DMAMASK);
83	iomd_writeb(val | mask, IOMD_DMAMASK);
84}
85
86static struct irq_chip iomd_dma_chip = {
87	.irq_ack	= iomd_mask_irq_dma,
88	.irq_mask	= iomd_mask_irq_dma,
89	.irq_unmask	= iomd_unmask_irq_dma,
90};
91
92static void iomd_mask_irq_fiq(struct irq_data *d)
93{
94	unsigned int val, mask;
95
96	mask = 1 << (d->irq & 7);
97	val = iomd_readb(IOMD_FIQMASK);
98	iomd_writeb(val & ~mask, IOMD_FIQMASK);
99}
100
101static void iomd_unmask_irq_fiq(struct irq_data *d)
102{
103	unsigned int val, mask;
104
105	mask = 1 << (d->irq & 7);
106	val = iomd_readb(IOMD_FIQMASK);
107	iomd_writeb(val | mask, IOMD_FIQMASK);
108}
109
110static struct irq_chip iomd_fiq_chip = {
111	.irq_ack	= iomd_mask_irq_fiq,
112	.irq_mask	= iomd_mask_irq_fiq,
113	.irq_unmask	= iomd_unmask_irq_fiq,
114};
115
116extern unsigned char rpc_default_fiq_start, rpc_default_fiq_end;
117
118void __init rpc_init_irq(void)
119{
120	unsigned int irq, clr, set = 0;
121
122	iomd_writeb(0, IOMD_IRQMASKA);
123	iomd_writeb(0, IOMD_IRQMASKB);
124	iomd_writeb(0, IOMD_FIQMASK);
125	iomd_writeb(0, IOMD_DMAMASK);
126
127	set_fiq_handler(&rpc_default_fiq_start,
128		&rpc_default_fiq_end - &rpc_default_fiq_start);
129
130	for (irq = 0; irq < NR_IRQS; irq++) {
131		clr = IRQ_NOREQUEST;
132
133		if (irq <= 6 || (irq >= 9 && irq <= 15))
134			clr |= IRQ_NOPROBE;
135
136		if (irq == 21 || (irq >= 16 && irq <= 19) ||
137		    irq == IRQ_KEYBOARDTX)
138			set |= IRQ_NOAUTOEN;
139
140		switch (irq) {
141		case 0 ... 7:
142			irq_set_chip_and_handler(irq, &iomd_a_chip,
143						 handle_level_irq);
144			irq_modify_status(irq, clr, set);
145			break;
146
147		case 8 ... 15:
148			irq_set_chip_and_handler(irq, &iomd_b_chip,
149						 handle_level_irq);
150			irq_modify_status(irq, clr, set);
151			break;
152
153		case 16 ... 21:
154			irq_set_chip_and_handler(irq, &iomd_dma_chip,
155						 handle_level_irq);
156			irq_modify_status(irq, clr, set);
157			break;
158
159		case 64 ... 71:
160			irq_set_chip(irq, &iomd_fiq_chip);
161			irq_modify_status(irq, clr, set);
162			break;
163		}
164	}
165
166	init_FIQ(FIQ_START);
167}
168
169