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