1*55c01d37SNuno Sá // SPDX-License-Identifier: GPL-2.0-only
2*55c01d37SNuno Sá /*
3*55c01d37SNuno Sá * Analog Devices LTC4283 GPIO driver
4*55c01d37SNuno Sá *
5*55c01d37SNuno Sá * Copyright 2025 Analog Devices Inc.
6*55c01d37SNuno Sá */
7*55c01d37SNuno Sá
8*55c01d37SNuno Sá #include <linux/auxiliary_bus.h>
9*55c01d37SNuno Sá #include <linux/bitfield.h>
10*55c01d37SNuno Sá #include <linux/bitmap.h>
11*55c01d37SNuno Sá #include <linux/bits.h>
12*55c01d37SNuno Sá #include <linux/device.h>
13*55c01d37SNuno Sá #include <linux/gpio/driver.h>
14*55c01d37SNuno Sá #include <linux/module.h>
15*55c01d37SNuno Sá #include <linux/regmap.h>
16*55c01d37SNuno Sá
17*55c01d37SNuno Sá #define LTC4283_PINS_MAX 8
18*55c01d37SNuno Sá #define LTC4283_PGIOX_START_NR 4
19*55c01d37SNuno Sá #define LTC4283_INPUT_STATUS 0x02
20*55c01d37SNuno Sá #define LTC4283_PGIO_CONFIG 0x10
21*55c01d37SNuno Sá #define LTC4283_PGIO_CFG_MASK(pin) \
22*55c01d37SNuno Sá GENMASK(((pin) - LTC4283_PGIOX_START_NR) * 2 + 1, (((pin) - LTC4283_PGIOX_START_NR) * 2))
23*55c01d37SNuno Sá #define LTC4283_PGIO_CONFIG_2 0x11
24*55c01d37SNuno Sá
25*55c01d37SNuno Sá #define LTC4283_ADIO_CONFIG 0x12
26*55c01d37SNuno Sá /* starts at bit 4 */
27*55c01d37SNuno Sá #define LTC4283_ADIOX_CONFIG_MASK(pin) BIT((pin) + 4)
28*55c01d37SNuno Sá #define LTC4283_PGIO_DIR_IN 3
29*55c01d37SNuno Sá #define LTC4283_PGIO_DIR_OUT 2
30*55c01d37SNuno Sá
31*55c01d37SNuno Sá struct ltc4283_gpio {
32*55c01d37SNuno Sá struct gpio_chip gpio_chip;
33*55c01d37SNuno Sá struct regmap *regmap;
34*55c01d37SNuno Sá };
35*55c01d37SNuno Sá
ltc4283_pgio_get_direction(const struct ltc4283_gpio * st,unsigned int off)36*55c01d37SNuno Sá static int ltc4283_pgio_get_direction(const struct ltc4283_gpio *st, unsigned int off)
37*55c01d37SNuno Sá {
38*55c01d37SNuno Sá unsigned int val;
39*55c01d37SNuno Sá int ret;
40*55c01d37SNuno Sá
41*55c01d37SNuno Sá ret = regmap_read(st->regmap, LTC4283_PGIO_CONFIG, &val);
42*55c01d37SNuno Sá if (ret)
43*55c01d37SNuno Sá return ret;
44*55c01d37SNuno Sá
45*55c01d37SNuno Sá val = field_get(LTC4283_PGIO_CFG_MASK(off), val);
46*55c01d37SNuno Sá if (val == LTC4283_PGIO_DIR_IN)
47*55c01d37SNuno Sá return GPIO_LINE_DIRECTION_IN;
48*55c01d37SNuno Sá
49*55c01d37SNuno Sá return GPIO_LINE_DIRECTION_OUT;
50*55c01d37SNuno Sá }
51*55c01d37SNuno Sá
ltc4283_gpio_get_direction(struct gpio_chip * gc,unsigned int off)52*55c01d37SNuno Sá static int ltc4283_gpio_get_direction(struct gpio_chip *gc, unsigned int off)
53*55c01d37SNuno Sá {
54*55c01d37SNuno Sá struct ltc4283_gpio *st = gpiochip_get_data(gc);
55*55c01d37SNuno Sá unsigned int val;
56*55c01d37SNuno Sá int ret;
57*55c01d37SNuno Sá
58*55c01d37SNuno Sá if (off >= LTC4283_PGIOX_START_NR)
59*55c01d37SNuno Sá return ltc4283_pgio_get_direction(st, off);
60*55c01d37SNuno Sá
61*55c01d37SNuno Sá ret = regmap_read(st->regmap, LTC4283_ADIO_CONFIG, &val);
62*55c01d37SNuno Sá if (ret)
63*55c01d37SNuno Sá return ret;
64*55c01d37SNuno Sá
65*55c01d37SNuno Sá if (val & LTC4283_ADIOX_CONFIG_MASK(off))
66*55c01d37SNuno Sá return GPIO_LINE_DIRECTION_IN;
67*55c01d37SNuno Sá
68*55c01d37SNuno Sá return GPIO_LINE_DIRECTION_OUT;
69*55c01d37SNuno Sá }
70*55c01d37SNuno Sá
ltc4283_gpio_direction_set(const struct ltc4283_gpio * st,unsigned int off,bool input)71*55c01d37SNuno Sá static int ltc4283_gpio_direction_set(const struct ltc4283_gpio *st,
72*55c01d37SNuno Sá unsigned int off, bool input)
73*55c01d37SNuno Sá {
74*55c01d37SNuno Sá if (off >= LTC4283_PGIOX_START_NR) {
75*55c01d37SNuno Sá unsigned int val = LTC4283_PGIO_DIR_OUT;
76*55c01d37SNuno Sá
77*55c01d37SNuno Sá if (input)
78*55c01d37SNuno Sá val = LTC4283_PGIO_DIR_IN;
79*55c01d37SNuno Sá
80*55c01d37SNuno Sá val = field_prep(LTC4283_PGIO_CFG_MASK(off), val);
81*55c01d37SNuno Sá return regmap_update_bits(st->regmap, LTC4283_PGIO_CONFIG,
82*55c01d37SNuno Sá LTC4283_PGIO_CFG_MASK(off), val);
83*55c01d37SNuno Sá }
84*55c01d37SNuno Sá
85*55c01d37SNuno Sá return regmap_update_bits(st->regmap, LTC4283_ADIO_CONFIG,
86*55c01d37SNuno Sá LTC4283_ADIOX_CONFIG_MASK(off),
87*55c01d37SNuno Sá field_prep(LTC4283_ADIOX_CONFIG_MASK(off), input));
88*55c01d37SNuno Sá }
89*55c01d37SNuno Sá
__ltc4283_gpio_set_value(const struct ltc4283_gpio * st,unsigned int off,int val)90*55c01d37SNuno Sá static int __ltc4283_gpio_set_value(const struct ltc4283_gpio *st,
91*55c01d37SNuno Sá unsigned int off, int val)
92*55c01d37SNuno Sá {
93*55c01d37SNuno Sá u32 reg = off < LTC4283_PGIOX_START_NR ? LTC4283_ADIO_CONFIG : LTC4283_PGIO_CONFIG_2;
94*55c01d37SNuno Sá
95*55c01d37SNuno Sá return regmap_update_bits(st->regmap, reg, BIT(off),
96*55c01d37SNuno Sá field_prep(BIT(off), !!val));
97*55c01d37SNuno Sá }
98*55c01d37SNuno Sá
ltc4283_gpio_direction_input(struct gpio_chip * gc,unsigned int off)99*55c01d37SNuno Sá static int ltc4283_gpio_direction_input(struct gpio_chip *gc, unsigned int off)
100*55c01d37SNuno Sá {
101*55c01d37SNuno Sá struct ltc4283_gpio *st = gpiochip_get_data(gc);
102*55c01d37SNuno Sá
103*55c01d37SNuno Sá return ltc4283_gpio_direction_set(st, off, true);
104*55c01d37SNuno Sá }
105*55c01d37SNuno Sá
ltc4283_gpio_direction_output(struct gpio_chip * gc,unsigned int off,int val)106*55c01d37SNuno Sá static int ltc4283_gpio_direction_output(struct gpio_chip *gc, unsigned int off, int val)
107*55c01d37SNuno Sá {
108*55c01d37SNuno Sá struct ltc4283_gpio *st = gpiochip_get_data(gc);
109*55c01d37SNuno Sá int ret;
110*55c01d37SNuno Sá
111*55c01d37SNuno Sá ret = ltc4283_gpio_direction_set(st, off, false);
112*55c01d37SNuno Sá if (ret)
113*55c01d37SNuno Sá return ret;
114*55c01d37SNuno Sá
115*55c01d37SNuno Sá return __ltc4283_gpio_set_value(st, off, val);
116*55c01d37SNuno Sá }
117*55c01d37SNuno Sá
ltc4283_gpio_get_value(struct gpio_chip * gc,unsigned int off)118*55c01d37SNuno Sá static int ltc4283_gpio_get_value(struct gpio_chip *gc, unsigned int off)
119*55c01d37SNuno Sá {
120*55c01d37SNuno Sá struct ltc4283_gpio *st = gpiochip_get_data(gc);
121*55c01d37SNuno Sá unsigned int val, reg;
122*55c01d37SNuno Sá int ret, dir;
123*55c01d37SNuno Sá
124*55c01d37SNuno Sá dir = ltc4283_gpio_get_direction(gc, off);
125*55c01d37SNuno Sá if (dir < 0)
126*55c01d37SNuno Sá return dir;
127*55c01d37SNuno Sá
128*55c01d37SNuno Sá if (dir == GPIO_LINE_DIRECTION_IN) {
129*55c01d37SNuno Sá ret = regmap_read(st->regmap, LTC4283_INPUT_STATUS, &val);
130*55c01d37SNuno Sá if (ret)
131*55c01d37SNuno Sá return ret;
132*55c01d37SNuno Sá
133*55c01d37SNuno Sá /* ADIO1 is at bit 3. */
134*55c01d37SNuno Sá if (off < LTC4283_PGIOX_START_NR)
135*55c01d37SNuno Sá return !!(val & BIT(3 - off));
136*55c01d37SNuno Sá
137*55c01d37SNuno Sá /* PGIO1 is at bit 7. */
138*55c01d37SNuno Sá return !!(val & BIT(7 - (off - LTC4283_PGIOX_START_NR)));
139*55c01d37SNuno Sá }
140*55c01d37SNuno Sá
141*55c01d37SNuno Sá if (off < LTC4283_PGIOX_START_NR)
142*55c01d37SNuno Sá reg = LTC4283_ADIO_CONFIG;
143*55c01d37SNuno Sá else
144*55c01d37SNuno Sá reg = LTC4283_PGIO_CONFIG_2;
145*55c01d37SNuno Sá
146*55c01d37SNuno Sá ret = regmap_read(st->regmap, reg, &val);
147*55c01d37SNuno Sá if (ret)
148*55c01d37SNuno Sá return ret;
149*55c01d37SNuno Sá
150*55c01d37SNuno Sá return !!(val & BIT(off));
151*55c01d37SNuno Sá }
152*55c01d37SNuno Sá
ltc4283_gpio_set_value(struct gpio_chip * gc,unsigned int off,int val)153*55c01d37SNuno Sá static int ltc4283_gpio_set_value(struct gpio_chip *gc, unsigned int off, int val)
154*55c01d37SNuno Sá {
155*55c01d37SNuno Sá struct ltc4283_gpio *st = gpiochip_get_data(gc);
156*55c01d37SNuno Sá
157*55c01d37SNuno Sá return __ltc4283_gpio_set_value(st, off, val);
158*55c01d37SNuno Sá }
159*55c01d37SNuno Sá
ltc4283_init_valid_mask(struct gpio_chip * gc,unsigned long * valid_mask,unsigned int ngpios)160*55c01d37SNuno Sá static int ltc4283_init_valid_mask(struct gpio_chip *gc, unsigned long *valid_mask,
161*55c01d37SNuno Sá unsigned int ngpios)
162*55c01d37SNuno Sá {
163*55c01d37SNuno Sá unsigned long *mask = dev_get_platdata(gc->parent);
164*55c01d37SNuno Sá
165*55c01d37SNuno Sá bitmap_copy(valid_mask, mask, ngpios);
166*55c01d37SNuno Sá return 0;
167*55c01d37SNuno Sá }
168*55c01d37SNuno Sá
ltc4283_gpio_probe(struct auxiliary_device * adev,const struct auxiliary_device_id * id)169*55c01d37SNuno Sá static int ltc4283_gpio_probe(struct auxiliary_device *adev,
170*55c01d37SNuno Sá const struct auxiliary_device_id *id)
171*55c01d37SNuno Sá {
172*55c01d37SNuno Sá struct device *dev = &adev->dev;
173*55c01d37SNuno Sá struct ltc4283_gpio *st;
174*55c01d37SNuno Sá struct gpio_chip *gc;
175*55c01d37SNuno Sá
176*55c01d37SNuno Sá st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL);
177*55c01d37SNuno Sá if (!st)
178*55c01d37SNuno Sá return -ENOMEM;
179*55c01d37SNuno Sá
180*55c01d37SNuno Sá st->regmap = dev_get_regmap(dev->parent, NULL);
181*55c01d37SNuno Sá if (!st->regmap)
182*55c01d37SNuno Sá return dev_err_probe(dev, -ENODEV,
183*55c01d37SNuno Sá "Failed to get regmap\n");
184*55c01d37SNuno Sá
185*55c01d37SNuno Sá gc = &st->gpio_chip;
186*55c01d37SNuno Sá gc->parent = dev;
187*55c01d37SNuno Sá gc->get_direction = ltc4283_gpio_get_direction;
188*55c01d37SNuno Sá gc->direction_input = ltc4283_gpio_direction_input;
189*55c01d37SNuno Sá gc->direction_output = ltc4283_gpio_direction_output;
190*55c01d37SNuno Sá gc->get = ltc4283_gpio_get_value;
191*55c01d37SNuno Sá gc->set = ltc4283_gpio_set_value;
192*55c01d37SNuno Sá gc->init_valid_mask = ltc4283_init_valid_mask;
193*55c01d37SNuno Sá gc->can_sleep = true;
194*55c01d37SNuno Sá
195*55c01d37SNuno Sá gc->base = -1;
196*55c01d37SNuno Sá gc->ngpio = LTC4283_PINS_MAX;
197*55c01d37SNuno Sá gc->label = adev->name;
198*55c01d37SNuno Sá gc->owner = THIS_MODULE;
199*55c01d37SNuno Sá
200*55c01d37SNuno Sá return devm_gpiochip_add_data(dev, &st->gpio_chip, st);
201*55c01d37SNuno Sá }
202*55c01d37SNuno Sá
203*55c01d37SNuno Sá static const struct auxiliary_device_id ltc4283_aux_id_table[] = {
204*55c01d37SNuno Sá { "ltc4283.gpio" },
205*55c01d37SNuno Sá { }
206*55c01d37SNuno Sá };
207*55c01d37SNuno Sá MODULE_DEVICE_TABLE(auxiliary, ltc4283_aux_id_table);
208*55c01d37SNuno Sá
209*55c01d37SNuno Sá static struct auxiliary_driver ltc4283_gpio_driver = {
210*55c01d37SNuno Sá .probe = ltc4283_gpio_probe,
211*55c01d37SNuno Sá .id_table = ltc4283_aux_id_table,
212*55c01d37SNuno Sá };
213*55c01d37SNuno Sá module_auxiliary_driver(ltc4283_gpio_driver);
214*55c01d37SNuno Sá
215*55c01d37SNuno Sá MODULE_AUTHOR("Nuno Sá <nuno.sa@analog.com>");
216*55c01d37SNuno Sá MODULE_DESCRIPTION("GPIO LTC4283 Driver");
217*55c01d37SNuno Sá MODULE_LICENSE("GPL");
218