Skip to content

Commit

Permalink
arch/risc-v/src/mpfs/mpfs_i2c.c: Recover i2c from pending transaction…
Browse files Browse the repository at this point in the history
…s in warm boot

Signed-off-by: Jukka Laitinen <[email protected]>
  • Loading branch information
jlaitine committed Jan 15, 2024
1 parent 5bc75c2 commit 15391f4
Showing 1 changed file with 47 additions and 2 deletions.
49 changes: 47 additions & 2 deletions arch/risc-v/src/mpfs/mpfs_i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -303,12 +303,57 @@ static uint32_t mpfs_i2c_timeout(int msgc, struct i2c_msg_s *msgv);
static int mpfs_i2c_init(struct mpfs_i2c_priv_s *priv)
{
int ret = OK;
uint32_t ctrl;
uint32_t status;

if (!priv->initialized)
{
/* Clear any pending serial interrupt flag */
/* In case of warm boot, or after reset, check that the IP block is
* not already active and try to recover from any pending data
* transfer if it is.
*/

modifyreg32(MPFS_I2C_CTRL, MPFS_I2C_CTRL_SI_MASK, 0);
ctrl = getreg32(MPFS_I2C_CTRL);
if (ctrl != 0)
{
/* Check if the IP is enabled */

status = getreg32(MPFS_I2C_STATUS);
if (ctrl & MPFS_I2C_CTRL_ENS1_MASK)
{
if (status == MPFS_I2C_ST_RX_DATA_ACK)
{
/* In case the machine was in the middle of data RX, try to
* receive one byte and nack it
*/

modifyreg32(MPFS_I2C_CTRL, MPFS_I2C_CTRL_AA_MASK, 0);
modifyreg32(MPFS_I2C_CTRL, MPFS_I2C_CTRL_SI_MASK, 0);
usleep(100);
status = getreg32(MPFS_I2C_STATUS);
}

if (status != MPFS_I2C_ST_IDLE)
{
/* If the bus is not idle, send STOP */

modifyreg32(MPFS_I2C_CTRL, MPFS_I2C_CTRL_SI_MASK, 0);
modifyreg32(MPFS_I2C_CTRL, 0, MPFS_I2C_CTRL_STO_MASK);
usleep(100);
modifyreg32(MPFS_I2C_CTRL, MPFS_I2C_CTRL_SI_MASK, 0);
status = getreg32(MPFS_I2C_STATUS);
}
}

if (status != MPFS_I2C_ST_IDLE)
{
i2cerr("Bus not idle before init\n");
}

/* Disable IP and continue initialization */

putreg32(0, MPFS_I2C_CTRL);
}

/* Attach interrupt */

Expand Down

0 comments on commit 15391f4

Please sign in to comment.