* [PATCH 0/9] gpio: mxc: bug fixes and probe cleanup
@ 2026-10-03 12:06 Peng Fan (OSS)
2026-10-03 12:06 ` [PATCH 1/9] gpio: mxc: fix race between chained IRQ handler install and probe completion Peng Fan (OSS)
` (8 more replies)
0 siblings, 9 replies; 20+ messages in thread
From: Peng Fan (OSS) @ 2026-10-03 12:06 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang,
Andy Shevchenko
Cc: linux-gpio, imx, linux-arm-kernel, linux-kernel, Peng Fan
Two bug fixes and follows up with probe modernization and bitops cleanup.
We not receive bug report and met issues during our test, so patch 1&2
are not critial for now.
Patches 1-2 are bug fixes:
1. Fix a race where the chained IRQ handler is installed before the
IRQ domain, generic IRQ chip, and port list entry are ready.
Also fixes a latent use-after-free on probe failure paths that
never unregistered the handler.
2. Fix wakeup_pads being typed as u32 while accessed through
set_bit/clear_bit (unsigned long *), causing adjacent field
corruption on 64-bit platforms. Switch to atomic bitops for
concurrency safety and fix the disable path to preserve the
wakeup_pads bit on disable_irq_wake() failure.
Patches 3-9 are cleanups, each building on the previous:
3. Cache of_device_is_compatible() results at probe into struct
fields, avoiding repeated DT string comparisons in suspend/resume.
4. Use devm_add_action_or_reset() for irq_domain_remove(), removing
manual cleanup in error paths.
5. Switch to devm-managed PM runtime and dev_err_probe(), eliminating
the remaining goto error labels entirely.
6. Introduce a local 'dev' variable and migrate to
device_is_compatible() for firmware-agnostic matching.
7. Introduce MXC_ICR_REG/MXC_ICR_MASK macros and use
field_prep()/field_get() for ICR register access, replacing
duplicated magic-number arithmetic in gpio_set_irq_type() and
mxc_flip_edge().
8. Replace open-coded '1 << n' with BIT() throughout the driver.
9. Simplify gpio_set_wake_irq() using irq_set_irq_wake() and
assign_bit().
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
Peng Fan (9):
gpio: mxc: fix race between chained IRQ handler install and probe completion
gpio: mxc: fix wakeup_pads bit operations for correctness
gpio: mxc: cache compatible checks at probe time
gpio: mxc: use devm action for irq_domain cleanup
gpio: mxc: use devres-managed PM runtime and dev_err_probe
gpio: mxc: use local dev variable and device_is_compatible()
gpio: mxc: introduce MXC_ICR macros and use field_prep/field_get
gpio: mxc: use BIT() macro for single-bit operations
gpio: mxc: simplify gpio_set_wake_irq() with irq_set_irq_wake and assign_bit
drivers/gpio/gpio-mxc.c | 158 ++++++++++++++++++++++++------------------------
1 file changed, 79 insertions(+), 79 deletions(-)
---
base-commit: f0406245cb9855e6318335a8a223551354291a46
change-id: 20261003-gpio-mxc-cleanup-e49cc626c51e
Best regards,
--
Peng Fan <peng.fan@nxp.com>
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 1/9] gpio: mxc: fix race between chained IRQ handler install and probe completion
2026-10-03 12:06 [PATCH 0/9] gpio: mxc: bug fixes and probe cleanup Peng Fan (OSS)
@ 2026-10-03 12:06 ` Peng Fan (OSS)
2026-10-03 17:35 ` Andy Shevchenko
2026-10-03 12:06 ` [PATCH 2/9] gpio: mxc: fix wakeup_pads bit operations for correctness Peng Fan (OSS)
` (7 subsequent siblings)
8 siblings, 1 reply; 20+ messages in thread
From: Peng Fan (OSS) @ 2026-10-03 12:06 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang,
Andy Shevchenko
Cc: linux-gpio, imx, linux-arm-kernel, linux-kernel, Peng Fan
From: Peng Fan <peng.fan@nxp.com>
mxc_update_irq_chained_handler() is called before the IRQ domain, the
generic IRQ chip, and the port list entry are set up. If an interrupt
arrives in that window:
- mx3_gpio_irq_handler() calls generic_handle_domain_irq() with
port->domain still NULL.
- mx2_gpio_irq_handler() walks mxc_gpio_ports, but the port has not
been added to the list yet.
Additionally, if any of the subsequent probe steps (gpio_generic_chip_init,
devm_gpiochip_add_data, irq_domain_create_legacy, or mxc_gpio_init_gc)
fail, the error paths never unregister the chained handler, leaving a
dangling handler that points at freed memory.
Move the handler installation after all its dependencies are ready and
after list_add_tail(), so the handler is never live while the data
structures it touches are incomplete, and is never installed if probe
fails.
Fixes: 5f6d1998adeb ("gpio: mxc: release the parent IRQ in runtime suspend")
Assisted-by: LLM
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
drivers/gpio/gpio-mxc.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index 7e2690d92df6..e05f276a50e8 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -474,8 +474,6 @@ static int mxc_gpio_probe(struct platform_device *pdev)
} else
port->mx_irq_handler = mx3_gpio_irq_handler;
- mxc_update_irq_chained_handler(port, true);
-
config.dev = &pdev->dev;
config.sz = 4;
config.dat = port->base + GPIO_PSR;
@@ -525,6 +523,8 @@ static int mxc_gpio_probe(struct platform_device *pdev)
list_add_tail(&port->node, &mxc_gpio_ports);
+ mxc_update_irq_chained_handler(port, true);
+
platform_set_drvdata(pdev, port);
pm_runtime_put_autosuspend(&pdev->dev);
--
2.51.0
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 2/9] gpio: mxc: fix wakeup_pads bit operations for correctness
2026-10-03 12:06 [PATCH 0/9] gpio: mxc: bug fixes and probe cleanup Peng Fan (OSS)
2026-10-03 12:06 ` [PATCH 1/9] gpio: mxc: fix race between chained IRQ handler install and probe completion Peng Fan (OSS)
@ 2026-10-03 12:06 ` Peng Fan (OSS)
2026-10-03 17:41 ` Andy Shevchenko
2026-10-03 12:06 ` [PATCH 3/9] gpio: mxc: cache compatible checks at probe time Peng Fan (OSS)
` (6 subsequent siblings)
8 siblings, 1 reply; 20+ messages in thread
From: Peng Fan (OSS) @ 2026-10-03 12:06 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang,
Andy Shevchenko
Cc: linux-gpio, imx, linux-arm-kernel, linux-kernel, Peng Fan
From: Peng Fan <peng.fan@nxp.com>
Replace the open-coded BIT() / mask operations with the atomic
set_bit() / clear_bit() / test_bit() API. Atomic variants are required
because gpio_set_wake_irq() can be called concurrently for different
pins on the same port - irq_set_irq_wake() only holds the per-IRQ
descriptor lock, not a per-port lock, so concurrent modification of
different bits in wakeup_pads is possible.
However wakeup_pads field is typed as u32 but accessed via set_bit() /
clear_bit() / test_bit() which operate on unsigned long pointers. On
64-bit platforms this causes an 8-byte read-modify-write on a 4-byte
field, corrupting the adjacent is_pad_wakeup field.
Change wakeup_pads from u32 to unsigned long to match the bitops API
width requirements.
Also fix the disable path to only clear the wakeup_pads bit when
disable_irq_wake() succeeds, matching the enable path which already
checks the return value. Previously, a failed disable_irq_wake() would
still clear the bit, causing the driver to lose track of the wakeup
source.
Also fix a latent signed-shift bug: the old (1 << i) expression in
mxc_gpio_set_pad_wakeup() has implementation-defined behavior when
i == 31, since 1 is a signed int.
Fixes: f60c9eac54af ("gpio: mxc: enable pad wakeup on i.MX8x platforms")
Assisted-by: LLM
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
drivers/gpio/gpio-mxc.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index e05f276a50e8..8a755ac1af83 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -71,7 +71,7 @@ struct mxc_gpio_port {
u32 both_edges;
struct mxc_gpio_reg_saved gpio_saved_reg;
bool power_off;
- u32 wakeup_pads;
+ unsigned long wakeup_pads;
bool is_pad_wakeup;
u32 pad_type[32];
const struct mxc_gpio_hwdata *hwdata;
@@ -330,13 +330,15 @@ static int gpio_set_wake_irq(struct irq_data *d, u32 enable)
ret = enable_irq_wake(port->irq_high);
else
ret = enable_irq_wake(port->irq);
- port->wakeup_pads |= BIT(gpio_idx);
+ if (!ret)
+ set_bit(gpio_idx, &port->wakeup_pads);
} else {
if (port->irq_high && (gpio_idx >= 16))
ret = disable_irq_wake(port->irq_high);
else
ret = disable_irq_wake(port->irq);
- port->wakeup_pads &= ~BIT(gpio_idx);
+ if (!ret)
+ clear_bit(gpio_idx, &port->wakeup_pads);
}
return ret;
@@ -599,7 +601,7 @@ static bool mxc_gpio_set_pad_wakeup(struct mxc_gpio_port *port, bool enable)
};
for (i = 0; i < 32; i++) {
- if ((port->wakeup_pads & (1 << i))) {
+ if (test_bit(i, &port->wakeup_pads)) {
type = port->pad_type[i];
if (enable)
config = pad_type_map[type];
--
2.51.0
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 3/9] gpio: mxc: cache compatible checks at probe time
2026-10-03 12:06 [PATCH 0/9] gpio: mxc: bug fixes and probe cleanup Peng Fan (OSS)
2026-10-03 12:06 ` [PATCH 1/9] gpio: mxc: fix race between chained IRQ handler install and probe completion Peng Fan (OSS)
2026-10-03 12:06 ` [PATCH 2/9] gpio: mxc: fix wakeup_pads bit operations for correctness Peng Fan (OSS)
@ 2026-10-03 12:06 ` Peng Fan (OSS)
2026-10-03 17:45 ` Andy Shevchenko
2026-10-04 3:06 ` Frank Li
2026-10-03 12:06 ` [PATCH 4/9] gpio: mxc: use devm action for irq_domain cleanup Peng Fan (OSS)
` (5 subsequent siblings)
8 siblings, 2 replies; 20+ messages in thread
From: Peng Fan (OSS) @ 2026-10-03 12:06 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang,
Andy Shevchenko
Cc: linux-gpio, imx, linux-arm-kernel, linux-kernel, Peng Fan
From: Peng Fan <peng.fan@nxp.com>
mxc_gpio_generic_config() and mxc_gpio_set_pad_wakeup() call
of_device_is_compatible() on every invocation to determine pad wakeup
capability and i.MX8QM-specific behavior. These properties are
invariant for the lifetime of the device.
Cache them as bool fields (has_pad_wakeup, is_imx8qm) in mxc_gpio_port
during probe, eliminating repeated device tree string comparisons in
the suspend/resume hot path.
Assisted-by: LLM
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
drivers/gpio/gpio-mxc.c | 24 ++++++++++++++----------
1 file changed, 14 insertions(+), 10 deletions(-)
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index 8a755ac1af83..1c27232f6a80 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -73,6 +73,8 @@ struct mxc_gpio_port {
bool power_off;
unsigned long wakeup_pads;
bool is_pad_wakeup;
+ bool has_pad_wakeup;
+ bool is_imx8qm;
u32 pad_type[32];
const struct mxc_gpio_hwdata *hwdata;
};
@@ -457,6 +459,14 @@ static int mxc_gpio_probe(struct platform_device *pdev)
if (of_device_is_compatible(np, "fsl,imx7d-gpio"))
port->power_off = true;
+ if (of_device_is_compatible(np, "fsl,imx8dxl-gpio") ||
+ of_device_is_compatible(np, "fsl,imx8qxp-gpio") ||
+ of_device_is_compatible(np, "fsl,imx8qm-gpio"))
+ port->has_pad_wakeup = true;
+
+ if (of_device_is_compatible(np, "fsl,imx8qm-gpio"))
+ port->is_imx8qm = true;
+
pm_runtime_get_noresume(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
@@ -570,15 +580,10 @@ static void mxc_gpio_restore_regs(struct mxc_gpio_port *port)
static bool mxc_gpio_generic_config(struct mxc_gpio_port *port,
unsigned int offset, unsigned long conf)
{
- struct device_node *np = port->dev->of_node;
-
- if (of_device_is_compatible(np, "fsl,imx8dxl-gpio") ||
- of_device_is_compatible(np, "fsl,imx8qxp-gpio") ||
- of_device_is_compatible(np, "fsl,imx8qm-gpio"))
- return (gpiochip_generic_config(&port->gen_gc.gc,
- offset, conf) == 0);
+ if (!port->has_pad_wakeup)
+ return false;
- return false;
+ return (gpiochip_generic_config(&port->gen_gc.gc, offset, conf) == 0);
}
static bool mxc_gpio_set_pad_wakeup(struct mxc_gpio_port *port, bool enable)
@@ -586,7 +591,6 @@ static bool mxc_gpio_set_pad_wakeup(struct mxc_gpio_port *port, bool enable)
unsigned long config;
bool ret = false;
int i, type;
- bool is_imx8qm = of_device_is_compatible(port->dev->of_node, "fsl,imx8qm-gpio");
static const u32 pad_type_map[] = {
IMX_SCU_WAKEUP_OFF, /* 0 */
@@ -608,7 +612,7 @@ static bool mxc_gpio_set_pad_wakeup(struct mxc_gpio_port *port, bool enable)
else
config = IMX_SCU_WAKEUP_OFF;
- if (is_imx8qm && config == IMX_SCU_WAKEUP_FALL_EDGE) {
+ if (port->is_imx8qm && config == IMX_SCU_WAKEUP_FALL_EDGE) {
dev_warn_once(port->dev,
"No falling-edge support for wakeup on i.MX8QM\n");
config = IMX_SCU_WAKEUP_OFF;
--
2.51.0
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 4/9] gpio: mxc: use devm action for irq_domain cleanup
2026-10-03 12:06 [PATCH 0/9] gpio: mxc: bug fixes and probe cleanup Peng Fan (OSS)
` (2 preceding siblings ...)
2026-10-03 12:06 ` [PATCH 3/9] gpio: mxc: cache compatible checks at probe time Peng Fan (OSS)
@ 2026-10-03 12:06 ` Peng Fan (OSS)
2026-10-03 17:48 ` Andy Shevchenko
2026-10-04 3:32 ` Frank Li
2026-10-03 12:06 ` [PATCH 5/9] gpio: mxc: use devres-managed PM runtime and dev_err_probe Peng Fan (OSS)
` (4 subsequent siblings)
8 siblings, 2 replies; 20+ messages in thread
From: Peng Fan (OSS) @ 2026-10-03 12:06 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang,
Andy Shevchenko
Cc: linux-gpio, imx, linux-arm-kernel, linux-kernel, Peng Fan
From: Peng Fan <peng.fan@nxp.com>
Replace the manual irq_domain_remove() error path with
devm_add_action_or_reset(), so the IRQ domain is cleaned up
automatically on both probe failure to eliminate the
out_irqdomain_remove goto label.
Assisted-by: LLM
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
drivers/gpio/gpio-mxc.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index 1c27232f6a80..3c395c82d7d4 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -417,6 +417,13 @@ static void mxc_update_irq_chained_handler(struct mxc_gpio_port *port, bool enab
}
}
+static void mxc_gpio_irq_domain_remove(void *data)
+{
+ struct irq_domain *domain = data;
+
+ irq_domain_remove(domain);
+}
+
static int mxc_gpio_probe(struct platform_device *pdev)
{
struct gpio_generic_chip_config config = { };
@@ -526,12 +533,16 @@ static int mxc_gpio_probe(struct platform_device *pdev)
goto out_bgio;
}
+ err = devm_add_action_or_reset(&pdev->dev, mxc_gpio_irq_domain_remove, port->domain);
+ if (err)
+ goto out_bgio;
+
irq_domain_set_pm_device(port->domain, &pdev->dev);
/* gpio-mxc can be a generic irq chip */
err = mxc_gpio_init_gc(port, irq_base);
if (err < 0)
- goto out_irqdomain_remove;
+ goto out_bgio;
list_add_tail(&port->node, &mxc_gpio_ports);
@@ -542,8 +553,6 @@ static int mxc_gpio_probe(struct platform_device *pdev)
return 0;
-out_irqdomain_remove:
- irq_domain_remove(port->domain);
out_bgio:
pm_runtime_disable(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
--
2.51.0
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 5/9] gpio: mxc: use devres-managed PM runtime and dev_err_probe
2026-10-03 12:06 [PATCH 0/9] gpio: mxc: bug fixes and probe cleanup Peng Fan (OSS)
` (3 preceding siblings ...)
2026-10-03 12:06 ` [PATCH 4/9] gpio: mxc: use devm action for irq_domain cleanup Peng Fan (OSS)
@ 2026-10-03 12:06 ` Peng Fan (OSS)
2026-10-03 17:52 ` Andy Shevchenko
2026-10-04 3:00 ` Frank Li
2026-10-03 12:06 ` [PATCH 6/9] gpio: mxc: use local dev variable and device_is_compatible() Peng Fan (OSS)
` (3 subsequent siblings)
8 siblings, 2 replies; 20+ messages in thread
From: Peng Fan (OSS) @ 2026-10-03 12:06 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang,
Andy Shevchenko
Cc: linux-gpio, imx, linux-arm-kernel, linux-kernel, Peng Fan
From: Peng Fan <peng.fan@nxp.com>
Switch pm_runtime_get_noresume() and pm_runtime_enable() to their
devm-managed variants so that pm_runtime_put_noidle() and
pm_runtime_disable() are handled automatically by devres on both
probe failure and device unbind.
Remove the out_bgio goto label and replacing all error paths with
direct returns using dev_err_probe(), which provides better
diagnostic output and handles -EPROBE_DEFER.
Assisted-by: LLM
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
drivers/gpio/gpio-mxc.c | 30 ++++++++++--------------------
1 file changed, 10 insertions(+), 20 deletions(-)
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index 3c395c82d7d4..73e19d2bf235 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -474,9 +474,9 @@ static int mxc_gpio_probe(struct platform_device *pdev)
if (of_device_is_compatible(np, "fsl,imx8qm-gpio"))
port->is_imx8qm = true;
- pm_runtime_get_noresume(&pdev->dev);
+ devm_pm_runtime_get_noresume(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
- pm_runtime_enable(&pdev->dev);
+ devm_pm_runtime_enable(&pdev->dev);
/* disable the interrupt and clear the status */
writel(0, port->base + GPIO_IMR);
@@ -502,7 +502,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
err = gpio_generic_chip_init(&port->gen_gc, &config);
if (err)
- goto out_bgio;
+ return dev_err_probe(&pdev->dev, err, "Failed to init gpio chip\n");
port->gen_gc.gc.request = mxc_gpio_request;
port->gen_gc.gc.free = mxc_gpio_free;
@@ -518,31 +518,27 @@ static int mxc_gpio_probe(struct platform_device *pdev)
err = devm_gpiochip_add_data(&pdev->dev, &port->gen_gc.gc, port);
if (err)
- goto out_bgio;
+ return dev_err_probe(&pdev->dev, err, "Failed to add gpiochip data\n");
irq_base = devm_irq_alloc_descs(&pdev->dev, -1, 0, 32, numa_node_id());
- if (irq_base < 0) {
- err = irq_base;
- goto out_bgio;
- }
+ if (irq_base < 0)
+ return dev_err_probe(&pdev->dev, irq_base, "Failed to alloc irq desc\n");
port->domain = irq_domain_create_legacy(dev_fwnode(&pdev->dev), 32, irq_base, 0,
&irq_domain_simple_ops, NULL);
- if (!port->domain) {
- err = -ENODEV;
- goto out_bgio;
- }
+ if (!port->domain)
+ return dev_err_probe(&pdev->dev, -ENODEV, "Failed to create irq domain\n");
err = devm_add_action_or_reset(&pdev->dev, mxc_gpio_irq_domain_remove, port->domain);
if (err)
- goto out_bgio;
+ return dev_err_probe(&pdev->dev, err, "Failed to add irq_domain_remove\n");
irq_domain_set_pm_device(port->domain, &pdev->dev);
/* gpio-mxc can be a generic irq chip */
err = mxc_gpio_init_gc(port, irq_base);
if (err < 0)
- goto out_bgio;
+ return dev_err_probe(&pdev->dev, err, "Failed mxc_gpio_init_gc\n");
list_add_tail(&port->node, &mxc_gpio_ports);
@@ -552,12 +548,6 @@ static int mxc_gpio_probe(struct platform_device *pdev)
pm_runtime_put_autosuspend(&pdev->dev);
return 0;
-
-out_bgio:
- pm_runtime_disable(&pdev->dev);
- pm_runtime_put_noidle(&pdev->dev);
- dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err);
- return err;
}
static void mxc_gpio_save_regs(struct mxc_gpio_port *port)
--
2.51.0
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 6/9] gpio: mxc: use local dev variable and device_is_compatible()
2026-10-03 12:06 [PATCH 0/9] gpio: mxc: bug fixes and probe cleanup Peng Fan (OSS)
` (4 preceding siblings ...)
2026-10-03 12:06 ` [PATCH 5/9] gpio: mxc: use devres-managed PM runtime and dev_err_probe Peng Fan (OSS)
@ 2026-10-03 12:06 ` Peng Fan (OSS)
2026-10-03 17:54 ` Andy Shevchenko
2026-10-03 12:06 ` [PATCH 7/9] gpio: mxc: introduce MXC_ICR macros and use field_prep/field_get Peng Fan (OSS)
` (2 subsequent siblings)
8 siblings, 1 reply; 20+ messages in thread
From: Peng Fan (OSS) @ 2026-10-03 12:06 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang,
Andy Shevchenko
Cc: linux-gpio, imx, linux-arm-kernel, linux-kernel, Peng Fan
From: Peng Fan <peng.fan@nxp.com>
Introduce a local 'struct device *dev' variable to replace repeated
'&pdev->dev' dereferences throughout mxc_gpio_probe(), improving
readability.
Switch from of_device_is_compatible(np, ...) to the device-model
device_is_compatible(dev, ...) API which works with both DT and ACPI
firmware backends. The 'np' variable is retained for
of_alias_get_id() which has no device-model equivalent.
No functional change.
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
drivers/gpio/gpio-mxc.c | 53 +++++++++++++++++++++++++------------------------
1 file changed, 27 insertions(+), 26 deletions(-)
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index 73e19d2bf235..a3274be7126a 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -428,17 +428,18 @@ static int mxc_gpio_probe(struct platform_device *pdev)
{
struct gpio_generic_chip_config config = { };
struct device_node *np = pdev->dev.of_node;
+ struct device *dev = &pdev->dev;
struct mxc_gpio_port *port;
int irq_count;
int irq_base;
int err;
- port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL);
+ port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
if (!port)
return -ENOMEM;
- port->dev = &pdev->dev;
- port->hwdata = device_get_match_data(&pdev->dev);
+ port->dev = dev;
+ port->hwdata = device_get_match_data(dev);
port->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(port->base))
@@ -459,30 +460,30 @@ static int mxc_gpio_probe(struct platform_device *pdev)
return port->irq;
/* the controller clock is optional */
- port->clk = devm_clk_get_optional_enabled(&pdev->dev, NULL);
+ port->clk = devm_clk_get_optional_enabled(dev, NULL);
if (IS_ERR(port->clk))
return PTR_ERR(port->clk);
- if (of_device_is_compatible(np, "fsl,imx7d-gpio"))
+ if (device_is_compatible(dev, "fsl,imx7d-gpio"))
port->power_off = true;
- if (of_device_is_compatible(np, "fsl,imx8dxl-gpio") ||
- of_device_is_compatible(np, "fsl,imx8qxp-gpio") ||
- of_device_is_compatible(np, "fsl,imx8qm-gpio"))
+ if (device_is_compatible(dev, "fsl,imx8dxl-gpio") ||
+ device_is_compatible(dev, "fsl,imx8qxp-gpio") ||
+ device_is_compatible(dev, "fsl,imx8qm-gpio"))
port->has_pad_wakeup = true;
- if (of_device_is_compatible(np, "fsl,imx8qm-gpio"))
+ if (device_is_compatible(dev, "fsl,imx8qm-gpio"))
port->is_imx8qm = true;
- devm_pm_runtime_get_noresume(&pdev->dev);
- pm_runtime_set_active(&pdev->dev);
- devm_pm_runtime_enable(&pdev->dev);
+ devm_pm_runtime_get_noresume(dev);
+ pm_runtime_set_active(dev);
+ devm_pm_runtime_enable(dev);
/* disable the interrupt and clear the status */
writel(0, port->base + GPIO_IMR);
writel(~0, port->base + GPIO_ISR);
- if (of_device_is_compatible(np, "fsl,imx21-gpio")) {
+ if (device_is_compatible(dev, "fsl,imx21-gpio")) {
/*
* Setup one handler for all GPIO interrupts. Actually setting
* the handler is needed only once, but doing it for every port
@@ -493,7 +494,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
} else
port->mx_irq_handler = mx3_gpio_irq_handler;
- config.dev = &pdev->dev;
+ config.dev = dev;
config.sz = 4;
config.dat = port->base + GPIO_PSR;
config.set = port->base + GPIO_DR;
@@ -502,7 +503,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
err = gpio_generic_chip_init(&port->gen_gc, &config);
if (err)
- return dev_err_probe(&pdev->dev, err, "Failed to init gpio chip\n");
+ return dev_err_probe(dev, err, "Failed to init gpio chip\n");
port->gen_gc.gc.request = mxc_gpio_request;
port->gen_gc.gc.free = mxc_gpio_free;
@@ -516,36 +517,36 @@ static int mxc_gpio_probe(struct platform_device *pdev)
else /* silence boot time warning */
port->gen_gc.gc.base = -1;
- err = devm_gpiochip_add_data(&pdev->dev, &port->gen_gc.gc, port);
+ err = devm_gpiochip_add_data(dev, &port->gen_gc.gc, port);
if (err)
- return dev_err_probe(&pdev->dev, err, "Failed to add gpiochip data\n");
+ return dev_err_probe(dev, err, "Failed to add gpiochip data\n");
- irq_base = devm_irq_alloc_descs(&pdev->dev, -1, 0, 32, numa_node_id());
+ irq_base = devm_irq_alloc_descs(dev, -1, 0, 32, numa_node_id());
if (irq_base < 0)
- return dev_err_probe(&pdev->dev, irq_base, "Failed to alloc irq desc\n");
+ return dev_err_probe(dev, irq_base, "Failed to alloc irq desc\n");
- port->domain = irq_domain_create_legacy(dev_fwnode(&pdev->dev), 32, irq_base, 0,
+ port->domain = irq_domain_create_legacy(dev_fwnode(dev), 32, irq_base, 0,
&irq_domain_simple_ops, NULL);
if (!port->domain)
- return dev_err_probe(&pdev->dev, -ENODEV, "Failed to create irq domain\n");
+ return dev_err_probe(dev, -ENODEV, "Failed to create irq domain\n");
- err = devm_add_action_or_reset(&pdev->dev, mxc_gpio_irq_domain_remove, port->domain);
+ err = devm_add_action_or_reset(dev, mxc_gpio_irq_domain_remove, port->domain);
if (err)
- return dev_err_probe(&pdev->dev, err, "Failed to add irq_domain_remove\n");
+ return dev_err_probe(dev, err, "Failed to add irq_domain_remove\n");
- irq_domain_set_pm_device(port->domain, &pdev->dev);
+ irq_domain_set_pm_device(port->domain, dev);
/* gpio-mxc can be a generic irq chip */
err = mxc_gpio_init_gc(port, irq_base);
if (err < 0)
- return dev_err_probe(&pdev->dev, err, "Failed mxc_gpio_init_gc\n");
+ return dev_err_probe(dev, err, "Failed mxc_gpio_init_gc\n");
list_add_tail(&port->node, &mxc_gpio_ports);
mxc_update_irq_chained_handler(port, true);
platform_set_drvdata(pdev, port);
- pm_runtime_put_autosuspend(&pdev->dev);
+ pm_runtime_put_autosuspend(dev);
return 0;
}
--
2.51.0
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 7/9] gpio: mxc: introduce MXC_ICR macros and use field_prep/field_get
2026-10-03 12:06 [PATCH 0/9] gpio: mxc: bug fixes and probe cleanup Peng Fan (OSS)
` (5 preceding siblings ...)
2026-10-03 12:06 ` [PATCH 6/9] gpio: mxc: use local dev variable and device_is_compatible() Peng Fan (OSS)
@ 2026-10-03 12:06 ` Peng Fan (OSS)
2026-10-03 12:06 ` [PATCH 8/9] gpio: mxc: use BIT() macro for single-bit operations Peng Fan (OSS)
2026-10-03 12:06 ` [PATCH 9/9] gpio: mxc: simplify gpio_set_wake_irq() with irq_set_irq_wake and assign_bit Peng Fan (OSS)
8 siblings, 0 replies; 20+ messages in thread
From: Peng Fan (OSS) @ 2026-10-03 12:06 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang,
Andy Shevchenko
Cc: linux-gpio, imx, linux-arm-kernel, linux-kernel, Peng Fan
From: Peng Fan <peng.fan@nxp.com>
Both gpio_set_irq_type() and mxc_flip_edge() open-code the same ICR
register selection and 2-bit field shift/mask arithmetic with magic
numbers (0x10, 0xf, 0x3).
Introduce two macros:
- MXC_ICR_REG(gpio): selects ICR1 (pins 0-15) or ICR2 (pins 16-31)
- MXC_ICR_MASK(gpio): 2-bit mask at the correct position
Use field_prep() and field_get() from linux/bitfield.h for the
shift/extract operations instead of open-coded shifts. The lowercase
variants accept runtime-computed masks.
Eliminate the intermediate 'bit' variable from both functions and
makes the register access pattern self-documenting.
No functional change.
Assisted-by: LLM
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
drivers/gpio/gpio-mxc.c | 24 +++++++++++++-----------
1 file changed, 13 insertions(+), 11 deletions(-)
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index a3274be7126a..18ff33a0abfb 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -7,6 +7,7 @@
// Authors: Daniel Mack, Juergen Beisert.
// Copyright (C) 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+#include <linux/bitfield.h>
#include <linux/cleanup.h>
#include <linux/clk.h>
#include <linux/err.h>
@@ -139,6 +140,9 @@ static struct mxc_gpio_hwdata imx35_gpio_hwdata = {
#define GPIO_INT_FALL_EDGE (port->hwdata->fall_edge)
#define GPIO_INT_BOTH_EDGES 0x4
+#define MXC_ICR_REG(gpio) (GPIO_ICR1 + (((gpio) & 0x10) >> 2))
+#define MXC_ICR_MASK(gpio) (0x3 << (((gpio) & 0xf) << 1))
+
static const struct of_device_id mxc_gpio_dt_ids[] = {
{ .compatible = "fsl,imx1-gpio", .data = &imx1_imx21_gpio_hwdata },
{ .compatible = "fsl,imx21-gpio", .data = &imx1_imx21_gpio_hwdata },
@@ -165,7 +169,7 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct mxc_gpio_port *port = gc->private;
- u32 bit, val;
+ u32 val;
u32 gpio_idx = d->hwirq;
int edge;
void __iomem *reg = port->base;
@@ -215,10 +219,9 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
}
if (edge != GPIO_INT_BOTH_EDGES) {
- reg += GPIO_ICR1 + ((gpio_idx & 0x10) >> 2); /* lower or upper register */
- bit = gpio_idx & 0xf;
- val = readl(reg) & ~(0x3 << (bit << 1));
- writel(val | (edge << (bit << 1)), reg);
+ reg += MXC_ICR_REG(gpio_idx);
+ val = readl(reg) & ~MXC_ICR_MASK(gpio_idx);
+ writel(val | field_prep(MXC_ICR_MASK(gpio_idx), edge), reg);
}
writel(1 << gpio_idx, port->base + GPIO_ISR);
@@ -231,16 +234,15 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio)
{
void __iomem *reg = port->base;
- u32 bit, val;
+ u32 val;
int edge;
guard(gpio_generic_lock_irqsave)(&port->gen_gc);
- reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */
- bit = gpio & 0xf;
+ reg += MXC_ICR_REG(gpio);
val = readl(reg);
- edge = (val >> (bit << 1)) & 3;
- val &= ~(0x3 << (bit << 1));
+ edge = field_get(MXC_ICR_MASK(gpio), val);
+ val &= ~MXC_ICR_MASK(gpio);
if (edge == GPIO_INT_HIGH_LEV) {
edge = GPIO_INT_LOW_LEV;
pr_debug("mxc: switch GPIO %d to low trigger\n", gpio);
@@ -252,7 +254,7 @@ static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio)
gpio, edge);
return;
}
- writel(val | (edge << (bit << 1)), reg);
+ writel(val | field_prep(MXC_ICR_MASK(gpio), edge), reg);
}
/* handle 32 interrupts in one status register */
--
2.51.0
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 8/9] gpio: mxc: use BIT() macro for single-bit operations
2026-10-03 12:06 [PATCH 0/9] gpio: mxc: bug fixes and probe cleanup Peng Fan (OSS)
` (6 preceding siblings ...)
2026-10-03 12:06 ` [PATCH 7/9] gpio: mxc: introduce MXC_ICR macros and use field_prep/field_get Peng Fan (OSS)
@ 2026-10-03 12:06 ` Peng Fan (OSS)
2026-10-03 12:06 ` [PATCH 9/9] gpio: mxc: simplify gpio_set_wake_irq() with irq_set_irq_wake and assign_bit Peng Fan (OSS)
8 siblings, 0 replies; 20+ messages in thread
From: Peng Fan (OSS) @ 2026-10-03 12:06 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang,
Andy Shevchenko
Cc: linux-gpio, imx, linux-arm-kernel, linux-kernel, Peng Fan
From: Peng Fan <peng.fan@nxp.com>
Replace open-coded '1 << n' shifts with the BIT() macro throughout
the driver for consistency and to avoid potential signed-shift issues
when the bit index is 31 (1 << 31 is implementation-defined for
signed int).
No functional change.
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
drivers/gpio/gpio-mxc.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index 18ff33a0abfb..bf1207f30460 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -174,7 +174,7 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
int edge;
void __iomem *reg = port->base;
- port->both_edges &= ~(1 << gpio_idx);
+ port->both_edges &= ~BIT(gpio_idx);
switch (type) {
case IRQ_TYPE_EDGE_RISING:
edge = GPIO_INT_RISE_EDGE;
@@ -194,7 +194,7 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
edge = GPIO_INT_HIGH_LEV;
pr_debug("mxc: set GPIO %d to high trigger\n", gpio_idx);
}
- port->both_edges |= 1 << gpio_idx;
+ port->both_edges |= BIT(gpio_idx);
}
break;
case IRQ_TYPE_LEVEL_LOW:
@@ -211,10 +211,10 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
if (GPIO_EDGE_SEL >= 0) {
val = readl(port->base + GPIO_EDGE_SEL);
if (edge == GPIO_INT_BOTH_EDGES)
- writel(val | (1 << gpio_idx),
+ writel(val | BIT(gpio_idx),
port->base + GPIO_EDGE_SEL);
else
- writel(val & ~(1 << gpio_idx),
+ writel(val & ~BIT(gpio_idx),
port->base + GPIO_EDGE_SEL);
}
@@ -224,7 +224,7 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
writel(val | field_prep(MXC_ICR_MASK(gpio_idx), edge), reg);
}
- writel(1 << gpio_idx, port->base + GPIO_ISR);
+ writel(BIT(gpio_idx), port->base + GPIO_ISR);
port->pad_type[gpio_idx] = type;
}
@@ -263,12 +263,12 @@ static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat)
while (irq_stat != 0) {
int irqoffset = fls(irq_stat) - 1;
- if (port->both_edges & (1 << irqoffset))
+ if (port->both_edges & BIT(irqoffset))
mxc_flip_edge(port, irqoffset);
generic_handle_domain_irq(port->domain, irqoffset);
- irq_stat &= ~(1 << irqoffset);
+ irq_stat &= ~BIT(irqoffset);
}
}
--
2.51.0
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 9/9] gpio: mxc: simplify gpio_set_wake_irq() with irq_set_irq_wake and assign_bit
2026-10-03 12:06 [PATCH 0/9] gpio: mxc: bug fixes and probe cleanup Peng Fan (OSS)
` (7 preceding siblings ...)
2026-10-03 12:06 ` [PATCH 8/9] gpio: mxc: use BIT() macro for single-bit operations Peng Fan (OSS)
@ 2026-10-03 12:06 ` Peng Fan (OSS)
2026-10-03 17:59 ` Andy Shevchenko
8 siblings, 1 reply; 20+ messages in thread
From: Peng Fan (OSS) @ 2026-10-03 12:06 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang,
Andy Shevchenko
Cc: linux-gpio, imx, linux-arm-kernel, linux-kernel, Peng Fan
From: Peng Fan <peng.fan@nxp.com>
To simplify gpio_set_wake_irq():
- Replace the enable/disable_irq_wake() if/else branches with a single
irq_set_irq_wake() call which handles both directions internally.
- Replace the separate set_bit()/clear_bit() calls with assign_bit()
which sets or clears the bit based on the enable parameter.
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
drivers/gpio/gpio-mxc.c | 22 +++++++---------------
1 file changed, 7 insertions(+), 15 deletions(-)
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index bf1207f30460..546a46857e1d 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -329,21 +329,13 @@ static int gpio_set_wake_irq(struct irq_data *d, u32 enable)
u32 gpio_idx = d->hwirq;
int ret;
- if (enable) {
- if (port->irq_high && (gpio_idx >= 16))
- ret = enable_irq_wake(port->irq_high);
- else
- ret = enable_irq_wake(port->irq);
- if (!ret)
- set_bit(gpio_idx, &port->wakeup_pads);
- } else {
- if (port->irq_high && (gpio_idx >= 16))
- ret = disable_irq_wake(port->irq_high);
- else
- ret = disable_irq_wake(port->irq);
- if (!ret)
- clear_bit(gpio_idx, &port->wakeup_pads);
- }
+ if (port->irq_high && (gpio_idx >= 16))
+ ret = irq_set_irq_wake(port->irq_high, enable);
+ else
+ ret = irq_set_irq_wake(port->irq, enable);
+
+ if (!ret)
+ assign_bit(gpio_idx, &port->wakeup_pads, enable);
return ret;
}
--
2.51.0
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/9] gpio: mxc: fix race between chained IRQ handler install and probe completion
2026-10-03 12:06 ` [PATCH 1/9] gpio: mxc: fix race between chained IRQ handler install and probe completion Peng Fan (OSS)
@ 2026-10-03 17:35 ` Andy Shevchenko
0 siblings, 0 replies; 20+ messages in thread
From: Andy Shevchenko @ 2026-10-03 17:35 UTC (permalink / raw)
To: Peng Fan (OSS)
Cc: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang, linux-gpio,
imx, linux-arm-kernel, linux-kernel, Peng Fan
On Sat, Oct 3, 2026 at 3:09 PM Peng Fan (OSS) <peng.fan@oss.nxp.com> wrote:
> mxc_update_irq_chained_handler() is called before the IRQ domain, the
> generic IRQ chip, and the port list entry are set up. If an interrupt
> arrives in that window:
>
> - mx3_gpio_irq_handler() calls generic_handle_domain_irq() with
> port->domain still NULL.
> - mx2_gpio_irq_handler() walks mxc_gpio_ports, but the port has not
> been added to the list yet.
>
> Additionally, if any of the subsequent probe steps (gpio_generic_chip_init,
> devm_gpiochip_add_data, irq_domain_create_legacy, or mxc_gpio_init_gc)
We refer to the functions as func(), like you have done above, but here...
(No need to resend just for this.)
> fail, the error paths never unregister the chained handler, leaving a
> dangling handler that points at freed memory.
>
> Move the handler installation after all its dependencies are ready and
> after list_add_tail(), so the handler is never live while the data
> structures it touches are incomplete, and is never installed if probe
> fails.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 2/9] gpio: mxc: fix wakeup_pads bit operations for correctness
2026-10-03 12:06 ` [PATCH 2/9] gpio: mxc: fix wakeup_pads bit operations for correctness Peng Fan (OSS)
@ 2026-10-03 17:41 ` Andy Shevchenko
0 siblings, 0 replies; 20+ messages in thread
From: Andy Shevchenko @ 2026-10-03 17:41 UTC (permalink / raw)
To: Peng Fan (OSS)
Cc: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang, linux-gpio,
imx, linux-arm-kernel, linux-kernel, Peng Fan
On Sat, Oct 3, 2026 at 3:09 PM Peng Fan (OSS) <peng.fan@oss.nxp.com> wrote:
> Replace the open-coded BIT() / mask operations with the atomic
> set_bit() / clear_bit() / test_bit() API. Atomic variants are required
> because gpio_set_wake_irq() can be called concurrently for different
> pins on the same port - irq_set_irq_wake() only holds the per-IRQ
> descriptor lock, not a per-port lock, so concurrent modification of
> different bits in wakeup_pads is possible.
>
> However wakeup_pads field is typed as u32 but accessed via set_bit() /
> clear_bit() / test_bit() which operate on unsigned long pointers. On
> 64-bit platforms this causes an 8-byte read-modify-write on a 4-byte
> field, corrupting the adjacent is_pad_wakeup field.
>
> Change wakeup_pads from u32 to unsigned long to match the bitops API
> width requirements.
>
> Also fix the disable path to only clear the wakeup_pads bit when
> disable_irq_wake() succeeds, matching the enable path which already
> checks the return value. Previously, a failed disable_irq_wake() would
> still clear the bit, causing the driver to lose track of the wakeup
> source.
The above is too verbose, try to squeeze it to the point.
> Also fix a latent signed-shift bug: the old (1 << i) expression in
> mxc_gpio_set_pad_wakeup() has implementation-defined behavior when
> i == 31, since 1 is a signed int.
Too many words for a simple (non-critical) update.
...
> struct mxc_gpio_port {
> u32 both_edges;
> struct mxc_gpio_reg_saved gpio_saved_reg;
> bool power_off;
> - u32 wakeup_pads;
> + unsigned long wakeup_pads;
> bool is_pad_wakeup;
> u32 pad_type[32];
> const struct mxc_gpio_hwdata *hwdata;
While at it, run `pahole` and update the arrangement (of the members
you touched here) accordingly.
...
> static int gpio_set_wake_irq(struct irq_data *d, u32 enable)
> ret = enable_irq_wake(port->irq_high);
> else
> ret = enable_irq_wake(port->irq);
> - port->wakeup_pads |= BIT(gpio_idx);
> + if (!ret)
> + set_bit(gpio_idx, &port->wakeup_pads);
> } else {
> if (port->irq_high && (gpio_idx >= 16))
> ret = disable_irq_wake(port->irq_high);
> else
> ret = disable_irq_wake(port->irq);
> - port->wakeup_pads &= ~BIT(gpio_idx);
> + if (!ret)
> + clear_bit(gpio_idx, &port->wakeup_pads);
> }
>
> return ret;
Instead do the following after the if (enable) {} else {} block, namely
if (ret)
return ret;
assign_bit(..., enable)
return 0;
...
> static bool mxc_gpio_set_pad_wakeup(struct mxc_gpio_port *port, bool enable)
> for (i = 0; i < 32; i++) {
> - if ((port->wakeup_pads & (1 << i))) {
> + if (test_bit(i, &port->wakeup_pads)) {
Instead just start using for_each_set_bits() from bitops.h.
> type = port->pad_type[i];
> if (enable)
> config = pad_type_map[type];
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 3/9] gpio: mxc: cache compatible checks at probe time
2026-10-03 12:06 ` [PATCH 3/9] gpio: mxc: cache compatible checks at probe time Peng Fan (OSS)
@ 2026-10-03 17:45 ` Andy Shevchenko
2026-10-04 3:06 ` Frank Li
1 sibling, 0 replies; 20+ messages in thread
From: Andy Shevchenko @ 2026-10-03 17:45 UTC (permalink / raw)
To: Peng Fan (OSS)
Cc: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang, linux-gpio,
imx, linux-arm-kernel, linux-kernel, Peng Fan
On Sat, Oct 3, 2026 at 3:09 PM Peng Fan (OSS) <peng.fan@oss.nxp.com> wrote:
> mxc_gpio_generic_config() and mxc_gpio_set_pad_wakeup() call
> of_device_is_compatible() on every invocation to determine pad wakeup
> capability and i.MX8QM-specific behavior. These properties are
> invariant for the lifetime of the device.
>
> Cache them as bool fields (has_pad_wakeup, is_imx8qm) in mxc_gpio_port
> during probe, eliminating repeated device tree string comparisons in
> the suspend/resume hot path.
...
> {
> - struct device_node *np = port->dev->of_node;
> -
> - if (of_device_is_compatible(np, "fsl,imx8dxl-gpio") ||
> - of_device_is_compatible(np, "fsl,imx8qxp-gpio") ||
> - of_device_is_compatible(np, "fsl,imx8qm-gpio"))
> - return (gpiochip_generic_config(&port->gen_gc.gc,
> - offset, conf) == 0);
> + if (!port->has_pad_wakeup)
> + return false;
>
> - return false;
> + return (gpiochip_generic_config(&port->gen_gc.gc, offset, conf) == 0);
Too many parentheses, also the semantic of 0 is not obvious. Better,
for example, this one
int ret;
...
ret = gpiochip_generic_config(...);
if (ret)
return false;
return true;
> }
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 4/9] gpio: mxc: use devm action for irq_domain cleanup
2026-10-03 12:06 ` [PATCH 4/9] gpio: mxc: use devm action for irq_domain cleanup Peng Fan (OSS)
@ 2026-10-03 17:48 ` Andy Shevchenko
2026-10-04 3:32 ` Frank Li
1 sibling, 0 replies; 20+ messages in thread
From: Andy Shevchenko @ 2026-10-03 17:48 UTC (permalink / raw)
To: Peng Fan (OSS)
Cc: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang, linux-gpio,
imx, linux-arm-kernel, linux-kernel, Peng Fan
On Sat, Oct 3, 2026 at 3:09 PM Peng Fan (OSS) <peng.fan@oss.nxp.com> wrote:
> Replace the manual irq_domain_remove() error path with
> devm_add_action_or_reset(), so the IRQ domain is cleaned up
> automatically on both probe failure to eliminate the
> out_irqdomain_remove goto label.
...
> + err = devm_add_action_or_reset(&pdev->dev, mxc_gpio_irq_domain_remove, port->domain);
> + if (err)
> + goto out_bgio;
> +
We have devm_irq_domain_instantiate() and the respective wrappers.
...
> /* gpio-mxc can be a generic irq chip */
> err = mxc_gpio_init_gc(port, irq_base);
> if (err < 0)
> - goto out_irqdomain_remove;
> + goto out_bgio;
This is simply wrong. No devm_*() call should be followed by goto.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 5/9] gpio: mxc: use devres-managed PM runtime and dev_err_probe
2026-10-03 12:06 ` [PATCH 5/9] gpio: mxc: use devres-managed PM runtime and dev_err_probe Peng Fan (OSS)
@ 2026-10-03 17:52 ` Andy Shevchenko
2026-10-04 3:00 ` Frank Li
1 sibling, 0 replies; 20+ messages in thread
From: Andy Shevchenko @ 2026-10-03 17:52 UTC (permalink / raw)
To: Peng Fan (OSS)
Cc: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang, linux-gpio,
imx, linux-arm-kernel, linux-kernel, Peng Fan
On Sat, Oct 3, 2026 at 3:09 PM Peng Fan (OSS) <peng.fan@oss.nxp.com> wrote:
> Switch pm_runtime_get_noresume() and pm_runtime_enable() to their
> devm-managed variants so that pm_runtime_put_noidle() and
> pm_runtime_disable() are handled automatically by devres on both
> probe failure and device unbind.
>
> Remove the out_bgio goto label and replacing all error paths with
replace
> direct returns using dev_err_probe(), which provides better
> diagnostic output and handles -EPROBE_DEFER.
...
> - pm_runtime_get_noresume(&pdev->dev);
> + devm_pm_runtime_get_noresume(&pdev->dev);
> pm_runtime_set_active(&pdev->dev);
> - pm_runtime_enable(&pdev->dev);
> + devm_pm_runtime_enable(&pdev->dev);
Definitely not. There is little point to using devm_*() if you don't
check the return value.
...
> err = gpio_generic_chip_init(&port->gen_gc, &config);
> if (err)
> - goto out_bgio;
> + return dev_err_probe(&pdev->dev, err, "Failed to init gpio chip\n");
> err = devm_gpiochip_add_data(&pdev->dev, &port->gen_gc.gc, port);
> if (err)
> - goto out_bgio;
> + return dev_err_probe(&pdev->dev, err, "Failed to add gpiochip data\n");
These (and more) don't belong to the change — split it to the
logically isolated ones.
One patch for dev_err_probe() and another for PM calls.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 6/9] gpio: mxc: use local dev variable and device_is_compatible()
2026-10-03 12:06 ` [PATCH 6/9] gpio: mxc: use local dev variable and device_is_compatible() Peng Fan (OSS)
@ 2026-10-03 17:54 ` Andy Shevchenko
0 siblings, 0 replies; 20+ messages in thread
From: Andy Shevchenko @ 2026-10-03 17:54 UTC (permalink / raw)
To: Peng Fan (OSS)
Cc: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang, linux-gpio,
imx, linux-arm-kernel, linux-kernel, Peng Fan
On Sat, Oct 3, 2026 at 3:10 PM Peng Fan (OSS) <peng.fan@oss.nxp.com> wrote:
>
> From: Peng Fan <peng.fan@nxp.com>
>
> Introduce a local 'struct device *dev' variable to replace repeated
> '&pdev->dev' dereferences throughout mxc_gpio_probe(), improving
> readability.
>
> Switch from of_device_is_compatible(np, ...) to the device-model
> device_is_compatible(dev, ...) API which works with both DT and ACPI
> firmware backends. The 'np' variable is retained for
> of_alias_get_id() which has no device-model equivalent.
>
> No functional change.
> --- a/drivers/gpio/gpio-mxc.c
> +++ b/drivers/gpio/gpio-mxc.c
> @@ -428,17 +428,18 @@ static int mxc_gpio_probe(struct platform_device *pdev)
It seems you missed updating the headers (like switching from of.h to
property.h). Other than that, it looks good.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 9/9] gpio: mxc: simplify gpio_set_wake_irq() with irq_set_irq_wake and assign_bit
2026-10-03 12:06 ` [PATCH 9/9] gpio: mxc: simplify gpio_set_wake_irq() with irq_set_irq_wake and assign_bit Peng Fan (OSS)
@ 2026-10-03 17:59 ` Andy Shevchenko
0 siblings, 0 replies; 20+ messages in thread
From: Andy Shevchenko @ 2026-10-03 17:59 UTC (permalink / raw)
To: Peng Fan (OSS)
Cc: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang, linux-gpio,
imx, linux-arm-kernel, linux-kernel, Peng Fan
On Sat, Oct 3, 2026 at 3:10 PM Peng Fan (OSS) <peng.fan@oss.nxp.com> wrote:
>
> To simplify gpio_set_wake_irq():
> - Replace the enable/disable_irq_wake() if/else branches with a single
> irq_set_irq_wake() call which handles both directions internally.
> - Replace the separate set_bit()/clear_bit() calls with assign_bit()
> which sets or clears the bit based on the enable parameter.
...
> - if (enable) {
> - if (port->irq_high && (gpio_idx >= 16))
> - ret = enable_irq_wake(port->irq_high);
> - else
> - ret = enable_irq_wake(port->irq);
> - if (!ret)
> - set_bit(gpio_idx, &port->wakeup_pads);
> - } else {
> - if (port->irq_high && (gpio_idx >= 16))
> - ret = disable_irq_wake(port->irq_high);
> - else
> - ret = disable_irq_wake(port->irq);
> - if (!ret)
> - clear_bit(gpio_idx, &port->wakeup_pads);
> - }
> + if (port->irq_high && (gpio_idx >= 16))
> + ret = irq_set_irq_wake(port->irq_high, enable);
> + else
> + ret = irq_set_irq_wake(port->irq, enable);
> + if (!ret)
> + assign_bit(gpio_idx, &port->wakeup_pads, enable);
>
> return ret;
This uses an unusual pattern, we check for the error first.
But also this part should not be ping-ponged over the series, it
should be from the start like this, see my comment against the
respective patch.
> }
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 5/9] gpio: mxc: use devres-managed PM runtime and dev_err_probe
2026-10-03 12:06 ` [PATCH 5/9] gpio: mxc: use devres-managed PM runtime and dev_err_probe Peng Fan (OSS)
2026-10-03 17:52 ` Andy Shevchenko
@ 2026-10-04 3:00 ` Frank Li
1 sibling, 0 replies; 20+ messages in thread
From: Frank Li @ 2026-10-04 3:00 UTC (permalink / raw)
To: Peng Fan (OSS)
Cc: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang,
Andy Shevchenko, linux-gpio, imx, linux-arm-kernel, linux-kernel,
Peng Fan
On Sat, Oct 03, 2026 at 08:06:47PM +0800, Peng Fan (OSS) wrote:
> From: Peng Fan <peng.fan@nxp.com>
>
> Switch pm_runtime_get_noresume() and pm_runtime_enable() to their
> devm-managed variants so that pm_runtime_put_noidle() and
> pm_runtime_disable() are handled automatically by devres on both
> probe failure and device unbind.
>
> Remove the out_bgio goto label and replacing all error paths with
> direct returns using dev_err_probe(), which provides better
> diagnostic output and handles -EPROBE_DEFER.
>
> Assisted-by: LLM
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> ---
> drivers/gpio/gpio-mxc.c | 30 ++++++++++--------------------
> 1 file changed, 10 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
> index 3c395c82d7d4..73e19d2bf235 100644
> --- a/drivers/gpio/gpio-mxc.c
> +++ b/drivers/gpio/gpio-mxc.c
> @@ -474,9 +474,9 @@ static int mxc_gpio_probe(struct platform_device *pdev)
> if (of_device_is_compatible(np, "fsl,imx8qm-gpio"))
> port->is_imx8qm = true;
>
> - pm_runtime_get_noresume(&pdev->dev);
> + devm_pm_runtime_get_noresume(&pdev->dev);
> pm_runtime_set_active(&pdev->dev);
> - pm_runtime_enable(&pdev->dev);
> + devm_pm_runtime_enable(&pdev->dev);
devm_pm_runtime_set_active_enabled() can include pm_runtime_set_active()
and need check return value here.
And why call pm_runtime_get_noresume() before enable()?
Frank
>
> /* disable the interrupt and clear the status */
> writel(0, port->base + GPIO_IMR);
> @@ -502,7 +502,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
>
> err = gpio_generic_chip_init(&port->gen_gc, &config);
> if (err)
> - goto out_bgio;
> + return dev_err_probe(&pdev->dev, err, "Failed to init gpio chip\n");
>
> port->gen_gc.gc.request = mxc_gpio_request;
> port->gen_gc.gc.free = mxc_gpio_free;
> @@ -518,31 +518,27 @@ static int mxc_gpio_probe(struct platform_device *pdev)
>
> err = devm_gpiochip_add_data(&pdev->dev, &port->gen_gc.gc, port);
> if (err)
> - goto out_bgio;
> + return dev_err_probe(&pdev->dev, err, "Failed to add gpiochip data\n");
>
> irq_base = devm_irq_alloc_descs(&pdev->dev, -1, 0, 32, numa_node_id());
> - if (irq_base < 0) {
> - err = irq_base;
> - goto out_bgio;
> - }
> + if (irq_base < 0)
> + return dev_err_probe(&pdev->dev, irq_base, "Failed to alloc irq desc\n");
>
> port->domain = irq_domain_create_legacy(dev_fwnode(&pdev->dev), 32, irq_base, 0,
> &irq_domain_simple_ops, NULL);
> - if (!port->domain) {
> - err = -ENODEV;
> - goto out_bgio;
> - }
> + if (!port->domain)
> + return dev_err_probe(&pdev->dev, -ENODEV, "Failed to create irq domain\n");
>
> err = devm_add_action_or_reset(&pdev->dev, mxc_gpio_irq_domain_remove, port->domain);
> if (err)
> - goto out_bgio;
> + return dev_err_probe(&pdev->dev, err, "Failed to add irq_domain_remove\n");
>
> irq_domain_set_pm_device(port->domain, &pdev->dev);
>
> /* gpio-mxc can be a generic irq chip */
> err = mxc_gpio_init_gc(port, irq_base);
> if (err < 0)
> - goto out_bgio;
> + return dev_err_probe(&pdev->dev, err, "Failed mxc_gpio_init_gc\n");
>
> list_add_tail(&port->node, &mxc_gpio_ports);
>
> @@ -552,12 +548,6 @@ static int mxc_gpio_probe(struct platform_device *pdev)
> pm_runtime_put_autosuspend(&pdev->dev);
>
> return 0;
> -
> -out_bgio:
> - pm_runtime_disable(&pdev->dev);
> - pm_runtime_put_noidle(&pdev->dev);
> - dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err);
> - return err;
> }
>
> static void mxc_gpio_save_regs(struct mxc_gpio_port *port)
>
> --
> 2.51.0
>
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 3/9] gpio: mxc: cache compatible checks at probe time
2026-10-03 12:06 ` [PATCH 3/9] gpio: mxc: cache compatible checks at probe time Peng Fan (OSS)
2026-10-03 17:45 ` Andy Shevchenko
@ 2026-10-04 3:06 ` Frank Li
1 sibling, 0 replies; 20+ messages in thread
From: Frank Li @ 2026-10-04 3:06 UTC (permalink / raw)
To: Peng Fan (OSS)
Cc: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang,
Andy Shevchenko, linux-gpio, imx, linux-arm-kernel, linux-kernel,
Peng Fan
On Sat, Oct 03, 2026 at 08:06:45PM +0800, Peng Fan (OSS) wrote:
> From: Peng Fan <peng.fan@nxp.com>
>
> mxc_gpio_generic_config() and mxc_gpio_set_pad_wakeup() call
> of_device_is_compatible() on every invocation to determine pad wakeup
> capability and i.MX8QM-specific behavior. These properties are
> invariant for the lifetime of the device.
>
> Cache them as bool fields (has_pad_wakeup, is_imx8qm) in mxc_gpio_port
> during probe, eliminating repeated device tree string comparisons in
> the suspend/resume hot path.
>
> Assisted-by: LLM
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> ---
> drivers/gpio/gpio-mxc.c | 24 ++++++++++++++----------
> 1 file changed, 14 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
> index 8a755ac1af83..1c27232f6a80 100644
> --- a/drivers/gpio/gpio-mxc.c
> +++ b/drivers/gpio/gpio-mxc.c
> @@ -73,6 +73,8 @@ struct mxc_gpio_port {
> bool power_off;
> unsigned long wakeup_pads;
> bool is_pad_wakeup;
> + bool has_pad_wakeup;
> + bool is_imx8qm;
> u32 pad_type[32];
> const struct mxc_gpio_hwdata *hwdata;
> };
> @@ -457,6 +459,14 @@ static int mxc_gpio_probe(struct platform_device *pdev)
> if (of_device_is_compatible(np, "fsl,imx7d-gpio"))
> port->power_off = true;
>
> + if (of_device_is_compatible(np, "fsl,imx8dxl-gpio") ||
> + of_device_is_compatible(np, "fsl,imx8qxp-gpio") ||
> + of_device_is_compatible(np, "fsl,imx8qm-gpio"))
> + port->has_pad_wakeup = true;
can you move has_pad_wakeup/is_imx8qm in mxc_gpio_hw_data?
Frank
> +
> + if (of_device_is_compatible(np, "fsl,imx8qm-gpio"))
> + port->is_imx8qm = true;
> +
> pm_runtime_get_noresume(&pdev->dev);
> pm_runtime_set_active(&pdev->dev);
> pm_runtime_enable(&pdev->dev);
> @@ -570,15 +580,10 @@ static void mxc_gpio_restore_regs(struct mxc_gpio_port *port)
> static bool mxc_gpio_generic_config(struct mxc_gpio_port *port,
> unsigned int offset, unsigned long conf)
> {
> - struct device_node *np = port->dev->of_node;
> -
> - if (of_device_is_compatible(np, "fsl,imx8dxl-gpio") ||
> - of_device_is_compatible(np, "fsl,imx8qxp-gpio") ||
> - of_device_is_compatible(np, "fsl,imx8qm-gpio"))
> - return (gpiochip_generic_config(&port->gen_gc.gc,
> - offset, conf) == 0);
> + if (!port->has_pad_wakeup)
> + return false;
>
> - return false;
> + return (gpiochip_generic_config(&port->gen_gc.gc, offset, conf) == 0);
> }
>
> static bool mxc_gpio_set_pad_wakeup(struct mxc_gpio_port *port, bool enable)
> @@ -586,7 +591,6 @@ static bool mxc_gpio_set_pad_wakeup(struct mxc_gpio_port *port, bool enable)
> unsigned long config;
> bool ret = false;
> int i, type;
> - bool is_imx8qm = of_device_is_compatible(port->dev->of_node, "fsl,imx8qm-gpio");
>
> static const u32 pad_type_map[] = {
> IMX_SCU_WAKEUP_OFF, /* 0 */
> @@ -608,7 +612,7 @@ static bool mxc_gpio_set_pad_wakeup(struct mxc_gpio_port *port, bool enable)
> else
> config = IMX_SCU_WAKEUP_OFF;
>
> - if (is_imx8qm && config == IMX_SCU_WAKEUP_FALL_EDGE) {
> + if (port->is_imx8qm && config == IMX_SCU_WAKEUP_FALL_EDGE) {
> dev_warn_once(port->dev,
> "No falling-edge support for wakeup on i.MX8QM\n");
> config = IMX_SCU_WAKEUP_OFF;
>
> --
> 2.51.0
>
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 4/9] gpio: mxc: use devm action for irq_domain cleanup
2026-10-03 12:06 ` [PATCH 4/9] gpio: mxc: use devm action for irq_domain cleanup Peng Fan (OSS)
2026-10-03 17:48 ` Andy Shevchenko
@ 2026-10-04 3:32 ` Frank Li
1 sibling, 0 replies; 20+ messages in thread
From: Frank Li @ 2026-10-04 3:32 UTC (permalink / raw)
To: Peng Fan (OSS)
Cc: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang,
Andy Shevchenko, linux-gpio, imx, linux-arm-kernel, linux-kernel,
Peng Fan
On Sat, Oct 03, 2026 at 08:06:46PM +0800, Peng Fan (OSS) wrote:
> From: Peng Fan <peng.fan@nxp.com>
>
> Replace the manual irq_domain_remove() error path with
> devm_add_action_or_reset(), so the IRQ domain is cleaned up
> automatically on both probe failure to eliminate the
> out_irqdomain_remove goto label.
>
> Assisted-by: LLM
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> ---
> drivers/gpio/gpio-mxc.c | 15 ++++++++++++---
> 1 file changed, 12 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
> index 1c27232f6a80..3c395c82d7d4 100644
> --- a/drivers/gpio/gpio-mxc.c
> +++ b/drivers/gpio/gpio-mxc.c
> @@ -417,6 +417,13 @@ static void mxc_update_irq_chained_handler(struct mxc_gpio_port *port, bool enab
> }
> }
>
> +static void mxc_gpio_irq_domain_remove(void *data)
> +{
> + struct irq_domain *domain = data;
> +
> + irq_domain_remove(domain);
> +}
> +
> static int mxc_gpio_probe(struct platform_device *pdev)
> {
> struct gpio_generic_chip_config config = { };
> @@ -526,12 +533,16 @@ static int mxc_gpio_probe(struct platform_device *pdev)
> goto out_bgio;
> }
>
No sure why not irq_domain_create_linear(),
https://lore.kernel.org/imx/aoW8V84mQ7UZhpaC@SMW015318/
Thomas Gleixner accept add devm_irq_domain_create_linear().
Frank
> + err = devm_add_action_or_reset(&pdev->dev, mxc_gpio_irq_domain_remove, port->domain);
> + if (err)
> + goto out_bgio;
> +
> irq_domain_set_pm_device(port->domain, &pdev->dev);
>
> /* gpio-mxc can be a generic irq chip */
> err = mxc_gpio_init_gc(port, irq_base);
> if (err < 0)
> - goto out_irqdomain_remove;
> + goto out_bgio;
>
> list_add_tail(&port->node, &mxc_gpio_ports);
>
> @@ -542,8 +553,6 @@ static int mxc_gpio_probe(struct platform_device *pdev)
>
> return 0;
>
> -out_irqdomain_remove:
> - irq_domain_remove(port->domain);
> out_bgio:
> pm_runtime_disable(&pdev->dev);
> pm_runtime_put_noidle(&pdev->dev);
>
> --
> 2.51.0
>
>
^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2026-10-04 3:32 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-03 12:06 [PATCH 0/9] gpio: mxc: bug fixes and probe cleanup Peng Fan (OSS)
2026-10-03 12:06 ` [PATCH 1/9] gpio: mxc: fix race between chained IRQ handler install and probe completion Peng Fan (OSS)
2026-10-03 17:35 ` Andy Shevchenko
2026-10-03 12:06 ` [PATCH 2/9] gpio: mxc: fix wakeup_pads bit operations for correctness Peng Fan (OSS)
2026-10-03 17:41 ` Andy Shevchenko
2026-10-03 12:06 ` [PATCH 3/9] gpio: mxc: cache compatible checks at probe time Peng Fan (OSS)
2026-10-03 17:45 ` Andy Shevchenko
2026-10-04 3:06 ` Frank Li
2026-10-03 12:06 ` [PATCH 4/9] gpio: mxc: use devm action for irq_domain cleanup Peng Fan (OSS)
2026-10-03 17:48 ` Andy Shevchenko
2026-10-04 3:32 ` Frank Li
2026-10-03 12:06 ` [PATCH 5/9] gpio: mxc: use devres-managed PM runtime and dev_err_probe Peng Fan (OSS)
2026-10-03 17:52 ` Andy Shevchenko
2026-10-04 3:00 ` Frank Li
2026-10-03 12:06 ` [PATCH 6/9] gpio: mxc: use local dev variable and device_is_compatible() Peng Fan (OSS)
2026-10-03 17:54 ` Andy Shevchenko
2026-10-03 12:06 ` [PATCH 7/9] gpio: mxc: introduce MXC_ICR macros and use field_prep/field_get Peng Fan (OSS)
2026-10-03 12:06 ` [PATCH 8/9] gpio: mxc: use BIT() macro for single-bit operations Peng Fan (OSS)
2026-10-03 12:06 ` [PATCH 9/9] gpio: mxc: simplify gpio_set_wake_irq() with irq_set_irq_wake and assign_bit Peng Fan (OSS)
2026-10-03 17:59 ` Andy Shevchenko
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®