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>
10 #include <linux/spi/spi.h>
11 #include <linux/spi/mcp23s08.h>
16 /* Registers are all 8 bits wide.
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.
21 * Also, there are I2C versions of both chips.
23 #define MCP_IODIR 0x00 /* init/reset: all ones */
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)
35 #define MCP_INTCAP 0x08
40 struct spi_device
*spi
;
44 /* lock protects the cached values */
47 struct gpio_chip chip
;
49 struct work_struct work
;
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.
57 struct mcp23s08_driver_data
{
59 struct mcp23s08
*mcp
[4];
60 struct mcp23s08 chip
[];
63 static int mcp23s08_read(struct mcp23s08
*mcp
, unsigned reg
)
68 tx
[0] = mcp
->addr
| 0x01;
70 status
= spi_write_then_read(mcp
->spi
, tx
, sizeof tx
, rx
, sizeof rx
);
71 return (status
< 0) ? status
: rx
[0];
74 static int mcp23s08_write(struct mcp23s08
*mcp
, unsigned reg
, u8 val
)
81 return spi_write_then_read(mcp
->spi
, tx
, sizeof tx
, NULL
, 0);
85 mcp23s08_read_regs(struct mcp23s08
*mcp
, unsigned reg
, u8
*vals
, unsigned n
)
89 if ((n
+ reg
) > sizeof mcp
->cache
)
91 tx
[0] = mcp
->addr
| 0x01;
93 return spi_write_then_read(mcp
->spi
, tx
, sizeof tx
, vals
, n
);
96 /*----------------------------------------------------------------------*/
98 static int mcp23s08_direction_input(struct gpio_chip
*chip
, unsigned offset
)
100 struct mcp23s08
*mcp
= container_of(chip
, struct mcp23s08
, chip
);
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
);
110 static int mcp23s08_get(struct gpio_chip
*chip
, unsigned offset
)
112 struct mcp23s08
*mcp
= container_of(chip
, struct mcp23s08
, chip
);
115 mutex_lock(&mcp
->lock
);
117 /* REVISIT reading this clears any IRQ ... */
118 status
= mcp23s08_read(mcp
, MCP_GPIO
);
122 mcp
->cache
[MCP_GPIO
] = status
;
123 status
= !!(status
& (1 << offset
));
125 mutex_unlock(&mcp
->lock
);
129 static int __mcp23s08_set(struct mcp23s08
*mcp
, unsigned mask
, int value
)
131 u8 olat
= mcp
->cache
[MCP_OLAT
];
137 mcp
->cache
[MCP_OLAT
] = olat
;
138 return mcp23s08_write(mcp
, MCP_OLAT
, olat
);
141 static void mcp23s08_set(struct gpio_chip
*chip
, unsigned offset
, int value
)
143 struct mcp23s08
*mcp
= container_of(chip
, struct mcp23s08
, chip
);
144 u8 mask
= 1 << offset
;
146 mutex_lock(&mcp
->lock
);
147 __mcp23s08_set(mcp
, mask
, value
);
148 mutex_unlock(&mcp
->lock
);
152 mcp23s08_direction_output(struct gpio_chip
*chip
, unsigned offset
, int value
)
154 struct mcp23s08
*mcp
= container_of(chip
, struct mcp23s08
, chip
);
155 u8 mask
= 1 << offset
;
158 mutex_lock(&mcp
->lock
);
159 status
= __mcp23s08_set(mcp
, mask
, value
);
161 mcp
->cache
[MCP_IODIR
] &= ~mask
;
162 status
= mcp23s08_write(mcp
, MCP_IODIR
, mcp
->cache
[MCP_IODIR
]);
164 mutex_unlock(&mcp
->lock
);
168 /*----------------------------------------------------------------------*/
170 #ifdef CONFIG_DEBUG_FS
172 #include <linux/seq_file.h>
175 * This shows more info than the generic gpio dump code:
176 * pullups, deglitching, open drain drive.
178 static void mcp23s08_dbg_show(struct seq_file
*s
, struct gpio_chip
*chip
)
180 struct mcp23s08
*mcp
;
185 mcp
= container_of(chip
, struct mcp23s08
, chip
);
187 /* NOTE: we only handle one bank for now ... */
188 bank
= '0' + ((mcp
->addr
>> 1) & 0x3);
190 mutex_lock(&mcp
->lock
);
191 t
= mcp23s08_read_regs(mcp
, 0, mcp
->cache
, sizeof mcp
->cache
);
193 seq_printf(s
, " I/O ERROR %d\n", t
);
197 for (t
= 0, mask
= 1; t
< 8; t
++, mask
<<= 1) {
200 label
= gpiochip_is_requested(chip
, t
);
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 */
213 mutex_unlock(&mcp
->lock
);
217 #define mcp23s08_dbg_show NULL
220 /*----------------------------------------------------------------------*/
222 static int mcp23s08_probe_one(struct spi_device
*spi
, unsigned addr
,
223 unsigned base
, unsigned pullups
)
225 struct mcp23s08_driver_data
*data
= spi_get_drvdata(spi
);
226 struct mcp23s08
*mcp
= data
->mcp
[addr
];
230 mutex_init(&mcp
->lock
);
233 mcp
->addr
= 0x40 | (addr
<< 1);
235 mcp
->chip
.label
= "mcp23s08",
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
;
243 mcp
->chip
.base
= base
;
245 mcp
->chip
.can_sleep
= 1;
246 mcp
->chip
.dev
= &spi
->dev
;
247 mcp
->chip
.owner
= THIS_MODULE
;
249 /* verify MCP_IOCON.SEQOP = 0, so sequential reads work,
250 * and MCP_IOCON.HAEN = 1, so we work with all chips.
252 status
= mcp23s08_read(mcp
, MCP_IOCON
);
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
);
263 /* configure ~100K pullups */
264 status
= mcp23s08_write(mcp
, MCP_GPPU
, pullups
);
268 status
= mcp23s08_read_regs(mcp
, 0, mcp
->cache
, sizeof mcp
->cache
);
272 /* disable inverter on input */
273 if (mcp
->cache
[MCP_IPOL
] != 0) {
274 mcp
->cache
[MCP_IPOL
] = 0;
279 if (mcp
->cache
[MCP_GPINTEN
] != 0) {
280 mcp
->cache
[MCP_GPINTEN
] = 0;
289 memcpy(&tx
[2], &mcp
->cache
[MCP_IPOL
], sizeof(tx
) - 2);
290 status
= spi_write_then_read(mcp
->spi
, tx
, sizeof tx
, NULL
, 0);
295 status
= gpiochip_add(&mcp
->chip
);
298 dev_dbg(&spi
->dev
, "can't setup chip %d, --> %d\n",
303 static int mcp23s08_probe(struct spi_device
*spi
)
305 struct mcp23s08_platform_data
*pdata
;
308 struct mcp23s08_driver_data
*data
;
312 pdata
= spi
->dev
.platform_data
;
313 if (!pdata
|| !gpio_is_valid(pdata
->base
))
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 module_init(mcp23s08_init
);
424 static void __exit
mcp23s08_exit(void)
426 spi_unregister_driver(&mcp23s08_driver
);
428 module_exit(mcp23s08_exit
);
430 MODULE_LICENSE("GPL");