Commit c5b4afec authored by Jon Povey's avatar Jon Povey Committed by Ben Dooks

i2c-davinci: Fix TX setup for more SoCs

This patch is an improvement to 4bba0fd8
which got to mainline a little early.

Sudhakar Rajashekhara explains that at least OMAP-L138 requires MDR mode
settings before DXR for correct behaviour, so load MDR first with
STT cleared and later load again with STT set.

Tested on DM355 connected to Techwell TW2836 and Wolfson WM8985
Signed-off-by: default avatarJon Povey <jon.povey@racelogic.co.uk>
Acked-by: default avatarTroy Kisky <troy.kisky@boundarydevices.com>
Tested-by: default avatarSudhakar Rajashekhara <sudhakar.raj@ti.com>
Acked-by: default avatarKevin Hilman <khilman@deeprootsystems.com>
Signed-off-by: default avatarBen Dooks <ben-linux@fluff.org>
parent 85a33188
...@@ -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,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment