diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index bb048e655be7..3ae74160001d 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -4,10 +4,12 @@
  *
  * Author: Mark A. Greer <mgreer@mvista.com>
  *
- * 2005 (c) MontaVista, Software, Inc.  This file is licensed under
- * the terms of the GNU General Public License version 2.  This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
+ * 2005 (c) MontaVista, Software, Inc.
+ * Copyright (c) 2024 Turing Machines, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License v2.
+ * This program is licensed "as is" without any warranty of any kind, whether
+ * express or implied.
  */
 #include <linux/kernel.h>
 #include <linux/slab.h>
@@ -86,12 +88,24 @@
 enum mv64xxx_i2c_state {
        MV64XXX_I2C_STATE_INVALID,
        MV64XXX_I2C_STATE_IDLE,
-       MV64XXX_I2C_STATE_WAITING_FOR_START_COND,
-       MV64XXX_I2C_STATE_WAITING_FOR_RESTART,
-       MV64XXX_I2C_STATE_WAITING_FOR_ADDR_1_ACK,
-       MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK,
-       MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK,
-       MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_DATA,
+       MV64XXX_I2C_STATE_START,
+       MV64XXX_I2C_STATE_RESTART,
+       MV64XXX_I2C_STATE_SEND_ADDR_1,
+       MV64XXX_I2C_STATE_SEND_ADDR_2,
+       MV64XXX_I2C_STATE_WRITE,
+       MV64XXX_I2C_STATE_READ,
+};
+
+/* Driver events */
+enum mv64xxx_i2c_event {
+       MV64XXX_I2C_EVENT_INVALID,
+       MV64XXX_I2C_EVENT_STARTED,
+       MV64XXX_I2C_EVENT_ADDR_ACK,
+       MV64XXX_I2C_EVENT_ADDR_NO_ACK,
+       MV64XXX_I2C_EVENT_WR_ACK,
+       MV64XXX_I2C_EVENT_WR_NO_ACK,
+       MV64XXX_I2C_EVENT_RD_ACKED,
+       MV64XXX_I2C_EVENT_RD_UNACKED,
 };

 /* Driver actions */
@@ -232,9 +246,73 @@ mv64xxx_i2c_hw_init(struct mv64xxx_i2c_data *drv_data)
        drv_data->state = MV64XXX_I2C_STATE_IDLE;
 }

+static enum mv64xxx_i2c_event
+mv64xxx_i2c_decode_status(struct mv64xxx_i2c_data *drv_data, u32 status)
+{
+       /* Decode status to event (state-driven; catches unexpected status) */
+       switch (drv_data->state) {
+       case MV64XXX_I2C_STATE_RESTART:
+       case MV64XXX_I2C_STATE_START:
+               if (status == MV64XXX_I2C_STATUS_MAST_START ||
+                   status == MV64XXX_I2C_STATUS_MAST_REPEAT_START)
+                       return MV64XXX_I2C_EVENT_STARTED;
+               return MV64XXX_I2C_EVENT_INVALID;
+
+       case MV64XXX_I2C_STATE_SEND_ADDR_1:
+               if (drv_data->msg->flags & I2C_M_RD) {
+                       if (status == MV64XXX_I2C_STATUS_MAST_RD_ADDR_ACK)
+                               return MV64XXX_I2C_EVENT_ADDR_ACK;
+                       else if (status ==
MV64XXX_I2C_STATUS_MAST_RD_ADDR_NO_ACK)
+                               return MV64XXX_I2C_EVENT_ADDR_NO_ACK;
+               } else {
+                       if (status == MV64XXX_I2C_STATUS_MAST_WR_ADDR_ACK)
+                               return MV64XXX_I2C_EVENT_ADDR_ACK;
+                       else if (status ==
MV64XXX_I2C_STATUS_MAST_WR_ADDR_NO_ACK)
+                               return MV64XXX_I2C_EVENT_ADDR_NO_ACK;
+               }
+               return MV64XXX_I2C_EVENT_INVALID;
+
+       case MV64XXX_I2C_STATE_SEND_ADDR_2:
+               if (drv_data->msg->flags & I2C_M_RD) {
+                       if (status == MV64XXX_I2C_STATUS_MAST_RD_ADDR_2_ACK)
+                               return MV64XXX_I2C_EVENT_ADDR_ACK;
+                       else if (status ==
MV64XXX_I2C_STATUS_MAST_RD_ADDR_2_NO_ACK)
+                               return MV64XXX_I2C_EVENT_ADDR_NO_ACK;
+               } else {
+                       if (status == MV64XXX_I2C_STATUS_MAST_WR_ADDR_2_ACK)
+                               return MV64XXX_I2C_EVENT_ADDR_ACK;
+                       else if (status ==
MV64XXX_I2C_STATUS_MAST_WR_ADDR_2_NO_ACK)
+                               return MV64XXX_I2C_EVENT_ADDR_NO_ACK;
+               }
+               return MV64XXX_I2C_EVENT_INVALID;
+
+       case MV64XXX_I2C_STATE_WRITE:
+               if (status == MV64XXX_I2C_STATUS_MAST_WR_ACK)
+                       return MV64XXX_I2C_EVENT_WR_ACK;
+               else if (status == MV64XXX_I2C_STATUS_MAST_WR_NO_ACK)
+                       return MV64XXX_I2C_EVENT_ADDR_NO_ACK;
+               return MV64XXX_I2C_EVENT_INVALID;
+
+       case MV64XXX_I2C_STATE_READ:
+               if (status == MV64XXX_I2C_STATUS_MAST_RD_DATA_ACK)
+                       return MV64XXX_I2C_EVENT_RD_ACKED;
+               else if (status == MV64XXX_I2C_STATUS_MAST_RD_DATA_NO_ACK)
+                       return MV64XXX_I2C_EVENT_RD_UNACKED;
+               return MV64XXX_I2C_EVENT_INVALID;
+
+       default:
+               return MV64XXX_I2C_EVENT_INVALID;
+       }
+}
+
 static void
 mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status)
 {
+       enum mv64xxx_i2c_event event;
+       enum mv64xxx_i2c_state prev_state = drv_data->state;
+
+       drv_data->action = MV64XXX_I2C_ACTION_INVALID;
