> 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
