* [PATCH v7 01/12] gpio: mxc: use irq_set_irq_wake() to simplify code
2026-10-27 12:09 [PATCH v7 00/12] gpio: mxc: probe cleanup Peng Fan (OSS)
@ 2026-10-27 12:09 ` Peng Fan (OSS)
2026-10-27 14:09 ` Frank Li
2026-10-27 12:09 ` [PATCH v7 02/12] gpio: mxc: use for_each_set_bit() to iterate wakeup pads Peng Fan (OSS)
` (10 subsequent siblings)
11 siblings, 1 reply; 20+ messages in thread
From: Peng Fan (OSS) @ 2026-10-27 12:09 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam
Cc: linux-kernel, linux-gpio, imx, linux-arm-kernel, Peng Fan
From: Peng Fan <peng.fan@nxp.com>
Simplify the logic by consolidating into a single irq_set_irq_wake()
call based on the enable parameter.
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
drivers/gpio/gpio-mxc.c | 15 ++++-----------
1 file changed, 4 insertions(+), 11 deletions(-)
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index 32ded7b548fb..95dfe199409a 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -326,17 +326,10 @@ 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);
- } else {
- if (port->irq_high && (gpio_idx >= 16))
- ret = disable_irq_wake(port->irq_high);
- else
- ret = disable_irq_wake(port->irq);
- }
+ 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)
return ret;
--
2.51.0
^ permalink raw reply [flat|nested] 20+ messages in thread* Re: [PATCH v7 01/12] gpio: mxc: use irq_set_irq_wake() to simplify code
2026-10-27 12:09 ` [PATCH v7 01/12] gpio: mxc: use irq_set_irq_wake() to simplify code Peng Fan (OSS)
@ 2026-10-27 14:09 ` Frank Li
0 siblings, 0 replies; 20+ messages in thread
From: Frank Li @ 2026-10-27 14:09 UTC (permalink / raw)
To: Peng Fan (OSS)
Cc: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, linux-kernel, linux-gpio,
imx, linux-arm-kernel, Peng Fan
On Tue, Oct 27, 2026 at 08:09:28PM +0800, Peng Fan (OSS) wrote:
> From: Peng Fan <peng.fan@nxp.com>
>
> Simplify the logic by consolidating into a single irq_set_irq_wake()
> call based on the enable parameter.
>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> ---
Reviewed-by: Frank Li <Frank.Li@nxp.com>
> drivers/gpio/gpio-mxc.c | 15 ++++-----------
> 1 file changed, 4 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
> index 32ded7b548fb..95dfe199409a 100644
> --- a/drivers/gpio/gpio-mxc.c
> +++ b/drivers/gpio/gpio-mxc.c
> @@ -326,17 +326,10 @@ 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);
> - } else {
> - if (port->irq_high && (gpio_idx >= 16))
> - ret = disable_irq_wake(port->irq_high);
> - else
> - ret = disable_irq_wake(port->irq);
> - }
> + 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)
> return ret;
>
>
> --
> 2.51.0
>
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v7 02/12] gpio: mxc: use for_each_set_bit() to iterate wakeup pads
2026-10-27 12:09 [PATCH v7 00/12] gpio: mxc: probe cleanup Peng Fan (OSS)
2026-10-27 12:09 ` [PATCH v7 01/12] gpio: mxc: use irq_set_irq_wake() to simplify code Peng Fan (OSS)
@ 2026-10-27 12:09 ` Peng Fan (OSS)
2026-10-27 16:35 ` Andy Shevchenko
2026-10-27 12:09 ` [PATCH v7 03/12] gpio: mxc: use 'unsigned int' instead of bare 'unsigned' Peng Fan (OSS)
` (9 subsequent siblings)
11 siblings, 1 reply; 20+ messages in thread
From: Peng Fan (OSS) @ 2026-10-27 12:09 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam
Cc: linux-kernel, linux-gpio, imx, linux-arm-kernel, Peng Fan,
Andy Shevchenko
From: Peng Fan <peng.fan@nxp.com>
Use for_each_set_bit() to iterate over the enabled wakeup pads instead
of checking every bit individually.
Suggested-by: Andy Shevchenko <andriy.shevchenko@intel.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
drivers/gpio/gpio-mxc.c | 26 ++++++++++++--------------
1 file changed, 12 insertions(+), 14 deletions(-)
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index 95dfe199409a..848d7725ccfe 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -599,22 +599,20 @@ static bool mxc_gpio_set_pad_wakeup(struct mxc_gpio_port *port, bool enable)
IMX_SCU_WAKEUP_LOW_LVL, /* IRQ_TYPE_LEVEL_LOW */
};
- for (i = 0; i < 32; i++) {
- if ((port->wakeup_pads & (1 << i))) {
- type = port->pad_type[i];
- if (enable)
- config = pad_type_map[type];
- else
- config = IMX_SCU_WAKEUP_OFF;
-
- if (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;
- }
+ for_each_set_bit(i, &port->wakeup_pads, 32) {
+ type = port->pad_type[i];
+ if (enable)
+ config = pad_type_map[type];
+ else
+ config = IMX_SCU_WAKEUP_OFF;
- ret |= mxc_gpio_generic_config(port, i, config);
+ if (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;
}
+
+ ret |= mxc_gpio_generic_config(port, i, config);
}
return ret;
--
2.51.0
^ permalink raw reply [flat|nested] 20+ messages in thread* Re: [PATCH v7 02/12] gpio: mxc: use for_each_set_bit() to iterate wakeup pads
2026-10-27 12:09 ` [PATCH v7 02/12] gpio: mxc: use for_each_set_bit() to iterate wakeup pads Peng Fan (OSS)
@ 2026-10-27 16:35 ` Andy Shevchenko
0 siblings, 0 replies; 20+ messages in thread
From: Andy Shevchenko @ 2026-10-27 16:35 UTC (permalink / raw)
To: Peng Fan (OSS)
Cc: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, linux-kernel, linux-gpio,
imx, linux-arm-kernel, Peng Fan
On Tue, Oct 27, 2026 at 08:09:29PM +0800, Peng Fan (OSS) wrote:
>
> Use for_each_set_bit() to iterate over the enabled wakeup pads instead
> of checking every bit individually.
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v7 03/12] gpio: mxc: use 'unsigned int' instead of bare 'unsigned'
2026-10-27 12:09 [PATCH v7 00/12] gpio: mxc: probe cleanup Peng Fan (OSS)
2026-10-27 12:09 ` [PATCH v7 01/12] gpio: mxc: use irq_set_irq_wake() to simplify code Peng Fan (OSS)
2026-10-27 12:09 ` [PATCH v7 02/12] gpio: mxc: use for_each_set_bit() to iterate wakeup pads Peng Fan (OSS)
@ 2026-10-27 12:09 ` Peng Fan (OSS)
2026-10-27 14:10 ` Frank Li
2026-10-27 16:36 ` Andy Shevchenko
2026-10-27 12:09 ` [PATCH v7 04/12] gpio: mxc: replace of_device_is_compatible() with hwdata flags Peng Fan (OSS)
` (8 subsequent siblings)
11 siblings, 2 replies; 20+ messages in thread
From: Peng Fan (OSS) @ 2026-10-27 12:09 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam
Cc: linux-kernel, linux-gpio, imx, linux-arm-kernel, Peng Fan,
Andy Shevchenko
From: Peng Fan <peng.fan@nxp.com>
The kernel coding style prefers 'unsigned int' over bare 'unsigned'.
Fix all instances in struct mxc_gpio_hwdata and mxc_gpio_to_irq().
No functional change.
Suggested-by: Andy Shevchenko <andriy.shevchenko@intel.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
drivers/gpio/gpio-mxc.c | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index 848d7725ccfe..43868a214c17 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -36,18 +36,18 @@
/* device type dependent stuff */
struct mxc_gpio_hwdata {
- unsigned dr_reg;
- unsigned gdir_reg;
- unsigned psr_reg;
- unsigned icr1_reg;
- unsigned icr2_reg;
- unsigned imr_reg;
- unsigned isr_reg;
+ unsigned int dr_reg;
+ unsigned int gdir_reg;
+ unsigned int psr_reg;
+ unsigned int icr1_reg;
+ unsigned int icr2_reg;
+ unsigned int imr_reg;
+ unsigned int isr_reg;
int edge_sel_reg;
- unsigned low_level;
- unsigned high_level;
- unsigned rise_edge;
- unsigned fall_edge;
+ unsigned int low_level;
+ unsigned int high_level;
+ unsigned int rise_edge;
+ unsigned int fall_edge;
};
struct mxc_gpio_reg_saved {
@@ -367,7 +367,7 @@ static int mxc_gpio_init_gc(struct mxc_gpio_port *port, int irq_base)
return rv;
}
-static int mxc_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
+static int mxc_gpio_to_irq(struct gpio_chip *gc, unsigned int offset)
{
struct mxc_gpio_port *port = gpiochip_get_data(gc);
--
2.51.0
^ permalink raw reply [flat|nested] 20+ messages in thread* Re: [PATCH v7 03/12] gpio: mxc: use 'unsigned int' instead of bare 'unsigned'
2026-10-27 12:09 ` [PATCH v7 03/12] gpio: mxc: use 'unsigned int' instead of bare 'unsigned' Peng Fan (OSS)
@ 2026-10-27 14:10 ` Frank Li
2026-10-27 16:36 ` Andy Shevchenko
1 sibling, 0 replies; 20+ messages in thread
From: Frank Li @ 2026-10-27 14:10 UTC (permalink / raw)
To: Peng Fan (OSS)
Cc: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, linux-kernel, linux-gpio,
imx, linux-arm-kernel, Peng Fan, Andy Shevchenko
On Tue, Oct 27, 2026 at 08:09:30PM +0800, Peng Fan (OSS) wrote:
> From: Peng Fan <peng.fan@nxp.com>
>
> The kernel coding style prefers 'unsigned int' over bare 'unsigned'.
> Fix all instances in struct mxc_gpio_hwdata and mxc_gpio_to_irq().
>
> No functional change.
>
> Suggested-by: Andy Shevchenko <andriy.shevchenko@intel.com>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> ---
Reviewed-by: Frank Li <Frank.Li@nxp.com>
> drivers/gpio/gpio-mxc.c | 24 ++++++++++++------------
> 1 file changed, 12 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
> index 848d7725ccfe..43868a214c17 100644
> --- a/drivers/gpio/gpio-mxc.c
> +++ b/drivers/gpio/gpio-mxc.c
> @@ -36,18 +36,18 @@
>
> /* device type dependent stuff */
> struct mxc_gpio_hwdata {
> - unsigned dr_reg;
> - unsigned gdir_reg;
> - unsigned psr_reg;
> - unsigned icr1_reg;
> - unsigned icr2_reg;
> - unsigned imr_reg;
> - unsigned isr_reg;
> + unsigned int dr_reg;
> + unsigned int gdir_reg;
> + unsigned int psr_reg;
> + unsigned int icr1_reg;
> + unsigned int icr2_reg;
> + unsigned int imr_reg;
> + unsigned int isr_reg;
> int edge_sel_reg;
> - unsigned low_level;
> - unsigned high_level;
> - unsigned rise_edge;
> - unsigned fall_edge;
> + unsigned int low_level;
> + unsigned int high_level;
> + unsigned int rise_edge;
> + unsigned int fall_edge;
> };
>
> struct mxc_gpio_reg_saved {
> @@ -367,7 +367,7 @@ static int mxc_gpio_init_gc(struct mxc_gpio_port *port, int irq_base)
> return rv;
> }
>
> -static int mxc_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
> +static int mxc_gpio_to_irq(struct gpio_chip *gc, unsigned int offset)
> {
> struct mxc_gpio_port *port = gpiochip_get_data(gc);
>
>
> --
> 2.51.0
>
>
^ permalink raw reply [flat|nested] 20+ messages in thread* Re: [PATCH v7 03/12] gpio: mxc: use 'unsigned int' instead of bare 'unsigned'
2026-10-27 12:09 ` [PATCH v7 03/12] gpio: mxc: use 'unsigned int' instead of bare 'unsigned' Peng Fan (OSS)
2026-10-27 14:10 ` Frank Li
@ 2026-10-27 16:36 ` Andy Shevchenko
1 sibling, 0 replies; 20+ messages in thread
From: Andy Shevchenko @ 2026-10-27 16:36 UTC (permalink / raw)
To: Peng Fan (OSS)
Cc: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, linux-kernel, linux-gpio,
imx, linux-arm-kernel, Peng Fan
On Tue, Oct 27, 2026 at 08:09:30PM +0800, Peng Fan (OSS) wrote:
>
> The kernel coding style prefers 'unsigned int' over bare 'unsigned'.
> Fix all instances in struct mxc_gpio_hwdata and mxc_gpio_to_irq().
>
> No functional change.
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v7 04/12] gpio: mxc: replace of_device_is_compatible() with hwdata flags
2026-10-27 12:09 [PATCH v7 00/12] gpio: mxc: probe cleanup Peng Fan (OSS)
` (2 preceding siblings ...)
2026-10-27 12:09 ` [PATCH v7 03/12] gpio: mxc: use 'unsigned int' instead of bare 'unsigned' Peng Fan (OSS)
@ 2026-10-27 12:09 ` Peng Fan (OSS)
2026-10-27 12:09 ` [PATCH v7 05/12] gpio: mxc: convert pad wakeup compatible checks to " Peng Fan (OSS)
` (7 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: Peng Fan (OSS) @ 2026-10-27 12:09 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam
Cc: linux-kernel, linux-gpio, imx, linux-arm-kernel, Peng Fan
From: Peng Fan <peng.fan@nxp.com>
Replace the runtime of_device_is_compatible() check for "fsl,imx7d-gpio"
with a flags field in mxc_gpio_hwdata to move the power-off capability
from a per-instance bool populated at probe time to static per-compatible
data.
Introduce MXC_GPIO_HAS_POWER_OFF and a dedicated imx7d_gpio_hwdata
instance that carries it, along with a mxc_gpio_has_power_off() helper
that replaces every former port->power_off test.
While at it, factor the register offsets shared by imx35 and imx7d into
a MXC_GPIO_HW_DATA_COMMON macro to avoid duplicating twelve identical
initializers.
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
drivers/gpio/gpio-mxc.c | 50 ++++++++++++++++++++++++++++++-------------------
1 file changed, 31 insertions(+), 19 deletions(-)
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index 43868a214c17..abff07bd3840 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -34,6 +34,8 @@
#define IMX_SCU_WAKEUP_RISE_EDGE 6
#define IMX_SCU_WAKEUP_HIGH_LVL 7
+#define MXC_GPIO_HAS_POWER_OFF BIT(0)
+
/* device type dependent stuff */
struct mxc_gpio_hwdata {
unsigned int dr_reg;
@@ -48,6 +50,7 @@ struct mxc_gpio_hwdata {
unsigned int high_level;
unsigned int rise_edge;
unsigned int fall_edge;
+ unsigned int flags;
};
struct mxc_gpio_reg_saved {
@@ -71,13 +74,26 @@ struct mxc_gpio_port {
struct device *dev;
unsigned long both_edges;
struct mxc_gpio_reg_saved gpio_saved_reg;
- bool power_off;
bool is_pad_wakeup;
unsigned long wakeup_pads;
u32 pad_type[32];
const struct mxc_gpio_hwdata *hwdata;
};
+#define MXC_GPIO_HW_DATA_COMMON \
+ .dr_reg = 0x00, \
+ .gdir_reg = 0x04, \
+ .psr_reg = 0x08, \
+ .icr1_reg = 0x0c, \
+ .icr2_reg = 0x10, \
+ .imr_reg = 0x14, \
+ .isr_reg = 0x18, \
+ .edge_sel_reg = 0x1c, \
+ .low_level = 0x00, \
+ .high_level = 0x01, \
+ .rise_edge = 0x02, \
+ .fall_edge = 0x03
+
static struct mxc_gpio_hwdata imx1_imx21_gpio_hwdata = {
.dr_reg = 0x1c,
.gdir_reg = 0x00,
@@ -109,20 +125,19 @@ static struct mxc_gpio_hwdata imx31_gpio_hwdata = {
};
static struct mxc_gpio_hwdata imx35_gpio_hwdata = {
- .dr_reg = 0x00,
- .gdir_reg = 0x04,
- .psr_reg = 0x08,
- .icr1_reg = 0x0c,
- .icr2_reg = 0x10,
- .imr_reg = 0x14,
- .isr_reg = 0x18,
- .edge_sel_reg = 0x1c,
- .low_level = 0x00,
- .high_level = 0x01,
- .rise_edge = 0x02,
- .fall_edge = 0x03,
+ MXC_GPIO_HW_DATA_COMMON,
+};
+
+static struct mxc_gpio_hwdata imx7d_gpio_hwdata = {
+ MXC_GPIO_HW_DATA_COMMON,
+ .flags = MXC_GPIO_HAS_POWER_OFF,
};
+static inline bool mxc_gpio_has_power_off(struct mxc_gpio_port *port)
+{
+ return port->hwdata->flags & MXC_GPIO_HAS_POWER_OFF;
+}
+
#define GPIO_DR (port->hwdata->dr_reg)
#define GPIO_GDIR (port->hwdata->gdir_reg)
#define GPIO_PSR (port->hwdata->psr_reg)
@@ -143,7 +158,7 @@ static const struct of_device_id mxc_gpio_dt_ids[] = {
{ .compatible = "fsl,imx21-gpio", .data = &imx1_imx21_gpio_hwdata },
{ .compatible = "fsl,imx31-gpio", .data = &imx31_gpio_hwdata },
{ .compatible = "fsl,imx35-gpio", .data = &imx35_gpio_hwdata },
- { .compatible = "fsl,imx7d-gpio", .data = &imx35_gpio_hwdata },
+ { .compatible = "fsl,imx7d-gpio", .data = &imx7d_gpio_hwdata },
{ .compatible = "fsl,imx8dxl-gpio", .data = &imx35_gpio_hwdata },
{ .compatible = "fsl,imx8qm-gpio", .data = &imx35_gpio_hwdata },
{ .compatible = "fsl,imx8qxp-gpio", .data = &imx35_gpio_hwdata },
@@ -448,9 +463,6 @@ static int mxc_gpio_probe(struct platform_device *pdev)
if (IS_ERR(port->clk))
return PTR_ERR(port->clk);
- if (of_device_is_compatible(np, "fsl,imx7d-gpio"))
- port->power_off = true;
-
pm_runtime_get_noresume(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
@@ -542,7 +554,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
static void mxc_gpio_save_regs(struct mxc_gpio_port *port)
{
- if (!port->power_off)
+ if (!mxc_gpio_has_power_off(port))
return;
port->gpio_saved_reg.icr1 = readl(port->base + GPIO_ICR1);
@@ -555,7 +567,7 @@ static void mxc_gpio_save_regs(struct mxc_gpio_port *port)
static void mxc_gpio_restore_regs(struct mxc_gpio_port *port)
{
- if (!port->power_off)
+ if (!mxc_gpio_has_power_off(port))
return;
writel(port->gpio_saved_reg.icr1, port->base + GPIO_ICR1);
--
2.51.0
^ permalink raw reply [flat|nested] 20+ messages in thread* [PATCH v7 05/12] gpio: mxc: convert pad wakeup compatible checks to hwdata flags
2026-10-27 12:09 [PATCH v7 00/12] gpio: mxc: probe cleanup Peng Fan (OSS)
` (3 preceding siblings ...)
2026-10-27 12:09 ` [PATCH v7 04/12] gpio: mxc: replace of_device_is_compatible() with hwdata flags Peng Fan (OSS)
@ 2026-10-27 12:09 ` Peng Fan (OSS)
2026-10-27 12:09 ` [PATCH v7 06/12] gpio: mxc: use local dev variable Peng Fan (OSS)
` (6 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: Peng Fan (OSS) @ 2026-10-27 12:09 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam
Cc: linux-kernel, linux-gpio, imx, linux-arm-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.
Extend the hwdata flags scheme introduced in the previous commit with
MXC_GPIO_HAS_PAD_WAKEUP and MXC_GPIO_FALL_EDGE_WAKEUP_BROKEN, adding
dedicated hwdata instances for imx8qm and imx8qxp (also used by imx8dxl).
This replaces the repeated device tree string comparisons in the
suspend/resume path with simple flag tests on static per-compatible
data.
While at it, clean up mxc_gpio_generic_config() to use a local ret
variable for clarity instead of the == 0 comparison.
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
drivers/gpio/gpio-mxc.c | 46 ++++++++++++++++++++++++++++++++++------------
1 file changed, 34 insertions(+), 12 deletions(-)
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index abff07bd3840..e7c6fbd811a6 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -35,6 +35,8 @@
#define IMX_SCU_WAKEUP_HIGH_LVL 7
#define MXC_GPIO_HAS_POWER_OFF BIT(0)
+#define MXC_GPIO_HAS_PAD_WAKEUP BIT(1)
+#define MXC_GPIO_FALL_EDGE_WAKEUP_BROKEN BIT(2)
/* device type dependent stuff */
struct mxc_gpio_hwdata {
@@ -133,6 +135,26 @@ static struct mxc_gpio_hwdata imx7d_gpio_hwdata = {
.flags = MXC_GPIO_HAS_POWER_OFF,
};
+static struct mxc_gpio_hwdata imx8qm_gpio_hwdata = {
+ MXC_GPIO_HW_DATA_COMMON,
+ .flags = MXC_GPIO_FALL_EDGE_WAKEUP_BROKEN | MXC_GPIO_HAS_PAD_WAKEUP,
+};
+
+static struct mxc_gpio_hwdata imx8qxp_gpio_hwdata = {
+ MXC_GPIO_HW_DATA_COMMON,
+ .flags = MXC_GPIO_HAS_PAD_WAKEUP,
+};
+
+static inline bool mxc_gpio_fall_edge_wakeup_broken(struct mxc_gpio_port *port)
+{
+ return port->hwdata->flags & MXC_GPIO_FALL_EDGE_WAKEUP_BROKEN;
+}
+
+static inline bool mxc_gpio_has_pad_wakeup(struct mxc_gpio_port *port)
+{
+ return port->hwdata->flags & MXC_GPIO_HAS_PAD_WAKEUP;
+}
+
static inline bool mxc_gpio_has_power_off(struct mxc_gpio_port *port)
{
return port->hwdata->flags & MXC_GPIO_HAS_POWER_OFF;
@@ -159,9 +181,9 @@ static const struct of_device_id mxc_gpio_dt_ids[] = {
{ .compatible = "fsl,imx31-gpio", .data = &imx31_gpio_hwdata },
{ .compatible = "fsl,imx35-gpio", .data = &imx35_gpio_hwdata },
{ .compatible = "fsl,imx7d-gpio", .data = &imx7d_gpio_hwdata },
- { .compatible = "fsl,imx8dxl-gpio", .data = &imx35_gpio_hwdata },
- { .compatible = "fsl,imx8qm-gpio", .data = &imx35_gpio_hwdata },
- { .compatible = "fsl,imx8qxp-gpio", .data = &imx35_gpio_hwdata },
+ { .compatible = "fsl,imx8dxl-gpio", .data = &imx8qxp_gpio_hwdata },
+ { .compatible = "fsl,imx8qm-gpio", .data = &imx8qm_gpio_hwdata },
+ { .compatible = "fsl,imx8qxp-gpio", .data = &imx8qxp_gpio_hwdata },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, mxc_gpio_dt_ids);
@@ -581,15 +603,16 @@ 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;
+ int ret;
+
+ if (!mxc_gpio_has_pad_wakeup(port))
+ return false;
- 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);
+ ret = gpiochip_generic_config(&port->gen_gc.gc, offset, conf);
+ if (ret)
+ return false;
- return false;
+ return true;
}
static bool mxc_gpio_set_pad_wakeup(struct mxc_gpio_port *port, bool enable)
@@ -597,7 +620,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 */
@@ -618,7 +640,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 (mxc_gpio_fall_edge_wakeup_broken(port) && 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 v7 06/12] gpio: mxc: use local dev variable
2026-10-27 12:09 [PATCH v7 00/12] gpio: mxc: probe cleanup Peng Fan (OSS)
` (4 preceding siblings ...)
2026-10-27 12:09 ` [PATCH v7 05/12] gpio: mxc: convert pad wakeup compatible checks to " Peng Fan (OSS)
@ 2026-10-27 12:09 ` Peng Fan (OSS)
2026-10-27 12:09 ` [PATCH v7 07/12] gpio: mxc: use __free guard for runtime PM cleanup Peng Fan (OSS)
` (5 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: Peng Fan (OSS) @ 2026-10-27 12:09 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam
Cc: linux-kernel, linux-gpio, imx, linux-arm-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.
No functional change.
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
drivers/gpio/gpio-mxc.c | 33 +++++++++++++++++----------------
1 file changed, 17 insertions(+), 16 deletions(-)
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index e7c6fbd811a6..21c74b244c1f 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -450,17 +450,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))
@@ -481,13 +482,13 @@ 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);
- pm_runtime_get_noresume(&pdev->dev);
- pm_runtime_set_active(&pdev->dev);
- pm_runtime_enable(&pdev->dev);
+ pm_runtime_get_noresume(dev);
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
/* disable the interrupt and clear the status */
writel(0, port->base + GPIO_IMR);
@@ -504,7 +505,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;
@@ -527,20 +528,20 @@ static int mxc_gpio_probe(struct platform_device *pdev)
else /* silence boot time warning */
port->gen_gc.gc.base = -1;
- 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) {
err = irq_base;
goto out_bgio;
}
- 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) {
err = -ENODEV;
goto out_bgio;
}
- 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);
@@ -552,7 +553,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
* chip visible to consumers immediately, so the IRQ domain and
* generic irq chip must be ready before any to_irq() call.
*/
- 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)
goto out_irqdomain_remove;
@@ -561,16 +562,16 @@ static int mxc_gpio_probe(struct platform_device *pdev)
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;
out_irqdomain_remove:
irq_domain_remove(port->domain);
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);
+ pm_runtime_disable(dev);
+ pm_runtime_put_noidle(dev);
+ dev_info(dev, "%s failed with errno %d\n", __func__, err);
return err;
}
--
2.51.0
^ permalink raw reply [flat|nested] 20+ messages in thread* [PATCH v7 07/12] gpio: mxc: use __free guard for runtime PM cleanup
2026-10-27 12:09 [PATCH v7 00/12] gpio: mxc: probe cleanup Peng Fan (OSS)
` (5 preceding siblings ...)
2026-10-27 12:09 ` [PATCH v7 06/12] gpio: mxc: use local dev variable Peng Fan (OSS)
@ 2026-10-27 12:09 ` Peng Fan (OSS)
2026-10-27 14:12 ` Frank Li
2026-10-27 12:09 ` [PATCH v7 08/12] gpio: mxc: use devres functions to simplify probe code Peng Fan (OSS)
` (4 subsequent siblings)
11 siblings, 1 reply; 20+ messages in thread
From: Peng Fan (OSS) @ 2026-10-27 12:09 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam
Cc: linux-kernel, linux-gpio, imx, linux-arm-kernel, Peng Fan
From: Peng Fan <peng.fan@nxp.com>
Use a scope-based cleanup guard to disable runtime PM and drop the
probe-scoped pm_runtime_get_noresume() reference on error paths. Disarm
it with retain_and_null_ptr() before the success-path
pm_runtime_put_autosuspend().
The guard keeps the required order: pm_runtime_disable() runs before
pm_runtime_put_noidle(), so dropping the reference cannot trigger a
runtime suspend callback while probe is still unwinding.
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
drivers/gpio/gpio-mxc.c | 21 +++++++++++++++++++--
1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index 21c74b244c1f..68857730b5e3 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -28,6 +28,20 @@
#include <linux/of.h>
#include <linux/bug.h>
+static void mxc_gpio_pm_release(struct device *dev)
+{
+ if (!dev)
+ return;
+
+ if (pm_runtime_enabled(dev))
+ pm_runtime_disable(dev);
+
+ pm_runtime_put_noidle(dev);
+}
+
+DEFINE_FREE(mxc_gpio_pm_cleanup, struct device *,
+ mxc_gpio_pm_release(_T))
+
#define IMX_SCU_WAKEUP_OFF 0
#define IMX_SCU_WAKEUP_LOW_LVL 4
#define IMX_SCU_WAKEUP_FALL_EDGE 5
@@ -487,6 +501,9 @@ static int mxc_gpio_probe(struct platform_device *pdev)
return PTR_ERR(port->clk);
pm_runtime_get_noresume(dev);
+
+ struct device *pm_guard __free(mxc_gpio_pm_cleanup) = dev;
+
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
@@ -562,6 +579,8 @@ static int mxc_gpio_probe(struct platform_device *pdev)
mxc_update_irq_chained_handler(port, true);
platform_set_drvdata(pdev, port);
+
+ retain_and_null_ptr(pm_guard);
pm_runtime_put_autosuspend(dev);
return 0;
@@ -569,8 +588,6 @@ static int mxc_gpio_probe(struct platform_device *pdev)
out_irqdomain_remove:
irq_domain_remove(port->domain);
out_bgio:
- pm_runtime_disable(dev);
- pm_runtime_put_noidle(dev);
dev_info(dev, "%s failed with errno %d\n", __func__, err);
return err;
}
--
2.51.0
^ permalink raw reply [flat|nested] 20+ messages in thread* Re: [PATCH v7 07/12] gpio: mxc: use __free guard for runtime PM cleanup
2026-10-27 12:09 ` [PATCH v7 07/12] gpio: mxc: use __free guard for runtime PM cleanup Peng Fan (OSS)
@ 2026-10-27 14:12 ` Frank Li
0 siblings, 0 replies; 20+ messages in thread
From: Frank Li @ 2026-10-27 14:12 UTC (permalink / raw)
To: Peng Fan (OSS)
Cc: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, linux-kernel, linux-gpio,
imx, linux-arm-kernel, Peng Fan
On Tue, Oct 27, 2026 at 08:09:34PM +0800, Peng Fan (OSS) wrote:
> From: Peng Fan <peng.fan@nxp.com>
>
> Use a scope-based cleanup guard to disable runtime PM and drop the
> probe-scoped pm_runtime_get_noresume() reference on error paths. Disarm
> it with retain_and_null_ptr() before the success-path
> pm_runtime_put_autosuspend().
>
> The guard keeps the required order: pm_runtime_disable() runs before
> pm_runtime_put_noidle(), so dropping the reference cannot trigger a
> runtime suspend callback while probe is still unwinding.
>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> ---
Reviewed-by: Frank Li <Frank.Li@nxp.com>
> drivers/gpio/gpio-mxc.c | 21 +++++++++++++++++++--
> 1 file changed, 19 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
> index 21c74b244c1f..68857730b5e3 100644
> --- a/drivers/gpio/gpio-mxc.c
> +++ b/drivers/gpio/gpio-mxc.c
> @@ -28,6 +28,20 @@
> #include <linux/of.h>
> #include <linux/bug.h>
>
> +static void mxc_gpio_pm_release(struct device *dev)
> +{
> + if (!dev)
> + return;
> +
> + if (pm_runtime_enabled(dev))
> + pm_runtime_disable(dev);
> +
> + pm_runtime_put_noidle(dev);
> +}
> +
> +DEFINE_FREE(mxc_gpio_pm_cleanup, struct device *,
> + mxc_gpio_pm_release(_T))
> +
> #define IMX_SCU_WAKEUP_OFF 0
> #define IMX_SCU_WAKEUP_LOW_LVL 4
> #define IMX_SCU_WAKEUP_FALL_EDGE 5
> @@ -487,6 +501,9 @@ static int mxc_gpio_probe(struct platform_device *pdev)
> return PTR_ERR(port->clk);
>
> pm_runtime_get_noresume(dev);
> +
> + struct device *pm_guard __free(mxc_gpio_pm_cleanup) = dev;
> +
> pm_runtime_set_active(dev);
> pm_runtime_enable(dev);
>
> @@ -562,6 +579,8 @@ static int mxc_gpio_probe(struct platform_device *pdev)
> mxc_update_irq_chained_handler(port, true);
>
> platform_set_drvdata(pdev, port);
> +
> + retain_and_null_ptr(pm_guard);
> pm_runtime_put_autosuspend(dev);
>
> return 0;
> @@ -569,8 +588,6 @@ static int mxc_gpio_probe(struct platform_device *pdev)
> out_irqdomain_remove:
> irq_domain_remove(port->domain);
> out_bgio:
> - pm_runtime_disable(dev);
> - pm_runtime_put_noidle(dev);
> dev_info(dev, "%s failed with errno %d\n", __func__, err);
> return err;
> }
>
> --
> 2.51.0
>
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v7 08/12] gpio: mxc: use devres functions to simplify probe code
2026-10-27 12:09 [PATCH v7 00/12] gpio: mxc: probe cleanup Peng Fan (OSS)
` (6 preceding siblings ...)
2026-10-27 12:09 ` [PATCH v7 07/12] gpio: mxc: use __free guard for runtime PM cleanup Peng Fan (OSS)
@ 2026-10-27 12:09 ` Peng Fan (OSS)
2026-10-27 12:09 ` [PATCH v7 09/12] gpio: mxc: add dev_err_probe() for error paths to help diagnostics Peng Fan (OSS)
` (3 subsequent siblings)
11 siblings, 0 replies; 20+ messages in thread
From: Peng Fan (OSS) @ 2026-10-27 12:09 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam
Cc: linux-kernel, linux-gpio, imx, linux-arm-kernel, Peng Fan
From: Peng Fan <peng.fan@nxp.com>
Replace irq_domain_create_legacy() with devm_irq_domain_instantiate()
and convert the remaining manually-unwound IRQ resources in probe to
devres management.
The runtime PM cleanup guard from the previous commit disables runtime PM
and drops the probe reference on these error returns.
With every allocation after the PM block now devm-managed, the
out_irqdomain_remove and out_bgio labels are no longer needed.
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
drivers/gpio/gpio-mxc.c | 37 ++++++++++++++++++-------------------
1 file changed, 18 insertions(+), 19 deletions(-)
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index 68857730b5e3..eeb7d36e6b44 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -465,6 +465,7 @@ 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 irq_domain_info d_info;
struct mxc_gpio_port *port;
int irq_count;
int irq_base;
@@ -531,7 +532,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 err;
port->gen_gc.gc.request = mxc_gpio_request;
port->gen_gc.gc.free = mxc_gpio_free;
@@ -546,24 +547,28 @@ static int mxc_gpio_probe(struct platform_device *pdev)
port->gen_gc.gc.base = -1;
irq_base = devm_irq_alloc_descs(dev, -1, 0, 32, numa_node_id());
- if (irq_base < 0) {
- err = irq_base;
- goto out_bgio;
- }
+ if (irq_base < 0)
+ return irq_base;
+
+ d_info = (struct irq_domain_info) {
+ .fwnode = dev_fwnode(dev),
+ .size = 32,
+ .hwirq_max = 32,
+ .virq_base = irq_base,
+ .ops = &irq_domain_simple_ops,
+ .dev = dev,
+ };
- port->domain = irq_domain_create_legacy(dev_fwnode(dev), 32, irq_base, 0,
- &irq_domain_simple_ops, NULL);
- if (!port->domain) {
- err = -ENODEV;
- goto out_bgio;
- }
+ port->domain = devm_irq_domain_instantiate(dev, &d_info);
+ if (IS_ERR(port->domain))
+ return PTR_ERR(port->domain);
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)
- goto out_irqdomain_remove;
+ return err;
/*
* Register the GPIO chip last: devm_gpiochip_add_data() makes the
@@ -572,7 +577,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
*/
err = devm_gpiochip_add_data(dev, &port->gen_gc.gc, port);
if (err)
- goto out_irqdomain_remove;
+ return err;
list_add_tail(&port->node, &mxc_gpio_ports);
@@ -584,12 +589,6 @@ static int mxc_gpio_probe(struct platform_device *pdev)
pm_runtime_put_autosuspend(dev);
return 0;
-
-out_irqdomain_remove:
- irq_domain_remove(port->domain);
-out_bgio:
- dev_info(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 v7 09/12] gpio: mxc: add dev_err_probe() for error paths to help diagnostics
2026-10-27 12:09 [PATCH v7 00/12] gpio: mxc: probe cleanup Peng Fan (OSS)
` (7 preceding siblings ...)
2026-10-27 12:09 ` [PATCH v7 08/12] gpio: mxc: use devres functions to simplify probe code Peng Fan (OSS)
@ 2026-10-27 12:09 ` Peng Fan (OSS)
2026-10-27 14:13 ` Frank Li
2026-10-27 12:09 ` [PATCH v7 10/12] gpio: mxc: introduce MXC_ICR macros and use field_prep/field_get Peng Fan (OSS)
` (2 subsequent siblings)
11 siblings, 1 reply; 20+ messages in thread
From: Peng Fan (OSS) @ 2026-10-27 12:09 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam
Cc: linux-kernel, linux-gpio, imx, linux-arm-kernel, Peng Fan
From: Peng Fan <peng.fan@nxp.com>
Use dev_err_probe() on probe error paths that do not already report the
failure, so that deferred probe reasons are recorded consistently. Leave
the devm_platform_ioremap_resource() and platform_get_irq() paths alone;
those already log their errors.
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
drivers/gpio/gpio-mxc.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index eeb7d36e6b44..f816822e36ad 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -484,7 +484,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
irq_count = platform_irq_count(pdev);
if (irq_count < 0)
- return irq_count;
+ return dev_err_probe(dev, irq_count, "Failed to count irq\n");
if (irq_count > 1) {
port->irq_high = platform_get_irq(pdev, 1);
@@ -499,7 +499,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
/* the controller clock is optional */
port->clk = devm_clk_get_optional_enabled(dev, NULL);
if (IS_ERR(port->clk))
- return PTR_ERR(port->clk);
+ return dev_err_probe(dev, PTR_ERR(port->clk), "Failed to get clk\n");
pm_runtime_get_noresume(dev);
@@ -532,7 +532,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
err = gpio_generic_chip_init(&port->gen_gc, &config);
if (err)
- return err;
+ 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;
@@ -548,7 +548,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
irq_base = devm_irq_alloc_descs(dev, -1, 0, 32, numa_node_id());
if (irq_base < 0)
- return irq_base;
+ return dev_err_probe(dev, irq_base, "Failed to alloc irq desc\n");
d_info = (struct irq_domain_info) {
.fwnode = dev_fwnode(dev),
@@ -561,14 +561,15 @@ static int mxc_gpio_probe(struct platform_device *pdev)
port->domain = devm_irq_domain_instantiate(dev, &d_info);
if (IS_ERR(port->domain))
- return PTR_ERR(port->domain);
+ return dev_err_probe(dev, PTR_ERR(port->domain),
+ "Failed to create irq domain\n");
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 err;
+ return dev_err_probe(dev, err, "Failed to init generic irq chip\n");
/*
* Register the GPIO chip last: devm_gpiochip_add_data() makes the
@@ -577,7 +578,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
*/
err = devm_gpiochip_add_data(dev, &port->gen_gc.gc, port);
if (err)
- return err;
+ return dev_err_probe(dev, err, "Failed to add gpiochip data\n");
list_add_tail(&port->node, &mxc_gpio_ports);
--
2.51.0
^ permalink raw reply [flat|nested] 20+ messages in thread* Re: [PATCH v7 09/12] gpio: mxc: add dev_err_probe() for error paths to help diagnostics
2026-10-27 12:09 ` [PATCH v7 09/12] gpio: mxc: add dev_err_probe() for error paths to help diagnostics Peng Fan (OSS)
@ 2026-10-27 14:13 ` Frank Li
0 siblings, 0 replies; 20+ messages in thread
From: Frank Li @ 2026-10-27 14:13 UTC (permalink / raw)
To: Peng Fan (OSS)
Cc: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, linux-kernel, linux-gpio,
imx, linux-arm-kernel, Peng Fan
On Tue, Oct 27, 2026 at 08:09:36PM +0800, Peng Fan (OSS) wrote:
> From: Peng Fan <peng.fan@nxp.com>
>
> Use dev_err_probe() on probe error paths that do not already report the
> failure, so that deferred probe reasons are recorded consistently. Leave
> the devm_platform_ioremap_resource() and platform_get_irq() paths alone;
> those already log their errors.
>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> ---
Reviewed-by: Frank Li <Frank.Li@nxp.com>
> drivers/gpio/gpio-mxc.c | 15 ++++++++-------
> 1 file changed, 8 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
> index eeb7d36e6b44..f816822e36ad 100644
> --- a/drivers/gpio/gpio-mxc.c
> +++ b/drivers/gpio/gpio-mxc.c
> @@ -484,7 +484,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
>
> irq_count = platform_irq_count(pdev);
> if (irq_count < 0)
> - return irq_count;
> + return dev_err_probe(dev, irq_count, "Failed to count irq\n");
>
> if (irq_count > 1) {
> port->irq_high = platform_get_irq(pdev, 1);
> @@ -499,7 +499,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
> /* the controller clock is optional */
> port->clk = devm_clk_get_optional_enabled(dev, NULL);
> if (IS_ERR(port->clk))
> - return PTR_ERR(port->clk);
> + return dev_err_probe(dev, PTR_ERR(port->clk), "Failed to get clk\n");
>
> pm_runtime_get_noresume(dev);
>
> @@ -532,7 +532,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
>
> err = gpio_generic_chip_init(&port->gen_gc, &config);
> if (err)
> - return err;
> + 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;
> @@ -548,7 +548,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
>
> irq_base = devm_irq_alloc_descs(dev, -1, 0, 32, numa_node_id());
> if (irq_base < 0)
> - return irq_base;
> + return dev_err_probe(dev, irq_base, "Failed to alloc irq desc\n");
>
> d_info = (struct irq_domain_info) {
> .fwnode = dev_fwnode(dev),
> @@ -561,14 +561,15 @@ static int mxc_gpio_probe(struct platform_device *pdev)
>
> port->domain = devm_irq_domain_instantiate(dev, &d_info);
> if (IS_ERR(port->domain))
> - return PTR_ERR(port->domain);
> + return dev_err_probe(dev, PTR_ERR(port->domain),
> + "Failed to create irq domain\n");
>
> 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 err;
> + return dev_err_probe(dev, err, "Failed to init generic irq chip\n");
>
> /*
> * Register the GPIO chip last: devm_gpiochip_add_data() makes the
> @@ -577,7 +578,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
> */
> err = devm_gpiochip_add_data(dev, &port->gen_gc.gc, port);
> if (err)
> - return err;
> + return dev_err_probe(dev, err, "Failed to add gpiochip data\n");
>
> list_add_tail(&port->node, &mxc_gpio_ports);
>
>
> --
> 2.51.0
>
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v7 10/12] gpio: mxc: introduce MXC_ICR macros and use field_prep/field_get
2026-10-27 12:09 [PATCH v7 00/12] gpio: mxc: probe cleanup Peng Fan (OSS)
` (8 preceding siblings ...)
2026-10-27 12:09 ` [PATCH v7 09/12] gpio: mxc: add dev_err_probe() for error paths to help diagnostics Peng Fan (OSS)
@ 2026-10-27 12:09 ` Peng Fan (OSS)
2026-10-27 12:09 ` [PATCH v7 11/12] gpio: mxc: use BIT() macro for single-bit operations Peng Fan (OSS)
2026-10-27 12:09 ` [PATCH v7 12/12] MAINTAINERS: Add an entry for gpio-mxc Peng Fan (OSS)
11 siblings, 0 replies; 20+ messages in thread
From: Peng Fan (OSS) @ 2026-10-27 12:09 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam
Cc: linux-kernel, linux-gpio, imx, linux-arm-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 0x3U in MXC_ICR_MASK() to avoid implementation-defined behavior
when shifting by 30 bits (pin 15 or 31).
Extract the read-modify-write pattern into icr_update_edge()
and the edge readback into icr_get_edge(), using field_prep() and
field_get() for the shift/extract operations.
No functional change.
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
drivers/gpio/gpio-mxc.c | 42 +++++++++++++++++++++++++-----------------
1 file changed, 25 insertions(+), 17 deletions(-)
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index f816822e36ad..87460dab67fa 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/bitops.h>
#include <linux/cleanup.h>
#include <linux/clk.h>
@@ -189,6 +190,9 @@ static inline bool mxc_gpio_has_power_off(struct mxc_gpio_port *port)
#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) (0x3U << (((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 },
@@ -211,14 +215,28 @@ static LIST_HEAD(mxc_gpio_ports);
/* Note: This driver assumes 32 GPIOs are handled in one register */
+static void icr_update_edge(struct mxc_gpio_port *port, u32 gpio, u32 edge)
+{
+ void __iomem *reg = port->base;
+ u32 val;
+
+ reg += MXC_ICR_REG(gpio);
+ val = readl(reg) & ~MXC_ICR_MASK(gpio);
+ writel(val | field_prep(MXC_ICR_MASK(gpio), edge), reg);
+}
+
+static u32 icr_get_edge(struct mxc_gpio_port *port, u32 gpio)
+{
+ return field_get(MXC_ICR_MASK(gpio), readl(port->base + MXC_ICR_REG(gpio)));
+}
+
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;
clear_bit(gpio_idx, &port->both_edges);
switch (type) {
@@ -264,12 +282,8 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
port->base + GPIO_EDGE_SEL);
}
- 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);
- }
+ if (edge != GPIO_INT_BOTH_EDGES)
+ icr_update_edge(port, gpio_idx, edge);
writel(1 << gpio_idx, port->base + GPIO_ISR);
port->pad_type[gpio_idx] = type;
@@ -280,17 +294,11 @@ 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;
- int edge;
+ u32 edge;
guard(gpio_generic_lock_irqsave)(&port->gen_gc);
- reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */
- bit = gpio & 0xf;
- val = readl(reg);
- edge = (val >> (bit << 1)) & 3;
- val &= ~(0x3 << (bit << 1));
+ edge = icr_get_edge(port, gpio);
if (edge == GPIO_INT_HIGH_LEV) {
edge = GPIO_INT_LOW_LEV;
pr_debug("mxc: switch GPIO %d to low trigger\n", gpio);
@@ -302,7 +310,7 @@ static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio)
gpio, edge);
return;
}
- writel(val | (edge << (bit << 1)), reg);
+ icr_update_edge(port, gpio, edge);
}
/* handle 32 interrupts in one status register */
--
2.51.0
^ permalink raw reply [flat|nested] 20+ messages in thread* [PATCH v7 11/12] gpio: mxc: use BIT() macro for single-bit operations
2026-10-27 12:09 [PATCH v7 00/12] gpio: mxc: probe cleanup Peng Fan (OSS)
` (9 preceding siblings ...)
2026-10-27 12:09 ` [PATCH v7 10/12] gpio: mxc: introduce MXC_ICR macros and use field_prep/field_get Peng Fan (OSS)
@ 2026-10-27 12:09 ` Peng Fan (OSS)
2026-10-27 12:09 ` [PATCH v7 12/12] MAINTAINERS: Add an entry for gpio-mxc Peng Fan (OSS)
11 siblings, 0 replies; 20+ messages in thread
From: Peng Fan (OSS) @ 2026-10-27 12:09 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam
Cc: linux-kernel, linux-gpio, imx, linux-arm-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.
Reviewed-by: Linus Walleij <linusw@kernel.org>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
drivers/gpio/gpio-mxc.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index 87460dab67fa..cef0da73b885 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -275,17 +275,17 @@ 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);
}
if (edge != GPIO_INT_BOTH_EDGES)
icr_update_edge(port, gpio_idx, edge);
- writel(1 << gpio_idx, port->base + GPIO_ISR);
+ writel(BIT(gpio_idx), port->base + GPIO_ISR);
port->pad_type[gpio_idx] = type;
}
@@ -324,7 +324,7 @@ static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat)
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 v7 12/12] MAINTAINERS: Add an entry for gpio-mxc
2026-10-27 12:09 [PATCH v7 00/12] gpio: mxc: probe cleanup Peng Fan (OSS)
` (10 preceding siblings ...)
2026-10-27 12:09 ` [PATCH v7 11/12] gpio: mxc: use BIT() macro for single-bit operations Peng Fan (OSS)
@ 2026-10-27 12:09 ` Peng Fan (OSS)
2026-10-27 14:14 ` Frank Li
11 siblings, 1 reply; 20+ messages in thread
From: Peng Fan (OSS) @ 2026-10-27 12:09 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam
Cc: linux-kernel, linux-gpio, imx, linux-arm-kernel, Peng Fan
From: Peng Fan <peng.fan@nxp.com>
Add myself as gpio-mxc maintainer
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
MAINTAINERS | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index fcff12847485..a7aa9a587496 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10738,6 +10738,14 @@ F: drivers/perf/fsl_imx8_ddr_perf.c
F: drivers/perf/fsl_imx9_ddr_perf.c
F: tools/perf/pmu-events/arch/arm64/freescale/
+FREESCALE IMX GPIO DRIVER
+M: Peng Fan <peng.fan@nxp.com>
+L: linux-gpio@vger.kernel.org
+L: imx@lists.linux.dev
+S: Maintained
+F: Documentation/devicetree/bindings/gpio/fsl-imx-gpio.yaml
+F: drivers/gpio/gpio-mxc.c
+
FREESCALE IMX I2C DRIVER
M: Oleksij Rempel <o.rempel@pengutronix.de>
R: Pengutronix Kernel Team <kernel@pengutronix.de>
--
2.51.0
^ permalink raw reply [flat|nested] 20+ messages in thread* Re: [PATCH v7 12/12] MAINTAINERS: Add an entry for gpio-mxc
2026-10-27 12:09 ` [PATCH v7 12/12] MAINTAINERS: Add an entry for gpio-mxc Peng Fan (OSS)
@ 2026-10-27 14:14 ` Frank Li
0 siblings, 0 replies; 20+ messages in thread
From: Frank Li @ 2026-10-27 14:14 UTC (permalink / raw)
To: Peng Fan (OSS)
Cc: Linus Walleij, Bartosz Golaszewski, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, linux-kernel, linux-gpio,
imx, linux-arm-kernel, Peng Fan
On Tue, Oct 27, 2026 at 08:09:39PM +0800, Peng Fan (OSS) wrote:
> From: Peng Fan <peng.fan@nxp.com>
>
> Add myself as gpio-mxc maintainer
>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> ---
Reviewed-by: Frank Li <Frank.Li@nxp.com>
> MAINTAINERS | 8 ++++++++
> 1 file changed, 8 insertions(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index fcff12847485..a7aa9a587496 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -10738,6 +10738,14 @@ F: drivers/perf/fsl_imx8_ddr_perf.c
> F: drivers/perf/fsl_imx9_ddr_perf.c
> F: tools/perf/pmu-events/arch/arm64/freescale/
>
> +FREESCALE IMX GPIO DRIVER
> +M: Peng Fan <peng.fan@nxp.com>
> +L: linux-gpio@vger.kernel.org
> +L: imx@lists.linux.dev
> +S: Maintained
> +F: Documentation/devicetree/bindings/gpio/fsl-imx-gpio.yaml
> +F: drivers/gpio/gpio-mxc.c
> +
> FREESCALE IMX I2C DRIVER
> M: Oleksij Rempel <o.rempel@pengutronix.de>
> R: Pengutronix Kernel Team <kernel@pengutronix.de>
>
> --
> 2.51.0
>
>
^ permalink raw reply [flat|nested] 20+ messages in thread