Advertisement
danielhilst

gpio-mcp23s08.c

Nov 11th, 2015
218
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 33.71 KB | None | 0 0
  1. /*
  2.  * MCP23S08 SPI/GPIO gpio expander driver
  3.  */
  4.  
  5. #include <linux/kernel.h>
  6. #include <linux/device.h>
  7. #include <linux/mutex.h>
  8. #include <linux/module.h>
  9. #include <linux/gpio.h>
  10. #include <linux/i2c.h>
  11. #include <linux/spi/spi.h>
  12. #include <linux/spi/mcp23s08.h>
  13. #include <linux/slab.h>
  14. #include <asm/byteorder.h>
  15. #include <linux/of.h>
  16. #include <linux/of_device.h>
  17. #include <linux/interrupt.h>
  18. #include <linux/circ_buf.h>
  19.  
  20. /**
  21.  * MCP types supported by driver
  22.  */
  23. #define MCP_TYPE_S08    0
  24. #define MCP_TYPE_S17    1
  25. #define MCP_TYPE_008    2
  26. #define MCP_TYPE_017    3
  27.  
  28. /* Registers are all 8 bits wide.
  29.  *
  30.  * The mcp23s17 has twice as many bits, and can be configured to work
  31.  * with either 16 bit registers or with two adjacent 8 bit banks.
  32.  */
  33. #define MCP_IODIR   0x00        /* init/reset:  all ones */
  34. #define MCP_IPOL    0x01
  35. #define MCP_GPINTEN 0x02
  36. #define MCP_DEFVAL  0x03
  37. #define MCP_INTCON  0x04
  38. #define MCP_IOCON   0x05
  39. #   define IOCON_SEQOP  (1 << 5)
  40. #   define IOCON_HAEN   (1 << 3)
  41. #   define IOCON_ODR    (1 << 2)
  42. #   define IOCON_INTPOL (1 << 1)
  43. #define MCP_GPPU    0x06
  44. #define MCP_INTF    0x07
  45. #define MCP_INTCAP  0x08
  46. #define MCP_GPIO    0x09
  47. #define MCP_OLAT    0x0a
  48.  
  49. struct mcp23s08;
  50.  
  51. struct mcp23s08_ops {
  52.     int (*read)(struct mcp23s08 *mcp, unsigned reg);
  53.     int (*write)(struct mcp23s08 *mcp, unsigned reg, unsigned val);
  54.     int (*read_regs)(struct mcp23s08 *mcp, unsigned reg,
  55.                  u16 *vals, unsigned n);
  56. };
  57.  
  58. struct mcp23s08 {
  59.     u8          addr;
  60.  
  61.     u16         cache[11];
  62.     /* lock protects the cached values */
  63.     struct mutex        lock;
  64.  
  65.     struct gpio_chip    chip;
  66.  
  67.     const struct mcp23s08_ops   *ops;
  68.     void            *data; /* ops specific data */
  69.         spinlock_t              msg_slk;
  70.         unsigned long           msg_slkflags;
  71.         struct spi_message      message; /* used for non-sleep reads */
  72.         u8                      tx[4];
  73.         u8                      rx[4];
  74.         struct spi_transfer tsf[4];
  75. };
  76.  
  77. /* A given spi_device can represent up to eight mcp23sxx chips
  78.  * sharing the same chipselect but using different addresses
  79.  * (e.g. chips #0 and #3 might be populated, but not #1 or $2).
  80.  * Driver data holds all the per-chip data.
  81.  */
  82. struct mcp23s08_driver_data {
  83.     unsigned        ngpio;
  84.     struct mcp23s08     *mcp[8];
  85.     struct mcp23s08     chip[];
  86. };
  87.  
  88. /* CSI STUFF:
  89.  *
  90.  * Optimized way to get input mask. Otherwise a read on every input
  91.  * pin is needed.
  92.  */
  93. #define REVISION "CSI: $Id: gpio-mcp23s08.c 14863 2015-08-26 18:56:55Z daniel.hilst $"
  94. #define LOG_msg(pri, fmt, args...) \
  95.         ({pr_ ## pri("mcp23s08 [" #pri "] %s@%d: " fmt "\n", __func__, __LINE__, ##args);})
  96. #ifdef  DEBUG
  97. # define LOG_debug(fmt, args...) LOG_msg(debug, fmt, ##args)
  98. #else
  99. # define LOG_debug(fmt, args...)
  100. #endif
  101. #define LOG_info(fmt, args...)  LOG_msg(info,  fmt, ##args)
  102. #define LOG_warn(fmt, args...)  LOG_msg(warn,  fmt, ##args)
  103. #define LOG_err(fmt, args...)   LOG_msg(err,   fmt, ##args)
  104.  
  105. static struct mcp23s08 *mcp_global = NULL;
  106. int mcp_getmask(void)
  107. {
  108.         int mask;
  109.         if (!mcp_global)
  110.                 return -1;
  111.  
  112.         mask = mcp_global->ops->read(mcp_global, MCP_GPIO);
  113.         if (mask < 0)
  114.                 return -2;
  115.  
  116.         return (0xff & ~(mask));
  117. }
  118. EXPORT_SYMBOL_GPL(mcp_getmask);
  119.  
  120. static DECLARE_WAIT_QUEUE_HEAD(mcp_irq_wq);
  121. static unsigned mcp_input_change = 0;
  122. static unsigned mcp_intcap;
  123. static unsigned mcp_lost_irq = 0;
  124. static unsigned mcp_total_irq = 0;
  125. static unsigned mcp_waited_irq = 0;
  126. int mcp_wait_irq(unsigned long timeout, unsigned mask, unsigned *intcap)
  127. {
  128.         int status;
  129.  
  130.         mcp_waited_irq++;
  131.         do {
  132.                 unsigned long bfwait = jiffies;
  133.  
  134.                 mcp_input_change = 0; /* reset condition */
  135.                 status = wait_event_interruptible_timeout(mcp_irq_wq, /* wait irq */
  136.                                                           mcp_input_change,
  137.                                                           timeout);
  138.                 if (status == 0) /* timeout */
  139.                         return -ETIME;
  140.  
  141.                 if ((status > 0) && /* interrupt happen before timeout */
  142.                     mcp_input_change) {
  143.                         *intcap = mcp_intcap;
  144.                         return 0;
  145.                 }
  146.  
  147.                 if (status == -ERESTARTSYS)
  148.                         return -ERESTARTSYS;
  149.                
  150.                 timeout = (bfwait + timeout) - jiffies;
  151.         } while (timeout > 0);
  152.         return -ETIME;
  153. }
  154. EXPORT_SYMBOL_GPL(mcp_wait_irq);
  155.  
  156. /* Circular queue, allocated at _probe()
  157.  *
  158.  *  NOTE: Applies only to mcp_global!
  159.  */
  160. static struct   circ_buf mcp_circ;
  161. static               int mcp_circ_hit_full = 0;
  162. static               int mcp_circ_produced = 0;
  163. static               int mcp_circ_consumed = 0;
  164. static               int mcp_circ_new_data = 0;
  165. static DECLARE_WAIT_QUEUE_HEAD(mcp_circ_wq);
  166. static struct      mutex mcp_circ_cons_lock;
  167. int mcp_getlast(int *msk, unsigned int timeout)
  168. {
  169.         int rc;
  170.         unsigned long head, tail;
  171.         unsigned long tout = timeout * HZ / 1000; /* convert from ms to jiffies */
  172.  
  173.         BUG_ON(!msk);
  174.  
  175.         LOG_debug("timeout %u", timeout);
  176.         LOG_debug("timeout in jiffies %lu", tout);
  177.         mutex_lock(&mcp_circ_cons_lock);
  178.  
  179.         for (;;) {
  180.                 head = ACCESS_ONCE(mcp_circ.head); /* read head */
  181.                 tail = mcp_circ.tail;              /* read tail */
  182.        
  183.                 if (CIRC_CNT(head, tail, PAGE_SIZE) >= 1) {
  184.                         LOG_debug("retrieving mask from queue");
  185.                         smp_read_barrier_depends(); /* complete the reads before this line */
  186.                         *msk = mcp_circ.buf[tail];  /* read the mask from queue */
  187.                         smp_mb();
  188.                         mcp_circ_consumed++;
  189.                         mcp_circ.tail = (tail + 1) & (PAGE_SIZE - 1); /* update tail */
  190.                         LOG_debug("0x%x consumed", *msk);
  191.                         rc = 0; /* return success */
  192.                         break;  /* break loop */
  193.                 } else {
  194.                         LOG_debug("queue empty waiting");
  195.                         mcp_circ_new_data = 0;
  196.                         rc = wait_event_interruptible_timeout(mcp_circ_wq, mcp_circ_new_data, tout);
  197.                         if (rc == -ERESTARTSYS) { /* interrupted  */
  198.                                 break;            /* return */
  199.                         } else if (rc == 0) {     /* timeout */
  200.                                 rc = -ETIME;    
  201.                                 break;       /* return */
  202.                         } else if (rc > 0) {      /* new input mask! */
  203.                                 continue; /* queue is not empty
  204.                                            * anymore, start loop again
  205.                                            * to get a new head and
  206.                                            * tail */
  207.                         }
  208.                 }
  209.         }
  210.  
  211.         mutex_unlock(&mcp_circ_cons_lock);
  212.         LOG_debug("returning %d", rc);
  213.         return rc;
  214. }
  215. EXPORT_SYMBOL_GPL(mcp_getlast);
  216.  
  217. void mcp_flush_queue(void)
  218. {
  219.         LOG_debug("flushing events queue");
  220.         mcp_circ.head = mcp_circ.tail = 0;
  221.         mcp_circ_hit_full = 0;
  222.         mcp_circ_produced = 0;
  223.         mcp_circ_consumed = 0;
  224.         memset(mcp_circ.buf, '\0', PAGE_SIZE);
  225. }
  226. EXPORT_SYMBOL_GPL(mcp_flush_queue);
  227.  
  228. /* Sysfs ---------------------------------------------------------------- */
  229. ssize_t show_queue(struct device *dev, struct device_attribute *attr, char *buf)
  230. {
  231.         int head = ACCESS_ONCE(mcp_circ.head);
  232.         int tail = ACCESS_ONCE(mcp_circ.tail);
  233.  
  234.         return snprintf(buf, PAGE_SIZE,
  235.                         "Queue Size:      %5lu\n"
  236.                         "Queue Available: %5lu\n"
  237.                         "Queue Total:     %5lu\n"
  238.                         "Queue Full hits: %5d\n"
  239.                         "Events produced: %5d\n"
  240.                         "Events consumed: %5d\n",
  241.                         CIRC_CNT(head, tail, PAGE_SIZE),
  242.                         CIRC_SPACE(head, tail, PAGE_SIZE),
  243.                         PAGE_SIZE,
  244.                         mcp_circ_hit_full,
  245.                         mcp_circ_produced,
  246.                         mcp_circ_consumed
  247.                 );
  248. }
  249. static DEVICE_ATTR(queue, 0400, show_queue, NULL);
  250.  
  251. ssize_t show_lost_irq(struct device *dev, struct device_attribute *attr, char *buf)
  252. {
  253.         return snprintf(buf, PAGE_SIZE,
  254.                         "IRQs:   % 5d\n"
  255.                         "Waited: % 5d\n"
  256.                         "Lost:   % 5d\n",
  257.                         mcp_total_irq,
  258.                         mcp_waited_irq,
  259.                         mcp_lost_irq);
  260. }
  261.  
  262. ssize_t store_lost_irq(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
  263. {
  264.         mcp_lost_irq = 0;
  265.         mcp_total_irq = 0;
  266.         mcp_waited_irq = 0;
  267.         return count;
  268. }
  269. static DEVICE_ATTR(lost_irq, 0600, show_lost_irq, store_lost_irq);
  270.  
  271. ssize_t show_reg(struct device *dev, struct device_attribute *attr, char *buf)
  272. {
  273.     int             addr, reg, off = 0;
  274.         struct spi_device               *spi = to_spi_device(dev);
  275.     struct mcp23s08_driver_data *data = spi_get_drvdata(spi);
  276.         int type = spi_get_device_id(spi)->driver_data;
  277.  
  278.         for (addr = 0; data->mcp[addr]; addr++) {
  279.                 struct mcp23s08 *mcp = data->mcp[addr];
  280.  
  281.                 mutex_lock(&mcp->lock);
  282.                 mcp->ops->read_regs(mcp, 0, mcp->cache, ARRAY_SIZE(mcp->cache));
  283.                 mutex_unlock(&mcp->lock);
  284.  
  285.                 off += snprintf(buf + off, PAGE_SIZE - off, "CHIP %d:\n--\n", addr);
  286.  
  287.                 if (type == MCP_TYPE_S17)
  288.                         off += snprintf(buf + off, PAGE_SIZE - off, "REG =>  B A\n");
  289.  
  290.                 for (reg = 0; reg < ARRAY_SIZE(mcp->cache); reg++)
  291.                         off += snprintf(buf + off, PAGE_SIZE - off, "%02xh => %04xh\n",
  292.                                         type == MCP_TYPE_S17 ? reg << 1 : reg,
  293.                                         mcp->cache[reg]);
  294.  
  295.         }
  296.  
  297.         return off;
  298. }
  299.  
  300. ssize_t store_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
  301. {
  302.         struct spi_device               *spi = to_spi_device(dev);
  303.     struct mcp23s08_driver_data *data = spi_get_drvdata(spi);
  304.         u8                              regaddr;
  305.         u16                             regval;
  306.         int                             chipaddr, status;
  307.         struct mcp23s08                 *mcp;
  308.         int                             type = spi_get_device_id(spi)->driver_data;
  309.  
  310.         status = sscanf(buf, "%x:%hhx:%hx", &chipaddr, &regaddr, &regval);
  311.  
  312.         if ((chipaddr < 0  ||
  313.              chipaddr > 3) ||
  314.             (regaddr < 0   ||
  315.              regaddr > 22))
  316.                 return -EINVAL;
  317.  
  318.         if (type == MCP_TYPE_S17)
  319.                 regaddr >>= 1;
  320.  
  321.         mcp = data->mcp[chipaddr];
  322.         mcp->ops->write(mcp, regaddr, regval);
  323.  
  324.         return count;
  325. }
  326. static DEVICE_ATTR(registers, 0600, show_reg, store_reg);
  327.  
  328. static struct attribute *mcp_attrs[] = {
  329.         &dev_attr_registers.attr,
  330.         &dev_attr_lost_irq.attr,
  331.         &dev_attr_queue.attr,
  332.         NULL,
  333. };
  334.  
  335. static struct attribute_group mcp_attr_group = {
  336.         .attrs = mcp_attrs,
  337. }
  338. ;
  339. /* IRQ ---------------------------------------------------------------- */
  340.  
  341. /* - A little explanation -
  342.  *
  343.  * The MCP23S17Q will generate a interrupt at each interrupt change,
  344.  * this will trigger the control path mcp_hard_irq() ->
  345.  * mcp23s17_produce() -> spi_async_locked() -//-> SPI core ->
  346.  * mcp23s17_produce_complete(). Note that spi_async_locked() will not
  347.  * block, so that mcp23s17_produce() will return before that
  348.  * mcp23s17_produce_complete() is called. The mcp23s17_produce() will
  349.  * use struct mcp23s08 { message, tx, rx, tx_tsf } buffers. They are
  350.  * global, allocated at _probe_one(). The interrupts will remain
  351.  * disabled (at MCP) until INTCAP is readed[1], this is the chip
  352.  * behavior. If you look carefully the INTCAP register is readed
  353.  * inside SPI core, so the buffers used inside of the struct mcp23s08
  354.  * must not be accessed before mcp23s17_produce_complete() returns,
  355.  * otherwise a race condition arises, i.e., calling spi_message_init()
  356.  * on a posted spi_message. struct mcp23s08 { msg_slk } spinlock is
  357.  * used to prevent this race condition, is locked at
  358.  * mcp23s08_produce() and unlocked if spi_async_locked() fail or at
  359.  * the end of the mcp23s08_produce_complete() if spi_async_locked()
  360.  * succeed.
  361.  *
  362.  * [1] MCP23S17Q Datasheet, section 1.7.4, page 24.
  363.  */
  364.  
  365. /* called from mcp_hard_irq (interrupt context) */
  366. static void mcp23s17_produce_complete(void *args)
  367. {
  368.         struct mcp23s08 *mcp = args;
  369.  
  370.         if (mcp->message.status == 0) { /* success transfer */
  371.                 /* begin of mcp_circ producer */
  372.                 do {
  373.                         int head = mcp_circ.head;
  374.                         int tail = ACCESS_ONCE(mcp_circ.tail);
  375.  
  376.                         mcp_total_irq++;
  377.                         /* Check if there is space on buffer. */
  378.                         if (CIRC_SPACE(head, tail, PAGE_SIZE) >= 1) {
  379.                                 u8 v = (0xff & ~(mcp->rx[0]));
  380.                                 if (mcp_intcap == v)
  381.                                     trace_printk("mcp23s08: fake input change %02x, %02x\n",
  382.                                                  mcp_intcap, v);
  383.                                 mcp_intcap = v;
  384.                                 mcp_circ.buf[head] = v;
  385.                                 smp_wmb();
  386.                                 mcp_circ_produced++;
  387.                                 mcp_circ.head = (head + 1) & (PAGE_SIZE - 1);
  388.                         } else  {
  389.                                 mcp_circ_hit_full++; /* keep track of full hits */
  390.                                 break;
  391.                         }
  392.                 } while (0);
  393.         } else
  394.                 trace_printk("mcp23s08: Error on SPI transfer, %d\n", mcp->message.status);
  395.  
  396.         spin_unlock_irqrestore(&mcp->msg_slk, mcp->msg_slkflags);
  397. }
  398.  
  399. /* will not sleep */
  400. static int mcp23s17_produce(struct mcp23s08 *mcp)
  401. {
  402.         int status;
  403.         struct spi_device *spi = mcp->data;
  404.         spin_lock_irqsave(&mcp->msg_slk, mcp->msg_slkflags);
  405.         mcp->tsf[0].tx_buf = mcp->tx;
  406.         mcp->tsf[1].rx_buf = mcp->rx;
  407.         mcp->tsf[0].len    = 2;
  408.         mcp->tsf[1].len    = 2;
  409.         mcp->tx[0] = mcp->addr | 0x01;
  410.         mcp->tx[1] = MCP_INTCAP << 1;
  411.         spi_message_init(&mcp->message);
  412.         spi_message_add_tail(&mcp->tsf[0], &mcp->message);
  413.         spi_message_add_tail(&mcp->tsf[1], &mcp->message);
  414.         mcp->message.complete = mcp23s17_produce_complete;
  415.         mcp->message.context  = mcp;
  416.         status = spi_async_locked(spi, &mcp->message);
  417.         if (status) {
  418.                 spin_unlock_irqrestore(&mcp->msg_slk, mcp->msg_slkflags);
  419.                 trace_printk("mcp23s08: spi_async_locked returned an error, %d\n", status);
  420.         }
  421.         return status;
  422. }
  423.  
  424. static irqreturn_t mcp_hard_irq(int irq, void *handle)
  425. {
  426.         mcp23s17_produce(handle);
  427.         return IRQ_WAKE_THREAD;
  428. }
  429.  
  430. static irqreturn_t mcp_irq(int irq, void *handle)
  431. {
  432.         LOG_debug("IRQ triggered");
  433.  
  434.         if (list_empty(&mcp_irq_wq.task_list))
  435.                 mcp_lost_irq++;
  436.  
  437.         mcp_circ_new_data = 1;
  438.         wake_up_interruptible(&mcp_circ_wq);
  439.  
  440.         mcp_input_change = 1;
  441.         wake_up_interruptible(&mcp_irq_wq);
  442.  
  443.         return IRQ_HANDLED;
  444. }
  445.  
  446. /* end of CSI STUFF */
  447. /*----------------------------------------------------------------------*/
  448.  
  449. #if IS_ENABLED(CONFIG_I2C)
  450.  
  451. static int mcp23008_read(struct mcp23s08 *mcp, unsigned reg)
  452. {
  453.     return i2c_smbus_read_byte_data(mcp->data, reg);
  454. }
  455.  
  456. static int mcp23008_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)
  457. {
  458.     return i2c_smbus_write_byte_data(mcp->data, reg, val);
  459. }
  460.  
  461. static int
  462. mcp23008_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
  463. {
  464.     while (n--) {
  465.         int ret = mcp23008_read(mcp, reg++);
  466.         if (ret < 0)
  467.             return ret;
  468.         *vals++ = ret;
  469.     }
  470.  
  471.     return 0;
  472. }
  473.  
  474. static int mcp23017_read(struct mcp23s08 *mcp, unsigned reg)
  475. {
  476.     return i2c_smbus_read_word_data(mcp->data, reg << 1);
  477. }
  478.  
  479. static int mcp23017_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)
  480. {
  481.     return i2c_smbus_write_word_data(mcp->data, reg << 1, val);
  482. }
  483.  
  484. static int
  485. mcp23017_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
  486. {
  487.     while (n--) {
  488.         int ret = mcp23017_read(mcp, reg++);
  489.         if (ret < 0)
  490.             return ret;
  491.         *vals++ = ret;
  492.     }
  493.  
  494.     return 0;
  495. }
  496.  
  497. static const struct mcp23s08_ops mcp23008_ops = {
  498.     .read       = mcp23008_read,
  499.     .write      = mcp23008_write,
  500.     .read_regs  = mcp23008_read_regs,
  501. };
  502.  
  503. static const struct mcp23s08_ops mcp23017_ops = {
  504.     .read       = mcp23017_read,
  505.     .write      = mcp23017_write,
  506.     .read_regs  = mcp23017_read_regs,
  507. };
  508.  
  509. #endif /* CONFIG_I2C */
  510.  
  511. /*----------------------------------------------------------------------*/
  512.  
  513. #ifdef CONFIG_SPI_MASTER
  514.  
  515. static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg)
  516. {
  517.     u8  tx[2], rx[1];
  518.     int status;
  519.  
  520.     tx[0] = mcp->addr | 0x01;
  521.     tx[1] = reg;
  522.     status = spi_write_then_read(mcp->data, tx, sizeof tx, rx, sizeof rx);
  523.     return (status < 0) ? status : rx[0];
  524. }
  525.  
  526. static int mcp23s08_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)
  527. {
  528.     u8  tx[3];
  529.  
  530.     tx[0] = mcp->addr;
  531.     tx[1] = reg;
  532.     tx[2] = val;
  533.     return spi_write_then_read(mcp->data, tx, sizeof tx, NULL, 0);
  534. }
  535.  
  536. static int
  537. mcp23s08_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
  538. {
  539.     u8  tx[2], *tmp;
  540.     int status;
  541.  
  542.     if ((n + reg) > sizeof mcp->cache)
  543.         return -EINVAL;
  544.     tx[0] = mcp->addr | 0x01;
  545.     tx[1] = reg;
  546.  
  547.     tmp = (u8 *)vals;
  548.     status = spi_write_then_read(mcp->data, tx, sizeof tx, tmp, n);
  549.     if (status >= 0) {
  550.         while (n--)
  551.             vals[n] = tmp[n]; /* expand to 16bit */
  552.     }
  553.     return status;
  554. }
  555.  
  556. static int mcp23s17_read(struct mcp23s08 *mcp, unsigned reg)
  557. {
  558.     u8  tx[2], rx[2];
  559.     int status;
  560.  
  561.     tx[0] = mcp->addr | 0x01;
  562.     tx[1] = reg << 1;
  563.     status = spi_write_then_read(mcp->data, tx, sizeof tx, rx, sizeof rx);
  564.     return (status < 0) ? status : (rx[0] | (rx[1] << 8));
  565. }
  566.  
  567. static int mcp23s17_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)
  568. {
  569.     u8  tx[4];
  570.  
  571.     tx[0] = mcp->addr;
  572.     tx[1] = reg << 1;
  573.     tx[2] = val;
  574.     tx[3] = val >> 8;
  575.     return spi_write_then_read(mcp->data, tx, sizeof tx, NULL, 0);
  576. }
  577.  
  578. static int
  579. mcp23s17_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
  580. {
  581.     u8  tx[2];
  582.     int status;
  583.  
  584.     if ((n + reg) > sizeof mcp->cache)
  585.         return -EINVAL;
  586.     tx[0] = mcp->addr | 0x01;
  587.     tx[1] = reg << 1;
  588.  
  589.     status = spi_write_then_read(mcp->data, tx, sizeof tx,
  590.                      (u8 *)vals, n * 2);
  591.     if (status >= 0) {
  592.         while (n--)
  593.             vals[n] = __le16_to_cpu((__le16)vals[n]);
  594.     }
  595.  
  596.     return status;
  597. }
  598.  
  599. static const struct mcp23s08_ops mcp23s08_ops = {
  600.     .read       = mcp23s08_read,
  601.     .write      = mcp23s08_write,
  602.     .read_regs  = mcp23s08_read_regs,
  603. };
  604.  
  605. static const struct mcp23s08_ops mcp23s17_ops = {
  606.     .read       = mcp23s17_read,
  607.     .write      = mcp23s17_write,
  608.     .read_regs  = mcp23s17_read_regs,
  609. };
  610.  
  611. #endif /* CONFIG_SPI_MASTER */
  612.  
  613. /*----------------------------------------------------------------------*/
  614.  
  615. static int mcp23s08_direction_input(struct gpio_chip *chip, unsigned offset)
  616. {
  617.     struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip);
  618.     int status;
  619.  
  620.     mutex_lock(&mcp->lock);
  621.     mcp->cache[MCP_IODIR] |= (1 << offset);
  622.     status = mcp->ops->write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]);
  623.     mutex_unlock(&mcp->lock);
  624.     return status;
  625. }
  626.  
  627. static int mcp23s08_get(struct gpio_chip *chip, unsigned offset)
  628. {
  629.     struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip);
  630.     int status;
  631.  
  632.     mutex_lock(&mcp->lock);
  633.  
  634.     /* REVISIT reading this clears any IRQ ... */
  635.     status = mcp->ops->read(mcp, MCP_GPIO);
  636.     if (status < 0)
  637.         status = 0;
  638.     else {
  639.         mcp->cache[MCP_GPIO] = status;
  640.         status = !!(status & (1 << offset));
  641.     }
  642.     mutex_unlock(&mcp->lock);
  643.     return status;
  644. }
  645.  
  646. static int __mcp23s08_set(struct mcp23s08 *mcp, unsigned mask, int value)
  647. {
  648.     unsigned olat = mcp->cache[MCP_OLAT];
  649.  
  650.     if (value)
  651.         olat |= mask;
  652.     else
  653.         olat &= ~mask;
  654.     mcp->cache[MCP_OLAT] = olat;
  655.     return mcp->ops->write(mcp, MCP_OLAT, olat);
  656. }
  657.  
  658. static void mcp23s08_set(struct gpio_chip *chip, unsigned offset, int value)
  659. {
  660.     struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip);
  661.     unsigned mask = 1 << offset;
  662.  
  663.     mutex_lock(&mcp->lock);
  664.     __mcp23s08_set(mcp, mask, value);
  665.     mutex_unlock(&mcp->lock);
  666. }
  667.  
  668. static int
  669. mcp23s08_direction_output(struct gpio_chip *chip, unsigned offset, int value)
  670. {
  671.     struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip);
  672.     unsigned mask = 1 << offset;
  673.     int status;
  674.  
  675.     mutex_lock(&mcp->lock);
  676.     status = __mcp23s08_set(mcp, mask, value);
  677.     if (status == 0) {
  678.         mcp->cache[MCP_IODIR] &= ~mask;
  679.         status = mcp->ops->write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]);
  680.     }
  681.     mutex_unlock(&mcp->lock);
  682.     return status;
  683. }
  684.  
  685. /*----------------------------------------------------------------------*/
  686.  
  687. #ifdef CONFIG_DEBUG_FS
  688.  
  689. #include <linux/seq_file.h>
  690.  
  691. /*
  692.  * This shows more info than the generic gpio dump code:
  693.  * pullups, deglitching, open drain drive.
  694.  */
  695. static void mcp23s08_dbg_show(struct seq_file *s, struct gpio_chip *chip)
  696. {
  697.     struct mcp23s08 *mcp;
  698.     char        bank;
  699.     int     t;
  700.     unsigned    mask;
  701.  
  702.     mcp = container_of(chip, struct mcp23s08, chip);
  703.  
  704.     /* NOTE: we only handle one bank for now ... */
  705.     bank = '0' + ((mcp->addr >> 1) & 0x7);
  706.  
  707.     mutex_lock(&mcp->lock);
  708.     t = mcp->ops->read_regs(mcp, 0, mcp->cache, ARRAY_SIZE(mcp->cache));
  709.     if (t < 0) {
  710.         seq_printf(s, " I/O ERROR %d\n", t);
  711.         goto done;
  712.     }
  713.  
  714.     for (t = 0, mask = 1; t < chip->ngpio; t++, mask <<= 1) {
  715.         const char  *label;
  716.  
  717.         label = gpiochip_is_requested(chip, t);
  718.         if (!label)
  719.             continue;
  720.  
  721.         seq_printf(s, " gpio-%-3d P%c.%d (%-12s) %s %s %s",
  722.             chip->base + t, bank, t, label,
  723.             (mcp->cache[MCP_IODIR] & mask) ? "in " : "out",
  724.             (mcp->cache[MCP_GPIO] & mask) ? "hi" : "lo",
  725.             (mcp->cache[MCP_GPPU] & mask) ? "up" : "  ");
  726.         /* NOTE:  ignoring the irq-related registers */
  727.         seq_printf(s, "\n");
  728.     }
  729. done:
  730.     mutex_unlock(&mcp->lock);
  731. }
  732.  
  733. #else
  734. #define mcp23s08_dbg_show   NULL
  735. #endif
  736.  
  737. /*----------------------------------------------------------------------*/
  738.  
  739. static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
  740.                   void *data, unsigned addr,
  741.                   unsigned type, unsigned base, unsigned pullups)
  742. {
  743.     int status;
  744.  
  745.         LOG_debug("");
  746.         LOG_debug("initializing driver data lock");
  747.     mutex_init(&mcp->lock);
  748.  
  749.     mcp->data = data;
  750.     mcp->addr = addr;
  751.  
  752.     mcp->chip.direction_input = mcp23s08_direction_input;
  753.     mcp->chip.get = mcp23s08_get;
  754.     mcp->chip.direction_output = mcp23s08_direction_output;
  755.     mcp->chip.set = mcp23s08_set;
  756.     mcp->chip.dbg_show = mcp23s08_dbg_show;
  757. #ifdef CONFIG_OF
  758.     mcp->chip.of_gpio_n_cells = 2;
  759.     mcp->chip.of_node = dev->of_node;
  760. #endif
  761.  
  762.     switch (type) {
  763. #ifdef CONFIG_SPI_MASTER
  764.     case MCP_TYPE_S08:
  765.         mcp->ops = &mcp23s08_ops;
  766.         mcp->chip.ngpio = 8;
  767.         mcp->chip.label = "mcp23s08";
  768.         break;
  769.  
  770.     case MCP_TYPE_S17:
  771.         mcp->ops = &mcp23s17_ops;
  772.         mcp->chip.ngpio = 16;
  773.         mcp->chip.label = "mcp23s17";
  774.         break;
  775. #endif /* CONFIG_SPI_MASTER */
  776.  
  777. #if IS_ENABLED(CONFIG_I2C)
  778.     case MCP_TYPE_008:
  779.         mcp->ops = &mcp23008_ops;
  780.         mcp->chip.ngpio = 8;
  781.         mcp->chip.label = "mcp23008";
  782.         break;
  783.  
  784.     case MCP_TYPE_017:
  785.         mcp->ops = &mcp23017_ops;
  786.         mcp->chip.ngpio = 16;
  787.         mcp->chip.label = "mcp23017";
  788.         break;
  789. #endif /* CONFIG_I2C */
  790.  
  791.     default:
  792.         dev_err(dev, "invalid device type (%d)\n", type);
  793.         return -EINVAL;
  794.     }
  795.         LOG_debug("Chip type %s", mcp->chip.label);
  796.  
  797.     mcp->chip.base = base;
  798.     mcp->chip.can_sleep = 1;
  799.     mcp->chip.dev = dev;
  800.     mcp->chip.owner = THIS_MODULE;
  801.  
  802.         spin_lock_init(&mcp->msg_slk);
  803.  
  804.     /* verify MCP_IOCON.SEQOP = 0, so sequential reads work,
  805.      * and MCP_IOCON.HAEN = 1, so we work with all chips.
  806.      */
  807.         LOG_debug("Configure IOCON");
  808.     status = mcp->ops->read(mcp, MCP_IOCON);
  809.     if (status < 0)
  810.         goto fail;
  811.     if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN)) {
  812.         /* mcp23s17 has IOCON twice, make sure they are in sync */
  813.         status &= ~(IOCON_SEQOP | (IOCON_SEQOP << 8));
  814.         status |= IOCON_HAEN | (IOCON_HAEN << 8);
  815.         status &= ~(IOCON_INTPOL | (IOCON_INTPOL << 8));
  816.                 status |= IOCON_ODR | (IOCON_ODR << 8);
  817.  
  818.         status = mcp->ops->write(mcp, MCP_IOCON, status);
  819.         if (status < 0)
  820.             goto fail;
  821.     }
  822.  
  823.     /* configure ~100K pullups */
  824.         LOG_debug("Configure 100k pullups");
  825.     status = mcp->ops->write(mcp, MCP_GPPU, 0x00ff);
  826.     if (status < 0)
  827.         goto fail;
  828.  
  829.  
  830.         /* Setup I/O directions, GPA is input, GPB is output */
  831.         LOG_debug("Configure IODIR");
  832.         status = mcp->ops->write(mcp, MCP_IODIR, 0x00ff);
  833.         if (status < 0)
  834.                 goto fail;
  835.  
  836.     /* disable inverter on input */
  837.         LOG_debug("Disabling IPOL on input");
  838.         status = mcp->ops->write(mcp, MCP_IPOL, 0);
  839.         if (status < 0)
  840.                 goto fail;
  841.  
  842.  
  843.         /* turn off output */
  844.         LOG_debug("Turning output off");
  845.         status = mcp->ops->write(mcp, MCP_GPIO, 0xff00);
  846.         if (status < 0)
  847.                 goto fail;
  848.  
  849.     /* enable irqs */
  850.         LOG_debug("Enabling IRQ");
  851.         status = mcp->ops->write(mcp, MCP_GPINTEN, 0x00ff);
  852.         if (status < 0)
  853.                 goto fail;
  854.  
  855.         /* Update registers cache */
  856.         LOG_debug("Updating registers cache");
  857.     status = mcp->ops->read_regs(mcp, 0, mcp->cache, ARRAY_SIZE(mcp->cache));
  858.     if (status < 0)
  859.         goto fail;
  860.  
  861.         /* adding GPIO chip */
  862.         LOG_debug("Registering gpio chip %d address %d", (~0x40 & addr), addr);
  863.     status = gpiochip_add(&mcp->chip);
  864. fail:
  865.     if (status < 0)
  866.         dev_dbg(dev, "can't setup chip %d, --> %d\n",
  867.             addr, status);
  868.        
  869.         LOG_debug("Returning %d", status);
  870.     return status;
  871. }
  872.  
  873. /*----------------------------------------------------------------------*/
  874.  
  875. #ifdef CONFIG_OF
  876. #ifdef CONFIG_SPI_MASTER
  877. static struct of_device_id mcp23s08_spi_of_match[] = {
  878.     {
  879.         .compatible = "mcp,mcp23s08", .data = (void *) MCP_TYPE_S08,
  880.     },
  881.     {
  882.         .compatible = "mcp,mcp23s17", .data = (void *) MCP_TYPE_S17,
  883.     },
  884.     { },
  885. };
  886. MODULE_DEVICE_TABLE(of, mcp23s08_spi_of_match);
  887. #endif
  888.  
  889. #if IS_ENABLED(CONFIG_I2C)
  890. static struct of_device_id mcp23s08_i2c_of_match[] = {
  891.     {
  892.         .compatible = "mcp,mcp23008", .data = (void *) MCP_TYPE_008,
  893.     },
  894.     {
  895.         .compatible = "mcp,mcp23017", .data = (void *) MCP_TYPE_017,
  896.     },
  897.     { },
  898. };
  899. MODULE_DEVICE_TABLE(of, mcp23s08_i2c_of_match);
  900. #endif
  901. #endif /* CONFIG_OF */
  902.  
  903.  
  904. #if IS_ENABLED(CONFIG_I2C)
  905.  
  906. static int mcp230xx_probe(struct i2c_client *client,
  907.                     const struct i2c_device_id *id)
  908. {
  909.     struct mcp23s08_platform_data *pdata;
  910.     struct mcp23s08 *mcp;
  911.     int status, base, pullups;
  912.     const struct of_device_id *match;
  913.  
  914.     match = of_match_device(of_match_ptr(mcp23s08_i2c_of_match),
  915.                     &client->dev);
  916.     if (match) {
  917.         base = -1;
  918.         pullups = 0;
  919.     } else {
  920.         pdata = client->dev.platform_data;
  921.         if (!pdata || !gpio_is_valid(pdata->base)) {
  922.             dev_dbg(&client->dev,
  923.                     "invalid or missing platform data\n");
  924.             return -EINVAL;
  925.         }
  926.         base = pdata->base;
  927.         pullups = pdata->chip[0].pullups;
  928.     }
  929.  
  930.     mcp = kzalloc(sizeof *mcp, GFP_KERNEL);
  931.     if (!mcp)
  932.         return -ENOMEM;
  933.  
  934.     status = mcp23s08_probe_one(mcp, &client->dev, client, client->addr,
  935.                     id->driver_data, base, pullups);
  936.     if (status)
  937.         goto fail;
  938.  
  939.     i2c_set_clientdata(client, mcp);
  940.  
  941.     return 0;
  942.  
  943. fail:
  944.     kfree(mcp);
  945.  
  946.     return status;
  947. }
  948.  
  949. static int mcp230xx_remove(struct i2c_client *client)
  950. {
  951.     struct mcp23s08 *mcp = i2c_get_clientdata(client);
  952.     int status;
  953.  
  954.     status = gpiochip_remove(&mcp->chip);
  955.     if (status == 0)
  956.         kfree(mcp);
  957.  
  958.     return status;
  959. }
  960.  
  961. static const struct i2c_device_id mcp230xx_id[] = {
  962.     { "mcp23008", MCP_TYPE_008 },
  963.     { "mcp23017", MCP_TYPE_017 },
  964.     { },
  965. };
  966. MODULE_DEVICE_TABLE(i2c, mcp230xx_id);
  967.  
  968. static struct i2c_driver mcp230xx_driver = {
  969.     .driver = {
  970.         .name   = "mcp230xx",
  971.         .owner  = THIS_MODULE,
  972.         .of_match_table = of_match_ptr(mcp23s08_i2c_of_match),
  973.     },
  974.     .probe      = mcp230xx_probe,
  975.     .remove     = mcp230xx_remove,
  976.     .id_table   = mcp230xx_id,
  977. };
  978.  
  979. static int __init mcp23s08_i2c_init(void)
  980. {
  981.     return i2c_add_driver(&mcp230xx_driver);
  982. }
  983.  
  984. static void mcp23s08_i2c_exit(void)
  985. {
  986.     i2c_del_driver(&mcp230xx_driver);
  987. }
  988.  
  989. #else
  990.  
  991. static int __init mcp23s08_i2c_init(void) { return 0; }
  992. static void mcp23s08_i2c_exit(void) { }
  993.  
  994. #endif /* CONFIG_I2C */
  995.  
  996. /*----------------------------------------------------------------------*/
  997.  
  998. #ifdef CONFIG_SPI_MASTER
  999.  
  1000. static int mcp23s08_probe(struct spi_device *spi)
  1001. {
  1002.     struct mcp23s08_platform_data   *pdata;
  1003.     unsigned            addr;
  1004.     unsigned            chips = 0;
  1005.     struct mcp23s08_driver_data *data;
  1006.     int             status, type;
  1007.     unsigned            base = -1,
  1008.                     ngpio = 0,
  1009.                     pullups[ARRAY_SIZE(pdata->chip)];
  1010.     const struct            of_device_id *match;
  1011.     u32             spi_present_mask = 0;
  1012.  
  1013.         LOG_debug("");
  1014.     match = of_match_device(of_match_ptr(mcp23s08_spi_of_match), &spi->dev);
  1015.     if (match) {
  1016.                 LOG_debug("device tree detected");
  1017.         type = (int)match->data;
  1018.         status = of_property_read_u32(spi->dev.of_node,
  1019.                 "mcp,spi-present-mask", &spi_present_mask);
  1020.         if (status) {
  1021.             dev_err(&spi->dev, "DT has no spi-present-mask\n");
  1022.             return -ENODEV;
  1023.         }
  1024.                 LOG_debug("spi-present-mask %x", spi_present_mask);
  1025.         if ((spi_present_mask <= 0) || (spi_present_mask >= 256)) {
  1026.             dev_err(&spi->dev, "invalid spi-present-mask\n");
  1027.             return -ENODEV;
  1028.         }
  1029.  
  1030.         for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) {
  1031.             pullups[addr] = 0;
  1032.             if (spi_present_mask & (1 << addr))
  1033.                 chips++;
  1034.                 }
  1035.     } else {
  1036.                 LOG_debug("no device tree detected");
  1037.         type = spi_get_device_id(spi)->driver_data;
  1038.         pdata = spi->dev.platform_data;
  1039.         if (!pdata || !gpio_is_valid(pdata->base)) {
  1040.             dev_dbg(&spi->dev,
  1041.                     "invalid or missing platform data\n");
  1042.             return -EINVAL;
  1043.         }
  1044.  
  1045.         for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) {
  1046.             if (!pdata->chip[addr].is_present)
  1047.                 continue;
  1048.             chips++;
  1049.             if ((type == MCP_TYPE_S08) && (addr > 3)) {
  1050.                 dev_err(&spi->dev,
  1051.                     "mcp23s08 only supports address 0..3\n");
  1052.                 return -EINVAL;
  1053.             }
  1054.             spi_present_mask |= 1 << addr;
  1055.             pullups[addr] = pdata->chip[addr].pullups;
  1056.         }
  1057.  
  1058.         base = pdata->base;
  1059.     }
  1060.  
  1061.         LOG_debug("%d chips detected", chips);
  1062.         if (!chips)
  1063.                 return -ENODEV;
  1064.  
  1065.         LOG_debug("allocating driver data");
  1066.     data = kzalloc(sizeof *data + chips * sizeof(struct mcp23s08),
  1067.             GFP_KERNEL);
  1068.     if (!data)
  1069.         return -ENOMEM;
  1070.     spi_set_drvdata(spi, data);
  1071.  
  1072.     for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) {
  1073.         if (!(spi_present_mask & (1 << addr)))
  1074.             continue;
  1075.         chips--;
  1076.         data->mcp[addr] = &data->chip[chips];
  1077.         status = mcp23s08_probe_one(data->mcp[addr], &spi->dev, spi,
  1078.                         0x40 | (addr << 1), type, base,
  1079.                         pullups[addr]);
  1080.         if (status < 0)
  1081.             goto fail;
  1082.  
  1083.         if (base != -1)
  1084.             base += (type == MCP_TYPE_S17) ? 16 : 8;
  1085.         ngpio += (type == MCP_TYPE_S17) ? 16 : 8;
  1086.     }
  1087.         /* optimization for CSI digital IO */
  1088.         LOG_debug("Setup CSI optimizations");
  1089.         mcp_global = data->mcp[0];
  1090.         LOG_debug("Allocating page for mcp_circ");
  1091.         mcp_circ.buf = (unsigned char *)get_zeroed_page(GFP_KERNEL); /* alloc circular buffer */
  1092.         if (!mcp_circ.buf)
  1093.                 return -ENOMEM;
  1094.         mcp_circ.head = mcp_circ.tail = 0; /* initialize head & tail */
  1095.         mutex_init(&mcp_circ_cons_lock);
  1096.         /* enfof: optimization for CSI digital IO */
  1097.     data->ngpio = ngpio;
  1098.  
  1099.         LOG_debug("Registering IRQ");
  1100.         status = request_threaded_irq(spi->irq, mcp_hard_irq, mcp_irq, IRQF_TRIGGER_FALLING, "MCP23sXX IRQ", mcp_global);
  1101.         if (status) {
  1102.                 dev_err(&spi->dev, "can't request IRQ");
  1103.                 goto fail;
  1104.         }
  1105.  
  1106.         LOG_debug("Creating sysfs attributes");
  1107.         status = sysfs_create_group(&spi->dev.kobj, &mcp_attr_group);
  1108.         if (status) {
  1109.                 dev_err(&spi->dev, "Can't create sysfs attributes");
  1110.                 goto fail2;
  1111.         }
  1112.  
  1113.         LOG_debug("Returning success");
  1114.     return 0;
  1115.  
  1116. fail2:
  1117.         free_irq(spi->irq, mcp_global);
  1118. fail:
  1119.     for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) {
  1120.         int tmp;
  1121.  
  1122.         if (!data->mcp[addr])
  1123.             continue;
  1124.                 LOG_debug("Removing gpio chip %d", addr);
  1125.         tmp = gpiochip_remove(&data->mcp[addr]->chip);
  1126.         if (tmp < 0)
  1127.             dev_err(&spi->dev, "%s --> %d\n", "remove", tmp);
  1128.     }
  1129.         LOG_debug("Freeing driver data");
  1130.     kfree(data);
  1131.     return status;
  1132. }
  1133.  
  1134. static int mcp23s08_remove(struct spi_device *spi)
  1135. {
  1136.     struct mcp23s08_driver_data *data = spi_get_drvdata(spi);
  1137.     unsigned            addr;
  1138.     int             status = 0;
  1139.  
  1140.         LOG_debug("Disabling IRQ");
  1141.         mcp_global->ops->write(mcp_global, MCP_GPINTEN, 0x0000);
  1142.  
  1143.         LOG_debug("Removing sysfs attributes");
  1144.         sysfs_remove_group(&spi->dev.kobj, &mcp_attr_group);
  1145.  
  1146.         LOG_debug("Freeing IRQ");
  1147.         free_irq(spi->irq, mcp_global);
  1148.  
  1149.         LOG_debug("Freeing circular buffer");
  1150.         free_page((unsigned long)mcp_circ.buf);
  1151.  
  1152.     for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) {
  1153.         int tmp;
  1154.  
  1155.         if (!data->mcp[addr])
  1156.             continue;
  1157.  
  1158.                 LOG_debug("Removing chip %d", addr);
  1159.         tmp = gpiochip_remove(&data->mcp[addr]->chip);
  1160.         if (tmp < 0) {
  1161.             dev_err(&spi->dev, "%s --> %d\n", "remove", tmp);
  1162.             status = tmp;
  1163.         }
  1164.     }
  1165.        
  1166.     if (status == 0) {
  1167.                 LOG_debug("Freeing driver data");
  1168.         kfree(data);
  1169.         }
  1170.     return status;
  1171. }
  1172.  
  1173. static const struct spi_device_id mcp23s08_ids[] = {
  1174.     { "mcp23s08", MCP_TYPE_S08 },
  1175.     { "mcp23s17", MCP_TYPE_S17 },
  1176.     { },
  1177. };
  1178. MODULE_DEVICE_TABLE(spi, mcp23s08_ids);
  1179.  
  1180. static struct spi_driver mcp23s08_driver = {
  1181.     .probe      = mcp23s08_probe,
  1182.     .remove     = mcp23s08_remove,
  1183.     .id_table   = mcp23s08_ids,
  1184.     .driver = {
  1185.         .name   = "mcp23s08",
  1186.         .owner  = THIS_MODULE,
  1187.         .of_match_table = of_match_ptr(mcp23s08_spi_of_match),
  1188.     },
  1189. };
  1190.  
  1191. static int __init mcp23s08_spi_init(void)
  1192. {
  1193.         LOG_debug("Registering spi driver");
  1194.     return spi_register_driver(&mcp23s08_driver);
  1195. }
  1196.  
  1197. static void mcp23s08_spi_exit(void)
  1198. {
  1199.         LOG_debug("Unregistering spi driver");
  1200.     spi_unregister_driver(&mcp23s08_driver);
  1201. }
  1202.  
  1203. #else
  1204.  
  1205. static int __init mcp23s08_spi_init(void) { return 0; }
  1206. static void mcp23s08_spi_exit(void) { }
  1207.  
  1208. #endif /* CONFIG_SPI_MASTER */
  1209.  
  1210. /*----------------------------------------------------------------------*/
  1211.  
  1212. static int __init mcp23s08_init(void)
  1213. {
  1214.     int ret;
  1215.  
  1216.     ret = mcp23s08_spi_init();
  1217.     if (ret)
  1218.         goto spi_fail;
  1219.  
  1220.     ret = mcp23s08_i2c_init();
  1221.     if (ret)
  1222.         goto i2c_fail;
  1223.  
  1224.     return 0;
  1225.  
  1226.  i2c_fail:
  1227.     mcp23s08_spi_exit();
  1228.  spi_fail:
  1229.     return ret;
  1230. }
  1231. /* register after spi/i2c postcore initcall and before
  1232.  * subsys initcalls that may rely on these GPIOs
  1233.  */
  1234. subsys_initcall(mcp23s08_init);
  1235.  
  1236. static void __exit mcp23s08_exit(void)
  1237. {
  1238.     mcp23s08_spi_exit();
  1239.     mcp23s08_i2c_exit();
  1240. }
  1241. module_exit(mcp23s08_exit);
  1242.  
  1243. MODULE_LICENSE("GPL");
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement