[PATCH v1 2/4] gpio: phytium: switch platform driver to immutable irq_chip
From: Zhu Ling
Date: Sun Mar 01 2026 - 20:52:52 EST
Use a static immutable irq_chip and gpio_irq_chip_set_chip() in the
platform frontend.
Also initialize and restore interrupt state more explicitly for suspend
and resume, and accept both ngpios and nr-gpios child properties when
probing GPIO ports.
Signed-off-by: Zhu Ling <1536943441@xxxxxx>
---
drivers/gpio/gpio-phytium-platform.c | 55 ++++++++++++++++++----------
1 file changed, 35 insertions(+), 20 deletions(-)
diff --git a/drivers/gpio/gpio-phytium-platform.c b/drivers/gpio/gpio-phytium-platform.c
index 4925b45c9..182b6480c 100644
--- a/drivers/gpio/gpio-phytium-platform.c
+++ b/drivers/gpio/gpio-phytium-platform.c
@@ -2,7 +2,7 @@
/*
* Support functions for Phytium GPIO
*
- * Copyright (c) 2019-2023, Phytium Phytium Technology Co., Ltd.
+ * Copyright (c) 2019-2023, Phytium Technology Co., Ltd.
*
* Derived from drivers/gpio/gpio-pl061.c
* Copyright (C) 2008, 2009 Provigent Ltd.
@@ -33,6 +33,20 @@ static const struct acpi_device_id phytium_gpio_acpi_match[] = {
};
MODULE_DEVICE_TABLE(acpi, phytium_gpio_acpi_match);
+static const struct irq_chip phytium_gpio_irq_chip = {
+ .irq_ack = phytium_gpio_irq_ack,
+ .irq_mask = phytium_gpio_irq_mask,
+ .irq_unmask = phytium_gpio_irq_unmask,
+ .irq_set_type = phytium_gpio_irq_set_type,
+ .irq_print_chip = phytium_gpio_irq_print_chip,
+ .irq_enable = phytium_gpio_irq_enable,
+ .irq_disable = phytium_gpio_irq_disable,
+ .irq_set_wake = phytium_gpio_irq_set_wake,
+ .irq_set_affinity = phytium_gpio_irq_set_affinity,
+ .flags = IRQCHIP_IMMUTABLE,
+ GPIOCHIP_IRQ_RESOURCE_HELPERS,
+};
+
static int phytium_gpio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -64,8 +78,10 @@ static int phytium_gpio_probe(struct platform_device *pdev)
return -EINVAL;
}
- if (fwnode_property_read_u32(fwnode, "ngpios",
- &gpio->ngpio[idx])) {
+ if ((fwnode_property_read_u32(fwnode, "ngpios",
+ &gpio->ngpio[idx])) &&
+ (fwnode_property_read_u32(fwnode, "nr-gpios",
+ &gpio->ngpio[idx]))) {
dev_info(dev,
"failed to get number of gpios for Port%c\n",
idx ? 'B' : 'A');
@@ -74,18 +90,11 @@ static int phytium_gpio_probe(struct platform_device *pdev)
}
/* irq_chip support */
- gpio->irq_chip.name = dev_name(dev);
- gpio->irq_chip.irq_ack = phytium_gpio_irq_ack;
- gpio->irq_chip.irq_mask = phytium_gpio_irq_mask;
- gpio->irq_chip.irq_unmask = phytium_gpio_irq_unmask;
- gpio->irq_chip.irq_set_type = phytium_gpio_irq_set_type;
- gpio->irq_chip.irq_enable = phytium_gpio_irq_enable;
- gpio->irq_chip.irq_disable = phytium_gpio_irq_disable;
-#ifdef CONFIG_SMP
- gpio->irq_chip.irq_set_affinity = phytium_gpio_irq_set_affinity;
-#endif
raw_spin_lock_init(&gpio->lock);
+ writel(0, gpio->regs + GPIO_INTEN);
+ writel(GPIO_CLEAR_IRQ, gpio->regs + GPIO_PORTA_EOI);
+
gpio->gc.base = -1;
gpio->gc.get_direction = phytium_gpio_get_direction;
gpio->gc.direction_input = phytium_gpio_direction_input;
@@ -101,20 +110,20 @@ static int phytium_gpio_probe(struct platform_device *pdev)
girq->handler = handle_bad_irq;
girq->default_type = IRQ_TYPE_NONE;
- for (irq_count = 0; irq_count < gpio->ngpio[0]; irq_count++) {
+ for (irq_count = 0; irq_count < platform_irq_count(pdev); irq_count++) {
gpio->irq[irq_count] = -ENXIO;
gpio->irq[irq_count] = platform_get_irq(pdev, irq_count);
if (gpio->irq[irq_count] < 0) {
dev_warn(dev, "no irq is found.\n");
break;
}
- };
+ }
girq->num_parents = irq_count;
girq->parents = gpio->irq;
girq->parent_handler = phytium_gpio_irq_handler;
- girq->chip = &gpio->irq_chip;
+ gpio_irq_chip_set_chip(girq, &phytium_gpio_irq_chip);
err = devm_gpiochip_add_data(dev, &gpio->gc, gpio);
if (err)
@@ -122,7 +131,7 @@ static int phytium_gpio_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, gpio);
dev_info(dev, "Phytium GPIO controller @%pa registered\n",
- &res->start);
+ &res->start);
return 0;
}
@@ -144,11 +153,14 @@ static int phytium_gpio_suspend(struct device *dev)
gpio->ctx.ext_portb = readl(gpio->regs + GPIO_EXT_PORTB);
gpio->ctx.inten = readl(gpio->regs + GPIO_INTEN);
+ gpio->is_resuming = 1;
gpio->ctx.intmask = readl(gpio->regs + GPIO_INTMASK);
gpio->ctx.inttype_level = readl(gpio->regs + GPIO_INTTYPE_LEVEL);
gpio->ctx.int_polarity = readl(gpio->regs + GPIO_INT_POLARITY);
gpio->ctx.debounce = readl(gpio->regs + GPIO_DEBOUNCE);
+ writel(~gpio->ctx.wake_en, gpio->regs + GPIO_INTMASK);
+ writel(gpio->ctx.wake_en, gpio->regs + GPIO_INTEN);
raw_spin_unlock_irqrestore(&gpio->lock, flags);
return 0;
@@ -169,13 +181,15 @@ static int phytium_gpio_resume(struct device *dev)
writel(gpio->ctx.swportb_ddr, gpio->regs + GPIO_SWPORTB_DDR);
writel(gpio->ctx.ext_portb, gpio->regs + GPIO_EXT_PORTB);
- writel(gpio->ctx.inten, gpio->regs + GPIO_INTEN);
writel(gpio->ctx.intmask, gpio->regs + GPIO_INTMASK);
writel(gpio->ctx.inttype_level, gpio->regs + GPIO_INTTYPE_LEVEL);
writel(gpio->ctx.int_polarity, gpio->regs + GPIO_INT_POLARITY);
writel(gpio->ctx.debounce, gpio->regs + GPIO_DEBOUNCE);
- writel(0xffffffff, gpio->regs + GPIO_PORTA_EOI);
+ writel(GPIO_CLEAR_IRQ, gpio->regs + GPIO_PORTA_EOI);
+
+ writel(gpio->ctx.inten, gpio->regs + GPIO_INTEN);
+ gpio->is_resuming = 0;
raw_spin_unlock_irqrestore(&gpio->lock, flags);
@@ -198,6 +212,7 @@ static struct platform_driver phytium_gpio_driver = {
module_platform_driver(phytium_gpio_driver);
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL");
MODULE_AUTHOR("Chen Baozi <chenbaozi@xxxxxxxxxxxxxx>");
MODULE_DESCRIPTION("Phytium GPIO driver");
+MODULE_VERSION(PHYTIUM_GPIO_DRIVER_VERSION);
--
2.34.1