qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v5 05/24] hw/arm: add Faraday FTDDRII030 support


From: Kuo-Jung Su
Subject: Re: [Qemu-devel] [PATCH v5 05/24] hw/arm: add Faraday FTDDRII030 support
Date: Mon, 4 Mar 2013 14:32:44 +0800

2013/3/4 Peter Crosthwaite <address@hidden>:
> Hi Kuo-Jung,
>
> On Wed, Feb 27, 2013 at 5:15 PM, Kuo-Jung Su <address@hidden> wrote:
>> From: Kuo-Jung Su <address@hidden>
>>
>> The FTDDRII030 is a DDRII SDRAM controller which is responsible for
>> SDRAM initialization.
>> In QEMU we emualte only the SDRAM enable function.
>>
>
> "emulate"
>

Got it, thanks

>> Signed-off-by: Kuo-Jung Su <address@hidden>
>> ---
>>  hw/arm/Makefile.objs      |    1 +
>>  hw/arm/faraday_a369_soc.c |    3 +
>>  hw/arm/ftddrii030.c       |  171 
>> +++++++++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 175 insertions(+)
>>  create mode 100644 hw/arm/ftddrii030.c
>>
>> diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
>> index 33c9482..2a4c7d6 100644
>> --- a/hw/arm/Makefile.objs
>> +++ b/hw/arm/Makefile.objs
>> @@ -39,3 +39,4 @@ obj-y += faraday_a369.o \
>>              faraday_a369_kpd.o
>>  obj-y += ftintc020.o
>>  obj-y += ftahbc020.o
>> +obj-y += ftddrii030.o
>> diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
>> index e7343d9..fdf13f8 100644
>> --- a/hw/arm/faraday_a369_soc.c
>> +++ b/hw/arm/faraday_a369_soc.c
>> @@ -148,6 +148,9 @@ a369soc_device_init(FaradaySoCState *s)
>>
>>      /* ftahbc020 */
>>      s->ahbc = sysbus_create_simple("ftahbc020", 0x94000000, NULL);
>> +
>> +    /* ftddrii030 */
>> +    s->ddrc = sysbus_create_simple("ftddrii030", 0x93100000, NULL);
>>  }
>>
>>  static int a369soc_init(SysBusDevice *busdev)
>> diff --git a/hw/arm/ftddrii030.c b/hw/arm/ftddrii030.c
>> new file mode 100644
>> index 0000000..1679bef
>> --- /dev/null
>> +++ b/hw/arm/ftddrii030.c
>> @@ -0,0 +1,171 @@
>> +/*
>> + * Faraday DDRII controller
>> + *
>> + * Copyright (c) 2012 Faraday Technology
>> + * Written by Dante Su <address@hidden>
>> + *
>> + * This code is licensed under GNU GPL v2+
>> + */
>> +
>> +#include "hw/hw.h"
>> +#include "hw/sysbus.h"
>> +#include "hw/devices.h"
>> +#include "sysemu/sysemu.h"
>> +
>> +#include "faraday.h"
>> +
>> +#define REG_MCR             0x00    /* memory configuration register */
>> +#define REG_MSR             0x04    /* memory status register */
>> +#define REG_REVR            0x50    /* revision register */
>> +
>> +#define MSR_INIT_OK         BIT(8)  /* DDR2 initial is completed */
>> +#define MSR_CMD_MRS         BIT(0)  /* start MRS command */
>> +
>> +#define CFG_REGSIZE         (0x50 / 4)
>> +
>> +#define TYPE_FTDDRII030     "ftddrii030"
>> +
>> +typedef struct Ftddrii030State {
>> +    SysBusDevice busdev;
>> +    MemoryRegion iomem;
>> +
>> +    /* HW register cache */
>> +    uint32_t regs[CFG_REGSIZE];
>> +} Ftddrii030State;
>> +
>> +#define FTDDRII030(obj) \
>> +    OBJECT_CHECK(Ftddrii030State, obj, TYPE_FTDDRII030)
>> +
>> +#define DDR_REG32(s, off) \
>> +    *(uint32_t *)((uint8_t *)(s)->regs + (off))
>
> Strange. You are forcing alignment in your memory region ops so Im not
> sure I see the need for this. Cant you just index directly ...
>

Sure, it's just a coding style which I used to write hardware access
macros for chip drivers.

>> +
>> +static uint64_t
>> +ftddrii030_mem_read(void *opaque, hwaddr addr, unsigned size)
>> +{
>> +    Ftddrii030State *s = FTDDRII030(opaque);
>> +    FaradaySoCState *soc = FARADAY_SOC_GET_CORE();
>> +    uint64_t ret = 0;
>> +
>> +    if (soc->ddr_inited) {
>> +        DDR_REG32(s, REG_MSR) |= MSR_INIT_OK;
>
> ... like this?
>
> s->regs[REG_MSR/4] |= MSR_INIT_OK
>
>> +    }
>> +
>> +    switch (addr) {
>> +    case REG_MCR ... 0x4c:
>
> s/0x4c/CFG_REGSIZE or something like it. I think you can define you
> macros to get rid of this magic number that is really just the end of
> your CFG_REGSIZE definition.
>

Got it, thanks

>> +        ret = s->regs[addr / 4];
>> +        break;
>> +    case REG_REVR:
>> +        ret = 0x100;    /* rev. = 0.1.0 */
>> +        break;
>> +    default:
>> +        qemu_log_mask(LOG_GUEST_ERROR,
>> +                      "ftddrii030: undefined memory address@hidden", addr);
>> +        break;
>> +    }
>> +
>> +    return ret;
>> +}
>> +
>> +static void
>> +ftddrii030_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
>> +{
>> +    Ftddrii030State *s = FTDDRII030(opaque);
>> +    FaradaySoCState *soc = FARADAY_SOC_GET_CORE();
>> +
>> +    switch (addr) {
>> +    case REG_MCR:
>> +        DDR_REG32(s, REG_MCR) = (uint32_t)val & 0xffff;
>> +        break;
>> +    case REG_MSR:
>> +        val = (val & 0x3f) | (DDR_REG32(s, REG_MSR) & MSR_INIT_OK);
>> +        if (!soc->ddr_inited && (val & MSR_CMD_MRS)) {
>> +            val &= ~MSR_CMD_MRS;
>> +            val |= MSR_INIT_OK;
>> +            memory_region_add_subregion(soc->as, soc->ram_base, soc->ram);
>> +            soc->ddr_inited = true;
>> +        }
>> +        DDR_REG32(s, REG_MSR) = (uint32_t)val;
>> +        break;
>> +    case 0x08 ... 0x4c: /* DDRII Timing, ECC ...etc. */
>> +        s->regs[addr / 4] = (uint32_t)val;
>> +        break;
>> +    default:
>> +        qemu_log_mask(LOG_GUEST_ERROR,
>> +                      "ftddrii030: undefined memory address@hidden", addr);
>> +        break;
>> +    }
>> +}
>> +
>> +static const MemoryRegionOps mmio_ops = {
>> +    .read  = ftddrii030_mem_read,
>> +    .write = ftddrii030_mem_write,
>> +    .endianness = DEVICE_LITTLE_ENDIAN,
>> +    .valid = {
>> +        .min_access_size = 4,
>> +        .max_access_size = 4,
>> +    }
>> +};
>> +
>> +static void ftddrii030_reset(DeviceState *ds)
>> +{
>> +    SysBusDevice *busdev = SYS_BUS_DEVICE(ds);
>> +    Ftddrii030State *s = FTDDRII030(FROM_SYSBUS(Ftddrii030State, busdev));
>> +    FaradaySoCState *soc = FARADAY_SOC_GET_CORE();
>> +
>> +    if (soc->ddr_inited && !soc->bi) {
>> +        memory_region_del_subregion(soc->as, soc->ram);
>> +        soc->ddr_inited = false;
>> +    }
>> +
>> +    memset(s->regs, 0, sizeof(s->regs));
>> +}
>> +
>> +static int ftddrii030_init(SysBusDevice *dev)
>> +{
>> +    Ftddrii030State *s = FTDDRII030(FROM_SYSBUS(Ftddrii030State, dev));
>> +
>> +    memory_region_init_io(&s->iomem,
>> +                          &mmio_ops,
>> +                          s,
>> +                          TYPE_FTDDRII030,
>> +                          0x1000);
>> +    sysbus_init_mmio(dev, &s->iomem);
>> +    return 0;
>> +}
>> +
>> +static const VMStateDescription vmstate_ftddrii030 = {
>> +    .name = TYPE_FTDDRII030,
>> +    .version_id = 1,
>> +    .minimum_version_id = 1,
>> +    .minimum_version_id_old = 1,
>> +    .fields = (VMStateField[]) {
>> +        VMSTATE_UINT32_ARRAY(regs, Ftddrii030State, CFG_REGSIZE),
>> +        VMSTATE_END_OF_LIST(),
>> +    }
>> +};
>> +
>> +static void ftddrii030_class_init(ObjectClass *klass, void *data)
>> +{
>> +    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
>> +    DeviceClass *dc = DEVICE_CLASS(klass);
>> +
>> +    k->init   = ftddrii030_init;
>> +    dc->desc  = TYPE_FTDDRII030;
>> +    dc->vmsd  = &vmstate_ftddrii030;
>> +    dc->reset = ftddrii030_reset;
>> +    dc->no_user = 1;
>> +}
>> +
>> +static const TypeInfo ftddrii030_info = {
>> +    .name          = TYPE_FTDDRII030,
>> +    .parent        = TYPE_FARADAY_SOC,
>> +    .instance_size = sizeof(Ftddrii030State),
>> +    .class_init    = ftddrii030_class_init,
>> +};
>> +
>> +static void ftddrii030_register_types(void)
>> +{
>> +    type_register_static(&ftddrii030_info);
>> +}
>> +
>> +type_init(ftddrii030_register_types)
>> --
>> 1.7.9.5
>>
>>



-- 
Best wishes,
Kuo-Jung Su



reply via email to

[Prev in Thread] Current Thread [Next in Thread]