Merge branch 'writeback' of git://git.kernel.dk/linux-2.6-block
[pandora-kernel.git] / drivers / gpio / mcp23s08.c
1 /*
2  * mcp23s08.c - SPI gpio expander driver
3  */
4
5 #include <linux/kernel.h>
6 #include <linux/device.h>
7 #include <linux/workqueue.h>
8 #include <linux/mutex.h>
9 #include <linux/gpio.h>
10 #include <linux/spi/spi.h>
11 #include <linux/spi/mcp23s08.h>
12
13
14 /* Registers are all 8 bits wide.
15  *
16  * The mcp23s17 has twice as many bits, and can be configured to work
17  * with either 16 bit registers or with two adjacent 8 bit banks.
18  *
19  * Also, there are I2C versions of both chips.
20  */
21 #define MCP_IODIR       0x00            /* init/reset:  all ones */
22 #define MCP_IPOL        0x01
23 #define MCP_GPINTEN     0x02
24 #define MCP_DEFVAL      0x03
25 #define MCP_INTCON      0x04
26 #define MCP_IOCON       0x05
27 #       define IOCON_SEQOP      (1 << 5)
28 #       define IOCON_HAEN       (1 << 3)
29 #       define IOCON_ODR        (1 << 2)
30 #       define IOCON_INTPOL     (1 << 1)
31 #define MCP_GPPU        0x06
32 #define MCP_INTF        0x07
33 #define MCP_INTCAP      0x08
34 #define MCP_GPIO        0x09
35 #define MCP_OLAT        0x0a
36
37 struct mcp23s08 {
38         struct spi_device       *spi;
39         u8                      addr;
40
41         u8                      cache[11];
42         /* lock protects the cached values */
43         struct mutex            lock;
44
45         struct gpio_chip        chip;
46
47         struct work_struct      work;
48 };
49
50 /* A given spi_device can represent up to four mcp23s08 chips
51  * sharing the same chipselect but using different addresses
52  * (e.g. chips #0 and #3 might be populated, but not #1 or $2).
53  * Driver data holds all the per-chip data.
54  */
55 struct mcp23s08_driver_data {
56         unsigned                ngpio;
57         struct mcp23s08         *mcp[4];
58         struct mcp23s08         chip[];
59 };
60
61 static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg)
62 {
63         u8      tx[2], rx[1];
64         int     status;
65
66         tx[0] = mcp->addr | 0x01;
67         tx[1] = reg;
68         status = spi_write_then_read(mcp->spi, tx, sizeof tx, rx, sizeof rx);
69         return (status < 0) ? status : rx[0];
70 }
71
72 static int mcp23s08_write(struct mcp23s08 *mcp, unsigned reg, u8 val)
73 {
74         u8      tx[3];
75
76         tx[0] = mcp->addr;
77         tx[1] = reg;
78         tx[2] = val;
79         return spi_write_then_read(mcp->spi, tx, sizeof tx, NULL, 0);
80 }
81
82 static int
83 mcp23s08_read_regs(struct mcp23s08 *mcp, unsigned reg, u8 *vals, unsigned n)
84 {
85         u8      tx[2];
86
87         if ((n + reg) > sizeof mcp->cache)
88                 return -EINVAL;
89         tx[0] = mcp->addr | 0x01;
90         tx[1] = reg;
91         return spi_write_then_read(mcp->spi, tx, sizeof tx, vals, n);
92 }
93
94 /*----------------------------------------------------------------------*/
95
96 static int mcp23s08_direction_input(struct gpio_chip *chip, unsigned offset)
97 {
98         struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip);
99         int status;
100
101         mutex_lock(&mcp->lock);
102         mcp->cache[MCP_IODIR] |= (1 << offset);
103         status = mcp23s08_write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]);
104         mutex_unlock(&mcp->lock);
105         return status;
106 }
107
108 static int mcp23s08_get(struct gpio_chip *chip, unsigned offset)
109 {
110         struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip);
111         int status;
112
113         mutex_lock(&mcp->lock);
114
115         /* REVISIT reading this clears any IRQ ... */
116         status = mcp23s08_read(mcp, MCP_GPIO);
117         if (status < 0)
118                 status = 0;
119         else {
120                 mcp->cache[MCP_GPIO] = status;
121                 status = !!(status & (1 << offset));
122         }
123         mutex_unlock(&mcp->lock);
124         return status;
125 }
126
127 static int __mcp23s08_set(struct mcp23s08 *mcp, unsigned mask, int value)
128 {
129         u8 olat = mcp->cache[MCP_OLAT];
130
131         if (value)
132                 olat |= mask;
133         else
134                 olat &= ~mask;
135         mcp->cache[MCP_OLAT] = olat;
136         return mcp23s08_write(mcp, MCP_OLAT, olat);
137 }
138
139 static void mcp23s08_set(struct gpio_chip *chip, unsigned offset, int value)
140 {
141         struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip);
142         u8 mask = 1 << offset;
143
144         mutex_lock(&mcp->lock);
145         __mcp23s08_set(mcp, mask, value);
146         mutex_unlock(&mcp->lock);
147 }
148
149 static int
150 mcp23s08_direction_output(struct gpio_chip *chip, unsigned offset, int value)
151 {
152         struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip);
153         u8 mask = 1 << offset;
154         int status;
155
156         mutex_lock(&mcp->lock);
157         status = __mcp23s08_set(mcp, mask, value);
158         if (status == 0) {
159                 mcp->cache[MCP_IODIR] &= ~mask;
160                 status = mcp23s08_write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]);
161         }
162         mutex_unlock(&mcp->lock);
163         return status;
164 }
165
166 /*----------------------------------------------------------------------*/
167
168 #ifdef CONFIG_DEBUG_FS
169
170 #include <linux/seq_file.h>
171
172 /*
173  * This shows more info than the generic gpio dump code:
174  * pullups, deglitching, open drain drive.
175  */
176 static void mcp23s08_dbg_show(struct seq_file *s, struct gpio_chip *chip)
177 {
178         struct mcp23s08 *mcp;
179         char            bank;
180         int             t;
181         unsigned        mask;
182
183         mcp = container_of(chip, struct mcp23s08, chip);
184
185         /* NOTE: we only handle one bank for now ... */
186         bank = '0' + ((mcp->addr >> 1) & 0x3);
187
188         mutex_lock(&mcp->lock);
189         t = mcp23s08_read_regs(mcp, 0, mcp->cache, sizeof mcp->cache);
190         if (t < 0) {
191                 seq_printf(s, " I/O ERROR %d\n", t);
192                 goto done;
193         }
194
195         for (t = 0, mask = 1; t < 8; t++, mask <<= 1) {
196                 const char      *label;
197
198                 label = gpiochip_is_requested(chip, t);
199                 if (!label)
200                         continue;
201
202                 seq_printf(s, " gpio-%-3d P%c.%d (%-12s) %s %s %s",
203                         chip->base + t, bank, t, label,
204                         (mcp->cache[MCP_IODIR] & mask) ? "in " : "out",
205                         (mcp->cache[MCP_GPIO] & mask) ? "hi" : "lo",
206                         (mcp->cache[MCP_GPPU] & mask) ? "  " : "up");
207                 /* NOTE:  ignoring the irq-related registers */
208                 seq_printf(s, "\n");
209         }
210 done:
211         mutex_unlock(&mcp->lock);
212 }
213
214 #else
215 #define mcp23s08_dbg_show       NULL
216 #endif
217
218 /*----------------------------------------------------------------------*/
219
220 static int mcp23s08_probe_one(struct spi_device *spi, unsigned addr,
221                 unsigned base, unsigned pullups)
222 {
223         struct mcp23s08_driver_data     *data = spi_get_drvdata(spi);
224         struct mcp23s08                 *mcp = data->mcp[addr];
225         int                             status;
226         int                             do_update = 0;
227
228         mutex_init(&mcp->lock);
229
230         mcp->spi = spi;
231         mcp->addr = 0x40 | (addr << 1);
232
233         mcp->chip.label = "mcp23s08",
234
235         mcp->chip.direction_input = mcp23s08_direction_input;
236         mcp->chip.get = mcp23s08_get;
237         mcp->chip.direction_output = mcp23s08_direction_output;
238         mcp->chip.set = mcp23s08_set;
239         mcp->chip.dbg_show = mcp23s08_dbg_show;
240
241         mcp->chip.base = base;
242         mcp->chip.ngpio = 8;
243         mcp->chip.can_sleep = 1;
244         mcp->chip.dev = &spi->dev;
245         mcp->chip.owner = THIS_MODULE;
246
247         /* verify MCP_IOCON.SEQOP = 0, so sequential reads work,
248          * and MCP_IOCON.HAEN = 1, so we work with all chips.
249          */
250         status = mcp23s08_read(mcp, MCP_IOCON);
251         if (status < 0)
252                 goto fail;
253         if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN)) {
254                 status &= ~IOCON_SEQOP;
255                 status |= IOCON_HAEN;
256                 status = mcp23s08_write(mcp, MCP_IOCON, (u8) status);
257                 if (status < 0)
258                         goto fail;
259         }
260
261         /* configure ~100K pullups */
262         status = mcp23s08_write(mcp, MCP_GPPU, pullups);
263         if (status < 0)
264                 goto fail;
265
266         status = mcp23s08_read_regs(mcp, 0, mcp->cache, sizeof mcp->cache);
267         if (status < 0)
268                 goto fail;
269
270         /* disable inverter on input */
271         if (mcp->cache[MCP_IPOL] != 0) {
272                 mcp->cache[MCP_IPOL] = 0;
273                 do_update = 1;
274         }
275
276         /* disable irqs */
277         if (mcp->cache[MCP_GPINTEN] != 0) {
278                 mcp->cache[MCP_GPINTEN] = 0;
279                 do_update = 1;
280         }
281
282         if (do_update) {
283                 u8 tx[4];
284
285                 tx[0] = mcp->addr;
286                 tx[1] = MCP_IPOL;
287                 memcpy(&tx[2], &mcp->cache[MCP_IPOL], sizeof(tx) - 2);
288                 status = spi_write_then_read(mcp->spi, tx, sizeof tx, NULL, 0);
289                 if (status < 0)
290                         goto fail;
291         }
292
293         status = gpiochip_add(&mcp->chip);
294 fail:
295         if (status < 0)
296                 dev_dbg(&spi->dev, "can't setup chip %d, --> %d\n",
297                                 addr, status);
298         return status;
299 }
300
301 static int mcp23s08_probe(struct spi_device *spi)
302 {
303         struct mcp23s08_platform_data   *pdata;
304         unsigned                        addr;
305         unsigned                        chips = 0;
306         struct mcp23s08_driver_data     *data;
307         int                             status;
308         unsigned                        base;
309
310         pdata = spi->dev.platform_data;
311         if (!pdata || !gpio_is_valid(pdata->base)) {
312                 dev_dbg(&spi->dev, "invalid or missing platform data\n");
313                 return -EINVAL;
314         }
315
316         for (addr = 0; addr < 4; addr++) {
317                 if (!pdata->chip[addr].is_present)
318                         continue;
319                 chips++;
320         }
321         if (!chips)
322                 return -ENODEV;
323
324         data = kzalloc(sizeof *data + chips * sizeof(struct mcp23s08),
325                         GFP_KERNEL);
326         if (!data)
327                 return -ENOMEM;
328         spi_set_drvdata(spi, data);
329
330         base = pdata->base;
331         for (addr = 0; addr < 4; addr++) {
332                 if (!pdata->chip[addr].is_present)
333                         continue;
334                 chips--;
335                 data->mcp[addr] = &data->chip[chips];
336                 status = mcp23s08_probe_one(spi, addr, base,
337                                 pdata->chip[addr].pullups);
338                 if (status < 0)
339                         goto fail;
340                 base += 8;
341         }
342         data->ngpio = base - pdata->base;
343
344         /* NOTE:  these chips have a relatively sane IRQ framework, with
345          * per-signal masking and level/edge triggering.  It's not yet
346          * handled here...
347          */
348
349         if (pdata->setup) {
350                 status = pdata->setup(spi,
351                                 pdata->base, data->ngpio,
352                                 pdata->context);
353                 if (status < 0)
354                         dev_dbg(&spi->dev, "setup --> %d\n", status);
355         }
356
357         return 0;
358
359 fail:
360         for (addr = 0; addr < 4; addr++) {
361                 int tmp;
362
363                 if (!data->mcp[addr])
364                         continue;
365                 tmp = gpiochip_remove(&data->mcp[addr]->chip);
366                 if (tmp < 0)
367                         dev_err(&spi->dev, "%s --> %d\n", "remove", tmp);
368         }
369         kfree(data);
370         return status;
371 }
372
373 static int mcp23s08_remove(struct spi_device *spi)
374 {
375         struct mcp23s08_driver_data     *data = spi_get_drvdata(spi);
376         struct mcp23s08_platform_data   *pdata = spi->dev.platform_data;
377         unsigned                        addr;
378         int                             status = 0;
379
380         if (pdata->teardown) {
381                 status = pdata->teardown(spi,
382                                 pdata->base, data->ngpio,
383                                 pdata->context);
384                 if (status < 0) {
385                         dev_err(&spi->dev, "%s --> %d\n", "teardown", status);
386                         return status;
387                 }
388         }
389
390         for (addr = 0; addr < 4; addr++) {
391                 int tmp;
392
393                 if (!data->mcp[addr])
394                         continue;
395
396                 tmp = gpiochip_remove(&data->mcp[addr]->chip);
397                 if (tmp < 0) {
398                         dev_err(&spi->dev, "%s --> %d\n", "remove", tmp);
399                         status = tmp;
400                 }
401         }
402         if (status == 0)
403                 kfree(data);
404         return status;
405 }
406
407 static struct spi_driver mcp23s08_driver = {
408         .probe          = mcp23s08_probe,
409         .remove         = mcp23s08_remove,
410         .driver = {
411                 .name   = "mcp23s08",
412                 .owner  = THIS_MODULE,
413         },
414 };
415
416 /*----------------------------------------------------------------------*/
417
418 static int __init mcp23s08_init(void)
419 {
420         return spi_register_driver(&mcp23s08_driver);
421 }
422 /* register after spi postcore initcall and before
423  * subsys initcalls that may rely on these GPIOs
424  */
425 subsys_initcall(mcp23s08_init);
426
427 static void __exit mcp23s08_exit(void)
428 {
429         spi_unregister_driver(&mcp23s08_driver);
430 }
431 module_exit(mcp23s08_exit);
432
433 MODULE_LICENSE("GPL");
434 MODULE_ALIAS("spi:mcp23s08");