[PATCH v3 3/5] pinctrl: renesas: rzt2h: fix reading pin value in IRQ function
From: Cosmin Tanislav
Date: Sun Sep 13 2026 - 15:59:27 EST
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>
---
V3:
* move leftover unused function to a later patch
V2:
* remove the PFC_FUNC_INTERRUPT check in rzt2h_gpio_get()
drivers/pinctrl/renesas/pinctrl-rzt2h.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/pinctrl/renesas/pinctrl-rzt2h.c b/drivers/pinctrl/renesas/pinctrl-rzt2h.c
index 796120e70bc4..9d7e4cba85c9 100644
--- a/drivers/pinctrl/renesas/pinctrl-rzt2h.c
+++ b/drivers/pinctrl/renesas/pinctrl-rzt2h.c
@@ -170,6 +170,16 @@ 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 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 +857,9 @@ 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))
+ return rzt2h_pin_read_input(pctrl, port, bit);
+
reg = rzt2h_pinctrl_readw(pctrl, port, PM(port));
reg = (reg >> (bit * 2)) & PM_MASK;
if (reg & PM_INPUT)
--
2.55.0