]> git.sur5r.net Git - u-boot/blob - drivers/gpio/pca9698.c
dm: core: Add ofnode function to read a 64-bit int
[u-boot] / drivers / gpio / pca9698.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2011
4  * Dirk Eibach,  Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
5  */
6
7 /*
8  * Driver for NXP's pca9698 40 bit I2C gpio expander
9  */
10
11 #include <common.h>
12 #include <i2c.h>
13 #include <linux/errno.h>
14 #include <pca9698.h>
15
16 /*
17  * The pca9698 registers
18  */
19
20 #define PCA9698_REG_INPUT               0x00
21 #define PCA9698_REG_OUTPUT              0x08
22 #define PCA9698_REG_POLARITY            0x10
23 #define PCA9698_REG_CONFIG              0x18
24
25 #define PCA9698_BUFFER_SIZE             5
26 #define PCA9698_GPIO_COUNT              40
27
28 static int pca9698_read40(u8 addr, u8 offset, u8 *buffer)
29 {
30         u8 command = offset | 0x80;  /* autoincrement */
31
32         return i2c_read(addr, command, 1, buffer, PCA9698_BUFFER_SIZE);
33 }
34
35 static int pca9698_write40(u8 addr, u8 offset, u8 *buffer)
36 {
37         u8 command = offset | 0x80;  /* autoincrement */
38
39         return i2c_write(addr, command, 1, buffer, PCA9698_BUFFER_SIZE);
40 }
41
42 static void pca9698_set_bit(unsigned gpio, u8 *buffer, unsigned value)
43 {
44         unsigned byte = gpio / 8;
45         unsigned bit = gpio % 8;
46
47         if (value)
48                 buffer[byte] |= (1 << bit);
49         else
50                 buffer[byte] &= ~(1 << bit);
51 }
52
53 int pca9698_request(unsigned gpio, const char *label)
54 {
55         if (gpio >= PCA9698_GPIO_COUNT)
56                 return -EINVAL;
57
58         return 0;
59 }
60
61 void pca9698_free(unsigned gpio)
62 {
63 }
64
65 int pca9698_direction_input(u8 addr, unsigned gpio)
66 {
67         u8 data[PCA9698_BUFFER_SIZE];
68         int res;
69
70         res = pca9698_read40(addr, PCA9698_REG_CONFIG, data);
71         if (res)
72                 return res;
73
74         pca9698_set_bit(gpio, data, 1);
75
76         return pca9698_write40(addr, PCA9698_REG_CONFIG, data);
77 }
78
79 int pca9698_direction_output(u8 addr, unsigned gpio, int value)
80 {
81         u8 data[PCA9698_BUFFER_SIZE];
82         int res;
83
84         res = pca9698_set_value(addr, gpio, value);
85         if (res)
86                 return res;
87
88         res = pca9698_read40(addr, PCA9698_REG_CONFIG, data);
89         if (res)
90                 return res;
91
92         pca9698_set_bit(gpio, data, 0);
93
94         return pca9698_write40(addr, PCA9698_REG_CONFIG, data);
95 }
96
97 int pca9698_get_value(u8 addr, unsigned gpio)
98 {
99         unsigned config_byte = gpio / 8;
100         unsigned config_bit = gpio % 8;
101         unsigned value;
102         u8 data[PCA9698_BUFFER_SIZE];
103         int res;
104
105         res = pca9698_read40(addr, PCA9698_REG_INPUT, data);
106         if (res)
107                 return -1;
108
109         value = data[config_byte] & (1 << config_bit);
110
111         return !!value;
112 }
113
114 int pca9698_set_value(u8 addr, unsigned gpio, int value)
115 {
116         u8 data[PCA9698_BUFFER_SIZE];
117         int res;
118
119         res = pca9698_read40(addr, PCA9698_REG_OUTPUT, data);
120         if (res)
121                 return res;
122
123         pca9698_set_bit(gpio, data, value);
124
125         return pca9698_write40(addr, PCA9698_REG_OUTPUT, data);
126 }