qemu/hw/misc/zynq_slcr.c
<<
>>
Prefs
   1/*
   2 * Status and system control registers for Xilinx Zynq Platform
   3 *
   4 * Copyright (c) 2011 Michal Simek <monstr@monstr.eu>
   5 * Copyright (c) 2012 PetaLogix Pty Ltd.
   6 * Based on hw/arm_sysctl.c, written by Paul Brook
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License
  10 * as published by the Free Software Foundation; either version
  11 * 2 of the License, or (at your option) any later version.
  12 *
  13 * You should have received a copy of the GNU General Public License along
  14 * with this program; if not, see <http://www.gnu.org/licenses/>.
  15 */
  16
  17#include "qemu/osdep.h"
  18#include "hw/hw.h"
  19#include "qemu/timer.h"
  20#include "hw/sysbus.h"
  21#include "hw/fdt_generic_devices.h"
  22#include "sysemu/sysemu.h"
  23#include "qom/cpu.h"
  24#include "qemu/error-report.h"
  25#include "qapi/error.h"
  26#include "qemu/log.h"
  27
  28#ifdef CONFIG_FDT
  29#include "qemu/config-file.h"
  30#include "sysemu/device_tree.h"
  31#endif
  32
  33#ifndef ZYNQ_SLCR_ERR_DEBUG
  34#define ZYNQ_SLCR_ERR_DEBUG 0
  35#endif
  36
  37#define DB_PRINT(...) do { \
  38        if (ZYNQ_SLCR_ERR_DEBUG) { \
  39            fprintf(stderr,  ": %s: ", __func__); \
  40            fprintf(stderr, ## __VA_ARGS__); \
  41        } \
  42    } while (0);
  43
  44#define XILINX_LOCK_KEY 0x767b
  45#define XILINX_UNLOCK_KEY 0xdf0d
  46
  47#define R_PSS_RST_CTRL_SOFT_RST 0x1
  48
  49enum {
  50    SCL             = 0x000 / 4,
  51    LOCK,
  52    UNLOCK,
  53    LOCKSTA,
  54
  55    ARM_PLL_CTRL    = 0x100 / 4,
  56    DDR_PLL_CTRL,
  57    IO_PLL_CTRL,
  58    PLL_STATUS,
  59    ARM_PLL_CFG,
  60    DDR_PLL_CFG,
  61    IO_PLL_CFG,
  62
  63    ARM_CLK_CTRL    = 0x120 / 4,
  64    DDR_CLK_CTRL,
  65    DCI_CLK_CTRL,
  66    APER_CLK_CTRL,
  67    USB0_CLK_CTRL,
  68    USB1_CLK_CTRL,
  69    GEM0_RCLK_CTRL,
  70    GEM1_RCLK_CTRL,
  71    GEM0_CLK_CTRL,
  72    GEM1_CLK_CTRL,
  73    SMC_CLK_CTRL,
  74    LQSPI_CLK_CTRL,
  75    SDIO_CLK_CTRL,
  76    UART_CLK_CTRL,
  77    SPI_CLK_CTRL,
  78    CAN_CLK_CTRL,
  79    CAN_MIOCLK_CTRL,
  80    DBG_CLK_CTRL,
  81    PCAP_CLK_CTRL,
  82    TOPSW_CLK_CTRL,
  83
  84#define FPGA_CTRL_REGS(n, start) \
  85    FPGA ## n ## _CLK_CTRL = (start) / 4, \
  86    FPGA ## n ## _THR_CTRL, \
  87    FPGA ## n ## _THR_CNT, \
  88    FPGA ## n ## _THR_STA,
  89    FPGA_CTRL_REGS(0, 0x170)
  90    FPGA_CTRL_REGS(1, 0x180)
  91    FPGA_CTRL_REGS(2, 0x190)
  92    FPGA_CTRL_REGS(3, 0x1a0)
  93
  94    BANDGAP_TRIP    = 0x1b8 / 4,
  95    PLL_PREDIVISOR  = 0x1c0 / 4,
  96    CLK_621_TRUE,
  97
  98    PSS_RST_CTRL    = 0x200 / 4,
  99    DDR_RST_CTRL,
 100    TOPSW_RESET_CTRL,
 101    DMAC_RST_CTRL,
 102    USB_RST_CTRL,
 103    GEM_RST_CTRL,
 104    SDIO_RST_CTRL,
 105    SPI_RST_CTRL,
 106    CAN_RST_CTRL,
 107    I2C_RST_CTRL,
 108    UART_RST_CTRL,
 109    GPIO_RST_CTRL,
 110    LQSPI_RST_CTRL,
 111    SMC_RST_CTRL,
 112    OCM_RST_CTRL,
 113    FPGA_RST_CTRL   = 0x240 / 4,
 114    A9_CPU_RST_CTRL,
 115
 116    RS_AWDT_CTRL    = 0x24c / 4,
 117    RST_REASON,
 118
 119    REBOOT_STATUS   = 0x258 / 4,
 120    BOOT_MODE,
 121
 122    APU_CTRL        = 0x300 / 4,
 123    WDT_CLK_SEL,
 124
 125    TZ_DMA_NS       = 0x440 / 4,
 126    TZ_DMA_IRQ_NS,
 127    TZ_DMA_PERIPH_NS,
 128
 129    PSS_IDCODE      = 0x530 / 4,
 130
 131    DDR_URGENT      = 0x600 / 4,
 132    DDR_CAL_START   = 0x60c / 4,
 133    DDR_REF_START   = 0x614 / 4,
 134    DDR_CMD_STA,
 135    DDR_URGENT_SEL,
 136    DDR_DFI_STATUS,
 137
 138    MIO             = 0x700 / 4,
 139#define MIO_LENGTH 54
 140
 141    MIO_LOOPBACK    = 0x804 / 4,
 142    MIO_MST_TRI0,
 143    MIO_MST_TRI1,
 144
 145    SD0_WP_CD_SEL   = 0x830 / 4,
 146    SD1_WP_CD_SEL,
 147
 148    LVL_SHFTR_EN    = 0x900 / 4,
 149    OCM_CFG         = 0x910 / 4,
 150
 151    CPU_RAM         = 0xa00 / 4,
 152
 153    IOU             = 0xa30 / 4,
 154
 155    DMAC_RAM        = 0xa50 / 4,
 156
 157    AFI0            = 0xa60 / 4,
 158    AFI1 = AFI0 + 3,
 159    AFI2 = AFI1 + 3,
 160    AFI3 = AFI2 + 3,
 161#define AFI_LENGTH 3
 162
 163    OCM             = 0xa90 / 4,
 164
 165    DEVCI_RAM       = 0xaa0 / 4,
 166
 167    CSG_RAM         = 0xab0 / 4,
 168
 169    GPIOB_CTRL      = 0xb00 / 4,
 170    GPIOB_CFG_CMOS18,
 171    GPIOB_CFG_CMOS25,
 172    GPIOB_CFG_CMOS33,
 173    GPIOB_CFG_HSTL  = 0xb14 / 4,
 174    GPIOB_DRVR_BIAS_CTRL,
 175
 176    DDRIOB          = 0xb40 / 4,
 177#define DDRIOB_LENGTH 14
 178};
 179
 180#define ZYNQ_SLCR_MMIO_SIZE     0x1000
 181#define ZYNQ_SLCR_NUM_REGS      (ZYNQ_SLCR_MMIO_SIZE / 4)
 182
 183#define ZYNQ_SLCR_NUM_CPUS 2
 184
 185#define FPGA_RST_VALID_BITS 0x01f33F0F
 186/* The action of the FPGA_RST_CTRL register on the reset pins
 187 * should be inverted as the resets are active low.
 188 */
 189#define FPGA_RST_INVERT_BITS 0x0000000F
 190#define A9_CPU_RST_CTRL_RST_SHIFT 0
 191
 192#define TYPE_ZYNQ_SLCR "xilinx,zynq_slcr"
 193#define ZYNQ_SLCR(obj) OBJECT_CHECK(ZynqSLCRState, (obj), TYPE_ZYNQ_SLCR)
 194
 195typedef struct ZynqSLCRState {
 196    SysBusDevice parent_obj;
 197
 198    MemoryRegion iomem;
 199    qemu_irq cpu_resets[ZYNQ_SLCR_NUM_CPUS];
 200
 201    /* PS to PL reset signals.  */
 202    qemu_irq fpga_resets[17];
 203
 204    uint32_t regs[ZYNQ_SLCR_NUM_REGS];
 205} ZynqSLCRState;
 206
 207/* Set up PS7 QSPI MIO registers based on the dtb */
 208static void zynq_slcr_set_qspi(ZynqSLCRState *s, void *fdt)
 209{
 210    int i;
 211    Error *errp = NULL;
 212    char node_path[DT_PATH_LENGTH];
 213
 214    memset(node_path, 0, sizeof(node_path));
 215    /* find the Zynq QSPI node path with compatible string, return if node
 216     * not found */
 217    if (qemu_devtree_node_by_compatible(fdt, node_path,
 218                                        "xlnx,zynq-qspi-1.0")) {
 219        DB_PRINT("DT, PS7 QSPI node not found\n");
 220        return ;
 221    }
 222
 223    /* Check if there is a child node and assume the child node is a QSPI
 224     * flash node. Then set up the MIO registers for the first QSPI flash.
 225     * Use the is-dual property to determine whether MIO registers
 226     * configuration is required to setup for the second QSPI flash*/
 227    if (qemu_devtree_get_num_children(fdt, node_path, 1)) {
 228        DB_PRINT("DT, PS7 QSPI: child node found\n");
 229        /* Set MIO 1 - 6 (qspi0)  with QSPI + LVCOMS18 (0x202) */
 230        for (i = 1; i <= 6; i++) {
 231            s->regs[MIO+i] = 0x00000202;
 232        }
 233
 234        /* Check for dual mode */
 235        if (qemu_fdt_getprop_cell(fdt, node_path, "is-dual", 0,
 236                                  false, &errp) ==  1) {
 237            DB_PRINT("DT, PS QSPI is in dual\n");
 238            /* Set MIO 0 (qspi1_cs) with QSPI + LVCOMS18 (0x202) */
 239            s->regs[MIO+0] = 0x00000202;
 240
 241            /* Set MIO 9 - 13 (qspi1) with QSPI + LVCOMS18 (0x202) */
 242            for (i = 9; i <= 13; i++) {
 243                s->regs[MIO+i] = 0x00000202;
 244            }
 245        }
 246    }
 247}
 248
 249static void zynq_slcr_fdt_config(ZynqSLCRState *s)
 250{
 251#ifdef CONFIG_FDT
 252    QemuOpts *machine_opts;
 253    const char *dtb_filename;
 254    int fdt_size;
 255    void *fdt = NULL;
 256
 257    /* identify dtb file name from qemu opts */
 258    machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
 259    if (machine_opts) {
 260        dtb_filename = qemu_opt_get(machine_opts, "dtb");
 261    } else {
 262        dtb_filename = NULL;
 263    }
 264
 265    if (dtb_filename) {
 266        fdt = load_device_tree(dtb_filename, &fdt_size);
 267    }
 268
 269    if (!fdt) {
 270        return;
 271    }
 272
 273    zynq_slcr_set_qspi(s, fdt);
 274#endif
 275
 276    return;
 277}
 278
 279static void zynq_slcr_update_fpga_resets(ZynqSLCRState *s)
 280{
 281    uint32_t val = s->regs[FPGA_RST_CTRL];
 282    /* Invert the active low resets */
 283    val ^= FPGA_RST_INVERT_BITS;
 284    int out_idx = 0;
 285    int i;
 286
 287    /* FPGA OUT Resets.  */
 288    for (i = 0; i < 32; i++) {
 289        bool rst = extract32(val, i, 1);
 290        bool valid = extract32(FPGA_RST_VALID_BITS, i, 1);
 291
 292        /* Ignore reserved bits.  */
 293        if (!valid) {
 294            continue;
 295        }
 296
 297        assert(out_idx < ARRAY_SIZE(s->fpga_resets));
 298        qemu_set_irq(s->fpga_resets[out_idx], rst);
 299        out_idx++;
 300    }
 301}
 302
 303static void zynq_slcr_reset(DeviceState *d)
 304{
 305    ZynqSLCRState *s = ZYNQ_SLCR(d);
 306    int i, boot_mode;
 307    QemuOpts *opts = qemu_find_opts_singleton("boot-opts");
 308
 309    DB_PRINT("RESET\n");
 310
 311    boot_mode = qemu_opt_get_number(opts, "mode", 0);
 312
 313    s->regs[LOCKSTA] = 1;
 314    /* 0x100 - 0x11C */
 315    s->regs[ARM_PLL_CTRL]   = 0x0001A008;
 316    s->regs[DDR_PLL_CTRL]   = 0x0001A008;
 317    s->regs[IO_PLL_CTRL]    = 0x0001A008;
 318    s->regs[PLL_STATUS]     = 0x0000003F;
 319    s->regs[ARM_PLL_CFG]    = 0x00014000;
 320    s->regs[DDR_PLL_CFG]    = 0x00014000;
 321    s->regs[IO_PLL_CFG]     = 0x00014000;
 322
 323    /* 0x120 - 0x16C */
 324    s->regs[ARM_CLK_CTRL]   = 0x1F000200;
 325    s->regs[DDR_CLK_CTRL]   = 0x18400003;
 326    s->regs[DCI_CLK_CTRL]   = 0x01E03201;
 327    s->regs[APER_CLK_CTRL]  = 0x01ed044d;
 328    s->regs[USB0_CLK_CTRL]  = s->regs[USB1_CLK_CTRL]    = 0x00101941;
 329    s->regs[GEM0_RCLK_CTRL] = s->regs[GEM1_RCLK_CTRL]   = 0x00000001;
 330    s->regs[GEM0_CLK_CTRL]  = s->regs[GEM1_CLK_CTRL]    = 0x00003C01;
 331    s->regs[SMC_CLK_CTRL]   = 0x00003C01;
 332    s->regs[LQSPI_CLK_CTRL] = 0x00002821;
 333    s->regs[SDIO_CLK_CTRL]  = 0x00001E03;
 334    s->regs[UART_CLK_CTRL]  = 0x00003F03;
 335    s->regs[SPI_CLK_CTRL]   = 0x00003F03;
 336    s->regs[CAN_CLK_CTRL]   = 0x00501903;
 337    s->regs[DBG_CLK_CTRL]   = 0x00000F03;
 338    s->regs[PCAP_CLK_CTRL]  = 0x00000F01;
 339
 340    /* 0x170 - 0x1AC */
 341    s->regs[FPGA0_CLK_CTRL] = s->regs[FPGA1_CLK_CTRL] = s->regs[FPGA2_CLK_CTRL]
 342                            = s->regs[FPGA3_CLK_CTRL] = 0x00101800;
 343    s->regs[FPGA0_THR_STA] = s->regs[FPGA1_THR_STA] = s->regs[FPGA2_THR_STA]
 344                           = s->regs[FPGA3_THR_STA] = 0x00010000;
 345
 346    /* 0x1B0 - 0x1D8 */
 347    s->regs[BANDGAP_TRIP]   = 0x0000001F;
 348    s->regs[PLL_PREDIVISOR] = 0x00000001;
 349    s->regs[CLK_621_TRUE]   = 0x00000001;
 350
 351    /* 0x200 - 0x25C */
 352    s->regs[FPGA_RST_CTRL]  = 0x01F33F0F;
 353    s->regs[RST_REASON]     = 0x00000040;
 354
 355    s->regs[BOOT_MODE]      = boot_mode;
 356
 357    /* 0x700 - 0x7D4 */
 358    for (i = 0; i < 54; i++) {
 359        s->regs[MIO + i] = 0x00001601;
 360    }
 361    for (i = 2; i <= 8; i++) {
 362        s->regs[MIO + i] = 0x00000601;
 363    }
 364
 365    s->regs[MIO_MST_TRI0] = s->regs[MIO_MST_TRI1] = 0xFFFFFFFF;
 366
 367    s->regs[CPU_RAM + 0] = s->regs[CPU_RAM + 1] = s->regs[CPU_RAM + 3]
 368                         = s->regs[CPU_RAM + 4] = s->regs[CPU_RAM + 7]
 369                         = 0x00010101;
 370    s->regs[CPU_RAM + 2] = s->regs[CPU_RAM + 5] = 0x01010101;
 371    s->regs[CPU_RAM + 6] = 0x00000001;
 372
 373    s->regs[IOU + 0] = s->regs[IOU + 1] = s->regs[IOU + 2] = s->regs[IOU + 3]
 374                     = 0x09090909;
 375    s->regs[IOU + 4] = s->regs[IOU + 5] = 0x00090909;
 376    s->regs[IOU + 6] = 0x00000909;
 377
 378    s->regs[DMAC_RAM] = 0x00000009;
 379
 380    s->regs[AFI0 + 0] = s->regs[AFI0 + 1] = 0x09090909;
 381    s->regs[AFI1 + 0] = s->regs[AFI1 + 1] = 0x09090909;
 382    s->regs[AFI2 + 0] = s->regs[AFI2 + 1] = 0x09090909;
 383    s->regs[AFI3 + 0] = s->regs[AFI3 + 1] = 0x09090909;
 384    s->regs[AFI0 + 2] = s->regs[AFI1 + 2] = s->regs[AFI2 + 2]
 385                      = s->regs[AFI3 + 2] = 0x00000909;
 386
 387    s->regs[OCM + 0]    = 0x01010101;
 388    s->regs[OCM + 1]    = s->regs[OCM + 2] = 0x09090909;
 389
 390    s->regs[DEVCI_RAM]  = 0x00000909;
 391    s->regs[CSG_RAM]    = 0x00000001;
 392
 393    s->regs[DDRIOB + 0] = s->regs[DDRIOB + 1] = s->regs[DDRIOB + 2]
 394                        = s->regs[DDRIOB + 3] = 0x00000e00;
 395    s->regs[DDRIOB + 4] = s->regs[DDRIOB + 5] = s->regs[DDRIOB + 6]
 396                        = 0x00000e00;
 397    s->regs[DDRIOB + 12] = 0x00000021;
 398
 399    zynq_slcr_fdt_config(s);
 400    zynq_slcr_update_fpga_resets(s);
 401}
 402
 403
 404static bool zynq_slcr_check_offset(hwaddr offset, bool rnw)
 405{
 406    switch (offset) {
 407    case LOCK:
 408    case UNLOCK:
 409    case DDR_CAL_START:
 410    case DDR_REF_START:
 411        return !rnw; /* Write only */
 412    case LOCKSTA:
 413    case FPGA0_THR_STA:
 414    case FPGA1_THR_STA:
 415    case FPGA2_THR_STA:
 416    case FPGA3_THR_STA:
 417    case BOOT_MODE:
 418    case PSS_IDCODE:
 419    case DDR_CMD_STA:
 420    case DDR_DFI_STATUS:
 421    case PLL_STATUS:
 422        return rnw;/* read only */
 423    case SCL:
 424    case ARM_PLL_CTRL ... IO_PLL_CTRL:
 425    case ARM_PLL_CFG ... IO_PLL_CFG:
 426    case ARM_CLK_CTRL ... TOPSW_CLK_CTRL:
 427    case FPGA0_CLK_CTRL ... FPGA0_THR_CNT:
 428    case FPGA1_CLK_CTRL ... FPGA1_THR_CNT:
 429    case FPGA2_CLK_CTRL ... FPGA2_THR_CNT:
 430    case FPGA3_CLK_CTRL ... FPGA3_THR_CNT:
 431    case BANDGAP_TRIP:
 432    case PLL_PREDIVISOR:
 433    case CLK_621_TRUE:
 434    case PSS_RST_CTRL ... A9_CPU_RST_CTRL:
 435    case RS_AWDT_CTRL:
 436    case RST_REASON:
 437    case REBOOT_STATUS:
 438    case APU_CTRL:
 439    case WDT_CLK_SEL:
 440    case TZ_DMA_NS ... TZ_DMA_PERIPH_NS:
 441    case DDR_URGENT:
 442    case DDR_URGENT_SEL:
 443    case MIO ... MIO + MIO_LENGTH - 1:
 444    case MIO_LOOPBACK ... MIO_MST_TRI1:
 445    case SD0_WP_CD_SEL:
 446    case SD1_WP_CD_SEL:
 447    case LVL_SHFTR_EN:
 448    case OCM_CFG:
 449    case CPU_RAM:
 450    case IOU:
 451    case DMAC_RAM:
 452    case AFI0 ... AFI3 + AFI_LENGTH - 1:
 453    case OCM:
 454    case DEVCI_RAM:
 455    case CSG_RAM:
 456    case GPIOB_CTRL ... GPIOB_CFG_CMOS33:
 457    case GPIOB_CFG_HSTL:
 458    case GPIOB_DRVR_BIAS_CTRL:
 459    case DDRIOB ... DDRIOB + DDRIOB_LENGTH - 1:
 460        return true;
 461    default:
 462        return false;
 463    }
 464}
 465
 466static uint64_t zynq_slcr_read(void *opaque, hwaddr offset,
 467    unsigned size)
 468{
 469    ZynqSLCRState *s = opaque;
 470    offset /= 4;
 471    uint32_t ret = s->regs[offset];
 472
 473    if (!zynq_slcr_check_offset(offset, true)) {
 474        qemu_log_mask(LOG_GUEST_ERROR, "zynq_slcr: Invalid read access to "
 475                      " addr %" HWADDR_PRIx "\n", offset * 4);
 476    }
 477
 478    DB_PRINT("addr: %08" HWADDR_PRIx " data: %08" PRIx32 "\n", offset * 4, ret);
 479    return ret;
 480}
 481
 482static void zynq_slcr_write(void *opaque, hwaddr offset,
 483                          uint64_t val, unsigned size)
 484{
 485    ZynqSLCRState *s = (ZynqSLCRState *)opaque;
 486    offset /= 4;
 487    int i;
 488
 489    DB_PRINT("addr: %08" HWADDR_PRIx " data: %08" PRIx64 "\n", offset * 4, val);
 490
 491    if (!zynq_slcr_check_offset(offset, false)) {
 492        qemu_log_mask(LOG_GUEST_ERROR, "zynq_slcr: Invalid write access to "
 493                      "addr %" HWADDR_PRIx "\n", offset * 4);
 494        return;
 495    }
 496
 497    switch (offset) {
 498    case SCL:
 499        s->regs[SCL] = val & 0x1;
 500        return;
 501    case LOCK:
 502        if ((val & 0xFFFF) == XILINX_LOCK_KEY) {
 503            DB_PRINT("XILINX LOCK 0xF8000000 + 0x%x <= 0x%x\n", (int)offset,
 504                (unsigned)val & 0xFFFF);
 505            s->regs[LOCKSTA] = 1;
 506        } else {
 507            DB_PRINT("WRONG XILINX LOCK KEY 0xF8000000 + 0x%x <= 0x%x\n",
 508                (int)offset, (unsigned)val & 0xFFFF);
 509        }
 510        return;
 511    case UNLOCK:
 512        if ((val & 0xFFFF) == XILINX_UNLOCK_KEY) {
 513            DB_PRINT("XILINX UNLOCK 0xF8000000 + 0x%x <= 0x%x\n", (int)offset,
 514                (unsigned)val & 0xFFFF);
 515            s->regs[LOCKSTA] = 0;
 516        } else {
 517            DB_PRINT("WRONG XILINX UNLOCK KEY 0xF8000000 + 0x%x <= 0x%x\n",
 518                (int)offset, (unsigned)val & 0xFFFF);
 519        }
 520        return;
 521    }
 522
 523    if (s->regs[LOCKSTA]) {
 524        qemu_log_mask(LOG_GUEST_ERROR,
 525                      "SCLR registers are locked. Unlock them first\n");
 526        return;
 527    }
 528    s->regs[offset] = val;
 529
 530    switch (offset) {
 531    case PSS_RST_CTRL:
 532        if (val & R_PSS_RST_CTRL_SOFT_RST) {
 533            qemu_system_reset_request();
 534        }
 535        break;
 536    case A9_CPU_RST_CTRL:
 537        for (i = 0; i < ZYNQ_SLCR_NUM_CPUS; ++i) {
 538            bool rst = extract32(val, A9_CPU_RST_CTRL_RST_SHIFT + i, 1);
 539
 540            qemu_set_irq(s->cpu_resets[i], rst);
 541            DB_PRINT("%sresetting cpu %d\n", rst ? "" : "un-", i);
 542        }
 543        break;
 544    case FPGA_RST_CTRL:
 545        /* Mask off invalid bits.  */
 546        s->regs[offset] &= FPGA_RST_VALID_BITS;
 547        zynq_slcr_update_fpga_resets(s);
 548        break;
 549    }
 550}
 551
 552static const MemoryRegionOps slcr_ops = {
 553    .read = zynq_slcr_read,
 554    .write = zynq_slcr_write,
 555    .endianness = DEVICE_NATIVE_ENDIAN,
 556};
 557
 558static void zynq_slcr_realize(DeviceState *dev, Error **errp)
 559{
 560    int i;
 561    CPUState *env = first_cpu;
 562
 563    /* FIXME: Make this not suck */
 564    for (i  = 0; i < fdt_generic_num_cpus && i < ZYNQ_SLCR_NUM_CPUS; ++i) {
 565        Object *cpu_obj = OBJECT(env);
 566        if (!cpu_obj->parent) {
 567            char *cpu_child_name = g_strdup_printf("cpu-%d\n", i);
 568            object_property_add_child(qdev_get_machine(), cpu_child_name,
 569                                      cpu_obj, &error_abort);
 570        }
 571        qdev_connect_gpio_out(dev, i,
 572                              qdev_get_gpio_in_named(DEVICE(env), "reset", 0));
 573        env = CPU_NEXT(env);
 574    }
 575}
 576
 577static void zynq_slcr_init(Object *obj)
 578{
 579    ZynqSLCRState *s = ZYNQ_SLCR(obj);
 580
 581    memory_region_init_io(&s->iomem, obj, &slcr_ops, s, "slcr",
 582                          ZYNQ_SLCR_MMIO_SIZE);
 583    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
 584
 585    qdev_init_gpio_out(DEVICE(obj), s->cpu_resets, ZYNQ_SLCR_NUM_CPUS);
 586    qdev_init_gpio_out(DEVICE(obj), s->fpga_resets, ARRAY_SIZE(s->fpga_resets));
 587}
 588
 589static const VMStateDescription vmstate_zynq_slcr = {
 590    .name = "zynq_slcr",
 591    .version_id = 2,
 592    .minimum_version_id = 2,
 593    .fields = (VMStateField[]) {
 594        VMSTATE_UINT32_ARRAY(regs, ZynqSLCRState, ZYNQ_SLCR_NUM_REGS),
 595        VMSTATE_END_OF_LIST()
 596    }
 597};
 598
 599static void zynq_slcr_class_init(ObjectClass *klass, void *data)
 600{
 601    DeviceClass *dc = DEVICE_CLASS(klass);
 602
 603    dc->vmsd = &vmstate_zynq_slcr;
 604    dc->reset = zynq_slcr_reset;
 605    dc->realize = zynq_slcr_realize;
 606}
 607
 608static const TypeInfo zynq_slcr_info = {
 609    .class_init = zynq_slcr_class_init,
 610    .name  = TYPE_ZYNQ_SLCR,
 611    .parent = TYPE_SYS_BUS_DEVICE,
 612    .instance_size  = sizeof(ZynqSLCRState),
 613    .instance_init = zynq_slcr_init,
 614};
 615
 616static void zynq_slcr_register_types(void)
 617{
 618    type_register_static(&zynq_slcr_info);
 619}
 620
 621type_init(zynq_slcr_register_types)
 622