i2c: xiic: Fix Tx Interrupt path for grouped messages
authorRaviteja Narayanam <raviteja.narayanam@xilinx.com>
Wed, 20 Apr 2022 07:59:24 +0000 (13:29 +0530)
committerWolfram Sang <wsa@kernel.org>
Sat, 14 May 2022 14:02:36 +0000 (16:02 +0200)
When a group of messages are sent from user space as a set, if
the last message has less than Tx FIFO DEPTH number of bytes
to transfer, Tx half empty interrupt is triggered continuously
from the hardware. It is due to Bus not busy interrupt coming
along with Tx half empty and tx empty.

Hence, service the Tx interrupts before Bus not busy interrupt
to update the i2c message status correctly.

Signed-off-by: Raviteja Narayanam <raviteja.narayanam@xilinx.com>
Signed-off-by: Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>
Acked-by: Michal Simek <michal.simek@xilinx.com>
Signed-off-by: Wolfram Sang <wsa@kernel.org>
drivers/i2c/busses/i2c-xiic.c

index 16a7e3164e68484ba1413a55797d5160fec10604..aa6e37a9f27577ac86b8ac32ee192334e9c06d1c 100644 (file)
@@ -468,24 +468,6 @@ static irqreturn_t xiic_process(int irq, void *dev_id)
                        }
                }
        }
-       if (pend & XIIC_INTR_BNB_MASK) {
-               /* IIC bus has transitioned to not busy */
-               clr |= XIIC_INTR_BNB_MASK;
-
-               /* The bus is not busy, disable BusNotBusy interrupt */
-               xiic_irq_dis(i2c, XIIC_INTR_BNB_MASK);
-
-               if (!i2c->tx_msg)
-                       goto out;
-
-               wakeup_req = 1;
-
-               if (i2c->nmsgs == 1 && !i2c->rx_msg &&
-                   xiic_tx_space(i2c) == 0)
-                       wakeup_code = STATE_DONE;
-               else
-                       wakeup_code = STATE_ERROR;
-       }
        if (pend & (XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_HALF_MASK)) {
                /* Transmit register/FIFO is empty or ½ empty */
 
@@ -522,6 +504,26 @@ static irqreturn_t xiic_process(int irq, void *dev_id)
                         */
                        xiic_irq_dis(i2c, XIIC_INTR_TX_HALF_MASK);
        }
+
+       if (pend & XIIC_INTR_BNB_MASK) {
+               /* IIC bus has transitioned to not busy */
+               clr |= XIIC_INTR_BNB_MASK;
+
+               /* The bus is not busy, disable BusNotBusy interrupt */
+               xiic_irq_dis(i2c, XIIC_INTR_BNB_MASK);
+
+               if (!i2c->tx_msg)
+                       goto out;
+
+               wakeup_req = 1;
+
+               if (i2c->nmsgs == 1 && !i2c->rx_msg &&
+                   xiic_tx_space(i2c) == 0)
+                       wakeup_code = STATE_DONE;
+               else
+                       wakeup_code = STATE_ERROR;
+       }
+
 out:
        dev_dbg(i2c->adap.dev.parent, "%s clr: 0x%x\n", __func__, clr);