Skip to content

Commit 6d3bbcf

Browse files
committed
gpio: gpio-adg1414: add ADG1414
The ADG1414 is a set of octal, single-pole, single-throw (SPST) switches controlled via a 3-wire serial interface. On resistance is matched closely between switches and is very flat over the full signal range. Each switch conducts equally well in both directions and the input signal range extends to the supplies. Data is written to these devices in the form of eight bits; each bit corresponds to one channel. Signed-off-by: Kim Seer Paller <[email protected]>
1 parent b2cc2a3 commit 6d3bbcf

3 files changed

Lines changed: 166 additions & 0 deletions

File tree

drivers/gpio/Kconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1708,6 +1708,16 @@ config GPIO_74X164
17081708
shift registers. This driver can be used to provide access
17091709
to more GPIO outputs.
17101710

1711+
config GPIO_ADG1414
1712+
tristate "ADG1414 SPST Switch Driver"
1713+
depends on GPIOLIB && SPI
1714+
help
1715+
Say yes here to build support for Analog Devices ADG1414 SPST
1716+
Switch Driver
1717+
1718+
To compile this driver as a module, choose M here: the
1719+
module will be called gpio-adg1414.
1720+
17111721
config GPIO_ADI_DAQ1
17121722
tristate "Analog Devices AD-FMCDAQ1-EBZ SPI-GPIO expander driver"
17131723
help

drivers/gpio/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ obj-$(CONFIG_GPIO_104_IDI_48) += gpio-104-idi-48.o
2424
obj-$(CONFIG_GPIO_104_IDIO_16) += gpio-104-idio-16.o
2525
obj-$(CONFIG_GPIO_74X164) += gpio-74x164.o
2626
obj-$(CONFIG_GPIO_74XX_MMIO) += gpio-74xx-mmio.o
27+
obj-$(CONFIG_GPIO_ADG1414) += gpio-adg1414.o
2728
obj-$(CONFIG_GPIO_ADI_DAQ1) += gpio-adi-daq1.o
2829
obj-$(CONFIG_GPIO_ADNP) += gpio-adnp.o
2930
obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o

drivers/gpio/gpio-adg1414.c

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* ADG1414 Serially-Controlled Octal SPST Switches Driver
4+
*
5+
* Copyright 2025 Analog Devices Inc.
6+
*/
7+
8+
#include <linux/delay.h>
9+
#include <linux/gpio/consumer.h>
10+
#include <linux/gpio/driver.h>
11+
#include <linux/module.h>
12+
#include <linux/property.h>
13+
#include <linux/spi/spi.h>
14+
15+
#define ADG1414_MAX_DEVICES 4
16+
17+
struct adg1414_state {
18+
struct spi_device *spi;
19+
struct gpio_chip chip;
20+
/* lock to protect against multiple access to the device and shared data */
21+
struct mutex lock;
22+
23+
u8 buffer[];
24+
};
25+
26+
static int adg1414_write_config(struct adg1414_state *st)
27+
{
28+
return spi_write(st->spi, st->buffer, st->chip.ngpio / 8);
29+
}
30+
31+
static int adg1414_get_value(struct gpio_chip *chip, unsigned int offset)
32+
{
33+
struct adg1414_state *st = gpiochip_get_data(chip);
34+
u8 bank, pin;
35+
36+
guard(mutex)(&st->lock);
37+
bank = (chip->ngpio / 8) - 1 - offset / 8;
38+
pin = offset % 8;
39+
40+
return (st->buffer[bank] >> pin) & 0x1;
41+
}
42+
43+
static void adg1414_set_value(struct gpio_chip *chip, unsigned int offset,
44+
int val)
45+
{
46+
struct adg1414_state *st = gpiochip_get_data(chip);
47+
u8 bank, pin;
48+
49+
guard(mutex)(&st->lock);
50+
bank = (chip->ngpio / 8) - 1 - offset / 8;
51+
pin = offset % 8;
52+
53+
if (val)
54+
st->buffer[bank] |= BIT(pin);
55+
else
56+
st->buffer[bank] &= ~BIT(pin);
57+
58+
adg1414_write_config(st);
59+
}
60+
61+
static void adg1414_set_multiple(struct gpio_chip *chip, unsigned long *mask,
62+
unsigned long *bits)
63+
{
64+
struct adg1414_state *st = gpiochip_get_data(chip);
65+
unsigned long offset, bankmask, bitmask;
66+
size_t bank;
67+
68+
guard(mutex)(&st->lock);
69+
for_each_set_clump8(offset, bankmask, mask, chip->ngpio) {
70+
bank = (chip->ngpio / 8) - 1 - offset / 8;
71+
bitmask = bitmap_get_value8(bits, offset) & bankmask;
72+
73+
st->buffer[bank] &= ~bankmask;
74+
st->buffer[bank] |= bitmask;
75+
}
76+
77+
adg1414_write_config(st);
78+
}
79+
80+
static int adg1414_direction_output(struct gpio_chip *chip, unsigned int offset,
81+
int val)
82+
{
83+
adg1414_set_value(chip, offset, val);
84+
return 0;
85+
}
86+
87+
static int adg1414_probe(struct spi_device *spi)
88+
{
89+
struct device *dev = &spi->dev;
90+
struct adg1414_state *st;
91+
struct gpio_desc *reset;
92+
u32 num_devices;
93+
int ret;
94+
95+
num_devices = 1;
96+
ret = device_property_read_u32(dev, "#daisy-chained-devices",
97+
&num_devices);
98+
if (!ret) {
99+
if (!num_devices || num_devices > ADG1414_MAX_DEVICES)
100+
return dev_err_probe(dev, ret,
101+
"Failed to get daisy-chained-devices property\n");
102+
}
103+
104+
st = devm_kzalloc(dev, sizeof(*st) + num_devices, GFP_KERNEL);
105+
if (!st)
106+
return -ENOMEM;
107+
108+
st->spi = spi;
109+
110+
/* Use reset pin to reset the device */
111+
reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
112+
if (IS_ERR(reset))
113+
return dev_err_probe(dev, PTR_ERR(reset),
114+
"Failed to get reset gpio");
115+
116+
if (reset) {
117+
fsleep(1);
118+
gpiod_set_value_cansleep(reset, 0);
119+
}
120+
121+
st->chip.label = "adg1414";
122+
st->chip.parent = dev;
123+
st->chip.direction_output = adg1414_direction_output;
124+
st->chip.set = adg1414_set_value;
125+
st->chip.get = adg1414_get_value;
126+
st->chip.set_multiple = adg1414_set_multiple;
127+
st->chip.base = -1;
128+
st->chip.ngpio = num_devices * 8;
129+
st->chip.can_sleep = true;
130+
131+
ret = devm_mutex_init(dev, &st->lock);
132+
if (ret)
133+
return ret;
134+
135+
return devm_gpiochip_add_data(dev, &st->chip, st);
136+
}
137+
138+
static const struct of_device_id adg1414_of_match[] = {
139+
{ .compatible = "adi,adg1414-gpio" },
140+
{ }
141+
};
142+
MODULE_DEVICE_TABLE(of, adg1414_of_match);
143+
144+
static struct spi_driver adg1414_driver = {
145+
.driver = {
146+
.name = "adg1414-gpio",
147+
.of_match_table = adg1414_of_match,
148+
},
149+
.probe = adg1414_probe,
150+
};
151+
module_spi_driver(adg1414_driver);
152+
153+
MODULE_AUTHOR("Kim Seer Paller <[email protected]>");
154+
MODULE_DESCRIPTION("ADG1414 Serially-Controlled Octal SPST Switches Driver");
155+
MODULE_LICENSE("GPL");

0 commit comments

Comments
 (0)