aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Bazhenov <dmitry.bazhenov@auriga.com>2016-09-21 02:51:03 -0400
committerWolfram Sang <wsa@the-dreams.de>2016-09-21 17:04:35 -0400
commitde919ff6a0060510b099405d9b8f9413aba9ae14 (patch)
tree078568adaac77f0323303276709bdce2c7291653
parente7051556b63dac163a82db6e6f324196c0c81e5b (diff)
i2c: octeon: Avoid sending STOP during recovery
Due to a bug in the ThunderX I2C hardware sending STOP during a recovery attempt could lock up the hardware. To work around this problem do not send STOP at the beginning of the recovery but use the override registers to bring the TWSI including the high-level controller out of the bad state. Signed-off-by: Dmitry Bazhenov <dmitry.bazhenov@auriga.com> Signed-off-by: Jan Glauber <jglauber@cavium.com> [Changed commit message] Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
-rw-r--r--drivers/i2c/busses/i2c-octeon-core.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/drivers/i2c/busses/i2c-octeon-core.c b/drivers/i2c/busses/i2c-octeon-core.c
index f322242cdbf8..7d4df8383b38 100644
--- a/drivers/i2c/busses/i2c-octeon-core.c
+++ b/drivers/i2c/busses/i2c-octeon-core.c
@@ -783,13 +783,14 @@ static void octeon_i2c_prepare_recovery(struct i2c_adapter *adap)
783{ 783{
784 struct octeon_i2c *i2c = i2c_get_adapdata(adap); 784 struct octeon_i2c *i2c = i2c_get_adapdata(adap);
785 785
786 octeon_i2c_hlc_disable(i2c);
787
786 /* 788 /*
787 * The stop resets the state machine, does not _transmit_ STOP unless 789 * Bring control register to a good state regardless
788 * engine was active. 790 * of HLC state.
789 */ 791 */
790 octeon_i2c_stop(i2c); 792 octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB);
791 793
792 octeon_i2c_hlc_disable(i2c);
793 octeon_i2c_write_int(i2c, 0); 794 octeon_i2c_write_int(i2c, 0);
794} 795}
795 796
@@ -797,6 +798,15 @@ static void octeon_i2c_unprepare_recovery(struct i2c_adapter *adap)
797{ 798{
798 struct octeon_i2c *i2c = i2c_get_adapdata(adap); 799 struct octeon_i2c *i2c = i2c_get_adapdata(adap);
799 800
801 /*
802 * Generate STOP to finish the unfinished transaction.
803 * Can't generate STOP via the TWSI CTL register
804 * since it could bring the TWSI controller into an inoperable state.
805 */
806 octeon_i2c_write_int(i2c, TWSI_INT_SDA_OVR | TWSI_INT_SCL_OVR);
807 udelay(5);
808 octeon_i2c_write_int(i2c, TWSI_INT_SDA_OVR);
809 udelay(5);
800 octeon_i2c_write_int(i2c, 0); 810 octeon_i2c_write_int(i2c, 0);
801} 811}
802 812