mcp23s08.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. /*
  2. * mcp23s08.c - SPI gpio expander driver
  3. */
  4. #include <linux/kernel.h>
  5. #include <linux/device.h>
  6. #include <linux/workqueue.h>
  7. #include <linux/mutex.h>
  8. #include <linux/spi/spi.h>
  9. #include <linux/spi/mcp23s08.h>
  10. #include <asm/gpio.h>
  11. /* Registers are all 8 bits wide.
  12. *
  13. * The mcp23s17 has twice as many bits, and can be configured to work
  14. * with either 16 bit registers or with two adjacent 8 bit banks.
  15. *
  16. * Also, there are I2C versions of both chips.
  17. */
  18. #define MCP_IODIR 0x00 /* init/reset: all ones */
  19. #define MCP_IPOL 0x01
  20. #define MCP_GPINTEN 0x02
  21. #define MCP_DEFVAL 0x03
  22. #define MCP_INTCON 0x04
  23. #define MCP_IOCON 0x05
  24. # define IOCON_SEQOP (1 << 5)
  25. # define IOCON_HAEN (1 << 3)
  26. # define IOCON_ODR (1 << 2)
  27. # define IOCON_INTPOL (1 << 1)
  28. #define MCP_GPPU 0x06
  29. #define MCP_INTF 0x07
  30. #define MCP_INTCAP 0x08
  31. #define MCP_GPIO 0x09
  32. #define MCP_OLAT 0x0a
  33. struct mcp23s08 {
  34. struct spi_device *spi;
  35. u8 addr;
  36. /* lock protects the cached values */
  37. struct mutex lock;
  38. u8 cache[11];
  39. struct gpio_chip chip;
  40. struct work_struct work;
  41. };
  42. static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg)
  43. {
  44. u8 tx[2], rx[1];
  45. int status;
  46. tx[0] = mcp->addr | 0x01;
  47. tx[1] = reg;
  48. status = spi_write_then_read(mcp->spi, tx, sizeof tx, rx, sizeof rx);
  49. return (status < 0) ? status : rx[0];
  50. }
  51. static int mcp23s08_write(struct mcp23s08 *mcp, unsigned reg, u8 val)
  52. {
  53. u8 tx[3];
  54. tx[0] = mcp->addr;
  55. tx[1] = reg;
  56. tx[2] = val;
  57. return spi_write_then_read(mcp->spi, tx, sizeof tx, NULL, 0);
  58. }
  59. static int
  60. mcp23s08_read_regs(struct mcp23s08 *mcp, unsigned reg, u8 *vals, unsigned n)
  61. {
  62. u8 tx[2];
  63. if ((n + reg) > sizeof mcp->cache)
  64. return -EINVAL;
  65. tx[0] = mcp->addr | 0x01;
  66. tx[1] = reg;
  67. return spi_write_then_read(mcp->spi, tx, sizeof tx, vals, n);
  68. }
  69. /*----------------------------------------------------------------------*/
  70. static int mcp23s08_direction_input(struct gpio_chip *chip, unsigned offset)
  71. {
  72. struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip);
  73. int status;
  74. mutex_lock(&mcp->lock);
  75. mcp->cache[MCP_IODIR] |= (1 << offset);
  76. status = mcp23s08_write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]);
  77. mutex_unlock(&mcp->lock);
  78. return status;
  79. }
  80. static int mcp23s08_get(struct gpio_chip *chip, unsigned offset)
  81. {
  82. struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip);
  83. int status;
  84. mutex_lock(&mcp->lock);
  85. /* REVISIT reading this clears any IRQ ... */
  86. status = mcp23s08_read(mcp, MCP_GPIO);
  87. if (status < 0)
  88. status = 0;
  89. else {
  90. mcp->cache[MCP_GPIO] = status;
  91. status = !!(status & (1 << offset));
  92. }
  93. mutex_unlock(&mcp->lock);
  94. return status;
  95. }
  96. static int __mcp23s08_set(struct mcp23s08 *mcp, unsigned mask, int value)
  97. {
  98. u8 olat = mcp->cache[MCP_OLAT];
  99. if (value)
  100. olat |= mask;
  101. else
  102. olat &= ~mask;
  103. mcp->cache[MCP_OLAT] = olat;
  104. return mcp23s08_write(mcp, MCP_OLAT, olat);
  105. }
  106. static void mcp23s08_set(struct gpio_chip *chip, unsigned offset, int value)
  107. {
  108. struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip);
  109. u8 mask = 1 << offset;
  110. mutex_lock(&mcp->lock);
  111. __mcp23s08_set(mcp, mask, value);
  112. mutex_unlock(&mcp->lock);
  113. }
  114. static int
  115. mcp23s08_direction_output(struct gpio_chip *chip, unsigned offset, int value)
  116. {
  117. struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip);
  118. u8 mask = 1 << offset;
  119. int status;
  120. mutex_lock(&mcp->lock);
  121. status = __mcp23s08_set(mcp, mask, value);
  122. if (status == 0) {
  123. mcp->cache[MCP_IODIR] &= ~mask;
  124. status = mcp23s08_write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]);
  125. }
  126. mutex_unlock(&mcp->lock);
  127. return status;
  128. }
  129. /*----------------------------------------------------------------------*/
  130. #ifdef CONFIG_DEBUG_FS
  131. #include <linux/seq_file.h>
  132. /*
  133. * This shows more info than the generic gpio dump code:
  134. * pullups, deglitching, open drain drive.
  135. */
  136. static void mcp23s08_dbg_show(struct seq_file *s, struct gpio_chip *chip)
  137. {
  138. struct mcp23s08 *mcp;
  139. char bank;
  140. int t;
  141. unsigned mask;
  142. mcp = container_of(chip, struct mcp23s08, chip);
  143. /* NOTE: we only handle one bank for now ... */
  144. bank = '0' + ((mcp->addr >> 1) & 0x3);
  145. mutex_lock(&mcp->lock);
  146. t = mcp23s08_read_regs(mcp, 0, mcp->cache, sizeof mcp->cache);
  147. if (t < 0) {
  148. seq_printf(s, " I/O ERROR %d\n", t);
  149. goto done;
  150. }
  151. for (t = 0, mask = 1; t < 8; t++, mask <<= 1) {
  152. const char *label;
  153. label = gpiochip_is_requested(chip, t);
  154. if (!label)
  155. continue;
  156. seq_printf(s, " gpio-%-3d P%c.%d (%-12s) %s %s %s",
  157. chip->base + t, bank, t, label,
  158. (mcp->cache[MCP_IODIR] & mask) ? "in " : "out",
  159. (mcp->cache[MCP_GPIO] & mask) ? "hi" : "lo",
  160. (mcp->cache[MCP_GPPU] & mask) ? " " : "up");
  161. /* NOTE: ignoring the irq-related registers */
  162. seq_printf(s, "\n");
  163. }
  164. done:
  165. mutex_unlock(&mcp->lock);
  166. }
  167. #else
  168. #define mcp23s08_dbg_show NULL
  169. #endif
  170. /*----------------------------------------------------------------------*/
  171. static int mcp23s08_probe(struct spi_device *spi)
  172. {
  173. struct mcp23s08 *mcp;
  174. struct mcp23s08_platform_data *pdata;
  175. int status;
  176. int do_update = 0;
  177. pdata = spi->dev.platform_data;
  178. if (!pdata || pdata->slave > 3 || !pdata->base)
  179. return -ENODEV;
  180. mcp = kzalloc(sizeof *mcp, GFP_KERNEL);
  181. if (!mcp)
  182. return -ENOMEM;
  183. mutex_init(&mcp->lock);
  184. mcp->spi = spi;
  185. mcp->addr = 0x40 | (pdata->slave << 1);
  186. mcp->chip.label = "mcp23s08",
  187. mcp->chip.direction_input = mcp23s08_direction_input;
  188. mcp->chip.get = mcp23s08_get;
  189. mcp->chip.direction_output = mcp23s08_direction_output;
  190. mcp->chip.set = mcp23s08_set;
  191. mcp->chip.dbg_show = mcp23s08_dbg_show;
  192. mcp->chip.base = pdata->base;
  193. mcp->chip.ngpio = 8;
  194. mcp->chip.can_sleep = 1;
  195. mcp->chip.owner = THIS_MODULE;
  196. spi_set_drvdata(spi, mcp);
  197. /* verify MCP_IOCON.SEQOP = 0, so sequential reads work */
  198. status = mcp23s08_read(mcp, MCP_IOCON);
  199. if (status < 0)
  200. goto fail;
  201. if (status & IOCON_SEQOP) {
  202. status &= ~IOCON_SEQOP;
  203. status = mcp23s08_write(mcp, MCP_IOCON, (u8) status);
  204. if (status < 0)
  205. goto fail;
  206. }
  207. /* configure ~100K pullups */
  208. status = mcp23s08_write(mcp, MCP_GPPU, pdata->pullups);
  209. if (status < 0)
  210. goto fail;
  211. status = mcp23s08_read_regs(mcp, 0, mcp->cache, sizeof mcp->cache);
  212. if (status < 0)
  213. goto fail;
  214. /* disable inverter on input */
  215. if (mcp->cache[MCP_IPOL] != 0) {
  216. mcp->cache[MCP_IPOL] = 0;
  217. do_update = 1;
  218. }
  219. /* disable irqs */
  220. if (mcp->cache[MCP_GPINTEN] != 0) {
  221. mcp->cache[MCP_GPINTEN] = 0;
  222. do_update = 1;
  223. }
  224. if (do_update) {
  225. u8 tx[4];
  226. tx[0] = mcp->addr;
  227. tx[1] = MCP_IPOL;
  228. memcpy(&tx[2], &mcp->cache[MCP_IPOL], sizeof(tx) - 2);
  229. status = spi_write_then_read(mcp->spi, tx, sizeof tx, NULL, 0);
  230. /* FIXME check status... */
  231. }
  232. status = gpiochip_add(&mcp->chip);
  233. /* NOTE: these chips have a relatively sane IRQ framework, with
  234. * per-signal masking and level/edge triggering. It's not yet
  235. * handled here...
  236. */
  237. if (pdata->setup) {
  238. status = pdata->setup(spi, mcp->chip.base,
  239. mcp->chip.ngpio, pdata->context);
  240. if (status < 0)
  241. dev_dbg(&spi->dev, "setup --> %d\n", status);
  242. }
  243. return 0;
  244. fail:
  245. kfree(mcp);
  246. return status;
  247. }
  248. static int mcp23s08_remove(struct spi_device *spi)
  249. {
  250. struct mcp23s08 *mcp = spi_get_drvdata(spi);
  251. struct mcp23s08_platform_data *pdata = spi->dev.platform_data;
  252. int status = 0;
  253. if (pdata->teardown) {
  254. status = pdata->teardown(spi,
  255. mcp->chip.base, mcp->chip.ngpio,
  256. pdata->context);
  257. if (status < 0) {
  258. dev_err(&spi->dev, "%s --> %d\n", "teardown", status);
  259. return status;
  260. }
  261. }
  262. status = gpiochip_remove(&mcp->chip);
  263. if (status == 0)
  264. kfree(mcp);
  265. else
  266. dev_err(&spi->dev, "%s --> %d\n", "remove", status);
  267. return status;
  268. }
  269. static struct spi_driver mcp23s08_driver = {
  270. .probe = mcp23s08_probe,
  271. .remove = mcp23s08_remove,
  272. .driver = {
  273. .name = "mcp23s08",
  274. .owner = THIS_MODULE,
  275. },
  276. };
  277. /*----------------------------------------------------------------------*/
  278. static int __init mcp23s08_init(void)
  279. {
  280. return spi_register_driver(&mcp23s08_driver);
  281. }
  282. module_init(mcp23s08_init);
  283. static void __exit mcp23s08_exit(void)
  284. {
  285. spi_unregister_driver(&mcp23s08_driver);
  286. }
  287. module_exit(mcp23s08_exit);
  288. MODULE_LICENSE("GPL");