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>
11 #include "socrates_fpga_pic.h"
14 * The FPGA supports 9 interrupt sources, which can be routed to 3
15 * interrupt request lines of the MPIC. The line to be used can be
16 * specified through the third cell of FDT property "interrupts".
19 #define SOCRATES_FPGA_NUM_IRQS 9
21 #define FPGA_PIC_IRQCFG (0x0)
22 #define FPGA_PIC_IRQMASK(n) (0x4 + 0x4 * (n))
24 #define SOCRATES_FPGA_IRQ_MASK ((1 << SOCRATES_FPGA_NUM_IRQS) - 1)
26 struct socrates_fpga_irq_info {
27 unsigned int irq_line;
32 * Interrupt routing and type table
34 * IRQ_TYPE_NONE means the interrupt type is configurable,
35 * otherwise it's fixed to the specified value.
37 static struct socrates_fpga_irq_info fpga_irqs[SOCRATES_FPGA_NUM_IRQS] = {
38 [0] = {0, IRQ_TYPE_NONE},
39 [1] = {0, IRQ_TYPE_LEVEL_HIGH},
40 [2] = {0, IRQ_TYPE_LEVEL_LOW},
41 [3] = {0, IRQ_TYPE_NONE},
42 [4] = {0, IRQ_TYPE_NONE},
43 [5] = {0, IRQ_TYPE_NONE},
44 [6] = {0, IRQ_TYPE_NONE},
45 [7] = {0, IRQ_TYPE_NONE},
46 [8] = {0, IRQ_TYPE_LEVEL_HIGH},
49 static DEFINE_RAW_SPINLOCK(socrates_fpga_pic_lock);
51 static void __iomem *socrates_fpga_pic_iobase;
52 static struct irq_domain *socrates_fpga_pic_irq_host;
53 static unsigned int socrates_fpga_irqs[3];
55 static inline uint32_t socrates_fpga_pic_read(int reg)
57 return in_be32(socrates_fpga_pic_iobase + reg);
60 static inline void socrates_fpga_pic_write(int reg, uint32_t val)
62 out_be32(socrates_fpga_pic_iobase + reg, val);
65 static inline unsigned int socrates_fpga_pic_get_irq(unsigned int irq)
71 /* Check irq line routed to the MPIC */
72 for (i = 0; i < 3; i++) {
73 if (irq == socrates_fpga_irqs[i])
79 raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
80 cause = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(i));
81 raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
82 for (i = SOCRATES_FPGA_NUM_IRQS - 1; i >= 0; i--) {
83 if (cause >> (i + 16))
86 return irq_linear_revmap(socrates_fpga_pic_irq_host,
90 static void socrates_fpga_pic_cascade(struct irq_desc *desc)
92 struct irq_chip *chip = irq_desc_get_chip(desc);
93 unsigned int irq = irq_desc_get_irq(desc);
94 unsigned int cascade_irq;
97 * See if we actually have an interrupt, call generic handling code if
100 cascade_irq = socrates_fpga_pic_get_irq(irq);
103 generic_handle_irq(cascade_irq);
104 chip->irq_eoi(&desc->irq_data);
107 static void socrates_fpga_pic_ack(struct irq_data *d)
110 unsigned int irq_line, hwirq = irqd_to_hwirq(d);
113 irq_line = fpga_irqs[hwirq].irq_line;
114 raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
115 mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
116 & SOCRATES_FPGA_IRQ_MASK;
117 mask |= (1 << (hwirq + 16));
118 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
119 raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
122 static void socrates_fpga_pic_mask(struct irq_data *d)
125 unsigned int hwirq = irqd_to_hwirq(d);
129 irq_line = fpga_irqs[hwirq].irq_line;
130 raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
131 mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
132 & SOCRATES_FPGA_IRQ_MASK;
133 mask &= ~(1 << hwirq);
134 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
135 raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
138 static void socrates_fpga_pic_mask_ack(struct irq_data *d)
141 unsigned int hwirq = irqd_to_hwirq(d);
145 irq_line = fpga_irqs[hwirq].irq_line;
146 raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
147 mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
148 & SOCRATES_FPGA_IRQ_MASK;
149 mask &= ~(1 << hwirq);
150 mask |= (1 << (hwirq + 16));
151 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
152 raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
155 static void socrates_fpga_pic_unmask(struct irq_data *d)
158 unsigned int hwirq = irqd_to_hwirq(d);
162 irq_line = fpga_irqs[hwirq].irq_line;
163 raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
164 mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
165 & SOCRATES_FPGA_IRQ_MASK;
166 mask |= (1 << hwirq);
167 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
168 raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
171 static void socrates_fpga_pic_eoi(struct irq_data *d)
174 unsigned int hwirq = irqd_to_hwirq(d);
178 irq_line = fpga_irqs[hwirq].irq_line;
179 raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
180 mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))
181 & SOCRATES_FPGA_IRQ_MASK;
182 mask |= (1 << (hwirq + 16));
183 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(irq_line), mask);
184 raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
187 static int socrates_fpga_pic_set_type(struct irq_data *d,
188 unsigned int flow_type)
191 unsigned int hwirq = irqd_to_hwirq(d);
195 if (fpga_irqs[hwirq].type != IRQ_TYPE_NONE)
198 switch (flow_type & IRQ_TYPE_SENSE_MASK) {
199 case IRQ_TYPE_LEVEL_HIGH:
202 case IRQ_TYPE_LEVEL_LOW:
208 raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
209 mask = socrates_fpga_pic_read(FPGA_PIC_IRQCFG);
211 mask |= (1 << hwirq);
213 mask &= ~(1 << hwirq);
214 socrates_fpga_pic_write(FPGA_PIC_IRQCFG, mask);
215 raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
219 static struct irq_chip socrates_fpga_pic_chip = {
221 .irq_ack = socrates_fpga_pic_ack,
222 .irq_mask = socrates_fpga_pic_mask,
223 .irq_mask_ack = socrates_fpga_pic_mask_ack,
224 .irq_unmask = socrates_fpga_pic_unmask,
225 .irq_eoi = socrates_fpga_pic_eoi,
226 .irq_set_type = socrates_fpga_pic_set_type,
229 static int socrates_fpga_pic_host_map(struct irq_domain *h, unsigned int virq,
230 irq_hw_number_t hwirq)
232 /* All interrupts are LEVEL sensitive */
233 irq_set_status_flags(virq, IRQ_LEVEL);
234 irq_set_chip_and_handler(virq, &socrates_fpga_pic_chip,
240 static int socrates_fpga_pic_host_xlate(struct irq_domain *h,
241 struct device_node *ct, const u32 *intspec, unsigned int intsize,
242 irq_hw_number_t *out_hwirq, unsigned int *out_flags)
244 struct socrates_fpga_irq_info *fpga_irq = &fpga_irqs[intspec[0]];
246 *out_hwirq = intspec[0];
247 if (fpga_irq->type == IRQ_TYPE_NONE) {
248 /* type is configurable */
249 if (intspec[1] != IRQ_TYPE_LEVEL_LOW &&
250 intspec[1] != IRQ_TYPE_LEVEL_HIGH) {
251 pr_warn("FPGA PIC: invalid irq type, setting default active low\n");
252 *out_flags = IRQ_TYPE_LEVEL_LOW;
254 *out_flags = intspec[1];
258 *out_flags = fpga_irq->type;
261 /* Use specified interrupt routing */
263 fpga_irq->irq_line = intspec[2];
265 pr_warn("FPGA PIC: invalid irq routing\n");
270 static const struct irq_domain_ops socrates_fpga_pic_host_ops = {
271 .map = socrates_fpga_pic_host_map,
272 .xlate = socrates_fpga_pic_host_xlate,
275 void __init socrates_fpga_pic_init(struct device_node *pic)
280 /* Setup an irq_domain structure */
281 socrates_fpga_pic_irq_host = irq_domain_add_linear(pic,
282 SOCRATES_FPGA_NUM_IRQS, &socrates_fpga_pic_host_ops, NULL);
283 if (socrates_fpga_pic_irq_host == NULL) {
284 pr_err("FPGA PIC: Unable to allocate host\n");
288 for (i = 0; i < 3; i++) {
289 socrates_fpga_irqs[i] = irq_of_parse_and_map(pic, i);
290 if (!socrates_fpga_irqs[i]) {
291 pr_warn("FPGA PIC: can't get irq%d\n", i);
294 irq_set_chained_handler(socrates_fpga_irqs[i],
295 socrates_fpga_pic_cascade);
298 socrates_fpga_pic_iobase = of_iomap(pic, 0);
300 raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
301 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(0),
302 SOCRATES_FPGA_IRQ_MASK << 16);
303 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(1),
304 SOCRATES_FPGA_IRQ_MASK << 16);
305 socrates_fpga_pic_write(FPGA_PIC_IRQMASK(2),
306 SOCRATES_FPGA_IRQ_MASK << 16);
307 raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
309 pr_info("FPGA PIC: Setting up Socrates FPGA PIC\n");