Re: [PATCH 1/3] hw/misc: sifive_e_aon: Support the watchdog timer of HiFive 1 rev b.

2022-10-31 Thread Tommy Wu
Hi Alistair,
Sorry for the late reply.
Thank you for the great feedback!

> Can you please keep all variable declarations at the top of the code
block.
I've fixed it in patch v2.

> Does the guest not expect to read the values back?
The devices : AON-LFROSC, AON-BACKUP, AON_PMU haven't been implemented yet.
So I'll log UNIMP in patch v2.

> We don't need a public create function, the board can just do all of this
itself
I've fixed it in patch v2.

> Couldn't we call this on realise and then have "wdogclk-frequency" be
a standard property exposed via device_class_set_props()?
According to the spec, the frequency of the watchdog timer is programmable.
So I decided to let it be changeable after the watchdog timer is realized.


>It's generally preferable to use the register field macros, such as
>REG8(TCR, 0)
I've fixed this in patch v2.


On Mon, Oct 10, 2022 at 10:25 AM Alistair Francis 
wrote:

> On Thu, Sep 22, 2022 at 6:43 PM Tommy Wu  wrote:
> >
> > The watchdog timer is in the always-on domain device of HiFive 1 rev b,
> > so this patch added the AON device to the sifive_e machine. This patch
> > only implemented the functionality of the watchdog timer.
> >
> > Signed-off-by: Tommy Wu 
> > ---
> >  hw/misc/Kconfig|   3 +
> >  hw/misc/meson.build|   1 +
> >  hw/misc/sifive_e_aon.c | 330 +
> >  include/hw/misc/sifive_e_aon.h |  87 +
> >  4 files changed, 421 insertions(+)
> >  create mode 100644 hw/misc/sifive_e_aon.c
> >  create mode 100644 include/hw/misc/sifive_e_aon.h
> >
> > diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
> > index cbabe9f78c..7d1247822e 100644
> > --- a/hw/misc/Kconfig
> > +++ b/hw/misc/Kconfig
> > @@ -162,6 +162,9 @@ config SIFIVE_TEST
> >  config SIFIVE_E_PRCI
> >  bool
> >
> > +config SIFIVE_E_AON
> > +bool
> > +
> >  config SIFIVE_U_OTP
> >  bool
> >
> > diff --git a/hw/misc/meson.build b/hw/misc/meson.build
> > index 95268eddc0..1536a0cc2e 100644
> > --- a/hw/misc/meson.build
> > +++ b/hw/misc/meson.build
> > @@ -30,6 +30,7 @@ softmmu_ss.add(when: 'CONFIG_MCHP_PFSOC_DMC', if_true:
> files('mchp_pfsoc_dmc.c')
> >  softmmu_ss.add(when: 'CONFIG_MCHP_PFSOC_IOSCB', if_true:
> files('mchp_pfsoc_ioscb.c'))
> >  softmmu_ss.add(when: 'CONFIG_MCHP_PFSOC_SYSREG', if_true:
> files('mchp_pfsoc_sysreg.c'))
> >  softmmu_ss.add(when: 'CONFIG_SIFIVE_TEST', if_true:
> files('sifive_test.c'))
> > +softmmu_ss.add(when: 'CONFIG_SIFIVE_E_AON', if_true:
> files('sifive_e_aon.c'))
> >  softmmu_ss.add(when: 'CONFIG_SIFIVE_E_PRCI', if_true:
> files('sifive_e_prci.c'))
> >  softmmu_ss.add(when: 'CONFIG_SIFIVE_U_OTP', if_true:
> files('sifive_u_otp.c'))
> >  softmmu_ss.add(when: 'CONFIG_SIFIVE_U_PRCI', if_true:
> files('sifive_u_prci.c'))
> > diff --git a/hw/misc/sifive_e_aon.c b/hw/misc/sifive_e_aon.c
> > new file mode 100644
> > index 00..7773dfb168
> > --- /dev/null
> > +++ b/hw/misc/sifive_e_aon.c
> > @@ -0,0 +1,330 @@
> > +/*
> > + * SiFive HiFive1 AON (Always On Domain) for QEMU.
> > + *
> > + * Copyright (c) 2022 SiFive, Inc. All rights reserved.
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> it
> > + * under the terms and conditions of the GNU General Public License,
> > + * version 2 or later, as published by the Free Software Foundation.
> > + *
> > + * This program is distributed in the hope it will be useful, but
> WITHOUT
> > + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> > + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
> License for
> > + * more details.
> > + *
> > + * You should have received a copy of the GNU General Public License
> along with
> > + * this program.  If not, see .
> > + */
> > +
> > +#include "qemu/osdep.h"
> > +#include "qapi/error.h"
> > +#include "qemu/timer.h"
> > +#include "qemu/log.h"
> > +#include "hw/irq.h"
> > +#include "sysemu/watchdog.h"
> > +#include "qapi/visitor.h"
> > +#include "hw/misc/sifive_e_aon.h"
> > +
> > +static void sifive_e_aon_wdt_update_wdogcount(SiFiveEAONState *r)
> > +{
> > +if (0 == r->wdogcfg.wdogenalways &&
> > +0 == r->wdogcfg.wdogencoreawake) {
> > +return;
> > +}
> > +int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
>
> Can you please keep all variable declarations at the top of the code block.
>
> > +r->wdogcount += muldiv64(now - r->wdog_restart_time,
> > + r->wdogclk_freq, NANOSECONDS_PER_SECOND);
> > +/* Clean the most significant bit. */
> > +r->wdogcount = ((r->wdogcount << 1) >> 1);
> > +r->wdog_restart_time = now;
> > +}
> > +
> > +static void sifive_e_aon_wdt_update_state(SiFiveEAONState *r)
> > +{
> > +sifive_e_aon_wdt_update_wdogcount(r);
> > +uint16_t wdogs = (uint16_t)(r->wdogcount >> r->wdogcfg.wdogscale);
> > +bool cmp_signal = false;
> > +if (wdogs >= r->wdogcmp0) {
> > +cmp_signal = true;
> > +if (1 == 

Re: [PATCH 1/3] hw/misc: sifive_e_aon: Support the watchdog timer of HiFive 1 rev b.

2022-10-09 Thread Alistair Francis
On Thu, Sep 22, 2022 at 6:43 PM Tommy Wu  wrote:
>
> The watchdog timer is in the always-on domain device of HiFive 1 rev b,
> so this patch added the AON device to the sifive_e machine. This patch
> only implemented the functionality of the watchdog timer.
>
> Signed-off-by: Tommy Wu 
> ---
>  hw/misc/Kconfig|   3 +
>  hw/misc/meson.build|   1 +
>  hw/misc/sifive_e_aon.c | 330 +
>  include/hw/misc/sifive_e_aon.h |  87 +
>  4 files changed, 421 insertions(+)
>  create mode 100644 hw/misc/sifive_e_aon.c
>  create mode 100644 include/hw/misc/sifive_e_aon.h
>
> diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
> index cbabe9f78c..7d1247822e 100644
> --- a/hw/misc/Kconfig
> +++ b/hw/misc/Kconfig
> @@ -162,6 +162,9 @@ config SIFIVE_TEST
>  config SIFIVE_E_PRCI
>  bool
>
> +config SIFIVE_E_AON
> +bool
> +
>  config SIFIVE_U_OTP
>  bool
>
> diff --git a/hw/misc/meson.build b/hw/misc/meson.build
> index 95268eddc0..1536a0cc2e 100644
> --- a/hw/misc/meson.build
> +++ b/hw/misc/meson.build
> @@ -30,6 +30,7 @@ softmmu_ss.add(when: 'CONFIG_MCHP_PFSOC_DMC', if_true: 
> files('mchp_pfsoc_dmc.c')
>  softmmu_ss.add(when: 'CONFIG_MCHP_PFSOC_IOSCB', if_true: 
> files('mchp_pfsoc_ioscb.c'))
>  softmmu_ss.add(when: 'CONFIG_MCHP_PFSOC_SYSREG', if_true: 
> files('mchp_pfsoc_sysreg.c'))
>  softmmu_ss.add(when: 'CONFIG_SIFIVE_TEST', if_true: files('sifive_test.c'))
> +softmmu_ss.add(when: 'CONFIG_SIFIVE_E_AON', if_true: files('sifive_e_aon.c'))
>  softmmu_ss.add(when: 'CONFIG_SIFIVE_E_PRCI', if_true: 
> files('sifive_e_prci.c'))
>  softmmu_ss.add(when: 'CONFIG_SIFIVE_U_OTP', if_true: files('sifive_u_otp.c'))
>  softmmu_ss.add(when: 'CONFIG_SIFIVE_U_PRCI', if_true: 
> files('sifive_u_prci.c'))
> diff --git a/hw/misc/sifive_e_aon.c b/hw/misc/sifive_e_aon.c
> new file mode 100644
> index 00..7773dfb168
> --- /dev/null
> +++ b/hw/misc/sifive_e_aon.c
> @@ -0,0 +1,330 @@
> +/*
> + * SiFive HiFive1 AON (Always On Domain) for QEMU.
> + *
> + * Copyright (c) 2022 SiFive, Inc. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2 or later, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along 
> with
> + * this program.  If not, see .
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qapi/error.h"
> +#include "qemu/timer.h"
> +#include "qemu/log.h"
> +#include "hw/irq.h"
> +#include "sysemu/watchdog.h"
> +#include "qapi/visitor.h"
> +#include "hw/misc/sifive_e_aon.h"
> +
> +static void sifive_e_aon_wdt_update_wdogcount(SiFiveEAONState *r)
> +{
> +if (0 == r->wdogcfg.wdogenalways &&
> +0 == r->wdogcfg.wdogencoreawake) {
> +return;
> +}
> +int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);

Can you please keep all variable declarations at the top of the code block.

> +r->wdogcount += muldiv64(now - r->wdog_restart_time,
> + r->wdogclk_freq, NANOSECONDS_PER_SECOND);
> +/* Clean the most significant bit. */
> +r->wdogcount = ((r->wdogcount << 1) >> 1);
> +r->wdog_restart_time = now;
> +}
> +
> +static void sifive_e_aon_wdt_update_state(SiFiveEAONState *r)
> +{
> +sifive_e_aon_wdt_update_wdogcount(r);
> +uint16_t wdogs = (uint16_t)(r->wdogcount >> r->wdogcfg.wdogscale);
> +bool cmp_signal = false;
> +if (wdogs >= r->wdogcmp0) {
> +cmp_signal = true;
> +if (1 == r->wdogcfg.wdogzerocmp) {
> +r->wdogcount = 0;
> +wdogs = 0;
> +}
> +}
> +
> +if (cmp_signal) {
> +if (1 == r->wdogcfg.wdogrsten) {
> +watchdog_perform_action();
> +}
> +r->wdogcfg.wdogip0 = 1;
> +}
> +
> +qemu_set_irq(r->wdog_irq, r->wdogcfg.wdogip0);
> +
> +if (wdogs < r->wdogcmp0 &&
> +(r->wdogcfg.wdogenalways ||
> + r->wdogcfg.wdogencoreawake)) {
> +int64_t next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
> +next += muldiv64((r->wdogcmp0 - wdogs) << r->wdogcfg.wdogscale,
> + NANOSECONDS_PER_SECOND, r->wdogclk_freq);
> +timer_mod(r->wdog_timer, next);
> +} else {
> +timer_mod(r->wdog_timer, INT64_MAX);
> +}
> +}
> +
> +/*
> + * Callback used when the timer set using timer_mod expires.
> + */
> +static void sifive_e_aon_wdt_expired_cb(void *opaque)
> +{
> +SiFiveEAONState *r = SIFIVE_E_AON(opaque);
> +sifive_e_aon_wdt_update_state(r);
> +}
> +
> +static uint64_t
> +sifive_e_aon_wdt_read(void *opaque, hwaddr addr, unsigned 

Re: [PATCH 1/3] hw/misc: sifive_e_aon: Support the watchdog timer of HiFive 1 rev b.

2022-09-27 Thread Frank Chang
Reviewed-by: Frank Chang 

On Thu, Sep 22, 2022 at 4:41 PM Tommy Wu  wrote:

> The watchdog timer is in the always-on domain device of HiFive 1 rev b,
> so this patch added the AON device to the sifive_e machine. This patch
> only implemented the functionality of the watchdog timer.
>
> Signed-off-by: Tommy Wu 
> ---
>  hw/misc/Kconfig|   3 +
>  hw/misc/meson.build|   1 +
>  hw/misc/sifive_e_aon.c | 330 +
>  include/hw/misc/sifive_e_aon.h |  87 +
>  4 files changed, 421 insertions(+)
>  create mode 100644 hw/misc/sifive_e_aon.c
>  create mode 100644 include/hw/misc/sifive_e_aon.h
>
> diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
> index cbabe9f78c..7d1247822e 100644
> --- a/hw/misc/Kconfig
> +++ b/hw/misc/Kconfig
> @@ -162,6 +162,9 @@ config SIFIVE_TEST
>  config SIFIVE_E_PRCI
>  bool
>
> +config SIFIVE_E_AON
> +bool
> +
>  config SIFIVE_U_OTP
>  bool
>
> diff --git a/hw/misc/meson.build b/hw/misc/meson.build
> index 95268eddc0..1536a0cc2e 100644
> --- a/hw/misc/meson.build
> +++ b/hw/misc/meson.build
> @@ -30,6 +30,7 @@ softmmu_ss.add(when: 'CONFIG_MCHP_PFSOC_DMC', if_true:
> files('mchp_pfsoc_dmc.c')
>  softmmu_ss.add(when: 'CONFIG_MCHP_PFSOC_IOSCB', if_true:
> files('mchp_pfsoc_ioscb.c'))
>  softmmu_ss.add(when: 'CONFIG_MCHP_PFSOC_SYSREG', if_true:
> files('mchp_pfsoc_sysreg.c'))
>  softmmu_ss.add(when: 'CONFIG_SIFIVE_TEST', if_true:
> files('sifive_test.c'))
> +softmmu_ss.add(when: 'CONFIG_SIFIVE_E_AON', if_true:
> files('sifive_e_aon.c'))
>  softmmu_ss.add(when: 'CONFIG_SIFIVE_E_PRCI', if_true:
> files('sifive_e_prci.c'))
>  softmmu_ss.add(when: 'CONFIG_SIFIVE_U_OTP', if_true:
> files('sifive_u_otp.c'))
>  softmmu_ss.add(when: 'CONFIG_SIFIVE_U_PRCI', if_true:
> files('sifive_u_prci.c'))
> diff --git a/hw/misc/sifive_e_aon.c b/hw/misc/sifive_e_aon.c
> new file mode 100644
> index 00..7773dfb168
> --- /dev/null
> +++ b/hw/misc/sifive_e_aon.c
> @@ -0,0 +1,330 @@
> +/*
> + * SiFive HiFive1 AON (Always On Domain) for QEMU.
> + *
> + * Copyright (c) 2022 SiFive, Inc. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2 or later, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
> for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License
> along with
> + * this program.  If not, see .
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qapi/error.h"
> +#include "qemu/timer.h"
> +#include "qemu/log.h"
> +#include "hw/irq.h"
> +#include "sysemu/watchdog.h"
> +#include "qapi/visitor.h"
> +#include "hw/misc/sifive_e_aon.h"
> +
> +static void sifive_e_aon_wdt_update_wdogcount(SiFiveEAONState *r)
> +{
> +if (0 == r->wdogcfg.wdogenalways &&
> +0 == r->wdogcfg.wdogencoreawake) {
> +return;
> +}
> +int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
> +r->wdogcount += muldiv64(now - r->wdog_restart_time,
> + r->wdogclk_freq, NANOSECONDS_PER_SECOND);
> +/* Clean the most significant bit. */
> +r->wdogcount = ((r->wdogcount << 1) >> 1);
> +r->wdog_restart_time = now;
> +}
> +
> +static void sifive_e_aon_wdt_update_state(SiFiveEAONState *r)
> +{
> +sifive_e_aon_wdt_update_wdogcount(r);
> +uint16_t wdogs = (uint16_t)(r->wdogcount >> r->wdogcfg.wdogscale);
> +bool cmp_signal = false;
> +if (wdogs >= r->wdogcmp0) {
> +cmp_signal = true;
> +if (1 == r->wdogcfg.wdogzerocmp) {
> +r->wdogcount = 0;
> +wdogs = 0;
> +}
> +}
> +
> +if (cmp_signal) {
> +if (1 == r->wdogcfg.wdogrsten) {
> +watchdog_perform_action();
> +}
> +r->wdogcfg.wdogip0 = 1;
> +}
> +
> +qemu_set_irq(r->wdog_irq, r->wdogcfg.wdogip0);
> +
> +if (wdogs < r->wdogcmp0 &&
> +(r->wdogcfg.wdogenalways ||
> + r->wdogcfg.wdogencoreawake)) {
> +int64_t next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
> +next += muldiv64((r->wdogcmp0 - wdogs) << r->wdogcfg.wdogscale,
> + NANOSECONDS_PER_SECOND, r->wdogclk_freq);
> +timer_mod(r->wdog_timer, next);
> +} else {
> +timer_mod(r->wdog_timer, INT64_MAX);
> +}
> +}
> +
> +/*
> + * Callback used when the timer set using timer_mod expires.
> + */
> +static void sifive_e_aon_wdt_expired_cb(void *opaque)
> +{
> +SiFiveEAONState *r = SIFIVE_E_AON(opaque);
> +sifive_e_aon_wdt_update_state(r);
> +}
> +
> +static uint64_t
> +sifive_e_aon_wdt_read(void *opaque, hwaddr addr, unsigned int size)
> +{
> +SiFiveEAONState *r = 

[PATCH 1/3] hw/misc: sifive_e_aon: Support the watchdog timer of HiFive 1 rev b.

2022-09-22 Thread Tommy Wu
The watchdog timer is in the always-on domain device of HiFive 1 rev b,
so this patch added the AON device to the sifive_e machine. This patch
only implemented the functionality of the watchdog timer.

Signed-off-by: Tommy Wu 
---
 hw/misc/Kconfig|   3 +
 hw/misc/meson.build|   1 +
 hw/misc/sifive_e_aon.c | 330 +
 include/hw/misc/sifive_e_aon.h |  87 +
 4 files changed, 421 insertions(+)
 create mode 100644 hw/misc/sifive_e_aon.c
 create mode 100644 include/hw/misc/sifive_e_aon.h

diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index cbabe9f78c..7d1247822e 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -162,6 +162,9 @@ config SIFIVE_TEST
 config SIFIVE_E_PRCI
 bool
 
+config SIFIVE_E_AON
+bool
+
 config SIFIVE_U_OTP
 bool
 
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 95268eddc0..1536a0cc2e 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -30,6 +30,7 @@ softmmu_ss.add(when: 'CONFIG_MCHP_PFSOC_DMC', if_true: 
files('mchp_pfsoc_dmc.c')
 softmmu_ss.add(when: 'CONFIG_MCHP_PFSOC_IOSCB', if_true: 
files('mchp_pfsoc_ioscb.c'))
 softmmu_ss.add(when: 'CONFIG_MCHP_PFSOC_SYSREG', if_true: 
files('mchp_pfsoc_sysreg.c'))
 softmmu_ss.add(when: 'CONFIG_SIFIVE_TEST', if_true: files('sifive_test.c'))
+softmmu_ss.add(when: 'CONFIG_SIFIVE_E_AON', if_true: files('sifive_e_aon.c'))
 softmmu_ss.add(when: 'CONFIG_SIFIVE_E_PRCI', if_true: files('sifive_e_prci.c'))
 softmmu_ss.add(when: 'CONFIG_SIFIVE_U_OTP', if_true: files('sifive_u_otp.c'))
 softmmu_ss.add(when: 'CONFIG_SIFIVE_U_PRCI', if_true: files('sifive_u_prci.c'))
diff --git a/hw/misc/sifive_e_aon.c b/hw/misc/sifive_e_aon.c
new file mode 100644
index 00..7773dfb168
--- /dev/null
+++ b/hw/misc/sifive_e_aon.c
@@ -0,0 +1,330 @@
+/*
+ * SiFive HiFive1 AON (Always On Domain) for QEMU.
+ *
+ * Copyright (c) 2022 SiFive, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see .
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/timer.h"
+#include "qemu/log.h"
+#include "hw/irq.h"
+#include "sysemu/watchdog.h"
+#include "qapi/visitor.h"
+#include "hw/misc/sifive_e_aon.h"
+
+static void sifive_e_aon_wdt_update_wdogcount(SiFiveEAONState *r)
+{
+if (0 == r->wdogcfg.wdogenalways &&
+0 == r->wdogcfg.wdogencoreawake) {
+return;
+}
+int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+r->wdogcount += muldiv64(now - r->wdog_restart_time,
+ r->wdogclk_freq, NANOSECONDS_PER_SECOND);
+/* Clean the most significant bit. */
+r->wdogcount = ((r->wdogcount << 1) >> 1);
+r->wdog_restart_time = now;
+}
+
+static void sifive_e_aon_wdt_update_state(SiFiveEAONState *r)
+{
+sifive_e_aon_wdt_update_wdogcount(r);
+uint16_t wdogs = (uint16_t)(r->wdogcount >> r->wdogcfg.wdogscale);
+bool cmp_signal = false;
+if (wdogs >= r->wdogcmp0) {
+cmp_signal = true;
+if (1 == r->wdogcfg.wdogzerocmp) {
+r->wdogcount = 0;
+wdogs = 0;
+}
+}
+
+if (cmp_signal) {
+if (1 == r->wdogcfg.wdogrsten) {
+watchdog_perform_action();
+}
+r->wdogcfg.wdogip0 = 1;
+}
+
+qemu_set_irq(r->wdog_irq, r->wdogcfg.wdogip0);
+
+if (wdogs < r->wdogcmp0 &&
+(r->wdogcfg.wdogenalways ||
+ r->wdogcfg.wdogencoreawake)) {
+int64_t next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+next += muldiv64((r->wdogcmp0 - wdogs) << r->wdogcfg.wdogscale,
+ NANOSECONDS_PER_SECOND, r->wdogclk_freq);
+timer_mod(r->wdog_timer, next);
+} else {
+timer_mod(r->wdog_timer, INT64_MAX);
+}
+}
+
+/*
+ * Callback used when the timer set using timer_mod expires.
+ */
+static void sifive_e_aon_wdt_expired_cb(void *opaque)
+{
+SiFiveEAONState *r = SIFIVE_E_AON(opaque);
+sifive_e_aon_wdt_update_state(r);
+}
+
+static uint64_t
+sifive_e_aon_wdt_read(void *opaque, hwaddr addr, unsigned int size)
+{
+SiFiveEAONState *r = SIFIVE_E_AON(opaque);
+
+switch (addr) {
+case SIFIVE_E_AON_WDT_WDOGCFG:
+return r->wdogcfg.value;
+case SIFIVE_E_AON_WDT_WDOGCOUNT:
+sifive_e_aon_wdt_update_wdogcount(r);
+return r->wdogcount;
+case SIFIVE_E_AON_WDT_WDOGS:
+sifive_e_aon_wdt_update_wdogcount(r);
+return r->wdogcount >> r->wdogcfg.wdogscale;