qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "KONRAD Frédéric" <fred.konrad@greensocs.com>
To: Dante <dantesu@faraday-tech.com>
Cc: peter.maydell@linaro.org, qemu-devel@nongnu.org,
	"Andreas Färber" <afaerber@suse.de>,
	paul@codesourcery.com
Subject: Re: [Qemu-devel] [PATCH 16/18] hw: add QEMU model for Faraday RTC timer
Date: Fri, 18 Jan 2013 09:44:00 +0100	[thread overview]
Message-ID: <50F90B50.2050408@greensocs.com> (raw)
In-Reply-To: <1358490767-18723-1-git-send-email-dantesu@faraday-tech.com>

On 18/01/2013 07:32, Dante wrote:
> Signed-off-by: Kuo-Jung Su <dantesu@faraday-tech.com>
> ---
>   hw/ftrtc011.c |  308 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 308 insertions(+)
>   create mode 100644 hw/ftrtc011.c
>
> diff --git a/hw/ftrtc011.c b/hw/ftrtc011.c
> new file mode 100644
> index 0000000..466cbb6
> --- /dev/null
> +++ b/hw/ftrtc011.c
> @@ -0,0 +1,308 @@
> +/*
> + * QEMU model of the FTRTC011 RTC Timer
> + *
> + * Copyright (C) 2012 Faraday Technology
> + * Copyright (C) 2012 Dante Su <dantesu@faraday-tech.com>
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#include "sysbus.h"
> +#include "sysemu/sysemu.h"
> +#include "qemu/timer.h"
> +
> +/* Hardware registers */
> +#define REG_SEC            0x00
> +#define REG_MIN            0x04
> +#define REG_HOUR        0x08
> +#define REG_DAY            0x0C
> +
> +#define REG_ALARM_SEC    0x10
> +#define REG_ALARM_MIN    0x14
> +#define REG_ALARM_HOUR    0x18
> +
> +#define REG_CR            0x20
> +#define REG_WSEC        0x24
> +#define REG_WMIN        0x28
> +#define REG_WHOUR        0x2C
> +#define REG_WDAY        0x30
> +#define REG_ISR            0x34
> +
> +#define REG_REV            0x3C
> +#define REG_CURRENT        0x44
> +
> +enum ftrtc011_irqpin {
> +    IRQ_ALARM_LEVEL = 0,
> +    IRQ_ALARM_EDGE,
> +    IRQ_SEC,
> +    IRQ_MIN,
> +    IRQ_HOUR,
> +    IRQ_DAY,
> +};
> +
> +typedef struct {
> +    SysBusDevice busdev;
> +    MemoryRegion mmio;
> +
> +    qemu_irq irq[6];
> +
> +    QEMUTimer *qtimer;
> +
> +    uint8_t sec;
> +    uint8_t min;
> +    uint8_t hr;
> +    uint32_t day;
> +
> +    uint8_t alarm_sec;
> +    uint8_t alarm_min;
> +    uint8_t alarm_hr;
> +
> +    uint32_t cr;
> +    uint32_t isr;
> +
> +} ftrtc011_state;
> +
> +/* Update interrupts.  */
> +static inline void ftrtc011_update_irq(ftrtc011_state *s)
> +{
> +    uint32_t mask = ((s->cr >> 1) & 0x1f) & s->isr;
> +
> +    qemu_set_irq(s->irq[IRQ_ALARM_LEVEL], (mask & 0x10) ? 1 : 0);
> +
> +    if (mask) {
> +        if (mask & 0x01)
> +            qemu_irq_pulse(s->irq[IRQ_SEC]);
> +        if (mask & 0x02)
> +            qemu_irq_pulse(s->irq[IRQ_MIN]);
> +        if (mask & 0x04)
> +            qemu_irq_pulse(s->irq[IRQ_HOUR]);
> +        if (mask & 0x08)
> +            qemu_irq_pulse(s->irq[IRQ_DAY]);
> +        if (mask & 0x10)
> +            qemu_irq_pulse(s->irq[IRQ_ALARM_EDGE]);
> +    }
> +}
> +
> +static uint64_t ftrtc011_mem_read(void *opaque, hwaddr addr, unsigned int size)
> +{
> +    ftrtc011_state *s = opaque;
> +    uint32_t rc = 0;
> +
> +    switch (addr) {
> +    case REG_SEC:
> +        return s->sec;
> +    case REG_MIN:
> +        return s->min;
> +    case REG_HOUR:
> +        return s->hr;
> +    case REG_DAY:
> +        return s->day;
> +    case REG_ALARM_SEC:
> +        return s->alarm_sec;
> +    case REG_ALARM_MIN:
> +        return s->alarm_min;
> +    case REG_ALARM_HOUR:
> +        return s->alarm_hr;
> +    case REG_CR:
> +        return s->cr;
> +    case REG_ISR:
> +        return s->isr;
> +    case REG_REV:
> +        return 0x00010000;
> +    case REG_CURRENT:
> +        return (s->day << 17) | (s->hr << 12) | (s->min << 6) | (s->sec);
> +    default:
> +        break;
> +    }
> +
> +    return rc;
> +}
> +
> +static void ftrtc011_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size)
> +{
> +    ftrtc011_state *s = opaque;
> +
> +    switch (addr) {
> +    case REG_ALARM_SEC:
> +        s->alarm_sec = (uint32_t)val;
> +        break;
> +    case REG_ALARM_MIN:
> +        s->alarm_min = (uint32_t)val;
> +        break;
> +    case REG_ALARM_HOUR:
> +        s->alarm_hr = (uint32_t)val;
> +        break;
> +    case REG_WSEC:
> +        s->sec = (uint32_t)val;
> +        break;
> +    case REG_WMIN:
> +        s->min = (uint32_t)val;
> +        break;
> +    case REG_WHOUR:
> +        s->hr = (uint32_t)val;
> +        break;
> +    case REG_WDAY:
> +        s->day = (uint32_t)val;
> +        break;
> +    case REG_CR:
> +        s->cr = (uint32_t)val;
> +        if (s->cr & 0x01) {
> +            qemu_mod_timer(s->qtimer, qemu_get_clock_ns(vm_clock) + get_ticks_per_sec());
> +        } else {
> +            qemu_del_timer(s->qtimer);
> +        }
> +        break;
> +    case REG_ISR:
> +        s->isr &= ~((uint32_t)val);
> +        ftrtc011_update_irq(s);
> +        break;
> +    default:
> +        break;
> +    }
> +}
> +
> +static const MemoryRegionOps bus_ops = {
> +    .read  = ftrtc011_mem_read,
> +    .write = ftrtc011_mem_write,
> +    .endianness = DEVICE_LITTLE_ENDIAN,
> +    .valid = {
> +        .min_access_size = 4,
> +        .max_access_size = 4
> +    }
> +};
> +
> +static void ftrtc011_timer_tick(void *opaque)
> +{
> +    ftrtc011_state *s = (ftrtc011_state *)opaque;
Didn't that need OBJECT_CHECK for QOM? (See below).
> +
> +    s->sec += 1;
> +    if (s->cr & (1 << 1))
> +        s->isr |= (1 << 0);
> +
> +    if (s->sec >= 60) {
> +        s->sec = 0;
> +        s->min += 1;
> +        if (s->cr & (1 << 2))
> +            s->isr |= (1 << 1);
> +
> +        if (s->min >= 60) {
> +            s->min = 0;
> +            s->hr += 1;
> +            if (s->cr & (1 << 3))
> +                s->isr |= (1 << 2);
> +
> +            if (s->hr >= 24) {
> +                s->hr = 0;
> +                s->day += 1;
> +                if (s->cr & (1 << 4))
> +                    s->isr |= (1 << 3);
> +            }
> +        }
> +    }
> +
> +    /* alarm interrupt */
> +    if (s->cr & (1 << 5)) {
> +        if ((s->sec | (s->min << 8) | (s->hr << 16)) ==
> +            (s->alarm_sec | (s->alarm_min << 8) | (s->alarm_hr << 16))) {
> +            s->isr |= (1 << 4);
> +        }
> +    }
> +
> +    /* send interrupt signal */
> +    ftrtc011_update_irq(s);
> +
> +    qemu_mod_timer(s->qtimer, qemu_get_clock_ns(vm_clock) + get_ticks_per_sec());
> +}
> +
> +static void ftrtc011_reset(DeviceState *d)
> +{
> +    ftrtc011_state *s = DO_UPCAST(ftrtc011_state, busdev.qdev, d);
As far as I understand this is not QOM (someone correct me if I'm wrong):

You must introduce QOM macros in header:

#define TYPE_FTRTC011 "ftrtc011"
#define TRTC011_GET_CLASS(obj) \
         OBJECT_GET_CLASS(ftrtc011_state, obj, TYPE_FTRTC011)
#define FTRTC011_CLASS(klass) \
         OBJECT_CLASS_CHECK(ftrtc011_state, klass, TYPE_FTRTC011)
#define FTRTC011(obj) \
         OBJECT_CHECK(ftrtc011_state, (obj), TYPE_FTRTC011)

Then use FTRTC011(d) instead of DO_UPCAST(...)

> +
> +    s->sec = 0;
> +    s->min = 0;
> +    s->hr  = 0;
> +    s->day = 0;
> +    s->alarm_sec = 0;
> +    s->alarm_min = 0;
> +    s->alarm_hr  = 0;
> +
> +    ftrtc011_update_irq(s);
> +}
> +
> +static int ftrtc011_init(SysBusDevice *dev)
> +{
> +    ftrtc011_state *s = FROM_SYSBUS(typeof(*s), dev);
The same.
> +
> +    s->qtimer = qemu_new_timer_ns(vm_clock, ftrtc011_timer_tick, s);
> +
> +    memory_region_init_io(&s->mmio, &bus_ops, s, "ftrtc011", 0x1000);
> +    sysbus_init_mmio(dev, &s->mmio);
> +    sysbus_init_irq(dev, &s->irq[IRQ_ALARM_LEVEL]);
> +    sysbus_init_irq(dev, &s->irq[IRQ_ALARM_EDGE]);
> +    sysbus_init_irq(dev, &s->irq[IRQ_SEC]);
> +    sysbus_init_irq(dev, &s->irq[IRQ_MIN]);
> +    sysbus_init_irq(dev, &s->irq[IRQ_HOUR]);
> +    sysbus_init_irq(dev, &s->irq[IRQ_DAY]);
> +
> +    return 0;
> +}
> +
> +static const VMStateDescription vmstate_ftrtc011 = {
> +    .name = "ftrtc011",
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .minimum_version_id_old = 1,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_UINT8(sec, ftrtc011_state),
> +        VMSTATE_UINT8(min, ftrtc011_state),
> +        VMSTATE_UINT8(hr, ftrtc011_state),
> +        VMSTATE_UINT32(day, ftrtc011_state),
> +        VMSTATE_UINT8(alarm_sec, ftrtc011_state),
> +        VMSTATE_UINT8(alarm_min, ftrtc011_state),
> +        VMSTATE_UINT8(alarm_hr, ftrtc011_state),
> +        VMSTATE_UINT32(cr, ftrtc011_state),
> +        VMSTATE_UINT32(isr, ftrtc011_state),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static void ftrtc011_class_init(ObjectClass *klass, void *data)
> +{
> +    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
> +    DeviceClass *k = DEVICE_CLASS(klass);
> +
> +    sdc->init  = ftrtc011_init;
> +    k->vmsd    = &vmstate_ftrtc011;
> +    k->reset   = ftrtc011_reset;
> +    k->no_user = 1;
> +}
> +
> +static TypeInfo ftrtc011_info = {
static *const* TypeInfo ftrtc011_info
> +    .name           = "ftrtc011",
> +    .parent         = TYPE_SYS_BUS_DEVICE,
> +    .instance_size  = sizeof(ftrtc011_state),
> +    .class_init     = ftrtc011_class_init,
> +};
> +
> +static void ftrtc011_register_types(void)
> +{
> +    type_register_static(&ftrtc011_info);
> +}
> +
> +type_init(ftrtc011_register_types)

  reply	other threads:[~2013-01-18  8:44 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-01-18  6:32 [Qemu-devel] [PATCH 16/18] hw: add QEMU model for Faraday RTC timer Dante
2013-01-18  8:44 ` KONRAD Frédéric [this message]
2013-01-18 10:43   ` Andreas Färber
2013-01-21  1:44     ` [Qemu-devel] [PATCH 16/18] hw: add QEMU model for Faraday RTCtimer Dante Kuo-Jung Su(蘇國榮)
2013-01-21  1:28   ` Dante Kuo-Jung Su(蘇國榮)

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=50F90B50.2050408@greensocs.com \
    --to=fred.konrad@greensocs.com \
    --cc=afaerber@suse.de \
    --cc=dantesu@faraday-tech.com \
    --cc=paul@codesourcery.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    /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 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).