diff --git a/arch/risc-v/src/mpfs/mpfs_i2c.c b/arch/risc-v/src/mpfs/mpfs_i2c.c index 0f760820c0a3e..2fb7a538117bb 100644 --- a/arch/risc-v/src/mpfs/mpfs_i2c.c +++ b/arch/risc-v/src/mpfs/mpfs_i2c.c @@ -163,6 +163,7 @@ struct mpfs_i2c_priv_s bool initialized; /* Bus initialization status */ bool fpga; /* FPGA i2c */ + bool inflight; /* Transfer ongoing */ }; #ifndef CONFIG_MPFS_COREI2C @@ -447,6 +448,8 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg) { priv->tx_idx = 0u; } + + priv->inflight = true; break; case MPFS_I2C_ST_LOST_ARB: @@ -479,7 +482,7 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg) clear_irq = 0u; modifyreg32(MPFS_I2C_CTRL, 0, MPFS_I2C_CTRL_STA_MASK); - /* Jump to the next message */ + /* Jump to the next message */ priv->msgid++; } @@ -498,7 +501,7 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg) clear_irq = 0u; modifyreg32(MPFS_I2C_CTRL, 0, MPFS_I2C_CTRL_STA_MASK); - /* Jump to the next message */ + /* Jump to the next message */ priv->msgid++; } @@ -566,12 +569,33 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg) break; case MPFS_I2C_ST_IDLE: - case MPFS_I2C_ST_STOP_SENT: /* No activity, bus idle */ break; + case MPFS_I2C_ST_STOP_SENT: + + /* FPGA driver terminates all transactions with STOP sent irq + * if there has been no errors, the transfer succeeded. + * Due to the IP bug that extra data & STOPs can be sent after + * the actual transaction, filter out any extra stops with + * priv->inflight flag + */ + + if (priv->inflight) + { + if (priv->status == MPFS_I2C_IN_PROGRESS) + { + priv->status = MPFS_I2C_SUCCESS; + } + + nxsem_post(&priv->sem_isr); + } + + priv->inflight = false; + break; + case MPFS_I2C_ST_RESET_ACTIVATED: case MPFS_I2C_ST_BUS_ERROR: /* Bus errors */ default: @@ -586,31 +610,12 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg) break; } - if (priv->fpga) - { - /* FPGA driver terminates all transactions with STOP sent irq */ + if (!priv->fpga && priv->status != MPFS_I2C_IN_PROGRESS) + { + /* MSS I2C has no STOP sent irq */ - if (status == MPFS_I2C_ST_STOP_SENT) - { - /* Don't post on a new request, STOPs possible initially */ - - if (!((priv->rx_idx == 0 && priv->rx_size > 0) || - (priv->tx_idx == 0 && priv->tx_size > 0))) - { - nxsem_post(&priv->sem_isr); - } - else if (priv->status == MPFS_I2C_FAILED) - { - nxsem_post(&priv->sem_isr); - } - } - } - else if (priv->status != MPFS_I2C_IN_PROGRESS) - { - /* MSS I2C has no STOP SENT irq */ - - nxsem_post(&priv->sem_isr); - } + nxsem_post(&priv->sem_isr); + } if (clear_irq) { @@ -642,7 +647,7 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg) static void mpfs_i2c_sendstart(struct mpfs_i2c_priv_s *priv) { up_enable_irq(priv->plic_irq); - modifyreg32(MPFS_I2C_CTRL, MPFS_I2C_CTRL_STA_MASK, MPFS_I2C_CTRL_STA_MASK); + modifyreg32(MPFS_I2C_CTRL, 0, MPFS_I2C_CTRL_STA_MASK); } static int mpfs_i2c_transfer(struct i2c_master_s *dev, @@ -661,11 +666,6 @@ static int mpfs_i2c_transfer(struct i2c_master_s *dev, return ret; } - if (priv->status != MPFS_I2C_SUCCESS) - { - priv->status = MPFS_I2C_SUCCESS; - } - priv->msgv = msgs; for (int i = 0; i < count; i++) @@ -728,6 +728,7 @@ static int mpfs_i2c_transfer(struct i2c_master_s *dev, if (mpfs_i2c_sem_waitdone(priv) < 0) { i2cinfo("Message %" PRIu8 " timed out.\n", priv->msgid); + priv->inflight = false; ret = -ETIMEDOUT; break; } @@ -741,7 +742,6 @@ static int mpfs_i2c_transfer(struct i2c_master_s *dev, } else { - priv->status = MPFS_I2C_SUCCESS; ret = OK; } } @@ -784,6 +784,8 @@ static int mpfs_i2c_reset(struct i2c_master_s *dev) up_disable_irq(priv->plic_irq); + priv->inflight = false; + priv->status = MPFS_I2C_SUCCESS; priv->initialized = false; ret = mpfs_i2c_init(priv);