On Fri, Jan 18, 2013 at 6:28 AM, Dante <dant...@faraday-tech.com> wrote: > 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:
The cover letter in git send-email will generate this for you, please use that instead. > > 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 <dant...@faraday-tech.com> > --- > 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 <dant...@faraday-tech.com> > + * > + * This code is licensed under the GPL. Which version? We prefer "GPL v2 or later, at your option". > + */ > + > +#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)) Macro names should be uppercase. > +#endif > + > +#ifndef max > +#define max(a, b) ((a) > (b) ? (a) : (b)) > +#endif > + > +struct a369_ahbc_state { Struct names should use CamelCase and don't forget the typedef as instructed in HACKING. > + 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); Function prototypes belong to a header file. > + > +/* 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) { Please use switch(). > + if (!(s->cr & 0x01) && (val & 0x01)) { > + /* AHB remap */ > + printf("[qemu] a369: AHB remap...\n"); Remove printfs or convert them to tracepoints or debug printfs. > + sysbus_mmio_map(sysbus_from_qdev(mach->rom), 0, 0x40000000); Doesn't the previous mapping still stay? > + 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); DEVICE_NATIVE_ENDIAN would indicate that the device is very close to CPU. Probably DEVICE_LITTLE_ENDIAN would make more sense. > + } > + 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 { Just move the variable definitions to the start of the function, or extract to a separate function. > + 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 No disabled or commented out code, please. They will just bit rot. > + 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++) { Space between 'for' and '('. > + 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"); exit(), hw_error()? > + } > + } 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) Please use checkpatch.pl to catch brace problems. > + 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 <dant...@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" > + > +typedef struct { The struct should also have a name. > + 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. > *********************************************************************** > >