[PATCH v2 2/2] pinctrl: renesas: rzg2l: Drop the unnecessary pin configurations

Biju posted 2 patches 1 month, 2 weeks ago
[PATCH v2 2/2] pinctrl: renesas: rzg2l: Drop the unnecessary pin configurations
Posted by Biju 1 month, 2 weeks ago
From: Biju Das <biju.das.jz@bp.renesas.com>

There is no need to reconfigure the pin if the pin's configuration values
are same as the reset values. E.g.: PS0 pin configuration for NMI function
is PMC = 1 and PFC = 0 and is same as that of reset values. Currently the
code is first setting it to GPIO HI-Z state and then again reconfiguring
to NMI function leading to spurious IRQ. Drop the unnecessary pin
configurations from the driver.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
---
v1->v2:
 * Updated commit header and description.
 * Added check in rzg2l_pinctrl_set_pfc_mode() to avoid unnecessary
   configuration
 * Updated rzg2l_pinctrl_pm_setup_pfc() to make changes minimal.
---
 drivers/pinctrl/renesas/pinctrl-rzg2l.c | 22 ++++++++++++++++------
 1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c
index 2b5d16594bb7..8422a5429ca3 100644
--- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c
+++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c
@@ -539,7 +539,11 @@ static void rzg2l_pinctrl_set_pfc_mode(struct rzg2l_pinctrl *pctrl,
 				       u8 pin, u8 off, u8 func)
 {
 	unsigned long flags;
-	u32 reg;
+	u32 reg, pfc;
+
+	pfc = readl(pctrl->base + PFC(off));
+	if (((pfc >> (pin * 4)) & PFC_MASK)  == func)
+		return;
 
 	spin_lock_irqsave(&pctrl->lock, flags);
 
@@ -555,9 +559,8 @@ static void rzg2l_pinctrl_set_pfc_mode(struct rzg2l_pinctrl *pctrl,
 	writeb(reg & ~BIT(pin), pctrl->base + PMC(off));
 
 	/* Select Pin function mode with PFC register */
-	reg = readl(pctrl->base + PFC(off));
-	reg &= ~(PFC_MASK << (pin * 4));
-	writel(reg | (func << (pin * 4)), pctrl->base + PFC(off));
+	pfc &= ~(PFC_MASK << (pin * 4));
+	writel(pfc | (func << (pin * 4)), pctrl->base + PFC(off));
 
 	/* Switch to Peripheral pin function with PMC register */
 	reg = readb(pctrl->base + PMC(off));
@@ -3103,11 +3106,18 @@ static void rzg2l_pinctrl_pm_setup_pfc(struct rzg2l_pinctrl *pctrl)
 		pm = readw(pctrl->base + PM(off));
 		for_each_set_bit(pin, &pinmap, max_pin) {
 			struct rzg2l_pinctrl_reg_cache *cache = pctrl->cache;
+			u32 pfc_val, pfc_mask;
 
 			/* Nothing to do if PFC was not configured before. */
 			if (!(cache->pmc[port] & BIT(pin)))
 				continue;
 
+			pfc_val = readl(pctrl->base + PFC(off));
+			pfc_mask = PFC_MASK << (pin * 4);
+			/* Nothing to do if reset value of the pin is same as cached value */
+			if ((cache->pfc[port] & pfc_mask) == (pfc_val & pfc_mask))
+				continue;
+
 			/* Set pin to 'Non-use (Hi-Z input protection)' */
 			pm &= ~(PM_MASK << (pin * 2));
 			writew(pm, pctrl->base + PM(off));
@@ -3117,8 +3127,8 @@ static void rzg2l_pinctrl_pm_setup_pfc(struct rzg2l_pinctrl *pctrl)
 			writeb(pmc, pctrl->base + PMC(off));
 
 			/* Select Pin function mode. */
-			pfc &= ~(PFC_MASK << (pin * 4));
-			pfc |= (cache->pfc[port] & (PFC_MASK << (pin * 4)));
+			pfc &= ~pfc_mask;
+			pfc |= (cache->pfc[port] & pfc_mask);
 			writel(pfc, pctrl->base + PFC(off));
 
 			/* Switch to Peripheral pin function. */
-- 
2.43.0
Re: [PATCH v2 2/2] pinctrl: renesas: rzg2l: Drop the unnecessary pin configurations
Posted by Geert Uytterhoeven 4 weeks, 1 day ago
Hi Biju,

On Sun, 17 Aug 2025 at 16:30, Biju <biju.das.au@gmail.com> wrote:
> From: Biju Das <biju.das.jz@bp.renesas.com>
>
> There is no need to reconfigure the pin if the pin's configuration values
> are same as the reset values. E.g.: PS0 pin configuration for NMI function
> is PMC = 1 and PFC = 0 and is same as that of reset values. Currently the
> code is first setting it to GPIO HI-Z state and then again reconfiguring
> to NMI function leading to spurious IRQ. Drop the unnecessary pin
> configurations from the driver.
>
> Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>

Thanks for your patch!

> --- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c
> +++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c
> @@ -539,7 +539,11 @@ static void rzg2l_pinctrl_set_pfc_mode(struct rzg2l_pinctrl *pctrl,
>                                        u8 pin, u8 off, u8 func)
>  {
>         unsigned long flags;
> -       u32 reg;
> +       u32 reg, pfc;
> +
> +       pfc = readl(pctrl->base + PFC(off));

As the read value may be used later, shouldn't it be read while holding
the spinlock below?

> +       if (((pfc >> (pin * 4)) & PFC_MASK)  == func)

Please drop the second space before the == operator.

> +               return;

What if the pin is currently configured for GPIO in the PMC register?
According to the documentation, that is even the initial state after reset.

>
>         spin_lock_irqsave(&pctrl->lock, flags);
>
> @@ -555,9 +559,8 @@ static void rzg2l_pinctrl_set_pfc_mode(struct rzg2l_pinctrl *pctrl,
>         writeb(reg & ~BIT(pin), pctrl->base + PMC(off));
>
>         /* Select Pin function mode with PFC register */
> -       reg = readl(pctrl->base + PFC(off));
> -       reg &= ~(PFC_MASK << (pin * 4));
> -       writel(reg | (func << (pin * 4)), pctrl->base + PFC(off));
> +       pfc &= ~(PFC_MASK << (pin * 4));
> +       writel(pfc | (func << (pin * 4)), pctrl->base + PFC(off));
>
>         /* Switch to Peripheral pin function with PMC register */
>         reg = readb(pctrl->base + PMC(off));
> @@ -3103,11 +3106,18 @@ static void rzg2l_pinctrl_pm_setup_pfc(struct rzg2l_pinctrl *pctrl)
>                 pm = readw(pctrl->base + PM(off));
>                 for_each_set_bit(pin, &pinmap, max_pin) {
>                         struct rzg2l_pinctrl_reg_cache *cache = pctrl->cache;
> +                       u32 pfc_val, pfc_mask;
>
>                         /* Nothing to do if PFC was not configured before. */
>                         if (!(cache->pmc[port] & BIT(pin)))
>                                 continue;
>
> +                       pfc_val = readl(pctrl->base + PFC(off));
> +                       pfc_mask = PFC_MASK << (pin * 4);
> +                       /* Nothing to do if reset value of the pin is same as cached value */
> +                       if ((cache->pfc[port] & pfc_mask) == (pfc_val & pfc_mask))
> +                               continue;

What if the pin is currently configured for GPIO in the PMC register?

> +
>                         /* Set pin to 'Non-use (Hi-Z input protection)' */
>                         pm &= ~(PM_MASK << (pin * 2));
>                         writew(pm, pctrl->base + PM(off));
> @@ -3117,8 +3127,8 @@ static void rzg2l_pinctrl_pm_setup_pfc(struct rzg2l_pinctrl *pctrl)
>                         writeb(pmc, pctrl->base + PMC(off));
>
>                         /* Select Pin function mode. */
> -                       pfc &= ~(PFC_MASK << (pin * 4));
> -                       pfc |= (cache->pfc[port] & (PFC_MASK << (pin * 4)));
> +                       pfc &= ~pfc_mask;
> +                       pfc |= (cache->pfc[port] & pfc_mask);
>                         writel(pfc, pctrl->base + PFC(off));
>
>                         /* Switch to Peripheral pin function. */

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds