^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Ingenic XBurst platform IRQ support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/types.h>
^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/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/irqchip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/of_address.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/timex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) struct ingenic_intc_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) struct irq_domain *domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) unsigned num_chips;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define JZ_REG_INTC_STATUS 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define JZ_REG_INTC_MASK 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define JZ_REG_INTC_SET_MASK 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define JZ_REG_INTC_CLEAR_MASK 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define JZ_REG_INTC_PENDING 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define CHIP_SIZE 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static irqreturn_t intc_cascade(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) struct ingenic_intc_data *intc = irq_get_handler_data(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) struct irq_domain *domain = intc->domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct irq_chip_generic *gc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) uint32_t pending;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) unsigned i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) for (i = 0; i < intc->num_chips; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) gc = irq_get_domain_generic_chip(domain, i * 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) pending = irq_reg_readl(gc, JZ_REG_INTC_PENDING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) if (!pending)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) while (pending) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) int bit = __fls(pending);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) irq = irq_linear_revmap(domain, bit + (i * 32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) generic_handle_irq(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) pending &= ~BIT(bit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) static int __init ingenic_intc_of_init(struct device_node *node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) unsigned num_chips)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct ingenic_intc_data *intc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct irq_chip_generic *gc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct irq_chip_type *ct;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct irq_domain *domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) int parent_irq, err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) unsigned i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) intc = kzalloc(sizeof(*intc), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (!intc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) parent_irq = irq_of_parse_and_map(node, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (!parent_irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) err = irq_set_handler_data(parent_irq, intc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) goto out_unmap_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) intc->num_chips = num_chips;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) intc->base = of_iomap(node, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (!intc->base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) goto out_unmap_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) domain = irq_domain_add_linear(node, num_chips * 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) &irq_generic_chip_ops, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (!domain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) goto out_unmap_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) intc->domain = domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) err = irq_alloc_domain_generic_chips(domain, 32, 1, "INTC",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) handle_level_irq, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) IRQ_NOPROBE | IRQ_LEVEL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) goto out_domain_remove;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) for (i = 0; i < num_chips; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) gc = irq_get_domain_generic_chip(domain, i * 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) gc->wake_enabled = IRQ_MSK(32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) gc->reg_base = intc->base + (i * CHIP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) ct = gc->chip_types;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) ct->regs.enable = JZ_REG_INTC_CLEAR_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) ct->regs.disable = JZ_REG_INTC_SET_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) ct->chip.irq_mask = irq_gc_mask_disable_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) ct->chip.irq_mask_ack = irq_gc_mask_disable_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) ct->chip.irq_set_wake = irq_gc_set_wake;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) ct->chip.flags = IRQCHIP_MASK_ON_SUSPEND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) /* Mask all irqs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) irq_reg_writel(gc, IRQ_MSK(32), JZ_REG_INTC_SET_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (request_irq(parent_irq, intc_cascade, IRQF_NO_SUSPEND,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) "SoC intc cascade interrupt", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) pr_err("Failed to register SoC intc cascade interrupt\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) out_domain_remove:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) irq_domain_remove(domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) out_unmap_base:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) iounmap(intc->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) out_unmap_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) irq_dispose_mapping(parent_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) kfree(intc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) static int __init intc_1chip_of_init(struct device_node *node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) struct device_node *parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return ingenic_intc_of_init(node, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) IRQCHIP_DECLARE(jz4740_intc, "ingenic,jz4740-intc", intc_1chip_of_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) IRQCHIP_DECLARE(jz4725b_intc, "ingenic,jz4725b-intc", intc_1chip_of_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) static int __init intc_2chip_of_init(struct device_node *node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct device_node *parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return ingenic_intc_of_init(node, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) IRQCHIP_DECLARE(jz4760_intc, "ingenic,jz4760-intc", intc_2chip_of_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) IRQCHIP_DECLARE(jz4770_intc, "ingenic,jz4770-intc", intc_2chip_of_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) IRQCHIP_DECLARE(jz4775_intc, "ingenic,jz4775-intc", intc_2chip_of_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) IRQCHIP_DECLARE(jz4780_intc, "ingenic,jz4780-intc", intc_2chip_of_init);