From: YannickV <y.vos...@beckhoff.com>

A dummy DDR controller for ZYNQ has been added. While all registers are present,
not all are functional. Read and write access is validated, and the user mode
can be set. This provides a basic DDR controller initialization, preventing
system hangs due to endless polling or similar issues.

Signed-off-by: Yannick Voßen <y.vos...@beckhoff.com>
---
 hw/misc/Kconfig                  |   3 +
 hw/misc/meson.build              |   1 +
 hw/misc/xlnx-zynq-ddrc.c         | 393 +++++++++++++++++++++++++++++++
 include/hw/misc/xlnx-zynq-ddrc.h | 140 +++++++++++
 4 files changed, 537 insertions(+)
 create mode 100644 hw/misc/xlnx-zynq-ddrc.c
 create mode 100644 include/hw/misc/xlnx-zynq-ddrc.h

diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index 8f9ce2f68c..99548e146f 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -220,4 +220,7 @@ config IOSB
 config XLNX_VERSAL_TRNG
     bool
 
+config XLNX_ZYNQ_DDRC
+    bool
+
 source macio/Kconfig
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 55f493521b..6ee7b6c71d 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -89,6 +89,7 @@ system_ss.add(when: 'CONFIG_RASPI', if_true: files(
 ))
 system_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_misc.c'))
 system_ss.add(when: 'CONFIG_ZYNQ', if_true: files('zynq_slcr.c'))
+system_ss.add(when: 'CONFIG_ZYNQ', if_true: files('xlnx-zynq-ddrc.c'))
 system_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: 
files('xlnx-zynqmp-crf.c'))
 system_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: 
files('xlnx-zynqmp-apu-ctrl.c'))
 system_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files(
diff --git a/hw/misc/xlnx-zynq-ddrc.c b/hw/misc/xlnx-zynq-ddrc.c
new file mode 100644
index 0000000000..8151a0e3ee
--- /dev/null
+++ b/hw/misc/xlnx-zynq-ddrc.c
@@ -0,0 +1,393 @@
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/register.h"
+#include "qemu/bitops.h"
+#include "qemu/log.h"
+#include "qapi/error.h"
+#include "hw/registerfields.h"
+#include "system/block-backend.h"
+#include "exec/address-spaces.h"
+#include "exec/memory.h"
+#include "system/dma.h"
+#include "hw/misc/xlnx-zynq-ddrc.h"
+
+#ifndef DDRCTRL_ERR_DEBUG
+#define DDRCTRL_ERR_DEBUG 0
+#endif
+
+static void zynq_ddrctrl_post_write(RegisterInfo *reg, uint64_t val)
+{
+    DDRCTRLState *s = DDRCTRL(reg->opaque);
+    if (reg->access->addr == A_DDRC_CTRL) {
+        if (val & 0x1) {
+            s->reg[R_MODE_STS_REG] |=
+                (R_MODE_STS_REG_DDR_REG_OPERATING_MODE_MASK & 0x1);
+        } else {
+            s->reg[R_MODE_STS_REG] &=
+                ~R_MODE_STS_REG_DDR_REG_OPERATING_MODE_MASK;
+        }
+    }
+}
+
+static const RegisterAccessInfo xlnx_zynq_ddrc_regs_info[] = {
+    /* 0x00 - 0x3C: Basic DDRC control and config */
+    { .name = "DDRC_CTRL",
+      .addr = A_DDRC_CTRL,
+      .reset = 0x00000200,
+      .post_write = zynq_ddrctrl_post_write },
+    { .name = "TWO_RANK_CFG",
+      .addr = A_TWO_RANK_CFG,
+      .reset = 0x000C1076 },
+    { .name = "HPR_REG",
+      .addr = A_HPR_REG,
+      .reset = 0x03C0780F },
+    { .name = "LPR_REG",
+      .addr = A_LPR_REG,
+      .reset = 0x03C0780F },
+    { .name = "WR_REG",
+      .addr = A_WR_REG,
+      .reset = 0x0007F80F },
+    { .name = "DRAM_PARAM_REG0",
+      .addr = A_DRAM_PARAM_REG0,
+      .reset = 0x00041016 },
+    { .name = "DRAM_PARAM_REG1",
+      .addr = A_DRAM_PARAM_REG1,
+      .reset = 0x351B48D9 },
+    { .name = "DRAM_PARAM_REG2",
+      .addr = A_DRAM_PARAM_REG2,
+      .reset = 0x83015904 },
+    { .name = "DRAM_PARAM_REG3",
+      .addr = A_DRAM_PARAM_REG3,
+      .reset = 0x250882D0 },
+    { .name = "DRAM_PARAM_REG4",
+      .addr = A_DRAM_PARAM_REG4,
+      .reset = 0x0000003C },
+    { .name = "DRAM_INIT_PARAM",
+      .addr = A_DRAM_INIT_PARAM,
+      .reset = 0x00002007 },
+    { .name = "DRAM_EMR_REG",
+      .addr = A_DRAM_EMR_REG,
+      .reset = 0x00000008 },
+    { .name = "DRAM_EMR_MR_REG",
+      .addr = A_DRAM_EMR_MR_REG,
+      .reset = 0x00000940 },
+    { .name = "DRAM_BURST8_RDWR",
+      .addr = A_DRAM_BURST8_RDWR,
+      .reset = 0x00020034 },
+    { .name = "DRAM_DISABLE_DQ",
+      .addr = A_DRAM_DISABLE_DQ },
+    { .name = "DRAM_ADDR_MAP_BANK",
+      .addr = A_DRAM_ADDR_MAP_BANK,
+      .reset = 0x00000F77 },
+    { .name = "DRAM_ADDR_MAP_COL",
+      .addr = A_DRAM_ADDR_MAP_COL,
+      .reset = 0xFFF00000 },
+    { .name = "DRAM_ADDR_MAP_ROW",
+      .addr = A_DRAM_ADDR_MAP_ROW,
+      .reset = 0x0FF55555 },
+    { .name = "DRAM_ODT_REG",
+      .addr = A_DRAM_ODT_REG,
+      .reset = 0x00000249 },
+
+    /* 0x4C - 0x5C: PHY and DLL */
+    { .name = "PHY_DBG_REG",
+      .addr = A_PHY_DBG_REG },
+    { .name = "PHY_CMD_TIMEOUT_RDDATA_CPT",
+      .addr = A_PHY_CMD_TIMEOUT_RDDATA_CPT,
+      .reset = 0x00010200 },
+    { .name = "MODE_STS_REG",
+      .addr = A_MODE_STS_REG },
+    { .name = "DLL_CALIB",
+      .addr = A_DLL_CALIB,
+      .reset = 0x00000101 },
+    { .name = "ODT_DELAY_HOLD",
+      .addr = A_ODT_DELAY_HOLD,
+      .reset = 0x00000023 },
+
+    /* 0x60 - 0x7C: Control registers */
+    { .name = "CTRL_REG1",
+      .addr = A_CTRL_REG1,
+      .reset = 0x0000003E },
+    { .name = "CTRL_REG2",
+      .addr = A_CTRL_REG2,
+      .reset = 0x00020000 },
+    { .name = "CTRL_REG3",
+      .addr = A_CTRL_REG3,
+      .reset = 0x00284027 },
+    { .name = "CTRL_REG4",
+      .addr = A_CTRL_REG4,
+      .reset = 0x00001610 },
+    { .name = "CTRL_REG5",
+      .addr = A_CTRL_REG5,
+      .reset = 0x00455111 },
+    { .name = "CTRL_REG6",
+      .addr = A_CTRL_REG6,
+      .reset = 0x00032222 },
+
+    /* 0xA0 - 0xB4: Refresh, ZQ, powerdown, misc */
+    { .name = "CHE_REFRESH_TIMER0",
+      .addr = A_CHE_REFRESH_TIMER0,
+      .reset = 0x00008000 },
+    { .name = "CHE_T_ZQ",
+      .addr = A_CHE_T_ZQ,
+      .reset = 0x10300802 },
+    { .name = "CHE_T_ZQ_SHORT_INTERVAL_REG",
+      .addr = A_CHE_T_ZQ_SHORT_INTERVAL_REG,
+      .reset = 0x0020003A },
+    { .name = "DEEP_PWRDWN_REG",
+      .addr = A_DEEP_PWRDWN_REG },
+    { .name = "REG_2C",
+      .addr = A_REG_2C },
+    { .name = "REG_2D",
+      .addr = A_REG_2D,
+      .reset = 0x00000200 },
+
+    /* 0xB8 - 0xF8: ECC, DFI, etc. */
+    { .name = "DFI_TIMING",
+      .addr = A_DFI_TIMING,
+      .reset = 0x00200067 },
+    { .name = "CHE_ECC_CONTROL_REG_OFFSET",
+      .addr = A_CHE_ECC_CONTROL_REG_OFFSET },
+    { .name = "CHE_CORR_ECC_LOG_REG_OFFSET",
+      .addr = A_CHE_CORR_ECC_LOG_REG_OFFSET },
+    { .name = "CHE_CORR_ECC_ADDR_REG_OFFSET",
+      .addr = A_CHE_CORR_ECC_ADDR_REG_OFFSET },
+    { .name = "CHE_CORR_ECC_DATA_31_0_REG_OFFSET",
+      .addr = A_CHE_CORR_ECC_DATA_31_0_REG_OFFSET },
+    { .name = "CHE_CORR_ECC_DATA_63_32_REG_OFFSET",
+      .addr = A_CHE_CORR_ECC_DATA_63_32_REG_OFFSET },
+    { .name = "CHE_CORR_ECC_DATA_71_64_REG_OFFSET",
+      .addr = A_CHE_CORR_ECC_DATA_71_64_REG_OFFSET },
+    { .name = "CHE_UNCORR_ECC_LOG_REG_OFFSET",
+      .addr = A_CHE_UNCORR_ECC_LOG_REG_OFFSET },
+    { .name = "CHE_UNCORR_ECC_ADDR_REG_OFFSET",
+      .addr = A_CHE_UNCORR_ECC_ADDR_REG_OFFSET },
+    { .name = "CHE_UNCORR_ECC_DATA_31_0_REG_OFFSET",
+      .addr = A_CHE_UNCORR_ECC_DATA_31_0_REG_OFFSET },
+    { .name = "CHE_UNCORR_ECC_DATA_63_32_REG_OFFSET",
+      .addr = A_CHE_UNCORR_ECC_DATA_63_32_REG_OFFSET },
+    { .name = "CHE_UNCORR_ECC_DATA_71_64_REG_OFFSET",
+      .addr = A_CHE_UNCORR_ECC_DATA_71_64_REG_OFFSET },
+    { .name = "CHE_ECC_STATS_REG_OFFSET",
+      .addr = A_CHE_ECC_STATS_REG_OFFSET },
+    { .name = "ECC_SCRUB",
+      .addr = A_ECC_SCRUB,
+      .reset = 0x00000008 },
+    { .name = "CHE_ECC_CORR_BIT_MASK_31_0_REG_OFFSET",
+      .addr = A_CHE_ECC_CORR_BIT_MASK_31_0_REG_OFFSET },
+    { .name = "CHE_ECC_CORR_BIT_MASK_63_32_REG_OFFSET",
+      .addr = A_CHE_ECC_CORR_BIT_MASK_63_32_REG_OFFSET },
+
+    /* 0x114 - 0x174: PHY config, ratios, DQS, WE */
+    { .name = "PHY_RCVER_ENABLE",
+      .addr = A_PHY_RCVER_ENABLE },
+    { .name = "PHY_CONFIG0",
+      .addr = A_PHY_CONFIG0,
+      .reset = 0x40000001 },
+    { .name = "PHY_CONFIG1",
+      .addr = A_PHY_CONFIG1,
+      .reset = 0x40000001 },
+    { .name = "PHY_CONFIG2",
+      .addr = A_PHY_CONFIG2,
+      .reset = 0x40000001 },
+    { .name = "PHY_CONFIG3",
+      .addr = A_PHY_CONFIG3,
+      .reset = 0x40000001 },
+    { .name = "PHY_INIT_RATIO0",
+      .addr = A_PHY_INIT_RATIO0 },
+    { .name = "PHY_INIT_RATIO1",
+      .addr = A_PHY_INIT_RATIO1 },
+    { .name = "PHY_INIT_RATIO2",
+      .addr = A_PHY_INIT_RATIO2 },
+    { .name = "PHY_INIT_RATIO3",
+      .addr = A_PHY_INIT_RATIO3 },
+    { .name = "PHY_RD_DQS_CFG0",
+      .addr = A_PHY_RD_DQS_CFG0,
+      .reset = 0x00000040 },
+    { .name = "PHY_RD_DQS_CFG1",
+      .addr = A_PHY_RD_DQS_CFG1,
+      .reset = 0x00000040 },
+    { .name = "PHY_RD_DQS_CFG2",
+      .addr = A_PHY_RD_DQS_CFG2,
+      .reset = 0x00000040 },
+    { .name = "PHY_RD_DQS_CFG3",
+      .addr = A_PHY_RD_DQS_CFG3,
+      .reset = 0x00000040 },
+    { .name = "PHY_WR_DQS_CFG0",
+      .addr = A_PHY_WR_DQS_CFG0 },
+    { .name = "PHY_WR_DQS_CFG1",
+      .addr = A_PHY_WR_DQS_CFG1 },
+    { .name = "PHY_WR_DQS_CFG2",
+      .addr = A_PHY_WR_DQS_CFG2 },
+    { .name = "PHY_WR_DQS_CFG3",
+      .addr = A_PHY_WR_DQS_CFG3 },
+    { .name = "PHY_WE_CFG0",
+      .addr = A_PHY_WE_CFG0,
+      .reset = 0x00000040 },
+    { .name = "PHY_WE_CFG1",
+      .addr = A_PHY_WE_CFG1,
+      .reset = 0x00000040 },
+    { .name = "PHY_WE_CFG2",
+      .addr = A_PHY_WE_CFG2,
+      .reset = 0x00000040 },
+    { .name = "PHY_WE_CFG3",
+      .addr = A_PHY_WE_CFG3,
+      .reset = 0x00000040 },
+
+    /* 0x17C - 0x194: Write data slaves, misc */
+    { .name = "WR_DATA_SLV0",
+      .addr = A_WR_DATA_SLV0,
+      .reset = 0x00000080 },
+    { .name = "WR_DATA_SLV1",
+      .addr = A_WR_DATA_SLV1,
+      .reset = 0x00000080 },
+    { .name = "WR_DATA_SLV2",
+      .addr = A_WR_DATA_SLV2,
+      .reset = 0x00000080 },
+    { .name = "WR_DATA_SLV3",
+      .addr = A_WR_DATA_SLV3,
+      .reset = 0x00000080 },
+    { .name = "REG_64",
+      .addr = A_REG_64,
+      .reset = 0x10020000 },
+    { .name = "REG_65",
+      .addr = A_REG_65 },
+
+    /* 0x1A4 - 0x1C4: Misc registers */
+    { .name = "REG69_6A0",
+      .addr = A_REG69_6A0 },
+    { .name = "REG69_6A1",
+      .addr = A_REG69_6A1 },
+    { .name = "REG6C_6D2",
+      .addr = A_REG6C_6D2 },
+    { .name = "REG6C_6D3",
+      .addr = A_REG6C_6D3 },
+    { .name = "REG6E_710",
+      .addr = A_REG6E_710 },
+    { .name = "REG6E_711",
+      .addr = A_REG6E_711 },
+    { .name = "REG6E_712",
+      .addr = A_REG6E_712 },
+    { .name = "REG6E_713",
+      .addr = A_REG6E_713 },
+
+    /* 0x1CC - 0x1E8: DLL, PHY status */
+    { .name = "PHY_DLL_STS0",
+      .addr = A_PHY_DLL_STS0 },
+    { .name = "PHY_DLL_STS1",
+      .addr = A_PHY_DLL_STS1 },
+    { .name = "PHY_DLL_STS2",
+      .addr = A_PHY_DLL_STS2 },
+    { .name = "PHY_DLL_STS3",
+      .addr = A_PHY_DLL_STS3 },
+    { .name = "DLL_LOCK_STS",
+      .addr = A_DLL_LOCK_STS },
+    { .name = "PHY_CTRL_STS",
+      .addr = A_PHY_CTRL_STS },
+    { .name = "PHY_CTRL_STS_REG2",
+      .addr = A_PHY_CTRL_STS_REG2 },
+
+    /* 0x200 - 0x2B4: AXI, LPDDR, misc */
+    { .name = "AXI_ID",
+      .addr = A_AXI_ID },
+    { .name = "PAGE_MASK",
+      .addr = A_PAGE_MASK },
+    { .name = "AXI_PRIORITY_WR_PORT0",
+      .addr = A_AXI_PRIORITY_WR_PORT0,
+      .reset = 0x000803FF },
+    { .name = "AXI_PRIORITY_WR_PORT1",
+      .addr = A_AXI_PRIORITY_WR_PORT1,
+      .reset = 0x000803FF },
+    { .name = "AXI_PRIORITY_WR_PORT2",
+      .addr = A_AXI_PRIORITY_WR_PORT2,
+      .reset = 0x000803FF },
+    { .name = "AXI_PRIORITY_WR_PORT3",
+      .addr = A_AXI_PRIORITY_WR_PORT3,
+      .reset = 0x000803FF },
+    { .name = "AXI_PRIORITY_RD_PORT0",
+      .addr = A_AXI_PRIORITY_RD_PORT0,
+      .reset = 0x000003FF },
+    { .name = "AXI_PRIORITY_RD_PORT1",
+      .addr = A_AXI_PRIORITY_RD_PORT1,
+      .reset = 0x000003FF },
+    { .name = "AXI_PRIORITY_RD_PORT2",
+      .addr = A_AXI_PRIORITY_RD_PORT2,
+      .reset = 0x000003FF },
+    { .name = "AXI_PRIORITY_RD_PORT3",
+      .addr = A_AXI_PRIORITY_RD_PORT3,
+      .reset = 0x000003FF },
+    { .name = "EXCL_ACCESS_CFG0",
+      .addr = A_EXCL_ACCESS_CFG0 },
+    { .name = "EXCL_ACCESS_CFG1",
+      .addr = A_EXCL_ACCESS_CFG1 },
+    { .name = "EXCL_ACCESS_CFG2",
+      .addr = A_EXCL_ACCESS_CFG2 },
+    { .name = "EXCL_ACCESS_CFG3",
+      .addr = A_EXCL_ACCESS_CFG3 },
+    { .name = "MODE_REG_READ",
+      .addr = A_MODE_REG_READ },
+    { .name = "LPDDR_CTRL0",
+      .addr = A_LPDDR_CTRL0 },
+    { .name = "LPDDR_CTRL1",
+      .addr = A_LPDDR_CTRL1 },
+    { .name = "LPDDR_CTRL2",
+      .addr = A_LPDDR_CTRL2,
+      .reset = 0x003C0015 },
+    { .name = "LPDDR_CTRL3",
+      .addr = A_LPDDR_CTRL3,
+      .reset = 0x00000601 },
+};
+
+static void zynq_ddrctrl_reset(DeviceState *dev)
+{
+    DDRCTRLState *s = DDRCTRL(dev);
+    int i;
+
+    for (i = 0; i < ZYNQ_DDRCTRL_NUM_REG; ++i) {
+        register_reset(&s->regs_info[i]);
+    }
+}
+
+static const MemoryRegionOps ddrctrl_ops = {
+    .read = register_read_memory,
+    .write = register_write_memory,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void zynq_ddrctrl_init(Object *obj)
+{
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    DDRCTRLState *s = DDRCTRL(obj);
+
+    s->reg_array =
+        register_init_block32(DEVICE(obj), xlnx_zynq_ddrc_regs_info,
+                              ARRAY_SIZE(xlnx_zynq_ddrc_regs_info),
+                              s->regs_info, s->reg,
+                              &ddrctrl_ops,
+                              DDRCTRL_ERR_DEBUG,
+                              ZYNQ_DDRCTRL_MMIO_SIZE);
+
+    sysbus_init_mmio(sbd, &s->reg_array->mem);
+}
+
+static void zynq_ddrctrl_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    device_class_set_legacy_reset(dc, zynq_ddrctrl_reset);
+}
+
+static const TypeInfo ddrctrl_info = {
+    .name = TYPE_DDRCTRL,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(DDRCTRLState),
+    .class_init = zynq_ddrctrl_class_init,
+    .instance_init = zynq_ddrctrl_init,
+};
+
+static void ddrctrl_register_types(void)
+{
+    type_register_static(&ddrctrl_info);
+}
+
+type_init(ddrctrl_register_types)
diff --git a/include/hw/misc/xlnx-zynq-ddrc.h b/include/hw/misc/xlnx-zynq-ddrc.h
new file mode 100644
index 0000000000..7b9b4d551e
--- /dev/null
+++ b/include/hw/misc/xlnx-zynq-ddrc.h
@@ -0,0 +1,140 @@
+#ifndef XLNX_ZYNQ_DDRC_H
+#define XLNX_ZYNQ_DDRC_H
+
+#include "hw/sysbus.h"
+#include "hw/register.h"
+
+#define TYPE_DDRCTRL "zynq.ddr-ctlr"
+#define DDRCTRL(obj) \
+    OBJECT_CHECK(DDRCTRLState, (obj), TYPE_DDRCTRL)
+
+REG32(DDRC_CTRL, 0x00)
+REG32(TWO_RANK_CFG, 0x04)
+REG32(HPR_REG, 0x08)
+REG32(LPR_REG, 0x0C)
+REG32(WR_REG, 0x10)
+REG32(DRAM_PARAM_REG0, 0x14)
+REG32(DRAM_PARAM_REG1, 0x18)
+REG32(DRAM_PARAM_REG2, 0x1C)
+REG32(DRAM_PARAM_REG3, 0x20)
+REG32(DRAM_PARAM_REG4, 0x24)
+REG32(DRAM_INIT_PARAM, 0x28)
+REG32(DRAM_EMR_REG, 0x2C)
+REG32(DRAM_EMR_MR_REG, 0x30)
+REG32(DRAM_BURST8_RDWR, 0x34)
+REG32(DRAM_DISABLE_DQ, 0x38)
+REG32(DRAM_ADDR_MAP_BANK, 0x3C)
+REG32(DRAM_ADDR_MAP_COL, 0x40)
+REG32(DRAM_ADDR_MAP_ROW, 0x44)
+REG32(DRAM_ODT_REG, 0x48)
+REG32(PHY_DBG_REG, 0x4C)
+REG32(PHY_CMD_TIMEOUT_RDDATA_CPT, 0x50)
+REG32(MODE_STS_REG, 0x54)
+    FIELD(MODE_STS_REG, DDR_REG_DBG_STALL, 3, 3)
+    FIELD(MODE_STS_REG, DDR_REG_OPERATING_MODE, 0, 2)
+REG32(DLL_CALIB, 0x58)
+REG32(ODT_DELAY_HOLD, 0x5C)
+REG32(CTRL_REG1, 0x60)
+REG32(CTRL_REG2, 0x64)
+REG32(CTRL_REG3, 0x68)
+REG32(CTRL_REG4, 0x6C)
+REG32(CTRL_REG5, 0x78)
+REG32(CTRL_REG6, 0x7C)
+REG32(CHE_REFRESH_TIMER0, 0xA0)
+REG32(CHE_T_ZQ, 0xA4)
+REG32(CHE_T_ZQ_SHORT_INTERVAL_REG, 0xA8)
+REG32(DEEP_PWRDWN_REG, 0xAC)
+REG32(REG_2C, 0xB0)
+REG32(REG_2D, 0xB4)
+REG32(DFI_TIMING, 0xB8)
+REG32(CHE_ECC_CONTROL_REG_OFFSET, 0xC4)
+REG32(CHE_CORR_ECC_LOG_REG_OFFSET, 0xC8)
+REG32(CHE_CORR_ECC_ADDR_REG_OFFSET, 0xCC)
+REG32(CHE_CORR_ECC_DATA_31_0_REG_OFFSET, 0xD0)
+REG32(CHE_CORR_ECC_DATA_63_32_REG_OFFSET, 0xD4)
+REG32(CHE_CORR_ECC_DATA_71_64_REG_OFFSET, 0xD8)
+REG32(CHE_UNCORR_ECC_LOG_REG_OFFSET, 0xDC)
+REG32(CHE_UNCORR_ECC_ADDR_REG_OFFSET, 0xE0)
+REG32(CHE_UNCORR_ECC_DATA_31_0_REG_OFFSET, 0xE4)
+REG32(CHE_UNCORR_ECC_DATA_63_32_REG_OFFSET, 0xE8)
+REG32(CHE_UNCORR_ECC_DATA_71_64_REG_OFFSET, 0xEC)
+REG32(CHE_ECC_STATS_REG_OFFSET, 0xF0)
+REG32(ECC_SCRUB, 0xF4)
+REG32(CHE_ECC_CORR_BIT_MASK_31_0_REG_OFFSET, 0xF8)
+REG32(CHE_ECC_CORR_BIT_MASK_63_32_REG_OFFSET, 0xFC)
+REG32(PHY_RCVER_ENABLE, 0x114)
+REG32(PHY_CONFIG0, 0x118)
+REG32(PHY_CONFIG1, 0x11C)
+REG32(PHY_CONFIG2, 0x120)
+REG32(PHY_CONFIG3, 0x124)
+REG32(PHY_INIT_RATIO0, 0x12C)
+REG32(PHY_INIT_RATIO1, 0x130)
+REG32(PHY_INIT_RATIO2, 0x134)
+REG32(PHY_INIT_RATIO3, 0x138)
+REG32(PHY_RD_DQS_CFG0, 0x140)
+REG32(PHY_RD_DQS_CFG1, 0x144)
+REG32(PHY_RD_DQS_CFG2, 0x148)
+REG32(PHY_RD_DQS_CFG3, 0x14C)
+REG32(PHY_WR_DQS_CFG0, 0x154)
+REG32(PHY_WR_DQS_CFG1, 0x158)
+REG32(PHY_WR_DQS_CFG2, 0x15C)
+REG32(PHY_WR_DQS_CFG3, 0x160)
+REG32(PHY_WE_CFG0, 0x168)
+REG32(PHY_WE_CFG1, 0x16C)
+REG32(PHY_WE_CFG2, 0x170)
+REG32(PHY_WE_CFG3, 0x174)
+REG32(WR_DATA_SLV0, 0x17C)
+REG32(WR_DATA_SLV1, 0x180)
+REG32(WR_DATA_SLV2, 0x184)
+REG32(WR_DATA_SLV3, 0x188)
+REG32(REG_64, 0x190)
+REG32(REG_65, 0x194)
+REG32(REG69_6A0, 0x1A4)
+REG32(REG69_6A1, 0x1A8)
+REG32(REG6C_6D2, 0x1B0)
+REG32(REG6C_6D3, 0x1B4)
+REG32(REG6E_710, 0x1B8)
+REG32(REG6E_711, 0x1BC)
+REG32(REG6E_712, 0x1C0)
+REG32(REG6E_713, 0x1C4)
+REG32(PHY_DLL_STS0, 0x1CC)
+REG32(PHY_DLL_STS1, 0x1D0)
+REG32(PHY_DLL_STS2, 0x1D4)
+REG32(PHY_DLL_STS3, 0x1D8)
+REG32(DLL_LOCK_STS, 0x1E0)
+REG32(PHY_CTRL_STS, 0x1E4)
+REG32(PHY_CTRL_STS_REG2, 0x1E8)
+REG32(AXI_ID, 0x200)
+REG32(PAGE_MASK, 0x204)
+REG32(AXI_PRIORITY_WR_PORT0, 0x208)
+REG32(AXI_PRIORITY_WR_PORT1, 0x20C)
+REG32(AXI_PRIORITY_WR_PORT2, 0x210)
+REG32(AXI_PRIORITY_WR_PORT3, 0x214)
+REG32(AXI_PRIORITY_RD_PORT0, 0x218)
+REG32(AXI_PRIORITY_RD_PORT1, 0x21C)
+REG32(AXI_PRIORITY_RD_PORT2, 0x220)
+REG32(AXI_PRIORITY_RD_PORT3, 0x224)
+REG32(EXCL_ACCESS_CFG0, 0x294)
+REG32(EXCL_ACCESS_CFG1, 0x298)
+REG32(EXCL_ACCESS_CFG2, 0x29C)
+REG32(EXCL_ACCESS_CFG3, 0x2A0)
+REG32(MODE_REG_READ, 0x2A4)
+REG32(LPDDR_CTRL0, 0x2A8)
+REG32(LPDDR_CTRL1, 0x2AC)
+REG32(LPDDR_CTRL2, 0x2B0)
+REG32(LPDDR_CTRL3, 0x2B4)
+
+
+#define ZYNQ_DDRCTRL_MMIO_SIZE      0x400
+#define ZYNQ_DDRCTRL_NUM_REG        (ZYNQ_DDRCTRL_MMIO_SIZE / 4)
+
+typedef struct DDRCTRLState {
+    SysBusDevice parent_obj;
+
+    MemoryRegion iomem;
+
+    RegisterInfoArray *reg_array;
+    uint32_t reg[ZYNQ_DDRCTRL_NUM_REG];
+    RegisterInfo regs_info[ZYNQ_DDRCTRL_NUM_REG];
+} DDRCTRLState;
+#endif
-- 
2.50.1


Reply via email to