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:
parent
bbf5b0bb6d
commit
bd52ae1ad9
@ -169,6 +169,7 @@ struct mpfs_i2c_priv_s
|
|||||||
|
|
||||||
bool initialized; /* Bus initialization status */
|
bool initialized; /* Bus initialization status */
|
||||||
bool fpga; /* FPGA i2c */
|
bool fpga; /* FPGA i2c */
|
||||||
|
bool inflight; /* Transfer ongoing */
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef CONFIG_MPFS_COREI2C
|
#ifndef CONFIG_MPFS_COREI2C
|
||||||
@ -455,6 +456,8 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg)
|
|||||||
{
|
{
|
||||||
priv->tx_idx = 0u;
|
priv->tx_idx = 0u;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
priv->inflight = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MPFS_I2C_ST_LOST_ARB:
|
case MPFS_I2C_ST_LOST_ARB:
|
||||||
@ -487,7 +490,7 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg)
|
|||||||
clear_irq = 0u;
|
clear_irq = 0u;
|
||||||
modifyreg32(MPFS_I2C_CTRL, 0, MPFS_I2C_CTRL_STA_MASK);
|
modifyreg32(MPFS_I2C_CTRL, 0, MPFS_I2C_CTRL_STA_MASK);
|
||||||
|
|
||||||
/* Jump to the next message */
|
/* Jump to the next message */
|
||||||
|
|
||||||
priv->msgid++;
|
priv->msgid++;
|
||||||
}
|
}
|
||||||
@ -506,7 +509,7 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg)
|
|||||||
clear_irq = 0u;
|
clear_irq = 0u;
|
||||||
modifyreg32(MPFS_I2C_CTRL, 0, MPFS_I2C_CTRL_STA_MASK);
|
modifyreg32(MPFS_I2C_CTRL, 0, MPFS_I2C_CTRL_STA_MASK);
|
||||||
|
|
||||||
/* Jump to the next message */
|
/* Jump to the next message */
|
||||||
|
|
||||||
priv->msgid++;
|
priv->msgid++;
|
||||||
}
|
}
|
||||||
@ -574,12 +577,33 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case MPFS_I2C_ST_IDLE:
|
case MPFS_I2C_ST_IDLE:
|
||||||
case MPFS_I2C_ST_STOP_SENT:
|
|
||||||
|
|
||||||
/* No activity, bus idle */
|
/* No activity, bus idle */
|
||||||
|
|
||||||
break;
|
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_RESET_ACTIVATED:
|
||||||
case MPFS_I2C_ST_BUS_ERROR: /* Bus errors */
|
case MPFS_I2C_ST_BUS_ERROR: /* Bus errors */
|
||||||
default:
|
default:
|
||||||
@ -594,31 +618,12 @@ static int mpfs_i2c_irq(int cpuint, void *context, void *arg)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->fpga)
|
if (!priv->fpga && priv->status != MPFS_I2C_IN_PROGRESS)
|
||||||
{
|
{
|
||||||
/* FPGA driver terminates all transactions with STOP sent irq */
|
/* MSS I2C has no STOP sent irq */
|
||||||
|
|
||||||
if (status == MPFS_I2C_ST_STOP_SENT)
|
nxsem_post(&priv->sem_isr);
|
||||||
{
|
}
|
||||||
/* 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (clear_irq)
|
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)
|
static void mpfs_i2c_sendstart(struct mpfs_i2c_priv_s *priv)
|
||||||
{
|
{
|
||||||
up_enable_irq(priv->plic_irq);
|
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,
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->status != MPFS_I2C_SUCCESS)
|
|
||||||
{
|
|
||||||
priv->status = MPFS_I2C_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
priv->msgv = msgs;
|
priv->msgv = msgs;
|
||||||
priv->msgc = count;
|
priv->msgc = count;
|
||||||
|
|
||||||
@ -737,6 +737,7 @@ static int mpfs_i2c_transfer(struct i2c_master_s *dev,
|
|||||||
if (mpfs_i2c_sem_waitdone(priv) < 0)
|
if (mpfs_i2c_sem_waitdone(priv) < 0)
|
||||||
{
|
{
|
||||||
i2cinfo("Message %" PRIu8 " timed out.\n", priv->msgid);
|
i2cinfo("Message %" PRIu8 " timed out.\n", priv->msgid);
|
||||||
|
priv->inflight = false;
|
||||||
ret = -ETIMEDOUT;
|
ret = -ETIMEDOUT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -750,7 +751,6 @@ static int mpfs_i2c_transfer(struct i2c_master_s *dev,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
priv->status = MPFS_I2C_SUCCESS;
|
|
||||||
ret = OK;
|
ret = OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -793,6 +793,8 @@ static int mpfs_i2c_reset(struct i2c_master_s *dev)
|
|||||||
|
|
||||||
up_disable_irq(priv->plic_irq);
|
up_disable_irq(priv->plic_irq);
|
||||||
|
|
||||||
|
priv->inflight = false;
|
||||||
|
priv->status = MPFS_I2C_SUCCESS;
|
||||||
priv->initialized = false;
|
priv->initialized = false;
|
||||||
|
|
||||||
ret = mpfs_i2c_init(priv);
|
ret = mpfs_i2c_init(priv);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user