aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
authorDavid Brownell <dbrownell@users.sourceforge.net>2008-02-05 01:28:24 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-05 12:44:13 -0500
commit15fae37d9f5f21571a9618d8353164b6ddfea6f6 (patch)
tree13b4fb5479cf3a9522c6673cc6ccae20b6658e55 /drivers/gpio
parent1c44f5f16fee880b294f8068354bfb9dddf1349b (diff)
gpiolib: pcf857x i2c gpio expander support
This is a new-style I2C driver for most common 8 and 16 bit I2C based "quasi-bidirectional" GPIO expanders: pcf8574 or pcf8575, and several compatible models (mostly faster, supporting I2C at up to 1 MHz). The driver exposes the GPIO signals using the platform-neutral GPIO programming interface, so they are easily accessed by other kernel code. The lack of such a flexible kernel API has been a big factor in the proliferation of board-specific drivers for these chips... stuff that rarely makes it upstream since it's so ugly. This driver will let such boards use standard calls. Since it's a new-style driver, these devices must be configured as part of board-specific init. That eliminates the need for error-prone manual configuration of module parameters, and makes compatibility with legacy drivers (pcf8574.c, pc8575.c) for these chips easier (there's a clear either/or disjunction). Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Acked-by: Jean Delvare <khali@linux-fr.org> Cc: Eric Miao <eric.miao@marvell.com> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Haavard Skinnemoen <hskinnemoen@atmel.com> Cc: Philipp Zabel <philipp.zabel@gmail.com> Cc: Russell King <rmk@arm.linux.org.uk> Cc: Ben Gardner <bgardner@wabtec.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/Kconfig23
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/pcf857x.c330
3 files changed, 354 insertions, 0 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 560687c4667..36d5d6aefc0 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -27,6 +27,29 @@ config DEBUG_GPIO
27 27
28comment "I2C GPIO expanders:" 28comment "I2C GPIO expanders:"
29 29
30config GPIO_PCF857X
31 tristate "PCF857x, PCA857x, and PCA967x I2C GPIO expanders"
32 depends on I2C
33 help
34 Say yes here to provide access to most "quasi-bidirectional" I2C
35 GPIO expanders used for additional digital outputs or inputs.
36 Most of these parts are from NXP, though TI is a second source for
37 some of them. Compatible models include:
38
39 8 bits: pcf8574, pcf8574a, pca8574, pca8574a,
40 pca9670, pca9672, pca9674, pca9674a
41
42 16 bits: pcf8575, pcf8575c, pca8575,
43 pca9671, pca9673, pca9675
44
45 Your board setup code will need to declare the expanders in
46 use, and assign numbers to the GPIOs they expose. Those GPIOs
47 can then be used from drivers and other kernel code, just like
48 other GPIOs, but only accessible from task contexts.
49
50 This driver provides an in-kernel interface to those GPIOs using
51 platform-neutral GPIO calls.
52
30comment "SPI GPIO expanders:" 53comment "SPI GPIO expanders:"
31 54
32endmenu 55endmenu
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index c3da03975d5..b469ab24fb1 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -4,3 +4,4 @@ ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG
4 4
5obj-$(CONFIG_HAVE_GPIO_LIB) += gpiolib.o 5obj-$(CONFIG_HAVE_GPIO_LIB) += gpiolib.o
6 6
7obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o
diff --git a/drivers/gpio/pcf857x.c b/drivers/gpio/pcf857x.c
new file mode 100644
index 00000000000..c6b3b537838
--- /dev/null
+++ b/drivers/gpio/pcf857x.c
@@ -0,0 +1,330 @@
1/*
2 * pcf857x - driver for pcf857x, pca857x, and pca967x I2C GPIO expanders
3 *
4 * Copyright (C) 2007 David Brownell
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21#include <linux/kernel.h>
22#include <linux/slab.h>
23#include <linux/i2c.h>
24#include <linux/i2c/pcf857x.h>
25
26#include <asm/gpio.h>
27
28
29/*
30 * The pcf857x, pca857x, and pca967x chips only expose one read and one
31 * write register. Writing a "one" bit (to match the reset state) lets
32 * that pin be used as an input; it's not an open-drain model, but acts
33 * a bit like one. This is described as "quasi-bidirectional"; read the
34 * chip documentation for details.
35 *
36 * Many other I2C GPIO expander chips (like the pca953x models) have
37 * more complex register models and more conventional circuitry using
38 * push/pull drivers. They often use the same 0x20..0x27 addresses as
39 * pcf857x parts, making the "legacy" I2C driver model problematic.
40 */
41struct pcf857x {
42 struct gpio_chip chip;
43 struct i2c_client *client;
44 unsigned out; /* software latch */
45};
46
47/*-------------------------------------------------------------------------*/
48
49/* Talk to 8-bit I/O expander */
50
51static int pcf857x_input8(struct gpio_chip *chip, unsigned offset)
52{
53 struct pcf857x *gpio = container_of(chip, struct pcf857x, chip);
54
55 gpio->out |= (1 << offset);
56 return i2c_smbus_write_byte(gpio->client, gpio->out);
57}
58
59static int pcf857x_get8(struct gpio_chip *chip, unsigned offset)
60{
61 struct pcf857x *gpio = container_of(chip, struct pcf857x, chip);
62 s32 value;
63
64 value = i2c_smbus_read_byte(gpio->client);
65 return (value < 0) ? 0 : (value & (1 << offset));
66}
67
68static int pcf857x_output8(struct gpio_chip *chip, unsigned offset, int value)
69{
70 struct pcf857x *gpio = container_of(chip, struct pcf857x, chip);
71 unsigned bit = 1 << offset;
72
73 if (value)
74 gpio->out |= bit;
75 else
76 gpio->out &= ~bit;
77 return i2c_smbus_write_byte(gpio->client, gpio->out);
78}
79
80static void pcf857x_set8(struct gpio_chip *chip, unsigned offset, int value)
81{
82 pcf857x_output8(chip, offset, value);
83}
84
85/*-------------------------------------------------------------------------*/
86
87/* Talk to 16-bit I/O expander */
88
89static int i2c_write_le16(struct i2c_client *client, u16 word)
90{
91 u8 buf[2] = { word & 0xff, word >> 8, };
92 int status;
93
94 status = i2c_master_send(client, buf, 2);
95 return (status < 0) ? status : 0;
96}
97
98static int i2c_read_le16(struct i2c_client *client)
99{
100 u8 buf[2];
101 int status;
102
103 status = i2c_master_recv(client, buf, 2);
104 if (status < 0)
105 return status;
106 return (buf[1] << 8) | buf[0];
107}
108
109static int pcf857x_input16(struct gpio_chip *chip, unsigned offset)
110{
111 struct pcf857x *gpio = container_of(chip, struct pcf857x, chip);
112
113 gpio->out |= (1 << offset);
114 return i2c_write_le16(gpio->client, gpio->out);
115}
116
117static int pcf857x_get16(struct gpio_chip *chip, unsigned offset)
118{
119 struct pcf857x *gpio = container_of(chip, struct pcf857x, chip);
120 int value;
121
122 value = i2c_read_le16(gpio->client);
123 return (value < 0) ? 0 : (value & (1 << offset));
124}
125
126static int pcf857x_output16(struct gpio_chip *chip, unsigned offset, int value)
127{
128 struct pcf857x *gpio = container_of(chip, struct pcf857x, chip);
129 unsigned bit = 1 << offset;
130
131 if (value)
132 gpio->out |= bit;
133 else
134 gpio->out &= ~bit;
135 return i2c_write_le16(gpio->client, gpio->out);
136}
137
138static void pcf857x_set16(struct gpio_chip *chip, unsigned offset, int value)
139{
140 pcf857x_output16(chip, offset, value);
141}
142
143/*-------------------------------------------------------------------------*/
144
145static int pcf857x_probe(struct i2c_client *client)
146{
147 struct pcf857x_platform_data *pdata;
148 struct pcf857x *gpio;
149 int status;
150
151 pdata = client->dev.platform_data;
152 if (!pdata)
153 return -ENODEV;
154
155 /* Allocate, initialize, and register this gpio_chip. */
156 gpio = kzalloc(sizeof *gpio, GFP_KERNEL);
157 if (!gpio)
158 return -ENOMEM;
159
160 gpio->chip.base = pdata->gpio_base;
161 gpio->chip.can_sleep = 1;
162
163 /* NOTE: the OnSemi jlc1562b is also largely compatible with
164 * these parts, notably for output. It has a low-resolution
165 * DAC instead of pin change IRQs; and its inputs can be the
166 * result of comparators.
167 */
168
169 /* 8574 addresses are 0x20..0x27; 8574a uses 0x38..0x3f;
170 * 9670, 9672, 9764, and 9764a use quite a variety.
171 *
172 * NOTE: we don't distinguish here between *4 and *4a parts.
173 */
174 if (strcmp(client->name, "pcf8574") == 0
175 || strcmp(client->name, "pca8574") == 0
176 || strcmp(client->name, "pca9670") == 0
177 || strcmp(client->name, "pca9672") == 0
178 || strcmp(client->name, "pca9674") == 0
179 ) {
180 gpio->chip.ngpio = 8;
181 gpio->chip.direction_input = pcf857x_input8;
182 gpio->chip.get = pcf857x_get8;
183 gpio->chip.direction_output = pcf857x_output8;
184 gpio->chip.set = pcf857x_set8;
185
186 if (!i2c_check_functionality(client->adapter,
187 I2C_FUNC_SMBUS_BYTE))
188 status = -EIO;
189
190 /* fail if there's no chip present */
191 else
192 status = i2c_smbus_read_byte(client);
193
194 /* '75/'75c addresses are 0x20..0x27, just like the '74;
195 * the '75c doesn't have a current source pulling high.
196 * 9671, 9673, and 9765 use quite a variety of addresses.
197 *
198 * NOTE: we don't distinguish here between '75 and '75c parts.
199 */
200 } else if (strcmp(client->name, "pcf8575") == 0
201 || strcmp(client->name, "pca8575") == 0
202 || strcmp(client->name, "pca9671") == 0
203 || strcmp(client->name, "pca9673") == 0
204 || strcmp(client->name, "pca9675") == 0
205 ) {
206 gpio->chip.ngpio = 16;
207 gpio->chip.direction_input = pcf857x_input16;
208 gpio->chip.get = pcf857x_get16;
209 gpio->chip.direction_output = pcf857x_output16;
210 gpio->chip.set = pcf857x_set16;
211
212 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
213 status = -EIO;
214
215 /* fail if there's no chip present */
216 else
217 status = i2c_read_le16(client);
218
219 } else
220 status = -ENODEV;
221
222 if (status < 0)
223 goto fail;
224
225 gpio->chip.label = client->name;
226
227 gpio->client = client;
228 i2c_set_clientdata(client, gpio);
229
230 /* NOTE: these chips have strange "quasi-bidirectional" I/O pins.
231 * We can't actually know whether a pin is configured (a) as output
232 * and driving the signal low, or (b) as input and reporting a low
233 * value ... without knowing the last value written since the chip
234 * came out of reset (if any). We can't read the latched output.
235 *
236 * In short, the only reliable solution for setting up pin direction
237 * is to do it explicitly. The setup() method can do that, but it
238 * may cause transient glitching since it can't know the last value
239 * written (some pins may need to be driven low).
240 *
241 * Using pdata->n_latch avoids that trouble. When left initialized
242 * to zero, our software copy of the "latch" then matches the chip's
243 * all-ones reset state. Otherwise it flags pins to be driven low.
244 */
245 gpio->out = ~pdata->n_latch;
246
247 status = gpiochip_add(&gpio->chip);
248 if (status < 0)
249 goto fail;
250
251 /* NOTE: these chips can issue "some pin-changed" IRQs, which we
252 * don't yet even try to use. Among other issues, the relevant
253 * genirq state isn't available to modular drivers; and most irq
254 * methods can't be called from sleeping contexts.
255 */
256
257 dev_info(&client->dev, "gpios %d..%d on a %s%s\n",
258 gpio->chip.base,
259 gpio->chip.base + gpio->chip.ngpio - 1,
260 client->name,
261 client->irq ? " (irq ignored)" : "");
262
263 /* Let platform code set up the GPIOs and their users.
264 * Now is the first time anyone could use them.
265 */
266 if (pdata->setup) {
267 status = pdata->setup(client,
268 gpio->chip.base, gpio->chip.ngpio,
269 pdata->context);
270 if (status < 0)
271 dev_warn(&client->dev, "setup --> %d\n", status);
272 }
273
274 return 0;
275
276fail:
277 dev_dbg(&client->dev, "probe error %d for '%s'\n",
278 status, client->name);
279 kfree(gpio);
280 return status;
281}
282
283static int pcf857x_remove(struct i2c_client *client)
284{
285 struct pcf857x_platform_data *pdata = client->dev.platform_data;
286 struct pcf857x *gpio = i2c_get_clientdata(client);
287 int status = 0;
288
289 if (pdata->teardown) {
290 status = pdata->teardown(client,
291 gpio->chip.base, gpio->chip.ngpio,
292 pdata->context);
293 if (status < 0) {
294 dev_err(&client->dev, "%s --> %d\n",
295 "teardown", status);
296 return status;
297 }
298 }
299
300 status = gpiochip_remove(&gpio->chip);
301 if (status == 0)
302 kfree(gpio);
303 else
304 dev_err(&client->dev, "%s --> %d\n", "remove", status);
305 return status;
306}
307
308static struct i2c_driver pcf857x_driver = {
309 .driver = {
310 .name = "pcf857x",
311 .owner = THIS_MODULE,
312 },
313 .probe = pcf857x_probe,
314 .remove = pcf857x_remove,
315};
316
317static int __init pcf857x_init(void)
318{
319 return i2c_add_driver(&pcf857x_driver);
320}
321module_init(pcf857x_init);
322
323static void __exit pcf857x_exit(void)
324{
325 i2c_del_driver(&pcf857x_driver);
326}
327module_exit(pcf857x_exit);
328
329MODULE_LICENSE("GPL");
330MODULE_AUTHOR("David Brownell");