All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v8 0/5] add allwinner A10 SoC support
@ 2013-12-04  8:09 liguang
  2013-12-04  8:09 ` [Qemu-devel] [PATCH v8 1/5] vmstate: add VMSTATE_PTIMER_ARRAY liguang
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: liguang @ 2013-12-04  8:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Peter Crosthwaite, Andreas Färber, liguang


lay a foundation for allwinner A10 SoC with a cortex-a8
processor, and will add more devices later.

v2: split timer and interrupt controller emulation into
	their corresponding files.
	
v3: 
1. change loader_start address
2. add 64-bit counter
3. fixup fail to clear interrup status issue

v4:
1. add VMSD
2. use defines of magic number for readability
3. code cleanup

v5:
1. add VMSTATE_PTIMER_ARRAY
2. code cleanup

v6:
1. fix a fiq lost issue pointed out by Peter Crosthwaite
2. code cleanup

v7:
model allwinner A10 as a SoC device,
and add cubieboard.

v8:
1. A10 be QOMified as a device
2. add AW as prefix of A10


TODO:
1. add BROM support
2. add more devices

test:
can boot-up officially released linux kernel build with
PLL disabled.

reference:
http://linux-sunxi.org/Main_Page


Li Guang (5)
	 vmstate: add VMSTATE_PTIMER_ARRAY
	 hw/timer: add allwinner a10 timer
	 hw/intc: add allwinner A10 interrupt controller
	 hw/arm: add allwinner a10 SoC support
	 hw/arm: add cubieboard support

default-configs/arm-softmmu.mak      |   2 +
hw/arm/Makefile.objs                 |   4 +-
hw/arm/allwinner-a10.c               |  39 +++++++++++++++++++++++++++++++++++++++
hw/arm/cubieboard.c                  |  33 +++++++++++++++++++++++++++++++++
hw/intc/Makefile.objs                |   1 +
hw/intc/allwinner-a10_pic.c          | 218 +++++++++++++++++++++++++++++++++++
hw/timer/Makefile.objs               |   2 +
hw/timer/allwinner-a10_pit.c         | 253 ++++++++++++++++++++++++++++++++++
include/hw/arm/allwinner-a10.h       |  27 +++++++++++++++++++++++++++
include/hw/intc/allwinner-a10_pic.h  |  40 +++++++
include/hw/timer/allwinner-a10_pit.h |  57 ++++++++
include/migration/vmstate.h          |   4 ++++
savevm.c                             |  31 +++++++++++++++++++++++++++++++
13 files changed, 709 insertions(+), 2 deletions(-)
 create mode 100644 hw/timer/allwinner-a10_pit.c
 create mode 100644 include/hw/timer/allwinner-a10_pit.h
 create mode 100644 hw/intc/allwinner-a10_pic.c
 create mode 100644 include/hw/intc/allwinner-a10_pic.h
 create mode 100644 hw/arm/allwinner-a10.c
 create mode 100644 include/hw/arm/allwinner-a10.h
 create mode 100644 hw/arm/cubieboard.c

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PATCH v8 1/5] vmstate: add VMSTATE_PTIMER_ARRAY
  2013-12-04  8:09 [Qemu-devel] [PATCH v8 0/5] add allwinner A10 SoC support liguang
@ 2013-12-04  8:09 ` liguang
  2013-12-04  8:09 ` [Qemu-devel] [PATCH v8 2/5] hw/timer: add allwinner a10 timer liguang
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: liguang @ 2013-12-04  8:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Peter Crosthwaite, Andreas Färber, liguang

Signed-off-by: liguang <lig.fnst@cn.fujitsu.com>
---
 include/migration/vmstate.h |    4 ++++
 savevm.c                    |   31 +++++++++++++++++++++++++++++++
 2 files changed, 35 insertions(+), 0 deletions(-)

diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index 9d09e60..977cf52 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -165,6 +165,7 @@ extern const VMStateInfo vmstate_info_timer;
 extern const VMStateInfo vmstate_info_buffer;
 extern const VMStateInfo vmstate_info_unused_buffer;
 extern const VMStateInfo vmstate_info_bitmap;
+extern const VMStateInfo vmstate_info_ptimer;
 
 #define type_check_2darray(t1,t2,n,m) ((t1(*)[n][m])0 - (t2*)0)
 #define type_check_array(t1,t2,n) ((t1(*)[n])0 - (t2*)0)
@@ -613,6 +614,9 @@ extern const VMStateInfo vmstate_info_bitmap;
 #define VMSTATE_TIMER_ARRAY(_f, _s, _n)                              \
     VMSTATE_ARRAY_OF_POINTER(_f, _s, _n, 0, vmstate_info_timer, QEMUTimer *)
 
+#define VMSTATE_PTIMER_ARRAY(_f, _s, _n)        \
+    VMSTATE_ARRAY_OF_POINTER(_f, _s, _n, 0, vmstate_info_ptimer, ptimer_state *)
+
 #define VMSTATE_BOOL_ARRAY_V(_f, _s, _n, _v)                         \
     VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_bool, bool)
 
diff --git a/savevm.c b/savevm.c
index 2f631d4..54dbb33 100644
--- a/savevm.c
+++ b/savevm.c
@@ -30,6 +30,7 @@
 #include "monitor/monitor.h"
 #include "sysemu/sysemu.h"
 #include "qemu/timer.h"
+#include "hw/ptimer.h"
 #include "audio/audio.h"
 #include "migration/migration.h"
 #include "qemu/sockets.h"
@@ -1362,6 +1363,36 @@ const VMStateInfo vmstate_info_timer = {
     .put  = put_timer,
 };
 
+static int get_ptimer(QEMUFile *f, void *pv, size_t size)
+{
+    ptimer_state *v = pv;
+    uint64_t count;
+
+    count = qemu_get_be64(f);
+    if (count != -1) {
+        ptimer_set_count(v, count);
+    } else {
+        ptimer_stop(v);
+    }
+
+    return 0;
+}
+
+static void put_ptimer(QEMUFile *f, void *pv, size_t size)
+{
+    ptimer_state *v = pv;
+    uint64_t count;
+
+    count = ptimer_get_count(v);
+    qemu_put_be64(f, count);
+}
+
+const VMStateInfo vmstate_info_ptimer = {
+    .name = "ptimer",
+    .get  = get_ptimer,
+    .put  = put_ptimer,
+};
+
 /* uint8_t buffers */
 
 static int get_buffer(QEMUFile *f, void *pv, size_t size)
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PATCH v8 2/5] hw/timer: add allwinner a10 timer
  2013-12-04  8:09 [Qemu-devel] [PATCH v8 0/5] add allwinner A10 SoC support liguang
  2013-12-04  8:09 ` [Qemu-devel] [PATCH v8 1/5] vmstate: add VMSTATE_PTIMER_ARRAY liguang
@ 2013-12-04  8:09 ` liguang
  2013-12-05  1:28   ` Peter Crosthwaite
  2013-12-04  8:09 ` [Qemu-devel] [PATCH v8 3/5] hw/intc: add allwinner A10 interrupt controller liguang
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 10+ messages in thread
From: liguang @ 2013-12-04  8:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Peter Crosthwaite, Andreas Färber, liguang

Signed-off-by: liguang <lig.fnst@cn.fujitsu.com>
---
 default-configs/arm-softmmu.mak      |    2 +
 hw/timer/Makefile.objs               |    2 +
 hw/timer/allwinner-a10-pit.c         |  253 ++++++++++++++++++++++++++++++++++
 include/hw/timer/allwinner-a10-pit.h |   57 ++++++++
 4 files changed, 314 insertions(+), 0 deletions(-)
 create mode 100644 hw/timer/allwinner-a10-pit.c
 create mode 100644 include/hw/timer/allwinner-a10-pit.h

diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index a555eef..0029596 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -81,3 +81,5 @@ CONFIG_VERSATILE_I2C=y
 
 CONFIG_SDHCI=y
 CONFIG_INTEGRATOR_DEBUG=y
+
+CONFIG_ALLWINNER_A10=y
diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
index eca5905..3020388 100644
--- a/hw/timer/Makefile.objs
+++ b/hw/timer/Makefile.objs
@@ -27,3 +27,5 @@ obj-$(CONFIG_SH4) += sh_timer.o
 obj-$(CONFIG_TUSB6010) += tusb6010.o
 
 obj-$(CONFIG_MC146818RTC) += mc146818rtc.o
+
+obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10-pit.o
diff --git a/hw/timer/allwinner-a10-pit.c b/hw/timer/allwinner-a10-pit.c
new file mode 100644
index 0000000..2305813
--- /dev/null
+++ b/hw/timer/allwinner-a10-pit.c
@@ -0,0 +1,253 @@
+/*
+ * Allwinner A10 timer device emulation
+ *
+ * Copyright (C) 2013 Li Guang
+ * Written by Li Guang <lig.fnst@cn.fujitsu.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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.
+ */
+
+#include "hw/sysbus.h"
+#include "sysemu/sysemu.h"
+#include "hw/timer/allwinner-a10-pit.h"
+
+
+static uint64_t a10_pit_read(void *opaque, hwaddr offset, unsigned size)
+{
+    AwA10PITState *s = AW_A10_PIT(opaque);
+    uint8_t index;
+
+    switch (offset) {
+    case AW_A10_PIT_TIMER_IRQ_EN:
+        return s->irq_enable;
+    case AW_A10_PIT_TIMER_IRQ_ST:
+        return s->irq_status;
+    case AW_A10_PIT_TIMER_BASE ... AW_A10_PIT_TIMER_BASE * 6 + AW_A10_PIT_TIMER_COUNT:
+        index = offset & 0xf0;
+        index >>= 4;
+        index -= 1;
+        switch (offset & 0x0f) {
+        case AW_A10_PIT_TIMER_CONTROL:
+            return s->control[index];
+        case AW_A10_PIT_TIMER_INTERVAL:
+            return s->interval[index];
+        case AW_A10_PIT_TIMER_COUNT:
+            s->count[index] = ptimer_get_count(s->timer[index]);
+            return s->count[index];
+        default:
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "%s: Bad offset 0x%x\n",  __func__, (int)offset);
+            break;
+        }
+    case AW_A10_PIT_WDOG_CONTROL:
+        break;
+    case AW_A10_PIT_WDOG_MODE:
+        break;
+    case AW_A10_PIT_COUNT_LO:
+        return s->count_lo;
+    case AW_A10_PIT_COUNT_HI:
+        return s->count_hi;
+    case AW_A10_PIT_COUNT_CTL:
+        return s->count_ctl;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: Bad offset 0x%x\n",  __func__, (int)offset);
+        break;
+    }
+
+    return 0;
+}
+
+static void a10_pit_write(void *opaque, hwaddr offset, uint64_t value,
+                            unsigned size)
+{
+     AwA10PITState *s = AW_A10_PIT(opaque);
+     uint8_t index;
+
+    switch (offset) {
+    case AW_A10_PIT_TIMER_IRQ_EN:
+        s->irq_enable = value;
+        break;
+    case AW_A10_PIT_TIMER_IRQ_ST:
+        s->irq_status &= ~value;
+        break;
+    case AW_A10_PIT_TIMER_BASE ... AW_A10_PIT_TIMER_BASE * 6 + AW_A10_PIT_TIMER_COUNT:
+        index = offset & 0xf0;
+        index >>= 4;
+        index -= 1;
+        switch (offset & 0x0f) {
+        case AW_A10_PIT_TIMER_CONTROL:
+            s->control[index] = value;
+            if (s->control[index] & AW_A10_PIT_TIMER_RELOAD) {
+                ptimer_set_count(s->timer[index], s->interval[index]);
+            }
+            if (s->control[index] & AW_A10_PIT_TIMER_EN) {
+                int oneshot = 0;
+                if (s->control[index] & AW_A10_PIT_TIMER_MODE) {
+                    oneshot = 1;
+                }
+                ptimer_run(s->timer[index], oneshot);
+            } else {
+                ptimer_stop(s->timer[index]);
+            }
+            break;
+        case AW_A10_PIT_TIMER_INTERVAL:
+            s->interval[index] = value;
+            ptimer_set_limit(s->timer[index], s->interval[index], 1);
+            break;
+        case AW_A10_PIT_TIMER_COUNT:
+            s->count[index] = value;
+            break;
+        default:
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "%s: Bad offset 0x%x\n",  __func__, (int)offset);
+        }
+        break;
+    case AW_A10_PIT_WDOG_CONTROL:
+        s->watch_dog_control = value;
+        break;
+    case AW_A10_PIT_WDOG_MODE:
+        s->watch_dog_mode = value;
+        break;
+    case AW_A10_PIT_COUNT_LO:
+        s->count_lo = value;
+        break;
+    case AW_A10_PIT_COUNT_HI:
+        s->count_hi = value;
+        break;
+    case AW_A10_PIT_COUNT_CTL:
+        s->count_ctl = value;
+        if (s->count_ctl & AW_A10_PIT_COUNT_RL_EN) {
+            s->count_lo = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+            s->count_hi = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) >> 32;
+            s->count_ctl &= ~AW_A10_PIT_COUNT_RL_EN;
+        }
+        if (s->count_ctl & AW_A10_PIT_COUNT_CLR_EN) {
+            s->count_lo = 0;
+            s->count_hi = 0;
+            s->count_ctl &= ~AW_A10_PIT_COUNT_CLR_EN;
+        }
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: Bad offset 0x%x\n",  __func__, (int)offset);
+        break;
+    }
+}
+
+static const MemoryRegionOps a10_pit_ops = {
+    .read = a10_pit_read,
+    .write = a10_pit_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const VMStateDescription vmstate_a10_pit = {
+    .name = "a10.pit",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(irq_enable, AwA10PITState),
+        VMSTATE_UINT32(irq_status, AwA10PITState),
+        VMSTATE_UINT32_ARRAY(control, AwA10PITState, AW_A10_PIT_TIMER_NR),
+        VMSTATE_UINT32_ARRAY(interval, AwA10PITState, AW_A10_PIT_TIMER_NR),
+        VMSTATE_UINT32_ARRAY(count, AwA10PITState, AW_A10_PIT_TIMER_NR),
+        VMSTATE_UINT32(watch_dog_mode, AwA10PITState),
+        VMSTATE_UINT32(watch_dog_control, AwA10PITState),
+        VMSTATE_UINT32(count_lo, AwA10PITState),
+        VMSTATE_UINT32(count_hi, AwA10PITState),
+        VMSTATE_UINT32(count_ctl, AwA10PITState),
+        VMSTATE_PTIMER_ARRAY(timer, AwA10PITState, AW_A10_PIT_TIMER_NR),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void a10_pit_reset(DeviceState *dev)
+{
+    AwA10PITState *s = AW_A10_PIT(dev);
+    uint8_t i;
+
+    s->irq_enable = 0;
+    s->irq_status = 0;
+    for (i = 0; i < 6; i++) {
+        s->control[i] = AW_A10_PIT_DEFAULT_CLOCK;
+        s->interval[i] = 0;
+        s->count[i] = 0;
+        ptimer_stop(s->timer[i]);
+    }
+    s->watch_dog_mode = 0;
+    s->watch_dog_control = 0;
+    s->count_lo = 0;
+    s->count_hi = 0;
+    s->count_ctl = 0;
+}
+
+static void a10_pit_timer_cb(void *opaque)
+{
+    AwA10PITState *s = AW_A10_PIT(opaque);
+    uint8_t i;
+
+    for (i = 0; i < AW_A10_PIT_TIMER_NR; i++) {
+        if (s->control[i] & AW_A10_PIT_TIMER_EN) {
+            s->irq_status |= 1 << i;
+            if (s->control[i] & AW_A10_PIT_TIMER_MODE) {
+                ptimer_stop(s->timer[i]);
+                s->control[i] &= ~AW_A10_PIT_TIMER_EN;
+            }
+            qemu_irq_pulse(s->irq[i]);
+        }
+    }
+}
+
+static void a10_pit_realize(DeviceState *dev, Error **errp)
+{
+    AwA10PITState *s = AW_A10_PIT(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+    QEMUBH * bh[AW_A10_PIT_TIMER_NR];
+    uint8_t i;
+
+    for (i = 0; i < AW_A10_PIT_TIMER_NR; i++) {
+        sysbus_init_irq(sbd, &s->irq[i]);
+    }
+    memory_region_init_io(&s->iomem, OBJECT(s), &a10_pit_ops, s,
+                          TYPE_AW_A10_PIT, 0x400);
+    sysbus_init_mmio(sbd, &s->iomem);
+
+    for (i = 0; i < AW_A10_PIT_TIMER_NR; i++) {
+        bh[i] = qemu_bh_new(a10_pit_timer_cb, s);
+        s->timer[i] = ptimer_init(bh[i]);
+        ptimer_set_freq(s->timer[i], 240000);
+    }
+}
+
+static void a10_pit_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc  = DEVICE_CLASS(klass);
+
+    dc->realize = a10_pit_realize;
+    dc->reset = a10_pit_reset;
+    dc->desc = "allwinner a10 timer";
+    dc->vmsd = &vmstate_a10_pit;
+}
+
+static const TypeInfo a10_pit_info = {
+    .name = TYPE_AW_A10_PIT,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(AwA10PITState),
+    .class_init = a10_pit_class_init,
+};
+
+static void a10_register_types(void)
+{
+    type_register_static(&a10_pit_info);
+}
+
+type_init(a10_register_types);
diff --git a/include/hw/timer/allwinner-a10-pit.h b/include/hw/timer/allwinner-a10-pit.h
new file mode 100644
index 0000000..329c05c
--- /dev/null
+++ b/include/hw/timer/allwinner-a10-pit.h
@@ -0,0 +1,57 @@
+#ifndef AW_A10_PIT_H
+#define AW_A10_PIT_H
+
+#include "hw/ptimer.h"
+
+#define TYPE_AW_A10_PIT "Allwinner-A10-timer"
+#define AW_A10_PIT(obj) OBJECT_CHECK(AwA10PITState, (obj), TYPE_AW_A10_PIT)
+
+#define AW_A10_PIT_TIMER_NR    6
+#define AW_A10_PIT_TIMER_IRQ   0x1
+#define AW_A10_PIT_WDOG_IRQ    0x100
+
+#define AW_A10_PIT_TIMER_IRQ_EN    0
+#define AW_A10_PIT_TIMER_IRQ_ST    0x4
+
+#define AW_A10_PIT_TIMER_CONTROL   0x0
+#define AW_A10_PIT_TIMER_EN        0x1
+#define AW_A10_PIT_TIMER_RELOAD    0x2
+#define AW_A10_PIT_TIMER_MODE      0x80
+
+#define AW_A10_PIT_TIMER_INTERVAL  0x4
+#define AW_A10_PIT_TIMER_COUNT     0x8
+#define AW_A10_PIT_WDOG_CONTROL    0x90
+#define AW_A10_PIT_WDOG_MODE       0x94
+
+#define AW_A10_PIT_COUNT_CTL       0xa0
+#define AW_A10_PIT_COUNT_RL_EN     0x2
+#define AW_A10_PIT_COUNT_CLR_EN    0x1
+#define AW_A10_PIT_COUNT_LO        0xa4
+#define AW_A10_PIT_COUNT_HI        0xa8
+
+#define AW_A10_PIT_TIMER_BASE      0x10
+
+#define AW_A10_PIT_DEFAULT_CLOCK   0x4
+
+typedef struct AwA10PITState {
+    /*< private >*/
+    SysBusDevice parent_obj;
+    /*< public >*/
+    qemu_irq irq[AW_A10_PIT_TIMER_NR];
+    ptimer_state *timer[AW_A10_PIT_TIMER_NR];
+    MemoryRegion iomem;
+
+    uint32_t  irq_enable;
+    uint32_t irq_status;
+    uint32_t control[AW_A10_PIT_TIMER_NR];
+    uint32_t interval[AW_A10_PIT_TIMER_NR];
+    uint32_t count[AW_A10_PIT_TIMER_NR];
+    uint32_t watch_dog_mode;
+    uint32_t watch_dog_control;
+    uint32_t count_lo;
+    uint32_t count_hi;
+    uint32_t count_ctl;
+} AwA10PITState;
+
+#endif
+
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PATCH v8 3/5] hw/intc: add allwinner A10 interrupt controller
  2013-12-04  8:09 [Qemu-devel] [PATCH v8 0/5] add allwinner A10 SoC support liguang
  2013-12-04  8:09 ` [Qemu-devel] [PATCH v8 1/5] vmstate: add VMSTATE_PTIMER_ARRAY liguang
  2013-12-04  8:09 ` [Qemu-devel] [PATCH v8 2/5] hw/timer: add allwinner a10 timer liguang
@ 2013-12-04  8:09 ` liguang
  2013-12-04  8:09 ` [Qemu-devel] [PATCH v8 4/5] hw/arm: add allwinner a10 SoC support liguang
  2013-12-04  8:09 ` [Qemu-devel] [PATCH v8 5/5] hw/arm: add cubieboard support liguang
  4 siblings, 0 replies; 10+ messages in thread
From: liguang @ 2013-12-04  8:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Peter Crosthwaite, Andreas Färber, liguang

Signed-off-by: liguang <lig.fnst@cn.fujitsu.com>
---
 hw/intc/Makefile.objs               |    1 +
 hw/intc/allwinner-a10-pic.c         |  218 +++++++++++++++++++++++++++++++++++
 include/hw/intc/allwinner-a10-pic.h |   40 +++++++
 3 files changed, 259 insertions(+), 0 deletions(-)
 create mode 100644 hw/intc/allwinner-a10-pic.c
 create mode 100644 include/hw/intc/allwinner-a10-pic.h

diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
index 47ac442..ec977c4 100644
--- a/hw/intc/Makefile.objs
+++ b/hw/intc/Makefile.objs
@@ -24,3 +24,4 @@ obj-$(CONFIG_OPENPIC_KVM) += openpic_kvm.o
 obj-$(CONFIG_SH4) += sh_intc.o
 obj-$(CONFIG_XICS) += xics.o
 obj-$(CONFIG_XICS_KVM) += xics_kvm.o
+obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10-pic.o
diff --git a/hw/intc/allwinner-a10-pic.c b/hw/intc/allwinner-a10-pic.c
new file mode 100644
index 0000000..fdc9e4e
--- /dev/null
+++ b/hw/intc/allwinner-a10-pic.c
@@ -0,0 +1,218 @@
+/*
+ * Allwinner A10 interrupt controller device emulation
+ *
+ * Copyright (C) 2013 Li Guang
+ * Written by Li Guang <lig.fnst@cn.fujitsu.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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.
+ */
+
+#include "hw/sysbus.h"
+#include "hw/devices.h"
+#include "sysemu/sysemu.h"
+#include "hw/intc/allwinner-a10-pic.h"
+
+
+static void aw_a10_pic_update(AwA10PICState *s)
+{
+    uint8_t i, j;
+    bool irq = false, fiq = false;
+
+    for (i = 0, j = 0; i < AW_A10_PIC_REG_NUM; i++) {
+        if (s->irq_pending[i] == 0 && s->fiq_pending[i] == 0) {
+            continue;
+        }
+        for (j = 0; j < 32; j++) {
+            if (test_bit(j, (void *)&s->mask[i])) {
+                continue;
+            }
+            if (test_bit(j, (void *)&s->irq_pending[i])) {
+                irq = true;
+            }
+            if (test_bit(j, (void *)&s->fiq_pending[i]) &&
+                test_bit(j, (void *)&s->select[i])) {
+                fiq = true;
+            }
+            if (irq && fiq) {
+                goto out;
+            }
+        }
+    }
+
+out:
+    qemu_set_irq(s->parent_irq, irq);
+    qemu_set_irq(s->parent_fiq, fiq);
+}
+
+static void aw_a10_pic_set_irq(void *opaque, int irq, int level)
+{
+    AwA10PICState *s = opaque;
+
+    if (level) {
+        set_bit(irq%32, (void *)&s->irq_pending[irq/32]);
+    }
+    aw_a10_pic_update(s);
+}
+
+static uint64_t aw_a10_pic_read(void *opaque, hwaddr offset, unsigned size)
+{
+    AwA10PICState *s = opaque;
+    uint8_t index = (offset & 0xc)/4;
+
+    switch (offset) {
+    case AW_A10_PIC_VECTOR:
+        return s->vector;
+    case AW_A10_PIC_BASE_ADDR:
+        return s->base_addr;
+    case AW_A10_PIC_PROTECT:
+        return s->protect;
+    case AW_A10_PIC_NMI:
+        return s->nmi;
+    case AW_A10_PIC_IRQ_PENDING ... AW_A10_PIC_IRQ_PENDING + 8:
+        return s->irq_pending[index];
+    case AW_A10_PIC_FIQ_PENDING ... AW_A10_PIC_FIQ_PENDING + 8:
+        return s->fiq_pending[index];
+    case AW_A10_PIC_SELECT ... AW_A10_PIC_SELECT + 8:
+        return s->select[index];
+    case AW_A10_PIC_ENABLE ... AW_A10_PIC_ENABLE + 8:
+        return s->enable[index];
+    case AW_A10_PIC_MASK ... AW_A10_PIC_MASK + 8:
+        return s->mask[index];
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: Bad offset 0x%x\n",  __func__, (int)offset);
+        break;
+    }
+
+    return 0;
+}
+
+static void aw_a10_pic_write(void *opaque, hwaddr offset, uint64_t value,
+                             unsigned size)
+{
+    AwA10PICState *s = opaque;
+    uint8_t index = (offset & 0xc)/4;
+
+    switch (offset) {
+    case AW_A10_PIC_VECTOR:
+        s->vector = value & ~0x3;
+        break;
+    case AW_A10_PIC_BASE_ADDR:
+        s->base_addr = value & ~0x3;
+    case AW_A10_PIC_PROTECT:
+        s->protect = value;
+        break;
+    case AW_A10_PIC_NMI:
+        s->nmi = value;
+        break;
+    case AW_A10_PIC_IRQ_PENDING ... AW_A10_PIC_IRQ_PENDING + 8:
+        s->irq_pending[index] &= ~value;
+        break;
+    case AW_A10_PIC_FIQ_PENDING ... AW_A10_PIC_FIQ_PENDING + 8:
+        s->fiq_pending[index] &= ~value;
+        break;
+    case AW_A10_PIC_SELECT ... AW_A10_PIC_SELECT + 8:
+        s->select[index] = value;
+        break;
+    case AW_A10_PIC_ENABLE ... AW_A10_PIC_ENABLE + 8:
+        s->enable[index] = value;
+        break;
+    case AW_A10_PIC_MASK ... AW_A10_PIC_MASK + 8:
+        s->mask[index] = value;
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: Bad offset 0x%x\n",  __func__, (int)offset);
+        break;
+    }
+
+    aw_a10_pic_update(s);
+}
+
+static const MemoryRegionOps aw_a10_pic_ops = {
+    .read = aw_a10_pic_read,
+    .write = aw_a10_pic_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const VMStateDescription vmstate_aw_a10_pic = {
+    .name = "a10.pic",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(vector, AwA10PICState),
+        VMSTATE_UINT32(base_addr, AwA10PICState),
+        VMSTATE_UINT32(protect, AwA10PICState),
+        VMSTATE_UINT32(nmi, AwA10PICState),
+        VMSTATE_UINT32_ARRAY(irq_pending, AwA10PICState, AW_A10_PIC_REG_NUM),
+        VMSTATE_UINT32_ARRAY(fiq_pending, AwA10PICState, AW_A10_PIC_REG_NUM),
+        VMSTATE_UINT32_ARRAY(enable, AwA10PICState, AW_A10_PIC_REG_NUM),
+        VMSTATE_UINT32_ARRAY(select, AwA10PICState, AW_A10_PIC_REG_NUM),
+        VMSTATE_UINT32_ARRAY(mask, AwA10PICState, AW_A10_PIC_REG_NUM),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void aw_a10_pic_realize(DeviceState *ds, Error **errp)
+{
+    AwA10PICState *s = AW_A10_PIC(ds);
+    SysBusDevice *dev = SYS_BUS_DEVICE(ds);
+
+     qdev_init_gpio_in(DEVICE(dev), aw_a10_pic_set_irq, AW_A10_PIC_INT_NR);
+     sysbus_init_irq(dev, &s->parent_irq);
+     sysbus_init_irq(dev, &s->parent_fiq);
+     memory_region_init_io(&s->iomem, OBJECT(s), &aw_a10_pic_ops, s,
+                           "a10-pic", 0x400);
+     sysbus_init_mmio(dev, &s->iomem);
+}
+
+static void aw_a10_pic_reset(DeviceState *d)
+{
+    AwA10PICState *s = AW_A10_PIC(d);
+    uint8_t i;
+
+    s->base_addr = 0;
+    s->protect = 0;
+    s->nmi = 0;
+    s->vector = 0;
+    for (i = 0; i < AW_A10_PIC_REG_NUM; i++) {
+        s->irq_pending[i] = 0;
+        s->fiq_pending[i] = 0;
+        s->select[i] = 0;
+        s->enable[i] = 0;
+        s->mask[i] = 0;
+    }
+}
+
+static void aw_a10_pic_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = aw_a10_pic_realize;
+    dc->reset = aw_a10_pic_reset;
+    dc->desc = "A10 pic";
+    dc->vmsd = &vmstate_aw_a10_pic;
+ }
+
+static const TypeInfo aw_a10_pic_info = {
+    .name = TYPE_AW_A10_PIC,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(AwA10PICState),
+    .class_init = aw_a10_pic_class_init,
+};
+
+static void aw_a10_register_types(void)
+{
+    type_register_static(&aw_a10_pic_info);
+}
+
+type_init(aw_a10_register_types);
diff --git a/include/hw/intc/allwinner-a10-pic.h b/include/hw/intc/allwinner-a10-pic.h
new file mode 100644
index 0000000..b5d1c05
--- /dev/null
+++ b/include/hw/intc/allwinner-a10-pic.h
@@ -0,0 +1,40 @@
+#ifndef AW_A10_PIC_H
+#define AW_A10_PIC_H
+
+#define TYPE_AW_A10_PIC  "a10-pic"
+#define AW_A10_PIC(obj) OBJECT_CHECK(AwA10PICState, (obj), TYPE_AW_A10_PIC)
+
+#define AW_A10_PIC_VECTOR       0
+#define AW_A10_PIC_BASE_ADDR    4
+#define AW_A10_PIC_PROTECT      8
+#define AW_A10_PIC_NMI          0xc
+#define AW_A10_PIC_IRQ_PENDING  0x10
+#define AW_A10_PIC_FIQ_PENDING  0x20
+#define AW_A10_PIC_SELECT       0x30
+#define AW_A10_PIC_ENABLE       0x40
+#define AW_A10_PIC_MASK         0x50
+
+#define AW_A10_PIC_INT_NR       95
+#define AW_A10_PIC_REG_NUM      DIV_ROUND_UP(AW_A10_PIC_INT_NR, 32)
+
+typedef struct AwA10PICState {
+    /*< private >*/
+    SysBusDevice parent_obj;
+    /*< public >*/
+    MemoryRegion iomem;
+    qemu_irq parent_fiq;
+    qemu_irq parent_irq;
+
+    uint32_t vector;
+    uint32_t base_addr;
+    uint32_t protect;
+    uint32_t nmi;
+    uint32_t irq_pending[AW_A10_PIC_REG_NUM];
+    uint32_t fiq_pending[AW_A10_PIC_REG_NUM];
+    uint32_t select[AW_A10_PIC_REG_NUM];
+    uint32_t enable[AW_A10_PIC_REG_NUM];
+    uint32_t mask[AW_A10_PIC_REG_NUM];
+    /*priority setting here*/
+} AwA10PICState;
+
+#endif
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PATCH v8 4/5] hw/arm: add allwinner a10 SoC support
  2013-12-04  8:09 [Qemu-devel] [PATCH v8 0/5] add allwinner A10 SoC support liguang
                   ` (2 preceding siblings ...)
  2013-12-04  8:09 ` [Qemu-devel] [PATCH v8 3/5] hw/intc: add allwinner A10 interrupt controller liguang
@ 2013-12-04  8:09 ` liguang
  2013-12-04 11:32   ` Peter Crosthwaite
  2013-12-04  8:09 ` [Qemu-devel] [PATCH v8 5/5] hw/arm: add cubieboard support liguang
  4 siblings, 1 reply; 10+ messages in thread
From: liguang @ 2013-12-04  8:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Peter Crosthwaite, Andreas Färber, liguang

Signed-off-by: liguang <lig.fnst@cn.fujitsu.com>
---
 hw/arm/Makefile.objs           |    2 +-
 hw/arm/allwinner-a10.c         |   77 ++++++++++++++++++++++++++++++++++++++++
 include/hw/arm/allwinner-a10.h |   36 ++++++++++++++++++
 3 files changed, 114 insertions(+), 1 deletions(-)
 create mode 100644 hw/arm/allwinner-a10.c
 create mode 100644 include/hw/arm/allwinner-a10.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 3671b42..b9e5983 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -4,4 +4,4 @@ obj-y += omap_sx1.o palm.o realview.o spitz.o stellaris.o
 obj-y += tosa.o versatilepb.o vexpress.o xilinx_zynq.o z2.o
 
 obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o
-obj-y += omap1.o omap2.o strongarm.o
+obj-y += omap1.o omap2.o strongarm.o allwinner-a10.o
diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
new file mode 100644
index 0000000..c4699b7
--- /dev/null
+++ b/hw/arm/allwinner-a10.c
@@ -0,0 +1,77 @@
+#include "hw/sysbus.h"
+#include "hw/devices.h"
+#include "hw/arm/allwinner-a10.h"
+
+
+static void aw_a10_init(Object *obj)
+{
+    AwA10State *s = AW_A10(obj);
+    DeviceState *dev;
+
+    object_initialize(&s->cpu, sizeof(s->cpu), "cortex-a8-" TYPE_ARM_CPU);
+    object_property_add_child(obj, "cpu", OBJECT(&s->cpu), NULL);
+
+    object_initialize(&s->intc, sizeof(s->timer), TYPE_AW_A10_PIC);
+    dev = DEVICE(&s->intc);
+    qdev_set_parent_bus(dev, sysbus_get_default());
+
+    object_initialize(&s->timer, sizeof(s->timer), TYPE_AW_A10_PIT);
+    dev = DEVICE(&s->timer);
+    qdev_set_parent_bus(dev, sysbus_get_default());
+}
+
+static void aw_a10_realize(DeviceState *dev, Error **errp)
+{
+    AwA10State *s = AW_A10(dev);
+    SysBusDevice *sysbusdev;
+    uint8_t i;
+    Error *err = NULL;
+
+    object_property_set_bool(OBJECT(&s->cpu), true, "realized", &err);
+    s->cpu_irq[0] = qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_IRQ);
+    s->cpu_irq[1] = qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_FIQ);
+
+    object_property_set_bool(OBJECT(&s->intc), true, "realized", &err);
+    sysbusdev = SYS_BUS_DEVICE(&s->intc);
+    sysbus_mmio_map(sysbusdev, 0, AW_A10_PIC_REG_BASE);
+    sysbus_connect_irq(sysbusdev, 0, s->cpu_irq[0]);
+    sysbus_connect_irq(sysbusdev, 1, s->cpu_irq[1]);
+    for (i = 0; i < AW_A10_PIC_INT_NR; i++) {
+        s->irq[i] = qdev_get_gpio_in(DEVICE(&s->intc), i);
+    }
+
+    object_property_set_bool(OBJECT(&s->timer), true, "realized", &err);
+    sysbusdev = SYS_BUS_DEVICE(&s->timer);
+    sysbus_mmio_map(sysbusdev, 0, AW_A10_PIT_REG_BASE);
+    sysbus_connect_irq(sysbusdev, 0, s->irq[22]);
+    sysbus_connect_irq(sysbusdev, 1, s->irq[23]);
+    sysbus_connect_irq(sysbusdev, 2, s->irq[24]);
+    sysbus_connect_irq(sysbusdev, 3, s->irq[25]);
+    sysbus_connect_irq(sysbusdev, 4, s->irq[67]);
+    sysbus_connect_irq(sysbusdev, 5, s->irq[68]);
+
+    serial_mm_init(get_system_memory(), AW_A10_UART0_REG_BASE, 2, s->irq[1],
+                   115200, serial_hds[0], DEVICE_NATIVE_ENDIAN);
+}
+
+static void aw_a10_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+
+    dc->realize = aw_a10_realize;
+}
+
+static const TypeInfo aw_a10_type_info = {
+    .name = TYPE_AW_A10,
+    .parent = TYPE_DEVICE,
+    .instance_size = sizeof(AwA10State),
+    .instance_init = aw_a10_init,
+    .class_init = aw_a10_class_init,
+};
+
+static void aw_a10_register_types(void)
+{
+    type_register_static(&aw_a10_type_info);
+}
+
+type_init(aw_a10_register_types)
diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
new file mode 100644
index 0000000..a3e7b77
--- /dev/null
+++ b/include/hw/arm/allwinner-a10.h
@@ -0,0 +1,36 @@
+#ifndef ALLWINNER_H_
+
+#include "qemu-common.h"
+#include "qemu/error-report.h"
+#include "hw/char/serial.h"
+#include "hw/arm/arm.h"
+#include "hw/timer/allwinner-a10-pit.h"
+#include "hw/intc/allwinner-a10-pic.h"
+
+#include "sysemu/sysemu.h"
+#include "exec/address-spaces.h"
+
+
+#define AW_A10_PIC_REG_BASE     0x01c20400
+#define AW_A10_PIT_REG_BASE     0x01c20c00
+#define AW_A10_UART0_REG_BASE   0x01c28000
+
+#define AW_A10_SDRAM_BASE       0x40000000
+
+#define TYPE_AW_A10 "allwiner-a10"
+#define AW_A10(obj) OBJECT_CHECK(AwA10State, (obj), TYPE_AW_A10)
+
+typedef struct AwA10State {
+    /*< private >*/
+    DeviceState parent_obj;
+    /*< public >*/
+
+    ARMCPU cpu;
+    qemu_irq irq[AW_A10_PIC_INT_NR];
+    qemu_irq cpu_irq[2];
+    AwA10PITState timer;
+    AwA10PICState intc;
+} AwA10State;
+
+#define ALLWINNER_H_
+#endif
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PATCH v8 5/5] hw/arm: add cubieboard support
  2013-12-04  8:09 [Qemu-devel] [PATCH v8 0/5] add allwinner A10 SoC support liguang
                   ` (3 preceding siblings ...)
  2013-12-04  8:09 ` [Qemu-devel] [PATCH v8 4/5] hw/arm: add allwinner a10 SoC support liguang
@ 2013-12-04  8:09 ` liguang
  4 siblings, 0 replies; 10+ messages in thread
From: liguang @ 2013-12-04  8:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Peter Crosthwaite, Andreas Färber, liguang

Signed-off-by: liguang <lig.fnst@cn.fujitsu.com>
---
 hw/arm/Makefile.objs |    2 +-
 hw/arm/cubieboard.c  |   52 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 53 insertions(+), 1 deletions(-)
 create mode 100644 hw/arm/cubieboard.c

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index b9e5983..8be8d8e 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -4,4 +4,4 @@ obj-y += omap_sx1.o palm.o realview.o spitz.o stellaris.o
 obj-y += tosa.o versatilepb.o vexpress.o xilinx_zynq.o z2.o
 
 obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o
-obj-y += omap1.o omap2.o strongarm.o allwinner-a10.o
+obj-y += omap1.o omap2.o strongarm.o allwinner-a10.o cubieboard.o
diff --git a/hw/arm/cubieboard.c b/hw/arm/cubieboard.c
new file mode 100644
index 0000000..0599061
--- /dev/null
+++ b/hw/arm/cubieboard.c
@@ -0,0 +1,52 @@
+#include "hw/sysbus.h"
+#include "hw/devices.h"
+#include "hw/boards.h"
+#include "hw/arm/allwinner-a10.h"
+
+
+static struct arm_boot_info cubieboard_binfo = {
+    .loader_start = AW_A10_SDRAM_BASE,
+    .board_id = 0x1008,
+};
+
+typedef struct CubieBoardState {
+    AwA10State *a10;
+    MemoryRegion sdram;
+} CubieBoardState;
+
+static void cubieboard_init(QEMUMachineInitArgs *args)
+{
+    CubieBoardState *s = g_new(CubieBoardState, 1);
+    Error *err = NULL;
+
+    s->a10 = AW_A10(object_new(TYPE_AW_A10));
+    object_property_set_bool(OBJECT(s->a10), true, "realized", &err);
+    if (err != NULL) {
+        error_report("Couldn't realize Allwinner A10: %s\n",
+                error_get_pretty(err));
+        exit(1);
+    }
+
+    memory_region_init_ram(&s->sdram, NULL, "cubieboard.ram", args->ram_size);
+    vmstate_register_ram_global(&s->sdram);
+    memory_region_add_subregion(get_system_memory(), AW_A10_SDRAM_BASE,
+                                &s->sdram);
+    cubieboard_binfo.ram_size = args->ram_size;
+    cubieboard_binfo.kernel_filename = args->kernel_filename;
+    cubieboard_binfo.kernel_cmdline = args->kernel_cmdline;
+    arm_load_kernel(&s->a10->cpu, &cubieboard_binfo);
+}
+
+static QEMUMachine cubieboard_machine = {
+    .name = "cubieboard",
+    .desc = "cubietec cubieboard emulation",
+    .init = cubieboard_init,
+};
+
+
+static void cubieboard_machine_init(void)
+{
+    qemu_register_machine(&cubieboard_machine);
+}
+
+machine_init(cubieboard_machine_init)
-- 
1.7.2.5

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/5] hw/arm: add allwinner a10 SoC support
  2013-12-04  8:09 ` [Qemu-devel] [PATCH v8 4/5] hw/arm: add allwinner a10 SoC support liguang
@ 2013-12-04 11:32   ` Peter Crosthwaite
  2013-12-05  0:21     ` Li Guang
  0 siblings, 1 reply; 10+ messages in thread
From: Peter Crosthwaite @ 2013-12-04 11:32 UTC (permalink / raw)
  To: liguang
  Cc: Peter Maydell, qemu-devel@nongnu.org Developers,
	Andreas Färber

On Wed, Dec 4, 2013 at 6:09 PM, liguang <lig.fnst@cn.fujitsu.com> wrote:
> Signed-off-by: liguang <lig.fnst@cn.fujitsu.com>
> ---
>  hw/arm/Makefile.objs           |    2 +-
>  hw/arm/allwinner-a10.c         |   77 ++++++++++++++++++++++++++++++++++++++++
>  include/hw/arm/allwinner-a10.h |   36 ++++++++++++++++++
>  3 files changed, 114 insertions(+), 1 deletions(-)
>  create mode 100644 hw/arm/allwinner-a10.c
>  create mode 100644 include/hw/arm/allwinner-a10.h
>
> diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
> index 3671b42..b9e5983 100644
> --- a/hw/arm/Makefile.objs
> +++ b/hw/arm/Makefile.objs
> @@ -4,4 +4,4 @@ obj-y += omap_sx1.o palm.o realview.o spitz.o stellaris.o
>  obj-y += tosa.o versatilepb.o vexpress.o xilinx_zynq.o z2.o
>
>  obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o
> -obj-y += omap1.o omap2.o strongarm.o
> +obj-y += omap1.o omap2.o strongarm.o allwinner-a10.o
> diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
> new file mode 100644
> index 0000000..c4699b7
> --- /dev/null
> +++ b/hw/arm/allwinner-a10.c
> @@ -0,0 +1,77 @@
> +#include "hw/sysbus.h"
> +#include "hw/devices.h"
> +#include "hw/arm/allwinner-a10.h"
> +
> +
> +static void aw_a10_init(Object *obj)
> +{
> +    AwA10State *s = AW_A10(obj);
> +    DeviceState *dev;
> +
> +    object_initialize(&s->cpu, sizeof(s->cpu), "cortex-a8-" TYPE_ARM_CPU);
> +    object_property_add_child(obj, "cpu", OBJECT(&s->cpu), NULL);
> +
> +    object_initialize(&s->intc, sizeof(s->timer), TYPE_AW_A10_PIC);
> +    dev = DEVICE(&s->intc);

You could just use DEVICE(foo) inline here and below and drop the dev
variable to reduce verbosity.

> +    qdev_set_parent_bus(dev, sysbus_get_default());
> +
> +    object_initialize(&s->timer, sizeof(s->timer), TYPE_AW_A10_PIT);
> +    dev = DEVICE(&s->timer);
> +    qdev_set_parent_bus(dev, sysbus_get_default());
> +}
> +
> +static void aw_a10_realize(DeviceState *dev, Error **errp)
> +{
> +    AwA10State *s = AW_A10(dev);
> +    SysBusDevice *sysbusdev;
> +    uint8_t i;
> +    Error *err = NULL;
> +
> +    object_property_set_bool(OBJECT(&s->cpu), true, "realized", &err);
> +    s->cpu_irq[0] = qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_IRQ);
> +    s->cpu_irq[1] = qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_FIQ);
> +
> +    object_property_set_bool(OBJECT(&s->intc), true, "realized", &err);

You neither assert nor propagate the error. So the repeated usage
below will cause a delayed (and somewhat obscure) assertion below if
both happen to error for some reason.

> +    sysbusdev = SYS_BUS_DEVICE(&s->intc);
> +    sysbus_mmio_map(sysbusdev, 0, AW_A10_PIC_REG_BASE);
> +    sysbus_connect_irq(sysbusdev, 0, s->cpu_irq[0]);
> +    sysbus_connect_irq(sysbusdev, 1, s->cpu_irq[1]);
> +    for (i = 0; i < AW_A10_PIC_INT_NR; i++) {
> +        s->irq[i] = qdev_get_gpio_in(DEVICE(&s->intc), i);
> +    }
> +
> +    object_property_set_bool(OBJECT(&s->timer), true, "realized", &err);
> +    sysbusdev = SYS_BUS_DEVICE(&s->timer);
> +    sysbus_mmio_map(sysbusdev, 0, AW_A10_PIT_REG_BASE);
> +    sysbus_connect_irq(sysbusdev, 0, s->irq[22]);
> +    sysbus_connect_irq(sysbusdev, 1, s->irq[23]);
> +    sysbus_connect_irq(sysbusdev, 2, s->irq[24]);
> +    sysbus_connect_irq(sysbusdev, 3, s->irq[25]);
> +    sysbus_connect_irq(sysbusdev, 4, s->irq[67]);
> +    sysbus_connect_irq(sysbusdev, 5, s->irq[68]);
> +
> +    serial_mm_init(get_system_memory(), AW_A10_UART0_REG_BASE, 2, s->irq[1],
> +                   115200, serial_hds[0], DEVICE_NATIVE_ENDIAN);
> +}
> +
> +static void aw_a10_class_init(ObjectClass *oc, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(oc);
> +
> +    dc->realize = aw_a10_realize;
> +}
> +
> +static const TypeInfo aw_a10_type_info = {
> +    .name = TYPE_AW_A10,
> +    .parent = TYPE_DEVICE,
> +    .instance_size = sizeof(AwA10State),
> +    .instance_init = aw_a10_init,
> +    .class_init = aw_a10_class_init,
> +};
> +
> +static void aw_a10_register_types(void)
> +{
> +    type_register_static(&aw_a10_type_info);
> +}
> +
> +type_init(aw_a10_register_types)
> diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
> new file mode 100644
> index 0000000..a3e7b77
> --- /dev/null
> +++ b/include/hw/arm/allwinner-a10.h
> @@ -0,0 +1,36 @@
> +#ifndef ALLWINNER_H_
> +
> +#include "qemu-common.h"
> +#include "qemu/error-report.h"
> +#include "hw/char/serial.h"
> +#include "hw/arm/arm.h"
> +#include "hw/timer/allwinner-a10-pit.h"
> +#include "hw/intc/allwinner-a10-pic.h"
> +
> +#include "sysemu/sysemu.h"
> +#include "exec/address-spaces.h"
> +
> +
> +#define AW_A10_PIC_REG_BASE     0x01c20400
> +#define AW_A10_PIT_REG_BASE     0x01c20c00
> +#define AW_A10_UART0_REG_BASE   0x01c28000
> +
> +#define AW_A10_SDRAM_BASE       0x40000000
> +
> +#define TYPE_AW_A10 "allwiner-a10"

"allwinner"

> +#define AW_A10(obj) OBJECT_CHECK(AwA10State, (obj), TYPE_AW_A10)
> +
> +typedef struct AwA10State {
> +    /*< private >*/
> +    DeviceState parent_obj;
> +    /*< public >*/
> +
> +    ARMCPU cpu;
> +    qemu_irq irq[AW_A10_PIC_INT_NR];
> +    qemu_irq cpu_irq[2];

I dont see the need to keep these as device state. They appear to be
just local variables to realize().

> +    AwA10PITState timer;
> +    AwA10PICState intc;
> +} AwA10State;
> +
> +#define ALLWINNER_H_
> +#endif
> --
> 1.7.2.5
>
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/5] hw/arm: add allwinner a10 SoC support
  2013-12-04 11:32   ` Peter Crosthwaite
@ 2013-12-05  0:21     ` Li Guang
  0 siblings, 0 replies; 10+ messages in thread
From: Li Guang @ 2013-12-05  0:21 UTC (permalink / raw)
  To: Peter Crosthwaite
  Cc: Peter Maydell, qemu-devel@nongnu.org Developers,
	Andreas Färber

Peter Crosthwaite wrote:
> On Wed, Dec 4, 2013 at 6:09 PM, liguang<lig.fnst@cn.fujitsu.com>  wrote:
>    
>> Signed-off-by: liguang<lig.fnst@cn.fujitsu.com>
>> ---
>>   hw/arm/Makefile.objs           |    2 +-
>>   hw/arm/allwinner-a10.c         |   77 ++++++++++++++++++++++++++++++++++++++++
>>   include/hw/arm/allwinner-a10.h |   36 ++++++++++++++++++
>>   3 files changed, 114 insertions(+), 1 deletions(-)
>>   create mode 100644 hw/arm/allwinner-a10.c
>>   create mode 100644 include/hw/arm/allwinner-a10.h
>>
>> diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
>> index 3671b42..b9e5983 100644
>> --- a/hw/arm/Makefile.objs
>> +++ b/hw/arm/Makefile.objs
>> @@ -4,4 +4,4 @@ obj-y += omap_sx1.o palm.o realview.o spitz.o stellaris.o
>>   obj-y += tosa.o versatilepb.o vexpress.o xilinx_zynq.o z2.o
>>
>>   obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o
>> -obj-y += omap1.o omap2.o strongarm.o
>> +obj-y += omap1.o omap2.o strongarm.o allwinner-a10.o
>> diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
>> new file mode 100644
>> index 0000000..c4699b7
>> --- /dev/null
>> +++ b/hw/arm/allwinner-a10.c
>> @@ -0,0 +1,77 @@
>> +#include "hw/sysbus.h"
>> +#include "hw/devices.h"
>> +#include "hw/arm/allwinner-a10.h"
>> +
>> +
>> +static void aw_a10_init(Object *obj)
>> +{
>> +    AwA10State *s = AW_A10(obj);
>> +    DeviceState *dev;
>> +
>> +    object_initialize(&s->cpu, sizeof(s->cpu), "cortex-a8-" TYPE_ARM_CPU);
>> +    object_property_add_child(obj, "cpu", OBJECT(&s->cpu), NULL);
>> +
>> +    object_initialize(&s->intc, sizeof(s->timer), TYPE_AW_A10_PIC);
>> +    dev = DEVICE(&s->intc);
>>      
> You could just use DEVICE(foo) inline here and below and drop the dev
> variable to reduce verbosity.
>
>    
>> +    qdev_set_parent_bus(dev, sysbus_get_default());
>> +
>> +    object_initialize(&s->timer, sizeof(s->timer), TYPE_AW_A10_PIT);
>> +    dev = DEVICE(&s->timer);
>> +    qdev_set_parent_bus(dev, sysbus_get_default());
>> +}
>> +
>> +static void aw_a10_realize(DeviceState *dev, Error **errp)
>> +{
>> +    AwA10State *s = AW_A10(dev);
>> +    SysBusDevice *sysbusdev;
>> +    uint8_t i;
>> +    Error *err = NULL;
>> +
>> +    object_property_set_bool(OBJECT(&s->cpu), true, "realized",&err);
>> +    s->cpu_irq[0] = qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_IRQ);
>> +    s->cpu_irq[1] = qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_FIQ);
>> +
>> +    object_property_set_bool(OBJECT(&s->intc), true, "realized",&err);
>>      
> You neither assert nor propagate the error. So the repeated usage
> below will cause a delayed (and somewhat obscure) assertion below if
> both happen to error for some reason.
>
>    
>> +    sysbusdev = SYS_BUS_DEVICE(&s->intc);
>> +    sysbus_mmio_map(sysbusdev, 0, AW_A10_PIC_REG_BASE);
>> +    sysbus_connect_irq(sysbusdev, 0, s->cpu_irq[0]);
>> +    sysbus_connect_irq(sysbusdev, 1, s->cpu_irq[1]);
>> +    for (i = 0; i<  AW_A10_PIC_INT_NR; i++) {
>> +        s->irq[i] = qdev_get_gpio_in(DEVICE(&s->intc), i);
>> +    }
>> +
>> +    object_property_set_bool(OBJECT(&s->timer), true, "realized",&err);
>> +    sysbusdev = SYS_BUS_DEVICE(&s->timer);
>> +    sysbus_mmio_map(sysbusdev, 0, AW_A10_PIT_REG_BASE);
>> +    sysbus_connect_irq(sysbusdev, 0, s->irq[22]);
>> +    sysbus_connect_irq(sysbusdev, 1, s->irq[23]);
>> +    sysbus_connect_irq(sysbusdev, 2, s->irq[24]);
>> +    sysbus_connect_irq(sysbusdev, 3, s->irq[25]);
>> +    sysbus_connect_irq(sysbusdev, 4, s->irq[67]);
>> +    sysbus_connect_irq(sysbusdev, 5, s->irq[68]);
>> +
>> +    serial_mm_init(get_system_memory(), AW_A10_UART0_REG_BASE, 2, s->irq[1],
>> +                   115200, serial_hds[0], DEVICE_NATIVE_ENDIAN);
>> +}
>> +
>> +static void aw_a10_class_init(ObjectClass *oc, void *data)
>> +{
>> +    DeviceClass *dc = DEVICE_CLASS(oc);
>> +
>> +    dc->realize = aw_a10_realize;
>> +}
>> +
>> +static const TypeInfo aw_a10_type_info = {
>> +    .name = TYPE_AW_A10,
>> +    .parent = TYPE_DEVICE,
>> +    .instance_size = sizeof(AwA10State),
>> +    .instance_init = aw_a10_init,
>> +    .class_init = aw_a10_class_init,
>> +};
>> +
>> +static void aw_a10_register_types(void)
>> +{
>> +    type_register_static(&aw_a10_type_info);
>> +}
>> +
>> +type_init(aw_a10_register_types)
>> diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
>> new file mode 100644
>> index 0000000..a3e7b77
>> --- /dev/null
>> +++ b/include/hw/arm/allwinner-a10.h
>> @@ -0,0 +1,36 @@
>> +#ifndef ALLWINNER_H_
>> +
>> +#include "qemu-common.h"
>> +#include "qemu/error-report.h"
>> +#include "hw/char/serial.h"
>> +#include "hw/arm/arm.h"
>> +#include "hw/timer/allwinner-a10-pit.h"
>> +#include "hw/intc/allwinner-a10-pic.h"
>> +
>> +#include "sysemu/sysemu.h"
>> +#include "exec/address-spaces.h"
>> +
>> +
>> +#define AW_A10_PIC_REG_BASE     0x01c20400
>> +#define AW_A10_PIT_REG_BASE     0x01c20c00
>> +#define AW_A10_UART0_REG_BASE   0x01c28000
>> +
>> +#define AW_A10_SDRAM_BASE       0x40000000
>> +
>> +#define TYPE_AW_A10 "allwiner-a10"
>>      
> "allwinner"
>
>    
>> +#define AW_A10(obj) OBJECT_CHECK(AwA10State, (obj), TYPE_AW_A10)
>> +
>> +typedef struct AwA10State {
>> +    /*<  private>*/
>> +    DeviceState parent_obj;
>> +    /*<  public>*/
>> +
>> +    ARMCPU cpu;
>> +    qemu_irq irq[AW_A10_PIC_INT_NR];
>> +    qemu_irq cpu_irq[2];
>>      
> I dont see the need to keep these as device state. They appear to be
> just local variables to realize().
>
>    
>> +    AwA10PITState timer;
>> +    AwA10PICState intc;
>> +} AwA10State;
>> +
>> +#define ALLWINNER_H_
>> +#endif
>> --
>> 1.7.2.5
>>
>>
>>      
>    
OK, will fix.

Thanks!
Li Guang

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [PATCH v8 2/5] hw/timer: add allwinner a10 timer
  2013-12-04  8:09 ` [Qemu-devel] [PATCH v8 2/5] hw/timer: add allwinner a10 timer liguang
@ 2013-12-05  1:28   ` Peter Crosthwaite
  2013-12-05  1:51     ` Li Guang
  0 siblings, 1 reply; 10+ messages in thread
From: Peter Crosthwaite @ 2013-12-05  1:28 UTC (permalink / raw)
  To: liguang
  Cc: Peter Maydell, qemu-devel@nongnu.org Developers,
	Andreas Färber

On Wed, Dec 4, 2013 at 6:09 PM, liguang <lig.fnst@cn.fujitsu.com> wrote:
> Signed-off-by: liguang <lig.fnst@cn.fujitsu.com>
> ---
>  default-configs/arm-softmmu.mak      |    2 +
>  hw/timer/Makefile.objs               |    2 +
>  hw/timer/allwinner-a10-pit.c         |  253 ++++++++++++++++++++++++++++++++++
>  include/hw/timer/allwinner-a10-pit.h |   57 ++++++++
>  4 files changed, 314 insertions(+), 0 deletions(-)
>  create mode 100644 hw/timer/allwinner-a10-pit.c
>  create mode 100644 include/hw/timer/allwinner-a10-pit.h
>
> diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
> index a555eef..0029596 100644
> --- a/default-configs/arm-softmmu.mak
> +++ b/default-configs/arm-softmmu.mak
> @@ -81,3 +81,5 @@ CONFIG_VERSATILE_I2C=y
>
>  CONFIG_SDHCI=y
>  CONFIG_INTEGRATOR_DEBUG=y
> +
> +CONFIG_ALLWINNER_A10=y
> diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
> index eca5905..3020388 100644
> --- a/hw/timer/Makefile.objs
> +++ b/hw/timer/Makefile.objs
> @@ -27,3 +27,5 @@ obj-$(CONFIG_SH4) += sh_timer.o
>  obj-$(CONFIG_TUSB6010) += tusb6010.o
>
>  obj-$(CONFIG_MC146818RTC) += mc146818rtc.o
> +
> +obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10-pit.o
> diff --git a/hw/timer/allwinner-a10-pit.c b/hw/timer/allwinner-a10-pit.c
> new file mode 100644
> index 0000000..2305813
> --- /dev/null
> +++ b/hw/timer/allwinner-a10-pit.c
> @@ -0,0 +1,253 @@
> +/*
> + * Allwinner A10 timer device emulation
> + *
> + * Copyright (C) 2013 Li Guang
> + * Written by Li Guang <lig.fnst@cn.fujitsu.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that 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.
> + */
> +
> +#include "hw/sysbus.h"
> +#include "sysemu/sysemu.h"
> +#include "hw/timer/allwinner-a10-pit.h"
> +
> +

Not sure of the motivation for extra blank lines.

> +static uint64_t a10_pit_read(void *opaque, hwaddr offset, unsigned size)
> +{
> +    AwA10PITState *s = AW_A10_PIT(opaque);
> +    uint8_t index;
> +
> +    switch (offset) {
> +    case AW_A10_PIT_TIMER_IRQ_EN:
> +        return s->irq_enable;
> +    case AW_A10_PIT_TIMER_IRQ_ST:
> +        return s->irq_status;
> +    case AW_A10_PIT_TIMER_BASE ... AW_A10_PIT_TIMER_BASE * 6 + AW_A10_PIT_TIMER_COUNT:

It's strange to me that AW_A10_PIT_TIMER_BASE is used as both an
offset and a stride. It's only co-incidence that 0x10 is both the
offset of the first timers' individual registers as well as the diff
between timer register offsets. I think you could just simplify by
putting it all in the header, something like:

#define AW_A10_PIT_TIMER_BASE_END (AW_A10_PIT_TIMER_BASE * 6 + 0x10).

> +        index = offset & 0xf0;
> +        index >>= 4;
> +        index -= 1;
> +        switch (offset & 0x0f) {
> +        case AW_A10_PIT_TIMER_CONTROL:
> +            return s->control[index];
> +        case AW_A10_PIT_TIMER_INTERVAL:
> +            return s->interval[index];
> +        case AW_A10_PIT_TIMER_COUNT:
> +            s->count[index] = ptimer_get_count(s->timer[index]);
> +            return s->count[index];
> +        default:
> +            qemu_log_mask(LOG_GUEST_ERROR,
> +                          "%s: Bad offset 0x%x\n",  __func__, (int)offset);
> +            break;
> +        }
> +    case AW_A10_PIT_WDOG_CONTROL:
> +        break;
> +    case AW_A10_PIT_WDOG_MODE:
> +        break;
> +    case AW_A10_PIT_COUNT_LO:
> +        return s->count_lo;
> +    case AW_A10_PIT_COUNT_HI:
> +        return s->count_hi;
> +    case AW_A10_PIT_COUNT_CTL:
> +        return s->count_ctl;
> +    default:
> +        qemu_log_mask(LOG_GUEST_ERROR,
> +                      "%s: Bad offset 0x%x\n",  __func__, (int)offset);
> +        break;
> +    }
> +
> +    return 0;
> +}
> +
> +static void a10_pit_write(void *opaque, hwaddr offset, uint64_t value,
> +                            unsigned size)
> +{
> +     AwA10PITState *s = AW_A10_PIT(opaque);
> +     uint8_t index;
> +
> +    switch (offset) {
> +    case AW_A10_PIT_TIMER_IRQ_EN:
> +        s->irq_enable = value;
> +        break;
> +    case AW_A10_PIT_TIMER_IRQ_ST:
> +        s->irq_status &= ~value;
> +        break;
> +    case AW_A10_PIT_TIMER_BASE ... AW_A10_PIT_TIMER_BASE * 6 + AW_A10_PIT_TIMER_COUNT:
> +        index = offset & 0xf0;
> +        index >>= 4;
> +        index -= 1;
> +        switch (offset & 0x0f) {
> +        case AW_A10_PIT_TIMER_CONTROL:
> +            s->control[index] = value;
> +            if (s->control[index] & AW_A10_PIT_TIMER_RELOAD) {
> +                ptimer_set_count(s->timer[index], s->interval[index]);
> +            }
> +            if (s->control[index] & AW_A10_PIT_TIMER_EN) {
> +                int oneshot = 0;
> +                if (s->control[index] & AW_A10_PIT_TIMER_MODE) {
> +                    oneshot = 1;
> +                }
> +                ptimer_run(s->timer[index], oneshot);
> +            } else {
> +                ptimer_stop(s->timer[index]);
> +            }
> +            break;
> +        case AW_A10_PIT_TIMER_INTERVAL:
> +            s->interval[index] = value;
> +            ptimer_set_limit(s->timer[index], s->interval[index], 1);
> +            break;
> +        case AW_A10_PIT_TIMER_COUNT:
> +            s->count[index] = value;
> +            break;
> +        default:
> +            qemu_log_mask(LOG_GUEST_ERROR,
> +                          "%s: Bad offset 0x%x\n",  __func__, (int)offset);
> +        }
> +        break;
> +    case AW_A10_PIT_WDOG_CONTROL:
> +        s->watch_dog_control = value;
> +        break;
> +    case AW_A10_PIT_WDOG_MODE:
> +        s->watch_dog_mode = value;
> +        break;
> +    case AW_A10_PIT_COUNT_LO:
> +        s->count_lo = value;
> +        break;
> +    case AW_A10_PIT_COUNT_HI:
> +        s->count_hi = value;
> +        break;
> +    case AW_A10_PIT_COUNT_CTL:
> +        s->count_ctl = value;
> +        if (s->count_ctl & AW_A10_PIT_COUNT_RL_EN) {
> +            s->count_lo = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
> +            s->count_hi = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) >> 32;

Sorry for not spotting this one earlier (i'm going full line by line
now), but you should just do the one call to qemu_clock_get_ns
(capture to local variable).

Whats probably cleanest is to implement s->count as uint64_t and just
use deposit64/extract64 in MMIO read/write fns. Saves about 5 LOC and
is a little more self documenting.

You counter is also implicitly 1GHz right? that's probably worth a comment.

Regards,
Peter

PS. You are still re-spinning very fast. Can I suggest 24hr as a
minimum wait to give other reviewers a chance? That gives all the
global timezones a chance to participate. I did a high level review of
one of your new patches last night at home, but I haven't had a chance
to look at this properly till this morning (at work) yet you have
already respun on me. Persoanally, I'm going for 48h respins atm.

> +            s->count_ctl &= ~AW_A10_PIT_COUNT_RL_EN;
> +        }
> +        if (s->count_ctl & AW_A10_PIT_COUNT_CLR_EN) {
> +            s->count_lo = 0;
> +            s->count_hi = 0;
> +            s->count_ctl &= ~AW_A10_PIT_COUNT_CLR_EN;
> +        }
> +        break;
> +    default:
> +        qemu_log_mask(LOG_GUEST_ERROR,
> +                      "%s: Bad offset 0x%x\n",  __func__, (int)offset);
> +        break;
> +    }
> +}
> +
> +static const MemoryRegionOps a10_pit_ops = {
> +    .read = a10_pit_read,
> +    .write = a10_pit_write,
> +    .endianness = DEVICE_NATIVE_ENDIAN,
> +};
> +
> +static const VMStateDescription vmstate_a10_pit = {
> +    .name = "a10.pit",
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .minimum_version_id_old = 1,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_UINT32(irq_enable, AwA10PITState),
> +        VMSTATE_UINT32(irq_status, AwA10PITState),
> +        VMSTATE_UINT32_ARRAY(control, AwA10PITState, AW_A10_PIT_TIMER_NR),
> +        VMSTATE_UINT32_ARRAY(interval, AwA10PITState, AW_A10_PIT_TIMER_NR),
> +        VMSTATE_UINT32_ARRAY(count, AwA10PITState, AW_A10_PIT_TIMER_NR),
> +        VMSTATE_UINT32(watch_dog_mode, AwA10PITState),
> +        VMSTATE_UINT32(watch_dog_control, AwA10PITState),
> +        VMSTATE_UINT32(count_lo, AwA10PITState),
> +        VMSTATE_UINT32(count_hi, AwA10PITState),
> +        VMSTATE_UINT32(count_ctl, AwA10PITState),
> +        VMSTATE_PTIMER_ARRAY(timer, AwA10PITState, AW_A10_PIT_TIMER_NR),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static void a10_pit_reset(DeviceState *dev)
> +{
> +    AwA10PITState *s = AW_A10_PIT(dev);
> +    uint8_t i;
> +
> +    s->irq_enable = 0;
> +    s->irq_status = 0;
> +    for (i = 0; i < 6; i++) {
> +        s->control[i] = AW_A10_PIT_DEFAULT_CLOCK;
> +        s->interval[i] = 0;
> +        s->count[i] = 0;
> +        ptimer_stop(s->timer[i]);
> +    }
> +    s->watch_dog_mode = 0;
> +    s->watch_dog_control = 0;
> +    s->count_lo = 0;
> +    s->count_hi = 0;
> +    s->count_ctl = 0;
> +}
> +
> +static void a10_pit_timer_cb(void *opaque)
> +{
> +    AwA10PITState *s = AW_A10_PIT(opaque);
> +    uint8_t i;
> +
> +    for (i = 0; i < AW_A10_PIT_TIMER_NR; i++) {
> +        if (s->control[i] & AW_A10_PIT_TIMER_EN) {
> +            s->irq_status |= 1 << i;
> +            if (s->control[i] & AW_A10_PIT_TIMER_MODE) {
> +                ptimer_stop(s->timer[i]);
> +                s->control[i] &= ~AW_A10_PIT_TIMER_EN;
> +            }
> +            qemu_irq_pulse(s->irq[i]);
> +        }
> +    }
> +}
> +
> +static void a10_pit_realize(DeviceState *dev, Error **errp)
> +{
> +    AwA10PITState *s = AW_A10_PIT(dev);
> +    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> +    QEMUBH * bh[AW_A10_PIT_TIMER_NR];
> +    uint8_t i;
> +
> +    for (i = 0; i < AW_A10_PIT_TIMER_NR; i++) {
> +        sysbus_init_irq(sbd, &s->irq[i]);
> +    }
> +    memory_region_init_io(&s->iomem, OBJECT(s), &a10_pit_ops, s,
> +                          TYPE_AW_A10_PIT, 0x400);
> +    sysbus_init_mmio(sbd, &s->iomem);
> +
> +    for (i = 0; i < AW_A10_PIT_TIMER_NR; i++) {
> +        bh[i] = qemu_bh_new(a10_pit_timer_cb, s);
> +        s->timer[i] = ptimer_init(bh[i]);
> +        ptimer_set_freq(s->timer[i], 240000);
> +    }
> +}
> +
> +static void a10_pit_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc  = DEVICE_CLASS(klass);
> +
> +    dc->realize = a10_pit_realize;
> +    dc->reset = a10_pit_reset;
> +    dc->desc = "allwinner a10 timer";
> +    dc->vmsd = &vmstate_a10_pit;
> +}
> +
> +static const TypeInfo a10_pit_info = {
> +    .name = TYPE_AW_A10_PIT,
> +    .parent = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(AwA10PITState),
> +    .class_init = a10_pit_class_init,
> +};
> +
> +static void a10_register_types(void)
> +{
> +    type_register_static(&a10_pit_info);
> +}
> +
> +type_init(a10_register_types);
> diff --git a/include/hw/timer/allwinner-a10-pit.h b/include/hw/timer/allwinner-a10-pit.h
> new file mode 100644
> index 0000000..329c05c
> --- /dev/null
> +++ b/include/hw/timer/allwinner-a10-pit.h
> @@ -0,0 +1,57 @@
> +#ifndef AW_A10_PIT_H
> +#define AW_A10_PIT_H
> +
> +#include "hw/ptimer.h"
> +
> +#define TYPE_AW_A10_PIT "Allwinner-A10-timer"
> +#define AW_A10_PIT(obj) OBJECT_CHECK(AwA10PITState, (obj), TYPE_AW_A10_PIT)
> +
> +#define AW_A10_PIT_TIMER_NR    6
> +#define AW_A10_PIT_TIMER_IRQ   0x1
> +#define AW_A10_PIT_WDOG_IRQ    0x100
> +
> +#define AW_A10_PIT_TIMER_IRQ_EN    0
> +#define AW_A10_PIT_TIMER_IRQ_ST    0x4
> +
> +#define AW_A10_PIT_TIMER_CONTROL   0x0
> +#define AW_A10_PIT_TIMER_EN        0x1
> +#define AW_A10_PIT_TIMER_RELOAD    0x2
> +#define AW_A10_PIT_TIMER_MODE      0x80
> +
> +#define AW_A10_PIT_TIMER_INTERVAL  0x4
> +#define AW_A10_PIT_TIMER_COUNT     0x8
> +#define AW_A10_PIT_WDOG_CONTROL    0x90
> +#define AW_A10_PIT_WDOG_MODE       0x94
> +
> +#define AW_A10_PIT_COUNT_CTL       0xa0
> +#define AW_A10_PIT_COUNT_RL_EN     0x2
> +#define AW_A10_PIT_COUNT_CLR_EN    0x1
> +#define AW_A10_PIT_COUNT_LO        0xa4
> +#define AW_A10_PIT_COUNT_HI        0xa8
> +
> +#define AW_A10_PIT_TIMER_BASE      0x10
> +
> +#define AW_A10_PIT_DEFAULT_CLOCK   0x4
> +
> +typedef struct AwA10PITState {
> +    /*< private >*/
> +    SysBusDevice parent_obj;
> +    /*< public >*/
> +    qemu_irq irq[AW_A10_PIT_TIMER_NR];
> +    ptimer_state *timer[AW_A10_PIT_TIMER_NR];
> +    MemoryRegion iomem;
> +
> +    uint32_t  irq_enable;
> +    uint32_t irq_status;
> +    uint32_t control[AW_A10_PIT_TIMER_NR];
> +    uint32_t interval[AW_A10_PIT_TIMER_NR];
> +    uint32_t count[AW_A10_PIT_TIMER_NR];
> +    uint32_t watch_dog_mode;
> +    uint32_t watch_dog_control;
> +    uint32_t count_lo;
> +    uint32_t count_hi;
> +    uint32_t count_ctl;
> +} AwA10PITState;
> +
> +#endif
> +
> --
> 1.7.2.5
>
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [PATCH v8 2/5] hw/timer: add allwinner a10 timer
  2013-12-05  1:28   ` Peter Crosthwaite
@ 2013-12-05  1:51     ` Li Guang
  0 siblings, 0 replies; 10+ messages in thread
From: Li Guang @ 2013-12-05  1:51 UTC (permalink / raw)
  To: Peter Crosthwaite
  Cc: Peter Maydell, qemu-devel@nongnu.org Developers,
	Andreas Färber

Peter Crosthwaite wrote:
> On Wed, Dec 4, 2013 at 6:09 PM, liguang<lig.fnst@cn.fujitsu.com>  wrote:
>    
>> Signed-off-by: liguang<lig.fnst@cn.fujitsu.com>
>> ---
>>   default-configs/arm-softmmu.mak      |    2 +
>>   hw/timer/Makefile.objs               |    2 +
>>   hw/timer/allwinner-a10-pit.c         |  253 ++++++++++++++++++++++++++++++++++
>>   include/hw/timer/allwinner-a10-pit.h |   57 ++++++++
>>   4 files changed, 314 insertions(+), 0 deletions(-)
>>   create mode 100644 hw/timer/allwinner-a10-pit.c
>>   create mode 100644 include/hw/timer/allwinner-a10-pit.h
>>
>> diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
>> index a555eef..0029596 100644
>> --- a/default-configs/arm-softmmu.mak
>> +++ b/default-configs/arm-softmmu.mak
>> @@ -81,3 +81,5 @@ CONFIG_VERSATILE_I2C=y
>>
>>   CONFIG_SDHCI=y
>>   CONFIG_INTEGRATOR_DEBUG=y
>> +
>> +CONFIG_ALLWINNER_A10=y
>> diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
>> index eca5905..3020388 100644
>> --- a/hw/timer/Makefile.objs
>> +++ b/hw/timer/Makefile.objs
>> @@ -27,3 +27,5 @@ obj-$(CONFIG_SH4) += sh_timer.o
>>   obj-$(CONFIG_TUSB6010) += tusb6010.o
>>
>>   obj-$(CONFIG_MC146818RTC) += mc146818rtc.o
>> +
>> +obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10-pit.o
>> diff --git a/hw/timer/allwinner-a10-pit.c b/hw/timer/allwinner-a10-pit.c
>> new file mode 100644
>> index 0000000..2305813
>> --- /dev/null
>> +++ b/hw/timer/allwinner-a10-pit.c
>> @@ -0,0 +1,253 @@
>> +/*
>> + * Allwinner A10 timer device emulation
>> + *
>> + * Copyright (C) 2013 Li Guang
>> + * Written by Li Guang<lig.fnst@cn.fujitsu.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify it
>> + * under the terms of the GNU General Public License as published by the
>> + * Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that 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.
>> + */
>> +
>> +#include "hw/sysbus.h"
>> +#include "sysemu/sysemu.h"
>> +#include "hw/timer/allwinner-a10-pit.h"
>> +
>> +
>>      
> Not sure of the motivation for extra blank lines.
>
>    

can strip

>> +static uint64_t a10_pit_read(void *opaque, hwaddr offset, unsigned size)
>> +{
>> +    AwA10PITState *s = AW_A10_PIT(opaque);
>> +    uint8_t index;
>> +
>> +    switch (offset) {
>> +    case AW_A10_PIT_TIMER_IRQ_EN:
>> +        return s->irq_enable;
>> +    case AW_A10_PIT_TIMER_IRQ_ST:
>> +        return s->irq_status;
>> +    case AW_A10_PIT_TIMER_BASE ... AW_A10_PIT_TIMER_BASE * 6 + AW_A10_PIT_TIMER_COUNT:
>>      
> It's strange to me that AW_A10_PIT_TIMER_BASE is used as both an
> offset and a stride. It's only co-incidence that 0x10 is both the
> offset of the first timers' individual registers as well as the diff
> between timer register offsets. I think you could just simplify by
> putting it all in the header, something like:
>
> #define AW_A10_PIT_TIMER_BASE_END (AW_A10_PIT_TIMER_BASE * 6 + 0x10).
>
>    

good suggestion!

>> +        index = offset&  0xf0;
>> +        index>>= 4;
>> +        index -= 1;
>> +        switch (offset&  0x0f) {
>> +        case AW_A10_PIT_TIMER_CONTROL:
>> +            return s->control[index];
>> +        case AW_A10_PIT_TIMER_INTERVAL:
>> +            return s->interval[index];
>> +        case AW_A10_PIT_TIMER_COUNT:
>> +            s->count[index] = ptimer_get_count(s->timer[index]);
>> +            return s->count[index];
>> +        default:
>> +            qemu_log_mask(LOG_GUEST_ERROR,
>> +                          "%s: Bad offset 0x%x\n",  __func__, (int)offset);
>> +            break;
>> +        }
>> +    case AW_A10_PIT_WDOG_CONTROL:
>> +        break;
>> +    case AW_A10_PIT_WDOG_MODE:
>> +        break;
>> +    case AW_A10_PIT_COUNT_LO:
>> +        return s->count_lo;
>> +    case AW_A10_PIT_COUNT_HI:
>> +        return s->count_hi;
>> +    case AW_A10_PIT_COUNT_CTL:
>> +        return s->count_ctl;
>> +    default:
>> +        qemu_log_mask(LOG_GUEST_ERROR,
>> +                      "%s: Bad offset 0x%x\n",  __func__, (int)offset);
>> +        break;
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>> +static void a10_pit_write(void *opaque, hwaddr offset, uint64_t value,
>> +                            unsigned size)
>> +{
>> +     AwA10PITState *s = AW_A10_PIT(opaque);
>> +     uint8_t index;
>> +
>> +    switch (offset) {
>> +    case AW_A10_PIT_TIMER_IRQ_EN:
>> +        s->irq_enable = value;
>> +        break;
>> +    case AW_A10_PIT_TIMER_IRQ_ST:
>> +        s->irq_status&= ~value;
>> +        break;
>> +    case AW_A10_PIT_TIMER_BASE ... AW_A10_PIT_TIMER_BASE * 6 + AW_A10_PIT_TIMER_COUNT:
>> +        index = offset&  0xf0;
>> +        index>>= 4;
>> +        index -= 1;
>> +        switch (offset&  0x0f) {
>> +        case AW_A10_PIT_TIMER_CONTROL:
>> +            s->control[index] = value;
>> +            if (s->control[index]&  AW_A10_PIT_TIMER_RELOAD) {
>> +                ptimer_set_count(s->timer[index], s->interval[index]);
>> +            }
>> +            if (s->control[index]&  AW_A10_PIT_TIMER_EN) {
>> +                int oneshot = 0;
>> +                if (s->control[index]&  AW_A10_PIT_TIMER_MODE) {
>> +                    oneshot = 1;
>> +                }
>> +                ptimer_run(s->timer[index], oneshot);
>> +            } else {
>> +                ptimer_stop(s->timer[index]);
>> +            }
>> +            break;
>> +        case AW_A10_PIT_TIMER_INTERVAL:
>> +            s->interval[index] = value;
>> +            ptimer_set_limit(s->timer[index], s->interval[index], 1);
>> +            break;
>> +        case AW_A10_PIT_TIMER_COUNT:
>> +            s->count[index] = value;
>> +            break;
>> +        default:
>> +            qemu_log_mask(LOG_GUEST_ERROR,
>> +                          "%s: Bad offset 0x%x\n",  __func__, (int)offset);
>> +        }
>> +        break;
>> +    case AW_A10_PIT_WDOG_CONTROL:
>> +        s->watch_dog_control = value;
>> +        break;
>> +    case AW_A10_PIT_WDOG_MODE:
>> +        s->watch_dog_mode = value;
>> +        break;
>> +    case AW_A10_PIT_COUNT_LO:
>> +        s->count_lo = value;
>> +        break;
>> +    case AW_A10_PIT_COUNT_HI:
>> +        s->count_hi = value;
>> +        break;
>> +    case AW_A10_PIT_COUNT_CTL:
>> +        s->count_ctl = value;
>> +        if (s->count_ctl&  AW_A10_PIT_COUNT_RL_EN) {
>> +            s->count_lo = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
>> +            s->count_hi = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)>>  32;
>>      
> Sorry for not spotting this one earlier (i'm going full line by line
> now), but you should just do the one call to qemu_clock_get_ns
> (capture to local variable).
>
>    

OK

> Whats probably cleanest is to implement s->count as uint64_t and just
> use deposit64/extract64 in MMIO read/write fns. Saves about 5 LOC and
> is a little more self documenting.
>
> You counter is also implicitly 1GHz right? that's probably worth a comment.
>
>    
currently it is fixed.

> Regards,
> Peter
>
> PS. You are still re-spinning very fast. Can I suggest 24hr as a
> minimum wait to give other reviewers a chance? That gives all the
> global timezones a chance to participate. I did a high level review of
> one of your new patches last night at home, but I haven't had a chance
> to look at this properly till this morning (at work) yet you have
> already respun on me. Persoanally, I'm going for 48h respins atm.
>
>    

OK.

Thanks!
Li Guang
>> +            s->count_ctl&= ~AW_A10_PIT_COUNT_RL_EN;
>> +        }
>> +        if (s->count_ctl&  AW_A10_PIT_COUNT_CLR_EN) {
>> +            s->count_lo = 0;
>> +            s->count_hi = 0;
>> +            s->count_ctl&= ~AW_A10_PIT_COUNT_CLR_EN;
>> +        }
>> +        break;
>> +    default:
>> +        qemu_log_mask(LOG_GUEST_ERROR,
>> +                      "%s: Bad offset 0x%x\n",  __func__, (int)offset);
>> +        break;
>> +    }
>> +}
>> +
>> +static const MemoryRegionOps a10_pit_ops = {
>> +    .read = a10_pit_read,
>> +    .write = a10_pit_write,
>> +    .endianness = DEVICE_NATIVE_ENDIAN,
>> +};
>> +
>> +static const VMStateDescription vmstate_a10_pit = {
>> +    .name = "a10.pit",
>> +    .version_id = 1,
>> +    .minimum_version_id = 1,
>> +    .minimum_version_id_old = 1,
>> +    .fields = (VMStateField[]) {
>> +        VMSTATE_UINT32(irq_enable, AwA10PITState),
>> +        VMSTATE_UINT32(irq_status, AwA10PITState),
>> +        VMSTATE_UINT32_ARRAY(control, AwA10PITState, AW_A10_PIT_TIMER_NR),
>> +        VMSTATE_UINT32_ARRAY(interval, AwA10PITState, AW_A10_PIT_TIMER_NR),
>> +        VMSTATE_UINT32_ARRAY(count, AwA10PITState, AW_A10_PIT_TIMER_NR),
>> +        VMSTATE_UINT32(watch_dog_mode, AwA10PITState),
>> +        VMSTATE_UINT32(watch_dog_control, AwA10PITState),
>> +        VMSTATE_UINT32(count_lo, AwA10PITState),
>> +        VMSTATE_UINT32(count_hi, AwA10PITState),
>> +        VMSTATE_UINT32(count_ctl, AwA10PITState),
>> +        VMSTATE_PTIMER_ARRAY(timer, AwA10PITState, AW_A10_PIT_TIMER_NR),
>> +        VMSTATE_END_OF_LIST()
>> +    }
>> +};
>> +
>> +static void a10_pit_reset(DeviceState *dev)
>> +{
>> +    AwA10PITState *s = AW_A10_PIT(dev);
>> +    uint8_t i;
>> +
>> +    s->irq_enable = 0;
>> +    s->irq_status = 0;
>> +    for (i = 0; i<  6; i++) {
>> +        s->control[i] = AW_A10_PIT_DEFAULT_CLOCK;
>> +        s->interval[i] = 0;
>> +        s->count[i] = 0;
>> +        ptimer_stop(s->timer[i]);
>> +    }
>> +    s->watch_dog_mode = 0;
>> +    s->watch_dog_control = 0;
>> +    s->count_lo = 0;
>> +    s->count_hi = 0;
>> +    s->count_ctl = 0;
>> +}
>> +
>> +static void a10_pit_timer_cb(void *opaque)
>> +{
>> +    AwA10PITState *s = AW_A10_PIT(opaque);
>> +    uint8_t i;
>> +
>> +    for (i = 0; i<  AW_A10_PIT_TIMER_NR; i++) {
>> +        if (s->control[i]&  AW_A10_PIT_TIMER_EN) {
>> +            s->irq_status |= 1<<  i;
>> +            if (s->control[i]&  AW_A10_PIT_TIMER_MODE) {
>> +                ptimer_stop(s->timer[i]);
>> +                s->control[i]&= ~AW_A10_PIT_TIMER_EN;
>> +            }
>> +            qemu_irq_pulse(s->irq[i]);
>> +        }
>> +    }
>> +}
>> +
>> +static void a10_pit_realize(DeviceState *dev, Error **errp)
>> +{
>> +    AwA10PITState *s = AW_A10_PIT(dev);
>> +    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
>> +    QEMUBH * bh[AW_A10_PIT_TIMER_NR];
>> +    uint8_t i;
>> +
>> +    for (i = 0; i<  AW_A10_PIT_TIMER_NR; i++) {
>> +        sysbus_init_irq(sbd,&s->irq[i]);
>> +    }
>> +    memory_region_init_io(&s->iomem, OBJECT(s),&a10_pit_ops, s,
>> +                          TYPE_AW_A10_PIT, 0x400);
>> +    sysbus_init_mmio(sbd,&s->iomem);
>> +
>> +    for (i = 0; i<  AW_A10_PIT_TIMER_NR; i++) {
>> +        bh[i] = qemu_bh_new(a10_pit_timer_cb, s);
>> +        s->timer[i] = ptimer_init(bh[i]);
>> +        ptimer_set_freq(s->timer[i], 240000);
>> +    }
>> +}
>> +
>> +static void a10_pit_class_init(ObjectClass *klass, void *data)
>> +{
>> +    DeviceClass *dc  = DEVICE_CLASS(klass);
>> +
>> +    dc->realize = a10_pit_realize;
>> +    dc->reset = a10_pit_reset;
>> +    dc->desc = "allwinner a10 timer";
>> +    dc->vmsd =&vmstate_a10_pit;
>> +}
>> +
>> +static const TypeInfo a10_pit_info = {
>> +    .name = TYPE_AW_A10_PIT,
>> +    .parent = TYPE_SYS_BUS_DEVICE,
>> +    .instance_size = sizeof(AwA10PITState),
>> +    .class_init = a10_pit_class_init,
>> +};
>> +
>> +static void a10_register_types(void)
>> +{
>> +    type_register_static(&a10_pit_info);
>> +}
>> +
>> +type_init(a10_register_types);
>> diff --git a/include/hw/timer/allwinner-a10-pit.h b/include/hw/timer/allwinner-a10-pit.h
>> new file mode 100644
>> index 0000000..329c05c
>> --- /dev/null
>> +++ b/include/hw/timer/allwinner-a10-pit.h
>> @@ -0,0 +1,57 @@
>> +#ifndef AW_A10_PIT_H
>> +#define AW_A10_PIT_H
>> +
>> +#include "hw/ptimer.h"
>> +
>> +#define TYPE_AW_A10_PIT "Allwinner-A10-timer"
>> +#define AW_A10_PIT(obj) OBJECT_CHECK(AwA10PITState, (obj), TYPE_AW_A10_PIT)
>> +
>> +#define AW_A10_PIT_TIMER_NR    6
>> +#define AW_A10_PIT_TIMER_IRQ   0x1
>> +#define AW_A10_PIT_WDOG_IRQ    0x100
>> +
>> +#define AW_A10_PIT_TIMER_IRQ_EN    0
>> +#define AW_A10_PIT_TIMER_IRQ_ST    0x4
>> +
>> +#define AW_A10_PIT_TIMER_CONTROL   0x0
>> +#define AW_A10_PIT_TIMER_EN        0x1
>> +#define AW_A10_PIT_TIMER_RELOAD    0x2
>> +#define AW_A10_PIT_TIMER_MODE      0x80
>> +
>> +#define AW_A10_PIT_TIMER_INTERVAL  0x4
>> +#define AW_A10_PIT_TIMER_COUNT     0x8
>> +#define AW_A10_PIT_WDOG_CONTROL    0x90
>> +#define AW_A10_PIT_WDOG_MODE       0x94
>> +
>> +#define AW_A10_PIT_COUNT_CTL       0xa0
>> +#define AW_A10_PIT_COUNT_RL_EN     0x2
>> +#define AW_A10_PIT_COUNT_CLR_EN    0x1
>> +#define AW_A10_PIT_COUNT_LO        0xa4
>> +#define AW_A10_PIT_COUNT_HI        0xa8
>> +
>> +#define AW_A10_PIT_TIMER_BASE      0x10
>> +
>> +#define AW_A10_PIT_DEFAULT_CLOCK   0x4
>> +
>> +typedef struct AwA10PITState {
>> +    /*<  private>*/
>> +    SysBusDevice parent_obj;
>> +    /*<  public>*/
>> +    qemu_irq irq[AW_A10_PIT_TIMER_NR];
>> +    ptimer_state *timer[AW_A10_PIT_TIMER_NR];
>> +    MemoryRegion iomem;
>> +
>> +    uint32_t  irq_enable;
>> +    uint32_t irq_status;
>> +    uint32_t control[AW_A10_PIT_TIMER_NR];
>> +    uint32_t interval[AW_A10_PIT_TIMER_NR];
>> +    uint32_t count[AW_A10_PIT_TIMER_NR];
>> +    uint32_t watch_dog_mode;
>> +    uint32_t watch_dog_control;
>> +    uint32_t count_lo;
>> +    uint32_t count_hi;
>> +    uint32_t count_ctl;
>> +} AwA10PITState;
>> +
>> +#endif
>> +
>> --
>> 1.7.2.5
>>
>>
>>      
>    

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2013-12-05  1:53 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-12-04  8:09 [Qemu-devel] [PATCH v8 0/5] add allwinner A10 SoC support liguang
2013-12-04  8:09 ` [Qemu-devel] [PATCH v8 1/5] vmstate: add VMSTATE_PTIMER_ARRAY liguang
2013-12-04  8:09 ` [Qemu-devel] [PATCH v8 2/5] hw/timer: add allwinner a10 timer liguang
2013-12-05  1:28   ` Peter Crosthwaite
2013-12-05  1:51     ` Li Guang
2013-12-04  8:09 ` [Qemu-devel] [PATCH v8 3/5] hw/intc: add allwinner A10 interrupt controller liguang
2013-12-04  8:09 ` [Qemu-devel] [PATCH v8 4/5] hw/arm: add allwinner a10 SoC support liguang
2013-12-04 11:32   ` Peter Crosthwaite
2013-12-05  0:21     ` Li Guang
2013-12-04  8:09 ` [Qemu-devel] [PATCH v8 5/5] hw/arm: add cubieboard support liguang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.