1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2008 Ilya Yanok, Emcraft Systems
7 #include <linux/of_address.h>
8 #include <linux/of_irq.h>
9 #include <linux/of_platform.h>
13 * The FPGA supports 9 interrupt sources, which can be routed to 3
14 * interrupt request lines of the MPIC. The line to be used can be
15 * specified through the third cell of FDT property "interrupts".
18 #define SOCRATES_FPGA_NUM_IRQS 9
20 #define FPGA_PIC_IRQCFG (0x0)
21 #define FPGA_PIC_IRQMASK(n) (0x4 + 0x4 * (n))
23 #define SOCRATES_FPGA_IRQ_MASK ((1 << SOCRATES_FPGA_NUM_IRQS) - 1)
25 struct socrates_fpga_irq_info
{
26 unsigned int irq_line
;
31 * Interrupt routing and type table
33 * IRQ_TYPE_NONE means the interrupt type is configurable,
34 * otherwise it's fixed to the specified value.
36 static struct socrates_fpga_irq_info fpga_irqs
[SOCRATES_FPGA_NUM_IRQS
] = {
37 [0] = {0, IRQ_TYPE_NONE
},
38 [1] = {0, IRQ_TYPE_LEVEL_HIGH
},
39 [2] = {0, IRQ_TYPE_LEVEL_LOW
},
40 [3] = {0, IRQ_TYPE_NONE
},
41 [4] = {0, IRQ_TYPE_NONE
},
42 [5] = {0, IRQ_TYPE_NONE
},
43 [6] = {0, IRQ_TYPE_NONE
},
44 [7] = {0, IRQ_TYPE_NONE
},
45 [8] = {0, IRQ_TYPE_LEVEL_HIGH
},
48 static DEFINE_RAW_SPINLOCK(socrates_fpga_pic_lock
);
50 static void __iomem
*socrates_fpga_pic_iobase
;
51 static struct irq_domain
*socrates_fpga_pic_irq_host
;
52 static unsigned int socrates_fpga_irqs
[3];
54 static inline uint32_t socrates_fpga_pic_read(int reg
)
56 return in_be32(socrates_fpga_pic_iobase
+ reg
);
59 static inline void socrates_fpga_pic_write(int reg
, uint32_t val
)
61 out_be32(socrates_fpga_pic_iobase
+ reg
, val
);
64 static inline unsigned int socrates_fpga_pic_get_irq(unsigned int irq
)
70 /* Check irq line routed to the MPIC */
71 for (i
= 0; i
< 3; i
++) {
72 if (irq
== socrates_fpga_irqs
[i
])
78 raw_spin_lock_irqsave(&socrates_fpga_pic_lock
, flags
);
79 cause
= socrates_fpga_pic_read(FPGA_PIC_IRQMASK(i
));
80 raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock
, flags
);
81 for (i
= SOCRATES_FPGA_NUM_IRQS
- 1; i
>= 0; i
--) {
82 if (cause
>> (i
+ 16))
85 return irq_linear_revmap(socrates_fpga_pic_irq_host
,
89 static void socrates_fpga_pic_cascade(struct irq_desc
*desc
)
91 struct irq_chip
*chip
= irq_desc_get_chip(desc
);
92 unsigned int irq
= irq_desc_get_irq(desc
);
93 unsigned int cascade_irq
;
96 * See if we actually have an interrupt, call generic handling code if
99 cascade_irq
= socrates_fpga_pic_get_irq(irq
);
102 generic_handle_irq(cascade_irq
);
103 chip
->irq_eoi(&desc
->irq_data
);
106 static void socrates_fpga_pic_ack(struct irq_data
*d
)
109 unsigned int irq_line
, hwirq
= irqd_to_hwirq(d
);
112 irq_line
= fpga_irqs
[hwirq
].irq_line
;
113 raw_spin_lock_irqsave(&socrates_fpga_pic_lock
, flags
);
114 mask
= socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line
))
115 & SOCRATES_FPGA_IRQ_MASK
;
116 mask
|= (1 << (hwirq
+ 16));
117 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line
), mask
);
118 raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock
, flags
);
121 static void socrates_fpga_pic_mask(struct irq_data
*d
)
124 unsigned int hwirq
= irqd_to_hwirq(d
);
128 irq_line
= fpga_irqs
[hwirq
].irq_line
;
129 raw_spin_lock_irqsave(&socrates_fpga_pic_lock
, flags
);
130 mask
= socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line
))
131 & SOCRATES_FPGA_IRQ_MASK
;
132 mask
&= ~(1 << hwirq
);
133 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line
), mask
);
134 raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock
, flags
);
137 static void socrates_fpga_pic_mask_ack(struct irq_data
*d
)
140 unsigned int hwirq
= irqd_to_hwirq(d
);
144 irq_line
= fpga_irqs
[hwirq
].irq_line
;
145 raw_spin_lock_irqsave(&socrates_fpga_pic_lock
, flags
);
146 mask
= socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line
))
147 & SOCRATES_FPGA_IRQ_MASK
;
148 mask
&= ~(1 << hwirq
);
149 mask
|= (1 << (hwirq
+ 16));
150 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line
), mask
);
151 raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock
, flags
);
154 static void socrates_fpga_pic_unmask(struct irq_data
*d
)
157 unsigned int hwirq
= irqd_to_hwirq(d
);
161 irq_line
= fpga_irqs
[hwirq
].irq_line
;
162 raw_spin_lock_irqsave(&socrates_fpga_pic_lock
, flags
);
163 mask
= socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line
))
164 & SOCRATES_FPGA_IRQ_MASK
;
165 mask
|= (1 << hwirq
);
166 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line
), mask
);
167 raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock
, flags
);
170 static void socrates_fpga_pic_eoi(struct irq_data
*d
)
173 unsigned int hwirq
= irqd_to_hwirq(d
);
177 irq_line
= fpga_irqs
[hwirq
].irq_line
;
178 raw_spin_lock_irqsave(&socrates_fpga_pic_lock
, flags
);
179 mask
= socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line
))
180 & SOCRATES_FPGA_IRQ_MASK
;
181 mask
|= (1 << (hwirq
+ 16));
182 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line
), mask
);
183 raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock
, flags
);
186 static int socrates_fpga_pic_set_type(struct irq_data
*d
,
187 unsigned int flow_type
)
190 unsigned int hwirq
= irqd_to_hwirq(d
);
194 if (fpga_irqs
[hwirq
].type
!= IRQ_TYPE_NONE
)
197 switch (flow_type
& IRQ_TYPE_SENSE_MASK
) {
198 case IRQ_TYPE_LEVEL_HIGH
:
201 case IRQ_TYPE_LEVEL_LOW
:
207 raw_spin_lock_irqsave(&socrates_fpga_pic_lock
, flags
);
208 mask
= socrates_fpga_pic_read(FPGA_PIC_IRQCFG
);
210 mask
|= (1 << hwirq
);
212 mask
&= ~(1 << hwirq
);
213 socrates_fpga_pic_write(FPGA_PIC_IRQCFG
, mask
);
214 raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock
, flags
);
218 static struct irq_chip socrates_fpga_pic_chip
= {
220 .irq_ack
= socrates_fpga_pic_ack
,
221 .irq_mask
= socrates_fpga_pic_mask
,
222 .irq_mask_ack
= socrates_fpga_pic_mask_ack
,
223 .irq_unmask
= socrates_fpga_pic_unmask
,
224 .irq_eoi
= socrates_fpga_pic_eoi
,
225 .irq_set_type
= socrates_fpga_pic_set_type
,
228 static int socrates_fpga_pic_host_map(struct irq_domain
*h
, unsigned int virq
,
229 irq_hw_number_t hwirq
)
231 /* All interrupts are LEVEL sensitive */
232 irq_set_status_flags(virq
, IRQ_LEVEL
);
233 irq_set_chip_and_handler(virq
, &socrates_fpga_pic_chip
,
239 static int socrates_fpga_pic_host_xlate(struct irq_domain
*h
,
240 struct device_node
*ct
, const u32
*intspec
, unsigned int intsize
,
241 irq_hw_number_t
*out_hwirq
, unsigned int *out_flags
)
243 struct socrates_fpga_irq_info
*fpga_irq
= &fpga_irqs
[intspec
[0]];
245 *out_hwirq
= intspec
[0];
246 if (fpga_irq
->type
== IRQ_TYPE_NONE
) {
247 /* type is configurable */
248 if (intspec
[1] != IRQ_TYPE_LEVEL_LOW
&&
249 intspec
[1] != IRQ_TYPE_LEVEL_HIGH
) {
250 pr_warn("FPGA PIC: invalid irq type, setting default active low\n");
251 *out_flags
= IRQ_TYPE_LEVEL_LOW
;
253 *out_flags
= intspec
[1];
257 *out_flags
= fpga_irq
->type
;
260 /* Use specified interrupt routing */
262 fpga_irq
->irq_line
= intspec
[2];
264 pr_warn("FPGA PIC: invalid irq routing\n");
269 static const struct irq_domain_ops socrates_fpga_pic_host_ops
= {
270 .map
= socrates_fpga_pic_host_map
,
271 .xlate
= socrates_fpga_pic_host_xlate
,
274 void socrates_fpga_pic_init(struct device_node
*pic
)
279 /* Setup an irq_domain structure */
280 socrates_fpga_pic_irq_host
= irq_domain_add_linear(pic
,
281 SOCRATES_FPGA_NUM_IRQS
, &socrates_fpga_pic_host_ops
, NULL
);
282 if (socrates_fpga_pic_irq_host
== NULL
) {
283 pr_err("FPGA PIC: Unable to allocate host\n");
287 for (i
= 0; i
< 3; i
++) {
288 socrates_fpga_irqs
[i
] = irq_of_parse_and_map(pic
, i
);
289 if (!socrates_fpga_irqs
[i
]) {
290 pr_warn("FPGA PIC: can't get irq%d\n", i
);
293 irq_set_chained_handler(socrates_fpga_irqs
[i
],
294 socrates_fpga_pic_cascade
);
297 socrates_fpga_pic_iobase
= of_iomap(pic
, 0);
299 raw_spin_lock_irqsave(&socrates_fpga_pic_lock
, flags
);
300 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(0),
301 SOCRATES_FPGA_IRQ_MASK
<< 16);
302 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(1),
303 SOCRATES_FPGA_IRQ_MASK
<< 16);
304 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(2),
305 SOCRATES_FPGA_IRQ_MASK
<< 16);
306 raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock
, flags
);
308 pr_info("FPGA PIC: Setting up Socrates FPGA PIC\n");