Merge tag 'v5.10-rockchip-dtsfixes1' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.git] / drivers / i2c / busses / i2c-designware-slave.c
index 44974b5..0d15f4c 100644 (file)
@@ -159,7 +159,6 @@ static int i2c_dw_irq_handler_slave(struct dw_i2c_dev *dev)
        u32 raw_stat, stat, enabled, tmp;
        u8 val = 0, slave_activity;
 
-       regmap_read(dev->map, DW_IC_INTR_STAT, &stat);
        regmap_read(dev->map, DW_IC_ENABLE, &enabled);
        regmap_read(dev->map, DW_IC_RAW_INTR_STAT, &raw_stat);
        regmap_read(dev->map, DW_IC_STATUS, &tmp);
@@ -168,32 +167,30 @@ static int i2c_dw_irq_handler_slave(struct dw_i2c_dev *dev)
        if (!enabled || !(raw_stat & ~DW_IC_INTR_ACTIVITY) || !dev->slave)
                return 0;
 
+       stat = i2c_dw_read_clear_intrbits_slave(dev);
        dev_dbg(dev->dev,
                "%#x STATUS SLAVE_ACTIVITY=%#x : RAW_INTR_STAT=%#x : INTR_STAT=%#x\n",
                enabled, slave_activity, raw_stat, stat);
 
-       if ((stat & DW_IC_INTR_RX_FULL) && (stat & DW_IC_INTR_STOP_DET))
-               i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_REQUESTED, &val);
+       if (stat & DW_IC_INTR_RX_FULL) {
+               if (dev->status != STATUS_WRITE_IN_PROGRESS) {
+                       dev->status = STATUS_WRITE_IN_PROGRESS;
+                       i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_REQUESTED,
+                                       &val);
+               }
+
+               regmap_read(dev->map, DW_IC_DATA_CMD, &tmp);
+               val = tmp;
+               if (!i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_RECEIVED,
+                                    &val))
+                       dev_vdbg(dev->dev, "Byte %X acked!", val);
+       }
 
        if (stat & DW_IC_INTR_RD_REQ) {
                if (slave_activity) {
-                       if (stat & DW_IC_INTR_RX_FULL) {
-                               regmap_read(dev->map, DW_IC_DATA_CMD, &tmp);
-                               val = tmp;
-
-                               if (!i2c_slave_event(dev->slave,
-                                                    I2C_SLAVE_WRITE_RECEIVED,
-                                                    &val)) {
-                                       dev_vdbg(dev->dev, "Byte %X acked!",
-                                                val);
-                               }
-                               regmap_read(dev->map, DW_IC_CLR_RD_REQ, &tmp);
-                               stat = i2c_dw_read_clear_intrbits_slave(dev);
-                       } else {
-                               regmap_read(dev->map, DW_IC_CLR_RD_REQ, &tmp);
-                               regmap_read(dev->map, DW_IC_CLR_RX_UNDER, &tmp);
-                               stat = i2c_dw_read_clear_intrbits_slave(dev);
-                       }
+                       regmap_read(dev->map, DW_IC_CLR_RD_REQ, &tmp);
+
+                       dev->status = STATUS_READ_IN_PROGRESS;
                        if (!i2c_slave_event(dev->slave,
                                             I2C_SLAVE_READ_REQUESTED,
                                             &val))
@@ -205,21 +202,11 @@ static int i2c_dw_irq_handler_slave(struct dw_i2c_dev *dev)
                if (!i2c_slave_event(dev->slave, I2C_SLAVE_READ_PROCESSED,
                                     &val))
                        regmap_read(dev->map, DW_IC_CLR_RX_DONE, &tmp);
-
-               i2c_slave_event(dev->slave, I2C_SLAVE_STOP, &val);
-               stat = i2c_dw_read_clear_intrbits_slave(dev);
-               return 1;
        }
 
-       if (stat & DW_IC_INTR_RX_FULL) {
-               regmap_read(dev->map, DW_IC_DATA_CMD, &tmp);
-               val = tmp;
-               if (!i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_RECEIVED,
-                                    &val))
-                       dev_vdbg(dev->dev, "Byte %X acked!", val);
-       } else {
+       if (stat & DW_IC_INTR_STOP_DET) {
+               dev->status = STATUS_IDLE;
                i2c_slave_event(dev->slave, I2C_SLAVE_STOP, &val);
-               stat = i2c_dw_read_clear_intrbits_slave(dev);
        }
 
        return 1;
@@ -230,7 +217,6 @@ static irqreturn_t i2c_dw_isr_slave(int this_irq, void *dev_id)
        struct dw_i2c_dev *dev = dev_id;
        int ret;
 
-       i2c_dw_read_clear_intrbits_slave(dev);
        ret = i2c_dw_irq_handler_slave(dev);
        if (ret > 0)
                complete(&dev->cmd_complete);