> Subject: [PATCH 11/19] hw/i3c/dw-i3c: Add IRQ MMIO behavior
> 
> Signed-off-by: Joe Komlodi <[email protected]>
> 
> Reviewed-by: Patrick Venture <[email protected]>
> Reviewed-by: Hao Wu <[email protected]>
> ---
>  hw/i3c/dw-i3c.c | 56
> +++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 56 insertions(+)
> 
> diff --git a/hw/i3c/dw-i3c.c b/hw/i3c/dw-i3c.c index ecd79aba8c..c58e12964c
> 100644
> --- a/hw/i3c/dw-i3c.c
> +++ b/hw/i3c/dw-i3c.c
> @@ -17,6 +17,7 @@
>  #include "qapi/error.h"
>  #include "migration/vmstate.h"
>  #include "trace.h"
> +#include "hw/irq.h"
> 
>  REG32(DEVICE_CTRL,                  0x00)
>      FIELD(DEVICE_CTRL, I3C_BROADCAST_ADDR_INC,    0, 1)
> @@ -352,6 +353,46 @@ static const uint32_t dw_i3c_ro[DW_I3C_NR_REGS] =
> {
>      [R_SLAVE_CONFIG]                = 0xffffffff,
>  };
> 
> +static void dw_i3c_update_irq(DWI3C *s) {
> +    bool level = !!(s->regs[R_INTR_SIGNAL_EN] & s->regs[R_INTR_STATUS]);
> +    qemu_set_irq(s->irq, level);
> +}
> +
> +static uint32_t dw_i3c_intr_status_r(DWI3C *s) {
> +    /* Only return the status whose corresponding EN bits are set. */
> +    return s->regs[R_INTR_STATUS] & s->regs[R_INTR_STATUS_EN]; }
> +
> +static void dw_i3c_intr_status_w(DWI3C *s, uint32_t val) {
> +    /* INTR_STATUS[13:5] is w1c, other bits are RO. */
> +    val &= 0x3fe0;
> +    s->regs[R_INTR_STATUS] &= ~val;
> +
> +    dw_i3c_update_irq(s);
> +}
> +
> +static void dw_i3c_intr_status_en_w(DWI3C *s, uint32_t val) {
> +    s->regs[R_INTR_STATUS_EN] = val;
> +    dw_i3c_update_irq(s);
> +}
> +
> +static void dw_i3c_intr_signal_en_w(DWI3C *s, uint32_t val) {
> +    s->regs[R_INTR_SIGNAL_EN] = val;
> +    dw_i3c_update_irq(s);
> +}
> +
> +static void dw_i3c_intr_force_w(DWI3C *s, uint32_t val) {
> +    /* INTR_FORCE is WO, just set the corresponding INTR_STATUS bits. */
> +    s->regs[R_INTR_STATUS] = val;
> +    dw_i3c_update_irq(s);
> +}
> +
>  static uint64_t dw_i3c_read(void *opaque, hwaddr offset, unsigned size)  {
>      DWI3C *s = DW_I3C(opaque);
> @@ -365,6 +406,9 @@ static uint64_t dw_i3c_read(void *opaque, hwaddr
> offset, unsigned size)
>      case R_INTR_FORCE:
>          value = 0;
>          break;
> +    case R_INTR_STATUS:
> +        value = dw_i3c_intr_status_r(s);
> +        break;
>      default:
>          value = s->regs[addr];
>          break;
> @@ -409,6 +453,18 @@ static void dw_i3c_write(void *opaque, hwaddr offset,
> uint64_t value,
>          break;
>      case R_RESET_CTRL:
>          break;
> +    case R_INTR_STATUS:
> +        dw_i3c_intr_status_w(s, val32);
> +        break;
> +    case R_INTR_STATUS_EN:
> +        dw_i3c_intr_status_en_w(s, val32);
> +        break;
> +    case R_INTR_SIGNAL_EN:
> +        dw_i3c_intr_signal_en_w(s, val32);
> +        break;
> +    case R_INTR_FORCE:
> +        dw_i3c_intr_force_w(s, val32);
> +        break;
>      default:
>          s->regs[addr] = val32;
>          break;
> --
> 2.50.0.rc1.591.g9c95f17f64-goog

Reviewed-by: Jamin Lin <[email protected]>

Thanks,
Jamin

Reply via email to