^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Abilis Systems interrupt controller driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) Abilis Systems 2012
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Author: Christian Ruppert <christian.ruppert@abilis.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/interrupt.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/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/irqchip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/of_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define AB_IRQCTL_INT_ENABLE 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define AB_IRQCTL_INT_STATUS 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define AB_IRQCTL_SRC_MODE 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define AB_IRQCTL_SRC_POLARITY 0x0C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define AB_IRQCTL_INT_MODE 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define AB_IRQCTL_INT_POLARITY 0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define AB_IRQCTL_INT_FORCE 0x18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define AB_IRQCTL_MAXIRQ 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static inline void ab_irqctl_writereg(struct irq_chip_generic *gc, u32 reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) irq_reg_writel(gc, val, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static inline u32 ab_irqctl_readreg(struct irq_chip_generic *gc, u32 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) return irq_reg_readl(gc, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static int tb10x_irq_set_type(struct irq_data *data, unsigned int flow_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) uint32_t im, mod, pol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) im = data->mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) irq_gc_lock(gc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) mod = ab_irqctl_readreg(gc, AB_IRQCTL_SRC_MODE) | im;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) pol = ab_irqctl_readreg(gc, AB_IRQCTL_SRC_POLARITY) | im;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) switch (flow_type & IRQF_TRIGGER_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) case IRQ_TYPE_EDGE_FALLING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) pol ^= im;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) case IRQ_TYPE_LEVEL_HIGH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) mod ^= im;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) case IRQ_TYPE_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) flow_type = IRQ_TYPE_LEVEL_LOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) case IRQ_TYPE_LEVEL_LOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) mod ^= im;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) pol ^= im;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) case IRQ_TYPE_EDGE_RISING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) irq_gc_unlock(gc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) pr_err("%s: Cannot assign multiple trigger modes to IRQ %d.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) __func__, data->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) return -EBADR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) irqd_set_trigger_type(data, flow_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) irq_setup_alt_chip(data, flow_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) ab_irqctl_writereg(gc, AB_IRQCTL_SRC_MODE, mod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) ab_irqctl_writereg(gc, AB_IRQCTL_SRC_POLARITY, pol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) ab_irqctl_writereg(gc, AB_IRQCTL_INT_STATUS, im);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) irq_gc_unlock(gc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return IRQ_SET_MASK_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static void tb10x_irq_cascade(struct irq_desc *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct irq_domain *domain = irq_desc_get_handler_data(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) unsigned int irq = irq_desc_get_irq(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) generic_handle_irq(irq_find_mapping(domain, irq));
^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) static int __init of_tb10x_init_irq(struct device_node *ictl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) struct device_node *parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) int i, ret, nrirqs = of_irq_count(ictl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct resource mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct irq_chip_generic *gc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct irq_domain *domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) void __iomem *reg_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (of_address_to_resource(ictl, 0, &mem)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) pr_err("%pOFn: No registers declared in DeviceTree.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) ictl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (!request_mem_region(mem.start, resource_size(&mem),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) ictl->full_name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) pr_err("%pOFn: Request mem region failed.\n", ictl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) reg_base = ioremap(mem.start, resource_size(&mem));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (!reg_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) pr_err("%pOFn: ioremap failed.\n", ictl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) goto ioremap_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) domain = irq_domain_add_linear(ictl, AB_IRQCTL_MAXIRQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) &irq_generic_chip_ops, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (!domain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) pr_err("%pOFn: Could not register interrupt domain.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) ictl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) goto irq_domain_add_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) ret = irq_alloc_domain_generic_chips(domain, AB_IRQCTL_MAXIRQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 2, ictl->name, handle_level_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) IRQ_NOREQUEST, IRQ_NOPROBE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) IRQ_GC_INIT_MASK_CACHE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) pr_err("%pOFn: Could not allocate generic interrupt chip.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) ictl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) goto gc_alloc_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) gc = domain->gc->gc[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) gc->reg_base = reg_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) gc->chip_types[0].type = IRQ_TYPE_LEVEL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) gc->chip_types[0].chip.irq_set_type = tb10x_irq_set_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) gc->chip_types[0].regs.mask = AB_IRQCTL_INT_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) gc->chip_types[1].type = IRQ_TYPE_EDGE_BOTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) gc->chip_types[1].chip.name = gc->chip_types[0].chip.name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) gc->chip_types[1].chip.irq_ack = irq_gc_ack_set_bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) gc->chip_types[1].chip.irq_mask = irq_gc_mask_clr_bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) gc->chip_types[1].chip.irq_unmask = irq_gc_mask_set_bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) gc->chip_types[1].chip.irq_set_type = tb10x_irq_set_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) gc->chip_types[1].regs.ack = AB_IRQCTL_INT_STATUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) gc->chip_types[1].regs.mask = AB_IRQCTL_INT_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) gc->chip_types[1].handler = handle_edge_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) for (i = 0; i < nrirqs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) unsigned int irq = irq_of_parse_and_map(ictl, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) irq_set_chained_handler_and_data(irq, tb10x_irq_cascade,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) ab_irqctl_writereg(gc, AB_IRQCTL_INT_ENABLE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) ab_irqctl_writereg(gc, AB_IRQCTL_INT_MODE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) ab_irqctl_writereg(gc, AB_IRQCTL_INT_POLARITY, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) ab_irqctl_writereg(gc, AB_IRQCTL_INT_STATUS, ~0UL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) gc_alloc_fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) irq_domain_remove(domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) irq_domain_add_fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) iounmap(reg_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) ioremap_fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) release_mem_region(mem.start, resource_size(&mem));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) IRQCHIP_DECLARE(tb10x_intc, "abilis,tb10x-ictl", of_tb10x_init_irq);