qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Kuo-Jung Su <dantesu@gmail.com>
To: qemu-devel@nongnu.org
Cc: Peter Maydell <peter.maydell@linaro.org>,
	i.mitsyanko@samsung.com, Blue Swirl <blauwirbel@gmail.com>,
	Kuo-Jung Su <dantesu@gmail.com>,
	Paul Brook <paul@codesourcery.com>, Andreas <afaerber@suse.de>,
	fred.konrad@greensocs.com
Subject: [Qemu-devel] [PATCH v6 07/24] hw/arm: add Faraday FTWDT010 watchdog timer support
Date: Wed,  6 Mar 2013 15:27:20 +0800	[thread overview]
Message-ID: <1362554857-3896-8-git-send-email-dantesu@gmail.com> (raw)
In-Reply-To: <1362554857-3896-1-git-send-email-dantesu@gmail.com>

The FTWDT010 is used to prevent system from infinite loop
while software gets trapped in the deadlock.

Under the normal operation, users should restart FTWDT010
at the regular intervals before counter counts down to 0.

If the counter does reach 0, FTWDT010 will try to reset
the system by generating one or a combination of signals,
system reset, system interrupt, and external interrupt.

Signed-off-by: Kuo-Jung Su <dantesu@gmail.com>
---
 hw/arm/Makefile.objs      |    1 +
 hw/arm/faraday_a369_soc.c |   23 +++++
 hw/arm/ftwdt010.c         |  212 +++++++++++++++++++++++++++++++++++++++++++++
 hw/arm/ftwdt010.h         |   35 ++++++++
 4 files changed, 271 insertions(+)
 create mode 100644 hw/arm/ftwdt010.c
 create mode 100644 hw/arm/ftwdt010.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 2190edd..bc8e2de 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -41,3 +41,4 @@ obj-y += ftintc020.o
 obj-y += ftahbc020.o
 obj-y += ftddrii030.o
 obj-y += ftpwmtmr010.o
+obj-y += ftwdt010.o
diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
index 66d9891..1bf64d4 100644
--- a/hw/arm/faraday_a369_soc.c
+++ b/hw/arm/faraday_a369_soc.c
@@ -68,6 +68,25 @@ static void a369soc_reset(DeviceState *ds)
 }
 
 static void
+a369soc_system_reset(void *opaque)
+{
+    FaradaySoCState *s = FARADAY_SOC(opaque);
+
+    if (s->scu) {
+        device_reset(s->scu);
+    }
+    if (s->ddrc) {
+        device_reset(s->ddrc);
+    }
+    if (s->ahbc) {
+        device_reset(s->ahbc);
+    }
+    if (s->cpu) {
+        cpu_reset(CPU(s->cpu));
+    }
+}
+
+static void
 a369soc_device_init(FaradaySoCState *s)
 {
     DriveInfo *dinfo;
@@ -166,6 +185,10 @@ a369soc_device_init(FaradaySoCState *s)
     sysbus_connect_irq(SYS_BUS_DEVICE(ds), 1, s->pic[9]);
     sysbus_connect_irq(SYS_BUS_DEVICE(ds), 2, s->pic[10]);
     sysbus_connect_irq(SYS_BUS_DEVICE(ds), 3, s->pic[11]);
+
+    /* ftwdt010 */
+    sysbus_create_simple("ftwdt010", 0x92200000, s->pic[46]);
+    qemu_register_reset(a369soc_system_reset, s);
 }
 
 static int a369soc_init(SysBusDevice *dev)
diff --git a/hw/arm/ftwdt010.c b/hw/arm/ftwdt010.c
new file mode 100644
index 0000000..361f16e
--- /dev/null
+++ b/hw/arm/ftwdt010.c
@@ -0,0 +1,212 @@
+/*
+ * QEMU model of the FTWDT010 WatchDog Timer
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su <dantesu@faraday-tech.com>
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+#include "hw/sysbus.h"
+#include "sysemu/sysemu.h"
+#include "qemu/timer.h"
+
+#include "faraday.h"
+#include "ftwdt010.h"
+
+#define TYPE_FTWDT010   "ftwdt010"
+
+typedef struct Ftwdt010State {
+    SysBusDevice busdev;
+    MemoryRegion mmio;
+
+    qemu_irq irq;
+
+    QEMUTimer *qtimer;
+
+    uint64_t timeout;
+    uint64_t freq;        /* desired source clock */
+    uint64_t step;        /* get_ticks_per_sec() / freq */
+    bool running;
+
+    /* HW register cache */
+    uint32_t load;
+    uint32_t cr;
+    uint32_t sr;
+} Ftwdt010State;
+
+#define FTWDT010(obj) \
+    OBJECT_CHECK(Ftwdt010State, obj, TYPE_FTWDT010)
+
+static uint64_t
+ftwdt010_mem_read(void *opaque, hwaddr addr, unsigned size)
+{
+    Ftwdt010State *s = FTWDT010(opaque);
+    uint32_t ret = 0;
+
+    switch (addr) {
+    case REG_COUNTER:
+        if (s->cr & CR_EN) {
+            ret = s->timeout - qemu_get_clock_ms(rt_clock);
+            ret = MIN(s->load, ret * 1000000ULL / s->step);
+        } else {
+            ret = s->load;
+        }
+        break;
+    case REG_LOAD:
+        return s->load;
+    case REG_CR:
+        return s->cr;
+    case REG_SR:
+        return s->sr;
+    case REG_REVR:
+        return 0x00010601;  /* rev. 1.6.1 */
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+            "ftwdt010: undefined memory access@%#" HWADDR_PRIx "\n", addr);
+        break;
+    }
+
+    return ret;
+}
+
+static void
+ftwdt010_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+    Ftwdt010State *s = FTWDT010(opaque);
+
+    switch (addr) {
+    case REG_LOAD:
+        s->load = (uint32_t)val;
+        break;
+    case REG_RESTART:
+        if ((s->cr & CR_EN) && (val == WDT_MAGIC)) {
+            s->timeout = (s->step * (uint64_t)s->load) / 1000000ULL;
+            s->timeout = qemu_get_clock_ms(rt_clock) + MAX(s->timeout, 1);
+            qemu_mod_timer(s->qtimer, s->timeout);
+        }
+        break;
+    case REG_CR:
+        s->cr = (uint32_t)val;
+        if (s->cr & CR_EN) {
+            if (s->running) {
+                break;
+            }
+            s->running = true;
+            s->timeout = (s->step * (uint64_t)s->load) / 1000000ULL;
+            s->timeout = qemu_get_clock_ms(rt_clock) + MAX(s->timeout, 1);
+            qemu_mod_timer(s->qtimer, s->timeout);
+        } else {
+            s->running = false;
+            qemu_del_timer(s->qtimer);
+        }
+        break;
+    case REG_SCR:
+        s->sr &= ~(uint32_t)val;
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+            "ftwdt010: undefined memory access@%#" HWADDR_PRIx "\n", addr);
+        break;
+    }
+}
+
+static const MemoryRegionOps mmio_ops = {
+    .read  = ftwdt010_mem_read,
+    .write = ftwdt010_mem_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4
+    }
+};
+
+static void ftwdt010_timer_tick(void *opaque)
+{
+    Ftwdt010State *s = FTWDT010(opaque);
+
+    s->sr = SR_SRST;
+
+    /* send interrupt signal */
+    qemu_set_irq(s->irq, (s->cr & CR_INTR) ? 1 : 0);
+
+    /* send system reset */
+    if (s->cr & CR_SRST) {
+        qemu_system_reset_request();
+    }
+}
+
+static void ftwdt010_reset(DeviceState *ds)
+{
+    Ftwdt010State *s = FTWDT010(SYS_BUS_DEVICE(ds));
+
+    s->cr      = 0;
+    s->sr      = 0;
+    s->load    = 0x3ef1480;
+    s->timeout = 0;
+}
+
+static int ftwdt010_init(SysBusDevice *dev)
+{
+    Ftwdt010State *s = FTWDT010(dev);
+
+    s->step = (uint64_t)get_ticks_per_sec() / s->freq;
+    s->qtimer = qemu_new_timer_ms(rt_clock, ftwdt010_timer_tick, s);
+
+    memory_region_init_io(&s->mmio,
+                          &mmio_ops,
+                          s,
+                          TYPE_FTWDT010,
+                          0x1000);
+    sysbus_init_mmio(dev, &s->mmio);
+    sysbus_init_irq(dev, &s->irq);
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_ftwdt010 = {
+    .name = TYPE_FTWDT010,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT64(timeout, Ftwdt010State),
+        VMSTATE_UINT64(freq, Ftwdt010State),
+        VMSTATE_UINT64(step, Ftwdt010State),
+        VMSTATE_UINT32(load, Ftwdt010State),
+        VMSTATE_UINT32(cr, Ftwdt010State),
+        VMSTATE_UINT32(sr, Ftwdt010State),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static Property ftwdt010_properties[] = {
+    DEFINE_PROP_UINT64("freq", Ftwdt010State, freq, 66000000ULL),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void ftwdt010_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    k->init     = ftwdt010_init;
+    dc->vmsd    = &vmstate_ftwdt010;
+    dc->props   = ftwdt010_properties;
+    dc->reset   = ftwdt010_reset;
+    dc->no_user = 1;
+}
+
+static const TypeInfo ftwdt010_info = {
+    .name           = TYPE_FTWDT010,
+    .parent         = TYPE_SYS_BUS_DEVICE,
+    .instance_size  = sizeof(Ftwdt010State),
+    .class_init     = ftwdt010_class_init,
+};
+
+static void ftwdt010_register_types(void)
+{
+    type_register_static(&ftwdt010_info);
+}
+
+type_init(ftwdt010_register_types)
diff --git a/hw/arm/ftwdt010.h b/hw/arm/ftwdt010.h
new file mode 100644
index 0000000..46c0871
--- /dev/null
+++ b/hw/arm/ftwdt010.h
@@ -0,0 +1,35 @@
+/*
+ * QEMU model of the FTWDT010 WatchDog Timer
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su <dantesu@faraday-tech.com>
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+#ifndef HW_ARM_FTWDT010_H
+#define HW_ARM_FTWDT010_H
+
+#include "qemu/bitops.h"
+
+/* Hardware registers */
+#define REG_COUNTER     0x00    /* counter register */
+#define REG_LOAD        0x04    /* (re)load register */
+#define REG_RESTART     0x08    /* restart register */
+#define REG_CR          0x0C    /* control register */
+#define REG_SR          0x10    /* status register */
+#define REG_SCR         0x14    /* status clear register */
+#define REG_INTR_LEN    0x18    /* interrupt length register */
+#define REG_REVR        0x1C    /* revision register */
+
+#define CR_CLKS         BIT(4)  /* clock source */
+#define CR_ESIG         BIT(3)  /* external signal enabled */
+#define CR_INTR         BIT(2)  /* system reset interrupt enabled */
+#define CR_SRST         BIT(1)  /* system reset enabled */
+#define CR_EN           BIT(0)  /* chip enabled */
+
+#define SR_SRST         BIT(1)  /* system reset */
+
+#define WDT_MAGIC       0x5ab9  /* magic for watchdog restart */
+
+#endif
-- 
1.7.9.5

  parent reply	other threads:[~2013-03-06  7:28 UTC|newest]

Thread overview: 48+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-03-06  7:27 [Qemu-devel] [PATCH v6 00/24] Add Faraday A369 SoC platform support Kuo-Jung Su
2013-03-06  7:27 ` [Qemu-devel] [PATCH v6 01/24] target-arm: add Faraday ARMv5TE processors support Kuo-Jung Su
2013-03-06  7:27 ` [Qemu-devel] [PATCH v6 02/24] hw/arm: add Faraday a369 SoC platform support Kuo-Jung Su
2013-03-06  7:27 ` [Qemu-devel] [PATCH v6 03/24] hw/arm: add Faraday FTINTC020 interrupt controller support Kuo-Jung Su
2013-03-12  3:42   ` Peter Crosthwaite
2013-03-06  7:27 ` [Qemu-devel] [PATCH v6 04/24] hw/arm: add Faraday FTAHBC020 support Kuo-Jung Su
2013-03-06  7:27 ` [Qemu-devel] [PATCH v6 05/24] hw/arm: add Faraday FTDDRII030 support Kuo-Jung Su
2013-03-06  7:27 ` [Qemu-devel] [PATCH v6 06/24] hw/arm: add Faraday FTPWMTMR010 timer support Kuo-Jung Su
2013-03-06  7:27 ` Kuo-Jung Su [this message]
2013-03-06  8:22   ` [Qemu-devel] [PATCH v6 07/24] hw/arm: add Faraday FTWDT010 watchdog " Paolo Bonzini
2013-03-06  8:56     ` Kuo-Jung Su
2013-03-06 10:46       ` Paolo Bonzini
2013-03-07  2:44         ` Kuo-Jung Su
2013-03-07  5:53           ` Kuo-Jung Su
2013-03-06  7:27 ` [Qemu-devel] [PATCH v6 08/24] hw/arm: add Faraday FTRTC011 RTC " Kuo-Jung Su
2013-03-06  8:24   ` Paolo Bonzini
2013-03-07  6:39     ` Kuo-Jung Su
2013-03-07  7:24       ` Paolo Bonzini
2013-03-07  7:27       ` 陳韋任 (Wei-Ren Chen)
2013-03-07  7:41         ` Paolo Bonzini
2013-03-07  8:01           ` 陳韋任 (Wei-Ren Chen)
2013-03-07  8:08           ` Kuo-Jung Su
2013-03-06  7:27 ` [Qemu-devel] [PATCH v6 09/24] hw/arm: add Faraday FTDMAC020 AHB DMA support Kuo-Jung Su
2013-03-06  7:27 ` [Qemu-devel] [PATCH v6 10/24] hw/arm: add Faraday FTAPBBRG020 APB " Kuo-Jung Su
2013-03-06  7:27 ` [Qemu-devel] [PATCH v6 11/24] hw/nand.c: correct the sense of the BUSY/READY status bit Kuo-Jung Su
2013-03-07  2:11   ` Peter Crosthwaite
2013-03-07  3:40     ` Kuo-Jung Su
2013-03-07  8:37     ` Edgar E. Iglesias
2013-03-06  7:27 ` [Qemu-devel] [PATCH v6 12/24] hw/nand.c: bug fix to erase operation Kuo-Jung Su
2013-03-07  2:18   ` Peter Crosthwaite
2013-03-07  2:28     ` Peter Maydell
2013-03-07  3:32       ` Peter Crosthwaite
2013-03-07  4:10         ` Kuo-Jung Su
2013-03-07  3:35       ` Kuo-Jung Su
2013-03-06  7:27 ` [Qemu-devel] [PATCH v6 13/24] hw/arm: add Faraday FTNANDC021 nand flash controller support Kuo-Jung Su
2013-03-06  7:27 ` [Qemu-devel] [PATCH v6 14/24] hw/arm: add Faraday FTI2C010 I2C " Kuo-Jung Su
2013-03-06  7:27 ` [Qemu-devel] [PATCH v6 15/24] hw: add WM8731 codec support Kuo-Jung Su
2013-03-06  7:27 ` [Qemu-devel] [PATCH v6 16/24] hw/arm: add Faraday FTSSP010 multi-function controller support Kuo-Jung Su
2013-03-06  7:27 ` [Qemu-devel] [PATCH v6 17/24] qemu/bitops.h: add the bit ordering reversal functions stolen from linux Kuo-Jung Su
2013-03-06  8:26   ` Paolo Bonzini
2013-03-07  2:58     ` Kuo-Jung Su
2013-03-06  7:27 ` [Qemu-devel] [PATCH v6 18/24] hw/arm: add Faraday FTGMAC100 1Gbps ethernet support Kuo-Jung Su
2013-03-06  7:27 ` [Qemu-devel] [PATCH v6 19/24] hw/arm: add Faraday FTLCDC200 LCD controller support Kuo-Jung Su
2013-03-06  7:27 ` [Qemu-devel] [PATCH v6 20/24] hw/arm: add Faraday FTTSC010 touchscreen " Kuo-Jung Su
2013-03-06  7:27 ` [Qemu-devel] [PATCH v6 21/24] hw/arm: add Faraday FTSDC010 MMC/SD " Kuo-Jung Su
2013-03-06  7:27 ` [Qemu-devel] [PATCH v6 22/24] hw/arm: add Faraday FTMAC110 10/100Mbps ethernet support Kuo-Jung Su
2013-03-06  7:27 ` [Qemu-devel] [PATCH v6 23/24] hw/arm: add Faraday FTTMR010 timer support Kuo-Jung Su
2013-03-06  7:27 ` [Qemu-devel] [PATCH v6 24/24] hw/arm: add Faraday FTSPI020 SPI flash controller support Kuo-Jung Su

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1362554857-3896-8-git-send-email-dantesu@gmail.com \
    --to=dantesu@gmail.com \
    --cc=afaerber@suse.de \
    --cc=blauwirbel@gmail.com \
    --cc=fred.konrad@greensocs.com \
    --cc=i.mitsyanko@samsung.com \
    --cc=paul@codesourcery.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).