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 | ||
