提交 f68c834b 编写于 作者: L Linus Torvalds

Merge branch 'for-linus/i2c/2636-rc8' of git://git.fluff.org/bjdooks/linux

* '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
...@@ -331,21 +331,16 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) ...@@ -331,21 +331,16 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
INIT_COMPLETION(dev->cmd_complete); INIT_COMPLETION(dev->cmd_complete);
dev->cmd_err = 0; dev->cmd_err = 0;
/* Take I2C out of reset, configure it as master and set the /* Take I2C out of reset and configure it as master */
* start bit */ flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST;
flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST | DAVINCI_I2C_MDR_STT;
/* if the slave address is ten bit address, enable XA bit */ /* if the slave address is ten bit address, enable XA bit */
if (msg->flags & I2C_M_TEN) if (msg->flags & I2C_M_TEN)
flag |= DAVINCI_I2C_MDR_XA; flag |= DAVINCI_I2C_MDR_XA;
if (!(msg->flags & I2C_M_RD)) if (!(msg->flags & I2C_M_RD))
flag |= DAVINCI_I2C_MDR_TRX; flag |= DAVINCI_I2C_MDR_TRX;
if (stop) if (msg->len == 0)
flag |= DAVINCI_I2C_MDR_STP;
if (msg->len == 0) {
flag |= DAVINCI_I2C_MDR_RM; flag |= DAVINCI_I2C_MDR_RM;
flag &= ~DAVINCI_I2C_MDR_STP;
}
/* Enable receive or transmit interrupts */ /* Enable receive or transmit interrupts */
w = davinci_i2c_read_reg(dev, DAVINCI_I2C_IMR_REG); 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) ...@@ -357,18 +352,29 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
dev->terminate = 0; 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, * First byte should be set here, not after interrupt,
* because transmit-data-ready interrupt can come before * because transmit-data-ready interrupt can come before
* NACK-interrupt during sending of previous message and * NACK-interrupt during sending of previous message and
* ICDXR may have wrong data * ICDXR may have wrong data
* It also saves us one interrupt, slightly faster
*/ */
if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) { if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) {
davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, *dev->buf++); davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, *dev->buf++);
dev->buf_len--; 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); davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
r = wait_for_completion_interruptible_timeout(&dev->cmd_complete, r = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
......
...@@ -159,15 +159,9 @@ static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy) ...@@ -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) static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx)
{ {
int result; wait_event_timeout(i2c_imx->queue, i2c_imx->i2csr & I2SR_IIF, HZ / 10);
result = wait_event_interruptible_timeout(i2c_imx->queue,
i2c_imx->i2csr & I2SR_IIF, HZ / 10);
if (unlikely(result < 0)) { if (unlikely(!(i2c_imx->i2csr & I2SR_IIF))) {
dev_dbg(&i2c_imx->adapter.dev, "<%s> result < 0\n", __func__);
return result;
} else if (unlikely(!(i2c_imx->i2csr & I2SR_IIF))) {
dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__); dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__);
return -ETIMEDOUT; return -ETIMEDOUT;
} }
...@@ -295,7 +289,7 @@ static irqreturn_t i2c_imx_isr(int irq, void *dev_id) ...@@ -295,7 +289,7 @@ static irqreturn_t i2c_imx_isr(int irq, void *dev_id)
i2c_imx->i2csr = temp; i2c_imx->i2csr = temp;
temp &= ~I2SR_IIF; temp &= ~I2SR_IIF;
writeb(temp, i2c_imx->base + IMX_I2C_I2SR); writeb(temp, i2c_imx->base + IMX_I2C_I2SR);
wake_up_interruptible(&i2c_imx->queue); wake_up(&i2c_imx->queue);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册