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 "hw/hw.h"
  18#include "qemu/timer.h"
  19#include "hw/sysbus.h"
  20#include "sysemu/sysemu.h"
  21
  22#ifndef ZYNQ_SLCR_ERR_DEBUG
  23#define ZYNQ_SLCR_ERR_DEBUG 0
  24#endif
  25
  26#define DB_PRINT(...) do { \
  27        if (ZYNQ_SLCR_ERR_DEBUG) { \
  28            fprintf(stderr,  ": %s: ", __func__); \
  29            fprintf(stderr, ## __VA_ARGS__); \
  30        } \
  31    } while (0);
  32
  33#define XILINX_LOCK_KEY 0x767b
  34#define XILINX_UNLOCK_KEY 0xdf0d
  35
  36#define R_PSS_RST_CTRL_SOFT_RST 0x1
  37
  38enum {
  39    SCL             = 0x000 / 4,
  40    LOCK,
  41    UNLOCK,
  42    LOCKSTA,
  43
  44    ARM_PLL_CTRL    = 0x100 / 4,
  45    DDR_PLL_CTRL,
  46    IO_PLL_CTRL,
  47    PLL_STATUS,
  48    ARM_PLL_CFG,
  49    DDR_PLL_CFG,
  50    IO_PLL_CFG,
  51
  52    ARM_CLK_CTRL    = 0x120 / 4,
  53    DDR_CLK_CTRL,
  54    DCI_CLK_CTRL,
  55    APER_CLK_CTRL,
  56    USB0_CLK_CTRL,
  57    USB1_CLK_CTRL,
  58    GEM0_RCLK_CTRL,
  59    GEM1_RCLK_CTRL,
  60    GEM0_CLK_CTRL,
  61    GEM1_CLK_CTRL,
  62    SMC_CLK_CTRL,
  63    LQSPI_CLK_CTRL,
  64    SDIO_CLK_CTRL,
  65    UART_CLK_CTRL,
  66    SPI_CLK_CTRL,
  67    CAN_CLK_CTRL,
  68    CAN_MIOCLK_CTRL,
  69    DBG_CLK_CTRL,
  70    PCAP_CLK_CTRL,
  71    TOPSW_CLK_CTRL,
  72
  73#define FPGA_CTRL_REGS(n, start) \
  74    FPGA ## n ## _CLK_CTRL = (start) / 4, \
  75    FPGA ## n ## _THR_CTRL, \
  76    FPGA ## n ## _THR_CNT, \
  77    FPGA ## n ## _THR_STA,
  78    FPGA_CTRL_REGS(0, 0x170)
  79    FPGA_CTRL_REGS(1, 0x180)
  80    FPGA_CTRL_REGS(2, 0x190)
  81    FPGA_CTRL_REGS(3, 0x1a0)
  82
  83    BANDGAP_TRIP    = 0x1b8 / 4,
  84    PLL_PREDIVISOR  = 0x1c0 / 4,
  85    CLK_621_TRUE,
  86
  87    PSS_RST_CTRL    = 0x200 / 4,
  88    DDR_RST_CTRL,
  89    TOPSW_RESET_CTRL,
  90    DMAC_RST_CTRL,
  91    USB_RST_CTRL,
  92    GEM_RST_CTRL,
  93    SDIO_RST_CTRL,
  94    SPI_RST_CTRL,
  95    CAN_RST_CTRL,
  96    I2C_RST_CTRL,
  97    UART_RST_CTRL,
  98    GPIO_RST_CTRL,
  99    LQSPI_RST_CTRL,
 100    SMC_RST_CTRL,
 101    OCM_RST_CTRL,
 102    FPGA_RST_CTRL   = 0x240 / 4,
 103    A9_CPU_RST_CTRL,
 104
 105    RS_AWDT_CTRL    = 0x24c / 4,
 106    RST_REASON,
 107
 108    REBOOT_STATUS   = 0x258 / 4,
 109    BOOT_MODE,
 110
 111    APU_CTRL        = 0x300 / 4,
 112    WDT_CLK_SEL,
 113
 114    TZ_DMA_NS       = 0x440 / 4,
 115    TZ_DMA_IRQ_NS,
 116    TZ_DMA_PERIPH_NS,
 117
 118    PSS_IDCODE      = 0x530 / 4,
 119
 120    DDR_URGENT      = 0x600 / 4,
 121    DDR_CAL_START   = 0x60c / 4,
 122    DDR_REF_START   = 0x614 / 4,
 123    DDR_CMD_STA,
 124    DDR_URGENT_SEL,
 125    DDR_DFI_STATUS,
 126
 127    MIO             = 0x700 / 4,
 128#define MIO_LENGTH 54
 129
 130    MIO_LOOPBACK    = 0x804 / 4,
 131    MIO_MST_TRI0,
 132    MIO_MST_TRI1,
 133
 134    SD0_WP_CD_SEL   = 0x830 / 4,
 135    SD1_WP_CD_SEL,
 136
 137    LVL_SHFTR_EN    = 0x900 / 4,
 138    OCM_CFG         = 0x910 / 4,
 139
 140    CPU_RAM         = 0xa00 / 4,
 141
 142    IOU             = 0xa30 / 4,
 143
 144    DMAC_RAM        = 0xa50 / 4,
 145
 146    AFI0            = 0xa60 / 4,
 147    AFI1 = AFI0 + 3,
 148    AFI2 = AFI1 + 3,
 149    AFI3 = AFI2 + 3,
 150#define AFI_LENGTH 3
 151
 152    OCM             = 0xa90 / 4,
 153
 154    DEVCI_RAM       = 0xaa0 / 4,
 155
 156    CSG_RAM         = 0xab0 / 4,
 157
 158    GPIOB_CTRL      = 0xb00 / 4,
 159    GPIOB_CFG_CMOS18,
 160    GPIOB_CFG_CMOS25,
 161    GPIOB_CFG_CMOS33,
 162    GPIOB_CFG_HSTL  = 0xb14 / 4,
 163    GPIOB_DRVR_BIAS_CTRL,
 164
 165    DDRIOB          = 0xb40 / 4,
 166#define DDRIOB_LENGTH 14
 167};
 168
 169#define ZYNQ_SLCR_MMIO_SIZE     0x1000
 170#define ZYNQ_SLCR_NUM_REGS      (ZYNQ_SLCR_MMIO_SIZE / 4)
 171
 172#define TYPE_ZYNQ_SLCR "xilinx,zynq_slcr"
 173#define ZYNQ_SLCR(obj) OBJECT_CHECK(ZynqSLCRState, (obj), TYPE_ZYNQ_SLCR)
 174
 175typedef struct ZynqSLCRState {
 176    SysBusDevice parent_obj;
 177
 178    MemoryRegion iomem;
 179
 180    uint32_t regs[ZYNQ_SLCR_NUM_REGS];
 181} ZynqSLCRState;
 182
 183static void zynq_slcr_reset(DeviceState *d)
 184{
 185    ZynqSLCRState *s = ZYNQ_SLCR(d);
 186    int i;
 187
 188    DB_PRINT("RESET\n");
 189
 190    s->regs[LOCKSTA] = 1;
 191    /* 0x100 - 0x11C */
 192    s->regs[ARM_PLL_CTRL]   = 0x0001A008;
 193    s->regs[DDR_PLL_CTRL]   = 0x0001A008;
 194    s->regs[IO_PLL_CTRL]    = 0x0001A008;
 195    s->regs[PLL_STATUS]     = 0x0000003F;
 196    s->regs[ARM_PLL_CFG]    = 0x00014000;
 197    s->regs[DDR_PLL_CFG]    = 0x00014000;
 198    s->regs[IO_PLL_CFG]     = 0x00014000;
 199
 200    /* 0x120 - 0x16C */
 201    s->regs[ARM_CLK_CTRL]   = 0x1F000400;
 202    s->regs[DDR_CLK_CTRL]   = 0x18400003;
 203    s->regs[DCI_CLK_CTRL]   = 0x01E03201;
 204    s->regs[APER_CLK_CTRL]  = 0x01FFCCCD;
 205    s->regs[USB0_CLK_CTRL]  = s->regs[USB1_CLK_CTRL]    = 0x00101941;
 206    s->regs[GEM0_RCLK_CTRL] = s->regs[GEM1_RCLK_CTRL]   = 0x00000001;
 207    s->regs[GEM0_CLK_CTRL]  = s->regs[GEM1_CLK_CTRL]    = 0x00003C01;
 208    s->regs[SMC_CLK_CTRL]   = 0x00003C01;
 209    s->regs[LQSPI_CLK_CTRL] = 0x00002821;
 210    s->regs[SDIO_CLK_CTRL]  = 0x00001E03;
 211    s->regs[UART_CLK_CTRL]  = 0x00003F03;
 212    s->regs[SPI_CLK_CTRL]   = 0x00003F03;
 213    s->regs[CAN_CLK_CTRL]   = 0x00501903;
 214    s->regs[DBG_CLK_CTRL]   = 0x00000F03;
 215    s->regs[PCAP_CLK_CTRL]  = 0x00000F01;
 216
 217    /* 0x170 - 0x1AC */
 218    s->regs[FPGA0_CLK_CTRL] = s->regs[FPGA1_CLK_CTRL] = s->regs[FPGA2_CLK_CTRL]
 219                            = s->regs[FPGA3_CLK_CTRL] = 0x00101800;
 220    s->regs[FPGA0_THR_STA] = s->regs[FPGA1_THR_STA] = s->regs[FPGA2_THR_STA]
 221                           = s->regs[FPGA3_THR_STA] = 0x00010000;
 222
 223    /* 0x1B0 - 0x1D8 */
 224    s->regs[BANDGAP_TRIP]   = 0x0000001F;
 225    s->regs[PLL_PREDIVISOR] = 0x00000001;
 226    s->regs[CLK_621_TRUE]   = 0x00000001;
 227
 228    /* 0x200 - 0x25C */
 229    s->regs[FPGA_RST_CTRL]  = 0x01F33F0F;
 230    s->regs[RST_REASON]     = 0x00000040;
 231
 232    s->regs[BOOT_MODE]      = 0x00000001;
 233
 234    /* 0x700 - 0x7D4 */
 235    for (i = 0; i < 54; i++) {
 236        s->regs[MIO + i] = 0x00001601;
 237    }
 238    for (i = 2; i <= 8; i++) {
 239        s->regs[MIO + i] = 0x00000601;
 240    }
 241
 242    s->regs[MIO_MST_TRI0] = s->regs[MIO_MST_TRI1] = 0xFFFFFFFF;
 243
 244    s->regs[CPU_RAM + 0] = s->regs[CPU_RAM + 1] = s->regs[CPU_RAM + 3]
 245                         = s->regs[CPU_RAM + 4] = s->regs[CPU_RAM + 7]
 246                         = 0x00010101;
 247    s->regs[CPU_RAM + 2] = s->regs[CPU_RAM + 5] = 0x01010101;
 248    s->regs[CPU_RAM + 6] = 0x00000001;
 249
 250    s->regs[IOU + 0] = s->regs[IOU + 1] = s->regs[IOU + 2] = s->regs[IOU + 3]
 251                     = 0x09090909;
 252    s->regs[IOU + 4] = s->regs[IOU + 5] = 0x00090909;
 253    s->regs[IOU + 6] = 0x00000909;
 254
 255    s->regs[DMAC_RAM] = 0x00000009;
 256
 257    s->regs[AFI0 + 0] = s->regs[AFI0 + 1] = 0x09090909;
 258    s->regs[AFI1 + 0] = s->regs[AFI1 + 1] = 0x09090909;
 259    s->regs[AFI2 + 0] = s->regs[AFI2 + 1] = 0x09090909;
 260    s->regs[AFI3 + 0] = s->regs[AFI3 + 1] = 0x09090909;
 261    s->regs[AFI0 + 2] = s->regs[AFI1 + 2] = s->regs[AFI2 + 2]
 262                      = s->regs[AFI3 + 2] = 0x00000909;
 263
 264    s->regs[OCM + 0]    = 0x01010101;
 265    s->regs[OCM + 1]    = s->regs[OCM + 2] = 0x09090909;
 266
 267    s->regs[DEVCI_RAM]  = 0x00000909;
 268    s->regs[CSG_RAM]    = 0x00000001;
 269
 270    s->regs[DDRIOB + 0] = s->regs[DDRIOB + 1] = s->regs[DDRIOB + 2]
 271                        = s->regs[DDRIOB + 3] = 0x00000e00;
 272    s->regs[DDRIOB + 4] = s->regs[DDRIOB + 5] = s->regs[DDRIOB + 6]
 273                        = 0x00000e00;
 274    s->regs[DDRIOB + 12] = 0x00000021;
 275}
 276
 277
 278static bool zynq_slcr_check_offset(hwaddr offset, bool rnw)
 279{
 280    switch (offset) {
 281    case LOCK:
 282    case UNLOCK:
 283    case DDR_CAL_START:
 284    case DDR_REF_START:
 285        return !rnw; /* Write only */
 286    case LOCKSTA:
 287    case FPGA0_THR_STA:
 288    case FPGA1_THR_STA:
 289    case FPGA2_THR_STA:
 290    case FPGA3_THR_STA:
 291    case BOOT_MODE:
 292    case PSS_IDCODE:
 293    case DDR_CMD_STA:
 294    case DDR_DFI_STATUS:
 295    case PLL_STATUS:
 296        return rnw;/* read only */
 297    case SCL:
 298    case ARM_PLL_CTRL ... IO_PLL_CTRL:
 299    case ARM_PLL_CFG ... IO_PLL_CFG:
 300    case ARM_CLK_CTRL ... TOPSW_CLK_CTRL:
 301    case FPGA0_CLK_CTRL ... FPGA0_THR_CNT:
 302    case FPGA1_CLK_CTRL ... FPGA1_THR_CNT:
 303    case FPGA2_CLK_CTRL ... FPGA2_THR_CNT:
 304    case FPGA3_CLK_CTRL ... FPGA3_THR_CNT:
 305    case BANDGAP_TRIP:
 306    case PLL_PREDIVISOR:
 307    case CLK_621_TRUE:
 308    case PSS_RST_CTRL ... A9_CPU_RST_CTRL:
 309    case RS_AWDT_CTRL:
 310    case RST_REASON:
 311    case REBOOT_STATUS:
 312    case APU_CTRL:
 313    case WDT_CLK_SEL:
 314    case TZ_DMA_NS ... TZ_DMA_PERIPH_NS:
 315    case DDR_URGENT:
 316    case DDR_URGENT_SEL:
 317    case MIO ... MIO + MIO_LENGTH - 1:
 318    case MIO_LOOPBACK ... MIO_MST_TRI1:
 319    case SD0_WP_CD_SEL:
 320    case SD1_WP_CD_SEL:
 321    case LVL_SHFTR_EN:
 322    case OCM_CFG:
 323    case CPU_RAM:
 324    case IOU:
 325    case DMAC_RAM:
 326    case AFI0 ... AFI3 + AFI_LENGTH - 1:
 327    case OCM:
 328    case DEVCI_RAM:
 329    case CSG_RAM:
 330    case GPIOB_CTRL ... GPIOB_CFG_CMOS33:
 331    case GPIOB_CFG_HSTL:
 332    case GPIOB_DRVR_BIAS_CTRL:
 333    case DDRIOB ... DDRIOB + DDRIOB_LENGTH - 1:
 334        return true;
 335    default:
 336        return false;
 337    }
 338}
 339
 340static uint64_t zynq_slcr_read(void *opaque, hwaddr offset,
 341    unsigned size)
 342{
 343    ZynqSLCRState *s = opaque;
 344    offset /= 4;
 345    uint32_t ret = s->regs[offset];
 346
 347    if (!zynq_slcr_check_offset(offset, true)) {
 348        qemu_log_mask(LOG_GUEST_ERROR, "zynq_slcr: Invalid read access to "
 349                      " addr %" HWADDR_PRIx "\n", offset * 4);
 350    }
 351
 352    DB_PRINT("addr: %08" HWADDR_PRIx " data: %08" PRIx32 "\n", offset * 4, ret);
 353    return ret;
 354}
 355
 356static void zynq_slcr_write(void *opaque, hwaddr offset,
 357                          uint64_t val, unsigned size)
 358{
 359    ZynqSLCRState *s = (ZynqSLCRState *)opaque;
 360    offset /= 4;
 361
 362    DB_PRINT("addr: %08" HWADDR_PRIx " data: %08" PRIx64 "\n", offset * 4, val);
 363
 364    if (!zynq_slcr_check_offset(offset, false)) {
 365        qemu_log_mask(LOG_GUEST_ERROR, "zynq_slcr: Invalid write access to "
 366                      "addr %" HWADDR_PRIx "\n", offset * 4);
 367        return;
 368    }
 369
 370    switch (offset) {
 371    case SCL:
 372        s->regs[SCL] = val & 0x1;
 373        return;
 374    case LOCK:
 375        if ((val & 0xFFFF) == XILINX_LOCK_KEY) {
 376            DB_PRINT("XILINX LOCK 0xF8000000 + 0x%x <= 0x%x\n", (int)offset,
 377                (unsigned)val & 0xFFFF);
 378            s->regs[LOCKSTA] = 1;
 379        } else {
 380            DB_PRINT("WRONG XILINX LOCK KEY 0xF8000000 + 0x%x <= 0x%x\n",
 381                (int)offset, (unsigned)val & 0xFFFF);
 382        }
 383        return;
 384    case UNLOCK:
 385        if ((val & 0xFFFF) == XILINX_UNLOCK_KEY) {
 386            DB_PRINT("XILINX UNLOCK 0xF8000000 + 0x%x <= 0x%x\n", (int)offset,
 387                (unsigned)val & 0xFFFF);
 388            s->regs[LOCKSTA] = 0;
 389        } else {
 390            DB_PRINT("WRONG XILINX UNLOCK KEY 0xF8000000 + 0x%x <= 0x%x\n",
 391                (int)offset, (unsigned)val & 0xFFFF);
 392        }
 393        return;
 394    }
 395
 396    if (!s->regs[LOCKSTA]) {
 397        s->regs[offset / 4] = val;
 398    } else {
 399        DB_PRINT("SCLR registers are locked. Unlock them first\n");
 400        return;
 401    }
 402
 403    switch (offset) {
 404    case PSS_RST_CTRL:
 405        if (val & R_PSS_RST_CTRL_SOFT_RST) {
 406            qemu_system_reset_request();
 407        }
 408        break;
 409    }
 410}
 411
 412static const MemoryRegionOps slcr_ops = {
 413    .read = zynq_slcr_read,
 414    .write = zynq_slcr_write,
 415    .endianness = DEVICE_NATIVE_ENDIAN,
 416};
 417
 418static void zynq_slcr_init(Object *obj)
 419{
 420    ZynqSLCRState *s = ZYNQ_SLCR(obj);
 421
 422    memory_region_init_io(&s->iomem, obj, &slcr_ops, s, "slcr",
 423                          ZYNQ_SLCR_MMIO_SIZE);
 424    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
 425}
 426
 427static const VMStateDescription vmstate_zynq_slcr = {
 428    .name = "zynq_slcr",
 429    .version_id = 2,
 430    .minimum_version_id = 2,
 431    .fields = (VMStateField[]) {
 432        VMSTATE_UINT32_ARRAY(regs, ZynqSLCRState, ZYNQ_SLCR_NUM_REGS),
 433        VMSTATE_END_OF_LIST()
 434    }
 435};
 436
 437static void zynq_slcr_class_init(ObjectClass *klass, void *data)
 438{
 439    DeviceClass *dc = DEVICE_CLASS(klass);
 440
 441    dc->vmsd = &vmstate_zynq_slcr;
 442    dc->reset = zynq_slcr_reset;
 443}
 444
 445static const TypeInfo zynq_slcr_info = {
 446    .class_init = zynq_slcr_class_init,
 447    .name  = TYPE_ZYNQ_SLCR,
 448    .parent = TYPE_SYS_BUS_DEVICE,
 449    .instance_size  = sizeof(ZynqSLCRState),
 450    .instance_init = zynq_slcr_init,
 451};
 452
 453static void zynq_slcr_register_types(void)
 454{
 455    type_register_static(&zynq_slcr_info);
 456}
 457
 458type_init(zynq_slcr_register_types)
 459