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