qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/5] add allwinner A10 SoC support
@ 2013-12-03  9:11 liguang
  2013-12-03  9:11 ` [Qemu-devel] [PATCH 1/5] vmstate: add VMSTATE_PTIMER_ARRAY liguang
                   ` (4 more replies)
  0 siblings, 5 replies; 14+ messages in thread
From: liguang @ 2013-12-03  9:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Peter Crosthwaite, Andreas Färber, liguang


add support 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.


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] 14+ messages in thread

* [Qemu-devel] [PATCH 1/5] vmstate: add VMSTATE_PTIMER_ARRAY
  2013-12-03  9:11 [Qemu-devel] [PATCH 0/5] add allwinner A10 SoC support liguang
@ 2013-12-03  9:11 ` liguang
  2013-12-03  9:11 ` [Qemu-devel] [PATCH 2/5] hw/timer: add allwinner a10 timer liguang
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 14+ messages in thread
From: liguang @ 2013-12-03  9:11 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] 14+ messages in thread

* [Qemu-devel] [PATCH 2/5] hw/timer: add allwinner a10 timer
  2013-12-03  9:11 [Qemu-devel] [PATCH 0/5] add allwinner A10 SoC support liguang
  2013-12-03  9:11 ` [Qemu-devel] [PATCH 1/5] vmstate: add VMSTATE_PTIMER_ARRAY liguang
@ 2013-12-03  9:11 ` liguang
  2013-12-03 11:36   ` Peter Crosthwaite
  2013-12-03  9:11 ` [Qemu-devel] [PATCH 3/5] hw/intc: add allwinner A10 interrupt controller liguang
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 14+ messages in thread
From: liguang @ 2013-12-03  9:11 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..4ff2e1f 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..2f9b458
--- /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)
+{
+    A10PITState *s = A10_PIT(opaque);
+    uint8_t index;
+
+    switch (offset) {
+    case A10PIT_TIMER_IRQ_EN:
+        return s->irq_enable;
+    case A10PIT_TIMER_IRQ_ST:
+        return s->irq_status;
+    case A10PIT_TIMER_BASE ...  A10PIT_TIMER_BASE * 6 + A10PIT_TIMER_COUNT:
+        index = offset & 0xf0;
+        index >>= 4;
+        index -= 1;
+        switch (offset & 0x0f) {
+        case A10PIT_TIMER_CONTROL:
+            return s->control[index];
+        case A10PIT_TIMER_INTERVAL:
+            return s->interval[index];
+        case A10PIT_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 A10PIT_WDOG_CONTROL:
+        break;
+    case A10PIT_WDOG_MODE:
+        break;
+    case A10PIT_COUNT_LO:
+        return s->count_lo;
+    case A10PIT_COUNT_HI:
+        return s->count_hi;
+    case A10PIT_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)
+{
+     A10PITState *s = A10_PIT(opaque);
+     uint8_t index;
+
+    switch (offset) {
+    case A10PIT_TIMER_IRQ_EN:
+        s->irq_enable = value;
+        break;
+    case A10PIT_TIMER_IRQ_ST:
+        s->irq_status &= ~value;
+        break;
+    case A10PIT_TIMER_BASE ...  A10PIT_TIMER_BASE * 6 + A10PIT_TIMER_COUNT:
+        index = offset & 0xf0;
+        index >>= 4;
+        index -= 1;
+        switch (offset & 0x0f) {
+        case A10PIT_TIMER_CONTROL:
+            s->control[index] = value;
+            if (s->control[index] & A10PIT_TIMER_RELOAD) {
+                ptimer_set_count(s->timer[index], s->interval[index]);
+            }
+            if (s->control[index] & A10PIT_TIMER_EN) {
+                ptimer_run(s->timer[index], 1);
+            } else {
+                ptimer_stop(s->timer[index]);
+            }
+            break;
+        case A10PIT_TIMER_INTERVAL:
+            s->interval[index] = value;
+            ptimer_set_count(s->timer[index], s->interval[index]);
+            break;
+        case A10PIT_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 A10PIT_WDOG_CONTROL:
+        s->watch_dog_control = value;
+        break;
+    case A10PIT_WDOG_MODE:
+        s->watch_dog_mode = value;
+        break;
+    case A10PIT_COUNT_LO:
+        s->count_lo = value;
+        break;
+    case A10PIT_COUNT_HI:
+        s->count_hi = value;
+        break;
+    case A10PIT_COUNT_CTL:
+        s->count_ctl = value;
+        if (s->count_ctl & A10PIT_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 &= ~A10PIT_COUNT_RL_EN;
+        }
+        if (s->count_ctl & A10PIT_COUNT_CLR_EN) {
+            s->count_lo = 0;
+            s->count_hi = 0;
+            s->count_ctl &= ~A10PIT_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, A10PITState),
+        VMSTATE_UINT32(irq_status, A10PITState),
+        VMSTATE_UINT32_ARRAY(control, A10PITState, A10PIT_TIMER_NR),
+        VMSTATE_UINT32_ARRAY(interval, A10PITState, A10PIT_TIMER_NR),
+        VMSTATE_UINT32_ARRAY(count, A10PITState, A10PIT_TIMER_NR),
+        VMSTATE_UINT32(watch_dog_mode, A10PITState),
+        VMSTATE_UINT32(watch_dog_control, A10PITState),
+        VMSTATE_UINT32(count_lo, A10PITState),
+        VMSTATE_UINT32(count_hi, A10PITState),
+        VMSTATE_UINT32(count_ctl, A10PITState),
+        VMSTATE_PTIMER_ARRAY(timer, A10PITState, A10PIT_TIMER_NR),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void a10_pit_reset(DeviceState *dev)
+{
+    A10PITState *s = A10_PIT(dev);
+    uint8_t i;
+
+    s->irq_enable = 0;
+    s->irq_status = 0;
+    for (i = 0; i < 6; i++) {
+        s->control[i] = A10PIT_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)
+{
+    A10PITState *s = A10_PIT(opaque);
+    uint8_t i;
+
+    for (i = 0; i < A10PIT_TIMER_NR; i++) {
+        if (s->control[i] & A10PIT_TIMER_EN &&
+            ptimer_get_count(s->timer[i]) == 0) {
+            s->irq_status |= 1 << i;
+            if (!(s->control[i] & A10PIT_TIMER_MODE)) {
+                ptimer_set_count(s->timer[i], s->interval[i]);
+                ptimer_run(s->timer[i], 1);
+                s->control[i] |= A10PIT_TIMER_EN;
+            } else {
+                s->control[i] &= ~A10PIT_TIMER_EN;
+            }
+            qemu_irq_pulse(s->irq[i]);
+        }
+    }
+}
+
+static void a10_pit_realize(DeviceState *dev, Error **errp)
+{
+    A10PITState *s = A10_PIT(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+    QEMUBH * bh[A10PIT_TIMER_NR];
+    uint8_t i;
+
+    for (i = 0; i < A10PIT_TIMER_NR; i++) {
+        sysbus_init_irq(sbd, &s->irq[i]);
+    }
+    memory_region_init_io(&s->iomem, OBJECT(s), &a10_pit_ops, s,
+                          TYPE_A10_PIT, 0x400);
+    sysbus_init_mmio(sbd, &s->iomem);
+
+    for (i = 0; i < A10PIT_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_A10_PIT,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(A10PITState),
+    .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..e061cc2
--- /dev/null
+++ b/include/hw/timer/allwinner-a10_pit.h
@@ -0,0 +1,57 @@
+#ifndef A10_PIT_H
+#define A10_PIT_H
+
+#include "hw/ptimer.h"
+
+#define TYPE_A10_PIT "a10-timer"
+#define A10_PIT(obj) OBJECT_CHECK(A10PITState, (obj), TYPE_A10_PIT)
+
+#define A10PIT_TIMER_NR	6
+#define A10PIT_TIMER_IRQ	0x1
+#define A10PIT_WDOG_IRQ	0x100
+
+#define A10PIT_TIMER_IRQ_EN	0
+#define A10PIT_TIMER_IRQ_ST	0x4
+
+#define A10PIT_TIMER_CONTROL	0x0
+#define A10PIT_TIMER_EN	0x1
+#define A10PIT_TIMER_RELOAD	0x2
+#define A10PIT_TIMER_MODE	0x80
+
+#define A10PIT_TIMER_INTERVAL	0x4
+#define A10PIT_TIMER_COUNT		0x8
+#define A10PIT_WDOG_CONTROL		0x90
+#define A10PIT_WDOG_MODE		0x94
+
+#define A10PIT_COUNT_CTL		0xa0
+#define A10PIT_COUNT_RL_EN		0x2
+#define A10PIT_COUNT_CLR_EN		0x1
+#define A10PIT_COUNT_LO		0xa4
+#define A10PIT_COUNT_HI		0xa8
+
+#define A10PIT_TIMER_BASE		0x10
+
+#define A10PIT_DEFAULT_CLOCK		0x4
+
+typedef struct A10PITState {
+    /*< private >*/
+    SysBusDevice parent_obj;
+    /*< public >*/
+    qemu_irq irq[A10PIT_TIMER_NR];
+    ptimer_state *timer[A10PIT_TIMER_NR];
+    MemoryRegion iomem;
+
+    uint32_t  irq_enable;
+    uint32_t irq_status;
+    uint32_t control[A10PIT_TIMER_NR];
+    uint32_t interval[A10PIT_TIMER_NR];
+    uint32_t count[A10PIT_TIMER_NR];
+    uint32_t watch_dog_mode;
+    uint32_t watch_dog_control;
+    uint32_t count_lo;
+    uint32_t count_hi;
+    uint32_t count_ctl;
+} A10PITState;
+
+#endif
+
-- 
1.7.2.5

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

* [Qemu-devel] [PATCH 3/5] hw/intc: add allwinner A10 interrupt controller
  2013-12-03  9:11 [Qemu-devel] [PATCH 0/5] add allwinner A10 SoC support liguang
  2013-12-03  9:11 ` [Qemu-devel] [PATCH 1/5] vmstate: add VMSTATE_PTIMER_ARRAY liguang
  2013-12-03  9:11 ` [Qemu-devel] [PATCH 2/5] hw/timer: add allwinner a10 timer liguang
@ 2013-12-03  9:11 ` liguang
  2013-12-03  9:11 ` [Qemu-devel] [PATCH 4/5] hw/arm: add allwinner a10 SoC support liguang
  2013-12-03  9:11 ` [Qemu-devel] [PATCH 5/5] hw/arm: add cubieboard support liguang
  4 siblings, 0 replies; 14+ messages in thread
From: liguang @ 2013-12-03  9:11 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..65572d3 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..e9322ee
--- /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 a10_pic_update(A10PICState *s)
+{
+    uint8_t i, j;
+    bool irq = false, fiq = false;
+
+    for (i = 0, j = 0; i < 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 a10_pic_set_irq(void *opaque, int irq, int level)
+{
+    A10PICState *s = opaque;
+
+    if (level) {
+        set_bit(irq%32, (void *)&s->irq_pending[irq/32]);
+    }
+    a10_pic_update(s);
+}
+
+static uint64_t a10_pic_read(void *opaque, hwaddr offset, unsigned size)
+{
+    A10PICState *s = opaque;
+    uint8_t index = (offset & 0xc)/4;
+
+    switch (offset) {
+    case A10_PIC_VECTOR:
+        return s->vector;
+    case A10_PIC_BASE_ADDR:
+        return s->base_addr;
+    case A10_PIC_PROTECT:
+        return s->protect;
+    case A10_PIC_NMI:
+        return s->nmi;
+    case A10_PIC_IRQ_PENDING ... A10_PIC_IRQ_PENDING + 8:
+        return s->irq_pending[index];
+    case A10_PIC_FIQ_PENDING ... A10_PIC_FIQ_PENDING + 8:
+        return s->fiq_pending[index];
+    case A10_PIC_SELECT ... A10_PIC_SELECT + 8:
+        return s->select[index];
+    case A10_PIC_ENABLE ... A10_PIC_ENABLE + 8:
+        return s->enable[index];
+    case A10_PIC_MASK ... 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 a10_pic_write(void *opaque, hwaddr offset, uint64_t value,
+                             unsigned size)
+{
+    A10PICState *s = opaque;
+    uint8_t index = (offset & 0xc)/4;
+
+    switch (offset) {
+    case A10_PIC_VECTOR:
+        s->vector = value & ~0x3;
+        break;
+    case A10_PIC_BASE_ADDR:
+        s->base_addr = value & ~0x3;
+    case A10_PIC_PROTECT:
+        s->protect = value;
+        break;
+    case A10_PIC_NMI:
+        s->nmi = value;
+        break;
+    case A10_PIC_IRQ_PENDING ... A10_PIC_IRQ_PENDING + 8:
+        s->irq_pending[index] &= ~value;
+        break;
+    case A10_PIC_FIQ_PENDING ... A10_PIC_FIQ_PENDING + 8:
+        s->fiq_pending[index] &= ~value;
+        break;
+    case A10_PIC_SELECT ... A10_PIC_SELECT + 8:
+        s->select[index] = value;
+        break;
+    case A10_PIC_ENABLE ... A10_PIC_ENABLE + 8:
+        s->enable[index] = value;
+        break;
+    case A10_PIC_MASK ... 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;
+    }
+
+    a10_pic_update(s);
+}
+
+static const MemoryRegionOps a10_pic_ops = {
+    .read = a10_pic_read,
+    .write = a10_pic_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const VMStateDescription vmstate_a10_pic = {
+    .name = "a10.pic",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(vector, A10PICState),
+        VMSTATE_UINT32(base_addr, A10PICState),
+        VMSTATE_UINT32(protect, A10PICState),
+        VMSTATE_UINT32(nmi, A10PICState),
+        VMSTATE_UINT32_ARRAY(irq_pending, A10PICState, A10_PIC_REG_NUM),
+        VMSTATE_UINT32_ARRAY(fiq_pending, A10PICState, A10_PIC_REG_NUM),
+        VMSTATE_UINT32_ARRAY(enable, A10PICState, A10_PIC_REG_NUM),
+        VMSTATE_UINT32_ARRAY(select, A10PICState, A10_PIC_REG_NUM),
+        VMSTATE_UINT32_ARRAY(mask, A10PICState, A10_PIC_REG_NUM),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void a10_pic_realize(DeviceState *ds, Error **errp)
+{
+    A10PICState *s = A10_PIC(ds);
+    SysBusDevice *dev = SYS_BUS_DEVICE(ds);
+
+     qdev_init_gpio_in(DEVICE(dev), a10_pic_set_irq, 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), &a10_pic_ops, s,
+                           "a10-pic", 0x400);
+     sysbus_init_mmio(dev, &s->iomem);
+}
+
+static void a10_pic_reset(DeviceState *d)
+{
+    A10PICState *s = A10_PIC(d);
+    uint8_t i;
+
+    s->base_addr = 0;
+    s->protect = 0;
+    s->nmi = 0;
+    s->vector = 0;
+    for (i = 0; i < 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 a10_pic_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = a10_pic_realize;
+    dc->reset = a10_pic_reset;
+    dc->desc = "A10 pic";
+    dc->vmsd = &vmstate_a10_pic;
+ }
+
+static const TypeInfo a10_pic_info = {
+    .name = TYPE_A10_PIC,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(A10PICState),
+    .class_init = a10_pic_class_init,
+};
+
+static void a10_register_types(void)
+{
+    type_register_static(&a10_pic_info);
+}
+
+type_init(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..9fd624b
--- /dev/null
+++ b/include/hw/intc/allwinner-a10_pic.h
@@ -0,0 +1,40 @@
+#ifndef A10_PIC_H
+#define A10_PIC_H
+
+#define TYPE_A10_PIC  "a10-pic"
+#define A10_PIC(obj) OBJECT_CHECK(A10PICState, (obj), TYPE_A10_PIC)
+
+#define A10_PIC_VECTOR 	0
+#define A10_PIC_BASE_ADDR 	4
+#define A10_PIC_PROTECT 	8
+#define A10_PIC_NMI		0xc
+#define A10_PIC_IRQ_PENDING	0x10
+#define A10_PIC_FIQ_PENDING	0x20
+#define A10_PIC_SELECT	0x30
+#define A10_PIC_ENABLE	0x40
+#define A10_PIC_MASK		0x50
+
+#define A10_PIC_INT_NR	95
+#define A10_PIC_REG_NUM	DIV_ROUND_UP(A10_PIC_INT_NR, 32)
+
+typedef struct A10PICState {
+    /*< 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[A10_PIC_REG_NUM];
+    uint32_t fiq_pending[A10_PIC_REG_NUM];
+    uint32_t select[A10_PIC_REG_NUM];
+    uint32_t enable[A10_PIC_REG_NUM];
+    uint32_t mask[A10_PIC_REG_NUM];
+    /*priority setting here*/
+} A10PICState;
+
+#endif
-- 
1.7.2.5

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

* [Qemu-devel] [PATCH 4/5] hw/arm: add allwinner a10 SoC support
  2013-12-03  9:11 [Qemu-devel] [PATCH 0/5] add allwinner A10 SoC support liguang
                   ` (2 preceding siblings ...)
  2013-12-03  9:11 ` [Qemu-devel] [PATCH 3/5] hw/intc: add allwinner A10 interrupt controller liguang
@ 2013-12-03  9:11 ` liguang
  2013-12-03 11:41   ` Peter Crosthwaite
  2013-12-03 11:48   ` Peter Crosthwaite
  2013-12-03  9:11 ` [Qemu-devel] [PATCH 5/5] hw/arm: add cubieboard support liguang
  4 siblings, 2 replies; 14+ messages in thread
From: liguang @ 2013-12-03  9:11 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         |   39 +++++++++++++++++++++++++++++++++++++++
 include/hw/arm/allwinner-a10.h |   27 +++++++++++++++++++++++++++
 3 files changed, 67 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..cbc6db4
--- /dev/null
+++ b/hw/arm/allwinner-a10.c
@@ -0,0 +1,39 @@
+#include "hw/sysbus.h"
+#include "hw/devices.h"
+#include "hw/arm/allwinner-a10.h"
+
+
+A10State *a10_init(MemoryRegion *system_mem, unsigned long ram_size)
+{
+    A10State *s = (A10State *)g_malloc0(sizeof(A10State));
+    MemoryRegion *address_space_mem = system_mem;
+    qemu_irq pic[A10_PIC_INT_NR];
+    DeviceState *dev;
+    uint8_t i;
+
+    s->cpu = cpu_arm_init("cortex-a8");
+    if (!s->cpu) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+
+    memory_region_init_ram(&s->sdram, NULL, "a10.ram", ram_size);
+    vmstate_register_ram_global(&s->sdram);
+    memory_region_add_subregion(address_space_mem, A10_SDRAM_BASE, &s->sdram);
+
+    dev = sysbus_create_varargs(TYPE_A10_PIC, A10_PIC_REG_BASE,
+                                qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ),
+                                qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_FIQ),
+                                NULL);
+    for (i = 0; i < A10_PIC_INT_NR; i++) {
+        pic[i] = qdev_get_gpio_in(dev, i);
+    }
+
+    sysbus_create_varargs(TYPE_A10_PIT, A10_PIT_REG_BASE, pic[22], pic[23],
+                          pic[24], pic[25], pic[67], pic[68], NULL);
+
+    serial_mm_init(address_space_mem, A10_UART0_REG_BASE, 2, pic[1], 115200,
+                    serial_hds[0], DEVICE_NATIVE_ENDIAN);
+
+    return s;
+}
diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
new file mode 100644
index 0000000..32a8cb5
--- /dev/null
+++ b/include/hw/arm/allwinner-a10.h
@@ -0,0 +1,27 @@
+#ifndef ALLWINNER_H_
+
+#include "qemu-common.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 A10_PIC_REG_BASE 0x01c20400
+#define A10_PIT_REG_BASE 0x01c20c00
+#define A10_UART0_REG_BASE 0x01c28000
+
+#define A10_SDRAM_BASE 0x40000000
+
+typedef struct A10State {
+    ARMCPU *cpu;
+    MemoryRegion sdram;
+} A10State;
+
+A10State *a10_init(MemoryRegion *system_mem, unsigned long ram_size);
+
+#define ALLWINNER_H_
+#endif
-- 
1.7.2.5

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

* [Qemu-devel] [PATCH 5/5] hw/arm: add cubieboard support
  2013-12-03  9:11 [Qemu-devel] [PATCH 0/5] add allwinner A10 SoC support liguang
                   ` (3 preceding siblings ...)
  2013-12-03  9:11 ` [Qemu-devel] [PATCH 4/5] hw/arm: add allwinner a10 SoC support liguang
@ 2013-12-03  9:11 ` liguang
  2013-12-03 12:01   ` Peter Crosthwaite
  4 siblings, 1 reply; 14+ messages in thread
From: liguang @ 2013-12-03  9:11 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  |   33 +++++++++++++++++++++++++++++++++
 2 files changed, 34 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..a5be21c
--- /dev/null
+++ b/hw/arm/cubieboard.c
@@ -0,0 +1,33 @@
+#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 = A10_SDRAM_BASE,
+    .board_id = 0x1008,
+};
+
+static void cubieboard_init(QEMUMachineInitArgs *args)
+{
+    A10State *s = a10_init(get_system_memory(), args->ram_size);
+
+    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->cpu, &cubieboard_binfo);
+}
+
+static QEMUMachine cubieboard_machine = {
+    .name = "cubieboard",
+    .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] 14+ messages in thread

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

On Tue, Dec 3, 2013 at 7:11 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 ++++++++++++++++++++++++++++++++++

Mix of _ and - in filename is ugly. I think all - in filename is best.

>  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..4ff2e1f 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..2f9b458
> --- /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)
> +{
> +    A10PITState *s = A10_PIT(opaque);
> +    uint8_t index;
> +
> +    switch (offset) {
> +    case A10PIT_TIMER_IRQ_EN:

Its odd to have no _ between A10 and PIT. Does that match your documentation?

> +        return s->irq_enable;
> +    case A10PIT_TIMER_IRQ_ST:
> +        return s->irq_status;
> +    case A10PIT_TIMER_BASE ...  A10PIT_TIMER_BASE * 6 + A10PIT_TIMER_COUNT:
> +        index = offset & 0xf0;
> +        index >>= 4;
> +        index -= 1;
> +        switch (offset & 0x0f) {
> +        case A10PIT_TIMER_CONTROL:
> +            return s->control[index];
> +        case A10PIT_TIMER_INTERVAL:
> +            return s->interval[index];
> +        case A10PIT_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 A10PIT_WDOG_CONTROL:
> +        break;
> +    case A10PIT_WDOG_MODE:
> +        break;
> +    case A10PIT_COUNT_LO:
> +        return s->count_lo;
> +    case A10PIT_COUNT_HI:
> +        return s->count_hi;
> +    case A10PIT_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)
> +{
> +     A10PITState *s = A10_PIT(opaque);
> +     uint8_t index;
> +
> +    switch (offset) {
> +    case A10PIT_TIMER_IRQ_EN:
> +        s->irq_enable = value;
> +        break;
> +    case A10PIT_TIMER_IRQ_ST:
> +        s->irq_status &= ~value;
> +        break;
> +    case A10PIT_TIMER_BASE ...  A10PIT_TIMER_BASE * 6 + A10PIT_TIMER_COUNT:
> +        index = offset & 0xf0;
> +        index >>= 4;
> +        index -= 1;
> +        switch (offset & 0x0f) {
> +        case A10PIT_TIMER_CONTROL:
> +            s->control[index] = value;
> +            if (s->control[index] & A10PIT_TIMER_RELOAD) {
> +                ptimer_set_count(s->timer[index], s->interval[index]);
> +            }

Why? Doesn't the count just always stay up to date when writing TIMER_INTERVAL?

> +            if (s->control[index] & A10PIT_TIMER_EN) {
> +                ptimer_run(s->timer[index], 1);
> +            } else {
> +                ptimer_stop(s->timer[index]);
> +            }
> +            break;
> +        case A10PIT_TIMER_INTERVAL:
> +            s->interval[index] = value;
> +            ptimer_set_count(s->timer[index], s->interval[index]);
> +            break;
> +        case A10PIT_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 A10PIT_WDOG_CONTROL:
> +        s->watch_dog_control = value;
> +        break;
> +    case A10PIT_WDOG_MODE:
> +        s->watch_dog_mode = value;
> +        break;
> +    case A10PIT_COUNT_LO:
> +        s->count_lo = value;
> +        break;
> +    case A10PIT_COUNT_HI:
> +        s->count_hi = value;
> +        break;
> +    case A10PIT_COUNT_CTL:
> +        s->count_ctl = value;
> +        if (s->count_ctl & A10PIT_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 &= ~A10PIT_COUNT_RL_EN;
> +        }
> +        if (s->count_ctl & A10PIT_COUNT_CLR_EN) {
> +            s->count_lo = 0;
> +            s->count_hi = 0;
> +            s->count_ctl &= ~A10PIT_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, A10PITState),
> +        VMSTATE_UINT32(irq_status, A10PITState),
> +        VMSTATE_UINT32_ARRAY(control, A10PITState, A10PIT_TIMER_NR),
> +        VMSTATE_UINT32_ARRAY(interval, A10PITState, A10PIT_TIMER_NR),
> +        VMSTATE_UINT32_ARRAY(count, A10PITState, A10PIT_TIMER_NR),
> +        VMSTATE_UINT32(watch_dog_mode, A10PITState),
> +        VMSTATE_UINT32(watch_dog_control, A10PITState),
> +        VMSTATE_UINT32(count_lo, A10PITState),
> +        VMSTATE_UINT32(count_hi, A10PITState),
> +        VMSTATE_UINT32(count_ctl, A10PITState),
> +        VMSTATE_PTIMER_ARRAY(timer, A10PITState, A10PIT_TIMER_NR),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static void a10_pit_reset(DeviceState *dev)
> +{
> +    A10PITState *s = A10_PIT(dev);
> +    uint8_t i;
> +
> +    s->irq_enable = 0;
> +    s->irq_status = 0;
> +    for (i = 0; i < 6; i++) {
> +        s->control[i] = A10PIT_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)
> +{
> +    A10PITState *s = A10_PIT(opaque);
> +    uint8_t i;
> +
> +    for (i = 0; i < A10PIT_TIMER_NR; i++) {
> +        if (s->control[i] & A10PIT_TIMER_EN &&
> +            ptimer_get_count(s->timer[i]) == 0) {
> +            s->irq_status |= 1 << i;
> +            if (!(s->control[i] & A10PIT_TIMER_MODE)) {
> +                ptimer_set_count(s->timer[i], s->interval[i]);
> +                ptimer_run(s->timer[i], 1);

You are still chaining oneshot timers together here to form a periodic
timer. Just run the timer as periodic in the first place when
!A10PIT_TIMER_MODE.

> +                s->control[i] |= A10PIT_TIMER_EN;

Dead assignment. TIMER_EN is already set.

> +            } else {
> +                s->control[i] &= ~A10PIT_TIMER_EN;

So the spurious interrupts are gone now, which is good news

> +            }
> +            qemu_irq_pulse(s->irq[i]);
> +        }
> +    }
> +}
> +
> +static void a10_pit_realize(DeviceState *dev, Error **errp)
> +{
> +    A10PITState *s = A10_PIT(dev);
> +    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> +    QEMUBH * bh[A10PIT_TIMER_NR];
> +    uint8_t i;
> +
> +    for (i = 0; i < A10PIT_TIMER_NR; i++) {
> +        sysbus_init_irq(sbd, &s->irq[i]);
> +    }
> +    memory_region_init_io(&s->iomem, OBJECT(s), &a10_pit_ops, s,
> +                          TYPE_A10_PIT, 0x400);
> +    sysbus_init_mmio(sbd, &s->iomem);
> +
> +    for (i = 0; i < A10PIT_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_A10_PIT,
> +    .parent = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(A10PITState),
> +    .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..e061cc2
> --- /dev/null
> +++ b/include/hw/timer/allwinner-a10_pit.h
> @@ -0,0 +1,57 @@
> +#ifndef A10_PIT_H
> +#define A10_PIT_H
> +
> +#include "hw/ptimer.h"
> +
> +#define TYPE_A10_PIT "a10-timer"
> +#define A10_PIT(obj) OBJECT_CHECK(A10PITState, (obj), TYPE_A10_PIT)
> +
> +#define A10PIT_TIMER_NR        6
> +#define A10PIT_TIMER_IRQ       0x1
> +#define A10PIT_WDOG_IRQ        0x100
> +

So "A10" as the macro prefix is a little vague. We could easily have
confusion with ARMs own usage of Axx. Is there a contraction of
"allwinner" we could prefix in there?

If you plan to use this timer in the future for devices other than
A10, you could just drop the "A10" labelling here now. That suggestion
to use the specific SoC name is more for the SoC container object, not
the peripheral devices.

Regards,
Peter

> +#define A10PIT_TIMER_IRQ_EN    0
> +#define A10PIT_TIMER_IRQ_ST    0x4
> +
> +#define A10PIT_TIMER_CONTROL   0x0
> +#define A10PIT_TIMER_EN        0x1
> +#define A10PIT_TIMER_RELOAD    0x2
> +#define A10PIT_TIMER_MODE      0x80
> +
> +#define A10PIT_TIMER_INTERVAL  0x4
> +#define A10PIT_TIMER_COUNT             0x8
> +#define A10PIT_WDOG_CONTROL            0x90
> +#define A10PIT_WDOG_MODE               0x94
> +
> +#define A10PIT_COUNT_CTL               0xa0
> +#define A10PIT_COUNT_RL_EN             0x2
> +#define A10PIT_COUNT_CLR_EN            0x1
> +#define A10PIT_COUNT_LO                0xa4
> +#define A10PIT_COUNT_HI                0xa8
> +
> +#define A10PIT_TIMER_BASE              0x10
> +
> +#define A10PIT_DEFAULT_CLOCK           0x4
> +
> +typedef struct A10PITState {
> +    /*< private >*/
> +    SysBusDevice parent_obj;
> +    /*< public >*/
> +    qemu_irq irq[A10PIT_TIMER_NR];
> +    ptimer_state *timer[A10PIT_TIMER_NR];
> +    MemoryRegion iomem;
> +
> +    uint32_t  irq_enable;
> +    uint32_t irq_status;
> +    uint32_t control[A10PIT_TIMER_NR];
> +    uint32_t interval[A10PIT_TIMER_NR];
> +    uint32_t count[A10PIT_TIMER_NR];
> +    uint32_t watch_dog_mode;
> +    uint32_t watch_dog_control;
> +    uint32_t count_lo;
> +    uint32_t count_hi;
> +    uint32_t count_ctl;
> +} A10PITState;
> +
> +#endif
> +
> --
> 1.7.2.5
>
>

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

* Re: [Qemu-devel] [PATCH 4/5] hw/arm: add allwinner a10 SoC support
  2013-12-03  9:11 ` [Qemu-devel] [PATCH 4/5] hw/arm: add allwinner a10 SoC support liguang
@ 2013-12-03 11:41   ` Peter Crosthwaite
  2013-12-03 11:48   ` Peter Crosthwaite
  1 sibling, 0 replies; 14+ messages in thread
From: Peter Crosthwaite @ 2013-12-03 11:41 UTC (permalink / raw)
  To: liguang
  Cc: Peter Maydell, qemu-devel@nongnu.org Developers,
	Andreas Färber

On Tue, Dec 3, 2013 at 7:11 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         |   39 +++++++++++++++++++++++++++++++++++++++
>  include/hw/arm/allwinner-a10.h |   27 +++++++++++++++++++++++++++
>  3 files changed, 67 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..cbc6db4
> --- /dev/null
> +++ b/hw/arm/allwinner-a10.c
> @@ -0,0 +1,39 @@
> +#include "hw/sysbus.h"
> +#include "hw/devices.h"
> +#include "hw/arm/allwinner-a10.h"
> +
> +
> +A10State *a10_init(MemoryRegion *system_mem, unsigned long ram_size)
> +{
> +    A10State *s = (A10State *)g_malloc0(sizeof(A10State));
> +    MemoryRegion *address_space_mem = system_mem;
> +    qemu_irq pic[A10_PIC_INT_NR];
> +    DeviceState *dev;
> +    uint8_t i;
> +
> +    s->cpu = cpu_arm_init("cortex-a8");
> +    if (!s->cpu) {
> +        fprintf(stderr, "Unable to find CPU definition\n");
> +        exit(1);
> +    }
> +
> +    memory_region_init_ram(&s->sdram, NULL, "a10.ram", ram_size);
> +    vmstate_register_ram_global(&s->sdram);
> +    memory_region_add_subregion(address_space_mem, A10_SDRAM_BASE, &s->sdram);
> +
> +    dev = sysbus_create_varargs(TYPE_A10_PIC, A10_PIC_REG_BASE,
> +                                qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ),
> +                                qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_FIQ),
> +                                NULL);
> +    for (i = 0; i < A10_PIC_INT_NR; i++) {
> +        pic[i] = qdev_get_gpio_in(dev, i);
> +    }
> +
> +    sysbus_create_varargs(TYPE_A10_PIT, A10_PIT_REG_BASE, pic[22], pic[23],
> +                          pic[24], pic[25], pic[67], pic[68], NULL);
> +
> +    serial_mm_init(address_space_mem, A10_UART0_REG_BASE, 2, pic[1], 115200,
> +                    serial_hds[0], DEVICE_NATIVE_ENDIAN);
> +
> +    return s;
> +}
> diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
> new file mode 100644
> index 0000000..32a8cb5
> --- /dev/null
> +++ b/include/hw/arm/allwinner-a10.h
> @@ -0,0 +1,27 @@
> +#ifndef ALLWINNER_H_
> +
> +#include "qemu-common.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 A10_PIC_REG_BASE 0x01c20400
> +#define A10_PIT_REG_BASE 0x01c20c00
> +#define A10_UART0_REG_BASE 0x01c28000
> +
> +#define A10_SDRAM_BASE 0x40000000
> +
> +typedef struct A10State {
> +    ARMCPU *cpu;
> +    MemoryRegion sdram;
> +} A10State;
> +
> +A10State *a10_init(MemoryRegion *system_mem, unsigned long ram_size);
> +
> +#define ALLWINNER_H_
> +#endif
> --
> 1.7.2.5
>
>

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

* Re: [Qemu-devel] [PATCH 4/5] hw/arm: add allwinner a10 SoC support
  2013-12-03  9:11 ` [Qemu-devel] [PATCH 4/5] hw/arm: add allwinner a10 SoC support liguang
  2013-12-03 11:41   ` Peter Crosthwaite
@ 2013-12-03 11:48   ` Peter Crosthwaite
  1 sibling, 0 replies; 14+ messages in thread
From: Peter Crosthwaite @ 2013-12-03 11:48 UTC (permalink / raw)
  To: liguang
  Cc: Peter Maydell, qemu-devel@nongnu.org Developers,
	Andreas Färber

On Tue, Dec 3, 2013 at 7:11 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         |   39 +++++++++++++++++++++++++++++++++++++++
>  include/hw/arm/allwinner-a10.h |   27 +++++++++++++++++++++++++++
>  3 files changed, 67 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..cbc6db4
> --- /dev/null
> +++ b/hw/arm/allwinner-a10.c
> @@ -0,0 +1,39 @@
> +#include "hw/sysbus.h"
> +#include "hw/devices.h"
> +#include "hw/arm/allwinner-a10.h"
> +
> +
> +A10State *a10_init(MemoryRegion *system_mem, unsigned long ram_size)
> +{
> +    A10State *s = (A10State *)g_malloc0(sizeof(A10State));
> +    MemoryRegion *address_space_mem = system_mem;
> +    qemu_irq pic[A10_PIC_INT_NR];
> +    DeviceState *dev;
> +    uint8_t i;
> +
> +    s->cpu = cpu_arm_init("cortex-a8");
> +    if (!s->cpu) {
> +        fprintf(stderr, "Unable to find CPU definition\n");

error_report is encouraged in situations like this I think.

> +        exit(1);
> +    }
> +
> +    memory_region_init_ram(&s->sdram, NULL, "a10.ram", ram_size);
> +    vmstate_register_ram_global(&s->sdram);
> +    memory_region_add_subregion(address_space_mem, A10_SDRAM_BASE, &s->sdram);
> +
> +    dev = sysbus_create_varargs(TYPE_A10_PIC, A10_PIC_REG_BASE,
> +                                qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ),
> +                                qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_FIQ),
> +                                NULL);

sysbus create is the old API. Object initialise is the new correct API for this.

> +    for (i = 0; i < A10_PIC_INT_NR; i++) {
> +        pic[i] = qdev_get_gpio_in(dev, i);
> +    }
> +
> +    sysbus_create_varargs(TYPE_A10_PIT, A10_PIT_REG_BASE, pic[22], pic[23],
> +                          pic[24], pic[25], pic[67], pic[68], NULL);
> +
> +    serial_mm_init(address_space_mem, A10_UART0_REG_BASE, 2, pic[1], 115200,
> +                    serial_hds[0], DEVICE_NATIVE_ENDIAN);
> +

what do you do with the sysbus devs once you you create them? arent
they just lost?

> +    return s;
> +}
> diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
> new file mode 100644
> index 0000000..32a8cb5
> --- /dev/null
> +++ b/include/hw/arm/allwinner-a10.h
> @@ -0,0 +1,27 @@
> +#ifndef ALLWINNER_H_
> +
> +#include "qemu-common.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 A10_PIC_REG_BASE 0x01c20400
> +#define A10_PIT_REG_BASE 0x01c20c00
> +#define A10_UART0_REG_BASE 0x01c28000
> +
> +#define A10_SDRAM_BASE 0x40000000
> +
> +typedef struct A10State {
> +    ARMCPU *cpu;
> +    MemoryRegion sdram;
> +} A10State;
> +

This needs to be QOMified as a device. There should be a type
definition for it. Check the Digic series for a good example (Patch 1
V6).

> +A10State *a10_init(MemoryRegion *system_mem, unsigned long ram_size);
> +

And this just becomes object-init or device-realize as appropriate.

Regards,
Peter

> +#define ALLWINNER_H_
> +#endif
> --
> 1.7.2.5
>
>

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

* Re: [Qemu-devel] [PATCH 5/5] hw/arm: add cubieboard support
  2013-12-03  9:11 ` [Qemu-devel] [PATCH 5/5] hw/arm: add cubieboard support liguang
@ 2013-12-03 12:01   ` Peter Crosthwaite
  2013-12-03 14:44     ` Andreas Färber
  2013-12-04  0:00     ` Li Guang
  0 siblings, 2 replies; 14+ messages in thread
From: Peter Crosthwaite @ 2013-12-03 12:01 UTC (permalink / raw)
  To: liguang
  Cc: Peter Maydell, qemu-devel@nongnu.org Developers,
	Andreas Färber

On Tue, Dec 3, 2013 at 7:11 PM, liguang <lig.fnst@cn.fujitsu.com> wrote:
> Signed-off-by: liguang <lig.fnst@cn.fujitsu.com>
> ---
>  hw/arm/Makefile.objs |    2 +-
>  hw/arm/cubieboard.c  |   33 +++++++++++++++++++++++++++++++++
>  2 files changed, 34 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..a5be21c
> --- /dev/null
> +++ b/hw/arm/cubieboard.c
> @@ -0,0 +1,33 @@
> +#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 = A10_SDRAM_BASE,
> +    .board_id = 0x1008,
> +};
> +
> +static void cubieboard_init(QEMUMachineInitArgs *args)
> +{
> +    A10State *s = a10_init(get_system_memory(), args->ram_size);
> +
> +    cubieboard_binfo.ram_size = args->ram_size;
> +    cubieboard_binfo.kernel_filename = args->kernel_filename;
> +    cubieboard_binfo.kernel_cmdline = args->kernel_cmdline;

I cant help but think that serial attachment needs to happen on the
board level. but im not sure how this can be made to work with the
un-qomified serial_mm_init, so no block from me unless Andreas has a
better idea.

> +    arm_load_kernel(s->cpu, &cubieboard_binfo);
> +}
> +
> +static QEMUMachine cubieboard_machine = {
> +    .name = "cubieboard",
> +    .init = cubieboard_init,

I think you should add at least the long descriptor so -M help plays nice.

Regards,
Peter

> +};
> +
> +
> +static void cubieboard_machine_init(void)
> +{
> +    qemu_register_machine(&cubieboard_machine);
> +}
> +
> +machine_init(cubieboard_machine_init);
> --
> 1.7.2.5
>
>

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

* Re: [Qemu-devel] [PATCH 5/5] hw/arm: add cubieboard support
  2013-12-03 12:01   ` Peter Crosthwaite
@ 2013-12-03 14:44     ` Andreas Färber
  2013-12-04  0:00       ` Li Guang
  2013-12-04  0:00     ` Li Guang
  1 sibling, 1 reply; 14+ messages in thread
From: Andreas Färber @ 2013-12-03 14:44 UTC (permalink / raw)
  To: Peter Crosthwaite, liguang
  Cc: Peter Maydell, qemu-devel@nongnu.org Developers

Am 03.12.2013 13:01, schrieb Peter Crosthwaite:
> On Tue, Dec 3, 2013 at 7:11 PM, liguang <lig.fnst@cn.fujitsu.com> wrote:
>> Signed-off-by: liguang <lig.fnst@cn.fujitsu.com>
>> ---
>>  hw/arm/Makefile.objs |    2 +-
>>  hw/arm/cubieboard.c  |   33 +++++++++++++++++++++++++++++++++
>>  2 files changed, 34 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..a5be21c
>> --- /dev/null
>> +++ b/hw/arm/cubieboard.c
>> @@ -0,0 +1,33 @@
>> +#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 = A10_SDRAM_BASE,
>> +    .board_id = 0x1008,
>> +};
>> +
>> +static void cubieboard_init(QEMUMachineInitArgs *args)
>> +{
>> +    A10State *s = a10_init(get_system_memory(), args->ram_size);
>> +
>> +    cubieboard_binfo.ram_size = args->ram_size;
>> +    cubieboard_binfo.kernel_filename = args->kernel_filename;
>> +    cubieboard_binfo.kernel_cmdline = args->kernel_cmdline;
> 
> I cant help but think that serial attachment needs to happen on the
> board level. but im not sure how this can be made to work with the
> un-qomified serial_mm_init, so no block from me unless Andreas has a
> better idea.

I don't have an immediate solution, same problem in Tegra2 code.

If someone is willing to convert serial_mm into QOM-friendly form that
would be nice but I will be unavailable for review the next ~two weeks.

What I do wonder here is why this is calling a new a10_init() rather
than object_new() and related QOM APIs. get_system_memory() can without
problems be called inside the device. If RAM is really on the SoC (it is
for Tegra2/3) then it could become a property of the device with
MemoryRegion initialization in realize - that is still unclean in my
code IIRC.

>> +    arm_load_kernel(s->cpu, &cubieboard_binfo);
>> +}
[...]
>> +machine_init(cubieboard_machine_init);

No semicolon here please, it's a function.

Regards,
Andreas

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

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

* Re: [Qemu-devel] [PATCH 5/5] hw/arm: add cubieboard support
  2013-12-03 12:01   ` Peter Crosthwaite
  2013-12-03 14:44     ` Andreas Färber
@ 2013-12-04  0:00     ` Li Guang
  1 sibling, 0 replies; 14+ messages in thread
From: Li Guang @ 2013-12-04  0:00 UTC (permalink / raw)
  To: Peter Crosthwaite
  Cc: Peter Maydell, qemu-devel@nongnu.org Developers,
	Andreas Färber

Peter Crosthwaite wrote:
> On Tue, Dec 3, 2013 at 7:11 PM, liguang<lig.fnst@cn.fujitsu.com>  wrote:
>    
>> Signed-off-by: liguang<lig.fnst@cn.fujitsu.com>
>> ---
>>   hw/arm/Makefile.objs |    2 +-
>>   hw/arm/cubieboard.c  |   33 +++++++++++++++++++++++++++++++++
>>   2 files changed, 34 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..a5be21c
>> --- /dev/null
>> +++ b/hw/arm/cubieboard.c
>> @@ -0,0 +1,33 @@
>> +#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 = A10_SDRAM_BASE,
>> +    .board_id = 0x1008,
>> +};
>> +
>> +static void cubieboard_init(QEMUMachineInitArgs *args)
>> +{
>> +    A10State *s = a10_init(get_system_memory(), args->ram_size);
>> +
>> +    cubieboard_binfo.ram_size = args->ram_size;
>> +    cubieboard_binfo.kernel_filename = args->kernel_filename;
>> +    cubieboard_binfo.kernel_cmdline = args->kernel_cmdline;
>>      
> I cant help but think that serial attachment needs to happen on the
> board level. but im not sure how this can be made to work with the
> un-qomified serial_mm_init, so no block from me unless Andreas has a
> better idea.
>
>    
>> +    arm_load_kernel(s->cpu,&cubieboard_binfo);
>> +}
>> +
>> +static QEMUMachine cubieboard_machine = {
>> +    .name = "cubieboard",
>> +    .init = cubieboard_init,
>>      
> I think you should add at least the long descriptor so -M help plays nice.
>
>    

OK, thanks!

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

* Re: [Qemu-devel] [PATCH 5/5] hw/arm: add cubieboard support
  2013-12-03 14:44     ` Andreas Färber
@ 2013-12-04  0:00       ` Li Guang
  0 siblings, 0 replies; 14+ messages in thread
From: Li Guang @ 2013-12-04  0:00 UTC (permalink / raw)
  To: Andreas Färber
  Cc: Peter Maydell, Peter Crosthwaite,
	qemu-devel@nongnu.org Developers

Andreas Färber wrote:
> Am 03.12.2013 13:01, schrieb Peter Crosthwaite:
>    
>> On Tue, Dec 3, 2013 at 7:11 PM, liguang<lig.fnst@cn.fujitsu.com>  wrote:
>>      
>>> Signed-off-by: liguang<lig.fnst@cn.fujitsu.com>
>>> ---
>>>   hw/arm/Makefile.objs |    2 +-
>>>   hw/arm/cubieboard.c  |   33 +++++++++++++++++++++++++++++++++
>>>   2 files changed, 34 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..a5be21c
>>> --- /dev/null
>>> +++ b/hw/arm/cubieboard.c
>>> @@ -0,0 +1,33 @@
>>> +#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 = A10_SDRAM_BASE,
>>> +    .board_id = 0x1008,
>>> +};
>>> +
>>> +static void cubieboard_init(QEMUMachineInitArgs *args)
>>> +{
>>> +    A10State *s = a10_init(get_system_memory(), args->ram_size);
>>> +
>>> +    cubieboard_binfo.ram_size = args->ram_size;
>>> +    cubieboard_binfo.kernel_filename = args->kernel_filename;
>>> +    cubieboard_binfo.kernel_cmdline = args->kernel_cmdline;
>>>        
>> I cant help but think that serial attachment needs to happen on the
>> board level. but im not sure how this can be made to work with the
>> un-qomified serial_mm_init, so no block from me unless Andreas has a
>> better idea.
>>      
> I don't have an immediate solution, same problem in Tegra2 code.
>
> If someone is willing to convert serial_mm into QOM-friendly form that
> would be nice but I will be unavailable for review the next ~two weeks.
>
> What I do wonder here is why this is calling a new a10_init() rather
> than object_new() and related QOM APIs. get_system_memory() can without
> problems be called inside the device. If RAM is really on the SoC (it is
> for Tegra2/3) then it could become a property of the device with
> MemoryRegion initialization in realize - that is still unclean in my
> code IIRC.
>
>    
>>> +    arm_load_kernel(s->cpu,&cubieboard_binfo);
>>> +}
>>>        
> [...]
>    
>>> +machine_init(cubieboard_machine_init);
>>>        
> No semicolon here please, it's a function.
>
>    

Yes, thanks!


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

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

Peter Crosthwaite wrote:
> On Tue, Dec 3, 2013 at 7:11 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 ++++++++++++++++++++++++++++++++++
>>      
> Mix of _ and - in filename is ugly. I think all - in filename is best.
>
>    

OK , will fix,
though I think '_' and '-' have different meanings here.
'_' is for separation,
'-' is for concatenation.
>>   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..4ff2e1f 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..2f9b458
>> --- /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)
>> +{
>> +    A10PITState *s = A10_PIT(opaque);
>> +    uint8_t index;
>> +
>> +    switch (offset) {
>> +    case A10PIT_TIMER_IRQ_EN:
>>      
> Its odd to have no _ between A10 and PIT. Does that match your documentation?
>
>    

hmm, OK, will fix

>> +        return s->irq_enable;
>> +    case A10PIT_TIMER_IRQ_ST:
>> +        return s->irq_status;
>> +    case A10PIT_TIMER_BASE ...  A10PIT_TIMER_BASE * 6 + A10PIT_TIMER_COUNT:
>> +        index = offset&  0xf0;
>> +        index>>= 4;
>> +        index -= 1;
>> +        switch (offset&  0x0f) {
>> +        case A10PIT_TIMER_CONTROL:
>> +            return s->control[index];
>> +        case A10PIT_TIMER_INTERVAL:
>> +            return s->interval[index];
>> +        case A10PIT_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 A10PIT_WDOG_CONTROL:
>> +        break;
>> +    case A10PIT_WDOG_MODE:
>> +        break;
>> +    case A10PIT_COUNT_LO:
>> +        return s->count_lo;
>> +    case A10PIT_COUNT_HI:
>> +        return s->count_hi;
>> +    case A10PIT_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)
>> +{
>> +     A10PITState *s = A10_PIT(opaque);
>> +     uint8_t index;
>> +
>> +    switch (offset) {
>> +    case A10PIT_TIMER_IRQ_EN:
>> +        s->irq_enable = value;
>> +        break;
>> +    case A10PIT_TIMER_IRQ_ST:
>> +        s->irq_status&= ~value;
>> +        break;
>> +    case A10PIT_TIMER_BASE ...  A10PIT_TIMER_BASE * 6 + A10PIT_TIMER_COUNT:
>> +        index = offset&  0xf0;
>> +        index>>= 4;
>> +        index -= 1;
>> +        switch (offset&  0x0f) {
>> +        case A10PIT_TIMER_CONTROL:
>> +            s->control[index] = value;
>> +            if (s->control[index]&  A10PIT_TIMER_RELOAD) {
>> +                ptimer_set_count(s->timer[index], s->interval[index]);
>> +            }
>>      
> Why? Doesn't the count just always stay up to date when writing TIMER_INTERVAL?
>
>    

just do as datasheet says, "Reload timer Interval value"

>> +            if (s->control[index]&  A10PIT_TIMER_EN) {
>> +                ptimer_run(s->timer[index], 1);
>> +            } else {
>> +                ptimer_stop(s->timer[index]);
>> +            }
>> +            break;
>> +        case A10PIT_TIMER_INTERVAL:
>> +            s->interval[index] = value;
>> +            ptimer_set_count(s->timer[index], s->interval[index]);
>> +            break;
>> +        case A10PIT_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 A10PIT_WDOG_CONTROL:
>> +        s->watch_dog_control = value;
>> +        break;
>> +    case A10PIT_WDOG_MODE:
>> +        s->watch_dog_mode = value;
>> +        break;
>> +    case A10PIT_COUNT_LO:
>> +        s->count_lo = value;
>> +        break;
>> +    case A10PIT_COUNT_HI:
>> +        s->count_hi = value;
>> +        break;
>> +    case A10PIT_COUNT_CTL:
>> +        s->count_ctl = value;
>> +        if (s->count_ctl&  A10PIT_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&= ~A10PIT_COUNT_RL_EN;
>> +        }
>> +        if (s->count_ctl&  A10PIT_COUNT_CLR_EN) {
>> +            s->count_lo = 0;
>> +            s->count_hi = 0;
>> +            s->count_ctl&= ~A10PIT_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, A10PITState),
>> +        VMSTATE_UINT32(irq_status, A10PITState),
>> +        VMSTATE_UINT32_ARRAY(control, A10PITState, A10PIT_TIMER_NR),
>> +        VMSTATE_UINT32_ARRAY(interval, A10PITState, A10PIT_TIMER_NR),
>> +        VMSTATE_UINT32_ARRAY(count, A10PITState, A10PIT_TIMER_NR),
>> +        VMSTATE_UINT32(watch_dog_mode, A10PITState),
>> +        VMSTATE_UINT32(watch_dog_control, A10PITState),
>> +        VMSTATE_UINT32(count_lo, A10PITState),
>> +        VMSTATE_UINT32(count_hi, A10PITState),
>> +        VMSTATE_UINT32(count_ctl, A10PITState),
>> +        VMSTATE_PTIMER_ARRAY(timer, A10PITState, A10PIT_TIMER_NR),
>> +        VMSTATE_END_OF_LIST()
>> +    }
>> +};
>> +
>> +static void a10_pit_reset(DeviceState *dev)
>> +{
>> +    A10PITState *s = A10_PIT(dev);
>> +    uint8_t i;
>> +
>> +    s->irq_enable = 0;
>> +    s->irq_status = 0;
>> +    for (i = 0; i<  6; i++) {
>> +        s->control[i] = A10PIT_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)
>> +{
>> +    A10PITState *s = A10_PIT(opaque);
>> +    uint8_t i;
>> +
>> +    for (i = 0; i<  A10PIT_TIMER_NR; i++) {
>> +        if (s->control[i]&  A10PIT_TIMER_EN&&
>> +            ptimer_get_count(s->timer[i]) == 0) {
>> +            s->irq_status |= 1<<  i;
>> +            if (!(s->control[i]&  A10PIT_TIMER_MODE)) {
>> +                ptimer_set_count(s->timer[i], s->interval[i]);
>> +                ptimer_run(s->timer[i], 1);
>>      
> You are still chaining oneshot timers together here to form a periodic
> timer. Just run the timer as periodic in the first place when
> !A10PIT_TIMER_MODE.
>
>    

OK, will use continuous timer.

>> +                s->control[i] |= A10PIT_TIMER_EN;
>>      
> Dead assignment. TIMER_EN is already set.
>
>    
>> +            } else {
>> +                s->control[i]&= ~A10PIT_TIMER_EN;
>>      
> So the spurious interrupts are gone now, which is good news
>
>    
>> +            }
>> +            qemu_irq_pulse(s->irq[i]);
>> +        }
>> +    }
>> +}
>> +
>> +static void a10_pit_realize(DeviceState *dev, Error **errp)
>> +{
>> +    A10PITState *s = A10_PIT(dev);
>> +    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
>> +    QEMUBH * bh[A10PIT_TIMER_NR];
>> +    uint8_t i;
>> +
>> +    for (i = 0; i<  A10PIT_TIMER_NR; i++) {
>> +        sysbus_init_irq(sbd,&s->irq[i]);
>> +    }
>> +    memory_region_init_io(&s->iomem, OBJECT(s),&a10_pit_ops, s,
>> +                          TYPE_A10_PIT, 0x400);
>> +    sysbus_init_mmio(sbd,&s->iomem);
>> +
>> +    for (i = 0; i<  A10PIT_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_A10_PIT,
>> +    .parent = TYPE_SYS_BUS_DEVICE,
>> +    .instance_size = sizeof(A10PITState),
>> +    .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..e061cc2
>> --- /dev/null
>> +++ b/include/hw/timer/allwinner-a10_pit.h
>> @@ -0,0 +1,57 @@
>> +#ifndef A10_PIT_H
>> +#define A10_PIT_H
>> +
>> +#include "hw/ptimer.h"
>> +
>> +#define TYPE_A10_PIT "a10-timer"
>> +#define A10_PIT(obj) OBJECT_CHECK(A10PITState, (obj), TYPE_A10_PIT)
>> +
>> +#define A10PIT_TIMER_NR        6
>> +#define A10PIT_TIMER_IRQ       0x1
>> +#define A10PIT_WDOG_IRQ        0x100
>> +
>>      
> So "A10" as the macro prefix is a little vague. We could easily have
> confusion with ARMs own usage of Axx. Is there a contraction of
> "allwinner" we could prefix in there?
> If you plan to use this timer in the future for devices other than
> A10, you could just drop the "A10" labelling here now. That suggestion
> to use the specific SoC name is more for the SoC container object, not
> the peripheral devices.
>
>    

I prefer A10 prefix, for we can't assure all allwinner chips
implement the same timer like A10.

and any chips implemented this timer can realize this timer.

Thanks!
Li Guang


>> +#define A10PIT_TIMER_IRQ_EN    0
>> +#define A10PIT_TIMER_IRQ_ST    0x4
>> +
>> +#define A10PIT_TIMER_CONTROL   0x0
>> +#define A10PIT_TIMER_EN        0x1
>> +#define A10PIT_TIMER_RELOAD    0x2
>> +#define A10PIT_TIMER_MODE      0x80
>> +
>> +#define A10PIT_TIMER_INTERVAL  0x4
>> +#define A10PIT_TIMER_COUNT             0x8
>> +#define A10PIT_WDOG_CONTROL            0x90
>> +#define A10PIT_WDOG_MODE               0x94
>> +
>> +#define A10PIT_COUNT_CTL               0xa0
>> +#define A10PIT_COUNT_RL_EN             0x2
>> +#define A10PIT_COUNT_CLR_EN            0x1
>> +#define A10PIT_COUNT_LO                0xa4
>> +#define A10PIT_COUNT_HI                0xa8
>> +
>> +#define A10PIT_TIMER_BASE              0x10
>> +
>> +#define A10PIT_DEFAULT_CLOCK           0x4
>> +
>> +typedef struct A10PITState {
>> +    /*<  private>*/
>> +    SysBusDevice parent_obj;
>> +    /*<  public>*/
>> +    qemu_irq irq[A10PIT_TIMER_NR];
>> +    ptimer_state *timer[A10PIT_TIMER_NR];
>> +    MemoryRegion iomem;
>> +
>> +    uint32_t  irq_enable;
>> +    uint32_t irq_status;
>> +    uint32_t control[A10PIT_TIMER_NR];
>> +    uint32_t interval[A10PIT_TIMER_NR];
>> +    uint32_t count[A10PIT_TIMER_NR];
>> +    uint32_t watch_dog_mode;
>> +    uint32_t watch_dog_control;
>> +    uint32_t count_lo;
>> +    uint32_t count_hi;
>> +    uint32_t count_ctl;
>> +} A10PITState;
>> +
>> +#endif
>> +
>> --
>> 1.7.2.5
>>
>>
>>      
>
>    

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

end of thread, other threads:[~2013-12-04  2:13 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-12-03  9:11 [Qemu-devel] [PATCH 0/5] add allwinner A10 SoC support liguang
2013-12-03  9:11 ` [Qemu-devel] [PATCH 1/5] vmstate: add VMSTATE_PTIMER_ARRAY liguang
2013-12-03  9:11 ` [Qemu-devel] [PATCH 2/5] hw/timer: add allwinner a10 timer liguang
2013-12-03 11:36   ` Peter Crosthwaite
2013-12-04  2:12     ` Li Guang
2013-12-03  9:11 ` [Qemu-devel] [PATCH 3/5] hw/intc: add allwinner A10 interrupt controller liguang
2013-12-03  9:11 ` [Qemu-devel] [PATCH 4/5] hw/arm: add allwinner a10 SoC support liguang
2013-12-03 11:41   ` Peter Crosthwaite
2013-12-03 11:48   ` Peter Crosthwaite
2013-12-03  9:11 ` [Qemu-devel] [PATCH 5/5] hw/arm: add cubieboard support liguang
2013-12-03 12:01   ` Peter Crosthwaite
2013-12-03 14:44     ` Andreas Färber
2013-12-04  0:00       ` Li Guang
2013-12-04  0:00     ` Li Guang

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).