Re: [PATCH 4/7] pinctrl: renesas: rzt2h: fix reading pin value in IRQ function
From: Geert Uytterhoeven
Date: Tue Sep 08 2026 - 06:28:30 EST
Hi Cosmin,
On Mon, 17 Aug 2026 at 20:58, Cosmin Tanislav
<cosmin-gabriel.tanislav.xa@xxxxxxxxxxx> wrote:
> rzt2h_gpio_get() only reports a level for pins in input or output mode
> and returns -EINVAL otherwise. When a pin is requested as an interrupt
> it is switched to IRQ function and its I/O mode is set to Hi-Z, so its
> value can no longer be read.
>
> gpiolib calls gpiod_get_value_cansleep() to determine the edge's
> direction when a line is watched with GPIO_V2_LINE_FLAG_EDGE_BOTH.
> Non-zero values are translated to a rising edge, zero to a falling edge.
>
> Since gpiod_get_value_cansleep() ends up calling rzt2h_gpio_get() which
> returns -EINVAL when the pin is in IRQ function, every edge is reported
> as rising.
>
> When using the IRQ function, the input buffers are enabled and the PINm
> registers reflect the live state of the input.
>
> Report the input level even when the pin is used as an IRQ.
>
> Cc: stable@xxxxxxxxxx
> Fixes: 829dde3369a9 ("pinctrl: renesas: rzt2h: Add GPIO IRQ chip to handle interrupts")
> Signed-off-by: Cosmin Tanislav <cosmin-gabriel.tanislav.xa@xxxxxxxxxxx>
Thanks for your patch!
> --- a/drivers/pinctrl/renesas/pinctrl-rzt2h.c
> +++ b/drivers/pinctrl/renesas/pinctrl-rzt2h.c
> @@ -171,6 +171,23 @@ static int rzt2h_validate_pin(struct rzt2h_pinctrl *pctrl, unsigned int offset)
> return (pincfg & BIT(pin)) ? 0 : -EINVAL;
> }
>
> +static bool rzt2h_pin_mode_is_peripheral(struct rzt2h_pinctrl *pctrl, u8 port, u8 bit)
> +{
> + return rzt2h_pinctrl_readb(pctrl, port, PMC(port)) & BIT(bit);
> +}
> +
> +static u8 rzt2h_pin_read_pfc(struct rzt2h_pinctrl *pctrl, u8 port, u8 pin)
> +{
> + u64 reg64 = rzt2h_pinctrl_readq(pctrl, port, PFC(port));
> +
> + return field_get(PFC_PIN_MASK(pin), reg64);
> +}
> +
> +static bool rzt2h_pin_read_input(struct rzt2h_pinctrl *pctrl, u8 port, u8 bit)
> +{
> + return rzt2h_pinctrl_readb(pctrl, port, PIN(port)) & BIT(bit);
> +}
> +
> static u8 rzt2h_pin_read_pm(struct rzt2h_pinctrl *pctrl, u8 port, u8 pin)
> {
> u16 reg = rzt2h_pinctrl_readw(pctrl, port, PM(port));
> @@ -847,6 +864,13 @@ static int rzt2h_gpio_get(struct gpio_chip *chip, unsigned int offset)
> u8 bit = RZT2H_PIN_ID_TO_PIN(offset);
> u16 reg;
>
> + if (rzt2h_pin_mode_is_peripheral(pctrl, port, bit)) {
> + if (rzt2h_pin_read_pfc(pctrl, port, bit) == PFC_FUNC_INTERRUPT)
Section 17.4.5 ("PINm : Port m Input Register (m = 00 to 35)") states:
"The PINm register is valid not only for general I/O mode (PMCn = 0b)
but also when peripheral function is selected (PMCn = 1b) and it works
as input."
this is not limited to PFC_FUNC_INTERRUPT, so I think you can drop
this check?
> + return rzt2h_pin_read_input(pctrl, port, bit);
> +
> + return -EINVAL;
> + }
> +
> reg = rzt2h_pinctrl_readw(pctrl, port, PM(port));
> reg = (reg >> (bit * 2)) & PM_MASK;
> if (reg & PM_INPUT)
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@xxxxxxxxxxxxxx
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