[PATCH 14/19] hw/i3c/dw-i3c: Add ctrl MMIO handling

Joe Komlodi posted 19 patches 8 months ago
Maintainers: Paolo Bonzini <pbonzini@redhat.com>, Peter Maydell <peter.maydell@linaro.org>, "Cédric Le Goater" <clg@kaod.org>, Steven Lee <steven_lee@aspeedtech.com>, Troy Lee <leetroy@gmail.com>, Jamin Lin <jamin_lin@aspeedtech.com>, Andrew Jeffery <andrew@codeconstruct.com.au>, Joel Stanley <joel@jms.id.au>, "Marc-André Lureau" <marcandre.lureau@redhat.com>, "Daniel P. Berrangé" <berrange@redhat.com>, "Philippe Mathieu-Daudé" <philmd@linaro.org>
There is a newer version of this series
[PATCH 14/19] hw/i3c/dw-i3c: Add ctrl MMIO handling
Posted by Joe Komlodi 8 months ago
Adds functionality to the CTRL register.

Signed-off-by: Joe Komlodi <komlodi@google.com>

Reviewed-by: Titus Rwantare <titusr@google.com>
Reviewed-by: Patrick Venture <venture@google.com>
---
 hw/i3c/dw-i3c.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/hw/i3c/dw-i3c.c b/hw/i3c/dw-i3c.c
index c5af331ac4..61845c909f 100644
--- a/hw/i3c/dw-i3c.c
+++ b/hw/i3c/dw-i3c.c
@@ -361,6 +361,8 @@ static const uint32_t dw_i3c_ro[DW_I3C_NR_REGS] = {
     [R_SLAVE_CONFIG]                = 0xffffffff,
 };
 
+static void dw_i3c_cmd_queue_execute(DWI3C *s);
+
 static inline bool dw_i3c_has_hdr_ts(DWI3C *s)
 {
     return ARRAY_FIELD_EX32(s->regs, HW_CAPABILITY, HDR_TS);
@@ -520,6 +522,36 @@ static int dw_i3c_recv_data(DWI3C *s, bool is_i2c, uint8_t *data,
     return ret;
 }
 
+static void dw_i3c_ctrl_w(DWI3C *s, uint32_t val)
+{
+    /*
+     * If the user is setting I3C_RESUME, the controller was halted.
+     * Try and resume execution and leave the bit cleared.
+     */
+    if (FIELD_EX32(val, DEVICE_CTRL, I3C_RESUME)) {
+        dw_i3c_cmd_queue_execute(s);
+        val = FIELD_DP32(val, DEVICE_CTRL, I3C_RESUME, 0);
+    }
+    /*
+     * I3C_ABORT being set sends an I3C STOP. It's cleared when the STOP is
+     * sent.
+     */
+    if (FIELD_EX32(val, DEVICE_CTRL, I3C_ABORT)) {
+        dw_i3c_end_transfer(s, /*is_i2c=*/true);
+        dw_i3c_end_transfer(s, /*is_i2c=*/false);
+        val = FIELD_DP32(val, DEVICE_CTRL, I3C_ABORT, 0);
+        ARRAY_FIELD_DP32(s->regs, INTR_STATUS, TRANSFER_ABORT, 1);
+        dw_i3c_update_irq(s);
+    }
+    /* Update present state. */
+    ARRAY_FIELD_DP32(s->regs, PRESENT_STATE, CM_TFR_ST_STATUS,
+                     DW_I3C_TRANSFER_STATE_IDLE);
+    ARRAY_FIELD_DP32(s->regs, PRESENT_STATE, CM_TFR_STATUS,
+                     DW_I3C_TRANSFER_STATUS_IDLE);
+
+    s->regs[R_DEVICE_CTRL] = val;
+}
+
 static inline bool dw_i3c_target_is_i2c(DWI3C *s, uint16_t offset)
 {
     /* / sizeof(uint32_t) because we're indexing into our 32-bit reg array. */
@@ -1592,6 +1624,9 @@ static void dw_i3c_write(void *opaque, hwaddr offset, uint64_t value,
                       "] = 0x%08" PRIx64 "\n",
                       __func__, offset, value);
         break;
+    case R_DEVICE_CTRL:
+        dw_i3c_ctrl_w(s, val32);
+        break;
     case R_RX_TX_DATA_PORT:
         dw_i3c_push_tx(s, val32);
         break;
-- 
2.50.0.rc1.591.g9c95f17f64-goog
RE: [PATCH 14/19] hw/i3c/dw-i3c: Add ctrl MMIO handling
Posted by Jamin Lin 1 month ago
> Subject: [PATCH 14/19] hw/i3c/dw-i3c: Add ctrl MMIO handling
> 
> Adds functionality to the CTRL register.
> 
> Signed-off-by: Joe Komlodi <komlodi@google.com>
> 
> Reviewed-by: Titus Rwantare <titusr@google.com>
> Reviewed-by: Patrick Venture <venture@google.com>
> ---
>  hw/i3c/dw-i3c.c | 35 +++++++++++++++++++++++++++++++++++
>  1 file changed, 35 insertions(+)
> 
> diff --git a/hw/i3c/dw-i3c.c b/hw/i3c/dw-i3c.c index c5af331ac4..61845c909f
> 100644
> --- a/hw/i3c/dw-i3c.c
> +++ b/hw/i3c/dw-i3c.c
> @@ -361,6 +361,8 @@ static const uint32_t dw_i3c_ro[DW_I3C_NR_REGS] = {
>      [R_SLAVE_CONFIG]                = 0xffffffff,
>  };
> 
> +static void dw_i3c_cmd_queue_execute(DWI3C *s);
> +
>  static inline bool dw_i3c_has_hdr_ts(DWI3C *s)  {
>      return ARRAY_FIELD_EX32(s->regs, HW_CAPABILITY, HDR_TS); @@
> -520,6 +522,36 @@ static int dw_i3c_recv_data(DWI3C *s, bool is_i2c, uint8_t
> *data,
>      return ret;
>  }
> 
> +static void dw_i3c_ctrl_w(DWI3C *s, uint32_t val) {
> +    /*
> +     * If the user is setting I3C_RESUME, the controller was halted.
> +     * Try and resume execution and leave the bit cleared.
> +     */
> +    if (FIELD_EX32(val, DEVICE_CTRL, I3C_RESUME)) {
> +        dw_i3c_cmd_queue_execute(s);
> +        val = FIELD_DP32(val, DEVICE_CTRL, I3C_RESUME, 0);
> +    }
> +    /*
> +     * I3C_ABORT being set sends an I3C STOP. It's cleared when the STOP is
> +     * sent.
> +     */
> +    if (FIELD_EX32(val, DEVICE_CTRL, I3C_ABORT)) {
> +        dw_i3c_end_transfer(s, /*is_i2c=*/true);
> +        dw_i3c_end_transfer(s, /*is_i2c=*/false);
> +        val = FIELD_DP32(val, DEVICE_CTRL, I3C_ABORT, 0);
> +        ARRAY_FIELD_DP32(s->regs, INTR_STATUS, TRANSFER_ABORT, 1);
> +        dw_i3c_update_irq(s);
> +    }
> +    /* Update present state. */
> +    ARRAY_FIELD_DP32(s->regs, PRESENT_STATE, CM_TFR_ST_STATUS,
> +                     DW_I3C_TRANSFER_STATE_IDLE);
> +    ARRAY_FIELD_DP32(s->regs, PRESENT_STATE, CM_TFR_STATUS,
> +                     DW_I3C_TRANSFER_STATUS_IDLE);
> +
> +    s->regs[R_DEVICE_CTRL] = val;
> +}
> +
>  static inline bool dw_i3c_target_is_i2c(DWI3C *s, uint16_t offset)  {
>      /* / sizeof(uint32_t) because we're indexing into our 32-bit reg array. */
> @@ -1592,6 +1624,9 @@ static void dw_i3c_write(void *opaque, hwaddr
> offset, uint64_t value,
>                        "] = 0x%08" PRIx64 "\n",
>                        __func__, offset, value);
>          break;
> +    case R_DEVICE_CTRL:
> +        dw_i3c_ctrl_w(s, val32);
> +        break;
>      case R_RX_TX_DATA_PORT:
>          dw_i3c_push_tx(s, val32);
>          break;
> --
> 2.50.0.rc1.591.g9c95f17f64-goog

Reviewed-by: Jamin Lin <jamin_lin@aspeedtech.com>

Thanks,
Jamin