arch/risc-v/src/mpfs/mpfs_i2c.c: Clean up using priv->status and STOP interrupts

- There are occasional extra STOPs being sent due to an IP bug when using an
  FPGA based I2C. Add a flag "inflight" to mask out extra STOP interrupts when
  using the FPGA based implementation
- There are no MPFS_I2C_ST_STOP_SENT irq's "initally". It is just already
  either success or still in progress

Signed-off-by: Jukka Laitinen <jukkax@ssrc.tii.ae>
This commit is contained in:
Jukka Laitinen 2023-09-11 09:21:31 +03:00 committed by Xiang Xiao
parent bbf5b0bb6d
commit bd52ae1ad9

View File

@ -169,6 +169,7 @@ struct mpfs_i2c_priv_s
bool initialized; /* Bus initialization status */
bool fpga; /* FPGA i2c */
bool inflight; /* Transfer ongoing */
};
#ifndef CONFIG_MPFS_COREI2C
@ -455,6 +456,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:
@ -487,7 +490,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++;
}
@ -506,7 +509,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++;
}
@ -574,12 +577,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:
@ -594,31 +618,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)
{
@ -650,7 +655,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,
@ -669,11 +674,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;
priv->msgc = count;
@ -737,6 +737,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;
}
@ -750,7 +751,6 @@ static int mpfs_i2c_transfer(struct i2c_master_s *dev,
}
else
{
priv->status = MPFS_I2C_SUCCESS;
ret = OK;
}
}
@ -793,6 +793,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);