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