^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) * Renesas RZ/A1 IRQC Driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2019 Glider bvba
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/init.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/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/irqdomain.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/module.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) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <dt-bindings/interrupt-controller/arm-gic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define IRQC_NUM_IRQ 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define ICR0 0 /* Interrupt Control Register 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define ICR0_NMIL BIT(15) /* NMI Input Level (0=low, 1=high) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define ICR0_NMIE BIT(8) /* Edge Select (0=falling, 1=rising) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define ICR0_NMIF BIT(1) /* NMI Interrupt Request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define ICR1 2 /* Interrupt Control Register 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define ICR1_IRQS(n, sense) ((sense) << ((n) * 2)) /* IRQ Sense Select */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define ICR1_IRQS_LEVEL_LOW 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define ICR1_IRQS_EDGE_FALLING 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define ICR1_IRQS_EDGE_RISING 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define ICR1_IRQS_EDGE_BOTH 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define ICR1_IRQS_MASK(n) ICR1_IRQS((n), 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define IRQRR 4 /* IRQ Interrupt Request Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct rza1_irqc_priv {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct device *dev;
^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) struct irq_domain *irq_domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct of_phandle_args map[IRQC_NUM_IRQ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) static struct rza1_irqc_priv *irq_data_to_priv(struct irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) return data->domain->host_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static void rza1_irqc_eoi(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 rza1_irqc_priv *priv = irq_data_to_priv(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) u16 bit = BIT(irqd_to_hwirq(d));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) u16 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) tmp = readw_relaxed(priv->base + IRQRR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (tmp & bit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) writew_relaxed(GENMASK(IRQC_NUM_IRQ - 1, 0) & ~bit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) priv->base + IRQRR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) irq_chip_eoi_parent(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) static int rza1_irqc_set_type(struct irq_data *d, unsigned int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct rza1_irqc_priv *priv = irq_data_to_priv(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) unsigned int hw_irq = irqd_to_hwirq(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) u16 sense, tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) switch (type & IRQ_TYPE_SENSE_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) case IRQ_TYPE_LEVEL_LOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) sense = ICR1_IRQS_LEVEL_LOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) case IRQ_TYPE_EDGE_FALLING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) sense = ICR1_IRQS_EDGE_FALLING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) case IRQ_TYPE_EDGE_RISING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) sense = ICR1_IRQS_EDGE_RISING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) case IRQ_TYPE_EDGE_BOTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) sense = ICR1_IRQS_EDGE_BOTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) return -EINVAL;
^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) tmp = readw_relaxed(priv->base + ICR1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) tmp &= ~ICR1_IRQS_MASK(hw_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) tmp |= ICR1_IRQS(hw_irq, sense);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) writew_relaxed(tmp, priv->base + ICR1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static int rza1_irqc_alloc(struct irq_domain *domain, unsigned int virq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) unsigned int nr_irqs, void *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct rza1_irqc_priv *priv = domain->host_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct irq_fwspec *fwspec = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) unsigned int hwirq = fwspec->param[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct irq_fwspec spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq, &priv->chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) spec.fwnode = &priv->dev->of_node->fwnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) spec.param_count = priv->map[hwirq].args_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) for (i = 0; i < spec.param_count; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) spec.param[i] = priv->map[hwirq].args[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &spec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static int rza1_irqc_translate(struct irq_domain *domain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) struct irq_fwspec *fwspec, unsigned long *hwirq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) unsigned int *type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (fwspec->param_count != 2 || fwspec->param[0] >= IRQC_NUM_IRQ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) *hwirq = fwspec->param[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) *type = fwspec->param[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static const struct irq_domain_ops rza1_irqc_domain_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) .alloc = rza1_irqc_alloc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) .translate = rza1_irqc_translate,
^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) static int rza1_irqc_parse_map(struct rza1_irqc_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) struct device_node *gic_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) unsigned int imaplen, i, j, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) struct device *dev = priv->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) struct device_node *ipar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) const __be32 *imap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) u32 intsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) imap = of_get_property(dev->of_node, "interrupt-map", &imaplen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (!imap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) for (i = 0; i < IRQC_NUM_IRQ; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (imaplen < 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /* Check interrupt number, ignore sense */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (be32_to_cpup(imap) != i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) ipar = of_find_node_by_phandle(be32_to_cpup(imap + 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (ipar != gic_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) of_node_put(ipar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return -EINVAL;
^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) imap += 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) imaplen -= 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) ret = of_property_read_u32(ipar, "#interrupt-cells", &intsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) of_node_put(ipar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (imaplen < intsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) priv->map[i].args_count = intsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) for (j = 0; j < intsize; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) priv->map[i].args[j] = be32_to_cpup(imap++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) imaplen -= intsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return 0;
^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) static int rza1_irqc_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) struct device_node *np = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) struct irq_domain *parent = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) struct device_node *gic_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) struct rza1_irqc_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (!priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) platform_set_drvdata(pdev, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) priv->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) priv->base = devm_platform_ioremap_resource(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (IS_ERR(priv->base))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) return PTR_ERR(priv->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) gic_node = of_irq_find_parent(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (gic_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) parent = irq_find_host(gic_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (!parent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) dev_err(dev, "cannot find parent domain\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) goto out_put_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) ret = rza1_irqc_parse_map(priv, gic_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) dev_err(dev, "cannot parse %s: %d\n", "interrupt-map", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) goto out_put_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) priv->chip.name = "rza1-irqc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) priv->chip.irq_mask = irq_chip_mask_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) priv->chip.irq_unmask = irq_chip_unmask_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) priv->chip.irq_eoi = rza1_irqc_eoi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) priv->chip.irq_retrigger = irq_chip_retrigger_hierarchy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) priv->chip.irq_set_type = rza1_irqc_set_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) priv->chip.flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) priv->irq_domain = irq_domain_add_hierarchy(parent, 0, IRQC_NUM_IRQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) np, &rza1_irqc_domain_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (!priv->irq_domain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) dev_err(dev, "cannot initialize irq domain\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) out_put_node:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) of_node_put(gic_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) static int rza1_irqc_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) struct rza1_irqc_priv *priv = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) irq_domain_remove(priv->irq_domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) static const struct of_device_id rza1_irqc_dt_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) { .compatible = "renesas,rza1-irqc" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) MODULE_DEVICE_TABLE(of, rza1_irqc_dt_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) static struct platform_driver rza1_irqc_device_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) .probe = rza1_irqc_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) .remove = rza1_irqc_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) .name = "renesas_rza1_irqc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) .of_match_table = rza1_irqc_dt_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) static int __init rza1_irqc_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) return platform_driver_register(&rza1_irqc_device_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) postcore_initcall(rza1_irqc_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) static void __exit rza1_irqc_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) platform_driver_unregister(&rza1_irqc_device_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) module_exit(rza1_irqc_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) MODULE_AUTHOR("Geert Uytterhoeven <geert+renesas@glider.be>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) MODULE_DESCRIPTION("Renesas RZ/A1 IRQC Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) MODULE_LICENSE("GPL v2");