aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses
diff options
context:
space:
mode:
authorDirk Behme <dirk.behme@googlemail.com>2008-03-28 01:16:12 -0400
committerKevin Hilman <khilman@deeprootsystems.com>2010-08-05 12:38:32 -0400
commitc6c7c729a22bfeb8e63eafce48dbaeea20e68703 (patch)
treed1fd3ea71d56b78ed4495d228b2772950a802a3b /drivers/i2c/busses
parent9fe6206f400646a2322096b56c59891d530e8d51 (diff)
i2c: davinci: Fix smbus Oops with AIC33 usage
This fixes Oops at kernel startup while "scanning" for TLV320AIC23IDx addresses. Additional fix from Sudhakar Rajashekhara: I think 'first byte set' should come after the write because an I2C transaction is being carried out before configuring the I2C mode register (which has bits to configure Master, Start condition etc), which causes undefined behavior. Signed-off-by: Sudhakar Rajashekhara <sudhakar.raj@ti.com> Signed-off-by: Alexander Vasiliev <alexvasiljev@gmail.com> Signed-off-by: Brad Griffis <bgriffis@ti.com> Signed-off-by: Dirk Behme <dirk.behme@gmail.com> Acked-by: Kevin Hilman <khilman@deeprootsystems.com>
Diffstat (limited to 'drivers/i2c/busses')
-rw-r--r--drivers/i2c/busses/i2c-davinci.c31
1 files changed, 27 insertions, 4 deletions
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index 4523364e6722..43913c1d50f5 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -113,6 +113,7 @@ struct davinci_i2c_dev {
113 u8 *buf; 113 u8 *buf;
114 size_t buf_len; 114 size_t buf_len;
115 int irq; 115 int irq;
116 int stop;
116 u8 terminate; 117 u8 terminate;
117 struct i2c_adapter adapter; 118 struct i2c_adapter adapter;
118}; 119};
@@ -250,9 +251,6 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
250 u16 w; 251 u16 w;
251 int r; 252 int r;
252 253
253 if (msg->len == 0)
254 return -EINVAL;
255
256 if (!pdata) 254 if (!pdata)
257 pdata = &davinci_i2c_platform_data_default; 255 pdata = &davinci_i2c_platform_data_default;
258 /* Introduce a delay, required for some boards (e.g Davinci EVM) */ 256 /* Introduce a delay, required for some boards (e.g Davinci EVM) */
@@ -264,6 +262,7 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
264 262
265 dev->buf = msg->buf; 263 dev->buf = msg->buf;
266 dev->buf_len = msg->len; 264 dev->buf_len = msg->len;
265 dev->stop = stop;
267 266
268 davinci_i2c_write_reg(dev, DAVINCI_I2C_CNT_REG, dev->buf_len); 267 davinci_i2c_write_reg(dev, DAVINCI_I2C_CNT_REG, dev->buf_len);
269 268
@@ -281,6 +280,10 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
281 flag |= DAVINCI_I2C_MDR_TRX; 280 flag |= DAVINCI_I2C_MDR_TRX;
282 if (stop) 281 if (stop)
283 flag |= DAVINCI_I2C_MDR_STP; 282 flag |= DAVINCI_I2C_MDR_STP;
283 if (msg->len == 0) {
284 flag |= DAVINCI_I2C_MDR_RM;
285 flag &= ~DAVINCI_I2C_MDR_STP;
286 }
284 287
285 /* Enable receive or transmit interrupts */ 288 /* Enable receive or transmit interrupts */
286 w = davinci_i2c_read_reg(dev, DAVINCI_I2C_IMR_REG); 289 w = davinci_i2c_read_reg(dev, DAVINCI_I2C_IMR_REG);
@@ -291,9 +294,21 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
291 davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, w); 294 davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, w);
292 295
293 dev->terminate = 0; 296 dev->terminate = 0;
297
294 /* write the data into mode register */ 298 /* write the data into mode register */
295 davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); 299 davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
296 300
301 /*
302 * First byte should be set here, not after interrupt,
303 * because transmit-data-ready interrupt can come before
304 * NACK-interrupt during sending of previous message and
305 * ICDXR may have wrong data
306 */
307 if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) {
308 davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, *dev->buf++);
309 dev->buf_len--;
310 }
311
297 r = wait_for_completion_interruptible_timeout(&dev->cmd_complete, 312 r = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
298 dev->adapter.timeout); 313 dev->adapter.timeout);
299 if (r == 0) { 314 if (r == 0) {
@@ -372,7 +387,7 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
372 387
373static u32 i2c_davinci_func(struct i2c_adapter *adap) 388static u32 i2c_davinci_func(struct i2c_adapter *adap)
374{ 389{
375 return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK); 390 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
376} 391}
377 392
378static void terminate_read(struct davinci_i2c_dev *dev) 393static void terminate_read(struct davinci_i2c_dev *dev)
@@ -431,6 +446,14 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)
431 case DAVINCI_I2C_IVR_ARDY: 446 case DAVINCI_I2C_IVR_ARDY:
432 davinci_i2c_write_reg(dev, 447 davinci_i2c_write_reg(dev,
433 DAVINCI_I2C_STR_REG, DAVINCI_I2C_STR_ARDY); 448 DAVINCI_I2C_STR_REG, DAVINCI_I2C_STR_ARDY);
449 if (((dev->buf_len == 0) && (dev->stop != 0)) ||
450 (dev->cmd_err & DAVINCI_I2C_STR_NACK)) {
451 w = davinci_i2c_read_reg(dev,
452 DAVINCI_I2C_MDR_REG);
453 w |= DAVINCI_I2C_MDR_STP;
454 davinci_i2c_write_reg(dev,
455 DAVINCI_I2C_MDR_REG, w);
456 }
434 complete(&dev->cmd_complete); 457 complete(&dev->cmd_complete);
435 break; 458 break;
436 459