[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH 01/18] hw: add Faraday a369 SoC platform support
From: |
Blue Swirl |
Subject: |
Re: [Qemu-devel] [PATCH 01/18] hw: add Faraday a369 SoC platform support |
Date: |
Sat, 19 Jan 2013 08:15:48 +0000 |
On Fri, Jan 18, 2013 at 6:28 AM, Dante <address@hidden> 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 <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.
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 <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 {
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.
> ***********************************************************************
>
>
- [Qemu-devel] [PATCH 01/18] hw: add Faraday a369 SoC platform support, Dante, 2013/01/18
- [Qemu-devel] [PATCH 02/18] hw: add QEMU model for Faraday APB DMA, Dante, 2013/01/18
- [Qemu-devel] [PATCH 03/18] hw: add QEMU model for Faraday AHB DMA, Dante, 2013/01/18
- [Qemu-devel] [PATCH 04/18] hw: add QEMU model for Faraday 1Gbps Ethernet MAC, Dante, 2013/01/18
- [Qemu-devel] [PATCH 05/18] hw: add QEMU model for Faraday 10/100Mbps Ethernet MAC, Dante, 2013/01/18
- Re: [Qemu-devel] [PATCH 01/18] hw: add Faraday a369 SoC platform support,
Blue Swirl <=
- [Qemu-devel] [PATCH v2 00/20] Add Faraday A36x SoC platform support, Kuo-Jung Su, 2013/01/25
- [Qemu-devel] [PATCH v2 01/20] arm: add Faraday a36x SoC platform support, Kuo-Jung Su, 2013/01/25
- Re: [Qemu-devel] [PATCH v2 01/20] arm: add Faraday a36x SoC platform support, Blue Swirl, 2013/01/25
- Re: [Qemu-devel] [PATCH v2 01/20] arm: add Faraday a36x SoC platform support, Igor Mitsyanko, 2013/01/31