[RFC v11 1/4] gpio: mpfs: Add interrupt support
Linus Walleij
linusw at kernel.org
Mon Mar 2 01:44:45 PST 2026
Hi Conor,
overall this looks okay, but one detail here:
On Fri, Feb 27, 2026 at 3:53 PM Conor Dooley <conor at kernel.org> wrote:
> From: Conor Dooley <conor.dooley at microchip.com>
>
> Add support for interrupts to the PolarFire SoC GPIO driver. Each GPIO
> has an independent interrupt that is wired to an interrupt mux that sits
> between the controllers and the PLIC. The SoC has more GPIO lines than
> connections from the mux to the PLIC, so some GPIOs must share PLIC
> interrupts. The configuration is not static and is set at runtime,
> conventionally by the platform's firmware. CoreGPIO, the version
> intended for use in the FPGA fabric has two interrupt output ports, one
> is IO_NUM bits wide, as is used in the hardened cores, and the other is
> a single bit with all lines ORed together.
>
> Signed-off-by: Conor Dooley <conor.dooley at microchip.com>
> ---
> Doing the chained thing kinda covers all the bases at the expense of the
> "direct" mode interrupts that have a dedicated connection to the PLIC.
Chained kinda thing, OK...
> +static irqreturn_t mpfs_gpio_irq_handler(int irq, void *data)
static void mpfs_gpio_irq_handler(struct irq_desc *desc)
> +{
> + struct mpfs_gpio_chip *mpfs_gpio = data;
> + unsigned int handled = 0;
> + unsigned long status;
> + u32 val;
> + int i;
> +
struct irq_chip *irqchip = irq_desc_get_chip(desc);
chained_irq_enter(irqchip, desc)
> + regmap_read(mpfs_gpio->regs, MPFS_IRQ_REG, &val);
> + status = val;
> + for_each_set_bit(i, &status, MPFS_MAX_NUM_GPIO) {
> + regmap_write(mpfs_gpio->regs, MPFS_IRQ_REG, BIT(i));
> + generic_handle_domain_irq(mpfs_gpio->gc.irq.domain, i);
> + handled++;
> + }
chained_irq_exit(irqchip, desc)
(no return value)
> static int mpfs_gpio_probe(struct platform_device *pdev)
> {
> struct device *dev = &pdev->dev;
> + struct device_node *node = pdev->dev.of_node;
> struct mpfs_gpio_chip *mpfs_gpio;
> + struct gpio_irq_chip *girq;
> struct clk *clk;
> void __iomem *base;
> - int ngpios;
> + int ngpios, nirqs, ret;
>
> mpfs_gpio = devm_kzalloc(dev, sizeof(*mpfs_gpio), GFP_KERNEL);
> if (!mpfs_gpio)
> @@ -157,6 +243,39 @@ static int mpfs_gpio_probe(struct platform_device *pdev)
> mpfs_gpio->gc.parent = dev;
> mpfs_gpio->gc.owner = THIS_MODULE;
>
> + nirqs = of_irq_count(node);
> + if (nirqs > MPFS_MAX_NUM_GPIO)
> + return -ENXIO;
> +
> + girq = &mpfs_gpio->gc.irq;
> + girq->num_parents = nirqs;
> +
> + if (girq->num_parents) {
> + gpio_irq_chip_set_chip(girq, &mpfs_gpio_irqchip);
> +
> + girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents,
> + sizeof(*girq->parents), GFP_KERNEL);
> + if (!girq->parents)
> + return -ENOMEM;
> +
> + for (int i = 0; i < girq->num_parents; i++) {
> + ret = platform_get_irq(pdev, i);
> + if (ret < 0)
> + return ret;
> +
> + girq->parents[i] = ret;
> + ret = devm_request_irq(dev, girq->parents[i], mpfs_gpio_irq_handler,
> + IRQF_SHARED, NULL, mpfs_gpio);
> + if (ret)
> + return dev_err_probe(dev, ret,
> + "failed to request irq for line %u\n",
> + i);
> + }
Why do this instead of letting the core do the multi-parent chaining without
explicitly requesting the IRQs like e.g. gpio-dwapb.c does for the
multi-parent case?
Yours,
Linus Walleij
More information about the linux-riscv
mailing list