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