[PATCH 4/7] pinctrl: renesas: rzt2h: fix reading pin value in IRQ function
From: Cosmin Tanislav
Date: Mon Aug 17 2026 - 15:00:17 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>
---
drivers/pinctrl/renesas/pinctrl-rzt2h.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/drivers/pinctrl/renesas/pinctrl-rzt2h.c b/drivers/pinctrl/renesas/pinctrl-rzt2h.c
index 287cacbcb37b..b8d5b6af5be4 100644
--- 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)
+ 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)
--
2.55.0