qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH 01/18] hw: add Faraday a369 SoC platform support


From: Dante
Subject: [Qemu-devel] [PATCH 01/18] hw: add Faraday a369 SoC platform support
Date: Fri, 18 Jan 2013 14:28:09 +0800

Faraday A369, is an ARM SoC prototype chip, highly integrated with common SoC
features, including a 533MHz ARM v5TE master CPU, a 133MHz ARM v5TE slave CPU,
a 32-bit DDR-2 533MHz memory controller, 2 USB 2.0 host/OTG ports, SATA
host/device port, 10/100/1000 Ethernet port, MPEG4 codec, H.264 decoder,
image signal processor, and various low-speed peripheral interfaces.

This patch adds QEMU model for A369 without MPEG4/H.264 and USB support.
The USB host is still under migration from qemu-1.3.0 into the current
development release from GIT.

These patches include:

1. hw/a369.c:        QEMU model for Faraday a369 SoC platform
2. hw/a369_scu.c:    A369 System Control Uint (Clock & Power Management)
3. hw/ftapbbrg020.c: APB DMA Engine
4. hw/ftapbbrg020.h
5. hw/ftdmac020.c:   AHB DMA Engine
6. hw/ftdmac020.h
7. hw/ftgmac100.c:   1Gbps Ethernet MAC
8. hw/ftgmac100.h
9. hw/fti2c010.c:    I2C Master
10.hw/fti2c010.h
11.hw/ftintc020.c:   Interrupt Controller
12.hw/ftkbc010.c:    A369 Keypad Controller
13.hw/ftlcdc200.c:   LCD Controller
14.hw/ftlcdc200.h
15.hw/ftlcdc200_template.h
16.hw/ftmac110.c:    100Mbps Ethernet MAC
17.hw/ftmac110.h
18.hw/ftnandc021.c:  NAND Flash Controller
19.hw/ftnandc021.h
20.hw/ftpwmtmr010.c: Timer
21.hw/ftrtc011.c:    RTC Timer
22.hw/ftsdc010.c:    MMC/SD Host Controller
23.hw/ftsdc010.h
24.hw/ftspi020.c:    SPI NOR Flash Controller
25.hw/ftspi020.h
26.hw/ftssp010.c:    Multi-function device with SPI and I2S support
27.hw/ftssp010.h
28.hw/fttmr010.c:    Timer
29/hw/fttsc010.c:    Touchscreen Controller
30.hw/fttsc010.h
31.hw/ftwdt010.c:    Watchdog Timer
32.hw/rom.c:         Embedded ROM device model for SoC Platform

Signed-off-by: Kuo-Jung Su <address@hidden>
---
 hw/a369.c            |  499 ++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/a369_scu.c        |  192 +++++++++++++++++++
 hw/arm/Makefile.objs |    6 +
 3 files changed, 697 insertions(+)
 create mode 100644 hw/a369.c
 create mode 100644 hw/a369_scu.c

diff --git a/hw/a369.c b/hw/a369.c
new file mode 100644
index 0000000..cc78351
--- /dev/null
+++ b/hw/a369.c
@@ -0,0 +1,499 @@
+/*
+ * Faraday A369 Evalution Board
+ *
+ * Copyright (c) 2012 Faraday Technology
+ *
+ * Written by Dante Su <address@hidden>
+ *
+ * This code is licensed under the GPL.
+ */
+
+#include "sysbus.h"
+#include "arm-misc.h"
+#include "devices.h"
+#include "net/net.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/blockdev.h"
+#include "exec/address-spaces.h"
+#include "i2c.h"
+#include "boards.h"
+#include "flash.h"
+#include "serial.h"
+#include "ssi.h"
+
+#define A369_NOR_FLASH_ADDR            0x20000000
+#define A369_NOR_FLASH_SIZE            (16 * 1024 * 1024)
+#define A369_NOR_FLASH_SECT_SIZE    (128 * 1024)
+
+#ifndef min
+#define min(a, b)                    ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef max
+#define max(a, b)                    ((a) > (b) ? (a) : (b))
+#endif
+
+struct a369_ahbc_state {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    /* HW register cache */
+    uint32_t cr;
+};
+
+struct a369_ddrc_state {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    
+    /* HW register caches */
+    uint32_t mcr;
+    uint32_t msr;
+};
+
+struct a369_state {
+    ARMCPU *cpu;
+    DeviceState *rom;
+    DeviceState *hdma;    /* AHB DMA */
+    DeviceState *pdma;    /* APB DMA */
+
+    MemoryRegion *as;
+    MemoryRegion *ram;
+    MemoryRegion *ram_alias;
+    MemoryRegion *sram;
+
+    i2c_bus *i2c[2];
+
+    struct a369_ahbc_state ahbc;
+    struct a369_ddrc_state ddrc;
+};
+
+/* ftintc020.c */
+qemu_irq *ftintc020_init(hwaddr base, ARMCPU *cpu);
+
+/* ftgmac100.c */
+void ftgmac100_init(NICInfo *nd, uint32_t base, qemu_irq irq);
+
+/* AHB controller block */
+
+static uint64_t a369_ahbc_read(void *opaque, hwaddr addr, unsigned size)
+{
+    struct a369_state *mach = opaque;
+    struct a369_ahbc_state *s = &mach->ahbc;
+    
+    switch(addr) {
+    case 0x00: return 0x94050000;
+    case 0x04: return 0x96040000;
+    case 0x08: return 0x90f00000;
+    case 0x0c: return 0x92050000;
+    case 0x10: return 0x20080000;
+    case 0x14: return 0xc0080000;
+    case 0x18: return 0x00090000; 
+    case 0x1c: return 0x90000000;
+    case 0x20: return 0x90100000;
+    case 0x24: return 0x90200000;
+    case 0x28: return 0x90300000;
+    case 0x2c: return 0x90400000;
+    case 0x30: return 0x90500000;
+    case 0x34: return 0x90600000;
+    case 0x38: return 0x90700000;
+    case 0x3c: return 0x90800000;
+    case 0x40: return 0x90900000;
+    case 0x44: return 0x90a00000;
+    case 0x48: return 0x90b00000;
+    case 0x4c: return 0x90c00000;
+    case 0x50: return 0x90d00000;
+    case 0x54: return 0x90e00000; 
+    case 0x58: return 0x40080000;
+    case 0x5c: return 0x60080000;
+    case 0x60: return 0xa0000000;
+    case 0x84: return 0x00000001;
+    case 0x88: return s->cr;
+    case 0x8c: return 0x00010301;
+    default:
+        break;
+    }
+    return 0;
+}
+
+static void a369_ahbc_write(void *opaque, hwaddr addr, uint64_t val, unsigned 
size)
+{
+    struct a369_state *mach = opaque;
+    struct a369_ahbc_state *s = &mach->ahbc;
+
+    if (addr == 0x88) {
+        if (!(s->cr & 0x01) && (val & 0x01)) {
+            /* AHB remap */
+            printf("[qemu] a369: AHB remap...\n");
+            sysbus_mmio_map(sysbus_from_qdev(mach->rom), 0, 0x40000000);
+            memory_region_del_subregion(mach->as, mach->ram_alias);
+            memory_region_add_subregion(mach->as, 0x00000000, mach->ram);      
      
+        }
+        s->cr = (uint32_t)val;
+    }
+}
+
+static const MemoryRegionOps a369_ahbc_ops = {
+    .read  = a369_ahbc_read,
+    .write = a369_ahbc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int a369_ahbc_init(struct a369_state *mach, hwaddr base)
+{
+    struct a369_ahbc_state *s = &mach->ahbc;
+    memory_region_init_io(&s->iomem, &a369_ahbc_ops, mach, "a369_ahbc", 
0x1000);
+    memory_region_add_subregion(mach->as, base, &s->iomem);
+    s->cr = 0;
+    return 0;
+}
+
+/* DDRII controller block */
+
+static uint64_t a369_ddrc_read(void *opaque, hwaddr addr, unsigned size)
+{
+    struct a369_state *mach = opaque;
+    struct a369_ddrc_state *s = &mach->ddrc;
+    
+    switch(addr) {
+    case 0x00:
+        return s->mcr;
+    case 0x04:
+        return s->msr;
+    default:
+        break;
+    }
+    return 0;
+}
+
+static void a369_ddrc_write(void *opaque, hwaddr addr, uint64_t val, unsigned 
size)
+{
+    struct a369_state *mach = opaque;
+    struct a369_ddrc_state *s = &mach->ddrc;
+    
+    switch(addr) {
+    case 0x00:
+        s->mcr = (uint32_t)val & 0xffff;
+        break;
+    case 0x04:
+        val = (val & 0x3f) | (s->msr & 0x100);
+        if (!(s->msr & 0x100) && (val & 0x01)) {
+            val &= 0xfffffffe;
+            val |= 0x100;
+            printf("[qemu] a369: ddr init...\n");
+            memory_region_add_subregion(mach->as, 0x10000000, 
mach->ram_alias);            
+        }
+        s->msr = (uint32_t)val;
+        break;
+    default:
+        break;
+    }
+}
+
+static const MemoryRegionOps a369_ddrc_ops = {
+    .read  = a369_ddrc_read,
+    .write = a369_ddrc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int a369_ddrc_init(struct a369_state *mach, hwaddr base)
+{
+    struct a369_ddrc_state *s = &mach->ddrc;
+    
+    memory_region_init_io(&s->iomem, &a369_ddrc_ops, mach, "a369_ddrc", 
0x1000);
+    memory_region_add_subregion(mach->as, base, &s->iomem);
+    s->mcr = 0;
+    s->msr = 0;
+    return 0;
+}
+
+/* Board init.  */
+
+static void a369_device_init(struct a369_state *s)
+{
+    qemu_irq *pic;
+    DeviceState *ds;
+    int done_nic = 0;
+    int i;
+    
+    /* Interrupt Controller */
+    pic = ftintc020_init(0x90100000, s->cpu);
+
+    /* Timer */
+    ds = qdev_create(NULL, "ftpwmtmr010");
+    qdev_prop_set_uint32(ds, "freq", 66 * 1000000);
+    qdev_init_nofail(ds);
+    sysbus_mmio_map(sysbus_from_qdev(ds), 0, 0x92300000);
+    sysbus_connect_irq(sysbus_from_qdev(ds), 0, pic[8]);
+    sysbus_connect_irq(sysbus_from_qdev(ds), 1, pic[9]);
+    sysbus_connect_irq(sysbus_from_qdev(ds), 2, pic[10]);
+    sysbus_connect_irq(sysbus_from_qdev(ds), 3, pic[11]);
+
+    /* Serial (FTUART010 which is 16550A compatible) */
+    if (serial_hds[0]) {
+        serial_mm_init(s->as, 
+                       0x92b00000,
+                       2, 
+                       pic[53],
+                       18432000 / 16,
+                       serial_hds[0], 
+                       DEVICE_NATIVE_ENDIAN);
+    }
+    if (serial_hds[1]) {
+        serial_mm_init(s->as,
+                       0x92c00000,
+                       2,
+                       pic[54],
+                       18432000 / 16,
+                       serial_hds[1],
+                       DEVICE_NATIVE_ENDIAN);
+    }
+
+    /* ftscu010 */
+    sysbus_create_simple("a369_scu", 0x92000000, pic[41]);
+    
+    /* ftdmac020 */
+    s->hdma = sysbus_create_simple("ftdmac020", 0x90300000, pic[15]);
+    sysbus_create_simple("ftdmac020", 0x96100000, pic[17]);
+
+    /* ftapbbrg020 */
+    s->pdma = sysbus_create_simple("ftapbbrg020", 0x90f00000, pic[14]);
+
+    /* ftnandc021 */
+    do {
+        qemu_irq ack, req;
+        ds = sysbus_create_simple("ftnandc021", 0x90200000, pic[30]);
+        ack = qdev_get_gpio_in(ds, 0);
+        req = qdev_get_gpio_in(s->hdma, 15);
+        qdev_connect_gpio_out(s->hdma, 15, ack);
+        qdev_connect_gpio_out(ds, 0, req);
+    } while(0);
+
+    /* ftsdc010 */
+#if 0
+    do {
+        qemu_irq ack, req;
+        ds = sysbus_create_simple("ftsdc010", 0x90500000, pic[38]);
+        ack = qdev_get_gpio_in(ds, 0);
+        req = qdev_get_gpio_in(s->hdma, 14);
+        qdev_connect_gpio_out(s->hdma, 14, ack);
+        qdev_connect_gpio_out(ds, 0, req);
+    } while(0);
+#endif
+    do {
+        qemu_irq ack, req;
+        ds = sysbus_create_simple("ftsdc010", 0x90600000, pic[39]);
+        ack = qdev_get_gpio_in(ds, 0);
+        req = qdev_get_gpio_in(s->hdma, 13);
+        qdev_connect_gpio_out(s->hdma, 13, ack);
+        qdev_connect_gpio_out(ds, 0, req);
+    } while(0);
+
+#if 0
+    /* fusbh200 */
+    sysbus_create_simple("faraday-ehci-usb", 0x90800000, pic[36]);
+    
+    /* fotg210 */
+    sysbus_create_simple("faraday-ehci-usb", 0x90900000, pic[37]);
+#endif
+
+    /* ftgmac100 */
+    for(i = 0; i < nb_nics; i++) {
+        NICInfo *nd = &nd_table[i];
+        if (!done_nic && (!nd->model || strcmp(nd->model, "ftgmac100") == 0)) {
+            ftgmac100_init(nd, 0x90c00000, pic[32]);
+            done_nic = 1;
+        }
+    }
+
+    /* ftrtc011 (only alarm interrupt is connected) */
+    sysbus_create_varargs("ftrtc011", 0x92100000, pic[0],    /* Alarm (Level): 
NC in A369 */
+                                                  pic[42],    /* Alarm (Edge) 
*/
+                                                  pic[43],    /* Second (Edge) 
*/
+                                                  pic[44],    /* Minute (Edge) 
*/
+                                                  pic[45],    /* Hour (Edge) */
+                                                  NULL);
+    
+    /* ftwdt010 */
+    sysbus_create_simple("ftwdt010", 0x92200000, pic[46]);
+    
+    /* fttsc010 */
+    sysbus_create_simple("fttsc010", 0x92400000, pic[19]);
+    
+    /* ftkbc010 */
+    sysbus_create_simple("ftkbc010", 0x92f00000, pic[21]);
+
+    /* ftlcdc200 */
+    sysbus_create_varargs("ftlcdc200",0x94a00000, pic[0],  /* Global (NC in 
A369) */
+                                                  pic[25], /* VSTATUS */
+                                                  pic[24], /* Base Address 
Update */
+                                                  pic[23], /* FIFO Under-Run */
+                                                  pic[22], /* AHB Bus Error */
+                                                  NULL);
+
+    /* fti2c010 */
+    ds = sysbus_create_simple("fti2c010", 0x92900000, pic[51]);
+    s->i2c[0] = (i2c_bus *)qdev_get_child_bus(ds, "i2c");
+    ds = sysbus_create_simple("fti2c010", 0x92A00000, pic[52]);
+    s->i2c[1] = (i2c_bus *)qdev_get_child_bus(ds, "i2c");
+    
+    /* ftssp010 */
+    do {
+        SSIBus *spi;
+        DeviceState *fl;
+        int nr_flash = 1;
+        qemu_irq cs_line;
+        qemu_irq ack, req;
+        
+        ds = qdev_create(NULL, "ftssp010");
+        
+        /* i2s */
+        qdev_prop_set_ptr(ds, "codec_i2c", s->i2c[0]);
+        qdev_init_nofail(ds);
+        sysbus_mmio_map(sysbus_from_qdev(ds), 0, 0x92700000);
+        sysbus_connect_irq(sysbus_from_qdev(ds), 0, pic[49]);
+
+        /* spi */
+        spi = (SSIBus *)qdev_get_child_bus(ds, "spi");
+        for (i = 0; i < nr_flash; i++) {
+            fl = ssi_create_slave_no_init(spi, "m25p80");
+            qdev_prop_set_string(fl, "partname", "w25q64");
+            qdev_init_nofail(fl);
+            cs_line = qdev_get_gpio_in(fl, 0);
+            sysbus_connect_irq(sysbus_from_qdev(ds), i+1, cs_line);
+        }
+        
+        /* DMA (Tx) */
+        ack = qdev_get_gpio_in(ds, 0);
+        req = qdev_get_gpio_in(s->pdma, 7);
+        qdev_connect_gpio_out(s->pdma, 7, ack);
+        qdev_connect_gpio_out(ds, 0, req);
+        
+        /* DMA (Rx) */
+        ack = qdev_get_gpio_in(ds, 1);
+        req = qdev_get_gpio_in(s->pdma, 8);
+        qdev_connect_gpio_out(s->pdma, 8, ack);
+        qdev_connect_gpio_out(ds, 1, req);
+    } while(0);
+
+    /* ftddrII030 */
+    a369_ddrc_init(s, 0x93100000);
+
+    /* ftahbc020 */
+    a369_ahbc_init(s, 0x94000000);
+
+    /* Parallel NOR Flash */
+    do {
+        DriveInfo *dinfo = drive_get_next(IF_PFLASH);
+        if (!pflash_cfi01_register(
+                        A369_NOR_FLASH_ADDR, 
+                        NULL,
+                        "a369.pflash",
+                        A369_NOR_FLASH_SIZE,
+                        dinfo ? dinfo->bdrv : NULL,
+                        A369_NOR_FLASH_SECT_SIZE,
+                        A369_NOR_FLASH_SIZE / A369_NOR_FLASH_SECT_SIZE,
+                        2, 0x0001, 0x227E, 0x2101, 0x0, 0)) {
+            fprintf(stderr, "qemu: Error registering flash memory.\n");
+        }
+    } while(0);
+}
+
+static void a369_board_reset(void *opaque)
+{
+    struct a369_state *s = opaque;
+    
+    if (s->ddrc.msr) {
+        s->ddrc.mcr = 0;
+        s->ddrc.msr = 0;
+        if (s->ahbc.cr) {
+            /* AHB remapped */
+            sysbus_mmio_map(sysbus_from_qdev(s->rom), 0, 0x00000000);
+            memory_region_del_subregion(s->as, s->ram);
+        } else {
+            /* AHB is not yet remapped, but SDRAM is ready */
+            memory_region_del_subregion(s->as, s->ram_alias);
+        }
+        s->ahbc.cr = 0;
+    }
+
+    cpu_reset(CPU(s->cpu));
+}
+
+static void a369_board_init(QEMUMachineInitArgs *args)
+{
+    struct a369_state *s = g_new(struct a369_state, 1);
+
+    s->as = get_system_memory();
+    s->ram  = g_new(MemoryRegion, 1);
+    s->sram = g_new(MemoryRegion, 1);
+
+    /* CPU */
+    if (!args->cpu_model)
+        args->cpu_model = "fa626te";
+
+    s->cpu = cpu_arm_init(args->cpu_model);
+    if (!s->cpu) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+
+    /* A369 supports upto 1GB ram space */
+    if (args->ram_size > 0x40000000)
+        args->ram_size = 0x40000000;
+        
+    printf("qemu: faraday a369 with %dMB ram.\n", args->ram_size >> 20);
+    
+    /* Embedded ROM Init */
+    s->rom = qdev_create(NULL, "rom");    
+    qdev_prop_set_uint32(s->rom, "size", 8192);
+    qdev_init_nofail(s->rom);
+    
+    /* 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);
+    
+    /* RAM Init */
+    memory_region_init_ram(s->ram, "a369.ram", args->ram_size);
+    vmstate_register_ram_global(s->ram);
+    
+    a369_device_init(s);
+    qemu_register_reset(a369_board_reset, s);
+    
+    if (args->kernel_filename) {
+        struct arm_boot_info *bi = g_new(struct arm_boot_info, 1);
+        
+        /* RAM Address Binding */
+        memory_region_add_subregion(s->as, 0x00000000, s->ram);
+        
+        /* Boot Info */
+        memset(bi, 0, sizeof(*bi));
+        bi->ram_size = args->ram_size;
+        bi->kernel_filename = args->kernel_filename;
+        bi->kernel_cmdline = args->kernel_cmdline;
+        bi->initrd_filename = args->initrd_filename;
+        bi->board_id = 0xa369;
+        arm_load_kernel(s->cpu, bi);
+    } else {
+        /* ROM Address Binding */
+        sysbus_mmio_map(sysbus_from_qdev(s->rom), 0, 0x00000000);
+        /* Partial RAM (before ahb remapped) Address Binding */
+        s->ram_alias = g_new(MemoryRegion, 1);
+        memory_region_init_alias(s->ram_alias, "a369.ram_alias",
+                                 s->ram,
+                                 0,
+                                 min(0x10000000, args->ram_size));
+    }
+}
+
+static QEMUMachine a369_machine = {
+    .name = "a369",
+    .desc = "Faraday A369 (fa626te)",
+    .init = a369_board_init,
+};
+
+static void a369_machine_init(void)
+{
+    qemu_register_machine(&a369_machine);
+}
+
+machine_init(a369_machine_init);
diff --git a/hw/a369_scu.c b/hw/a369_scu.c
new file mode 100644
index 0000000..ee548d4
--- /dev/null
+++ b/hw/a369_scu.c
@@ -0,0 +1,192 @@
+/*
+ * QEMU model of the A369 SCU
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Copyright (C) 2012 Dante Su <address@hidden>
+ *
+ * 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"
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    qemu_irq     irq;
+    
+    /* HW register caches */
+    uint32_t general_cfg;
+    uint32_t sclk_cfg0;
+    uint32_t sclk_cfg1;
+    uint32_t mfpsr0;
+    uint32_t mfpsr1;
+
+} a369_scu_state;
+
+static uint64_t
+a369_scu_mem_read(void *opaque, hwaddr addr, unsigned int size)
+{
+    a369_scu_state *s = opaque;
+
+    switch(addr) {
+    case 0x000:
+        return 0x00003369;
+    case 0x004:
+        return 0x00010000;
+    case 0x008:
+        return 0x00000c10;
+    case 0x00c:
+        return 0x00000230;
+    case 0x010:
+        return 0x00000083;
+    case 0x014:
+        return 0x00000100;
+    case 0x01C:
+        return 0x00000003;
+    case 0x020:
+        return 0x20010003;
+    case 0x024:
+        return 0x00000003;
+    case 0x060:
+        return 0x00280028;
+    case 0x200:
+        return s->general_cfg;
+    case 0x204:
+        return 0x00001cc8;
+    case 0x228:
+        return s->sclk_cfg0;
+    case 0x22c:
+        return s->sclk_cfg1;
+    case 0x230:
+        return 0x00003fff;
+    case 0x238:
+        return s->mfpsr0;
+    case 0x23c:
+        return s->mfpsr1;
+    case 0x240:
+        return 0x11111111;
+    case 0x244:
+        return 0x11111111;
+    case 0x254:
+        return 0x00000303;
+    case 0x258:
+        return 0x8000007f;
+    }
+
+    return 0;
+}
+
+static void
+a369_scu_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size)
+{
+    a369_scu_state *s = opaque;
+    
+    switch(addr) {
+    case 0x200:
+        s->general_cfg = (uint32_t)val;
+        break;
+    case 0x228:
+        s->sclk_cfg0 = (uint32_t)val;
+        break;
+    case 0x22c:
+        s->sclk_cfg1 = (uint32_t)val;
+        break;
+    case 0x238:
+        s->mfpsr0 = (uint32_t)val;
+        break;
+    case 0x23c:
+        s->mfpsr1 = (uint32_t)val;
+        break;
+    default:
+        break;
+    }
+}
+
+static const MemoryRegionOps bus_ops = {
+    .read  = a369_scu_mem_read,
+    .write = a369_scu_mem_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4
+    }
+};
+
+static void a369_scu_reset(DeviceState *d)
+{
+    a369_scu_state *s = DO_UPCAST(a369_scu_state, busdev.qdev, d);
+    
+    s->general_cfg = 0x00001078;
+    s->sclk_cfg0   = 0x26877330;
+    s->sclk_cfg1   = 0x000a0a0a;
+    s->mfpsr0      = 0x00000241;
+    s->mfpsr1      = 0x00000000;
+}
+
+static int a369_scu_init(SysBusDevice *dev)
+{
+    a369_scu_state *s = FROM_SYSBUS(typeof(*s), dev);
+    
+    memory_region_init_io(&s->iomem, &bus_ops, s, "a369_scu", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+    sysbus_init_irq(dev, &s->irq);
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_a369_scu = {
+    .name = "a369_scu",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(general_cfg, a369_scu_state),
+        VMSTATE_UINT32(sclk_cfg0, a369_scu_state),
+        VMSTATE_UINT32(sclk_cfg1, a369_scu_state),
+        VMSTATE_UINT32(mfpsr0, a369_scu_state),
+        VMSTATE_UINT32(mfpsr1, a369_scu_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void a369_scu_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+    DeviceClass *k = DEVICE_CLASS(klass);
+
+    sdc->init  = a369_scu_init;
+    k->vmsd    = &vmstate_a369_scu;
+    k->reset   = a369_scu_reset;
+    k->no_user = 1;
+}
+
+static TypeInfo a369_scu_info = {
+    .name           = "a369_scu",
+    .parent         = TYPE_SYS_BUS_DEVICE,
+    .instance_size  = sizeof(a369_scu_state),
+    .class_init     = a369_scu_class_init,
+};
+
+static void a369_scu_register_types(void)
+{
+    type_register_static(&a369_scu_info);
+}
+
+type_init(a369_scu_register_types)
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 6d049e7..4cc85e5 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -1,4 +1,10 @@
 obj-y = integratorcp.o versatilepb.o arm_pic.o
+obj-y += a369.o a369_scu.o \
+                               rom.o ftdmac020.o ftapbbrg020.o \
+                               ftintc020.o fttmr010.o ftpwmtmr010.o \
+                               ftspi020.o ftssp010.o fti2c010.o \
+                               ftrtc011.o ftwdt010.o ftmac110.o ftgmac100.o 
ftlcdc200.o \
+                               fttsc010.o ftkbc010.o ftnandc021.o ftsdc010.o
 obj-y += arm_boot.o
 obj-y += xilinx_zynq.o zynq_slcr.o
 obj-y += xilinx_spips.o
-- 
1.7.9.5


********************* Confidentiality Notice ************************
This electronic message and any attachments may contain
confidential and legally privileged information or
information which is otherwise protected from disclosure.
If you are not the intended recipient,please do not disclose
the contents, either in whole or in part, to anyone,and
immediately delete the message and any attachments from
your computer system and destroy all hard copies.
Thank you for your cooperation.
***********************************************************************




reply via email to

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