You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2024/02/06 16:52:43 UTC
(nuttx) 07/07: arch/risc-v/src/mpfs/mpfs_i2c.c: Recover i2c from pending transactions in warm boot
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit df01c83c2524d4316f4dc10629dde00b26174b3e
Author: Jukka Laitinen <ju...@ssrc.tii.ae>
AuthorDate: Fri Jan 12 15:49:27 2024 +0200
arch/risc-v/src/mpfs/mpfs_i2c.c: Recover i2c from pending transactions in warm boot
Signed-off-by: Jukka Laitinen <ju...@ssrc.tii.ae>
---
arch/risc-v/src/mpfs/mpfs_i2c.c | 49 +++++++++++++++++++++++++++++++++++++++--
1 file changed, 47 insertions(+), 2 deletions(-)
diff --git a/arch/risc-v/src/mpfs/mpfs_i2c.c b/arch/risc-v/src/mpfs/mpfs_i2c.c
index 495ff7658c..cf0ecd418a 100644
--- a/arch/risc-v/src/mpfs/mpfs_i2c.c
+++ b/arch/risc-v/src/mpfs/mpfs_i2c.c
@@ -304,12 +304,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 */