diff options
-rw-r--r-- | drivers/i2c/busses/i2c-davinci.c | 31 |
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 | ||
373 | static u32 i2c_davinci_func(struct i2c_adapter *adap) | 388 | static 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 | ||
378 | static void terminate_read(struct davinci_i2c_dev *dev) | 393 | static 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 | ||