[PATCH v4 13/14] gpio: ad7768: Add AD7768 GPIO auxiliary driver

From: Janani Sunil

Date: Fri Aug 21 2026 - 10:15:01 EST


The AD7768 provides five GPIOs controlled through registers shared
with the parent IIO device. Register an auxiliary gpio-regmap driver
and use the parent device for runtime PM.

The device has separate input-state and output-latch registers. Add a
reg_mask_xlate() callback that checks the line direction and reads the
programmed output latch for output lines while retaining input-state
reads for input lines.

Signed-off-by: Janani Sunil <janani.sunil@xxxxxxxxxx>
---
MAINTAINERS | 1 +
drivers/gpio/Kconfig | 12 +++++
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-ad7768.c | 118 +++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 132 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index dc94e7803a7c..3de7ebcc4ee7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1639,6 +1639,7 @@ L: linux-iio@xxxxxxxxxxxxxxx
S: Supported
W: https://ez.analog.com/linux-software-drivers
F: Documentation/devicetree/bindings/iio/adc/adi,ad7768.yaml
+F: drivers/gpio/gpio-ad7768.c
F: drivers/iio/adc/ad7768.c

ANALOG DEVICES INC AD7780 DRIVER
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 28cf6d2e83c2..85cb0c82a823 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -1796,6 +1796,18 @@ endmenu
menu "Auxiliary Bus GPIO drivers"
depends on AUXILIARY_BUS

+config GPIO_AD7768
+ tristate "Analog Devices AD7768 GPIO support"
+ depends on AD7768
+ depends on GPIOLIB
+ select GPIO_REGMAP
+ help
+ Say yes here to expose the AD7768 utility pins as GPIOs when the
+ device tree node is marked as a GPIO controller.
+
+ To compile this driver as a module, choose M here: the module will be
+ called gpio-ad7768.
+
config GPIO_LTC4283
tristate "Analog Devices LTC4283 GPIO support"
depends on SENSORS_LTC4283
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 4d0e900402fc..d2921963efc7 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_GPIO_104_IDI_48) += gpio-104-idi-48.o
obj-$(CONFIG_GPIO_104_IDIO_16) += gpio-104-idio-16.o
obj-$(CONFIG_GPIO_74X164) += gpio-74x164.o
obj-$(CONFIG_GPIO_74XX_MMIO) += gpio-74xx-mmio.o
+obj-$(CONFIG_GPIO_AD7768) += gpio-ad7768.o
obj-$(CONFIG_GPIO_ADNP) += gpio-adnp.o
obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o
obj-$(CONFIG_GPIO_ADP5585) += gpio-adp5585.o
diff --git a/drivers/gpio/gpio-ad7768.c b/drivers/gpio/gpio-ad7768.c
new file mode 100644
index 000000000000..710739e33dff
--- /dev/null
+++ b/drivers/gpio/gpio-ad7768.c
@@ -0,0 +1,118 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Analog Devices AD7768 GPIO auxiliary driver
+ *
+ * Copyright 2026 Analog Devices Inc.
+ */
+
+#include <linux/auxiliary_bus.h>
+#include <linux/bitmap.h>
+#include <linux/bits.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/gpio/driver.h>
+#include <linux/gpio/regmap.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+
+#define AD7768_REG_GPIO_CONTROL 0x0E
+#define AD7768_GPIO_UGPIO_ENABLE BIT(7)
+
+#define AD7768_REG_GPIO_WRITE 0x0F
+#define AD7768_REG_GPIO_READ 0x10
+
+#define AD7768_NUM_GPIOS 5
+
+static int ad7768_gpio_init_valid_mask(struct gpio_chip *gc,
+ unsigned long *valid_mask,
+ unsigned int ngpios)
+{
+ unsigned long *mask = dev_get_platdata(gc->parent);
+
+ bitmap_copy(valid_mask, mask, ngpios);
+
+ return 0;
+}
+
+static int ad7768_gpio_reg_mask_xlate(struct gpio_regmap *gpio,
+ unsigned int base, unsigned int offset,
+ unsigned int *reg, unsigned int *mask)
+{
+ struct regmap *regmap = gpio_regmap_get_drvdata(gpio);
+ int ret;
+
+ *reg = base;
+ *mask = BIT(offset);
+
+ if (base != AD7768_REG_GPIO_READ)
+ return 0;
+
+ /*
+ * AD7768 has separate input-state and output-latch registers. For an
+ * output line, report the programmed value from the output latch;
+ * input lines continue to use the input-state register.
+ */
+ ret = regmap_test_bits(regmap, AD7768_REG_GPIO_CONTROL, *mask);
+ if (ret < 0)
+ return ret;
+ if (ret)
+ *reg = AD7768_REG_GPIO_WRITE;
+
+ return 0;
+}
+
+static int ad7768_gpio_probe(struct auxiliary_device *adev,
+ const struct auxiliary_device_id *id)
+{
+ struct device *parent = adev->dev.parent;
+ struct gpio_regmap_config config = {
+ .parent = &adev->dev,
+ .label = dev_name(parent),
+ .ngpio = AD7768_NUM_GPIOS,
+ .reg_dat_base = AD7768_REG_GPIO_READ,
+ .reg_set_base = AD7768_REG_GPIO_WRITE,
+ .reg_dir_out_base = AD7768_REG_GPIO_CONTROL,
+ .pm_dev = parent,
+ .reg_mask_xlate = ad7768_gpio_reg_mask_xlate,
+ .init_valid_mask = ad7768_gpio_init_valid_mask,
+ };
+ struct gpio_regmap *gpio;
+ struct regmap *map;
+ int ret;
+
+ map = dev_get_regmap(parent, NULL);
+ if (!map)
+ return -ENODEV;
+
+ PM_RUNTIME_ACQUIRE_AUTOSUSPEND(parent, pm);
+ ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+ if (ret)
+ return ret;
+
+ ret = regmap_set_bits(map, AD7768_REG_GPIO_CONTROL, AD7768_GPIO_UGPIO_ENABLE);
+ if (ret)
+ return ret;
+
+ config.regmap = map;
+ config.drvdata = map;
+
+ gpio = devm_gpio_regmap_register(&adev->dev, &config);
+ return PTR_ERR_OR_ZERO(gpio);
+}
+
+static const struct auxiliary_device_id ad7768_gpio_ids[] = {
+ { .name = "ad7768.gpio" },
+ { }
+};
+MODULE_DEVICE_TABLE(auxiliary, ad7768_gpio_ids);
+
+static struct auxiliary_driver ad7768_gpio_driver = {
+ .probe = ad7768_gpio_probe,
+ .id_table = ad7768_gpio_ids,
+};
+module_auxiliary_driver(ad7768_gpio_driver);
+
+MODULE_AUTHOR("Janani Sunil <janani.sunil@xxxxxxxxxx>");
+MODULE_DESCRIPTION("Analog Devices AD7768 GPIO auxiliary driver");
+MODULE_LICENSE("GPL");

--
2.43.0