2 * Copyright (C) 2008 Ilya Yanok, Emcraft Systems
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
11 #include <linux/irq.h>
12 #include <linux/of_platform.h>
16 * The FPGA supports 9 interrupt sources, which can be routed to 3
17 * interrupt request lines of the MPIC. The line to be used can be
18 * specified through the third cell of FDT property "interrupts".
21 #define SOCRATES_FPGA_NUM_IRQS 9
23 #define FPGA_PIC_IRQCFG (0x0)
24 #define FPGA_PIC_IRQMASK(n) (0x4 + 0x4 * (n))
26 #define SOCRATES_FPGA_IRQ_MASK ((1 << SOCRATES_FPGA_NUM_IRQS) - 1)
28 struct socrates_fpga_irq_info
{
29 unsigned int irq_line
;
34 * Interrupt routing and type table
36 * IRQ_TYPE_NONE means the interrupt type is configurable,
37 * otherwise it's fixed to the specified value.
39 static struct socrates_fpga_irq_info fpga_irqs
[SOCRATES_FPGA_NUM_IRQS
] = {
40 [0] = {0, IRQ_TYPE_NONE
},
41 [1] = {0, IRQ_TYPE_LEVEL_HIGH
},
42 [2] = {0, IRQ_TYPE_LEVEL_LOW
},
43 [3] = {0, IRQ_TYPE_NONE
},
44 [4] = {0, IRQ_TYPE_NONE
},
45 [5] = {0, IRQ_TYPE_NONE
},
46 [6] = {0, IRQ_TYPE_NONE
},
47 [7] = {0, IRQ_TYPE_NONE
},
48 [8] = {0, IRQ_TYPE_LEVEL_HIGH
},
51 #define socrates_fpga_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq)
53 static DEFINE_SPINLOCK(socrates_fpga_pic_lock
);
55 static void __iomem
*socrates_fpga_pic_iobase
;
56 static struct irq_host
*socrates_fpga_pic_irq_host
;
57 static unsigned int socrates_fpga_irqs
[3];
59 static inline uint32_t socrates_fpga_pic_read(int reg
)
61 return in_be32(socrates_fpga_pic_iobase
+ reg
);
64 static inline void socrates_fpga_pic_write(int reg
, uint32_t val
)
66 out_be32(socrates_fpga_pic_iobase
+ reg
, val
);
69 static inline unsigned int socrates_fpga_pic_get_irq(unsigned int irq
)
75 /* Check irq line routed to the MPIC */
76 for (i
= 0; i
< 3; i
++) {
77 if (irq
== socrates_fpga_irqs
[i
])
83 spin_lock_irqsave(&socrates_fpga_pic_lock
, flags
);
84 cause
= socrates_fpga_pic_read(FPGA_PIC_IRQMASK(i
));
85 spin_unlock_irqrestore(&socrates_fpga_pic_lock
, flags
);
86 for (i
= SOCRATES_FPGA_NUM_IRQS
- 1; i
>= 0; i
--) {
87 if (cause
>> (i
+ 16))
90 return irq_linear_revmap(socrates_fpga_pic_irq_host
,
94 void socrates_fpga_pic_cascade(unsigned int irq
, struct irq_desc
*desc
)
96 unsigned int cascade_irq
;
99 * See if we actually have an interrupt, call generic handling code if
102 cascade_irq
= socrates_fpga_pic_get_irq(irq
);
104 if (cascade_irq
!= NO_IRQ
)
105 generic_handle_irq(cascade_irq
);
106 desc
->chip
->eoi(irq
);
110 static void socrates_fpga_pic_ack(unsigned int virq
)
113 unsigned int hwirq
, irq_line
;
116 hwirq
= socrates_fpga_irq_to_hw(virq
);
118 irq_line
= fpga_irqs
[hwirq
].irq_line
;
119 spin_lock_irqsave(&socrates_fpga_pic_lock
, flags
);
120 mask
= socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line
))
121 & SOCRATES_FPGA_IRQ_MASK
;
122 mask
|= (1 << (hwirq
+ 16));
123 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line
), mask
);
124 spin_unlock_irqrestore(&socrates_fpga_pic_lock
, flags
);
127 static void socrates_fpga_pic_mask(unsigned int virq
)
134 hwirq
= socrates_fpga_irq_to_hw(virq
);
136 irq_line
= fpga_irqs
[hwirq
].irq_line
;
137 spin_lock_irqsave(&socrates_fpga_pic_lock
, flags
);
138 mask
= socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line
))
139 & SOCRATES_FPGA_IRQ_MASK
;
140 mask
&= ~(1 << hwirq
);
141 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line
), mask
);
142 spin_unlock_irqrestore(&socrates_fpga_pic_lock
, flags
);
145 static void socrates_fpga_pic_mask_ack(unsigned int virq
)
152 hwirq
= socrates_fpga_irq_to_hw(virq
);
154 irq_line
= fpga_irqs
[hwirq
].irq_line
;
155 spin_lock_irqsave(&socrates_fpga_pic_lock
, flags
);
156 mask
= socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line
))
157 & SOCRATES_FPGA_IRQ_MASK
;
158 mask
&= ~(1 << hwirq
);
159 mask
|= (1 << (hwirq
+ 16));
160 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line
), mask
);
161 spin_unlock_irqrestore(&socrates_fpga_pic_lock
, flags
);
164 static void socrates_fpga_pic_unmask(unsigned int virq
)
171 hwirq
= socrates_fpga_irq_to_hw(virq
);
173 irq_line
= fpga_irqs
[hwirq
].irq_line
;
174 spin_lock_irqsave(&socrates_fpga_pic_lock
, flags
);
175 mask
= socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line
))
176 & SOCRATES_FPGA_IRQ_MASK
;
177 mask
|= (1 << hwirq
);
178 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line
), mask
);
179 spin_unlock_irqrestore(&socrates_fpga_pic_lock
, flags
);
182 static void socrates_fpga_pic_eoi(unsigned int virq
)
189 hwirq
= socrates_fpga_irq_to_hw(virq
);
191 irq_line
= fpga_irqs
[hwirq
].irq_line
;
192 spin_lock_irqsave(&socrates_fpga_pic_lock
, flags
);
193 mask
= socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line
))
194 & SOCRATES_FPGA_IRQ_MASK
;
195 mask
|= (1 << (hwirq
+ 16));
196 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line
), mask
);
197 spin_unlock_irqrestore(&socrates_fpga_pic_lock
, flags
);
200 static int socrates_fpga_pic_set_type(unsigned int virq
,
201 unsigned int flow_type
)
208 hwirq
= socrates_fpga_irq_to_hw(virq
);
210 if (fpga_irqs
[hwirq
].type
!= IRQ_TYPE_NONE
)
213 switch (flow_type
& IRQ_TYPE_SENSE_MASK
) {
214 case IRQ_TYPE_LEVEL_HIGH
:
217 case IRQ_TYPE_LEVEL_LOW
:
223 spin_lock_irqsave(&socrates_fpga_pic_lock
, flags
);
224 mask
= socrates_fpga_pic_read(FPGA_PIC_IRQCFG
);
226 mask
|= (1 << hwirq
);
228 mask
&= ~(1 << hwirq
);
229 socrates_fpga_pic_write(FPGA_PIC_IRQCFG
, mask
);
230 spin_unlock_irqrestore(&socrates_fpga_pic_lock
, flags
);
234 static struct irq_chip socrates_fpga_pic_chip
= {
235 .typename
= " FPGA-PIC ",
236 .ack
= socrates_fpga_pic_ack
,
237 .mask
= socrates_fpga_pic_mask
,
238 .mask_ack
= socrates_fpga_pic_mask_ack
,
239 .unmask
= socrates_fpga_pic_unmask
,
240 .eoi
= socrates_fpga_pic_eoi
,
241 .set_type
= socrates_fpga_pic_set_type
,
244 static int socrates_fpga_pic_host_map(struct irq_host
*h
, unsigned int virq
,
245 irq_hw_number_t hwirq
)
247 /* All interrupts are LEVEL sensitive */
248 get_irq_desc(virq
)->status
|= IRQ_LEVEL
;
249 set_irq_chip_and_handler(virq
, &socrates_fpga_pic_chip
,
255 static int socrates_fpga_pic_host_xlate(struct irq_host
*h
,
256 struct device_node
*ct
, u32
*intspec
, unsigned int intsize
,
257 irq_hw_number_t
*out_hwirq
, unsigned int *out_flags
)
259 struct socrates_fpga_irq_info
*fpga_irq
= &fpga_irqs
[intspec
[0]];
261 *out_hwirq
= intspec
[0];
262 if (fpga_irq
->type
== IRQ_TYPE_NONE
) {
263 /* type is configurable */
264 if (intspec
[1] != IRQ_TYPE_LEVEL_LOW
&&
265 intspec
[1] != IRQ_TYPE_LEVEL_HIGH
) {
266 pr_warning("FPGA PIC: invalid irq type, "
267 "setting default active low\n");
268 *out_flags
= IRQ_TYPE_LEVEL_LOW
;
270 *out_flags
= intspec
[1];
274 *out_flags
= fpga_irq
->type
;
277 /* Use specified interrupt routing */
279 fpga_irq
->irq_line
= intspec
[2];
281 pr_warning("FPGA PIC: invalid irq routing\n");
286 static struct irq_host_ops socrates_fpga_pic_host_ops
= {
287 .map
= socrates_fpga_pic_host_map
,
288 .xlate
= socrates_fpga_pic_host_xlate
,
291 void socrates_fpga_pic_init(struct device_node
*pic
)
296 /* Setup an irq_host structure */
297 socrates_fpga_pic_irq_host
= irq_alloc_host(pic
, IRQ_HOST_MAP_LINEAR
,
298 SOCRATES_FPGA_NUM_IRQS
, &socrates_fpga_pic_host_ops
,
299 SOCRATES_FPGA_NUM_IRQS
);
300 if (socrates_fpga_pic_irq_host
== NULL
) {
301 pr_err("FPGA PIC: Unable to allocate host\n");
305 for (i
= 0; i
< 3; i
++) {
306 socrates_fpga_irqs
[i
] = irq_of_parse_and_map(pic
, i
);
307 if (socrates_fpga_irqs
[i
] == NO_IRQ
) {
308 pr_warning("FPGA PIC: can't get irq%d.\n", i
);
311 set_irq_chained_handler(socrates_fpga_irqs
[i
],
312 socrates_fpga_pic_cascade
);
315 socrates_fpga_pic_iobase
= of_iomap(pic
, 0);
317 spin_lock_irqsave(&socrates_fpga_pic_lock
, flags
);
318 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(0),
319 SOCRATES_FPGA_IRQ_MASK
<< 16);
320 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(1),
321 SOCRATES_FPGA_IRQ_MASK
<< 16);
322 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(2),
323 SOCRATES_FPGA_IRQ_MASK
<< 16);
324 spin_unlock_irqrestore(&socrates_fpga_pic_lock
, flags
);
326 pr_info("FPGA PIC: Setting up Socrates FPGA PIC\n");