^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Allwinner A20/A31 SoCs NMI IRQ chip driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Carlo Caione <carlo.caione@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * This file is licensed under the terms of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * License version 2. This program is licensed "as is" without any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * warranty of any kind, whether express or implied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #define DRV_NAME "sunxi-nmi"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #define pr_fmt(fmt) DRV_NAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/irqdomain.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/of_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/irqchip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/irqchip/chained_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define SUNXI_NMI_SRC_TYPE_MASK 0x00000003
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define SUNXI_NMI_IRQ_BIT BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define SUN6I_R_INTC_CTRL 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define SUN6I_R_INTC_PENDING 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define SUN6I_R_INTC_ENABLE 0x40
^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) * For deprecated sun6i-a31-sc-nmi compatible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * Registers are offset by 0x0c.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define SUN6I_R_INTC_NMI_OFFSET 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define SUN6I_NMI_CTRL (SUN6I_R_INTC_CTRL - SUN6I_R_INTC_NMI_OFFSET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define SUN6I_NMI_PENDING (SUN6I_R_INTC_PENDING - SUN6I_R_INTC_NMI_OFFSET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define SUN6I_NMI_ENABLE (SUN6I_R_INTC_ENABLE - SUN6I_R_INTC_NMI_OFFSET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define SUN7I_NMI_CTRL 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define SUN7I_NMI_PENDING 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define SUN7I_NMI_ENABLE 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define SUN9I_NMI_CTRL 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define SUN9I_NMI_ENABLE 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define SUN9I_NMI_PENDING 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) SUNXI_SRC_TYPE_LEVEL_LOW = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) SUNXI_SRC_TYPE_EDGE_FALLING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) SUNXI_SRC_TYPE_LEVEL_HIGH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) SUNXI_SRC_TYPE_EDGE_RISING,
^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) struct sunxi_sc_nmi_reg_offs {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) u32 ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) u32 pend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) u32 enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static const struct sunxi_sc_nmi_reg_offs sun6i_r_intc_reg_offs __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) .ctrl = SUN6I_R_INTC_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) .pend = SUN6I_R_INTC_PENDING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) .enable = SUN6I_R_INTC_ENABLE,
^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 const struct sunxi_sc_nmi_reg_offs sun6i_reg_offs __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) .ctrl = SUN6I_NMI_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) .pend = SUN6I_NMI_PENDING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) .enable = SUN6I_NMI_ENABLE,
^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) static const struct sunxi_sc_nmi_reg_offs sun7i_reg_offs __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) .ctrl = SUN7I_NMI_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) .pend = SUN7I_NMI_PENDING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) .enable = SUN7I_NMI_ENABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static const struct sunxi_sc_nmi_reg_offs sun9i_reg_offs __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) .ctrl = SUN9I_NMI_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) .pend = SUN9I_NMI_PENDING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) .enable = SUN9I_NMI_ENABLE,
^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 inline void sunxi_sc_nmi_write(struct irq_chip_generic *gc, u32 off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) irq_reg_writel(gc, val, off);
^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) static inline u32 sunxi_sc_nmi_read(struct irq_chip_generic *gc, u32 off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return irq_reg_readl(gc, off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static void sunxi_sc_nmi_handle_irq(struct irq_desc *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct irq_domain *domain = irq_desc_get_handler_data(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct irq_chip *chip = irq_desc_get_chip(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) unsigned int virq = irq_find_mapping(domain, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) chained_irq_enter(chip, desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) generic_handle_irq(virq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) chained_irq_exit(chip, desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static int sunxi_sc_nmi_set_type(struct irq_data *data, unsigned int flow_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) struct irq_chip_type *ct = gc->chip_types;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) u32 src_type_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) u32 ctrl_off = ct->regs.type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) unsigned int src_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) irq_gc_lock(gc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) switch (flow_type & IRQF_TRIGGER_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) case IRQ_TYPE_EDGE_FALLING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) src_type = SUNXI_SRC_TYPE_EDGE_FALLING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) case IRQ_TYPE_EDGE_RISING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) src_type = SUNXI_SRC_TYPE_EDGE_RISING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) case IRQ_TYPE_LEVEL_HIGH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) src_type = SUNXI_SRC_TYPE_LEVEL_HIGH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) case IRQ_TYPE_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) case IRQ_TYPE_LEVEL_LOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) src_type = SUNXI_SRC_TYPE_LEVEL_LOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) irq_gc_unlock(gc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) pr_err("Cannot assign multiple trigger modes to IRQ %d.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) data->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return -EBADR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) irqd_set_trigger_type(data, flow_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) irq_setup_alt_chip(data, flow_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) for (i = 0; i < gc->num_ct; i++, ct++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (ct->type & flow_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) ctrl_off = ct->regs.type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) src_type_reg = sunxi_sc_nmi_read(gc, ctrl_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) src_type_reg &= ~SUNXI_NMI_SRC_TYPE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) src_type_reg |= src_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) sunxi_sc_nmi_write(gc, ctrl_off, src_type_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) irq_gc_unlock(gc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return IRQ_SET_MASK_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) static int __init sunxi_sc_nmi_irq_init(struct device_node *node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) const struct sunxi_sc_nmi_reg_offs *reg_offs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) struct irq_domain *domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) struct irq_chip_generic *gc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) unsigned int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) int ret;
^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) domain = irq_domain_add_linear(node, 1, &irq_generic_chip_ops, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) if (!domain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) pr_err("Could not register interrupt domain.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) ret = irq_alloc_domain_generic_chips(domain, 1, 2, DRV_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) handle_fasteoi_irq, clr, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) IRQ_GC_INIT_MASK_CACHE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) pr_err("Could not allocate generic interrupt chip.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) goto fail_irqd_remove;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) irq = irq_of_parse_and_map(node, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (irq <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) pr_err("unable to parse irq\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) goto fail_irqd_remove;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) gc = irq_get_domain_generic_chip(domain, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) gc->reg_base = of_io_request_and_map(node, 0, of_node_full_name(node));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (IS_ERR(gc->reg_base)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) pr_err("unable to map resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) ret = PTR_ERR(gc->reg_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) goto fail_irqd_remove;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) gc->chip_types[0].type = IRQ_TYPE_LEVEL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) gc->chip_types[0].chip.irq_eoi = irq_gc_ack_set_bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) gc->chip_types[0].chip.irq_set_type = sunxi_sc_nmi_set_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) gc->chip_types[0].chip.flags = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) gc->chip_types[0].regs.ack = reg_offs->pend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) gc->chip_types[0].regs.mask = reg_offs->enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) gc->chip_types[0].regs.type = reg_offs->ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) gc->chip_types[1].type = IRQ_TYPE_EDGE_BOTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) gc->chip_types[1].chip.name = gc->chip_types[0].chip.name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) gc->chip_types[1].chip.irq_ack = irq_gc_ack_set_bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) gc->chip_types[1].chip.irq_mask = irq_gc_mask_clr_bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) gc->chip_types[1].chip.irq_unmask = irq_gc_mask_set_bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) gc->chip_types[1].chip.irq_set_type = sunxi_sc_nmi_set_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) gc->chip_types[1].regs.ack = reg_offs->pend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) gc->chip_types[1].regs.mask = reg_offs->enable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) gc->chip_types[1].regs.type = reg_offs->ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) gc->chip_types[1].handler = handle_edge_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) /* Disable any active interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) sunxi_sc_nmi_write(gc, reg_offs->enable, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) /* Clear any pending NMI interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) sunxi_sc_nmi_write(gc, reg_offs->pend, SUNXI_NMI_IRQ_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) irq_set_chained_handler_and_data(irq, sunxi_sc_nmi_handle_irq, domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) fail_irqd_remove:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) irq_domain_remove(domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) static int __init sun6i_r_intc_irq_init(struct device_node *node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) struct device_node *parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) return sunxi_sc_nmi_irq_init(node, &sun6i_r_intc_reg_offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) IRQCHIP_DECLARE(sun6i_r_intc, "allwinner,sun6i-a31-r-intc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) sun6i_r_intc_irq_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) static int __init sun6i_sc_nmi_irq_init(struct device_node *node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) struct device_node *parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return sunxi_sc_nmi_irq_init(node, &sun6i_reg_offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) IRQCHIP_DECLARE(sun6i_sc_nmi, "allwinner,sun6i-a31-sc-nmi", sun6i_sc_nmi_irq_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) static int __init sun7i_sc_nmi_irq_init(struct device_node *node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) struct device_node *parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return sunxi_sc_nmi_irq_init(node, &sun7i_reg_offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) IRQCHIP_DECLARE(sun7i_sc_nmi, "allwinner,sun7i-a20-sc-nmi", sun7i_sc_nmi_irq_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) static int __init sun9i_nmi_irq_init(struct device_node *node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) struct device_node *parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return sunxi_sc_nmi_irq_init(node, &sun9i_reg_offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) IRQCHIP_DECLARE(sun9i_nmi, "allwinner,sun9i-a80-nmi", sun9i_nmi_irq_init);