[PATCH 1/2] gpio: vybrid: read and write the GPIO block, not the PORT block

Mehmet Fide <[email protected]> Thu, 6 Aug 2026 14:47:59 +0200
Newsgroups gmane.comp.boot-loaders.u-boot
Message-ID <20260806124800.262013-2-mehmet.fide__38654.5558738121$1786021537$gmane$org@gmail.com>
From: Mehmet Fide <[email protected]>

The Vybrid GPIO node describes two register ranges: the PORT block, which
holds the pin control and interrupt registers, and the GPIO block, which
holds the registers this driver touches (PDOR, PSOR, PCOR, PTOR, PDIR):

	gpio0: gpio@40049000 {
		compatible = "fsl,vf610-gpio";
		reg = <0x40049000 0x1000 0x400ff000 0x40>;

vybrid_gpio_odata_to_plat() takes the first range, so every set, clear and
read goes to the PORT block: an output never changes level, an input
returns a pin control register, and the write lands on the pin control
register of an unrelated pad. The gpio command reports success either way.

The direction is not affected. imx_iomux_gpio_set_direction() applies
IOMUXC itself, so a pin requested as an output is driven, but always to
the reset value of PDOR.

The single range device tree this driver was written against described the
GPIO block alone:

	gpio1: gpio@400ff000 {
		compatible = "fsl,vf610-gpio";
		reg = <0x400ff000 0x40>;

so the first range was the right one until the device trees were
synchronised with Linux. Take the second range when the node has one and
keep the first as the fallback, which is what the Linux driver does for the
single range imx7ulp binding.

Tested on a Colibri VF50: with the fix "gpio set 50" sets bit 18 of PDOR in
the GPIO block at 0x400ff040 and the pin drives its load, and the display
reset and backlight lines the board wires to GPIOs work again. Without it
the register never changes.

Fixes: e8a9521e649f ("vf500/vf610: synchronise device trees with linux")
Signed-off-by: Mehmet Fide <[email protected]>
---
 drivers/gpio/vybrid_gpio.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/gpio/vybrid_gpio.c b/drivers/gpio/vybrid_gpio.c
index 5b4bba96da7..3d2e16e8ef3 100644
--- a/drivers/gpio/vybrid_gpio.c
+++ b/drivers/gpio/vybrid_gpio.c
@@ -109,7 +109,13 @@ static int vybrid_gpio_odata_to_plat(struct udevice *dev)
 	struct vybrid_gpio_plat *plat = dev_get_plat(dev);
 	fdt_addr_t base_addr;
 
-	base_addr = dev_read_addr(dev);
+	/*
+	 * The first reg range is the PORT block (pin control), the second one
+	 * the GPIO block this driver reads and writes.
+	 */
+	base_addr = dev_read_addr_index(dev, 1);
+	if (base_addr == FDT_ADDR_T_NONE)
+		base_addr = dev_read_addr(dev);
 	if (base_addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
-- 
2.54.0