Message ID | 20220419090848.9018-5-frank.chang@sifive.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Support ACLINT 32/64-bit mtimecmp/mtime read/write accesses | expand |
On Tue, Apr 19, 2022 at 7:29 PM <frank.chang@sifive.com> wrote: > > From: Jim Shu <jim.shu@sifive.com> > > This commit implements reset function of all ACLINT devices. > ACLINT device reset will clear MTIME and MSIP register to 0. > > Depend on RISC-V ACLINT spec v1.0-rc4: > https://github.com/riscv/riscv-aclint/blob/v1.0-rc4/riscv-aclint.adoc > > Signed-off-by: Jim Shu <jim.shu@sifive.com> > Reviewed-by: Frank Chang <frank.chang@sifive.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Alistair > --- > hw/intc/riscv_aclint.c | 39 +++++++++++++++++++++++++++++++++++++++ > 1 file changed, 39 insertions(+) > > diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c > index ad7ccf96cd..67a07bb5b9 100644 > --- a/hw/intc/riscv_aclint.c > +++ b/hw/intc/riscv_aclint.c > @@ -293,11 +293,29 @@ static void riscv_aclint_mtimer_realize(DeviceState *dev, Error **errp) > } > } > > +static void riscv_aclint_mtimer_reset_enter(Object *obj, ResetType type) > +{ > + /* > + * According to RISC-V ACLINT spec: > + * - On MTIMER device reset, the MTIME register is cleared to zero. > + * - On MTIMER device reset, the MTIMECMP registers are in unknown state. > + */ > + RISCVAclintMTimerState *mtimer = RISCV_ACLINT_MTIMER(obj); > + > + /* > + * Clear mtime register by writing to 0 it. > + * Pending mtime interrupts will also be cleared at the same time. > + */ > + riscv_aclint_mtimer_write(mtimer, mtimer->time_base, 0, 8); > +} > + > static void riscv_aclint_mtimer_class_init(ObjectClass *klass, void *data) > { > DeviceClass *dc = DEVICE_CLASS(klass); > dc->realize = riscv_aclint_mtimer_realize; > device_class_set_props(dc, riscv_aclint_mtimer_properties); > + ResettableClass *rc = RESETTABLE_CLASS(klass); > + rc->phases.enter = riscv_aclint_mtimer_reset_enter; > } > > static const TypeInfo riscv_aclint_mtimer_info = { > @@ -452,11 +470,32 @@ static void riscv_aclint_swi_realize(DeviceState *dev, Error **errp) > } > } > > +static void riscv_aclint_swi_reset_enter(Object *obj, ResetType type) > +{ > + /* > + * According to RISC-V ACLINT spec: > + * - On MSWI device reset, each MSIP register is cleared to zero. > + * > + * p.s. SSWI device reset does nothing since SETSIP register always reads 0. > + */ > + RISCVAclintSwiState *swi = RISCV_ACLINT_SWI(obj); > + int i; > + > + if (!swi->sswi) { > + for (i = 0; i < swi->num_harts; i++) { > + /* Clear MSIP registers by lowering software interrupts. */ > + qemu_irq_lower(swi->soft_irqs[i]); > + } > + } > +} > + > static void riscv_aclint_swi_class_init(ObjectClass *klass, void *data) > { > DeviceClass *dc = DEVICE_CLASS(klass); > dc->realize = riscv_aclint_swi_realize; > device_class_set_props(dc, riscv_aclint_swi_properties); > + ResettableClass *rc = RESETTABLE_CLASS(klass); > + rc->phases.enter = riscv_aclint_swi_reset_enter; > } > > static const TypeInfo riscv_aclint_swi_info = { > -- > 2.35.1 > >
diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c index ad7ccf96cd..67a07bb5b9 100644 --- a/hw/intc/riscv_aclint.c +++ b/hw/intc/riscv_aclint.c @@ -293,11 +293,29 @@ static void riscv_aclint_mtimer_realize(DeviceState *dev, Error **errp) } } +static void riscv_aclint_mtimer_reset_enter(Object *obj, ResetType type) +{ + /* + * According to RISC-V ACLINT spec: + * - On MTIMER device reset, the MTIME register is cleared to zero. + * - On MTIMER device reset, the MTIMECMP registers are in unknown state. + */ + RISCVAclintMTimerState *mtimer = RISCV_ACLINT_MTIMER(obj); + + /* + * Clear mtime register by writing to 0 it. + * Pending mtime interrupts will also be cleared at the same time. + */ + riscv_aclint_mtimer_write(mtimer, mtimer->time_base, 0, 8); +} + static void riscv_aclint_mtimer_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); dc->realize = riscv_aclint_mtimer_realize; device_class_set_props(dc, riscv_aclint_mtimer_properties); + ResettableClass *rc = RESETTABLE_CLASS(klass); + rc->phases.enter = riscv_aclint_mtimer_reset_enter; } static const TypeInfo riscv_aclint_mtimer_info = { @@ -452,11 +470,32 @@ static void riscv_aclint_swi_realize(DeviceState *dev, Error **errp) } } +static void riscv_aclint_swi_reset_enter(Object *obj, ResetType type) +{ + /* + * According to RISC-V ACLINT spec: + * - On MSWI device reset, each MSIP register is cleared to zero. + * + * p.s. SSWI device reset does nothing since SETSIP register always reads 0. + */ + RISCVAclintSwiState *swi = RISCV_ACLINT_SWI(obj); + int i; + + if (!swi->sswi) { + for (i = 0; i < swi->num_harts; i++) { + /* Clear MSIP registers by lowering software interrupts. */ + qemu_irq_lower(swi->soft_irqs[i]); + } + } +} + static void riscv_aclint_swi_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); dc->realize = riscv_aclint_swi_realize; device_class_set_props(dc, riscv_aclint_swi_properties); + ResettableClass *rc = RESETTABLE_CLASS(klass); + rc->phases.enter = riscv_aclint_swi_reset_enter; } static const TypeInfo riscv_aclint_swi_info = {