^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Support for Versatile FPGA-based IRQ controllers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/irqchip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/irqchip/chained_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/irqchip/versatile-fpga.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/irqdomain.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/of_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <asm/exception.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <asm/mach/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define IRQ_STATUS 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define IRQ_RAW_STATUS 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define IRQ_ENABLE_SET 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define IRQ_ENABLE_CLEAR 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define INT_SOFT_SET 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define INT_SOFT_CLEAR 0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define FIQ_STATUS 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define FIQ_RAW_STATUS 0x24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define FIQ_ENABLE 0x28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define FIQ_ENABLE_SET 0x28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define FIQ_ENABLE_CLEAR 0x2C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define PIC_ENABLES 0x20 /* set interrupt pass through bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * struct fpga_irq_data - irq data container for the FPGA IRQ controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * @base: memory offset in virtual memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * @chip: chip container for this instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * @domain: IRQ domain for this instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * @valid: mask for valid IRQs on this controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * @used_irqs: number of active IRQs on this controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct fpga_irq_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct irq_chip chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) u32 valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct irq_domain *domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) u8 used_irqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) /* we cannot allocate memory when the controllers are initially registered */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static struct fpga_irq_data fpga_irq_devices[CONFIG_VERSATILE_FPGA_IRQ_NR];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) static int fpga_irq_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static void fpga_irq_mask(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct fpga_irq_data *f = irq_data_get_irq_chip_data(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) u32 mask = 1 << d->hwirq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) writel(mask, f->base + IRQ_ENABLE_CLEAR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static void fpga_irq_unmask(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct fpga_irq_data *f = irq_data_get_irq_chip_data(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) u32 mask = 1 << d->hwirq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) writel(mask, f->base + IRQ_ENABLE_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static void fpga_irq_handle(struct irq_desc *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct irq_chip *chip = irq_desc_get_chip(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) struct fpga_irq_data *f = irq_desc_get_handler_data(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) u32 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) chained_irq_enter(chip, desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) status = readl(f->base + IRQ_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (status == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) do_bad_IRQ(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) unsigned int irq = ffs(status) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) status &= ~(1 << irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) generic_handle_irq(irq_find_mapping(f->domain, irq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) } while (status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) chained_irq_exit(chip, desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * Handle each interrupt in a single FPGA IRQ controller. Returns non-zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * if we've handled at least one interrupt. This does a single read of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * status register and handles all interrupts in order from LSB first.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static int handle_one_fpga(struct fpga_irq_data *f, struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) int handled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) u32 status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) while ((status = readl(f->base + IRQ_STATUS))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) irq = ffs(status) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) handle_domain_irq(f->domain, irq, regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) handled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return handled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * Keep iterating over all registered FPGA IRQ controllers until there are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * no pending interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) asmlinkage void __exception_irq_entry fpga_handle_irq(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) int i, handled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) for (i = 0, handled = 0; i < fpga_irq_id; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) handled |= handle_one_fpga(&fpga_irq_devices[i], regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) } while (handled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static int fpga_irqdomain_map(struct irq_domain *d, unsigned int irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) irq_hw_number_t hwirq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct fpga_irq_data *f = d->host_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) /* Skip invalid IRQs, only register handlers for the real ones */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (!(f->valid & BIT(hwirq)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) irq_set_chip_data(irq, f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) irq_set_chip_and_handler(irq, &f->chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) handle_level_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) irq_set_probe(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) static const struct irq_domain_ops fpga_irqdomain_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) .map = fpga_irqdomain_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) .xlate = irq_domain_xlate_onetwocell,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) void __init fpga_irq_init(void __iomem *base, const char *name, int irq_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) int parent_irq, u32 valid, struct device_node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) struct fpga_irq_data *f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (fpga_irq_id >= ARRAY_SIZE(fpga_irq_devices)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) pr_err("%s: too few FPGA IRQ controllers, increase CONFIG_VERSATILE_FPGA_IRQ_NR\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) f = &fpga_irq_devices[fpga_irq_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) f->base = base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) f->chip.name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) f->chip.irq_ack = fpga_irq_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) f->chip.irq_mask = fpga_irq_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) f->chip.irq_unmask = fpga_irq_unmask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) f->valid = valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (parent_irq != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) irq_set_chained_handler_and_data(parent_irq, fpga_irq_handle,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) /* This will also allocate irq descriptors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) f->domain = irq_domain_add_simple(node, fls(valid), irq_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) &fpga_irqdomain_ops, f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) /* This will allocate all valid descriptors in the linear case */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) for (i = 0; i < fls(valid); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (valid & BIT(i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (!irq_start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) irq_create_mapping(f->domain, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) f->used_irqs++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) pr_info("FPGA IRQ chip %d \"%s\" @ %p, %u irqs",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) fpga_irq_id, name, base, f->used_irqs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (parent_irq != -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) pr_cont(", parent IRQ: %d\n", parent_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) pr_cont("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) fpga_irq_id++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) #ifdef CONFIG_OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) int __init fpga_irq_of_init(struct device_node *node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) struct device_node *parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) u32 clear_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) u32 valid_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) int parent_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (WARN_ON(!node))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) base = of_iomap(node, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) WARN(!base, "unable to map fpga irq registers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (of_property_read_u32(node, "clear-mask", &clear_mask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) clear_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (of_property_read_u32(node, "valid-mask", &valid_mask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) valid_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) writel(clear_mask, base + IRQ_ENABLE_CLEAR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) writel(clear_mask, base + FIQ_ENABLE_CLEAR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) /* Some chips are cascaded from a parent IRQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) parent_irq = irq_of_parse_and_map(node, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (!parent_irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) set_handle_irq(fpga_handle_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) parent_irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) fpga_irq_init(base, node->name, 0, parent_irq, valid_mask, node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) * On Versatile AB/PB, some secondary interrupts have a direct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * pass-thru to the primary controller for IRQs 20 and 22-31 which need
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) * to be enabled. See section 3.10 of the Versatile AB user guide.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (of_device_is_compatible(node, "arm,versatile-sic"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) writel(0xffd00000, base + PIC_ENABLES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) IRQCHIP_DECLARE(arm_fpga, "arm,versatile-fpga-irq", fpga_irq_of_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) IRQCHIP_DECLARE(arm_fpga_sic, "arm,versatile-sic", fpga_irq_of_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) IRQCHIP_DECLARE(ox810se_rps, "oxsemi,ox810se-rps-irq", fpga_irq_of_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) #endif