From: Li Guang <lig.fnst@cn.fujitsu.com>
To: Antony Pavlov <antonynpavlov@gmail.com>
Cc: "Peter Maydell" <peter.maydell@linaro.org>,
"Peter Crosthwaite" <peter.crosthwaite@xilinx.com>,
"QEMU Developers" <qemu-devel@nongnu.org>,
"Andreas Färber" <afaerber@suse.de>,
"Juan Quintela" <quintela@redhat.com>
Subject: Re: [Qemu-devel] [PATCH v12 2/5] hw/timer: add allwinner a10 timer
Date: Mon, 16 Dec 2013 09:45:57 +0800 [thread overview]
Message-ID: <52AE5B55.3010708@cn.fujitsu.com> (raw)
In-Reply-To: <20131214001724.42a13430bd5e02086073adf0@gmail.com>
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
>
>
>
next prev parent reply other threads:[~2013-12-16 1:48 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
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 [this message]
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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=52AE5B55.3010708@cn.fujitsu.com \
--to=lig.fnst@cn.fujitsu.com \
--cc=afaerber@suse.de \
--cc=antonynpavlov@gmail.com \
--cc=peter.crosthwaite@xilinx.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
--cc=quintela@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.