* [Qemu-devel] [PATCH v12 0/5] add allwinner A10 SoC support
@ 2013-12-13 1:19 liguang
2013-12-13 1:19 ` [Qemu-devel] [PATCH v12 1/5] vmstate: Add support for an array of ptimer_state * liguang
` (4 more replies)
0 siblings, 5 replies; 10+ messages in thread
From: liguang @ 2013-12-13 1:19 UTC (permalink / raw)
To: QEMU Developers
Cc: Peter Maydell, Peter Crosthwaite, Andreas Färber, liguang,
Juan Quintela
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
v9:
code cleanup for PATCH 4/5 A10 SoC support
v10:
code cleanup for PATCH 2/5
v11:
code cleanup for PATCH 2/5, 3/5
v12:
1. use bool type for irq setting
2. use Peter's VMSTATE_PTIMER_ARRAY
TODO:
1. add BROM support
2. add more devices
test:
can boot-up officially released linux kernel build with
PLL disabled.
can find test zImage at:
http://dl.dbank.com/c0jaibr54s
reference:
http://linux-sunxi.org/Main_Page
Li Guang (5)
vmstate: Add support for an array of ptimer_state *
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 | 4 +
hw/arm/Makefile.objs | 3 +
hw/arm/allwinner-a10.c | 103 +++++++++++++++++++++++++++++++++++++++
hw/arm/cubieboard.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++
hw/intc/Makefile.objs | 1 +
hw/intc/allwinner-a10-pic.c | 200 +++++++++++++++++++++++++++++++++++
hw/timer/Makefile.objs | 2 +
hw/timer/allwinner-a10-pit.c | 254 ++++++++++++++++++++++++++++++++++
include/hw/arm/allwinner-a10.h | 35 +++++++++++++
include/hw/intc/allwinner-a10-pic.h | 40 +++++++
include/hw/ptimer.h | 4 ++++
include/hw/timer/allwinner-a10-pit.h | 59 ++++++++
include/migration/vmstate.h | 10 ++++++++++
13 files changed, 783 insertions(+), 1 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 v12 1/5] vmstate: Add support for an array of ptimer_state *
2013-12-13 1:19 [Qemu-devel] [PATCH v12 0/5] add allwinner A10 SoC support liguang
@ 2013-12-13 1:19 ` liguang
2013-12-13 3:22 ` Peter Crosthwaite
2013-12-13 1:19 ` [Qemu-devel] [PATCH v12 2/5] hw/timer: add allwinner a10 timer liguang
` (3 subsequent siblings)
4 siblings, 1 reply; 10+ messages in thread
From: liguang @ 2013-12-13 1:19 UTC (permalink / raw)
To: QEMU Developers
Cc: Peter Maydell, Peter Crosthwaite, Andreas Färber,
Juan Quintela
From: Peter Maydell <peter.maydell@linaro.org>
Add support for defining a vmstate field which is an array
of pointers to structures, and use this to define a
VMSTATE_PTIMER_ARRAY() which allows an array of ptimer_state*
to be used by devices.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
include/hw/ptimer.h | 4 ++++
include/migration/vmstate.h | 10 ++++++++++
2 files changed, 14 insertions(+), 0 deletions(-)
diff --git a/include/hw/ptimer.h b/include/hw/ptimer.h
index 28fcaf1..a33edf4 100644
--- a/include/hw/ptimer.h
+++ b/include/hw/ptimer.h
@@ -36,4 +36,8 @@ extern const VMStateDescription vmstate_ptimer;
.offset = vmstate_offset_pointer(_state, _field, ptimer_state), \
}
+#define VMSTATE_PTIMER_ARRAY(_f, _s, _n) \
+ VMSTATE_ARRAY_OF_POINTER_TO_STRUCT(_f, _s, _n, 0, \
+ vmstate_ptimer, ptimer_state)
+
#endif
diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index 9d09e60..be193ba 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -339,6 +339,16 @@ extern const VMStateInfo vmstate_info_bitmap;
.offset = vmstate_offset_array(_state, _field, _type, _num), \
}
+#define VMSTATE_ARRAY_OF_POINTER_TO_STRUCT(_f, _s, _n, _v, _vmsd, _type) { \
+ .name = (stringify(_f)), \
+ .version_id = (_v), \
+ .num = (_n), \
+ .vmsd = &(_vmsd), \
+ .size = sizeof(_type *), \
+ .flags = VMS_ARRAY|VMS_STRUCT|VMS_ARRAY_OF_POINTER, \
+ .offset = vmstate_offset_array(_s, _f, _type*, _n), \
+}
+
#define VMSTATE_STRUCT_ARRAY_TEST(_field, _state, _num, _test, _version, _vmsd, _type) { \
.name = (stringify(_field)), \
.num = (_num), \
--
1.7.2.5
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH v12 2/5] hw/timer: add allwinner a10 timer
2013-12-13 1:19 [Qemu-devel] [PATCH v12 0/5] add allwinner A10 SoC support liguang
2013-12-13 1:19 ` [Qemu-devel] [PATCH v12 1/5] vmstate: Add support for an array of ptimer_state * liguang
@ 2013-12-13 1:19 ` liguang
2013-12-13 20:17 ` Antony Pavlov
2013-12-13 1:19 ` [Qemu-devel] [PATCH v12 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-13 1:19 UTC (permalink / raw)
To: QEMU Developers
Cc: Peter Maydell, Peter Crosthwaite, Andreas Färber, liguang,
Juan Quintela
Signed-off-by: liguang <lig.fnst@cn.fujitsu.com>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
default-configs/arm-softmmu.mak | 2 +
hw/timer/Makefile.objs | 2 +
hw/timer/allwinner-a10-pit.c | 254 ++++++++++++++++++++++++++++++++++
include/hw/timer/allwinner-a10-pit.h | 59 ++++++++
4 files changed, 317 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..7858abf 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_PIT=y
diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
index eca5905..f6ace47 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_PIT) += 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..8bba5e2
--- /dev/null
+++ b/hw/timer/allwinner-a10-pit.c
@@ -0,0 +1,254 @@
+/*
+ * 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_END:
+ 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_END:
+ 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) {
+ uint64_t tmp_count = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+
+ s->count_lo = tmp_count;
+ s->count_hi = tmp_count >> 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_init(Object *obj)
+{
+ AwA10PITState *s = AW_A10_PIT(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ 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->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),
+ .instance_init = a10_pit_init,
+ .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..0e9e384
--- /dev/null
+++ b/include/hw/timer/allwinner-a10-pit.h
@@ -0,0 +1,59 @@
+#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_TIMER_BASE_END \
+ (AW_A10_PIT_TIMER_BASE * 6 + AW_A10_PIT_TIMER_COUNT)
+
+#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 v12 3/5] hw/intc: add allwinner A10 interrupt controller
2013-12-13 1:19 [Qemu-devel] [PATCH v12 0/5] add allwinner A10 SoC support liguang
2013-12-13 1:19 ` [Qemu-devel] [PATCH v12 1/5] vmstate: Add support for an array of ptimer_state * liguang
2013-12-13 1:19 ` [Qemu-devel] [PATCH v12 2/5] hw/timer: add allwinner a10 timer liguang
@ 2013-12-13 1:19 ` liguang
2013-12-13 1:19 ` [Qemu-devel] [PATCH v12 4/5] hw/arm: add allwinner a10 SoC support liguang
2013-12-13 1:19 ` [Qemu-devel] [PATCH v12 5/5] hw/arm: add cubieboard support liguang
4 siblings, 0 replies; 10+ messages in thread
From: liguang @ 2013-12-13 1:19 UTC (permalink / raw)
To: QEMU Developers
Cc: Peter Maydell, Peter Crosthwaite, Andreas Färber, liguang,
Juan Quintela
Signed-off-by: liguang <lig.fnst@cn.fujitsu.com>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
default-configs/arm-softmmu.mak | 1 +
hw/intc/Makefile.objs | 1 +
hw/intc/allwinner-a10-pic.c | 200 +++++++++++++++++++++++++++++++++++
include/hw/intc/allwinner-a10-pic.h | 40 +++++++
4 files changed, 242 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/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index 7858abf..e965068 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -83,3 +83,4 @@ CONFIG_SDHCI=y
CONFIG_INTEGRATOR_DEBUG=y
CONFIG_ALLWINNER_A10_PIT=y
+CONFIG_ALLWINNER_A10_PIC=y
diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
index 47ac442..60eb936 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_PIC) += 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..407d563
--- /dev/null
+++ b/hw/intc/allwinner-a10-pic.c
@@ -0,0 +1,200 @@
+/*
+ * 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;
+ int irq = 0, fiq = 0;
+
+ for (i = 0; i < AW_A10_PIC_REG_NUM; i++) {
+ irq |= s->irq_pending[i] & ~s->mask[i];
+ fiq |= s->select[i] & s->irq_pending[i] & ~s->mask[i];
+ }
+
+ 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_init(Object *obj)
+{
+ AwA10PICState *s = AW_A10_PIC(obj);
+ SysBusDevice *dev = SYS_BUS_DEVICE(obj);
+
+ 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,
+ TYPE_AW_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->reset = aw_a10_pic_reset;
+ dc->desc = "allwinner 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),
+ .instance_init = aw_a10_pic_init,
+ .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..5721b2e
--- /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 "allwinner-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 v12 4/5] hw/arm: add allwinner a10 SoC support
2013-12-13 1:19 [Qemu-devel] [PATCH v12 0/5] add allwinner A10 SoC support liguang
` (2 preceding siblings ...)
2013-12-13 1:19 ` [Qemu-devel] [PATCH v12 3/5] hw/intc: add allwinner A10 interrupt controller liguang
@ 2013-12-13 1:19 ` liguang
2013-12-13 1:19 ` [Qemu-devel] [PATCH v12 5/5] hw/arm: add cubieboard support liguang
4 siblings, 0 replies; 10+ messages in thread
From: liguang @ 2013-12-13 1:19 UTC (permalink / raw)
To: QEMU Developers
Cc: Peter Maydell, Peter Crosthwaite, Andreas Färber, liguang,
Juan Quintela
Signed-off-by: liguang <lig.fnst@cn.fujitsu.com>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
default-configs/arm-softmmu.mak | 1 +
hw/arm/Makefile.objs | 1 +
hw/arm/allwinner-a10.c | 103 +++++++++++++++++++++++++++++++++++++++
include/hw/arm/allwinner-a10.h | 35 +++++++++++++
4 files changed, 140 insertions(+), 0 deletions(-)
create mode 100644 hw/arm/allwinner-a10.c
create mode 100644 include/hw/arm/allwinner-a10.h
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index e965068..a19208f 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -84,3 +84,4 @@ CONFIG_INTEGRATOR_DEBUG=y
CONFIG_ALLWINNER_A10_PIT=y
CONFIG_ALLWINNER_A10_PIC=y
+CONFIG_ALLWINNER_A10=y
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 3671b42..012bd2c 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -5,3 +5,4 @@ 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-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o
diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
new file mode 100644
index 0000000..4658e19
--- /dev/null
+++ b/hw/arm/allwinner-a10.c
@@ -0,0 +1,103 @@
+/*
+ * Allwinner A10 SoC 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 "hw/arm/allwinner-a10.h"
+
+static void aw_a10_init(Object *obj)
+{
+ AwA10State *s = AW_A10(obj);
+
+ 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->intc), TYPE_AW_A10_PIC);
+ qdev_set_parent_bus(DEVICE(&s->intc), sysbus_get_default());
+
+ object_initialize(&s->timer, sizeof(s->timer), TYPE_AW_A10_PIT);
+ qdev_set_parent_bus(DEVICE(&s->timer), sysbus_get_default());
+}
+
+static void aw_a10_realize(DeviceState *dev, Error **errp)
+{
+ AwA10State *s = AW_A10(dev);
+ SysBusDevice *sysbusdev;
+ uint8_t i;
+ qemu_irq fiq, irq;
+ Error *err = NULL;
+
+ object_property_set_bool(OBJECT(&s->cpu), true, "realized", &err);
+ if (err != NULL) {
+ error_propagate(errp, err);
+ return;
+ }
+ irq = qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_IRQ);
+ fiq = qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_FIQ);
+
+ object_property_set_bool(OBJECT(&s->intc), true, "realized", &err);
+ if (err != NULL) {
+ error_propagate(errp, err);
+ return;
+ }
+ sysbusdev = SYS_BUS_DEVICE(&s->intc);
+ sysbus_mmio_map(sysbusdev, 0, AW_A10_PIC_REG_BASE);
+ sysbus_connect_irq(sysbusdev, 0, irq);
+ sysbus_connect_irq(sysbusdev, 1, fiq);
+ 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);
+ if (err != NULL) {
+ error_propagate(errp, err);
+ return;
+ }
+ 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..da36647
--- /dev/null
+++ b/include/hw/arm/allwinner-a10.h
@@ -0,0 +1,35 @@
+#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 "allwinner-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];
+ 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 v12 5/5] hw/arm: add cubieboard support
2013-12-13 1:19 [Qemu-devel] [PATCH v12 0/5] add allwinner A10 SoC support liguang
` (3 preceding siblings ...)
2013-12-13 1:19 ` [Qemu-devel] [PATCH v12 4/5] hw/arm: add allwinner a10 SoC support liguang
@ 2013-12-13 1:19 ` liguang
4 siblings, 0 replies; 10+ messages in thread
From: liguang @ 2013-12-13 1:19 UTC (permalink / raw)
To: QEMU Developers
Cc: Peter Maydell, Peter Crosthwaite, Andreas Färber, liguang,
Juan Quintela
Signed-off-by: liguang <lig.fnst@cn.fujitsu.com>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
hw/arm/Makefile.objs | 2 +-
hw/arm/cubieboard.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 70 insertions(+), 1 deletions(-)
create mode 100644 hw/arm/cubieboard.c
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 012bd2c..1dd94de 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -5,4 +5,4 @@ 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-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o
+obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
diff --git a/hw/arm/cubieboard.c b/hw/arm/cubieboard.c
new file mode 100644
index 0000000..3fcb6d2
--- /dev/null
+++ b/hw/arm/cubieboard.c
@@ -0,0 +1,69 @@
+/*
+ * cubieboard 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 "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 = "cubietech 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] 10+ messages in thread
* Re: [Qemu-devel] [PATCH v12 1/5] vmstate: Add support for an array of ptimer_state *
2013-12-13 1:19 ` [Qemu-devel] [PATCH v12 1/5] vmstate: Add support for an array of ptimer_state * liguang
@ 2013-12-13 3:22 ` Peter Crosthwaite
2013-12-13 5:29 ` Li Guang
0 siblings, 1 reply; 10+ messages in thread
From: Peter Crosthwaite @ 2013-12-13 3:22 UTC (permalink / raw)
To: liguang; +Cc: Peter Maydell, Juan Quintela, QEMU Developers,
Andreas Färber
On Fri, Dec 13, 2013 at 11:19 AM, liguang <lig.fnst@cn.fujitsu.com> wrote:
> From: Peter Maydell <peter.maydell@linaro.org>
>
> Add support for defining a vmstate field which is an array
> of pointers to structures, and use this to define a
> VMSTATE_PTIMER_ARRAY() which allows an array of ptimer_state*
> to be used by devices.
>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
If you are intending someones else patch for merge as part of your own
series, you should sign it off yourself. Considering it's only one
patch, you probably can just do this on list (just like a review)
rather than a respin.
Regards,
Peter
> ---
> include/hw/ptimer.h | 4 ++++
> include/migration/vmstate.h | 10 ++++++++++
> 2 files changed, 14 insertions(+), 0 deletions(-)
>
> diff --git a/include/hw/ptimer.h b/include/hw/ptimer.h
> index 28fcaf1..a33edf4 100644
> --- a/include/hw/ptimer.h
> +++ b/include/hw/ptimer.h
> @@ -36,4 +36,8 @@ extern const VMStateDescription vmstate_ptimer;
> .offset = vmstate_offset_pointer(_state, _field, ptimer_state), \
> }
>
> +#define VMSTATE_PTIMER_ARRAY(_f, _s, _n) \
> + VMSTATE_ARRAY_OF_POINTER_TO_STRUCT(_f, _s, _n, 0, \
> + vmstate_ptimer, ptimer_state)
> +
> #endif
> diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
> index 9d09e60..be193ba 100644
> --- a/include/migration/vmstate.h
> +++ b/include/migration/vmstate.h
> @@ -339,6 +339,16 @@ extern const VMStateInfo vmstate_info_bitmap;
> .offset = vmstate_offset_array(_state, _field, _type, _num), \
> }
>
> +#define VMSTATE_ARRAY_OF_POINTER_TO_STRUCT(_f, _s, _n, _v, _vmsd, _type) { \
> + .name = (stringify(_f)), \
> + .version_id = (_v), \
> + .num = (_n), \
> + .vmsd = &(_vmsd), \
> + .size = sizeof(_type *), \
> + .flags = VMS_ARRAY|VMS_STRUCT|VMS_ARRAY_OF_POINTER, \
> + .offset = vmstate_offset_array(_s, _f, _type*, _n), \
> +}
> +
> #define VMSTATE_STRUCT_ARRAY_TEST(_field, _state, _num, _test, _version, _vmsd, _type) { \
> .name = (stringify(_field)), \
> .num = (_num), \
> --
> 1.7.2.5
>
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH v12 1/5] vmstate: Add support for an array of ptimer_state *
2013-12-13 3:22 ` Peter Crosthwaite
@ 2013-12-13 5:29 ` Li Guang
0 siblings, 0 replies; 10+ messages in thread
From: Li Guang @ 2013-12-13 5:29 UTC (permalink / raw)
To: Peter Crosthwaite
Cc: Peter Maydell, QEMU Developers, Andreas Färber,
Juan Quintela
Peter Crosthwaite wrote:
> On Fri, Dec 13, 2013 at 11:19 AM, liguang<lig.fnst@cn.fujitsu.com> wrote:
>
>> From: Peter Maydell<peter.maydell@linaro.org>
>>
>> Add support for defining a vmstate field which is an array
>> of pointers to structures, and use this to define a
>> VMSTATE_PTIMER_ARRAY() which allows an array of ptimer_state*
>> to be used by devices.
>>
>> Signed-off-by: Peter Maydell<peter.maydell@linaro.org>
>>
> If you are intending someones else patch for merge as part of your own
> series, you should sign it off yourself. Considering it's only one
> patch, you probably can just do this on list (just like a review)
> rather than a respin.
>
>
Ok, here's a
Signed-off-by: liguang<lig.fnst@cn.fujitsu.com>
Thanks!
> Regards,
> Peter
>
>
>> ---
>> include/hw/ptimer.h | 4 ++++
>> include/migration/vmstate.h | 10 ++++++++++
>> 2 files changed, 14 insertions(+), 0 deletions(-)
>>
>> diff --git a/include/hw/ptimer.h b/include/hw/ptimer.h
>> index 28fcaf1..a33edf4 100644
>> --- a/include/hw/ptimer.h
>> +++ b/include/hw/ptimer.h
>> @@ -36,4 +36,8 @@ extern const VMStateDescription vmstate_ptimer;
>> .offset = vmstate_offset_pointer(_state, _field, ptimer_state), \
>> }
>>
>> +#define VMSTATE_PTIMER_ARRAY(_f, _s, _n) \
>> + VMSTATE_ARRAY_OF_POINTER_TO_STRUCT(_f, _s, _n, 0, \
>> + vmstate_ptimer, ptimer_state)
>> +
>> #endif
>> diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
>> index 9d09e60..be193ba 100644
>> --- a/include/migration/vmstate.h
>> +++ b/include/migration/vmstate.h
>> @@ -339,6 +339,16 @@ extern const VMStateInfo vmstate_info_bitmap;
>> .offset = vmstate_offset_array(_state, _field, _type, _num), \
>> }
>>
>> +#define VMSTATE_ARRAY_OF_POINTER_TO_STRUCT(_f, _s, _n, _v, _vmsd, _type) { \
>> + .name = (stringify(_f)), \
>> + .version_id = (_v), \
>> + .num = (_n), \
>> + .vmsd =&(_vmsd), \
>> + .size = sizeof(_type *), \
>> + .flags = VMS_ARRAY|VMS_STRUCT|VMS_ARRAY_OF_POINTER, \
>> + .offset = vmstate_offset_array(_s, _f, _type*, _n), \
>> +}
>> +
>> #define VMSTATE_STRUCT_ARRAY_TEST(_field, _state, _num, _test, _version, _vmsd, _type) { \
>> .name = (stringify(_field)), \
>> .num = (_num), \
>> --
>> 1.7.2.5
>>
>>
>>
>
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH v12 2/5] hw/timer: add allwinner a10 timer
2013-12-13 1:19 ` [Qemu-devel] [PATCH v12 2/5] hw/timer: add allwinner a10 timer liguang
@ 2013-12-13 20:17 ` Antony Pavlov
2013-12-16 1:45 ` Li Guang
0 siblings, 1 reply; 10+ messages in thread
From: Antony Pavlov @ 2013-12-13 20:17 UTC (permalink / raw)
To: liguang
Cc: Peter Maydell, Peter Crosthwaite, Juan Quintela, QEMU Developers,
Andreas Färber
On Fri, 13 Dec 2013 09:19:08 +0800
liguang <lig.fnst@cn.fujitsu.com> wrote:
> Signed-off-by: liguang <lig.fnst@cn.fujitsu.com>
> Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
> ---
> default-configs/arm-softmmu.mak | 2 +
> hw/timer/Makefile.objs | 2 +
> hw/timer/allwinner-a10-pit.c | 254 ++++++++++++++++++++++++++++++++++
> include/hw/timer/allwinner-a10-pit.h | 59 ++++++++
> 4 files changed, 317 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..7858abf 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_PIT=y
> diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
> index eca5905..f6ace47 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_PIT) += 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..8bba5e2
> --- /dev/null
> +++ b/hw/timer/allwinner-a10-pit.c
> @@ -0,0 +1,254 @@
> +/*
> + * 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_END:
> + 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_END:
> + 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) {
> + uint64_t tmp_count = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
> +
> + s->count_lo = tmp_count;
> + s->count_hi = tmp_count >> 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_init(Object *obj)
> +{
> + AwA10PITState *s = AW_A10_PIT(obj);
> + SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
> + 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);
please fix extra whitespaces here.
> +
> + 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),
> + .instance_init = a10_pit_init,
> + .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..0e9e384
> --- /dev/null
> +++ b/include/hw/timer/allwinner-a10-pit.h
> @@ -0,0 +1,59 @@
> +#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_TIMER_BASE_END \
> + (AW_A10_PIT_TIMER_BASE * 6 + AW_A10_PIT_TIMER_COUNT)
> +
> +#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;
please fix extra whitespaces here.
> + 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
> +
And here.
> --
> 1.7.2.5
>
>
--
Best regards,
Antony Pavlov
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH v12 2/5] hw/timer: add allwinner a10 timer
2013-12-13 20:17 ` Antony Pavlov
@ 2013-12-16 1:45 ` Li Guang
0 siblings, 0 replies; 10+ messages in thread
From: Li Guang @ 2013-12-16 1:45 UTC (permalink / raw)
To: Antony Pavlov
Cc: Peter Maydell, Peter Crosthwaite, QEMU Developers,
Andreas Färber, Juan Quintela
Antony Pavlov wrote:
> On Fri, 13 Dec 2013 09:19:08 +0800
> liguang<lig.fnst@cn.fujitsu.com> wrote:
>
>
>> Signed-off-by: liguang<lig.fnst@cn.fujitsu.com>
>> Reviewed-by: Peter Crosthwaite<peter.crosthwaite@xilinx.com>
>> ---
>> default-configs/arm-softmmu.mak | 2 +
>> hw/timer/Makefile.objs | 2 +
>> hw/timer/allwinner-a10-pit.c | 254 ++++++++++++++++++++++++++++++++++
>> include/hw/timer/allwinner-a10-pit.h | 59 ++++++++
>> 4 files changed, 317 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..7858abf 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_PIT=y
>> diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
>> index eca5905..f6ace47 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_PIT) += 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..8bba5e2
>> --- /dev/null
>> +++ b/hw/timer/allwinner-a10-pit.c
>> @@ -0,0 +1,254 @@
>> +/*
>> + * 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_END:
>> + 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_END:
>> + 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) {
>> + uint64_t tmp_count = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
>> +
>> + s->count_lo = tmp_count;
>> + s->count_hi = tmp_count>> 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_init(Object *obj)
>> +{
>> + AwA10PITState *s = AW_A10_PIT(obj);
>> + SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
>> + 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);
>>
> please fix extra whitespaces here.
>
>
>> +
>> + 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),
>> + .instance_init = a10_pit_init,
>> + .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..0e9e384
>> --- /dev/null
>> +++ b/include/hw/timer/allwinner-a10-pit.h
>> @@ -0,0 +1,59 @@
>> +#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_TIMER_BASE_END \
>> + (AW_A10_PIT_TIMER_BASE * 6 + AW_A10_PIT_TIMER_COUNT)
>> +
>> +#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;
>>
> please fix extra whitespaces here.
>
>
>> + 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
>> +
>>
> And here.
>
>
Ok, will remove odd spaces.
Thanks!
>> --
>> 1.7.2.5
>>
>>
>>
>
> --
> Best regards,
> Antony Pavlov
>
>
>
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2013-12-16 1:48 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-12-13 1:19 [Qemu-devel] [PATCH v12 0/5] add allwinner A10 SoC support liguang
2013-12-13 1:19 ` [Qemu-devel] [PATCH v12 1/5] vmstate: Add support for an array of ptimer_state * liguang
2013-12-13 3:22 ` Peter Crosthwaite
2013-12-13 5:29 ` Li Guang
2013-12-13 1:19 ` [Qemu-devel] [PATCH v12 2/5] hw/timer: add allwinner a10 timer liguang
2013-12-13 20:17 ` Antony Pavlov
2013-12-16 1:45 ` Li Guang
2013-12-13 1:19 ` [Qemu-devel] [PATCH v12 3/5] hw/intc: add allwinner A10 interrupt controller liguang
2013-12-13 1:19 ` [Qemu-devel] [PATCH v12 4/5] hw/arm: add allwinner a10 SoC support liguang
2013-12-13 1:19 ` [Qemu-devel] [PATCH v12 5/5] hw/arm: add cubieboard support liguang
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).