All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Peter A. G. Crosthwaite" <peter.crosthwaite@petalogix.com>
To: qemu-devel@nongnu.org, monstr@monstr.eu,
	john.williams@petalogix.com, peter.crosthwaite@petalogix.com,
	edgar.iglesias@petalogix.com, duyl@xilinx.com, linnj@xilinx.com,
	paul@codesourcery.com, peter.maydell@linaro.org,
	afaerber@suse.de
Subject: [Qemu-devel] [RFC PATCH v2 4/4] xilinx_zynq: machine model initial version
Date: Tue,  7 Feb 2012 16:19:47 +1000	[thread overview]
Message-ID: <9c00559489fb68d9a0cd1f0383b0cc98a565cbae.1328594621.git.peter.crosthwaite@petalogix.com> (raw)
In-Reply-To: <cover.1328594621.git.peter.crosthwaite@petalogix.com>
In-Reply-To: <cover.1328594621.git.peter.crosthwaite@petalogix.com>

Xilinx zynq-7000 machine model. Also includes device model for the zynq-specific
system level control register (SLCR) module.

Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite@petalogix.com>
---
changes since v1:
Added gem init function
remowed WDT instantiation
Added maintainers information
removed dead sys_id and proc_id variables

 MAINTAINERS          |    5 +
 Makefile.target      |    1 +
 hw/xilinx_zynq.c     |  178 +++++++++++++++++
 hw/zynq_arm_sysctl.c |  526 ++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 710 insertions(+), 0 deletions(-)
 create mode 100644 hw/xilinx_zynq.c
 create mode 100644 hw/zynq_arm_sysctl.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 173e893..9246bfa 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -237,6 +237,11 @@ M: Peter Maydell <peter.maydell@linaro.org>
 S: Maintained
 F: hw/versatilepb.c
 
+Xilinx Zynq
+M: Peter Crosthwaite <peter.crosthwaite@petalogix.com>
+S: Maintained
+F: hw/xilinx_zynq.c
+
 CRIS Machines
 -------------
 Axis Dev88
diff --git a/Makefile.target b/Makefile.target
index e02a56b..87a8662 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -340,6 +340,7 @@ obj-arm-y += versatile_pci.o
 obj-arm-y += cadence_uart.o
 obj-arm-y += cadence_ttc.o
 obj-arm-y += cadence_gem.o
+obj-arm-y += xilinx_zynq.o zynq_arm_sysctl.o
 obj-arm-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o
 obj-arm-y += arm_l2x0.o
 obj-arm-y += arm_mptimer.o
diff --git a/hw/xilinx_zynq.c b/hw/xilinx_zynq.c
new file mode 100644
index 0000000..36765fb
--- /dev/null
+++ b/hw/xilinx_zynq.c
@@ -0,0 +1,178 @@
+/*
+ * Xilinx Zynq Baseboard System emulation.
+ *
+ * Copyright (c) 2010 Xilinx.
+ * Copyright (c) 2012 Peter A.G. Crosthwaite (peter.croshtwaite@petalogix.com)
+ * Copyright (c) 2012 Petalogix Pty Ltd.
+ * Written by Haibing Ma
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
+ * 02139, USA.
+ */
+
+#include "sysbus.h"
+#include "arm-misc.h"
+#include "net.h"
+#include "exec-memory.h"
+#include "sysemu.h"
+#include "boards.h"
+#include "flash.h"
+#include "blockdev.h"
+#include "loader.h"
+
+#define FLASH_SIZE (64 * 1024 * 1024)
+#define FLASH_SECTOR_SIZE (128 * 1024)
+
+#define IRQ_OFFSET 32 /* pic interrupts start from index 32 */
+
+static struct arm_boot_info zynq_binfo = {};
+
+static void gem_init(NICInfo *nd, uint32_t base, qemu_irq irq)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+
+    qemu_check_nic_model(nd, "cadence_gem");
+    dev = qdev_create(NULL, "cadence_gem");
+    qdev_set_nic_properties(dev, nd);
+    qdev_init_nofail(dev);
+    s = sysbus_from_qdev(dev);
+    sysbus_mmio_map(s, 0, base);
+    sysbus_connect_irq(s, 0, irq);
+}
+
+static void zynq_init(ram_addr_t ram_size, const char *boot_device,
+                        const char *kernel_filename, const char *kernel_cmdline,
+                        const char *initrd_filename, const char *cpu_model)
+{
+    CPUState *env = NULL;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *ext_ram = g_new(MemoryRegion, 1);
+    MemoryRegion *ocm_ram = g_new(MemoryRegion, 1);
+    DeviceState *dev;
+    SysBusDevice *busdev;
+    qemu_irq *irqp;
+    qemu_irq pic[64];
+    NICInfo *nd;
+    int n;
+    qemu_irq cpu_irq[4];
+
+    if (!cpu_model) {
+        cpu_model = "cortex-a9";
+    }
+
+    for (n = 0; n < smp_cpus; n++) {
+        env = cpu_init(cpu_model);
+        if (!env) {
+            fprintf(stderr, "Unable to find CPU definition\n");
+            exit(1);
+        }
+        irqp = arm_pic_init_cpu(env);
+        cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
+    }
+
+    /* max 2GB ram */
+    if (ram_size > 0x80000000) {
+        ram_size = 0x80000000;
+    }
+
+    /* DDR remapped to address zero.  */
+    memory_region_init_ram(ext_ram, "zynq.ext_ram", ram_size);
+    vmstate_register_ram_global(ext_ram);
+    memory_region_add_subregion(address_space_mem, 0, ext_ram);
+
+    /* 256K of on-chip memory */
+    memory_region_init_ram(ocm_ram, "zynq.ocm_ram", 256 << 10);
+    vmstate_register_ram_global(ocm_ram);
+    memory_region_add_subregion(address_space_mem, 0xFFFC0000, ocm_ram);
+
+    DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0);
+
+#ifndef ZYNQ_FLASH_INTEL
+    /* AMD */
+    pflash_cfi02_register(0xe2000000, NULL, "zynq.pflash", FLASH_SIZE,
+                          dinfo ? dinfo->bdrv : NULL, FLASH_SECTOR_SIZE,
+                          FLASH_SIZE/FLASH_SECTOR_SIZE, 1,
+                          1, 0x0066, 0x0022, 0x0000, 0x0000, 0x0555, 0x2aa,
+                              0);
+#else
+    /* INTEL is working well */
+    pflash_cfi01_register(0xe2000000, NULL, "zynq.pflash", FLASH_SIZE,
+                          dinfo ? dinfo->bdrv : NULL, FLASH_SECTOR_SIZE,
+                          FLASH_SIZE/FLASH_SECTOR_SIZE,
+                          1, 0x89, 0x18, 0x0000, 0x0, 0);
+#endif
+
+    { /* System Level Control Register (SLCR) */
+        dev = qdev_create(NULL, "xilinx,zynq_sysctl");
+        qdev_init_nofail(dev);
+        sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xF8000000);
+    }
+
+    { /* mp core */
+        dev = qdev_create(NULL, "a9mpcore_priv");
+        qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
+        qdev_init_nofail(dev);
+        busdev = sysbus_from_qdev(dev);
+        zynq_binfo.smp_priv_base = 0xF8F00000;
+        printf("a0mpcore_priv: smp_priv_base %x\n",
+                (unsigned)zynq_binfo.smp_priv_base);
+        sysbus_mmio_map(busdev, 0, zynq_binfo.smp_priv_base);
+        for (n = 0; n < smp_cpus; n++) {
+            sysbus_connect_irq(busdev, n, cpu_irq[n]);
+        }
+    }
+
+    for (n = 0; n < 64; n++) { /* external IRQ pin is at offset 32 */
+        pic[n] = qdev_get_gpio_in(dev, n);
+    }
+
+    sysbus_create_simple("cadence_uart", 0xE0000000, pic[59-IRQ_OFFSET]);
+    sysbus_create_simple("cadence_uart", 0xE0001000, pic[82-IRQ_OFFSET]);
+
+    sysbus_create_varargs("cadence_ttc", 0xF8001000,
+            pic[42-IRQ_OFFSET], pic[43-IRQ_OFFSET], pic[44-IRQ_OFFSET], NULL);
+    sysbus_create_varargs("cadence_ttc", 0xF8002000,
+            pic[69-IRQ_OFFSET], pic[70-IRQ_OFFSET], pic[71-IRQ_OFFSET], NULL);
+
+    for (n = 0; n < nb_nics; n++) {
+        nd = &nd_table[n];
+        if (n == 0) {
+            gem_init(nd, 0xE000B000, pic[54-IRQ_OFFSET]);
+        } else if (n == 1) {
+            gem_init(nd, 0xE000C000, pic[77-IRQ_OFFSET]);
+        }
+    }
+
+    zynq_binfo.ram_size = ram_size;
+    zynq_binfo.kernel_filename = kernel_filename;
+    zynq_binfo.kernel_cmdline = kernel_cmdline;
+    zynq_binfo.initrd_filename = initrd_filename;
+    zynq_binfo.nb_cpus = smp_cpus;
+    zynq_binfo.board_id = 0xd32;
+    zynq_binfo.loader_start = 0;
+    arm_load_kernel(first_cpu, &zynq_binfo);
+}
+
+static QEMUMachine zynq_machine = {
+    .name = "xilinx-zynq-a9",
+    .desc = "Xilinx Zynq Platform Baseboard for Cortex-A9",
+    .init = zynq_init,
+    .use_scsi = 1,
+    .max_cpus = 2,
+    .no_sdcard = 1
+};
+
+static void zynq_machine_init(void)
+{
+    qemu_register_machine(&zynq_machine);
+}
+
+machine_init(zynq_machine_init);
diff --git a/hw/zynq_arm_sysctl.c b/hw/zynq_arm_sysctl.c
new file mode 100644
index 0000000..138531e
--- /dev/null
+++ b/hw/zynq_arm_sysctl.c
@@ -0,0 +1,526 @@
+/*
+ * Status and system control registers for Xilinx Zynq Platform
+ *
+ * Copyright (c) 2011 Michal Simek <monstr@monstr.eu>
+ * Copyright (c) 2012 PetaLogix Pty Ltd.
+ * Based on hw/arm_sysctl.c, written by Paul Brook
+ *
+ * This code is licenced under the GPL.
+ */
+
+#include "hw.h"
+#include "qemu-timer.h"
+#include "sysbus.h"
+#include "sysemu.h"
+
+#ifdef ZYNQ_ARM_SYSCTL_ERR_DEBUG
+#define qemu_debug(...) do { \
+    fprintf(stderr,  ": %s: ", __func__); \
+    fprintf(stderr, ## __VA_ARGS__); \
+    fflush(stderr); \
+    } while (0);
+#else
+    #define qemu_debug(...)
+#endif
+
+#define XILINX_LOCK_KEY 0x767b
+#define XILINX_UNLOCK_KEY 0xdf0d
+
+typedef enum {
+  ARM_PLL_CTRL,
+  DDR_PLL_CTRL,
+  IO_PLL_CTRL,
+  PLL_STATUS,
+  ARM_PPL_CFG,
+  DDR_PLL_CFG,
+  IO_PLL_CFG,
+  PLL_BG_CTRL,
+  PLL_MAX
+} pll_values;
+
+typedef enum {
+  ARM_CLK_CTRL,
+  DDR_CLK_CTRL,
+  DCI_CLK_CTRL,
+  APER_CLK_CTRL,
+  USB0_CLK_CTRL,
+  USB1_CLK_CTRL,
+  GEM0_RCLK_CTRL,
+  GEM1_RCLK_CTRL,
+  GEM0_CLK_CTRL,
+  GEM1_CLK_CTRL,
+  SMC_CLK_CTRL,
+  LQSPI_CLK_CTRL,
+  SDIO_CLK_CTRL,
+  UART_CLK_CTRL,
+  SPI_CLK_CTRL,
+  CAN_CLK_CTRL,
+  CAN_MIOCLK_CTRL,
+  DBG_CLK_CTRL,
+  PCAP_CLK_CTRL,
+  TOPSW_CLK_CTRL,
+  CLK_MAX
+} clk_values;
+
+typedef enum {
+  CLK_CTRL,
+  THR_CTRL,
+  THR_CNT,
+  THR_STA,
+  FPGA_MAX
+} fpga_values;
+
+typedef enum {
+  SYNC_CTRL,
+  SYNC_STATUS,
+  BANDGAP_TRIP,
+  CC_TEST,
+  PLL_PREDIVISOR,
+  CLK_621_TRUE,
+  PICTURE_DBG,
+  PICTURE_DBG_UCNT,
+  PICTURE_DBG_LCNT,
+  MISC_MAX
+} misc_values;
+
+typedef enum {
+  PSS,
+  DDDR,
+  DMAC,
+  USB,
+  GEM,
+  SDIO,
+  SPI,
+  CAN,
+  I2C,
+  UART,
+  GPIO,
+  LQSPI,
+  SMC,
+  OCM,
+  DEVCI,
+  FPGA,
+  A9_CPU,
+  RS_AWDT,
+  RST_REASON,
+  RST_REASON_CLR,
+  REBOOT_STATUS,
+  BOOT_MODE,
+  RESET_MAX
+} reset_values;
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+
+    uint16_t scl;
+    uint16_t lockval;
+    uint32_t pll[PLL_MAX]; /* 0x100 - 0x11C */
+    uint32_t clk[CLK_MAX]; /* 0x120 - 0x16C */
+    uint32_t fpga[4][FPGA_MAX]; /* 0x170 - 0x1AC */
+    uint32_t misc[MISC_MAX]; /* 0x1B0 - 0x1D8 */
+    uint32_t reset[RESET_MAX]; /* 0x200 - 0x25C */
+    uint32_t apu_ctrl; /* 0x300 */
+    uint32_t wdt_clk_sel; /* 0x304 */
+    uint32_t tz_ocm[3]; /* 0x400 - 0x408 */
+    uint32_t tz_ddr; /* 0x430 */
+    uint32_t tz_dma[3]; /* 0x440 - 0x448 */
+    uint32_t tz_misc[3]; /* 0x450 - 0x458 */
+    uint32_t tz_fpga[2]; /* 0x484 - 0x488 */
+    uint32_t dbg_ctrl; /* 0x500 */
+    uint32_t pss_idcode; /* 0x530 */
+    uint32_t ddr[8]; /* 0x600 - 0x620 - 0x604-missing */
+    uint32_t mio[54]; /* 0x700 - 0x7D4 */
+    uint32_t mio_func[4]; /* 0x800 - 0x810 */
+    uint32_t sd[2]; /* 0x830 - 0x834 */
+    uint32_t lvl_shftr_en; /* 0x900 */
+    uint32_t ocm_cfg; /* 0x910 */
+    uint32_t cpu_ram[8]; /* 0xA00 - 0xA1C */
+    uint32_t iou[7]; /* 0xA30 - 0xA48 */
+    uint32_t dmac_ram; /* 0xA50 */
+    uint32_t afi[4][3]; /* 0xA60 - 0xA8C */
+    uint32_t ocm[3]; /* 0xA90 - 0xA98 */
+    uint32_t devci_ram; /* 0xAA0 */
+    uint32_t csg_ram; /* 0xAB0 */
+    uint32_t gpiob[12]; /* 0xB00 - 0xB2C */
+    uint32_t ddriob[14]; /* 0xB40 - 0xB74 */
+} ZynqArmSysCtlState;
+
+static const VMStateDescription vmstate_zynq_arm_sysctl = {
+    .name = "zynq_sysctl",
+    .version_id = 2,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT16(lockval, ZynqArmSysCtlState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void zynq_arm_sysctl_reset(DeviceState *d)
+{
+    int i;
+    ZynqArmSysCtlState *s =
+            FROM_SYSBUS(ZynqArmSysCtlState, sysbus_from_qdev(d));
+
+    qemu_debug("RESET\n");
+
+    s->lockval = 1;
+    /* 0x100 - 0x11C */
+    s->pll[ARM_PLL_CTRL] = 0x0001A008;
+    s->pll[DDR_PLL_CTRL] = 0x0001A008;
+    s->pll[IO_PLL_CTRL] = 0x0001A008;
+    s->pll[PLL_STATUS] = 0x0000003F;
+    s->pll[ARM_PPL_CFG] = 0x00014000;
+    s->pll[DDR_PLL_CFG] = 0x00014000;
+    s->pll[IO_PLL_CFG] = 0x00014000;
+
+    /* 0x120 - 0x16C */
+    s->clk[ARM_CLK_CTRL] = 0x1F000400;
+    s->clk[DDR_CLK_CTRL] = 0x18400003;
+    s->clk[DCI_CLK_CTRL] = 0x01E03201;
+    s->clk[APER_CLK_CTRL] = 0x01FFCCCD;
+    s->clk[USB0_CLK_CTRL] = s->clk[USB1_CLK_CTRL] = 0x00101941;
+    s->clk[GEM0_RCLK_CTRL] = s->clk[GEM1_RCLK_CTRL] = 0x00000001;
+    s->clk[GEM0_CLK_CTRL] = s->clk[GEM1_CLK_CTRL] = 0x00003C01;
+    s->clk[SMC_CLK_CTRL] = 0x00003C01;
+    s->clk[LQSPI_CLK_CTRL] = 0x00002821;
+    s->clk[SDIO_CLK_CTRL] = 0x00001E03;
+    s->clk[UART_CLK_CTRL] = 0x00003F03;
+    s->clk[SPI_CLK_CTRL] = 0x00003F03;
+    s->clk[CAN_CLK_CTRL] = 0x00501903;
+    s->clk[DBG_CLK_CTRL] = 0x00000F03;
+    s->clk[PCAP_CLK_CTRL] = 0x00000F01;
+
+    /* 0x170 - 0x1AC */
+    s->fpga[0][CLK_CTRL] = s->fpga[1][CLK_CTRL] = s->fpga[2][CLK_CTRL] =
+            s->fpga[3][CLK_CTRL] = 0x00101800;
+    s->fpga[0][THR_STA] = s->fpga[1][THR_STA] = s->fpga[2][THR_STA] =
+            s->fpga[3][THR_STA] = 0x00010000;
+
+    /* 0x1B0 - 0x1D8 */
+    s->misc[BANDGAP_TRIP] = 0x0000001F;
+    s->misc[PLL_PREDIVISOR] = 0x00000001;
+    s->misc[CLK_621_TRUE] = 0x00000001;
+
+    /* 0x200 - 0x25C */
+    s->reset[FPGA] = 0x01F33F0F;
+    s->reset[RST_REASON] = 0x00000040;
+
+    /* 0x700 - 0x7D4 */
+    for (i = 0; i < 54; i++) {
+        s->mio[i] = 0x00001601;
+    }
+    for (i = 2; i <= 8; i++) {
+        s->mio[i] = 0x00000601;
+    }
+
+    /* MIO_MST_TRI0, MIO_MST_TRI1 */
+    s->mio_func[2] = s->mio_func[3] = 0xFFFFFFFF;
+
+    s->cpu_ram[0] = s->cpu_ram[1] = s->cpu_ram[3] =
+            s->cpu_ram[4] = s->cpu_ram[7] = 0x00010101;
+    s->cpu_ram[2] = s->cpu_ram[5] = 0x01010101;
+    s->cpu_ram[6] = 0x00000001;
+
+    s->iou[0] = s->iou[1] = s->iou[2] = s->iou[3] = 0x09090909;
+    s->iou[4] = s->iou[5] = 0x00090909;
+    s->iou[6] = 0x00000909;
+
+    s->dmac_ram = 0x00000009;
+
+    s->afi[0][0] = s->afi[0][1] = 0x09090909;
+    s->afi[1][0] = s->afi[1][1] = 0x09090909;
+    s->afi[2][0] = s->afi[2][1] = 0x09090909;
+    s->afi[3][0] = s->afi[3][1] = 0x09090909;
+    s->afi[0][2] = s->afi[1][2] = s->afi[2][2] = s->afi[3][2] = 0x00000909;
+
+    s->ocm[0] = 0x01010101;
+    s->ocm[1] = s->ocm[2] = 0x09090909;
+
+    s->devci_ram = 0x00000909;
+    s->csg_ram = 0x00000001;
+
+    s->ddriob[0] = s->ddriob[1] = s->ddriob[2] = s->ddriob[3] = 0x00000e00;
+    s->ddriob[4] = s->ddriob[5] = s->ddriob[6] = 0x00000e00;
+    s->ddriob[12] = 0x00000021;
+}
+
+static inline uint32_t zynq_arm_sysctl_read_imp(void *opaque,
+    target_phys_addr_t offset)
+{
+    ZynqArmSysCtlState *s = (ZynqArmSysCtlState *)opaque;
+
+    switch (offset) {
+    case 0x0: /* SCL */
+        return s->scl;
+    case 0x4: /* LOCK */
+    case 0x8: /* UNLOCK */
+        qemu_debug("Reading SCLR_LOCK/UNLOCK is not enabled\n"); /* CHECK */
+        return 0;
+    case 0x0C: /* LOCKSTA */
+        return s->lockval;
+    case 0x100 ... 0x11C:
+        return s->pll[(offset - 0x100) / 4];
+    case 0x120 - 0x16C:
+        return s->clk[(offset - 0x120) / 4];
+    case 0x170 ... 0x1AC:
+        /* two arrays solution - offset is from the beggining */
+        return s->fpga[0][(offset - 0x170) / 4];
+    case 0x1B0 ... 0x1D8:
+        return s->misc[(offset - 0x1B0) / 4];
+    case 0x200 ... 0x258:
+        return s->reset[(offset - 0x200) / 4];
+    case 0x25c:
+        return 1;
+    case 0x300:
+        return s->apu_ctrl;
+    case 0x304:
+        return s->wdt_clk_sel;
+    case 0x400 ... 0x408:
+        return s->tz_ocm[(offset - 0x400) / 4];
+    case 0x430:
+        return s->tz_ddr;
+    case 0x440 ... 0x448:
+        return s->tz_dma[(offset - 0x440) / 4];
+    case 0x450 ... 0x458:
+        return s->tz_misc[(offset - 0x450) / 4];
+    case 0x484 ... 0x488:
+        return s->tz_fpga[(offset - 0x484) / 4];
+    case 0x500:
+        return s->dbg_ctrl;
+    case 0x530:
+        return s->pss_idcode;
+    case 0x600 ... 0x620:
+        if (offset == 0x604) {
+            goto bad_reg;
+        }
+        return s->ddr[(offset - 0x600) / 4];
+    case 0x700 ... 0x7D4:
+        return s->mio[(offset - 0x700) / 4];
+    case 0x800 ... 0x810:
+        return s->mio_func[(offset - 0x800) / 4];
+    case 0x830 ... 0x834:
+        return s->sd[(offset - 0x830) / 4];
+    case 0x900:
+        return s->lvl_shftr_en;
+    case 0x910:
+        return s->ocm_cfg;
+    case 0xA00 ... 0xA1C:
+        return s->cpu_ram[(offset - 0xA00) / 4];
+    case 0xA30 ... 0xA48:
+        return s->iou[(offset - 0xA30) / 4];
+    case 0xA50:
+        return s->dmac_ram;
+    case 0xA60 ... 0xA8C:
+        return s->afi[0][(offset - 0x700) / 4];
+    case 0xA90 ... 0xA98:
+        return s->ocm[(offset - 0xA90) / 4];
+    case 0xAA0:
+        return s->devci_ram;
+    case 0xAB0:
+        return s->csg_ram;
+    case 0xB00 ... 0xB2C:
+        return s->gpiob[(offset - 0xB00) / 4];
+    case 0xB40 ... 0xB74:
+        return s->ddriob[(offset - 0xB40) / 4];
+    default:
+    bad_reg:
+        qemu_debug("Bad register offset 0x%x\n", (int)offset);
+        return 0;
+    }
+}
+
+static uint64_t zynq_arm_sysctl_read(void *opaque, target_phys_addr_t offset,
+    unsigned size)
+{
+    uint32_t ret = zynq_arm_sysctl_read_imp(opaque, offset);
+
+    qemu_debug("addr: %08x data: %08x\n", offset, ret);
+    return ret;
+}
+
+static void zynq_arm_sysctl_write(void *opaque, target_phys_addr_t offset,
+                          uint64_t val, unsigned size)
+{
+    ZynqArmSysCtlState *s = (ZynqArmSysCtlState *)opaque;
+
+    qemu_debug("offset: %08x data: %08x\n", offset, (unsigned)val);
+
+    switch (offset) {
+    case 0x00: /* SCL */
+        s->scl = val & 0x1;
+    return;
+    case 0x4: /* SLCR_LOCK */
+        if ((val & 0xFFFF) == XILINX_LOCK_KEY) {
+            qemu_debug("XILINX LOCK 0xF8000000 + 0x%x <= 0x%x\n", (int)offset,
+                (unsigned)val & 0xFFFF);
+            s->lockval = 1;
+        } else {
+            qemu_debug("WRONG XILINX LOCK KEY 0xF8000000 + 0x%x <= 0x%x\n",
+                (int)offset, (unsigned)val & 0xFFFF);
+        }
+        return;
+    case 0x8: /* SLCR_UNLOCK */
+        if ((val & 0xFFFF) == XILINX_UNLOCK_KEY) {
+            qemu_debug("XILINX UNLOCK 0xF8000000 + 0x%x <= 0x%x\n", (int)offset,
+                (unsigned)val & 0xFFFF);
+            s->lockval = 0;
+        } else {
+            qemu_debug("WRONG XILINX UNLOCK KEY 0xF8000000 + 0x%x <= 0x%x\n",
+                (int)offset, (unsigned)val & 0xFFFF);
+        }
+        return;
+    case 0xc: /* LOCKSTA */
+        qemu_debug("Writing SCLR_LOCKSTA is not enabled\n");
+        return;
+    }
+
+    if (!s->lockval) {
+        switch (offset) {
+        case 0x100 ... 0x11C:
+            if (offset == 0x10C) {
+                goto bad_reg;
+            }
+            s->pll[(offset - 0x100) / 4] = val;
+            break;
+        case 0x120 - 0x16C:
+            s->clk[(offset - 0x120) / 4] = val;
+            break;
+        case 0x170 ... 0x1AC:
+            /* two arrays solution - offset is from the beggining */
+            s->fpga[0][(offset - 0x170) / 4] = val;
+            break;
+        case 0x1B0 ... 0x1D8:
+            s->misc[(offset - 0x1B0) / 4] = val;
+            break;
+        case 0x200 ... 0x25C:
+            if (offset == 0x250) {
+                goto bad_reg;
+            }
+            s->reset[(offset - 0x200) / 4] = val;
+            break;
+        case 0x300:
+            s->apu_ctrl = val;
+            break;
+        case 0x304:
+            s->wdt_clk_sel = val;
+            break;
+        case 0x400 ... 0x408:
+            s->tz_ocm[(offset - 0x400) / 4] = val;
+            break;
+        case 0x430:
+            s->tz_ddr = val;
+            break;
+        case 0x440 ... 0x448:
+            s->tz_dma[(offset - 0x440) / 4] = val;
+            break;
+        case 0x450 ... 0x458:
+            s->tz_misc[(offset - 0x450) / 4] = val;
+            break;
+        case 0x484 ... 0x488:
+            s->tz_fpga[(offset - 0x484) / 4] = val;
+            break;
+        case 0x500:
+            s->dbg_ctrl = val;
+            break;
+        case 0x530:
+            s->pss_idcode = val;
+            break;
+        case 0x600 ... 0x620:
+            if (offset == 0x604) {
+                goto bad_reg;
+            }
+            s->ddr[(offset - 0x600) / 4] = val;
+            break;
+        case 0x700 ... 0x7D4:
+            s->mio[(offset - 0x700) / 4] = val;
+            break;
+        case 0x800 ... 0x810:
+            s->mio_func[(offset - 0x800) / 4] = val;
+            break;
+        case 0x830 ... 0x834:
+            s->sd[(offset - 0x830) / 4] = val;
+            break;
+        case 0x900:
+            s->lvl_shftr_en = val;
+            break;
+        case 0x910:
+            break;
+        case 0xA00 ... 0xA1C:
+            s->cpu_ram[(offset - 0xA00) / 4] = val;
+            break;
+        case 0xA30 ... 0xA48:
+            s->iou[(offset - 0xA30) / 4] = val;
+            break;
+        case 0xA50:
+            s->dmac_ram = val;
+            break;
+        case 0xA60 ... 0xA8C:
+            s->afi[0][(offset - 0x700) / 4] = val;
+            break;
+        case 0xA90:
+            s->ocm[0] = val;
+            break;
+        case 0xAA0:
+            s->devci_ram = val;
+            break;
+        case 0xAB0:
+            s->csg_ram = val;
+            break;
+        case 0xB00 ... 0xB2C:
+            if (offset == 0xB20 || offset == 0xB2C) {
+                goto bad_reg;
+            }
+            s->gpiob[(offset - 0xB00) / 4] = val;
+            break;
+        case 0xB40 ... 0xB74:
+            s->ddriob[(offset - 0xB40) / 4] = val;
+            break;
+        default:
+        bad_reg:
+            qemu_debug("Bad register write %x <= %08x\n", (int)offset, val);
+        }
+    } else {
+        qemu_debug("SCLR registers are locked. Unlock them at first\n");
+    }
+}
+
+static const MemoryRegionOps sysctl_ops = {
+    .read = zynq_arm_sysctl_read,
+    .write = zynq_arm_sysctl_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int zynq_arm_sysctl_init(SysBusDevice *dev)
+{
+    ZynqArmSysCtlState *s = FROM_SYSBUS(ZynqArmSysCtlState, dev);
+
+    memory_region_init_io(&s->iomem, &sysctl_ops, s, "slcr", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+
+    return 0;
+}
+
+static void zynq_arm_sysctl_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+
+    sdc->init = zynq_arm_sysctl_init;
+    dc->vmsd = &vmstate_zynq_arm_sysctl;
+    dc->reset = zynq_arm_sysctl_reset;
+}
+
+static TypeInfo zynq_arm_sysctl_info = {
+    .class_init = zynq_arm_sysctl_class_init,
+    .name  = "xilinx,zynq_sysctl",
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size  = sizeof(ZynqArmSysCtlState),
+};
+
+static void zynq_arm_sysctl_register(void)
+{
+    type_register_static(&zynq_arm_sysctl_info);
+}
+
+device_init(zynq_arm_sysctl_register)
-- 
1.7.3.2

  parent reply	other threads:[~2012-02-07  6:15 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-02-07  6:19 [Qemu-devel] [RFC PATCH v2 0/4]Zynq-7000 EPP platform model Peter A. G. Crosthwaite
2012-02-07  6:19 ` [Qemu-devel] [RFC PATCH v2 1/4] cadence_uart: initial version of device model Peter A. G. Crosthwaite
2012-02-07  6:19 ` [Qemu-devel] [RFC PATCH v2 2/4] cadence_ttc: " Peter A. G. Crosthwaite
2012-02-07 11:28   ` Paul Brook
2012-02-08  7:27     ` Peter Crosthwaite
2012-02-08 10:15       ` Paul Brook
2012-02-08 10:35         ` Peter Crosthwaite
2012-02-08 12:35           ` Paul Brook
2012-02-08 12:47             ` Peter Crosthwaite
2012-02-07  6:19 ` [Qemu-devel] [RFC PATCH v2 3/4] cadence_gem: " Peter A. G. Crosthwaite
2012-02-07  6:19 ` Peter A. G. Crosthwaite [this message]
2012-02-07 11:25 ` [Qemu-devel] [RFC PATCH v2 0/4]Zynq-7000 EPP platform model Paul Brook
2012-02-08  8:24   ` Peter Crosthwaite

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=9c00559489fb68d9a0cd1f0383b0cc98a565cbae.1328594621.git.peter.crosthwaite@petalogix.com \
    --to=peter.crosthwaite@petalogix.com \
    --cc=afaerber@suse.de \
    --cc=duyl@xilinx.com \
    --cc=edgar.iglesias@petalogix.com \
    --cc=john.williams@petalogix.com \
    --cc=linnj@xilinx.com \
    --cc=monstr@monstr.eu \
    --cc=paul@codesourcery.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.