Merge branch 'for-linus/i2c/2636-rc8' of git://git.fluff.org/bjdooks/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 18 Oct 2010 20:05:10 +0000 (13:05 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 18 Oct 2010 20:05:10 +0000 (13:05 -0700)
* 'for-linus/i2c/2636-rc8' of git://git.fluff.org/bjdooks/linux:
  i2c-imx: do not allow interruptions when waiting for I2C to complete
  i2c-davinci: Fix TX setup for more SoCs

drivers/i2c/busses/i2c-davinci.c
drivers/i2c/busses/i2c-imx.c

index b8feac5..5795c83 100644 (file)
@@ -331,21 +331,16 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
        INIT_COMPLETION(dev->cmd_complete);
        dev->cmd_err = 0;
 
-       /* Take I2C out of reset, configure it as master and set the
-        * start bit */
-       flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST | DAVINCI_I2C_MDR_STT;
+       /* Take I2C out of reset and configure it as master */
+       flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST;
 
        /* if the slave address is ten bit address, enable XA bit */
        if (msg->flags & I2C_M_TEN)
                flag |= DAVINCI_I2C_MDR_XA;
        if (!(msg->flags & I2C_M_RD))
                flag |= DAVINCI_I2C_MDR_TRX;
-       if (stop)
-               flag |= DAVINCI_I2C_MDR_STP;
-       if (msg->len == 0) {
+       if (msg->len == 0)
                flag |= DAVINCI_I2C_MDR_RM;
-               flag &= ~DAVINCI_I2C_MDR_STP;
-       }
 
        /* Enable receive or transmit interrupts */
        w = davinci_i2c_read_reg(dev, DAVINCI_I2C_IMR_REG);
@@ -357,18 +352,29 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
 
        dev->terminate = 0;
 
+       /*
+        * Write mode register first as needed for correct behaviour
+        * on OMAP-L138, but don't set STT yet to avoid a race with XRDY
+        * occuring before we have loaded DXR
+        */
+       davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
+
        /*
         * First byte should be set here, not after interrupt,
         * because transmit-data-ready interrupt can come before
         * NACK-interrupt during sending of previous message and
         * ICDXR may have wrong data
+        * It also saves us one interrupt, slightly faster
         */
        if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) {
                davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, *dev->buf++);
                dev->buf_len--;
        }
 
-       /* write the data into mode register; start transmitting */
+       /* Set STT to begin transmit now DXR is loaded */
+       flag |= DAVINCI_I2C_MDR_STT;
+       if (stop && msg->len != 0)
+               flag |= DAVINCI_I2C_MDR_STP;
        davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
 
        r = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
index d1ff940..4c2a62b 100644 (file)
@@ -159,15 +159,9 @@ static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy)
 
 static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx)
 {
-       int result;
-
-       result = wait_event_interruptible_timeout(i2c_imx->queue,
-               i2c_imx->i2csr & I2SR_IIF, HZ / 10);
+       wait_event_timeout(i2c_imx->queue, i2c_imx->i2csr & I2SR_IIF, HZ / 10);
 
-       if (unlikely(result < 0)) {
-               dev_dbg(&i2c_imx->adapter.dev, "<%s> result < 0\n", __func__);
-               return result;
-       } else if (unlikely(!(i2c_imx->i2csr & I2SR_IIF))) {
+       if (unlikely(!(i2c_imx->i2csr & I2SR_IIF))) {
                dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__);
                return -ETIMEDOUT;
        }
@@ -295,7 +289,7 @@ static irqreturn_t i2c_imx_isr(int irq, void *dev_id)
                i2c_imx->i2csr = temp;
                temp &= ~I2SR_IIF;
                writeb(temp, i2c_imx->base + IMX_I2C_I2SR);
-               wake_up_interruptible(&i2c_imx->queue);
+               wake_up(&i2c_imx->queue);
                return IRQ_HANDLED;
        }