qemu/hw/misc/xilinx-lpd-slcr.c
<<
>>
Prefs
   1/*
   2 * QEMU model of the LPD_SLCR Global system level control registers for the low power domain
   3 *
   4 * Copyright (c) 2014 Xilinx Inc.
   5 *
   6 * Autogenerated by xregqemu.py 2014-12-16.
   7 *
   8 * Permission is hereby granted, free of charge, to any person obtaining a copy
   9 * of this software and associated documentation files (the "Software"), to deal
  10 * in the Software without restriction, including without limitation the rights
  11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12 * copies of the Software, and to permit persons to whom the Software is
  13 * furnished to do so, subject to the following conditions:
  14 *
  15 * The above copyright notice and this permission notice shall be included in
  16 * all copies or substantial portions of the Software.
  17 *
  18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24 * THE SOFTWARE.
  25 */
  26
  27#include "qemu/osdep.h"
  28#include "hw/sysbus.h"
  29#include "hw/register.h"
  30#include "qemu/bitops.h"
  31#include "qapi/qmp/qerror.h"
  32#include "qapi/error.h"
  33#include "qemu/log.h"
  34#include "hw/intc/xlnx_scu_gic.h"
  35#include "hw/fdt_generic_util.h"
  36
  37#ifndef XILINX_LPD_SLCR_ERR_DEBUG
  38#define XILINX_LPD_SLCR_ERR_DEBUG 0
  39#endif
  40
  41#define TYPE_XILINX_LPD_SLCR "xlnx.lpd-slcr"
  42
  43#define XILINX_LPD_SLCR(obj) \
  44     OBJECT_CHECK(LPD_SLCR, (obj), TYPE_XILINX_LPD_SLCR)
  45
  46REG32(WPROT0, 0x0)
  47    FIELD(WPROT0, ACTIVE, 1, 0)
  48REG32(CTRL, 0x4)
  49    FIELD(CTRL, SLVERR_ENABLE, 1, 0)
  50REG32(ISR, 0x8)
  51    FIELD(ISR, ADDR_DECODE_ERR, 1, 0)
  52REG32(IMR, 0xc)
  53    FIELD(IMR, ADDR_DECODE_ERR, 1, 0)
  54REG32(IER, 0x10)
  55    FIELD(IER, ADDR_DECODE_ERR, 1, 0)
  56REG32(IDR, 0x14)
  57    FIELD(IDR, ADDR_DECODE_ERR, 1, 0)
  58REG32(ITR, 0x18)
  59    FIELD(ITR, ADDR_DECODE_ERR, 1, 0)
  60REG32(ECO, 0x1c)
  61REG32(PERSISTENT0, 0x20)
  62REG32(PERSISTENT1, 0x24)
  63REG32(PERSISTENT2, 0x28)
  64REG32(PERSISTENT3, 0x2c)
  65REG32(PERSISTENT4, 0x30)
  66REG32(PERSISTENT5, 0x34)
  67REG32(PERSISTENT6, 0x38)
  68REG32(PERSISTENT7, 0x3c)
  69REG32(SAFETY_CHK0, 0x40)
  70REG32(SAFETY_CHK1, 0x44)
  71REG32(SAFETY_CHK2, 0x48)
  72REG32(SAFETY_CHK3, 0x4c)
  73REG32(CSUPMU_WDT_CLK_SEL, 0x00000050)
  74REG32(ADMA_CFG, 0x0000200C)
  75REG32(ADMA_RAM, 0x00002010)
  76REG32(ERR_AIBAXI_ISR, 0x00003000)
  77REG32(ERR_AIBAXI_IMR, 0x00003008)
  78REG32(ERR_AIBAXI_IER, 0x00003010)
  79REG32(ERR_AIBAXI_IDR, 0x00003018)
  80REG32(ERR_AIBAPB_ISR, 0x00003020)
  81REG32(ERR_AIBAPB_IMR, 0x00003024)
  82REG32(ERR_AIBAPB_IER, 0x00003028)
  83REG32(ERR_AIBAPB_IDR, 0x0000302C)
  84REG32(ISO_AIBAXI_REQ, 0x00003030)
  85REG32(ISO_AIBAXI_TYPE, 0x00003038)
  86REG32(ISO_AIBAXI_ACK, 0x00003040)
  87REG32(ISO_AIBAPB_REQ, 0x00003048)
  88REG32(ISO_AIBAPB_TYPE, 0x0000304C)
  89REG32(ISO_AIBAPB_ACK, 0x00003050)
  90REG32(ERR_ATB_ISR, 0x00006000)
  91REG32(ERR_ATB_IMR, 0x00006004)
  92REG32(ERR_ATB_IER, 0x00006008)
  93REG32(ERR_ATB_IDR, 0x0000600C)
  94REG32(ATB_CMD_STORE_EN, 0x00006010)
  95REG32(ATB_RESP_EN, 0x00006014)
  96REG32(ATB_RESP_TYPE, 0x00006018)
  97REG32(ATB_PRESCALE, 0x00006020)
  98REG32(MUTEX0, 0x00007000)
  99REG32(MUTEX1, 0x00007004)
 100REG32(MUTEX2, 0x00007008)
 101REG32(MUTEX3, 0x0000700C)
 102REG32(GICP0_IRQ_STATUS, 0x00008000)
 103REG32(GICP0_IRQ_MASK, 0x00008004)
 104REG32(GICP0_IRQ_ENABLE, 0x00008008)
 105REG32(GICP0_IRQ_DISABLE, 0x0000800C)
 106REG32(GICP0_IRQ_TRIGGER, 0x00008010)
 107REG32(GICP1_IRQ_STATUS, 0x00008014)
 108REG32(GICP1_IRQ_MASK, 0x00008018)
 109REG32(GICP1_IRQ_ENABLE, 0x0000801C)
 110REG32(GICP1_IRQ_DISABLE, 0x00008020)
 111REG32(GICP1_IRQ_TRIGGER, 0x00008024)
 112REG32(GICP2_IRQ_STATUS, 0x00008028)
 113REG32(GICP2_IRQ_MASK, 0x0000802C)
 114REG32(GICP2_IRQ_ENABLE, 0x00008030)
 115REG32(GICP2_IRQ_DISABLE, 0x00008034)
 116REG32(GICP2_IRQ_TRIGGER, 0x00008038)
 117REG32(GICP3_IRQ_STATUS, 0x0000803C)
 118REG32(GICP3_IRQ_MASK, 0x00008040)
 119REG32(GICP3_IRQ_ENABLE, 0x00008044)
 120REG32(GICP3_IRQ_DISABLE, 0x00008048)
 121REG32(GICP3_IRQ_TRIGGER, 0x0000804C)
 122REG32(GICP4_IRQ_STATUS, 0x00008050)
 123REG32(GICP4_IRQ_MASK, 0x00008054)
 124REG32(GICP4_IRQ_ENABLE, 0x00008058)
 125REG32(GICP4_IRQ_DISABLE, 0x0000805C)
 126REG32(GICP4_IRQ_TRIGGER, 0x00008060)
 127REG32(GICP_PMU_IRQ_STATUS, 0x000080A0)
 128REG32(GICP_PMU_IRQ_MASK, 0x000080A4)
 129REG32(GICP_PMU_IRQ_ENABLE, 0x000080A8)
 130REG32(GICP_PMU_IRQ_DISABLE, 0x000080AC)
 131REG32(GICP_PMU_IRQ_TRIGGER, 0x000080B0)
 132REG32(AFI_FS, 0x00009000)
 133REG32(LPD_CCI, 0x0000A000)
 134REG32(LPD_CCI_ADDRMAP, 0x0000A004)
 135REG32(LPD_CCI_QVNPREALLOC, 0x0000A008)
 136REG32(LPD_SMMU, 0x0000A020)
 137REG32(LPD_APU, 0x0000A040)
 138
 139#define R_MAX (R_LPD_APU + 1)
 140
 141#define OFFSET_TO_BANK(offset) (((offset >> 2) - R_GICP0_IRQ_STATUS)           \
 142                                / (R_GICP1_IRQ_STATUS - R_GICP0_IRQ_STATUS))
 143#define GIC_IRQ_STATUS(n) (R_GICP0_IRQ_STATUS + (0x14 >> 2) * (n))
 144
 145typedef struct LPD_SLCR {
 146    SysBusDevice parent_obj;
 147    MemoryRegion iomem;
 148    qemu_irq irq_isr;
 149
 150    /* GIC associated to the RPUs. */
 151    XlnxSCUGICState *rpu_gic;
 152    /* GIC associated to the APUs. */
 153    XlnxSCUGICState *apu_gic;
 154
 155    uint32_t regs[R_MAX];
 156    RegisterInfo regs_info[R_MAX];
 157} LPD_SLCR;
 158
 159/*
 160 * This allows to enable/disable the write.
 161 * All protected register have to set that as a pre_write callback.
 162 */
 163static uint64_t protection_prew(RegisterInfo *reg, uint64_t val64)
 164{
 165    LPD_SLCR *s = XILINX_LPD_SLCR(reg->opaque);
 166    bool w_dis = AF_EX32(s->regs, WPROT0, ACTIVE);
 167
 168    if (w_dis) {
 169        val64 = s->regs[reg->access->decode.addr >> 2];
 170    }
 171
 172    return val64;
 173}
 174
 175static void isr_update_irq(LPD_SLCR *s)
 176{
 177    bool pending = s->regs[R_ISR] & ~s->regs[R_IMR];
 178    qemu_set_irq(s->irq_isr, pending);
 179}
 180
 181static void isr_postw(RegisterInfo *reg, uint64_t val64)
 182{
 183    LPD_SLCR *s = XILINX_LPD_SLCR(reg->opaque);
 184    isr_update_irq(s);
 185}
 186
 187static uint64_t ier_prew(RegisterInfo *reg, uint64_t val64)
 188{
 189    LPD_SLCR *s = XILINX_LPD_SLCR(reg->opaque);
 190    uint32_t val = protection_prew(reg, val64);
 191
 192    s->regs[R_IMR] &= ~val;
 193    isr_update_irq(s);
 194    return 0;
 195}
 196
 197static uint64_t idr_prew(RegisterInfo *reg, uint64_t val64)
 198{
 199    LPD_SLCR *s = XILINX_LPD_SLCR(reg->opaque);
 200    uint32_t val = protection_prew(reg, val64);
 201
 202    s->regs[R_IMR] |= val;
 203    isr_update_irq(s);
 204    return 0;
 205}
 206
 207static uint64_t itr_prew(RegisterInfo *reg, uint64_t val64)
 208{
 209    LPD_SLCR *s = XILINX_LPD_SLCR(reg->opaque);
 210    uint32_t val = protection_prew(reg, val64);
 211
 212    s->regs[R_ISR] |= val;
 213    isr_update_irq(s);
 214    return 0;
 215}
 216
 217static uint64_t mutex_prew(RegisterInfo *reg, uint64_t val64)
 218{
 219    LPD_SLCR *s = XILINX_LPD_SLCR(reg->opaque);
 220    uint32_t val = protection_prew(reg, val64);
 221
 222    if (!val) {
 223        return 0;
 224    } else if (!s->regs[reg->access->decode.addr >> 2]) {
 225        return val;
 226    } else {
 227        return s->regs[reg->access->decode.addr >> 2];
 228    }
 229}
 230
 231/* RPU, APU IRQ injection callbacks. */
 232static void lpd_slcr_peripheral_irq_update(LPD_SLCR *s, uint8_t bank)
 233{
 234    xlnx_scu_gic_set_intr(s->rpu_gic, bank, s->regs[GIC_IRQ_STATUS(bank)], 1);
 235    xlnx_scu_gic_set_intr(s->apu_gic, bank, s->regs[GIC_IRQ_STATUS(bank)], 1);
 236}
 237
 238static uint64_t lpd_slcr_ier_prew(RegisterInfo *reg, uint64_t val64)
 239{
 240    LPD_SLCR *s = XILINX_LPD_SLCR(reg->opaque);
 241    uint32_t val = protection_prew(reg, val64);
 242    uint32_t mask_offset = (reg->access->decode.addr >> 2)
 243                         - (R_GICP0_IRQ_ENABLE - R_GICP0_IRQ_MASK);
 244
 245    s->regs[mask_offset] &= ~val;
 246    return 0;
 247}
 248
 249static uint64_t lpd_slcr_idr_prew(RegisterInfo *reg, uint64_t val64)
 250{
 251    LPD_SLCR *s = XILINX_LPD_SLCR(reg->opaque);
 252    uint32_t val = protection_prew(reg, val64);
 253    uint32_t mask_offset = (reg->access->decode.addr >> 2)
 254                         - (R_GICP0_IRQ_DISABLE - R_GICP0_IRQ_MASK);
 255
 256    s->regs[mask_offset] |= val;
 257    return 0;
 258}
 259
 260static void lpd_slcr_inttrig_posw(RegisterInfo *reg, uint64_t val64)
 261{
 262    LPD_SLCR *s = XILINX_LPD_SLCR(reg->opaque);
 263    uint32_t val = val64;
 264    uint32_t mask_offset = (reg->access->decode.addr >> 2)
 265                         - (R_GICP0_IRQ_TRIGGER - R_GICP0_IRQ_MASK);
 266    uint32_t status_offset = (reg->access->decode.addr >> 2)
 267                           - (R_GICP0_IRQ_TRIGGER - R_GICP0_IRQ_STATUS);
 268    uint32_t enable = ~(s->regs[mask_offset]) & val;
 269    s->regs[status_offset] |= enable;
 270
 271    lpd_slcr_peripheral_irq_update(s, OFFSET_TO_BANK(reg->access->decode.addr));
 272}
 273
 274static void lpd_slcr_intstatus_posw(RegisterInfo *reg, uint64_t val64)
 275{
 276    LPD_SLCR *s = XILINX_LPD_SLCR(reg->opaque);
 277
 278    lpd_slcr_peripheral_irq_update(s, OFFSET_TO_BANK(reg->access->decode.addr));
 279}
 280
 281static RegisterAccessInfo lpd_slcr_regs_info[] = {
 282    {   .name = "WPROT0",  .decode.addr = A_WPROT0,
 283        .reset = 0x1,
 284    },{ .name = "CTRL",  .decode.addr = A_CTRL,
 285    },{ .name = "ISR",  .decode.addr = A_ISR,
 286        .w1c = 0x1,
 287        .post_write = isr_postw,
 288        .pre_write = protection_prew,
 289    },{ .name = "IMR",  .decode.addr = A_IMR,
 290        .reset = 0x1,
 291        .ro = 0x1,
 292        .pre_write = protection_prew,
 293    },{ .name = "IER",  .decode.addr = A_IER,
 294        .pre_write = ier_prew,
 295    },{ .name = "IDR",  .decode.addr = A_IDR,
 296        .pre_write = idr_prew,
 297    },{ .name = "ITR",  .decode.addr = A_ITR,
 298        .pre_write = itr_prew,
 299    },{ .name = "ECO",  .decode.addr = A_ECO,
 300        .pre_write = protection_prew,
 301    },{ .name = "PERSISTENT0",  .decode.addr = A_PERSISTENT0,
 302        .pre_write = protection_prew,
 303    },{ .name = "PERSISTENT1",  .decode.addr = A_PERSISTENT1,
 304        .pre_write = protection_prew,
 305    },{ .name = "PERSISTENT2",  .decode.addr = A_PERSISTENT2,
 306        .pre_write = protection_prew,
 307    },{ .name = "PERSISTENT3",  .decode.addr = A_PERSISTENT3,
 308        .pre_write = protection_prew,
 309    },{ .name = "PERSISTENT4",  .decode.addr = A_PERSISTENT4,
 310        .pre_write = protection_prew,
 311    },{ .name = "PERSISTENT5",  .decode.addr = A_PERSISTENT5,
 312        .pre_write = protection_prew,
 313    },{ .name = "PERSISTENT6",  .decode.addr = A_PERSISTENT6,
 314        .pre_write = protection_prew,
 315    },{ .name = "PERSISTENT7",  .decode.addr = A_PERSISTENT7,
 316        .pre_write = protection_prew,
 317    },{ .name = "SAFETY_CHK0",  .decode.addr = A_SAFETY_CHK0,
 318        .pre_write = protection_prew,
 319    },{ .name = "SAFETY_CHK1",  .decode.addr = A_SAFETY_CHK1,
 320        .pre_write = protection_prew,
 321    },{ .name = "SAFETY_CHK2",  .decode.addr = A_SAFETY_CHK2,
 322        .pre_write = protection_prew,
 323    },{ .name = "SAFETY_CHK3",  .decode.addr = A_SAFETY_CHK3,
 324        .pre_write = protection_prew,
 325    },{ .name = "CSUPMU_WDT_CLK_SEL", .decode.addr = A_CSUPMU_WDT_CLK_SEL,
 326        .reset = 0,
 327        .ro = 0xFFFFFFFE,
 328        .pre_write = protection_prew,
 329    },{ .name = "ADMA_CFG", .decode.addr = A_ADMA_CFG,
 330        .reset = 0x00000028,
 331        .ro = 0xFFFFFFFF,
 332        .pre_write = protection_prew,
 333    },{ .name = "ADMA_RAM", .decode.addr = A_ADMA_RAM,
 334        .reset = 0x00003B3B,
 335        .ro = 0xFFFFFF00,
 336        .pre_write = protection_prew,
 337    },{ .name = "ERR_AIBAXI_ISR", .decode.addr = A_ERR_AIBAXI_ISR,
 338        .reset = 0,
 339        .w1c = 0xFFFFFFFF,
 340    },{ .name = "ERR_AIBAXI_IMR", .decode.addr = A_ERR_AIBAXI_IMR,
 341        .reset = 0x1DCF000F,
 342        .ro = 0xFFFFFFFF,
 343        .pre_write = protection_prew,
 344    },{ .name = "ERR_AIBAXI_IER", .decode.addr = A_ERR_AIBAXI_IER,
 345        .reset = 0,
 346        .pre_write = protection_prew,
 347    },{ .name = "ERR_AIBAXI_IDR", .decode.addr = A_ERR_AIBAXI_IDR,
 348        .reset = 0,
 349        .pre_write = protection_prew,
 350    },{ .name = "ERR_AIBAPB_ISR", .decode.addr = A_ERR_AIBAPB_ISR,
 351        .reset = 0,
 352        .w1c = 0xFFFFFFFF,
 353        .pre_write = protection_prew,
 354    },{ .name = "ERR_AIBAPB_IMR", .decode.addr = A_ERR_AIBAPB_IMR,
 355        .reset = 0x00000001,
 356        .ro = 0xFFFFFFFF,
 357        .pre_write = protection_prew,
 358    },{ .name = "ERR_AIBAPB_IER", .decode.addr = A_ERR_AIBAPB_IER,
 359        .reset = 0,
 360        .pre_write = protection_prew,
 361    },{ .name = "ERR_AIBAPB_IDR", .decode.addr = A_ERR_AIBAPB_IDR,
 362        .reset = 0,
 363        .pre_write = protection_prew,
 364    },{ .name = "ISO_AIBAXI_REQ", .decode.addr = A_ISO_AIBAXI_REQ,
 365        .reset = 0,
 366        .pre_write = protection_prew,
 367    },{ .name = "ISO_AIBAXI_TYPE", .decode.addr = A_ISO_AIBAXI_TYPE,
 368        .reset = 0x19CF000F,
 369        .pre_write = protection_prew,
 370    },{ .name = "ISO_AIBAXI_ACK", .decode.addr = A_ISO_AIBAXI_ACK,
 371        .reset = 0,
 372        .ro = 0xFFFFFFFF,
 373        .pre_write = protection_prew,
 374    },{ .name = "ISO_AIBAPB_REQ", .decode.addr = A_ISO_AIBAPB_REQ,
 375        .reset = 0,
 376        .pre_write = protection_prew,
 377    },{ .name = "ISO_AIBAPB_TYPE", .decode.addr = A_ISO_AIBAPB_TYPE,
 378        .reset = 0x00000001,
 379        .pre_write = protection_prew,
 380    },{ .name = "ISO_AIBAPB_ACK", .decode.addr = A_ISO_AIBAPB_ACK,
 381        .reset = 0,
 382        .ro = 0xFFFFFFFF,
 383        .pre_write = protection_prew,
 384    },{ .name = "ERR_ATB_ISR", .decode.addr = A_ERR_ATB_ISR,
 385        .reset = 0,
 386        .w1c = 0xFFFFFFFF,
 387        .pre_write = protection_prew,
 388    },{ .name = "ERR_ATB_IMR", .decode.addr = A_ERR_ATB_IMR,
 389        .reset = 0x00000003,
 390        .ro = 0xFFFFFFFF,
 391        .pre_write = protection_prew,
 392    },{ .name = "ERR_ATB_IER", .decode.addr = A_ERR_ATB_IER,
 393        .reset = 0,
 394        .pre_write = protection_prew,
 395    },{ .name = "ERR_ATB_IDR", .decode.addr = A_ERR_ATB_IDR,
 396        .reset = 0,
 397        .pre_write = protection_prew,
 398    },{ .name = "ATB_CMD_STORE_EN", .decode.addr = A_ATB_CMD_STORE_EN,
 399        .reset = 0x00000003,
 400        .pre_write = protection_prew,
 401    },{ .name = "ATB_RESP_EN", .decode.addr = A_ATB_RESP_EN,
 402        .reset = 0,
 403        .pre_write = protection_prew,
 404    },{ .name = "ATB_RESP_TYPE", .decode.addr = A_ATB_RESP_TYPE,
 405        .reset = 0x00000003,
 406        .pre_write = protection_prew,
 407    },{ .name = "ATB_PRESCALE", .decode.addr = A_ATB_PRESCALE,
 408        .reset = 0x0000FFFF,
 409        .pre_write = protection_prew,
 410    },{ .name = "MUTEX0", .decode.addr = A_MUTEX0,
 411        .reset = 0,
 412        .pre_write = mutex_prew,
 413    },{ .name = "MUTEX1", .decode.addr = A_MUTEX1,
 414        .reset = 0,
 415        .pre_write = mutex_prew,
 416    },{ .name = "MUTEX2", .decode.addr = A_MUTEX2,
 417        .reset = 0,
 418        .pre_write = mutex_prew,
 419    },{ .name = "MUTEX3", .decode.addr = A_MUTEX3,
 420        .reset = 0,
 421        .pre_write = mutex_prew,
 422    },{ .name = "GICP0_IRQ_STATUS", .decode.addr = A_GICP0_IRQ_STATUS,
 423        .reset = 0,
 424        .w1c = 0xFFFFFFFF,
 425        .pre_write = protection_prew,
 426        .post_write = lpd_slcr_intstatus_posw,
 427    },{ .name = "GICP0_IRQ_MASK", .decode.addr = A_GICP0_IRQ_MASK,
 428        .reset = 0xFFFFFFFF,
 429        .ro = 0xFFFFFFFF,
 430        .pre_write = protection_prew,
 431    },{ .name = "GICP0_IRQ_ENABLE", .decode.addr = A_GICP0_IRQ_ENABLE,
 432        .reset = 0,
 433        .pre_write = lpd_slcr_ier_prew,
 434    },{ .name = "GICP0_IRQ_DISABLE", .decode.addr = A_GICP0_IRQ_DISABLE,
 435        .reset = 0,
 436        .pre_write = lpd_slcr_idr_prew,
 437    },{ .name = "GICP0_IRQ_TRIGGER", .decode.addr = A_GICP0_IRQ_TRIGGER,
 438        .reset = 0,
 439        .pre_write = protection_prew,
 440        .post_write = lpd_slcr_inttrig_posw,
 441    },{ .name = "GICP1_IRQ_STATUS", .decode.addr = A_GICP1_IRQ_STATUS,
 442        .reset = 0,
 443        .w1c = 0xFFFFFFFF,
 444        .pre_write = protection_prew,
 445        .post_write = lpd_slcr_intstatus_posw,
 446    },{ .name = "GICP1_IRQ_MASK", .decode.addr = A_GICP1_IRQ_MASK,
 447        .reset = 0xFFFFFFFF,
 448        .ro = 0xFFFFFFFF,
 449        .pre_write = protection_prew,
 450    },{ .name = "GICP1_IRQ_ENABLE", .decode.addr = A_GICP1_IRQ_ENABLE,
 451        .reset = 0,
 452        .pre_write = lpd_slcr_ier_prew,
 453    },{ .name = "GICP1_IRQ_DISABLE", .decode.addr = A_GICP1_IRQ_DISABLE,
 454        .reset = 0,
 455        .pre_write = lpd_slcr_idr_prew,
 456    },{ .name = "GICP1_IRQ_TRIGGER", .decode.addr = A_GICP1_IRQ_TRIGGER,
 457        .reset = 0,
 458        .pre_write = protection_prew,
 459        .post_write = lpd_slcr_inttrig_posw,
 460    },{ .name = "GICP2_IRQ_STATUS", .decode.addr = A_GICP2_IRQ_STATUS,
 461        .reset = 0,
 462        .w1c = 0xFFFFFFFF,
 463        .pre_write = protection_prew,
 464        .post_write = lpd_slcr_intstatus_posw,
 465    },{ .name = "GICP2_IRQ_MASK", .decode.addr = A_GICP2_IRQ_MASK,
 466        .reset = 0xFFFFFFFF,
 467        .ro = 0xFFFFFFFF,
 468        .pre_write = protection_prew,
 469    },{ .name = "GICP2_IRQ_ENABLE", .decode.addr = A_GICP2_IRQ_ENABLE,
 470        .reset = 0,
 471        .pre_write = lpd_slcr_ier_prew,
 472    },{ .name = "GICP2_IRQ_DISABLE", .decode.addr = A_GICP2_IRQ_DISABLE,
 473        .reset = 0,
 474        .pre_write = lpd_slcr_idr_prew,
 475    },{ .name = "GICP2_IRQ_TRIGGER", .decode.addr = A_GICP2_IRQ_TRIGGER,
 476        .reset = 0,
 477        .pre_write = protection_prew,
 478        .post_write = lpd_slcr_inttrig_posw,
 479    },{ .name = "GICP3_IRQ_STATUS", .decode.addr = A_GICP3_IRQ_STATUS,
 480        .reset = 0,
 481        .w1c = 0xFFFFFFFF,
 482        .pre_write = protection_prew,
 483        .post_write = lpd_slcr_intstatus_posw,
 484    },{ .name = "GICP3_IRQ_MASK", .decode.addr = A_GICP3_IRQ_MASK,
 485        .reset = 0xFFFFFFFF,
 486        .ro = 0xFFFFFFFF,
 487        .pre_write = protection_prew,
 488    },{ .name = "GICP3_IRQ_ENABLE", .decode.addr = A_GICP3_IRQ_ENABLE,
 489        .reset = 0,
 490        .pre_write = lpd_slcr_ier_prew,
 491    },{ .name = "GICP3_IRQ_DISABLE", .decode.addr = A_GICP3_IRQ_DISABLE,
 492        .reset = 0,
 493        .pre_write = lpd_slcr_idr_prew,
 494    },{ .name = "GICP3_IRQ_TRIGGER", .decode.addr = A_GICP3_IRQ_TRIGGER,
 495        .reset = 0,
 496        .pre_write = protection_prew,
 497        .post_write = lpd_slcr_inttrig_posw,
 498    },{ .name = "GICP4_IRQ_STATUS", .decode.addr = A_GICP4_IRQ_STATUS,
 499        .reset = 0,
 500        .w1c = 0xFFFFFFFF,
 501        .pre_write = protection_prew,
 502        .post_write = lpd_slcr_intstatus_posw,
 503    },{ .name = "GICP4_IRQ_MASK", .decode.addr = A_GICP4_IRQ_MASK,
 504        .reset = 0xFFFFFFFF,
 505        .ro = 0xFFFFFFFF,
 506        .pre_write = protection_prew,
 507    },{ .name = "GICP4_IRQ_ENABLE", .decode.addr = A_GICP4_IRQ_ENABLE,
 508        .reset = 0,
 509        .pre_write = lpd_slcr_ier_prew,
 510    },{ .name = "GICP4_IRQ_DISABLE", .decode.addr = A_GICP4_IRQ_DISABLE,
 511        .reset = 0,
 512        .pre_write = lpd_slcr_idr_prew,
 513    },{ .name = "GICP4_IRQ_TRIGGER", .decode.addr = A_GICP4_IRQ_TRIGGER,
 514        .reset = 0,
 515        .pre_write = protection_prew,
 516        .post_write = lpd_slcr_inttrig_posw,
 517    },{ .name = "GICP_PMU_IRQ_STATUS", .decode.addr = A_GICP_PMU_IRQ_STATUS,
 518        .reset = 0,
 519        .pre_write = protection_prew,
 520        .w1c = 0xFFFFFFFF,
 521    },{ .name = "GICP_PMU_IRQ_MASK", .decode.addr = A_GICP_PMU_IRQ_MASK,
 522        .reset = 0x000000FF,
 523        .ro = 0xFFFFFFFF,
 524        .pre_write = protection_prew,
 525    },{ .name = "GICP_PMU_IRQ_ENABLE", .decode.addr = A_GICP_PMU_IRQ_ENABLE,
 526        .reset = 0,
 527        .pre_write = protection_prew,
 528    },{ .name = "GICP_PMU_IRQ_DISABLE", .decode.addr = A_GICP_PMU_IRQ_DISABLE,
 529        .reset = 0,
 530        .pre_write = protection_prew,
 531    },{ .name = "GICP_PMU_IRQ_TRIGGER", .decode.addr = A_GICP_PMU_IRQ_TRIGGER,
 532        .reset = 0,
 533        .pre_write = protection_prew,
 534    },{ .name = "AFI_FS", .decode.addr = A_AFI_FS,
 535        .reset = 0x00000200,
 536        .pre_write = protection_prew,
 537    },{ .name = "LPD_CCI", .decode.addr = A_LPD_CCI,
 538        .reset = 0x03801C07,
 539        .pre_write = protection_prew,
 540    },{ .name = "LPD_CCI_ADDRMAP", .decode.addr = A_LPD_CCI_ADDRMAP,
 541        .reset = 0x00C000FF,
 542        .pre_write = protection_prew,
 543    },{ .name = "LPD_CCI_QVNPREALLOC", .decode.addr = A_LPD_CCI_QVNPREALLOC,
 544        .reset = 0x00330330,
 545        .ro = 0x0000F00F,
 546        .pre_write = protection_prew,
 547    },{ .name = "LPD_SMMU", .decode.addr = A_LPD_SMMU,
 548        .reset = 0x0000003F,
 549        .pre_write = protection_prew,
 550    },{ .name = "LPD_APU", .decode.addr = A_LPD_APU,
 551        .reset = 0x00000001,
 552        .pre_write = protection_prew,
 553    },
 554};
 555
 556static void lpd_slcr_reset(DeviceState *dev)
 557{
 558    LPD_SLCR *s = XILINX_LPD_SLCR(dev);
 559    unsigned int i;
 560
 561    for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
 562        register_reset(&s->regs_info[i]);
 563    }
 564
 565    isr_update_irq(s);
 566}
 567
 568static uint64_t lpd_slcr_read(void *opaque, hwaddr addr, unsigned size)
 569{
 570    LPD_SLCR *s = XILINX_LPD_SLCR(opaque);
 571    RegisterInfo *r = &s->regs_info[addr / 4];
 572
 573    if (!r->data) {
 574        qemu_log("%s: Decode error: read from %" HWADDR_PRIx "\n",
 575                 object_get_canonical_path(OBJECT(s)),
 576                 addr);
 577        return 0;
 578    }
 579    return register_read(r);
 580}
 581
 582static void lpd_slcr_write(void *opaque, hwaddr addr, uint64_t value,
 583                      unsigned size)
 584{
 585    LPD_SLCR *s = XILINX_LPD_SLCR(opaque);
 586    RegisterInfo *r = &s->regs_info[addr / 4];
 587
 588    if (!r->data) {
 589        qemu_log("%s: Decode error: write to %" HWADDR_PRIx "=%" PRIx64 "\n",
 590                 object_get_canonical_path(OBJECT(s)),
 591                 addr, value);
 592        return;
 593    }
 594    register_write(r, value, ~0);
 595}
 596
 597static const MemoryRegionOps lpd_slcr_ops = {
 598    .read = lpd_slcr_read,
 599    .write = lpd_slcr_write,
 600    .endianness = DEVICE_LITTLE_ENDIAN,
 601    .valid = {
 602        .min_access_size = 4,
 603        .max_access_size = 4,
 604    },
 605};
 606
 607static void lpd_slcr_realize(DeviceState *dev, Error **errp)
 608{
 609    LPD_SLCR *s = XILINX_LPD_SLCR(dev);
 610    const char *prefix = object_get_canonical_path(OBJECT(dev));
 611    unsigned int i;
 612
 613    if (!s->rpu_gic) {
 614        error_set(errp, ERROR_CLASS_GENERIC_ERROR, "gic-for-rpu");
 615        return;
 616    }
 617
 618    if (!s->apu_gic) {
 619        error_set(errp, ERROR_CLASS_GENERIC_ERROR, "gic-for-apu");
 620        return;
 621    }
 622
 623    for (i = 0; i < ARRAY_SIZE(lpd_slcr_regs_info); ++i) {
 624        RegisterInfo *r = &s->regs_info[lpd_slcr_regs_info[i].decode.addr/4];
 625
 626        *r = (RegisterInfo) {
 627            .data = (uint8_t *)&s->regs[
 628                    lpd_slcr_regs_info[i].decode.addr/4],
 629            .data_size = sizeof(uint32_t),
 630            .access = &lpd_slcr_regs_info[i],
 631            .debug = XILINX_LPD_SLCR_ERR_DEBUG,
 632            .prefix = prefix,
 633            .opaque = s,
 634        };
 635    }
 636}
 637
 638static void lpd_slcr_init(Object *obj)
 639{
 640    LPD_SLCR *s = XILINX_LPD_SLCR(obj);
 641    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 642
 643    memory_region_init_io(&s->iomem, obj, &lpd_slcr_ops, s,
 644                          TYPE_XILINX_LPD_SLCR, R_MAX * 4);
 645    sysbus_init_mmio(sbd, &s->iomem);
 646    sysbus_init_irq(sbd, &s->irq_isr);
 647
 648    /* Link to the GIC which allow to inject irq through registers.
 649     */
 650    object_property_add_link(obj, "gic-for-rpu", TYPE_XLNX_SCU_GIC,
 651                             (Object **)&s->rpu_gic,
 652                             qdev_prop_allow_set_link_before_realize,
 653                             OBJ_PROP_LINK_UNREF_ON_RELEASE,
 654                             &error_abort);
 655    object_property_add_link(obj, "gic-for-apu", TYPE_XLNX_SCU_GIC,
 656                             (Object **)&s->apu_gic,
 657                             qdev_prop_allow_set_link_before_realize,
 658                             OBJ_PROP_LINK_UNREF_ON_RELEASE,
 659                             &error_abort);
 660}
 661
 662static const VMStateDescription vmstate_lpd_slcr = {
 663    .name = TYPE_XILINX_LPD_SLCR,
 664    .version_id = 1,
 665    .minimum_version_id = 1,
 666    .minimum_version_id_old = 1,
 667    .fields = (VMStateField[]) {
 668        VMSTATE_UINT32_ARRAY(regs, LPD_SLCR, R_MAX),
 669        VMSTATE_END_OF_LIST(),
 670    }
 671};
 672
 673static void lpd_slcr_class_init(ObjectClass *klass, void *data)
 674{
 675    DeviceClass *dc = DEVICE_CLASS(klass);
 676
 677    dc->reset = lpd_slcr_reset;
 678    dc->realize = lpd_slcr_realize;
 679    dc->vmsd = &vmstate_lpd_slcr;
 680}
 681
 682static const TypeInfo lpd_slcr_info = {
 683    .name          = TYPE_XILINX_LPD_SLCR,
 684    .parent        = TYPE_SYS_BUS_DEVICE,
 685    .instance_size = sizeof(LPD_SLCR),
 686    .class_init    = lpd_slcr_class_init,
 687    .instance_init = lpd_slcr_init,
 688};
 689
 690static void lpd_slcr_register_types(void)
 691{
 692    type_register_static(&lpd_slcr_info);
 693}
 694
 695type_init(lpd_slcr_register_types)
 696