1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
22389d501SLinus Walleij /*
32389d501SLinus Walleij  *  Support for Versatile FPGA-based IRQ controllers
42389d501SLinus Walleij  */
52389d501SLinus Walleij #include <linux/bitops.h>
62389d501SLinus Walleij #include <linux/irq.h>
72389d501SLinus Walleij #include <linux/io.h>
841a83e06SJoel Porquet #include <linux/irqchip.h>
9486562daSSungbo Eo #include <linux/irqchip/chained_irq.h>
102389d501SLinus Walleij #include <linux/irqdomain.h>
112389d501SLinus Walleij #include <linux/module.h>
122389d501SLinus Walleij #include <linux/of.h>
132389d501SLinus Walleij #include <linux/of_address.h>
14bdd272cbSLinus Walleij #include <linux/of_irq.h>
15*3fb212a0SMarc Zyngier #include <linux/seq_file.h>
162389d501SLinus Walleij 
172389d501SLinus Walleij #include <asm/exception.h>
182389d501SLinus Walleij #include <asm/mach/irq.h>
192389d501SLinus Walleij 
202389d501SLinus Walleij #define IRQ_STATUS		0x00
212389d501SLinus Walleij #define IRQ_RAW_STATUS		0x04
222389d501SLinus Walleij #define IRQ_ENABLE_SET		0x08
232389d501SLinus Walleij #define IRQ_ENABLE_CLEAR	0x0c
242389d501SLinus Walleij #define INT_SOFT_SET		0x10
252389d501SLinus Walleij #define INT_SOFT_CLEAR		0x14
262389d501SLinus Walleij #define FIQ_STATUS		0x20
272389d501SLinus Walleij #define FIQ_RAW_STATUS		0x24
282389d501SLinus Walleij #define FIQ_ENABLE		0x28
292389d501SLinus Walleij #define FIQ_ENABLE_SET		0x28
302389d501SLinus Walleij #define FIQ_ENABLE_CLEAR	0x2C
312389d501SLinus Walleij 
3259318461SRob Herring #define PIC_ENABLES             0x20	/* set interrupt pass through bits */
3359318461SRob Herring 
342389d501SLinus Walleij /**
352389d501SLinus Walleij  * struct fpga_irq_data - irq data container for the FPGA IRQ controller
362389d501SLinus Walleij  * @base: memory offset in virtual memory
372389d501SLinus Walleij  * @domain: IRQ domain for this instance
382389d501SLinus Walleij  * @valid: mask for valid IRQs on this controller
392389d501SLinus Walleij  * @used_irqs: number of active IRQs on this controller
402389d501SLinus Walleij  */
412389d501SLinus Walleij struct fpga_irq_data {
422389d501SLinus Walleij 	void __iomem *base;
432389d501SLinus Walleij 	u32 valid;
442389d501SLinus Walleij 	struct irq_domain *domain;
452389d501SLinus Walleij 	u8 used_irqs;
462389d501SLinus Walleij };
472389d501SLinus Walleij 
482389d501SLinus Walleij /* we cannot allocate memory when the controllers are initially registered */
492389d501SLinus Walleij static struct fpga_irq_data fpga_irq_devices[CONFIG_VERSATILE_FPGA_IRQ_NR];
502389d501SLinus Walleij static int fpga_irq_id;
512389d501SLinus Walleij 
fpga_irq_mask(struct irq_data * d)522389d501SLinus Walleij static void fpga_irq_mask(struct irq_data *d)
532389d501SLinus Walleij {
542389d501SLinus Walleij 	struct fpga_irq_data *f = irq_data_get_irq_chip_data(d);
552389d501SLinus Walleij 	u32 mask = 1 << d->hwirq;
562389d501SLinus Walleij 
572389d501SLinus Walleij 	writel(mask, f->base + IRQ_ENABLE_CLEAR);
582389d501SLinus Walleij }
592389d501SLinus Walleij 
fpga_irq_unmask(struct irq_data * d)602389d501SLinus Walleij static void fpga_irq_unmask(struct irq_data *d)
612389d501SLinus Walleij {
622389d501SLinus Walleij 	struct fpga_irq_data *f = irq_data_get_irq_chip_data(d);
632389d501SLinus Walleij 	u32 mask = 1 << d->hwirq;
642389d501SLinus Walleij 
652389d501SLinus Walleij 	writel(mask, f->base + IRQ_ENABLE_SET);
662389d501SLinus Walleij }
672389d501SLinus Walleij 
fpga_irq_print_chip(struct irq_data * d,struct seq_file * p)68*3fb212a0SMarc Zyngier static void fpga_irq_print_chip(struct irq_data *d, struct seq_file *p)
69*3fb212a0SMarc Zyngier {
70*3fb212a0SMarc Zyngier 	struct fpga_irq_data *f = irq_data_get_irq_chip_data(d);
71*3fb212a0SMarc Zyngier 
72*3fb212a0SMarc Zyngier 	seq_printf(p, irq_domain_get_of_node(f->domain)->name);
73*3fb212a0SMarc Zyngier }
74*3fb212a0SMarc Zyngier 
75*3fb212a0SMarc Zyngier static const struct irq_chip fpga_chip = {
76*3fb212a0SMarc Zyngier 	.irq_ack	= fpga_irq_mask,
77*3fb212a0SMarc Zyngier 	.irq_mask	= fpga_irq_mask,
78*3fb212a0SMarc Zyngier 	.irq_unmask	= fpga_irq_unmask,
79*3fb212a0SMarc Zyngier 	.irq_print_chip	= fpga_irq_print_chip,
80*3fb212a0SMarc Zyngier };
81*3fb212a0SMarc Zyngier 
fpga_irq_handle(struct irq_desc * desc)82bd0b9ac4SThomas Gleixner static void fpga_irq_handle(struct irq_desc *desc)
832389d501SLinus Walleij {
84486562daSSungbo Eo 	struct irq_chip *chip = irq_desc_get_chip(desc);
852389d501SLinus Walleij 	struct fpga_irq_data *f = irq_desc_get_handler_data(desc);
86486562daSSungbo Eo 	u32 status;
872389d501SLinus Walleij 
88486562daSSungbo Eo 	chained_irq_enter(chip, desc);
89486562daSSungbo Eo 
90486562daSSungbo Eo 	status = readl(f->base + IRQ_STATUS);
912389d501SLinus Walleij 	if (status == 0) {
92bd0b9ac4SThomas Gleixner 		do_bad_IRQ(desc);
93486562daSSungbo Eo 		goto out;
942389d501SLinus Walleij 	}
952389d501SLinus Walleij 
962389d501SLinus Walleij 	do {
97bd0b9ac4SThomas Gleixner 		unsigned int irq = ffs(status) - 1;
98bd0b9ac4SThomas Gleixner 
992389d501SLinus Walleij 		status &= ~(1 << irq);
100046a6ee2SMarc Zyngier 		generic_handle_domain_irq(f->domain, irq);
1012389d501SLinus Walleij 	} while (status);
102486562daSSungbo Eo 
103486562daSSungbo Eo out:
104486562daSSungbo Eo 	chained_irq_exit(chip, desc);
1052389d501SLinus Walleij }
1062389d501SLinus Walleij 
1072389d501SLinus Walleij /*
1082389d501SLinus Walleij  * Handle each interrupt in a single FPGA IRQ controller.  Returns non-zero
1092389d501SLinus Walleij  * if we've handled at least one interrupt.  This does a single read of the
1102389d501SLinus Walleij  * status register and handles all interrupts in order from LSB first.
1112389d501SLinus Walleij  */
handle_one_fpga(struct fpga_irq_data * f,struct pt_regs * regs)1122389d501SLinus Walleij static int handle_one_fpga(struct fpga_irq_data *f, struct pt_regs *regs)
1132389d501SLinus Walleij {
1142389d501SLinus Walleij 	int handled = 0;
1152389d501SLinus Walleij 	int irq;
1162389d501SLinus Walleij 	u32 status;
1172389d501SLinus Walleij 
1182389d501SLinus Walleij 	while ((status  = readl(f->base + IRQ_STATUS))) {
1192389d501SLinus Walleij 		irq = ffs(status) - 1;
1200953fb26SMark Rutland 		generic_handle_domain_irq(f->domain, irq);
1212389d501SLinus Walleij 		handled = 1;
1222389d501SLinus Walleij 	}
1232389d501SLinus Walleij 
1242389d501SLinus Walleij 	return handled;
1252389d501SLinus Walleij }
1262389d501SLinus Walleij 
1272389d501SLinus Walleij /*
1282389d501SLinus Walleij  * Keep iterating over all registered FPGA IRQ controllers until there are
1292389d501SLinus Walleij  * no pending interrupts.
1302389d501SLinus Walleij  */
fpga_handle_irq(struct pt_regs * regs)131*3fb212a0SMarc Zyngier static asmlinkage void __exception_irq_entry fpga_handle_irq(struct pt_regs *regs)
1322389d501SLinus Walleij {
1332389d501SLinus Walleij 	int i, handled;
1342389d501SLinus Walleij 
1352389d501SLinus Walleij 	do {
1362389d501SLinus Walleij 		for (i = 0, handled = 0; i < fpga_irq_id; ++i)
1372389d501SLinus Walleij 			handled |= handle_one_fpga(&fpga_irq_devices[i], regs);
1382389d501SLinus Walleij 	} while (handled);
1392389d501SLinus Walleij }
1402389d501SLinus Walleij 
fpga_irqdomain_map(struct irq_domain * d,unsigned int irq,irq_hw_number_t hwirq)1412389d501SLinus Walleij static int fpga_irqdomain_map(struct irq_domain *d, unsigned int irq,
1422389d501SLinus Walleij 		irq_hw_number_t hwirq)
1432389d501SLinus Walleij {
1442389d501SLinus Walleij 	struct fpga_irq_data *f = d->host_data;
1452389d501SLinus Walleij 
1462389d501SLinus Walleij 	/* Skip invalid IRQs, only register handlers for the real ones */
1472389d501SLinus Walleij 	if (!(f->valid & BIT(hwirq)))
148d94ea3f6SGrant Likely 		return -EPERM;
1492389d501SLinus Walleij 	irq_set_chip_data(irq, f);
150*3fb212a0SMarc Zyngier 	irq_set_chip_and_handler(irq, &fpga_chip, handle_level_irq);
151d17cab44SRob Herring 	irq_set_probe(irq);
1522389d501SLinus Walleij 	return 0;
1532389d501SLinus Walleij }
1542389d501SLinus Walleij 
15596009736SKrzysztof Kozlowski static const struct irq_domain_ops fpga_irqdomain_ops = {
1562389d501SLinus Walleij 	.map = fpga_irqdomain_map,
1572389d501SLinus Walleij 	.xlate = irq_domain_xlate_onetwocell,
1582389d501SLinus Walleij };
1592389d501SLinus Walleij 
fpga_irq_init(void __iomem * base,int parent_irq,u32 valid,struct device_node * node)160*3fb212a0SMarc Zyngier static void __init fpga_irq_init(void __iomem *base, int parent_irq,
161*3fb212a0SMarc Zyngier 				 u32 valid, struct device_node *node)
1622389d501SLinus Walleij {
1632389d501SLinus Walleij 	struct fpga_irq_data *f;
1642389d501SLinus Walleij 	int i;
1652389d501SLinus Walleij 
1662389d501SLinus Walleij 	if (fpga_irq_id >= ARRAY_SIZE(fpga_irq_devices)) {
167e6423f8bSPaul Bolle 		pr_err("%s: too few FPGA IRQ controllers, increase CONFIG_VERSATILE_FPGA_IRQ_NR\n", __func__);
1682389d501SLinus Walleij 		return;
1692389d501SLinus Walleij 	}
1702389d501SLinus Walleij 	f = &fpga_irq_devices[fpga_irq_id];
1712389d501SLinus Walleij 	f->base = base;
1722389d501SLinus Walleij 	f->valid = valid;
1732389d501SLinus Walleij 
1742389d501SLinus Walleij 	if (parent_irq != -1) {
175fcd3c5beSThomas Gleixner 		irq_set_chained_handler_and_data(parent_irq, fpga_irq_handle,
176fcd3c5beSThomas Gleixner 						 f);
1772389d501SLinus Walleij 	}
1782389d501SLinus Walleij 
179*3fb212a0SMarc Zyngier 	f->domain = irq_domain_add_linear(node, fls(valid),
1802389d501SLinus Walleij 					  &fpga_irqdomain_ops, f);
1812389d501SLinus Walleij 
1822389d501SLinus Walleij 	/* This will allocate all valid descriptors in the linear case */
1832389d501SLinus Walleij 	for (i = 0; i < fls(valid); i++)
1842389d501SLinus Walleij 		if (valid & BIT(i)) {
185*3fb212a0SMarc Zyngier 			/* Is this still required? */
1862389d501SLinus Walleij 			irq_create_mapping(f->domain, i);
1872389d501SLinus Walleij 			f->used_irqs++;
1882389d501SLinus Walleij 		}
1892389d501SLinus Walleij 
190bdd272cbSLinus Walleij 	pr_info("FPGA IRQ chip %d \"%s\" @ %p, %u irqs",
191*3fb212a0SMarc Zyngier 		fpga_irq_id, node->name, base, f->used_irqs);
192bdd272cbSLinus Walleij 	if (parent_irq != -1)
193bdd272cbSLinus Walleij 		pr_cont(", parent IRQ: %d\n", parent_irq);
194bdd272cbSLinus Walleij 	else
195bdd272cbSLinus Walleij 		pr_cont("\n");
1962389d501SLinus Walleij 
1972389d501SLinus Walleij 	fpga_irq_id++;
1982389d501SLinus Walleij }
1992389d501SLinus Walleij 
2002389d501SLinus Walleij #ifdef CONFIG_OF
fpga_irq_of_init(struct device_node * node,struct device_node * parent)201*3fb212a0SMarc Zyngier static int __init fpga_irq_of_init(struct device_node *node,
2022389d501SLinus Walleij 				   struct device_node *parent)
2032389d501SLinus Walleij {
2042389d501SLinus Walleij 	void __iomem *base;
2052389d501SLinus Walleij 	u32 clear_mask;
2062389d501SLinus Walleij 	u32 valid_mask;
207bdd272cbSLinus Walleij 	int parent_irq;
2082389d501SLinus Walleij 
2092389d501SLinus Walleij 	if (WARN_ON(!node))
2102389d501SLinus Walleij 		return -ENODEV;
2112389d501SLinus Walleij 
2122389d501SLinus Walleij 	base = of_iomap(node, 0);
2132389d501SLinus Walleij 	WARN(!base, "unable to map fpga irq registers\n");
2142389d501SLinus Walleij 
2152389d501SLinus Walleij 	if (of_property_read_u32(node, "clear-mask", &clear_mask))
2162389d501SLinus Walleij 		clear_mask = 0;
2172389d501SLinus Walleij 
2182389d501SLinus Walleij 	if (of_property_read_u32(node, "valid-mask", &valid_mask))
2192389d501SLinus Walleij 		valid_mask = 0;
2202389d501SLinus Walleij 
2216a214a28SSungbo Eo 	writel(clear_mask, base + IRQ_ENABLE_CLEAR);
2226a214a28SSungbo Eo 	writel(clear_mask, base + FIQ_ENABLE_CLEAR);
2236a214a28SSungbo Eo 
224bdd272cbSLinus Walleij 	/* Some chips are cascaded from a parent IRQ */
225bdd272cbSLinus Walleij 	parent_irq = irq_of_parse_and_map(node, 0);
2262920bc9aSRob Herring 	if (!parent_irq) {
2272920bc9aSRob Herring 		set_handle_irq(fpga_handle_irq);
228bdd272cbSLinus Walleij 		parent_irq = -1;
2292920bc9aSRob Herring 	}
230bdd272cbSLinus Walleij 
231*3fb212a0SMarc Zyngier 	fpga_irq_init(base, parent_irq, valid_mask, node);
2322389d501SLinus Walleij 
23359318461SRob Herring 	/*
23459318461SRob Herring 	 * On Versatile AB/PB, some secondary interrupts have a direct
23559318461SRob Herring 	 * pass-thru to the primary controller for IRQs 20 and 22-31 which need
23659318461SRob Herring 	 * to be enabled. See section 3.10 of the Versatile AB user guide.
23759318461SRob Herring 	 */
23859318461SRob Herring 	if (of_device_is_compatible(node, "arm,versatile-sic"))
23959318461SRob Herring 		writel(0xffd00000, base + PIC_ENABLES);
24059318461SRob Herring 
2412389d501SLinus Walleij 	return 0;
2422389d501SLinus Walleij }
2432920bc9aSRob Herring IRQCHIP_DECLARE(arm_fpga, "arm,versatile-fpga-irq", fpga_irq_of_init);
24459318461SRob Herring IRQCHIP_DECLARE(arm_fpga_sic, "arm,versatile-sic", fpga_irq_of_init);
2452389d501SLinus Walleij #endif
246