include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6] / drivers / i2c / busses / i2c-designware.c
index f184d82..b664ed8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Synopsys Designware I2C adapter driver (master only).
+ * Synopsys DesignWare I2C adapter driver (master only).
  *
  * Based on the TI DAVINCI I2C adapter driver.
  *
@@ -36,6 +36,7 @@
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/slab.h>
 
 /*
  * Registers offset
 #define ABRT_SBYTE_ACKDET      7
 #define ABRT_SBYTE_NORSTRT     9
 #define ABRT_10B_RD_NORSTRT    10
-#define ARB_MASTER_DIS         11
+#define ABRT_MASTER_DIS                11
 #define ARB_LOST               12
 
+#define DW_IC_TX_ABRT_7B_ADDR_NOACK    (1UL << ABRT_7B_ADDR_NOACK)
+#define DW_IC_TX_ABRT_10ADDR1_NOACK    (1UL << ABRT_10ADDR1_NOACK)
+#define DW_IC_TX_ABRT_10ADDR2_NOACK    (1UL << ABRT_10ADDR2_NOACK)
+#define DW_IC_TX_ABRT_TXDATA_NOACK     (1UL << ABRT_TXDATA_NOACK)
+#define DW_IC_TX_ABRT_GCALL_NOACK      (1UL << ABRT_GCALL_NOACK)
+#define DW_IC_TX_ABRT_GCALL_READ       (1UL << ABRT_GCALL_READ)
+#define DW_IC_TX_ABRT_SBYTE_ACKDET     (1UL << ABRT_SBYTE_ACKDET)
+#define DW_IC_TX_ABRT_SBYTE_NORSTRT    (1UL << ABRT_SBYTE_NORSTRT)
+#define DW_IC_TX_ABRT_10B_RD_NORSTRT   (1UL << ABRT_10B_RD_NORSTRT)
+#define DW_IC_TX_ABRT_MASTER_DIS       (1UL << ABRT_MASTER_DIS)
+#define DW_IC_TX_ARB_LOST              (1UL << ARB_LOST)
+
+#define DW_IC_TX_ABRT_NOACK            (DW_IC_TX_ABRT_7B_ADDR_NOACK | \
+                                        DW_IC_TX_ABRT_10ADDR1_NOACK | \
+                                        DW_IC_TX_ABRT_10ADDR2_NOACK | \
+                                        DW_IC_TX_ABRT_TXDATA_NOACK | \
+                                        DW_IC_TX_ABRT_GCALL_NOACK)
+
 static char *abort_sources[] = {
-       [ABRT_7B_ADDR_NOACK]    =
+       [ABRT_7B_ADDR_NOACK] =
                "slave address not acknowledged (7bit mode)",
-       [ABRT_10ADDR1_NOACK]    =
+       [ABRT_10ADDR1_NOACK] =
                "first address byte not acknowledged (10bit mode)",
-       [ABRT_10ADDR2_NOACK]    =
+       [ABRT_10ADDR2_NOACK] =
                "second address byte not acknowledged (10bit mode)",
-       [ABRT_TXDATA_NOACK]             =
+       [ABRT_TXDATA_NOACK] =
                "data not acknowledged",
-       [ABRT_GCALL_NOACK]              =
+       [ABRT_GCALL_NOACK] =
                "no acknowledgement for a general call",
-       [ABRT_GCALL_READ]               =
+       [ABRT_GCALL_READ] =
                "read after general call",
-       [ABRT_SBYTE_ACKDET]             =
+       [ABRT_SBYTE_ACKDET] =
                "start byte acknowledged",
-       [ABRT_SBYTE_NORSTRT]    =
+       [ABRT_SBYTE_NORSTRT] =
                "trying to send start byte when restart is disabled",
-       [ABRT_10B_RD_NORSTRT]   =
+       [ABRT_10B_RD_NORSTRT] =
                "trying to read when restart is disabled (10bit mode)",
-       [ARB_MASTER_DIS]                =
+       [ABRT_MASTER_DIS] =
                "trying to use disabled adapter",
-       [ARB_LOST]                      =
+       [ARB_LOST] =
                "lost arbitration",
 };
 
@@ -376,18 +395,23 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
        intr_mask = DW_IC_INTR_DEFAULT_MASK;
 
        for (; dev->msg_write_idx < dev->msgs_num; dev->msg_write_idx++) {
-               /* if target address has changed, we need to
+               /*
+                * if target address has changed, we need to
                 * reprogram the target address in the i2c
                 * adapter when we are done with this transfer
                 */
-               if (msgs[dev->msg_write_idx].addr != addr)
-                       return;
+               if (msgs[dev->msg_write_idx].addr != addr) {
+                       dev_err(dev->dev,
+                               "%s: invalid target address\n", __func__);
+                       dev->msg_err = -EINVAL;
+                       break;
+               }
 
                if (msgs[dev->msg_write_idx].len == 0) {
                        dev_err(dev->dev,
                                "%s: invalid message length\n", __func__);
                        dev->msg_err = -EINVAL;
-                       return;
+                       break;
                }
 
                if (!(dev->status & STATUS_WRITE_IN_PROGRESS)) {
@@ -415,12 +439,20 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
                        /* more bytes to be written */
                        dev->status |= STATUS_WRITE_IN_PROGRESS;
                        break;
-               } else {
+               } else
                        dev->status &= ~STATUS_WRITE_IN_PROGRESS;
-                       intr_mask &= ~DW_IC_INTR_TX_EMPTY;
-               }
        }
 
+       /*
+        * If i2c_msg index search is completed, we don't need TX_EMPTY
+        * interrupt any more.
+        */
+       if (dev->msg_write_idx == dev->msgs_num)
+               intr_mask &= ~DW_IC_INTR_TX_EMPTY;
+
+       if (dev->msg_err)
+               intr_mask = 0;
+
        writel(intr_mask, dev->base + DW_IC_INTR_MASK);
 }
 
@@ -460,6 +492,29 @@ i2c_dw_read(struct dw_i2c_dev *dev)
        }
 }
 
+static int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
+{
+       unsigned long abort_source = dev->abort_source;
+       int i;
+
+       if (abort_source & DW_IC_TX_ABRT_NOACK) {
+               for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources))
+                       dev_dbg(dev->dev,
+                               "%s: %s\n", __func__, abort_sources[i]);
+               return -EREMOTEIO;
+       }
+
+       for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources))
+               dev_err(dev->dev, "%s: %s\n", __func__, abort_sources[i]);
+
+       if (abort_source & DW_IC_TX_ARB_LOST)
+               return -EAGAIN;
+       else if (abort_source & DW_IC_TX_ABRT_GCALL_READ)
+               return -EINVAL; /* wrong msgs[] data */
+       else
+               return -EIO;
+}
+
 /*
  * Prepare controller for a transaction and call i2c_dw_xfer_msg
  */
@@ -481,6 +536,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
        dev->msg_read_idx = 0;
        dev->msg_err = 0;
        dev->status = STATUS_IDLE;
+       dev->abort_source = 0;
 
        ret = i2c_dw_wait_bus_not_busy(dev);
        if (ret < 0)
@@ -514,12 +570,8 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
 
        /* We have an error */
        if (dev->cmd_err == DW_IC_ERR_TX_ABRT) {
-               unsigned long abort_source = dev->abort_source;
-               int i;
-
-               for_each_bit(i, &abort_source, ARRAY_SIZE(abort_sources)) {
-                   dev_err(dev->dev, "%s: %s\n", __func__, abort_sources[i]);
-               }
+               ret = i2c_dw_handle_tx_abort(dev);
+               goto done;
        }
        ret = -EIO;
 
@@ -609,6 +661,13 @@ static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
        if (stat & DW_IC_INTR_TX_ABRT) {
                dev->cmd_err |= DW_IC_ERR_TX_ABRT;
                dev->status = STATUS_IDLE;
+
+               /*
+                * Anytime TX_ABRT is set, the contents of the tx/rx
+                * buffers are flushed.  Make sure to skip them.
+                */
+               writel(0, dev->base + DW_IC_INTR_MASK);
+               goto tx_aborted;
        }
 
        if (stat & DW_IC_INTR_RX_FULL)
@@ -623,7 +682,8 @@ static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
         * the current transmit status.
         */
 
-       if (stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET))
+tx_aborted:
+       if ((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) || dev->msg_err)
                complete(&dev->cmd_complete);
 
        return IRQ_HANDLED;