2 * mcp23s08.c - SPI gpio expander driver
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>
14 /* Registers are all 8 bits wide.
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.
19 * Also, there are I2C versions of both chips.
21 #define MCP_IODIR 0x00 /* init/reset: all ones */
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)
33 #define MCP_INTCAP 0x08
38 struct spi_device
*spi
;
42 /* lock protects the cached values */
45 struct gpio_chip chip
;
47 struct work_struct work
;
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.
55 struct mcp23s08_driver_data
{
57 struct mcp23s08
*mcp
[4];
58 struct mcp23s08 chip
[];
61 static int mcp23s08_read(struct mcp23s08
*mcp
, unsigned reg
)
66 tx
[0] = mcp
->addr
| 0x01;
68 status
= spi_write_then_read(mcp
->spi
, tx
, sizeof tx
, rx
, sizeof rx
);
69 return (status
< 0) ? status
: rx
[0];
72 static int mcp23s08_write(struct mcp23s08
*mcp
, unsigned reg
, u8 val
)
79 return spi_write_then_read(mcp
->spi
, tx
, sizeof tx
, NULL
, 0);
83 mcp23s08_read_regs(struct mcp23s08
*mcp
, unsigned reg
, u8
*vals
, unsigned n
)
87 if ((n
+ reg
) > sizeof mcp
->cache
)
89 tx
[0] = mcp
->addr
| 0x01;
91 return spi_write_then_read(mcp
->spi
, tx
, sizeof tx
, vals
, n
);
94 /*----------------------------------------------------------------------*/
96 static int mcp23s08_direction_input(struct gpio_chip
*chip
, unsigned offset
)
98 struct mcp23s08
*mcp
= container_of(chip
, struct mcp23s08
, chip
);
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
);
108 static int mcp23s08_get(struct gpio_chip
*chip
, unsigned offset
)
110 struct mcp23s08
*mcp
= container_of(chip
, struct mcp23s08
, chip
);
113 mutex_lock(&mcp
->lock
);
115 /* REVISIT reading this clears any IRQ ... */
116 status
= mcp23s08_read(mcp
, MCP_GPIO
);
120 mcp
->cache
[MCP_GPIO
] = status
;
121 status
= !!(status
& (1 << offset
));
123 mutex_unlock(&mcp
->lock
);
127 static int __mcp23s08_set(struct mcp23s08
*mcp
, unsigned mask
, int value
)
129 u8 olat
= mcp
->cache
[MCP_OLAT
];
135 mcp
->cache
[MCP_OLAT
] = olat
;
136 return mcp23s08_write(mcp
, MCP_OLAT
, olat
);
139 static void mcp23s08_set(struct gpio_chip
*chip
, unsigned offset
, int value
)
141 struct mcp23s08
*mcp
= container_of(chip
, struct mcp23s08
, chip
);
142 u8 mask
= 1 << offset
;
144 mutex_lock(&mcp
->lock
);
145 __mcp23s08_set(mcp
, mask
, value
);
146 mutex_unlock(&mcp
->lock
);
150 mcp23s08_direction_output(struct gpio_chip
*chip
, unsigned offset
, int value
)
152 struct mcp23s08
*mcp
= container_of(chip
, struct mcp23s08
, chip
);
153 u8 mask
= 1 << offset
;
156 mutex_lock(&mcp
->lock
);
157 status
= __mcp23s08_set(mcp
, mask
, value
);
159 mcp
->cache
[MCP_IODIR
] &= ~mask
;
160 status
= mcp23s08_write(mcp
, MCP_IODIR
, mcp
->cache
[MCP_IODIR
]);
162 mutex_unlock(&mcp
->lock
);
166 /*----------------------------------------------------------------------*/
168 #ifdef CONFIG_DEBUG_FS
170 #include <linux/seq_file.h>
173 * This shows more info than the generic gpio dump code:
174 * pullups, deglitching, open drain drive.
176 static void mcp23s08_dbg_show(struct seq_file
*s
, struct gpio_chip
*chip
)
178 struct mcp23s08
*mcp
;
183 mcp
= container_of(chip
, struct mcp23s08
, chip
);
185 /* NOTE: we only handle one bank for now ... */
186 bank
= '0' + ((mcp
->addr
>> 1) & 0x3);
188 mutex_lock(&mcp
->lock
);
189 t
= mcp23s08_read_regs(mcp
, 0, mcp
->cache
, sizeof mcp
->cache
);
191 seq_printf(s
, " I/O ERROR %d\n", t
);
195 for (t
= 0, mask
= 1; t
< 8; t
++, mask
<<= 1) {
198 label
= gpiochip_is_requested(chip
, t
);
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 */
211 mutex_unlock(&mcp
->lock
);
215 #define mcp23s08_dbg_show NULL
218 /*----------------------------------------------------------------------*/
220 static int mcp23s08_probe_one(struct spi_device
*spi
, unsigned addr
,
221 unsigned base
, unsigned pullups
)
223 struct mcp23s08_driver_data
*data
= spi_get_drvdata(spi
);
224 struct mcp23s08
*mcp
= data
->mcp
[addr
];
228 mutex_init(&mcp
->lock
);
231 mcp
->addr
= 0x40 | (addr
<< 1);
233 mcp
->chip
.label
= "mcp23s08",
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
;
241 mcp
->chip
.base
= base
;
243 mcp
->chip
.can_sleep
= 1;
244 mcp
->chip
.dev
= &spi
->dev
;
245 mcp
->chip
.owner
= THIS_MODULE
;
247 /* verify MCP_IOCON.SEQOP = 0, so sequential reads work,
248 * and MCP_IOCON.HAEN = 1, so we work with all chips.
250 status
= mcp23s08_read(mcp
, MCP_IOCON
);
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
);
261 /* configure ~100K pullups */
262 status
= mcp23s08_write(mcp
, MCP_GPPU
, pullups
);
266 status
= mcp23s08_read_regs(mcp
, 0, mcp
->cache
, sizeof mcp
->cache
);
270 /* disable inverter on input */
271 if (mcp
->cache
[MCP_IPOL
] != 0) {
272 mcp
->cache
[MCP_IPOL
] = 0;
277 if (mcp
->cache
[MCP_GPINTEN
] != 0) {
278 mcp
->cache
[MCP_GPINTEN
] = 0;
287 memcpy(&tx
[2], &mcp
->cache
[MCP_IPOL
], sizeof(tx
) - 2);
288 status
= spi_write_then_read(mcp
->spi
, tx
, sizeof tx
, NULL
, 0);
293 status
= gpiochip_add(&mcp
->chip
);
296 dev_dbg(&spi
->dev
, "can't setup chip %d, --> %d\n",
301 static int mcp23s08_probe(struct spi_device
*spi
)
303 struct mcp23s08_platform_data
*pdata
;
306 struct mcp23s08_driver_data
*data
;
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");
316 for (addr
= 0; addr
< 4; addr
++) {
317 if (!pdata
->chip
[addr
].is_present
)
324 data
= kzalloc(sizeof *data
+ chips
* sizeof(struct mcp23s08
),
328 spi_set_drvdata(spi
, data
);
331 for (addr
= 0; addr
< 4; addr
++) {
332 if (!pdata
->chip
[addr
].is_present
)
335 data
->mcp
[addr
] = &data
->chip
[chips
];
336 status
= mcp23s08_probe_one(spi
, addr
, base
,
337 pdata
->chip
[addr
].pullups
);
342 data
->ngpio
= base
- pdata
->base
;
344 /* NOTE: these chips have a relatively sane IRQ framework, with
345 * per-signal masking and level/edge triggering. It's not yet
350 status
= pdata
->setup(spi
,
351 pdata
->base
, data
->ngpio
,
354 dev_dbg(&spi
->dev
, "setup --> %d\n", status
);
360 for (addr
= 0; addr
< 4; addr
++) {
363 if (!data
->mcp
[addr
])
365 tmp
= gpiochip_remove(&data
->mcp
[addr
]->chip
);
367 dev_err(&spi
->dev
, "%s --> %d\n", "remove", tmp
);
373 static int mcp23s08_remove(struct spi_device
*spi
)
375 struct mcp23s08_driver_data
*data
= spi_get_drvdata(spi
);
376 struct mcp23s08_platform_data
*pdata
= spi
->dev
.platform_data
;
380 if (pdata
->teardown
) {
381 status
= pdata
->teardown(spi
,
382 pdata
->base
, data
->ngpio
,
385 dev_err(&spi
->dev
, "%s --> %d\n", "teardown", status
);
390 for (addr
= 0; addr
< 4; addr
++) {
393 if (!data
->mcp
[addr
])
396 tmp
= gpiochip_remove(&data
->mcp
[addr
]->chip
);
398 dev_err(&spi
->dev
, "%s --> %d\n", "remove", tmp
);
407 static struct spi_driver mcp23s08_driver
= {
408 .probe
= mcp23s08_probe
,
409 .remove
= mcp23s08_remove
,
412 .owner
= THIS_MODULE
,
416 /*----------------------------------------------------------------------*/
418 static int __init
mcp23s08_init(void)
420 return spi_register_driver(&mcp23s08_driver
);
422 /* register after spi postcore initcall and before
423 * subsys initcalls that may rely on these GPIOs
425 subsys_initcall(mcp23s08_init
);
427 static void __exit
mcp23s08_exit(void)
429 spi_unregister_driver(&mcp23s08_driver
);
431 module_exit(mcp23s08_exit
);
433 MODULE_LICENSE("GPL");
434 MODULE_ALIAS("spi:mcp23s08");