Prepare v2023.10
[platform/kernel/u-boot.git] / drivers / gpio / pca953x_gpio.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Take linux kernel driver drivers/gpio/gpio-pca953x.c for reference.
4  *
5  * Copyright (C) 2016 Peng Fan <van.freenix@gmail.com>
6  *
7  */
8
9 /*
10  * Note:
11  * The driver's compatible table is borrowed from Linux Kernel,
12  * but now max supported gpio pins is 24 and only PCA953X_TYPE
13  * is supported. PCA957X_TYPE is not supported now.
14  * Also the Polarity Inversion feature is not supported now.
15  *
16  * TODO:
17  * 1. Support PCA957X_TYPE
18  * 2. Support Polarity Inversion
19  */
20
21 #include <common.h>
22 #include <errno.h>
23 #include <dm.h>
24 #include <fdtdec.h>
25 #include <i2c.h>
26 #include <malloc.h>
27 #include <asm/gpio.h>
28 #include <asm/io.h>
29 #include <dm/device_compat.h>
30 #include <dt-bindings/gpio/gpio.h>
31 #include <linux/bitops.h>
32
33 #define PCA953X_INPUT           0
34 #define PCA953X_OUTPUT          1
35 #define PCA953X_INVERT          2
36 #define PCA953X_DIRECTION       3
37
38 #define PCA957X_INPUT           0
39 #define PCA957X_OUTPUT          5
40 #define PCA957X_INVERT          1
41 #define PCA957X_DIRECTION       4
42
43
44 #define PCA_GPIO_MASK           0x00FF
45 #define PCA_INT                 0x0100
46 #define PCA_PCAL                BIT(9)
47 #define PCA_LATCH_INT           (PCA_PCAL | PCA_INT)
48 #define PCA953X_TYPE            0x1000
49 #define PCA957X_TYPE            0x2000
50 #define PCA_TYPE_MASK           0xF000
51 #define PCA_CHIP_TYPE(x)        ((x) & PCA_TYPE_MASK)
52
53 enum {
54         PCA953X_DIRECTION_IN,
55         PCA953X_DIRECTION_OUT,
56 };
57
58 #define MAX_BANK 5
59 #define BANK_SZ 8
60
61 struct pca95xx_reg {
62         int input;
63         int output;
64         int invert;
65         int direction;
66 };
67
68 static const struct pca95xx_reg pca953x_regs = {
69         .direction = PCA953X_DIRECTION,
70         .output = PCA953X_OUTPUT,
71         .input = PCA953X_INPUT,
72         .invert = PCA953X_INVERT,
73 };
74
75 static const struct pca95xx_reg pca957x_regs = {
76         .direction = PCA957X_DIRECTION,
77         .output = PCA957X_OUTPUT,
78         .input = PCA957X_INPUT,
79         .invert = PCA957X_INVERT,
80 };
81
82 /*
83  * struct pca953x_info - Data for pca953x/pca957x
84  *
85  * @dev: udevice structure for the device
86  * @addr: i2c slave address
87  * @invert: Polarity inversion or not
88  * @gpio_count: the number of gpio pins that the device supports
89  * @chip_type: indicate the chip type,PCA953X or PCA957X
90  * @bank_count: the number of banks that the device supports
91  * @reg_output: array to hold the value of output registers
92  * @reg_direction: array to hold the value of direction registers
93  * @regs: struct to hold the registers addresses
94  */
95 struct pca953x_info {
96         struct udevice *dev;
97         int addr;
98         int invert;
99         int gpio_count;
100         int chip_type;
101         int bank_count;
102         u8 reg_output[MAX_BANK];
103         u8 reg_direction[MAX_BANK];
104         const struct pca95xx_reg *regs;
105 };
106
107 static int pca953x_write_single(struct udevice *dev, int reg, u8 val,
108                                 int offset)
109 {
110         struct pca953x_info *info = dev_get_plat(dev);
111         int bank_shift = fls((info->gpio_count - 1) / BANK_SZ);
112         int off = offset / BANK_SZ;
113         int ret = 0;
114
115         ret = dm_i2c_write(dev, (reg << bank_shift) + off, &val, 1);
116         if (ret) {
117                 dev_err(dev, "%s error\n", __func__);
118                 return ret;
119         }
120
121         return 0;
122 }
123
124 static int pca953x_read_single(struct udevice *dev, int reg, u8 *val,
125                                int offset)
126 {
127         struct pca953x_info *info = dev_get_plat(dev);
128         int bank_shift = fls((info->gpio_count - 1) / BANK_SZ);
129         int off = offset / BANK_SZ;
130         int ret;
131         u8 byte;
132
133         ret = dm_i2c_read(dev, (reg << bank_shift) + off, &byte, 1);
134         if (ret) {
135                 dev_err(dev, "%s error\n", __func__);
136                 return ret;
137         }
138
139         *val = byte;
140
141         return 0;
142 }
143
144 static int pca953x_read_regs(struct udevice *dev, int reg, u8 *val)
145 {
146         struct pca953x_info *info = dev_get_plat(dev);
147         int ret = 0;
148
149         if (info->gpio_count <= 8) {
150                 ret = dm_i2c_read(dev, reg, val, 1);
151         } else if (info->gpio_count <= 16) {
152                 ret = dm_i2c_read(dev, reg << 1, val, info->bank_count);
153         } else if (info->gpio_count <= 24) {
154                 /* Auto increment */
155                 ret = dm_i2c_read(dev, (reg << 2) | 0x80, val,
156                                   info->bank_count);
157         } else if (info->gpio_count == 40) {
158                 /* Auto increment */
159                 ret = dm_i2c_read(dev, (reg << 3) | 0x80, val,
160                                   info->bank_count);
161         } else {
162                 dev_err(dev, "Unsupported now\n");
163                 return -EINVAL;
164         }
165
166         return ret;
167 }
168
169 static int pca953x_write_regs(struct udevice *dev, int reg, u8 *val)
170 {
171         struct pca953x_info *info = dev_get_plat(dev);
172         int ret = 0;
173
174         if (info->gpio_count <= 8) {
175                 ret = dm_i2c_write(dev, reg, val, 1);
176         } else if (info->gpio_count <= 16) {
177                 ret = dm_i2c_write(dev, reg << 1, val, info->bank_count);
178         } else if (info->gpio_count <= 24) {
179                 /* Auto increment */
180                 ret = dm_i2c_write(dev, (reg << 2) | 0x80, val,
181                                    info->bank_count);
182         } else if (info->gpio_count == 40) {
183                 /* Auto increment */
184                 ret = dm_i2c_write(dev, (reg << 3) | 0x80, val, info->bank_count);
185         } else {
186                 return -EINVAL;
187         }
188
189         return ret;
190 }
191
192 static int pca953x_is_output(struct udevice *dev, int offset)
193 {
194         struct pca953x_info *info = dev_get_plat(dev);
195
196         int bank = offset / BANK_SZ;
197         int off = offset % BANK_SZ;
198
199         /*0: output; 1: input */
200         return !(info->reg_direction[bank] & (1 << off));
201 }
202
203 static int pca953x_get_value(struct udevice *dev, uint offset)
204 {
205         struct pca953x_info *info = dev_get_plat(dev);
206         int ret;
207         u8 val = 0;
208
209         int off = offset % BANK_SZ;
210
211         ret = pca953x_read_single(dev, info->regs->input, &val, offset);
212         if (ret)
213                 return ret;
214
215         return (val >> off) & 0x1;
216 }
217
218 static int pca953x_set_value(struct udevice *dev, uint offset, int value)
219 {
220         struct pca953x_info *info = dev_get_plat(dev);
221         int bank = offset / BANK_SZ;
222         int off = offset % BANK_SZ;
223         u8 val;
224         int ret;
225
226         if (value)
227                 val = info->reg_output[bank] | (1 << off);
228         else
229                 val = info->reg_output[bank] & ~(1 << off);
230
231         ret = pca953x_write_single(dev, info->regs->output, val, offset);
232         if (ret)
233                 return ret;
234
235         info->reg_output[bank] = val;
236
237         return 0;
238 }
239
240 static int pca953x_set_direction(struct udevice *dev, uint offset, int dir)
241 {
242         struct pca953x_info *info = dev_get_plat(dev);
243         int bank = offset / BANK_SZ;
244         int off = offset % BANK_SZ;
245         u8 val;
246         int ret;
247
248         if (dir == PCA953X_DIRECTION_IN)
249                 val = info->reg_direction[bank] | (1 << off);
250         else
251                 val = info->reg_direction[bank] & ~(1 << off);
252
253         ret = pca953x_write_single(dev, info->regs->direction, val, offset);
254         if (ret)
255                 return ret;
256
257         info->reg_direction[bank] = val;
258
259         return 0;
260 }
261
262 static int pca953x_direction_input(struct udevice *dev, uint offset)
263 {
264         return pca953x_set_direction(dev, offset, PCA953X_DIRECTION_IN);
265 }
266
267 static int pca953x_direction_output(struct udevice *dev, uint offset, int value)
268 {
269         /* Configure output value. */
270         pca953x_set_value(dev, offset, value);
271
272         /* Configure direction as output. */
273         pca953x_set_direction(dev, offset, PCA953X_DIRECTION_OUT);
274
275         return 0;
276 }
277
278 static int pca953x_get_function(struct udevice *dev, uint offset)
279 {
280         if (pca953x_is_output(dev, offset))
281                 return GPIOF_OUTPUT;
282         else
283                 return GPIOF_INPUT;
284 }
285
286 static int pca953x_xlate(struct udevice *dev, struct gpio_desc *desc,
287                          struct ofnode_phandle_args *args)
288 {
289         desc->offset = args->args[0];
290         desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0;
291
292         return 0;
293 }
294
295 static const struct dm_gpio_ops pca953x_ops = {
296         .direction_input        = pca953x_direction_input,
297         .direction_output       = pca953x_direction_output,
298         .get_value              = pca953x_get_value,
299         .set_value              = pca953x_set_value,
300         .get_function           = pca953x_get_function,
301         .xlate                  = pca953x_xlate,
302 };
303
304 static int pca953x_probe(struct udevice *dev)
305 {
306         struct pca953x_info *info = dev_get_plat(dev);
307         struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
308         char name[32], label[8], *str;
309         int addr;
310         ulong driver_data;
311         int ret;
312         int size;
313         const u8 *tmp;
314         u8 val[MAX_BANK];
315
316         addr = dev_read_addr(dev);
317         if (addr == 0)
318                 return -ENODEV;
319
320         info->addr = addr;
321
322         driver_data = dev_get_driver_data(dev);
323
324         info->gpio_count = driver_data & PCA_GPIO_MASK;
325         if (info->gpio_count > MAX_BANK * BANK_SZ) {
326                 dev_err(dev, "Max support %d pins now\n", MAX_BANK * BANK_SZ);
327                 return -EINVAL;
328         }
329
330         info->chip_type = PCA_CHIP_TYPE(driver_data);
331         if (info->chip_type == PCA953X_TYPE)
332                 info->regs = &pca953x_regs;
333         else
334                 info->regs = &pca957x_regs;
335
336         info->bank_count = DIV_ROUND_UP(info->gpio_count, BANK_SZ);
337
338         ret = pca953x_read_regs(dev, info->regs->output, info->reg_output);
339         if (ret) {
340                 dev_err(dev, "Error reading output register\n");
341                 return ret;
342         }
343
344         ret = pca953x_read_regs(dev, PCA953X_DIRECTION, info->reg_direction);
345         if (ret) {
346                 dev_err(dev, "Error reading direction register\n");
347                 return ret;
348         }
349
350         tmp = dev_read_prop(dev, "label", &size);
351
352         if (tmp) {
353                 memcpy(label, tmp, sizeof(label) - 1);
354                 label[sizeof(label) - 1] = '\0';
355                 snprintf(name, sizeof(name), "%s@%x_", label, info->addr);
356         } else {
357                 snprintf(name, sizeof(name), "gpio@%x_", info->addr);
358         }
359
360         /* Clear the polarity registers to no invert */
361         memset(val, 0, MAX_BANK);
362         ret = pca953x_write_regs(dev, info->regs->invert, val);
363         if (ret < 0) {
364                 dev_err(dev, "Error writing invert register\n");
365                 return ret;
366         }
367
368         str = strdup(name);
369         if (!str)
370                 return -ENOMEM;
371         uc_priv->bank_name = str;
372         uc_priv->gpio_count = info->gpio_count;
373
374         dev_dbg(dev, "%s is ready\n", str);
375
376         return 0;
377 }
378
379 #define OF_953X(__nrgpio, __int) (ulong)(__nrgpio | PCA953X_TYPE | __int)
380 #define OF_957X(__nrgpio, __int) (ulong)(__nrgpio | PCA957X_TYPE | __int)
381
382 static const struct udevice_id pca953x_ids[] = {
383         { .compatible = "nxp,pca9505", .data = OF_953X(40, PCA_INT), },
384         { .compatible = "nxp,pca9534", .data = OF_953X(8, PCA_INT), },
385         { .compatible = "nxp,pca9535", .data = OF_953X(16, PCA_INT), },
386         { .compatible = "nxp,pca9536", .data = OF_953X(4, 0), },
387         { .compatible = "nxp,pca9537", .data = OF_953X(4, PCA_INT), },
388         { .compatible = "nxp,pca9538", .data = OF_953X(8, PCA_INT), },
389         { .compatible = "nxp,pca9539", .data = OF_953X(16, PCA_INT), },
390         { .compatible = "nxp,pca9554", .data = OF_953X(8, PCA_INT), },
391         { .compatible = "nxp,pca9555", .data = OF_953X(16, PCA_INT), },
392         { .compatible = "nxp,pca9556", .data = OF_953X(8, 0), },
393         { .compatible = "nxp,pca9557", .data = OF_953X(8, 0), },
394         { .compatible = "nxp,pca9574", .data = OF_957X(8, PCA_INT), },
395         { .compatible = "nxp,pca9575", .data = OF_957X(16, PCA_INT), },
396         { .compatible = "nxp,pca9698", .data = OF_953X(40, 0), },
397
398         { .compatible = "nxp,pcal6524", .data = OF_953X(24, PCA_LATCH_INT), },
399
400         { .compatible = "maxim,max7310", .data = OF_953X(8, 0), },
401         { .compatible = "maxim,max7312", .data = OF_953X(16, PCA_INT), },
402         { .compatible = "maxim,max7313", .data = OF_953X(16, PCA_INT), },
403         { .compatible = "maxim,max7315", .data = OF_953X(8, PCA_INT), },
404
405         { .compatible = "ti,pca6107", .data = OF_953X(8, PCA_INT), },
406         { .compatible = "ti,tca6408", .data = OF_953X(8, PCA_INT), },
407         { .compatible = "ti,tca6416", .data = OF_953X(16, PCA_INT), },
408         { .compatible = "ti,tca6424", .data = OF_953X(24, PCA_INT), },
409         { .compatible = "ti,tca9539", .data = OF_953X(16, PCA_INT), },
410
411         { .compatible = "onsemi,pca9654", .data = OF_953X(8, PCA_INT), },
412
413         { .compatible = "exar,xra1202", .data = OF_953X(8, 0), },
414         { }
415 };
416
417 U_BOOT_DRIVER(pca953x) = {
418         .name           = "pca953x",
419         .id             = UCLASS_GPIO,
420         .ops            = &pca953x_ops,
421         .probe          = pca953x_probe,
422         .plat_auto      = sizeof(struct pca953x_info),
423         .of_match       = pca953x_ids,
424 };