All of lore.kernel.org
 help / color / mirror / Atom feed
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
>
>
>    

  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.