qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
  • * Re: [Qemu-devel] [PATCH v5 02/24] hw/arm: add Faraday a369 SoC platform support
           [not found] ` <1361949350-22241-3-git-send-email-dantesu@gmail.com>
           [not found]   ` <5130F9D8.3030200@gmail.com>
    @ 2013-03-02  3:43   ` Peter Crosthwaite
      2013-03-04  6:09     ` Kuo-Jung Su
      1 sibling, 1 reply; 15+ messages in thread
    From: Peter Crosthwaite @ 2013-03-02  3:43 UTC (permalink / raw)
      To: Kuo-Jung Su
      Cc: Peter Maydell, i.mitsyanko, qemu-devel, Blue Swirl, Paul Brook,
    	Kuo-Jung Su, Andreas, fred.konrad
    
    Hi Kuo-Jung,
    
    On Wed, Feb 27, 2013 at 5:15 PM, Kuo-Jung Su <dantesu@gmail.com> wrote:
    > From: Kuo-Jung Su <dantesu@faraday-tech.com>
    >
    > The Faraday A369 EVB is a Faraday SoC platform evalution board used for
    > Faraday IP functional verification based on the well-known ARM AMBA 2.0
    > architecture.
    >
    > Signed-off-by: Kuo-Jung Su <dantesu@faraday-tech.com>
    > ---
    >  hw/arm/Makefile.objs      |    4 +
    >  hw/arm/faraday.h          |   65 +++++++++++++
    >  hw/arm/faraday_a369.c     |   94 ++++++++++++++++++
    >  hw/arm/faraday_a369_kpd.c |  237 +++++++++++++++++++++++++++++++++++++++++++++
    >  hw/arm/faraday_a369_scu.c |  187 +++++++++++++++++++++++++++++++++++
    >  hw/arm/faraday_a369_soc.c |  197 +++++++++++++++++++++++++++++++++++++
    >  hw/arm/ftkbc010.h         |   42 ++++++++
    >  7 files changed, 826 insertions(+)
    >  create mode 100644 hw/arm/faraday.h
    >  create mode 100644 hw/arm/faraday_a369.c
    >  create mode 100644 hw/arm/faraday_a369_kpd.c
    >  create mode 100644 hw/arm/faraday_a369_scu.c
    >  create mode 100644 hw/arm/faraday_a369_soc.c
    >  create mode 100644 hw/arm/ftkbc010.h
    >
    > diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
    > index 6d049e7..f6fd60d 100644
    > --- a/hw/arm/Makefile.objs
    > +++ b/hw/arm/Makefile.objs
    > @@ -33,3 +33,7 @@ obj-y += kzm.o
    >  obj-$(CONFIG_FDT) += ../device_tree.o
    >
    >  obj-y := $(addprefix ../,$(obj-y))
    > +obj-y += faraday_a369.o \
    > +            faraday_a369_soc.o \
    > +            faraday_a369_scu.o \
    > +            faraday_a369_kpd.o
    > diff --git a/hw/arm/faraday.h b/hw/arm/faraday.h
    > new file mode 100644
    > index 0000000..d6ed860
    > --- /dev/null
    > +++ b/hw/arm/faraday.h
    > @@ -0,0 +1,65 @@
    > +/*
    > + * Faraday SoC platform support.
    > + *
    > + * Copyright (c) 2013 Faraday Technology
    > + * Written by Kuo-Jung Su <dantesu@gmail.com>
    > + *
    > + * This code is licensed under the GNU GPL v2.
    > + */
    > +#ifndef HW_ARM_FARADAY_H
    > +#define HW_ARM_FARADAY_H
    > +
    > +#include "hw/flash.h"
    > +#include "qemu/bitops.h"
    > +
    > +#ifdef DEBUG_FARADAY
    > +#define DPRINTF(fmt, ...) \
    > +    do { printf("faraday: " fmt , ## __VA_ARGS__); } while (0)
    > +#else
    > +#define DPRINTF(fmt, ...) \
    > +    do { } while (0)
    > +#endif
    > +
    > +typedef struct FaradaySoCState {
    > +    SysBusDevice busdev;
    > +    hwaddr       rom_base;
    > +    uint64_t     rom_size;
    > +    hwaddr       ram_base;
    > +    uint64_t     ram_size;
    > +    char         *cpu_model;
    > +    ARMCPU       *cpu;
    > +    DeviceState  *scu;      /* System Control Unit */
    > +    DeviceState  *ahbc;     /* AHB controller */
    > +    DeviceState  *ddrc;     /* DDR controller */
    > +    DeviceState  *hdma[2];  /* AHB DMA */
    > +    DeviceState  *pdma[1];  /* APB DMA */
    > +    DeviceState  *spi[2];
    
    Your two spi controllers are completely unrelated to each other. They
    are different devices so I don't see a win in lumping them together in
    a single array - there's no scope for iterating over this array. I
    think it would be cleaner if they were separate variables as you would
    then be able to provide more descriptive names "DeviceState
    *spi_flash", or even better, the actual name of the device
    "DeviceState *ftspi020". The same may be true for I2C, ill get around
    to that shortly!
    
    > +    DeviceState  *i2c[2];
    > +    DeviceState  *i2s[2];
    > +    DeviceState  *codec;    /* Audio codec */
    > +    void (*codec_out)(void *, uint32_t);
    > +    uint32_t (*codec_in)(void *);
    > +
    > +    MemoryRegion *as;
    > +    MemoryRegion *ram;
    > +    pflash_t     *rom;
    > +    MemoryRegion *sram;
    > +
    > +    void         *priv;
    > +
    > +    uint32_t ahb_slave[32];
    > +    uint32_t apb_slave[32];
    > +    bool     ahb_remapped;
    > +    bool     ddr_inited;
    > +    struct arm_boot_info *bi;
    > +} FaradaySoCState;
    > +
    > +/* SoC common APIs */
    > +#define TYPE_FARADAY_SOC    "faraday/soc"
    > +#define FARADAY_SOC(obj) \
    > +    OBJECT_CHECK(FaradaySoCState, obj, TYPE_FARADAY_SOC)
    > +#define FARADAY_SOC_GET_CORE() \
    > +    FARADAY_SOC(object_resolve_path_component(qdev_get_machine(), \
    > +                                              TYPE_FARADAY_SOC))
    > +
    > +#endif
    > diff --git a/hw/arm/faraday_a369.c b/hw/arm/faraday_a369.c
    > new file mode 100644
    > index 0000000..0b6201a
    > --- /dev/null
    > +++ b/hw/arm/faraday_a369.c
    > @@ -0,0 +1,94 @@
    > +/*
    > + * Faraday A369 Evalution Board
    > + *
    > + * Copyright (c) 2012 Faraday Technology
    > + * Written by Dante Su <dantesu@faraday-tech.com>
    > + *
    > + * This code is licensed under GNU GPL v2+.
    > + */
    > +
    > +#include "hw/sysbus.h"
    > +#include "hw/arm-misc.h"
    > +#include "hw/devices.h"
    > +#include "hw/i2c.h"
    > +#include "hw/boards.h"
    > +#include "hw/ssi.h"
    > +#include "sysemu/sysemu.h"
    > +
    > +#include "faraday.h"
    > +
    > +/* Board init.  */
    > +
    > +static void
    > +a369_board_init(QEMUMachineInitArgs *args)
    > +{
    > +    DeviceState *ds;
    > +    FaradaySoCState *s;
    > +
    > +    if (!args->cpu_model) {
    > +        args->cpu_model = "fa626te";
    > +    }
    > +    if (!args->ram_size) {
    > +        args->ram_size = 512 << 20;
    > +    }
    > +
    > +    ds = qdev_create(NULL, TYPE_FARADAY_SOC);
    > +    qdev_prop_set_string(ds, "cpu_model", args->cpu_model);
    > +    qdev_prop_set_uint64(ds, "ram_size", args->ram_size);
    > +    /* Setup QOM path for the SoC object (i.e. /machine/faraday/soc) */
    > +    object_property_add_child(qdev_get_machine(),
    > +                              TYPE_FARADAY_SOC,
    > +                              OBJECT(ds),
    > +                              NULL);
    > +    qdev_init_nofail(ds);
    > +
    > +    s = FARADAY_SOC(ds);
    > +
    > +    if (args->kernel_filename) {
    > +        s->bi = g_new0(struct arm_boot_info, 1);
    > +
    > +        s->ddr_inited = true;
    > +        s->ahb_remapped = true;
    > +
    > +        /* Remap AHB slave 4 (ROM) & slave 6 (RAM) */
    > +        /* 1. Remap RAM to base of ROM */
    > +        s->ram_base = s->ahb_slave[4] & 0xfff00000;
    > +        s->ahb_slave[6] = s->ram_base | (s->ahb_slave[6] & 0x000f0000);
    > +        /* 2. Remap ROM to base of ROM + size of RAM */
    > +        s->rom_base = s->ram_base
    > +                    + ((1 << extract32(s->ahb_slave[6], 16, 4)) << 20);
    > +        s->ahb_slave[4] = s->rom_base | (s->ahb_slave[4] & 0x000f0000);
    > +
    > +        /* 3. Update ROM Address */
    > +        sysbus_mmio_map(SYS_BUS_DEVICE(s->rom), 0, s->rom_base);
    > +
    > +        /* 4. RAM Address Binding */
    > +        memory_region_add_subregion(s->as, s->ram_base, s->ram);
    > +
    > +        /* 5. Boot Info */
    > +        s->bi->ram_size = s->ram_size;
    > +        s->bi->kernel_filename = args->kernel_filename;
    > +        s->bi->kernel_cmdline = args->kernel_cmdline;
    > +        s->bi->initrd_filename = args->initrd_filename;
    > +        s->bi->board_id = 0x3369;
    > +        arm_load_kernel(s->cpu, s->bi);
    > +    } else if (!drive_get(IF_PFLASH, 0, 0)) {
    > +        hw_error("a369: failed to load ROM image!\n");
    > +        exit(1);
    > +    }
    > +}
    > +
    > +static QEMUMachine a369_machine = {
    > +    .name = "a369",
    > +    .desc = "Faraday A369 (fa626te)",
    > +    .init = a369_board_init,
    > +    DEFAULT_MACHINE_OPTIONS,
    > +};
    > +
    > +static void
    > +a369_machine_init(void)
    > +{
    > +    qemu_register_machine(&a369_machine);
    > +}
    > +
    > +machine_init(a369_machine_init);
    > diff --git a/hw/arm/faraday_a369_kpd.c b/hw/arm/faraday_a369_kpd.c
    > new file mode 100644
    > index 0000000..967ada6
    > --- /dev/null
    > +++ b/hw/arm/faraday_a369_kpd.c
    > @@ -0,0 +1,237 @@
    > +/*
    > + * Faraday FTKBC010 emulator for A369.
    > + *
    > + * Copyright (c) 2012 Faraday Technology
    > + * Written by Dante Su <dantesu@faraday-tech.com>
    > + *
    > + * The FTKBC010 is configured as a keypad controller for A369.
    > + * It's a group of hard wired buttons on the board, each of them
    > + * is monitored by the FTKBC010, and coordinated as (x, y).
    > + * However in A369, there is a pinmux issue that the Y-axis usually
    > + * malfunctioned, so there are only 3 button emulated here.
    > + *
    > + * This code is licensed under GNU GPL v2+
    > + */
    > +
    > +#include "hw/hw.h"
    > +#include "hw/sysbus.h"
    > +#include "hw/devices.h"
    > +#include "ui/console.h"
    > +#include "sysemu/sysemu.h"
    > +
    > +#include "faraday.h"
    > +#include "ftkbc010.h"
    > +
    > +#define CFG_REGSIZE     (0x3c / 4)
    > +
    > +/* Key codes */
    > +#define KEYCODE_ESC             1
    > +#define KEYCODE_BACKSPACE       14
    > +#define KEYCODE_ENTER           28
    > +#define KEYCODE_SPACE           57
    > +#define KEYCODE_MENU            139    /* Menu (show menu) */
    > +
    > +#define TYPE_FTKBC010           "a369.keypad"
    > +
    > +typedef struct Ftkbc010State {
    > +    SysBusDevice busdev;
    > +    MemoryRegion iomem;
    > +    qemu_irq irq;
    > +
    > +    /* HW registers */
    > +    uint32_t regs[CFG_REGSIZE];
    > +} Ftkbc010State;
    > +
    > +#define FTKBC010(obj) \
    > +    OBJECT_CHECK(Ftkbc010State, obj, TYPE_FTKBC010)
    > +
    > +#define KBC_REG32(s, off) \
    > +    *(uint32_t *)((uint8_t *)(s)->regs + (off))
    > +
    > +static void ftkbc010_update_irq(Ftkbc010State *s)
    > +{
    > +    uint32_t ier = 0;
    > +
    > +    /* keypad interrupt */
    > +    ier |= (KBC_REG32(s, REG_CR) & CR_KPDEN) ? ISR_KPDI : 0;
    > +    /* tx interrupt */
    > +    ier |= (KBC_REG32(s, REG_CR) & CR_TXIEN) ? ISR_TXI : 0;
    > +    /* rx interrupt */
    > +    ier |= (KBC_REG32(s, REG_CR) & CR_RXIEN) ? ISR_RXI : 0;
    > +
    > +    qemu_set_irq(s->irq, (ier & KBC_REG32(s, REG_ISR)) ? 1 : 0);
    > +}
    > +
    > +static uint64_t ftkbc010_mem_read(void *opaque, hwaddr addr, unsigned size)
    > +{
    > +    Ftkbc010State *s = FTKBC010(opaque);
    > +    uint64_t ret = 0;
    > +
    > +    switch (addr) {
    > +    case REG_CR ... REG_ASPR:
    > +        ret = s->regs[addr / 4];
    > +        break;
    > +    case REG_REVR:
    > +        ret = 0x00010403;  /* rev. = 1.4.3 */
    > +        break;
    > +    case REG_FEAR:
    > +        ret = 0x00000808;  /* 8x8 scan code for keypad */
    > +        break;
    > +    default:
    > +        qemu_log_mask(LOG_GUEST_ERROR,
    > +                      "a369kpd: undefined memory access@0x%llx\n", addr);
    > +        break;
    > +    }
    > +
    > +    return ret;
    > +}
    > +
    > +static void ftkbc010_mem_write(void    *opaque,
    > +                               hwaddr   addr,
    > +                               uint64_t val,
    > +                               unsigned size)
    > +{
    > +    Ftkbc010State *s = FTKBC010(opaque);
    > +
    > +    switch (addr) {
    > +    case REG_CR:
    > +        KBC_REG32(s, REG_CR) = (uint32_t)val;
    > +        /* if ftkbc010 enabled */
    > +        if (!(KBC_REG32(s, REG_CR) & CR_EN)) {
    > +            break;
    > +        }
    > +        /* if keypad interrupt cleared */
    > +        if (KBC_REG32(s, REG_CR) & CR_KPDIC) {
    > +            KBC_REG32(s, REG_CR) &= ~CR_KPDIC;
    > +            KBC_REG32(s, REG_ISR) &= ~ISR_KPDI;
    > +        }
    > +        /* if rx interrupt cleared */
    > +        if (KBC_REG32(s, REG_CR) & CR_RXICLR) {
    > +            KBC_REG32(s, REG_CR) &= ~CR_RXICLR;
    > +            KBC_REG32(s, REG_ISR) &= ~ISR_RXI;
    > +        }
    > +        /* if tx interrupt cleared */
    > +        if (KBC_REG32(s, REG_CR) & CR_TXICLR) {
    > +            KBC_REG32(s, REG_CR) &= ~CR_TXICLR;
    > +            KBC_REG32(s, REG_ISR) &= ~ISR_TXI;
    > +        }
    > +        ftkbc010_update_irq(s);
    > +        break;
    > +    default:
    > +        qemu_log_mask(LOG_GUEST_ERROR,
    > +                      "a369kpd: undefined memory access@0x%llx\n", addr);
    > +        break;
    > +    }
    > +}
    > +
    > +static const MemoryRegionOps mmio_ops = {
    > +    .read  = ftkbc010_mem_read,
    > +    .write = ftkbc010_mem_write,
    > +    .endianness = DEVICE_LITTLE_ENDIAN,
    > +    .valid = {
    > +        .min_access_size = 4,
    > +        .max_access_size = 4,
    > +    }
    > +};
    > +
    > +static void ftkbc010_key_event(void *opaque, int scancode)
    > +{
    > +    Ftkbc010State *s = FTKBC010(opaque);
    > +    int x, y, released = 0;
    > +
    > +    /* key release from qemu */
    > +    if (scancode & 0x80) {
    > +        released = 1;
    > +    }
    > +
    > +    /* strip qemu key release bit */
    > +    scancode &= ~0x80;
    > +
    > +    /* keypad interrupt */
    > +    if (!released && (KBC_REG32(s, REG_CR) & CR_KPDEN)) {
    > +        switch (scancode) {
    > +        case KEYCODE_ESC:
    > +        case KEYCODE_BACKSPACE:
    > +            x = 1;
    > +            break;
    > +        case KEYCODE_ENTER:
    > +        case KEYCODE_MENU:
    > +        case KEYCODE_SPACE:
    > +            x = 3;
    > +            break;
    > +        default:
    > +            x = 2;    /* KEY_HOME */
    > +            break;
    > +        }
    > +        y = 0;
    > +        KBC_REG32(s, REG_KPDXR) = ~BIT(x);
    > +        KBC_REG32(s, REG_KPDYR) = ~BIT(y);
    > +        KBC_REG32(s, REG_ISR)  |= ISR_KPDI;
    > +        ftkbc010_update_irq(s);
    > +    }
    > +}
    > +
    > +static void ftkbc010_reset(DeviceState *ds)
    > +{
    > +    SysBusDevice *busdev = SYS_BUS_DEVICE(ds);
    > +    Ftkbc010State *s = FTKBC010(FROM_SYSBUS(Ftkbc010State, busdev));
    > +
    > +    memset(s->regs, 0, sizeof(s->regs));
    > +    KBC_REG32(s, REG_KPDXR) = 0xffffffff;
    > +    KBC_REG32(s, REG_KPDYR) = 0xffffffff;
    > +
    > +    qemu_irq_lower(s->irq);
    > +}
    > +
    > +static int ftkbc010_init(SysBusDevice *dev)
    > +{
    > +    Ftkbc010State *s = FTKBC010(FROM_SYSBUS(Ftkbc010State, dev));
    > +
    > +    memory_region_init_io(&s->iomem,
    > +                          &mmio_ops,
    > +                          s,
    > +                          TYPE_FTKBC010,
    > +                          0x1000);
    > +    sysbus_init_mmio(dev, &s->iomem);
    > +    sysbus_init_irq(dev, &s->irq);
    > +
    > +    qemu_add_kbd_event_handler(ftkbc010_key_event, s);
    > +
    > +    return 0;
    > +}
    > +
    > +static const VMStateDescription vmstate_ftkbc010 = {
    > +    .name = TYPE_FTKBC010,
    > +    .version_id = 1,
    > +    .minimum_version_id = 1,
    > +    .minimum_version_id_old = 1,
    > +    .fields = (VMStateField[]) {
    > +        VMSTATE_UINT32_ARRAY(regs, Ftkbc010State, CFG_REGSIZE),
    > +        VMSTATE_END_OF_LIST(),
    > +    }
    > +};
    > +
    > +static void ftkbc010_class_init(ObjectClass *klass, void *data)
    > +{
    > +    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
    > +    DeviceClass *dc = DEVICE_CLASS(klass);
    > +
    > +    k->init   = ftkbc010_init;
    > +    dc->desc  = TYPE_FTKBC010;
    > +    dc->vmsd  = &vmstate_ftkbc010;
    > +    dc->reset = ftkbc010_reset;
    > +}
    > +
    > +static const TypeInfo ftkbc010_info = {
    > +    .name          = TYPE_FTKBC010,
    > +    .parent        = TYPE_SYS_BUS_DEVICE,
    > +    .instance_size = sizeof(Ftkbc010State),
    > +    .class_init    = ftkbc010_class_init,
    > +};
    > +
    > +static void ftkbc010_register_types(void)
    > +{
    > +    type_register_static(&ftkbc010_info);
    > +}
    > +
    > +type_init(ftkbc010_register_types)
    > diff --git a/hw/arm/faraday_a369_scu.c b/hw/arm/faraday_a369_scu.c
    > new file mode 100644
    > index 0000000..4c779ab
    > --- /dev/null
    > +++ b/hw/arm/faraday_a369_scu.c
    > @@ -0,0 +1,187 @@
    > +/*
    > + * Faraday A369 SCU
    > + *
    > + * Copyright (c) 2012 Faraday Technology
    > + * Written by Dante Su <dantesu@faraday-tech.com>
    > + *
    > + * The system control unit (SCU) is responsible for
    > + * power, clock and pinmux management. Since most of
    > + * the features are useless to QEMU, only partial clock
    > + * and pinmux management are implemented as a set of R/W values.
    > + *
    > + * 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_CHIPID      0x000   /* SoC chip id */
    > +#define REG_REVISON     0x004   /* SCU revision id */
    > +#define REG_HWCFG       0x008   /* HW configuration strap */
    > +#define REG_CPUMFCR     0x00C   /* CPUM (master) freq. control */
    > +#define REG_SCUCR       0x010   /* SCU control register */
    > +#define REG_SCUSR       0x014   /* SCU status register */
    > +#define REG_OSCCR       0x01C   /* OSC control register */
    > +#define REG_PLL1CR      0x020   /* PLL1 control register */
    > +#define REG_DLLCR       0x024   /* DLL control register */
    > +#define REG_SPR(n)      (0x100 + ((n) << 2)) /* Scratchpad register 0 - 15 */
    > +#define REG_GPINMUX     0x200   /* General PINMUX */
    > +#define REG_EXTHWCFG    0x204   /* Extended HW configuration strap */
    > +#define REG_CLKCFG0     0x228   /* Clock configuration 0 */
    > +#define REG_CLKCFG1     0x22C   /* Clock configuration 1 */
    > +#define REG_SCER        0x230   /* Special clock enable register */
    > +#define REG_MFPINMUX0   0x238   /* Multi-function pinmux 0 */
    > +#define REG_MFPINMUX1   0x23C   /* Multi-function pinmux 1 */
    > +#define REG_DCSRCR0     0x240   /* Driving cap. & Slew rate control 0 */
    > +#define REG_DCSRCR1     0x244   /* Driving cap. & Slew rate control 1 */
    > +#define REG_DCCR        0x254   /* Delay chain control register */
    > +#define REG_PCR         0x258   /* Power control register */
    > +
    > +#define TYPE_A369SCU    "a369.scu"
    > +#define CFG_REGSIZE     (0x260 / 4)
    > +
    > +typedef struct A369SCUState {
    > +    SysBusDevice busdev;
    > +    MemoryRegion iomem;
    > +
    > +    /* HW registers */
    > +    uint32_t regs[CFG_REGSIZE];
    > +} A369SCUState;
    > +
    > +#define A369SCU(obj) \
    > +    OBJECT_CHECK(A369SCUState, obj, TYPE_A369SCU)
    > +
    > +#define SCU_REG32(s, off) \
    > +    *(uint32_t *)((uint8_t *)(s)->regs + (off))
    > +
    > +static uint64_t
    > +a369scu_mem_read(void *opaque, hwaddr addr, unsigned size)
    > +{
    > +    A369SCUState *s = A369SCU(opaque);
    > +    uint64_t ret = 0;
    > +
    > +    switch (addr) {
    > +    case 0x000 ... 0x25C:
    > +        ret = s->regs[addr / 4];
    > +        break;
    > +    default:
    > +        qemu_log_mask(LOG_GUEST_ERROR,
    > +                      "a369scu: undefined memory access@0x%llx\n", addr);
    > +        break;
    > +    }
    > +
    > +    return ret;
    > +}
    > +
    > +static void
    > +a369scu_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
    > +{
    > +    A369SCUState *s = A369SCU(opaque);
    > +
    > +    switch (addr) {
    > +    case REG_GPINMUX:
    > +    case REG_CLKCFG0:
    > +    case REG_CLKCFG1:
    > +    case REG_MFPINMUX0:
    > +    case REG_MFPINMUX1:
    > +        s->regs[addr / 4] = (uint32_t)val;
    > +        break;
    > +    default:
    > +        qemu_log_mask(LOG_GUEST_ERROR,
    > +                      "a369scu: undefined memory access@0x%llx\n", addr);
    > +        break;
    > +    }
    > +}
    > +
    > +static const MemoryRegionOps mmio_ops = {
    > +    .read  = a369scu_mem_read,
    > +    .write = a369scu_mem_write,
    > +    .endianness = DEVICE_LITTLE_ENDIAN,
    > +    .valid = {
    > +        .min_access_size = 4,
    > +        .max_access_size = 4,
    > +    }
    > +};
    > +
    > +static void a369scu_reset(DeviceState *ds)
    > +{
    > +    SysBusDevice *busdev = SYS_BUS_DEVICE(ds);
    > +    A369SCUState *s = A369SCU(FROM_SYSBUS(A369SCUState, busdev));
    > +
    > +    memset(s->regs, 0, sizeof(s->regs));
    > +
    > +    SCU_REG32(s, REG_CHIPID)    = 0x00003369; /* A369 */
    > +    SCU_REG32(s, REG_REVISON)   = 0x00010000; /* Rev. = 1.0.0 */
    > +    SCU_REG32(s, REG_HWCFG)     = 0x00000c10; /* CPU = 4 * HCLK */
    > +    SCU_REG32(s, REG_CPUMFCR)   = 0x00000230; /* CPU = 4 * HCLK */
    > +    SCU_REG32(s, REG_SCUCR)     = 0x00000083; /* no low power detect */
    > +    SCU_REG32(s, REG_SCUSR)     = 0x00000100; /* CPU freq. stable */
    > +    SCU_REG32(s, REG_OSCCR)     = 0x00000003; /* OSCH disabled */
    > +    SCU_REG32(s, REG_PLL1CR)    = 0x20010003; /* PLL_NS = 32 */
    > +    SCU_REG32(s, REG_DLLCR)     = 0x00000003; /* DLL enabled & stable */
    > +    SCU_REG32(s, REG_GPINMUX)   = 0x00001078; /* Pinmux */
    > +    SCU_REG32(s, REG_EXTHWCFG)  = 0x00001cc8; /* NAND flash boot */
    > +    SCU_REG32(s, REG_CLKCFG0)   = 0x26877330; /* LCD = HCLK */
    > +    SCU_REG32(s, REG_CLKCFG1)   = 0x000a0a0a; /* SD = HCLK, SPI=PCLK */
    > +    SCU_REG32(s, REG_SCER)      = 0x00003fff; /* All clock enabled */
    > +    SCU_REG32(s, REG_MFPINMUX0) = 0x00000241; /* Pinmux */
    > +    SCU_REG32(s, REG_MFPINMUX1) = 0x00000000; /* Pinmux */
    > +    SCU_REG32(s, REG_DCSRCR0)   = 0x11111111; /* Slow slew rate */
    > +    SCU_REG32(s, REG_DCSRCR1)   = 0x11111111; /* Slow slew rate */
    > +    SCU_REG32(s, REG_DCCR)      = 0x00000303; /* All delay chain = 3 */
    > +    SCU_REG32(s, REG_PCR)       = 0x8000007f; /* High performance mode */
    > +}
    > +
    > +static int a369scu_init(SysBusDevice *dev)
    > +{
    > +    A369SCUState *s = A369SCU(FROM_SYSBUS(A369SCUState, dev));
    > +
    > +    memory_region_init_io(&s->iomem,
    > +                          &mmio_ops,
    > +                          s,
    > +                          TYPE_A369SCU,
    > +                          0x1000);
    > +    sysbus_init_mmio(dev, &s->iomem);
    > +    return 0;
    > +}
    > +
    > +static const VMStateDescription vmstate_a369scu = {
    > +    .name = TYPE_A369SCU,
    > +    .version_id = 1,
    > +    .minimum_version_id = 1,
    > +    .minimum_version_id_old = 1,
    > +    .fields = (VMStateField[]) {
    > +        VMSTATE_UINT32_ARRAY(regs, A369SCUState, CFG_REGSIZE),
    > +        VMSTATE_END_OF_LIST(),
    > +    }
    > +};
    > +
    > +static void a369scu_class_init(ObjectClass *klass, void *data)
    > +{
    > +    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
    > +    DeviceClass *dc = DEVICE_CLASS(klass);
    > +
    > +    k->init   = a369scu_init;
    > +    dc->desc  = TYPE_A369SCU;
    > +    dc->vmsd  = &vmstate_a369scu;
    > +    dc->reset = a369scu_reset;
    > +    dc->no_user = 1;
    > +}
    > +
    > +static const TypeInfo a369scu_info = {
    > +    .name          = TYPE_A369SCU,
    > +    .parent        = TYPE_SYS_BUS_DEVICE,
    > +    .instance_size = sizeof(A369SCUState),
    > +    .class_init    = a369scu_class_init,
    > +};
    > +
    > +static void a369scu_register_types(void)
    > +{
    > +    type_register_static(&a369scu_info);
    > +}
    > +
    > +type_init(a369scu_register_types)
    > diff --git a/hw/arm/faraday_a369_soc.c b/hw/arm/faraday_a369_soc.c
    > new file mode 100644
    > index 0000000..0372868
    > --- /dev/null
    > +++ b/hw/arm/faraday_a369_soc.c
    > @@ -0,0 +1,197 @@
    > +/*
    > + * Faraday A369 SoC
    > + *
    > + * Copyright (c) 2012 Faraday Technology
    > + * Written by Dante Su <dantesu@faraday-tech.com>
    > + *
    > + * This code is licensed under GNU GPL v2+.
    > + */
    > +
    > +#include "hw/sysbus.h"
    > +#include "hw/arm-misc.h"
    > +#include "hw/devices.h"
    > +#include "hw/i2c.h"
    > +#include "hw/boards.h"
    > +#include "hw/flash.h"
    > +#include "hw/serial.h"
    > +#include "hw/ssi.h"
    > +#include "net/net.h"
    > +#include "sysemu/sysemu.h"
    > +#include "sysemu/blockdev.h"
    > +#include "exec/address-spaces.h"
    > +
    > +#include "faraday.h"
    > +
    > +static void a369soc_reset(DeviceState *ds)
    > +{
    > +    int i;
    > +    uint64_t size;
    > +    SysBusDevice *busdev = SYS_BUS_DEVICE(ds);
    > +    FaradaySoCState *s = FARADAY_SOC(FROM_SYSBUS(FaradaySoCState, busdev));
    > +
    > +    /* AHB slave base & window configuration */
    > +    memset(s->ahb_slave, 0, sizeof(s->ahb_slave));
    > +    s->ahb_slave[0] = 0x94050000;
    > +    s->ahb_slave[1] = 0x96040000;
    > +    s->ahb_slave[2] = 0x90f00000;
    > +    s->ahb_slave[3] = 0x92050000; /* APB: base=0x92000000, size=32MB */
    > +    s->ahb_slave[5] = 0xc0080000;
    > +    if (!s->bi) {   /* ROM emulation enabled */
    > +        s->ahb_slave[4] = 0x00080000; /* ROM: base=0x00000000, size=256MB */
    > +        s->ahb_slave[6] = 0x10090000; /* RAM: base=0x10000000, size=512MB */
    > +    } else {        /* Direct boot */
    > +        s->ahb_slave[4] = s->rom_base | 0x80000; /* ROM: size=256MB */
    > +        s->ahb_slave[6] = s->ram_base | 0x90000; /* RAM: size=512MB */
    > +    }
    > +    for (i = 0; i < 15; ++i) {
    > +        s->ahb_slave[7 + i] = 0x90000000 + (i << 20);
    > +    }
    > +    s->ahb_slave[22] = 0x40080000;
    > +    s->ahb_slave[23] = 0x60080000;
    > +    s->ahb_slave[24] = 0xa0000000; /* SRAM: base=0xA0000000, size=1MB */
    > +
    > +    /* APB slave base & window configuration */
    > +    memset(s->apb_slave, 0, sizeof(s->apb_slave));
    > +    for (i = 0; i < 18; ++i) {
    > +        s->apb_slave[i] = 0x12000000 + (i << 20);
    > +    }
    > +
    > +    /* ROM base = salve4 & 0x000fffff, size = 6KB */
    > +    s->rom_base = s->ahb_slave[4] & 0xfff00000;
    > +    s->rom_size = 6 << 10;
    > +
    > +    /* RAM base = salve6 & 0x000fffff, size <= (1 << slave6.BIT[19-16]) MB */
    > +    size = (1 << extract32(s->ahb_slave[6], 16, 4)) << 20;
    > +    s->ram_base = s->ahb_slave[6] & 0xfff00000;
    > +    if (!s->ram_size || s->ram_size > size) {
    > +        s->ram_size = size;
    > +    }
    > +}
    > +
    > +static void
    > +a369soc_device_init(FaradaySoCState *s)
    > +{
    > +    DriveInfo *dinfo;
    > +    DeviceState *ds;
    > +
    > +    s->as = get_system_memory();
    > +    s->ram = g_new(MemoryRegion, 1);
    > +    s->sram = g_new(MemoryRegion, 1);
    > +
    > +    /* CPU */
    > +    if (!s->cpu_model) {
    > +        s->cpu_model = (char *)"fa626te";
    > +    }
    > +    s->cpu = cpu_arm_init(s->cpu_model);
    > +    if (!s->cpu) {
    > +        hw_error("a369: Unable to find CPU definition\n");
    > +        exit(1);
    > +    }
    > +
    > +    /* RAM Init */
    > +    memory_region_init_ram(s->ram, "a369.ram", s->ram_size);
    > +    vmstate_register_ram_global(s->ram);
    > +
    > +    /* Embedded RAM Init */
    > +    memory_region_init_ram(s->sram, "a369.sram", 0x4000);
    > +    vmstate_register_ram_global(s->sram);
    > +    memory_region_add_subregion(s->as, 0xA0000000, s->sram);
    > +
    > +    /* Embedded ROM Init (Emulated with a parallel NOR flash) */
    > +    dinfo = drive_get_next(IF_PFLASH);
    > +    s->rom = pflash_cfi01_register(
    > +                    s->rom_base,
    > +                    NULL,
    > +                    "a369.rom",
    > +                    s->rom_size,
    > +                    dinfo ? dinfo->bdrv : NULL,
    > +                    1024,               /* 1 KB sector */
    > +                    s->rom_size >> 10,  /* sectors per chip */
    > +                    4,                  /* 32 bits */
    > +                    0, 0, 0, 0,         /* id */
    > +                    0                   /* Little Endian */);
    > +    if (!s->rom) {
    > +        hw_error("a369soc: failed to init ROM device.\n");
    > +        exit(1);
    > +    }
    > +
    > +    /* Serial (FTUART010 which is 16550A compatible) */
    > +    if (serial_hds[0]) {
    > +        serial_mm_init(s->as,
    > +                       0x92b00000,
    > +                       2,
    > +                       NULL,
    > +                       18432000,
    > +                       serial_hds[0],
    > +                       DEVICE_LITTLE_ENDIAN);
    > +    }
    > +    if (serial_hds[1]) {
    > +        serial_mm_init(s->as,
    > +                       0x92c00000,
    > +                       2,
    > +                       NULL,
    > +                       18432000,
    > +                       serial_hds[1],
    > +                       DEVICE_LITTLE_ENDIAN);
    > +    }
    > +
    > +    /* ftscu010 */
    > +    ds = sysbus_create_simple("a369.scu", 0x92000000, NULL);
    > +    s->scu = ds;
    > +
    > +    /* ftkbc010 */
    > +    sysbus_create_simple("a369.keypad", 0x92f00000, NULL);
    > +}
    > +
    > +static int a369soc_init(SysBusDevice *busdev)
    > +{
    > +    FaradaySoCState *s = FARADAY_SOC(FROM_SYSBUS(FaradaySoCState, busdev));
    > +
    > +    a369soc_reset(DEVICE(busdev));
    > +    a369soc_device_init(s);
    > +
    > +    return 0;
    > +}
    > +
    > +static Property a369soc_properties[] = {
    > +    DEFINE_PROP_STRING("cpu_model", FaradaySoCState, cpu_model),
    > +    DEFINE_PROP_UINT64("ram_size", FaradaySoCState, ram_size, 0x20000000),
    > +    DEFINE_PROP_END_OF_LIST(),
    > +};
    > +
    > +static const VMStateDescription vmstate_a369soc = {
    > +    .name = TYPE_FARADAY_SOC,
    > +    .version_id = 1,
    > +    .minimum_version_id = 1,
    > +    .minimum_version_id_old = 1,
    > +    .fields = (VMStateField[]) {
    > +        VMSTATE_END_OF_LIST(),
    > +    }
    > +};
    > +
    > +static void a369soc_class_init(ObjectClass *klass, void *data)
    > +{
    > +    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
    > +    DeviceClass *dc = DEVICE_CLASS(klass);
    > +
    > +    k->init   = a369soc_init;
    > +    dc->desc  = TYPE_FARADAY_SOC;
    > +    dc->vmsd  = &vmstate_a369soc;
    > +    dc->props = a369soc_properties;
    > +    dc->reset = a369soc_reset;
    > +    dc->no_user = 1;
    > +}
    > +
    > +static const TypeInfo a369soc_info = {
    > +    .name          = TYPE_FARADAY_SOC,
    > +    .parent        = TYPE_SYS_BUS_DEVICE,
    > +    .instance_size = sizeof(FaradaySoCState),
    > +    .class_init    = a369soc_class_init,
    > +};
    > +
    > +static void a369soc_register_types(void)
    > +{
    > +    type_register_static(&a369soc_info);
    > +}
    > +
    > +type_init(a369soc_register_types)
    > diff --git a/hw/arm/ftkbc010.h b/hw/arm/ftkbc010.h
    > new file mode 100644
    > index 0000000..48e39e1
    > --- /dev/null
    > +++ b/hw/arm/ftkbc010.h
    > @@ -0,0 +1,42 @@
    > +/*
    > + * Faraday FTKBC010 Keyboard/Keypad Controller
    > + *
    > + * Copyright (c) 2012 Faraday Technology
    > + * Written by Dante Su <dantesu@faraday-tech.com>
    > + *
    > + * This code is licensed under GNU GPL v2+
    > + */
    > +#ifndef HW_ARM_FTKBC010_H
    > +#define HW_ARM_FTKBC010_H
    > +
    > +#define REG_CR      0x00    /* control register */
    > +#define REG_SRDR    0x04    /* sample rate division register */
    > +#define REG_RSCR    0x08    /* request to send counter register */
    > +#define REG_SR      0x0C    /* status register */
    > +#define REG_ISR     0x10    /* interrupt status register */
    > +#define REG_KBDRR   0x14    /* keyboard receive register */
    > +#define REG_KBDTR   0x18    /* keyboard transmit register */
    > +#define REG_IMR     0x1C    /* interrupt mask register */
    > +#define REG_KPDXR   0x30    /* keypad X-Axis register */
    > +#define REG_KPDYR   0x34    /* keypad Y-Axis register */
    > +#define REG_ASPR    0x38    /* auto-scan period register */
    > +#define REG_REVR    0x50    /* revision register */
    > +#define REG_FEAR    0x54    /* feature register */
    > +
    > +#define CR_KPDIC    BIT(10) /* Write 1 to clear Keypad interupt */
    > +#define CR_KPDAS    BIT(9)  /* Keypad audo-scan enabled */
    > +#define CR_KPDEN    BIT(8)  /* Keypad function enabled */
    > +#define CR_RXICLR   BIT(7)  /* Write 1 to clear Keyboard/Mouse Rx interrupt */
    > +#define CR_TXICLR   BIT(6)  /* Write 1 to clear Keyboard/Mouse Tx interrupt */
    > +#define CR_NOLC     BIT(5)  /* No line control bit */
    > +#define CR_RXIEN    BIT(4)  /* Keyboard/Mouse Rx interrupt enabled */
    > +#define CR_TXIEN    BIT(3)  /* Keyboard/Mouse Tx interrupt enabled */
    > +#define CR_EN       BIT(2)  /* Chip enabled */
    > +#define CR_DATDN    BIT(1)  /* Data disabled */
    > +#define CR_CLKDN    BIT(0)  /* Clock disabled */
    > +
    > +#define ISR_KPDI    BIT(2)  /* Keypad interupt */
    > +#define ISR_TXI     BIT(1)  /* Keyboard/Mouse Tx interrupt enabled */
    > +#define ISR_RXI     BIT(0)  /* Keyboard/Mouse Rx interrupt enabled */
    > +
    > +#endif
    > --
    > 1.7.9.5
    >
    >
    
    ^ permalink raw reply	[flat|nested] 15+ messages in thread
  • [parent not found: <1361949350-22241-4-git-send-email-dantesu@gmail.com>]
  • [parent not found: <1361949350-22241-5-git-send-email-dantesu@gmail.com>]
  • [parent not found: <1361949350-22241-6-git-send-email-dantesu@gmail.com>]

  • end of thread, other threads:[~2013-03-04  6:54 UTC | newest]
    
    Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
    -- links below jump to the message on this page --
         [not found] <1361949350-22241-1-git-send-email-dantesu@gmail.com>
         [not found] ` <1361949350-22241-3-git-send-email-dantesu@gmail.com>
         [not found]   ` <5130F9D8.3030200@gmail.com>
    2013-03-01 19:00     ` [Qemu-devel] [PATCH v5 02/24] hw/arm: add Faraday a369 SoC platform support Igor Mitsyanko
    2013-03-04  6:06       ` Kuo-Jung Su
    2013-03-02  3:43   ` Peter Crosthwaite
    2013-03-04  6:09     ` Kuo-Jung Su
         [not found] ` <1361949350-22241-4-git-send-email-dantesu@gmail.com>
    2013-03-02  4:13   ` [Qemu-devel] [PATCH v5 03/24] hw/arm: add Faraday FTINTC020 interrupt controller support Peter Crosthwaite
    2013-03-03  4:58     ` Peter Crosthwaite
    2013-03-03  6:29     ` Peter Crosthwaite
    2013-03-04  6:29       ` Kuo-Jung Su
    2013-03-04  6:20     ` Kuo-Jung Su
    2013-03-04  6:33       ` Peter Crosthwaite
    2013-03-04  6:54         ` Kuo-Jung Su
         [not found] ` <1361949350-22241-5-git-send-email-dantesu@gmail.com>
    2013-03-04  3:35   ` [Qemu-devel] [PATCH v5 04/24] hw/arm: add Faraday FTAHBC020 support Peter Crosthwaite
    2013-03-04  6:30     ` Kuo-Jung Su
         [not found] ` <1361949350-22241-6-git-send-email-dantesu@gmail.com>
    2013-03-04  3:56   ` [Qemu-devel] [PATCH v5 05/24] hw/arm: add Faraday FTDDRII030 support Peter Crosthwaite
    2013-03-04  6:32     ` Kuo-Jung Su
    

    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).