diff options
author | Jaedon Shin <jaedon.shin@gmail.com> | 2017-03-02 20:55:03 -0500 |
---|---|---|
committer | Wolfram Sang <wsa@the-dreams.de> | 2017-03-08 12:00:49 -0500 |
commit | 2de3ec4f1d4ba6ee380478055104eb918bd50cce (patch) | |
tree | 591c46dc7de5b2a23ef5124fb10590090e5fdbf9 | |
parent | 02dbfa5e5583523035f05636c614a0eca77f1aab (diff) |
i2c: brcmstb: Fix START and STOP conditions
The BSC data buffers to send and receive data are each of size 32 bytes
or 8 bytes 'xfersz' depending on SoC. The problem observed for all the
combined message transfer was if length of data transfer was a multiple
of 'xfersz' a repeated START was being transmitted by BSC driver. Fixed
this by appropriately setting START/STOP conditions for such transfers.
Fixes: dd1aa2524bc5 ("i2c: brcmstb: Add Broadcom settop SoC i2c controller driver")
Signed-off-by: Jaedon Shin <jaedon.shin@gmail.com>
Acked-by: Kamal Dasu <kdasu.kdev@gmail.com>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
-rw-r--r-- | drivers/i2c/busses/i2c-brcmstb.c | 27 |
1 files changed, 21 insertions, 6 deletions
diff --git a/drivers/i2c/busses/i2c-brcmstb.c b/drivers/i2c/busses/i2c-brcmstb.c index 0652281662a8..78792b4d6437 100644 --- a/drivers/i2c/busses/i2c-brcmstb.c +++ b/drivers/i2c/busses/i2c-brcmstb.c | |||
@@ -465,6 +465,7 @@ static int brcmstb_i2c_xfer(struct i2c_adapter *adapter, | |||
465 | u8 *tmp_buf; | 465 | u8 *tmp_buf; |
466 | int len = 0; | 466 | int len = 0; |
467 | int xfersz = brcmstb_i2c_get_xfersz(dev); | 467 | int xfersz = brcmstb_i2c_get_xfersz(dev); |
468 | u32 cond, cond_per_msg; | ||
468 | 469 | ||
469 | if (dev->is_suspended) | 470 | if (dev->is_suspended) |
470 | return -EBUSY; | 471 | return -EBUSY; |
@@ -481,10 +482,11 @@ static int brcmstb_i2c_xfer(struct i2c_adapter *adapter, | |||
481 | pmsg->buf ? pmsg->buf[0] : '0', pmsg->len); | 482 | pmsg->buf ? pmsg->buf[0] : '0', pmsg->len); |
482 | 483 | ||
483 | if (i < (num - 1) && (msgs[i + 1].flags & I2C_M_NOSTART)) | 484 | if (i < (num - 1) && (msgs[i + 1].flags & I2C_M_NOSTART)) |
484 | brcmstb_set_i2c_start_stop(dev, ~(COND_START_STOP)); | 485 | cond = ~COND_START_STOP; |
485 | else | 486 | else |
486 | brcmstb_set_i2c_start_stop(dev, | 487 | cond = COND_RESTART | COND_NOSTOP; |
487 | COND_RESTART | COND_NOSTOP); | 488 | |
489 | brcmstb_set_i2c_start_stop(dev, cond); | ||
488 | 490 | ||
489 | /* Send slave address */ | 491 | /* Send slave address */ |
490 | if (!(pmsg->flags & I2C_M_NOSTART)) { | 492 | if (!(pmsg->flags & I2C_M_NOSTART)) { |
@@ -497,13 +499,24 @@ static int brcmstb_i2c_xfer(struct i2c_adapter *adapter, | |||
497 | } | 499 | } |
498 | } | 500 | } |
499 | 501 | ||
502 | cond_per_msg = cond; | ||
503 | |||
500 | /* Perform data transfer */ | 504 | /* Perform data transfer */ |
501 | while (len) { | 505 | while (len) { |
502 | bytes_to_xfer = min(len, xfersz); | 506 | bytes_to_xfer = min(len, xfersz); |
503 | 507 | ||
504 | if (len <= xfersz && i == (num - 1)) | 508 | if (len <= xfersz) { |
505 | brcmstb_set_i2c_start_stop(dev, | 509 | if (i == (num - 1)) |
506 | ~(COND_START_STOP)); | 510 | cond_per_msg = cond_per_msg & |
511 | ~(COND_RESTART | COND_NOSTOP); | ||
512 | else | ||
513 | cond_per_msg = cond; | ||
514 | } else { | ||
515 | cond_per_msg = (cond_per_msg & ~COND_RESTART) | | ||
516 | COND_NOSTOP; | ||
517 | } | ||
518 | |||
519 | brcmstb_set_i2c_start_stop(dev, cond_per_msg); | ||
507 | 520 | ||
508 | rc = brcmstb_i2c_xfer_bsc_data(dev, tmp_buf, | 521 | rc = brcmstb_i2c_xfer_bsc_data(dev, tmp_buf, |
509 | bytes_to_xfer, pmsg); | 522 | bytes_to_xfer, pmsg); |
@@ -512,6 +525,8 @@ static int brcmstb_i2c_xfer(struct i2c_adapter *adapter, | |||
512 | 525 | ||
513 | len -= bytes_to_xfer; | 526 | len -= bytes_to_xfer; |
514 | tmp_buf += bytes_to_xfer; | 527 | tmp_buf += bytes_to_xfer; |
528 | |||
529 | cond_per_msg = COND_NOSTART | COND_NOSTOP; | ||
515 | } | 530 | } |
516 | } | 531 | } |
517 | 532 | ||