Skip to content
/ linux Public

Commit e86bc71

Browse files
Demon000Sasha Levin
authored andcommitted
pinctrl: renesas: rzt2h: Allow .get_direction() for IRQ function GPIOs
[ Upstream commit 49b039a ] Setting up an IRQ would normally be done in the .activate() and .deactivate() ops of the IRQ domain, but for hierarchical IRQ domains the .activate() and .deactivate() ops are overridden in the gpiochip_hierarchy_setup_domain_ops() function. As such, activating and deactivating need to be done in the .translate() and .free() ops of the IRQ domain. For RZ/T2H and RZ/N2H, interrupts go through the pin controller, into the ICU, which level-translates them and forwards them to the GIC. To use a GPIO as an interrupt it needs to be put into peripheral function mode 0, which will connect it to the IRQ lines of the ICU. The IRQ chip .child_to_parent_hwirq() callback is called as part of the IRQ fwspec parsing logic (as part of irq_create_of_mapping()) which happens before the IRQ is requested (as part of gpiochip_lock_as_irq()). gpiochip_lock_as_irq() calls gpiod_get_direction() if the .get_direction() callback is provided to ensure that the GPIO line is set up as input. In our case, IRQ function is separate from GPIO, and both cannot be true at the same time. Return GPIO_LINE_DIRECTION_IN even if pin is in IRQ function to allow this setup to work. Hold the spinlock to ensure atomicity between reading the PMC register (which determines whether the pin is in GPIO mode or not) and reading the function of the pin when it is not in GPIO mode. Signed-off-by: Cosmin Tanislav <cosmin-gabriel.tanislav.xa@renesas.com> Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be> Link: https://patch.msgid.link/20251205150234.2958140-3-cosmin-gabriel.tanislav.xa@renesas.com Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent d297560 commit e86bc71

File tree

1 file changed

+20
-1
lines changed

1 file changed

+20
-1
lines changed

drivers/pinctrl/renesas/pinctrl-rzt2h.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151

5252
#define PFC_MASK GENMASK_ULL(5, 0)
5353
#define PFC_PIN_MASK(pin) (PFC_MASK << ((pin) * 8))
54+
#define PFC_FUNC_INTERRUPT 0
5455

5556
/*
5657
* Use 16 lower bits [15:0] for pin identifier
@@ -486,15 +487,33 @@ static int rzt2h_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
486487
struct rzt2h_pinctrl *pctrl = gpiochip_get_data(chip);
487488
u8 port = RZT2H_PIN_ID_TO_PORT(offset);
488489
u8 bit = RZT2H_PIN_ID_TO_PIN(offset);
490+
u64 reg64;
489491
u16 reg;
490492
int ret;
491493

492494
ret = rzt2h_validate_pin(pctrl, offset);
493495
if (ret)
494496
return ret;
495497

496-
if (rzt2h_pinctrl_readb(pctrl, port, PMC(port)) & BIT(bit))
498+
guard(spinlock_irqsave)(&pctrl->lock);
499+
500+
if (rzt2h_pinctrl_readb(pctrl, port, PMC(port)) & BIT(bit)) {
501+
/*
502+
* When a GPIO is being requested as an IRQ, the pinctrl
503+
* framework expects to be able to read the GPIO's direction.
504+
* IRQ function is separate from GPIO, and enabling it takes the
505+
* pin out of GPIO mode.
506+
* At this point, .child_to_parent_hwirq() has already been
507+
* called to enable the IRQ function.
508+
* Default to input direction for IRQ function.
509+
*/
510+
reg64 = rzt2h_pinctrl_readq(pctrl, port, PFC(port));
511+
reg64 = (reg64 >> (bit * 8)) & PFC_MASK;
512+
if (reg64 == PFC_FUNC_INTERRUPT)
513+
return GPIO_LINE_DIRECTION_IN;
514+
497515
return -EINVAL;
516+
}
498517

499518
reg = rzt2h_pinctrl_readw(pctrl, port, PM(port));
500519
reg = (reg >> (bit * 2)) & PM_MASK;

0 commit comments

Comments
 (0)