On Fri, Jan 25, 2013 at 8:19 AM, Kuo-Jung Su <dant...@gmail.com> wrote: > From: Kuo-Jung Su <dant...@faraday-tech.com> > > The Faraday A360/A369 EVB is a Faraday platform main board used for the > Faraday IP functional verification based on the well-known ARM AMBA 2.0 > architecture. This main board provides a fully verified microprocessor > platform, ATA-II, OTG 2.0 and USB 2.0 host connectivity. > > Faraday A360 EVB provides the on-board DDR2-SODIMM (256 MB), > NAND Flash (128 MB), USB2.0 interface, two PCI Express interfaces, > two I2C interfaces, two SSP ports, Secure Digital interface, and a 12-bit > A/D converter in addition to many other features. > > Faraday A369 EVB provides the on-board DDR2-SODIMM (512 MB), > NAND Flash (256 MB), SPI Flash ROM (16 MB), I2C EPROM, Giga-bit Ethernet, > IDE, SATA host, OTG 2.0 and USB 2.0 host connectors, video output interface, > TV encoder for video output, LCD controller interface, SD/MMC card reader > interface, I2S codec, UART(X2), Multi-ICE, 80 ports, and an AHB extension bus. > > Signed-off-by: Kuo-Jung Su <dant...@faraday-tech.com> > --- > hw/a360.c | 271 +++++++++++++++++++++++ > hw/a369.c | 581 > ++++++++++++++++++++++++++++++++++++++++++++++++++ > hw/arm/Makefile.objs | 6 + > hw/faraday.h | 21 ++ > 4 files changed, 879 insertions(+) > create mode 100644 hw/a360.c > create mode 100644 hw/a369.c > create mode 100644 hw/faraday.h > > diff --git a/hw/a360.c b/hw/a360.c > new file mode 100644 > index 0000000..cb0a588 > --- /dev/null > +++ b/hw/a360.c > @@ -0,0 +1,271 @@ > +/* > + * Faraday A360 Evalution Board > + * > + * Copyright (c) 2012 Faraday Technology > + * Written by Dante Su <dant...@faraday-tech.com> > + * > + * This code is licensed under GNU GPL v2. > + */ > + > +#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" > +#include "faraday.h" > + > +typedef struct A360State { > + ARMCPU *cpu; > + DeviceState *hdma; /* AHB DMA */ > + DeviceState *pdma; /* APB DMA */ > + > + MemoryRegion *as; > + MemoryRegion *ram; > + > + i2c_bus *i2c[2]; > + > + struct { > + MemoryRegion iomem; > + } pmu; > +} a360_state;
The typedef names should be also in CamelCase. > + > +/* PMU block */ > +static uint64_t > +a360_pmu_read(void *opaque, hwaddr addr, unsigned size) > +{ > + uint64_t ret = 0; > + > + switch (addr) { > + case 0x30: > + ret = 27 << 3; > + break; > + } > + > + return ret; > +} > + > +static void > +a360_pmu_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) > +{ > +} > + > +static const MemoryRegionOps a360_pmu_ops = { > + .read = a360_pmu_read, > + .write = a360_pmu_write, > + .endianness = DEVICE_LITTLE_ENDIAN, > +}; > + > +static int > +a360_pmu_init(a360_state *s, hwaddr base) > +{ > + MemoryRegion *iomem = &s->pmu.iomem; > + memory_region_init_io(iomem, &a360_pmu_ops, s, "a360_pmu", 0x1000); > + memory_region_add_subregion(s->as, base, iomem); > + return 0; > +} > + > +/* Board init. */ > +static void > +a360_device_init(a360_state *s) > +{ > + qemu_irq *pic; > + qemu_irq ack, req; > + qemu_irq cs_line; > + DeviceState *ds; > + int i, done_nic = 0, nr_flash = 1; > + SSIBus *spi; > + DeviceState *fl; > + > + /* Interrupt Controller */ > + pic = ftintc020_init(0x98800000, s->cpu); > + > + /* Timer */ > + ds = qdev_create(NULL, "fttmr010"); > + qdev_prop_set_uint32(ds, "freq", 66 * 1000000); > + qdev_init_nofail(ds); > + sysbus_mmio_map(SYS_BUS_DEVICE(ds), 0, 0x98400000); > + sysbus_connect_irq(SYS_BUS_DEVICE(ds), 0, pic[42]); > + sysbus_connect_irq(SYS_BUS_DEVICE(ds), 1, pic[19]); > + sysbus_connect_irq(SYS_BUS_DEVICE(ds), 2, pic[14]); > + sysbus_connect_irq(SYS_BUS_DEVICE(ds), 3, pic[15]); > + > + /* Serial (FTUART010 which is 16550A compatible) */ > + if (serial_hds[0]) { > + serial_mm_init(s->as, > + 0x98200000, > + 2, > + pic[10], > + 18432000 / 16, > + serial_hds[0], > + DEVICE_LITTLE_ENDIAN); > + } > + if (serial_hds[1]) { > + serial_mm_init(s->as, > + 0x98300000, > + 2, > + pic[11], > + 18432000 / 16, > + serial_hds[1], > + DEVICE_LITTLE_ENDIAN); > + } > + > + /* pmu */ > + a360_pmu_init(s, 0x98100000); > + > + /* ftdmac020 */ > + s->hdma = sysbus_create_varargs("ftdmac020", > + 0x90400000, > + pic[21], /* ALL */ > + pic[40], /* TC */ > + pic[41], /* ERR */ > + NULL); > + > + /* ftapbbrg020 */ > + s->pdma = sysbus_create_simple("ftapbbrg020", 0x90500000, pic[24]); > + > + /* ftsdc010 */ > + ds = sysbus_create_simple("ftsdc010", 0x90700000, pic[5]); > + ack = qdev_get_gpio_in(ds, 0); > + req = qdev_get_gpio_in(s->hdma, 0); > + qdev_connect_gpio_out(s->hdma, 0, ack); > + qdev_connect_gpio_out(ds, 0, req); > + > + /* fusbh200 */ > + sysbus_create_simple("faraday-ehci-usb", 0x90A00000, pic[23]); > + > + /* fotg210 */ > + sysbus_create_simple("faraday-ehci-usb", 0x90B00000, pic[26]); > + > + /* ftmac110 */ > + for (i = 0; i < nb_nics; i++) { > + NICInfo *nd = &nd_table[i]; > + if (!done_nic && (!nd->model || strcmp(nd->model, "ftmac110") == 0)) > { > + ftmac110_init(nd, 0x90900000, pic[25]); > + done_nic = 1; > + } > + } > + > + /* ftwdt010 */ > + sysbus_create_simple("ftwdt010", 0x98500000, pic[16]); > + > + /* ftlcdc200 */ > + sysbus_create_varargs("ftlcdc200", > + 0x90600000, > + pic[27], /* Global */ > + NULL); > + > + /* fti2c010 */ > + ds = sysbus_create_simple("fti2c010", 0x98A00000, pic[3]); > + s->i2c[0] = (i2c_bus *)qdev_get_child_bus(ds, "i2c"); > + ds = sysbus_create_simple("fti2c010", 0x98C00000, pic[22]); > + s->i2c[1] = (i2c_bus *)qdev_get_child_bus(ds, "i2c"); > + > + /* ftssp010 */ > + ds = qdev_create(NULL, "ftssp010"); > + > + /* i2s */ > + qdev_prop_set_ptr(ds, "codec_i2c", s->i2c[0]); > + qdev_init_nofail(ds); > + sysbus_mmio_map(SYS_BUS_DEVICE(ds), 0, 0x98B00000); > + sysbus_connect_irq(SYS_BUS_DEVICE(ds), 0, pic[2]); > + > + /* 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(SYS_BUS_DEVICE(ds), i+1, cs_line); > + } > + > + /* DMA (Tx) */ > + ack = qdev_get_gpio_in(ds, 0); > + req = qdev_get_gpio_in(s->pdma, 1); > + qdev_connect_gpio_out(s->pdma, 1, ack); > + qdev_connect_gpio_out(ds, 0, req); > + > + /* DMA (Rx) */ > + ack = qdev_get_gpio_in(ds, 1); > + req = qdev_get_gpio_in(s->pdma, 2); > + qdev_connect_gpio_out(s->pdma, 2, ack); > + qdev_connect_gpio_out(ds, 1, req); > +} > + > +static void > +a360_board_reset(void *opaque) > +{ > + a360_state *s = opaque; > + > + cpu_reset(CPU(s->cpu)); > +} > + > +static void > +a360_board_init(QEMUMachineInitArgs *args) > +{ > + struct arm_boot_info *bi = NULL; > + a360_state *s = g_new(a360_state, 1); > + > + s->as = get_system_memory(); > + s->ram = 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); > + } > + > + /* A360 supports upto 1GB ram space */ > + if (args->ram_size > 0x40000000) { > + args->ram_size = 0x40000000; > + } > + > + printf("qemu: faraday a360 with %dMB ram.\n", args->ram_size >> 20); Please turn printfs into debug versions or tracepoints. > + > + /* RAM Init */ > + memory_region_init_ram(s->ram, "a360.ram", args->ram_size); > + vmstate_register_ram_global(s->ram); > + > + a360_device_init(s); > + qemu_register_reset(a360_board_reset, s); > + > + /* Prepare for direct boot from linux kernel or u-boot elf */ > + bi = g_new0(struct arm_boot_info, 1); > + > + /* RAM Address Binding */ > + memory_region_add_subregion(s->as, 0x00000000, s->ram); > + > + /* Boot Info */ > + 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 = 0xa360; > + arm_load_kernel(s->cpu, bi); > +} > + > +static QEMUMachine a360_machine = { > + .name = "a360", > + .desc = "Faraday A360 (fa626te)", > + .init = a360_board_init, > +}; > + > +static void > +a360_machine_init(void) > +{ > + qemu_register_machine(&a360_machine); > +} > + > +machine_init(a360_machine_init); > diff --git a/hw/a369.c b/hw/a369.c > new file mode 100644 > index 0000000..646888f > --- /dev/null > +++ b/hw/a369.c > @@ -0,0 +1,581 @@ > +/* > + * Faraday A369 Evalution Board > + * > + * Copyright (c) 2012 Faraday Technology > + * Written by Dante Su <dant...@faraday-tech.com> > + * > + * This code is licensed under GNU GPL v2. > + */ > + > +#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" > +#include "faraday.h" > + > +#define A369_NOR_FLASH_ADDR 0x20000000 > +#define A369_NOR_FLASH_SIZE (16 * 1024 * 1024) > +#define A369_NOR_FLASH_SECT_SIZE (128 * 1024) > + > +typedef struct A369State { > + ARMCPU *cpu; > + DeviceState *rom; > + DeviceState *hdma[2]; /* AHB DMA */ > + DeviceState *pdma; /* APB DMA */ > + > + MemoryRegion *as; > + MemoryRegion *ram; > + MemoryRegion *ram_alias; > + MemoryRegion *sram; > + > + i2c_bus *i2c[2]; > + > + struct { > + MemoryRegion iomem; > + /* HW register cache */ > + uint32_t general_cfg; > + uint32_t sclk_cfg0; > + uint32_t sclk_cfg1; > + uint32_t mfpsr0; > + uint32_t mfpsr1; > + } scu; > + > + struct { > + MemoryRegion iomem; > + /* HW register cache */ > + uint32_t cr; > + } ahbc; > + > + struct { > + MemoryRegion iomem; > + /* HW register cache */ > + uint32_t mcr; > + uint32_t msr; > + } ddrc; > + > +} a369_state; > + > +/* SCU block */ > + > +static uint64_t > +a369_scu_read(void *opaque, hwaddr addr, unsigned size) > +{ > + a369_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->scu.general_cfg; > + case 0x204: return 0x00001cc8; > + case 0x228: return s->scu.sclk_cfg0; > + case 0x22c: return s->scu.sclk_cfg1; > + case 0x230: return 0x00003fff; > + case 0x238: return s->scu.mfpsr0; > + case 0x23c: return s->scu.mfpsr1; > + case 0x240: return 0x11111111; > + case 0x244: return 0x11111111; > + case 0x254: return 0x00000303; > + case 0x258: return 0x8000007f; > + } > + > + return 0; > +} > + > +static void > +a369_scu_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) > +{ > + a369_state *s = opaque; > + > + switch (addr) { > + case 0x200: > + s->scu.general_cfg = (uint32_t)val; > + break; > + case 0x228: > + s->scu.sclk_cfg0 = (uint32_t)val; > + break; > + case 0x22c: > + s->scu.sclk_cfg1 = (uint32_t)val; > + break; > + case 0x238: > + s->scu.mfpsr0 = (uint32_t)val; > + break; > + case 0x23c: > + s->scu.mfpsr1 = (uint32_t)val; > + break; > + } > +} > + > +static const MemoryRegionOps a369_scu_ops = { > + .read = a369_scu_read, > + .write = a369_scu_write, > + .endianness = DEVICE_LITTLE_ENDIAN, > + .valid = { > + .min_access_size = 4, > + .max_access_size = 4 > + } > +}; > + > +static int > +a369_scu_init(a369_state *s, hwaddr base) > +{ > + MemoryRegion *iomem = &s->scu.iomem; > + > + memory_region_init_io(iomem, &a369_scu_ops, s, "a369_scu", 0x1000); > + memory_region_add_subregion(s->as, base, iomem); > + > + s->scu.general_cfg = 0x00001078; > + s->scu.sclk_cfg0 = 0x26877330; > + s->scu.sclk_cfg1 = 0x000a0a0a; > + s->scu.mfpsr0 = 0x00000241; > + s->scu.mfpsr1 = 0x00000000; > + > + return 0; > +} > + > +/* AHB controller block */ > + > +static uint64_t > +a369_ahbc_read(void *opaque, hwaddr addr, unsigned size) > +{ > + a369_state *s = opaque; > + > + 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->ahbc.cr; > + case 0x8c: return 0x00010301; > + } > + > + return 0; > +} > + > +static void > +a369_ahbc_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) > +{ > + a369_state *s = opaque; > + > + switch (addr) { > + case 0x88: > + if (!(s->ahbc.cr & 0x01) && (val & 0x01)) { > + /* AHB remap */ > + sysbus_mmio_map(SYS_BUS_DEVICE(s->rom), 0, 0x40000000); > + memory_region_del_subregion(s->as, s->ram_alias); > + memory_region_add_subregion(s->as, 0x00000000, s->ram); > + } > + s->ahbc.cr = (uint32_t)val; > + break; > + } > +} > + > +static const MemoryRegionOps a369_ahbc_ops = { > + .read = a369_ahbc_read, > + .write = a369_ahbc_write, > + .endianness = DEVICE_LITTLE_ENDIAN, > +}; > + > +static int > +a369_ahbc_init(a369_state *s, hwaddr base) > +{ > + MemoryRegion *iomem = &s->ahbc.iomem; > + > + memory_region_init_io(iomem, &a369_ahbc_ops, s, "a369_ahbc", 0x1000); > + memory_region_add_subregion(s->as, base, iomem); > + > + s->ahbc.cr = 0; > + > + return 0; > +} > + > +/* DDRII controller block */ > + > +static uint64_t > +a369_ddrc_read(void *opaque, hwaddr addr, unsigned size) > +{ > + a369_state *s = opaque; > + > + switch (addr) { > + case 0x00: return s->ddrc.mcr; > + case 0x04: return s->ddrc.msr; > + } > + > + return 0; > +} > + > +static void > +a369_ddrc_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) > +{ > + a369_state *s = opaque; > + > + switch (addr) { > + case 0x00: > + s->ddrc.mcr = (uint32_t)val & 0xffff; > + break; > + case 0x04: > + val = (val & 0x3f) | (s->ddrc.msr & 0x100); > + if (!(s->ddrc.msr & 0x100) && (val & 0x01)) { > + val &= 0xfffffffe; > + val |= 0x100; > + memory_region_add_subregion(s->as, 0x10000000, s->ram_alias); > + } > + s->ddrc.msr = (uint32_t)val; > + break; > + } > +} > + > +static const MemoryRegionOps a369_ddrc_ops = { > + .read = a369_ddrc_read, > + .write = a369_ddrc_write, > + .endianness = DEVICE_LITTLE_ENDIAN, > +}; > + > +static int > +a369_ddrc_init(a369_state *s, hwaddr base) > +{ > + MemoryRegion *iomem = &s->ddrc.iomem; > + > + memory_region_init_io(iomem, &a369_ddrc_ops, s, "a369_ddrc", 0x1000); > + memory_region_add_subregion(s->as, base, iomem); > + > + s->ddrc.mcr = 0; > + s->ddrc.msr = 0; > + > + return 0; > +} > + > +/* Board init. */ > + > +static void > +a369_device_init(a369_state *s) > +{ > + qemu_irq *pic; > + qemu_irq ack, req; > + qemu_irq cs_line; > + DeviceState *ds; > + int i, done_nic = 0, nr_flash = 1; > + SSIBus *spi; > + DeviceState *fl; > + DriveInfo *dinfo; > + > + /* 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(SYS_BUS_DEVICE(ds), 0, 0x92300000); > + sysbus_connect_irq(SYS_BUS_DEVICE(ds), 0, pic[8]); > + sysbus_connect_irq(SYS_BUS_DEVICE(ds), 1, pic[9]); > + sysbus_connect_irq(SYS_BUS_DEVICE(ds), 2, pic[10]); > + sysbus_connect_irq(SYS_BUS_DEVICE(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_LITTLE_ENDIAN); > + } > + if (serial_hds[1]) { > + serial_mm_init(s->as, > + 0x92c00000, > + 2, > + pic[54], > + 18432000 / 16, > + serial_hds[1], > + DEVICE_LITTLE_ENDIAN); > + } > + > + /* ftscu010 */ > + a369_scu_init(s, 0x92000000); > + > + /* ftddrII030 */ > + a369_ddrc_init(s, 0x93100000); > + > + /* ftahbc020 */ > + a369_ahbc_init(s, 0x94000000); > + > + /* ftdmac020 */ > + s->hdma[0] = sysbus_create_varargs("ftdmac020", > + 0x90300000, > + pic[0], /* ALL (NC in A369) */ > + pic[15], /* TC */ > + pic[16], /* ERR */ > + NULL); > + s->hdma[1] = sysbus_create_varargs("ftdmac020", > + 0x96100000, > + pic[0], /* ALL (NC in A369) */ > + pic[17], /* TC */ > + pic[18], /* ERR */ > + NULL); > + > + /* ftapbbrg020 */ > + s->pdma = sysbus_create_simple("ftapbbrg020", 0x90f00000, pic[14]); > + > + /* ftnandc021 */ > + ds = sysbus_create_simple("ftnandc021", 0x90200000, pic[30]); > + ack = qdev_get_gpio_in(ds, 0); > + req = qdev_get_gpio_in(s->hdma[0], 15); > + qdev_connect_gpio_out(s->hdma[0], 15, ack); > + qdev_connect_gpio_out(ds, 0, req); > + > + /* ftsdc010 */ > +#if 0 > + ds = sysbus_create_simple("ftsdc010", 0x90500000, pic[38]); > + ack = qdev_get_gpio_in(ds, 0); > + req = qdev_get_gpio_in(s->hdma[0], 14); > + qdev_connect_gpio_out(s->hdma[0], 14, ack); > + qdev_connect_gpio_out(ds, 0, req); > +#endif Remove disabled code. > + > + ds = sysbus_create_simple("ftsdc010", 0x90600000, pic[39]); > + ack = qdev_get_gpio_in(ds, 0); > + req = qdev_get_gpio_in(s->hdma[0], 13); > + qdev_connect_gpio_out(s->hdma[0], 13, ack); > + qdev_connect_gpio_out(ds, 0, req); > + > + /* fusbh200 */ > + sysbus_create_simple("faraday-ehci-usb", 0x90800000, pic[36]); > + > + /* fotg210 */ > + sysbus_create_simple("faraday-ehci-usb", 0x90900000, pic[37]); > + > + /* 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], /* ALL (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 */ > + ds = qdev_create(NULL, "ftssp010"); > + > + /* i2s */ > + qdev_prop_set_ptr(ds, "codec_i2c", s->i2c[0]); > + qdev_init_nofail(ds); > + sysbus_mmio_map(SYS_BUS_DEVICE(ds), 0, 0x92700000); > + sysbus_connect_irq(SYS_BUS_DEVICE(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(SYS_BUS_DEVICE(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); > + > + /* Parallel NOR Flash */ > + 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)) { > + hw_error("qemu: Error registering flash memory.\n"); > + exit(1); > + } > +} > + > +static void > +a369_board_reset(void *opaque) > +{ > + 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(SYS_BUS_DEVICE(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 arm_boot_info *bi = NULL; > + a369_state *s = g_new(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) { > + bi = g_new0(struct arm_boot_info, 1); > + > + /* RAM Address Binding */ > + memory_region_add_subregion(s->as, 0x00000000, s->ram); > + > + /* Boot Info */ > + 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(SYS_BUS_DEVICE(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/arm/Makefile.objs b/hw/arm/Makefile.objs > index 6d049e7..c7bb10e 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 += a360.o a369.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 > diff --git a/hw/faraday.h b/hw/faraday.h > new file mode 100644 > index 0000000..f4fe0cc > --- /dev/null > +++ b/hw/faraday.h > @@ -0,0 +1,21 @@ > +/* > + * Faraday SoC platform support. > + * > + * Copyright (c) 2013 Faraday Technology > + * Written by Kuo-Jung Su <dant...@gmail.com> > + * > + * This code is licensed under the GNU GPL v2. > + */ > +#ifndef FARADAY_H > +#define FARADAY_H > + > +/* ftintc020.c */ > +qemu_irq *ftintc020_init(hwaddr base, ARMCPU *cpu); > + > +/* ftgmac100.c */ > +void ftgmac100_init(NICInfo *, uint32_t, qemu_irq); Please add the parameter names, they also document how to use the function. > + > +/* ftmac110.c */ > +void ftmac110_init(NICInfo *, uint32_t, qemu_irq); > + > +#endif > -- > 1.7.9.5 >