aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJarkko Nikula <jarkko.nikula@linux.intel.com>2016-11-25 10:22:27 -0500
committerWolfram Sang <wsa@the-dreams.de>2016-11-25 17:23:25 -0500
commit89119f08354b628548118cacd686a7700372ad19 (patch)
tree5c7e9ad9a00f412ccda1bd5976a8658f092f4316
parent4d6d5f1d08d2138dc43b28966eb6200e3db2e623 (diff)
Revert "i2c: designware: do not disable adapter after transfer"
This reverts commit 0317e6c0f1dc1ba86b8d9dccc010c5e77b8355fa. Srinivas reported recently touchscreen and touchpad stopped working in Haswell based machine in Linux 4.9-rc series with timeout errors from i2c_designware: [ 16.508013] i2c_designware INT33C3:00: controller timed out [ 16.508302] i2c_hid i2c-MSFT0001:02: failed to change power setting. [ 17.532016] i2c_designware INT33C3:00: controller timed out [ 18.556022] i2c_designware INT33C3:00: controller timed out [ 18.556315] i2c_hid i2c-ATML1000:00: failed to retrieve report from device. I managed to reproduce similar errors on another Haswell based machine where touchscreen initialization fails maybe in every 1/5 - 1/2 boots. Since root cause for these errors is not clear yet and debugging is ongoing it's better to revert this commit as we are near to release. Reported-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Signed-off-by: Jarkko Nikula <jarkko.nikula@linux.intel.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
-rw-r--r--drivers/i2c/busses/i2c-designware-core.c55
1 files changed, 18 insertions, 37 deletions
diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c
index c53058d6139c..b403fa5ecf49 100644
--- a/drivers/i2c/busses/i2c-designware-core.c
+++ b/drivers/i2c/busses/i2c-designware-core.c
@@ -91,9 +91,7 @@
91 DW_IC_INTR_TX_ABRT | \ 91 DW_IC_INTR_TX_ABRT | \
92 DW_IC_INTR_STOP_DET) 92 DW_IC_INTR_STOP_DET)
93 93
94#define DW_IC_STATUS_ACTIVITY 0x1 94#define DW_IC_STATUS_ACTIVITY 0x1
95#define DW_IC_STATUS_TFE BIT(2)
96#define DW_IC_STATUS_MST_ACTIVITY BIT(5)
97 95
98#define DW_IC_SDA_HOLD_RX_SHIFT 16 96#define DW_IC_SDA_HOLD_RX_SHIFT 16
99#define DW_IC_SDA_HOLD_RX_MASK GENMASK(23, DW_IC_SDA_HOLD_RX_SHIFT) 97#define DW_IC_SDA_HOLD_RX_MASK GENMASK(23, DW_IC_SDA_HOLD_RX_SHIFT)
@@ -478,25 +476,9 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
478{ 476{
479 struct i2c_msg *msgs = dev->msgs; 477 struct i2c_msg *msgs = dev->msgs;
480 u32 ic_tar = 0; 478 u32 ic_tar = 0;
481 bool enabled;
482 479
483 enabled = dw_readl(dev, DW_IC_ENABLE_STATUS) & 1; 480 /* Disable the adapter */
484 481 __i2c_dw_enable_and_wait(dev, false);
485 if (enabled) {
486 u32 ic_status;
487
488 /*
489 * Only disable adapter if ic_tar and ic_con can't be
490 * dynamically updated
491 */
492 ic_status = dw_readl(dev, DW_IC_STATUS);
493 if (!dev->dynamic_tar_update_enabled ||
494 (ic_status & DW_IC_STATUS_MST_ACTIVITY) ||
495 !(ic_status & DW_IC_STATUS_TFE)) {
496 __i2c_dw_enable_and_wait(dev, false);
497 enabled = false;
498 }
499 }
500 482
501 /* if the slave address is ten bit address, enable 10BITADDR */ 483 /* if the slave address is ten bit address, enable 10BITADDR */
502 if (dev->dynamic_tar_update_enabled) { 484 if (dev->dynamic_tar_update_enabled) {
@@ -526,8 +508,8 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
526 /* enforce disabled interrupts (due to HW issues) */ 508 /* enforce disabled interrupts (due to HW issues) */
527 i2c_dw_disable_int(dev); 509 i2c_dw_disable_int(dev);
528 510
529 if (!enabled) 511 /* Enable the adapter */
530 __i2c_dw_enable(dev, true); 512 __i2c_dw_enable(dev, true);
531 513
532 /* Clear and enable interrupts */ 514 /* Clear and enable interrupts */
533 dw_readl(dev, DW_IC_CLR_INTR); 515 dw_readl(dev, DW_IC_CLR_INTR);
@@ -708,8 +690,7 @@ static int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
708} 690}
709 691
710/* 692/*
711 * Prepare controller for a transaction and start transfer by calling 693 * Prepare controller for a transaction and call i2c_dw_xfer_msg
712 * i2c_dw_xfer_init()
713 */ 694 */
714static int 695static int
715i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) 696i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
@@ -752,6 +733,16 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
752 goto done; 733 goto done;
753 } 734 }
754 735
736 /*
737 * We must disable the adapter before returning and signaling the end
738 * of the current transfer. Otherwise the hardware might continue
739 * generating interrupts which in turn causes a race condition with
740 * the following transfer. Needs some more investigation if the
741 * additional interrupts are a hardware bug or this driver doesn't
742 * handle them correctly yet.
743 */
744 __i2c_dw_enable(dev, false);
745
755 if (dev->msg_err) { 746 if (dev->msg_err) {
756 ret = dev->msg_err; 747 ret = dev->msg_err;
757 goto done; 748 goto done;
@@ -893,19 +884,9 @@ static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
893 */ 884 */
894 885
895tx_aborted: 886tx_aborted:
896 if ((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) 887 if ((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) || dev->msg_err)
897 || dev->msg_err) {
898 /*
899 * We must disable interruts before returning and signaling
900 * the end of the current transfer. Otherwise the hardware
901 * might continue generating interrupts for non-existent
902 * transfers.
903 */
904 i2c_dw_disable_int(dev);
905 dw_readl(dev, DW_IC_CLR_INTR);
906
907 complete(&dev->cmd_complete); 888 complete(&dev->cmd_complete);
908 } else if (unlikely(dev->accessor_flags & ACCESS_INTR_MASK)) { 889 else if (unlikely(dev->accessor_flags & ACCESS_INTR_MASK)) {
909 /* workaround to trigger pending interrupt */ 890 /* workaround to trigger pending interrupt */
910 stat = dw_readl(dev, DW_IC_INTR_MASK); 891 stat = dw_readl(dev, DW_IC_INTR_MASK);
911 i2c_dw_disable_int(dev); 892 i2c_dw_disable_int(dev);