/*
 * QEMU model of the Xilinx Zynq Double Data Rate Controller
 *
 * Copyright (c) Beckhoff Automation GmbH. & Co. KG
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

#ifndef XLNX_ZYNQ_DDRC_H
#define XLNX_ZYNQ_DDRC_H

#include "hw/core/sysbus.h"
#include "hw/core/register.h"

#define TYPE_DDRCTRL "zynq.ddr-ctlr"
OBJECT_DECLARE_SIMPLE_TYPE(DDRCTRLState, 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
