Skip to content

Commit c5b4afe

Browse files
Jon PoveyBen Dooks
authored andcommitted
i2c-davinci: Fix TX setup for more SoCs
This patch is an improvement to 4bba0fd 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: Jon Povey <jon.povey@racelogic.co.uk> Acked-by: Troy Kisky <troy.kisky@boundarydevices.com> Tested-by: Sudhakar Rajashekhara <sudhakar.raj@ti.com> Acked-by: Kevin Hilman <khilman@deeprootsystems.com> Signed-off-by: Ben Dooks <ben-linux@fluff.org>
1 parent 85a3318 commit c5b4afe

File tree

1 file changed

+15
-9
lines changed

1 file changed

+15
-9
lines changed

drivers/i2c/busses/i2c-davinci.c

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -331,21 +331,16 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
331331
INIT_COMPLETION(dev->cmd_complete);
332332
dev->cmd_err = 0;
333333

334-
/* Take I2C out of reset, configure it as master and set the
335-
* start bit */
336-
flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST | DAVINCI_I2C_MDR_STT;
334+
/* Take I2C out of reset and configure it as master */
335+
flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST;
337336

338337
/* if the slave address is ten bit address, enable XA bit */
339338
if (msg->flags & I2C_M_TEN)
340339
flag |= DAVINCI_I2C_MDR_XA;
341340
if (!(msg->flags & I2C_M_RD))
342341
flag |= DAVINCI_I2C_MDR_TRX;
343-
if (stop)
344-
flag |= DAVINCI_I2C_MDR_STP;
345-
if (msg->len == 0) {
342+
if (msg->len == 0)
346343
flag |= DAVINCI_I2C_MDR_RM;
347-
flag &= ~DAVINCI_I2C_MDR_STP;
348-
}
349344

350345
/* Enable receive or transmit interrupts */
351346
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)
357352

358353
dev->terminate = 0;
359354

355+
/*
356+
* Write mode register first as needed for correct behaviour
357+
* on OMAP-L138, but don't set STT yet to avoid a race with XRDY
358+
* occuring before we have loaded DXR
359+
*/
360+
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
361+
360362
/*
361363
* First byte should be set here, not after interrupt,
362364
* because transmit-data-ready interrupt can come before
363365
* NACK-interrupt during sending of previous message and
364366
* ICDXR may have wrong data
367+
* It also saves us one interrupt, slightly faster
365368
*/
366369
if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) {
367370
davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, *dev->buf++);
368371
dev->buf_len--;
369372
}
370373

371-
/* write the data into mode register; start transmitting */
374+
/* Set STT to begin transmit now DXR is loaded */
375+
flag |= DAVINCI_I2C_MDR_STT;
376+
if (stop && msg->len != 0)
377+
flag |= DAVINCI_I2C_MDR_STP;
372378
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
373379

374380
r = wait_for_completion_interruptible_timeout(&dev->cmd_complete,

0 commit comments

Comments
 (0)