/*
 * QEMU model of the PSXC_CRL APB control registers for clock controller.
 *
 * Copyright (c) 2023 Advanced Micro Devices Inc.
 *
 * Autogenerated by xregqemu.py 2023-02-10.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "qemu/osdep.h"
#include "hw/sysbus.h"
#include "hw/register.h"
#include "qemu/bitops.h"
#include "qemu/log.h"
#include "hw/irq.h"
#include "hw/qdev-properties.h"
#include "migration/vmstate.h"

#include "hw/fdt_generic_util.h"

#ifndef XILINX_PSXC_CRL_ERR_DEBUG
#define XILINX_PSXC_CRL_ERR_DEBUG 0
#endif

#define TYPE_XILINX_PSXC_CRL "xlnx.psxc_crl"

#define XILINX_PSXC_CRL(obj) \
     OBJECT_CHECK(PSXC_CRL, (obj), TYPE_XILINX_PSXC_CRL)

REG32(ERR_CTRL, 0x0)
REG32(WPROT, 0x1c)
    FIELD(WPROT, ACTIVE, 0, 1)
REG32(RPLL_CTRL, 0x40)
    FIELD(RPLL_CTRL, POST_SRC, 24, 3)
    FIELD(RPLL_CTRL, PRE_SRC, 20, 3)
    FIELD(RPLL_CTRL, CLKOUTDIV, 16, 2)
    FIELD(RPLL_CTRL, FBDIV, 8, 8)
    FIELD(RPLL_CTRL, BYPASS, 3, 1)
    FIELD(RPLL_CTRL, RESET, 0, 1)
REG32(RPLL_CFG, 0x44)
    FIELD(RPLL_CFG, LOCK_DLY, 25, 7)
    FIELD(RPLL_CFG, LOCK_CNT, 13, 10)
    FIELD(RPLL_CFG, LFHF, 10, 2)
    FIELD(RPLL_CFG, CP, 5, 4)
    FIELD(RPLL_CFG, RES, 0, 4)
REG32(FLXPLL_CTRL, 0x50)
    FIELD(FLXPLL_CTRL, POST_SRC, 24, 3)
    FIELD(FLXPLL_CTRL, PRE_SRC, 20, 3)
    FIELD(FLXPLL_CTRL, CLKOUTDIV, 16, 2)
    FIELD(FLXPLL_CTRL, FBDIV, 8, 8)
    FIELD(FLXPLL_CTRL, BYPASS, 3, 1)
    FIELD(FLXPLL_CTRL, RESET, 0, 1)
REG32(FLXPLL_CFG, 0x54)
    FIELD(FLXPLL_CFG, LOCK_DLY, 25, 7)
    FIELD(FLXPLL_CFG, LOCK_CNT, 13, 10)
    FIELD(FLXPLL_CFG, LFHF, 10, 2)
    FIELD(FLXPLL_CFG, CP, 5, 4)
    FIELD(FLXPLL_CFG, RES, 0, 4)
REG32(PLL_STATUS, 0x60)
    FIELD(PLL_STATUS, FLXPLL_STABLE, 3, 1)
    FIELD(PLL_STATUS, RPLL_STABLE, 2, 1)
    FIELD(PLL_STATUS, FLXPLL_LOCK, 1, 1)
    FIELD(PLL_STATUS, RPLL_LOCK, 0, 1)
REG32(RPLL_TO_XPD_CTRL, 0x100)
    FIELD(RPLL_TO_XPD_CTRL, DIVISOR0, 8, 10)
REG32(LPX_TOP_SWITCH_CTRL, 0x104)
    FIELD(LPX_TOP_SWITCH_CTRL, CLKACT_ADMA, 26, 1)
    FIELD(LPX_TOP_SWITCH_CTRL, CLKACT, 25, 1)
    FIELD(LPX_TOP_SWITCH_CTRL, DIVISOR0, 8, 10)
    FIELD(LPX_TOP_SWITCH_CTRL, SRCSEL, 0, 3)
REG32(LPX_LSBUS_CLK_CTRL, 0x108)
    FIELD(LPX_LSBUS_CLK_CTRL, CLKACT, 25, 1)
    FIELD(LPX_LSBUS_CLK_CTRL, DIVISOR0, 8, 10)
    FIELD(LPX_LSBUS_CLK_CTRL, SRCSEL, 0, 3)
REG32(RPU_CLK_CTRL, 0x10c)
    FIELD(RPU_CLK_CTRL, CLKACT, 25, 1)
    FIELD(RPU_CLK_CTRL, CLKACT_CLUSTERE, 24, 1)
    FIELD(RPU_CLK_CTRL, CLKACT_CLUSTERD, 23, 1)
    FIELD(RPU_CLK_CTRL, CLKACT_CLUSTERC, 22, 1)
    FIELD(RPU_CLK_CTRL, CLKACT_CLUSTERB, 21, 1)
    FIELD(RPU_CLK_CTRL, CLKACT_CLUSTERA, 20, 1)
    FIELD(RPU_CLK_CTRL, DIVISOR0, 8, 10)
    FIELD(RPU_CLK_CTRL, SRCSEL, 0, 3)
REG32(OCM_CLK_CTRL, 0x120)
    FIELD(OCM_CLK_CTRL, CLKACT_OCM3, 24, 1)
    FIELD(OCM_CLK_CTRL, CLKACT_OCM2, 23, 1)
    FIELD(OCM_CLK_CTRL, CLKACT_OCM1, 22, 1)
    FIELD(OCM_CLK_CTRL, CLKACT_OCM0, 21, 1)
REG32(IOU_SWITCH_CLK_CTRL, 0x124)
    FIELD(IOU_SWITCH_CLK_CTRL, CLKACT, 25, 1)
    FIELD(IOU_SWITCH_CLK_CTRL, DIVISOR0, 8, 10)
    FIELD(IOU_SWITCH_CLK_CTRL, SRCSEL, 0, 3)
REG32(GEM0_REF_CTRL, 0x128)
    FIELD(GEM0_REF_CTRL, CLKACT_RX, 27, 1)
    FIELD(GEM0_REF_CTRL, CLKACT_TX, 26, 1)
    FIELD(GEM0_REF_CTRL, CLKACT, 25, 1)
    FIELD(GEM0_REF_CTRL, DIVISOR0, 8, 10)
    FIELD(GEM0_REF_CTRL, SRCSEL, 0, 3)
REG32(GEM1_REF_CTRL, 0x12c)
    FIELD(GEM1_REF_CTRL, CLKACT_RX, 27, 1)
    FIELD(GEM1_REF_CTRL, CLKACT_TX, 26, 1)
    FIELD(GEM1_REF_CTRL, CLKACT, 25, 1)
    FIELD(GEM1_REF_CTRL, DIVISOR0, 8, 10)
    FIELD(GEM1_REF_CTRL, SRCSEL, 0, 3)
REG32(GEM_TSU_REF_CLK_CTRL, 0x130)
    FIELD(GEM_TSU_REF_CLK_CTRL, CLKACT, 25, 1)
    FIELD(GEM_TSU_REF_CLK_CTRL, DIVISOR0, 8, 10)
    FIELD(GEM_TSU_REF_CLK_CTRL, SRCSEL, 0, 3)
REG32(USB0_BUS_REF_CLK_CTRL, 0x134)
    FIELD(USB0_BUS_REF_CLK_CTRL, CLKACT, 25, 1)
    FIELD(USB0_BUS_REF_CLK_CTRL, DIVISOR0, 8, 10)
    FIELD(USB0_BUS_REF_CLK_CTRL, SRCSEL, 0, 3)
REG32(USB1_BUS_REF_CLK_CTRL, 0x138)
    FIELD(USB1_BUS_REF_CLK_CTRL, CLKACT, 25, 1)
    FIELD(USB1_BUS_REF_CLK_CTRL, DIVISOR0, 8, 10)
    FIELD(USB1_BUS_REF_CLK_CTRL, SRCSEL, 0, 3)
REG32(UART0_REF_CLK_CTRL, 0x13c)
    FIELD(UART0_REF_CLK_CTRL, CLKACT, 25, 1)
    FIELD(UART0_REF_CLK_CTRL, DIVISOR0, 8, 10)
    FIELD(UART0_REF_CLK_CTRL, SRCSEL, 0, 3)
REG32(UART1_REF_CLK_CTRL, 0x140)
    FIELD(UART1_REF_CLK_CTRL, CLKACT, 25, 1)
    FIELD(UART1_REF_CLK_CTRL, DIVISOR0, 8, 10)
    FIELD(UART1_REF_CLK_CTRL, SRCSEL, 0, 3)
REG32(SPI0_REF_CLK_CTRL, 0x144)
    FIELD(SPI0_REF_CLK_CTRL, CLKACT, 25, 1)
    FIELD(SPI0_REF_CLK_CTRL, DIVISOR0, 8, 10)
    FIELD(SPI0_REF_CLK_CTRL, SRCSEL, 0, 3)
REG32(SPI1_REF_CLK_CTRL, 0x148)
    FIELD(SPI1_REF_CLK_CTRL, CLKACT, 25, 1)
    FIELD(SPI1_REF_CLK_CTRL, DIVISOR0, 8, 10)
    FIELD(SPI1_REF_CLK_CTRL, SRCSEL, 0, 3)
REG32(CAN0_REF_2X_CTRL, 0x14c)
    FIELD(CAN0_REF_2X_CTRL, CLKACT, 25, 1)
    FIELD(CAN0_REF_2X_CTRL, DIVISOR0, 8, 10)
    FIELD(CAN0_REF_2X_CTRL, SRCSEL, 0, 3)
REG32(CAN1_REF_2X_CTRL, 0x150)
    FIELD(CAN1_REF_2X_CTRL, CLKACT, 25, 1)
    FIELD(CAN1_REF_2X_CTRL, DIVISOR0, 8, 10)
    FIELD(CAN1_REF_2X_CTRL, SRCSEL, 0, 3)
REG32(CAN2_REF_2X_CTRL, 0x154)
    FIELD(CAN2_REF_2X_CTRL, CLKACT, 25, 1)
    FIELD(CAN2_REF_2X_CTRL, DIVISOR0, 8, 10)
    FIELD(CAN2_REF_2X_CTRL, SRCSEL, 0, 3)
REG32(CAN3_REF_2X_CTRL, 0x158)
    FIELD(CAN3_REF_2X_CTRL, CLKACT, 25, 1)
    FIELD(CAN3_REF_2X_CTRL, DIVISOR0, 8, 10)
    FIELD(CAN3_REF_2X_CTRL, SRCSEL, 0, 3)
REG32(I3C0_REF_CTRL, 0x15c)
    FIELD(I3C0_REF_CTRL, CLKACT, 25, 1)
    FIELD(I3C0_REF_CTRL, DIVISOR0, 8, 10)
    FIELD(I3C0_REF_CTRL, SRCSEL, 0, 3)
REG32(I3C1_REF_CTRL, 0x160)
    FIELD(I3C1_REF_CTRL, CLKACT, 25, 1)
    FIELD(I3C1_REF_CTRL, DIVISOR0, 8, 10)
    FIELD(I3C1_REF_CTRL, SRCSEL, 0, 3)
REG32(I3C2_REF_CTRL, 0x164)
    FIELD(I3C2_REF_CTRL, CLKACT, 25, 1)
    FIELD(I3C2_REF_CTRL, DIVISOR0, 8, 10)
    FIELD(I3C2_REF_CTRL, SRCSEL, 0, 3)
REG32(I3C3_REF_CTRL, 0x168)
    FIELD(I3C3_REF_CTRL, CLKACT, 25, 1)
    FIELD(I3C3_REF_CTRL, DIVISOR0, 8, 10)
    FIELD(I3C3_REF_CTRL, SRCSEL, 0, 3)
REG32(I3C4_REF_CTRL, 0x16c)
    FIELD(I3C4_REF_CTRL, CLKACT, 25, 1)
    FIELD(I3C4_REF_CTRL, DIVISOR0, 8, 10)
    FIELD(I3C4_REF_CTRL, SRCSEL, 0, 3)
REG32(I3C5_REF_CTRL, 0x170)
    FIELD(I3C5_REF_CTRL, CLKACT, 25, 1)
    FIELD(I3C5_REF_CTRL, DIVISOR0, 8, 10)
    FIELD(I3C5_REF_CTRL, SRCSEL, 0, 3)
REG32(I3C6_REF_CTRL, 0x174)
    FIELD(I3C6_REF_CTRL, CLKACT, 25, 1)
    FIELD(I3C6_REF_CTRL, DIVISOR0, 8, 10)
    FIELD(I3C6_REF_CTRL, SRCSEL, 0, 3)
REG32(I3C7_REF_CTRL, 0x178)
    FIELD(I3C7_REF_CTRL, CLKACT, 25, 1)
    FIELD(I3C7_REF_CTRL, DIVISOR0, 8, 10)
    FIELD(I3C7_REF_CTRL, SRCSEL, 0, 3)
REG32(DBG_LPX_CTRL, 0x17c)
    FIELD(DBG_LPX_CTRL, CLKACT, 25, 1)
    FIELD(DBG_LPX_CTRL, DIVISOR0, 8, 10)
    FIELD(DBG_LPX_CTRL, SRCSEL, 0, 3)
REG32(TIMESTAMP_REF_CTRL, 0x180)
    FIELD(TIMESTAMP_REF_CTRL, CLKACT, 25, 1)
    FIELD(TIMESTAMP_REF_CTRL, DIVISOR0, 8, 10)
    FIELD(TIMESTAMP_REF_CTRL, SRCSEL, 0, 3)
REG32(SAFETY_CHK, 0x184)
REG32(ASU_CLK_CTRL, 0x188)
    FIELD(ASU_CLK_CTRL, DIVISOR0, 8, 10)
    FIELD(ASU_CLK_CTRL, SRCSEL, 0, 3)
REG32(DBG_TSTMP_CLK_CTRL, 0x18c)
    FIELD(DBG_TSTMP_CLK_CTRL, CLKACT, 25, 1)
    FIELD(DBG_TSTMP_CLK_CTRL, DIVISOR0, 8, 10)
    FIELD(DBG_TSTMP_CLK_CTRL, SRCSEL, 0, 3)
REG32(MMI_TOPSW_CLK_CTRL, 0x190)
    FIELD(MMI_TOPSW_CLK_CTRL, CLKACT, 25, 1)
    FIELD(MMI_TOPSW_CLK_CTRL, DIVISOR0, 8, 10)
    FIELD(MMI_TOPSW_CLK_CTRL, SRCSEL, 0, 3)
REG32(WWDT_PLL_CLK_CTRL, 0x194)
    FIELD(WWDT_PLL_CLK_CTRL, DIVISOR0, 8, 10)
    FIELD(WWDT_PLL_CLK_CTRL, SRCSEL, 0, 3)
REG32(RCLK_CTRL, 0x1a0)
    FIELD(RCLK_CTRL, CLKACT, 8, 6)
    FIELD(RCLK_CTRL, SELECT, 0, 6)
REG32(RST_RPU_A, 0x310)
    FIELD(RST_RPU_A, TOPRESET, 16, 1)
    FIELD(RST_RPU_A, CORE1_POR, 9, 1)
    FIELD(RST_RPU_A, CORE0_POR, 8, 1)
    FIELD(RST_RPU_A, CORE1_RESET, 1, 1)
    FIELD(RST_RPU_A, CORE0_RESET, 0, 1)
REG32(RST_RPU_B, 0x314)
    FIELD(RST_RPU_B, TOPRESET, 16, 1)
    FIELD(RST_RPU_B, CORE1_POR, 9, 1)
    FIELD(RST_RPU_B, CORE0_POR, 8, 1)
    FIELD(RST_RPU_B, CORE1_RESET, 1, 1)
    FIELD(RST_RPU_B, CORE0_RESET, 0, 1)
REG32(RST_RPU_C, 0x318)
    FIELD(RST_RPU_C, TOPRESET, 16, 1)
    FIELD(RST_RPU_C, CORE1_POR, 9, 1)
    FIELD(RST_RPU_C, CORE0_POR, 8, 1)
    FIELD(RST_RPU_C, CORE1_RESET, 1, 1)
    FIELD(RST_RPU_C, CORE0_RESET, 0, 1)
REG32(RST_RPU_D, 0x31c)
    FIELD(RST_RPU_D, TOPRESET, 16, 1)
    FIELD(RST_RPU_D, CORE1_POR, 9, 1)
    FIELD(RST_RPU_D, CORE0_POR, 8, 1)
    FIELD(RST_RPU_D, CORE1_RESET, 1, 1)
    FIELD(RST_RPU_D, CORE0_RESET, 0, 1)
REG32(RST_RPU_E, 0x320)
    FIELD(RST_RPU_E, TOPRESET, 16, 1)
    FIELD(RST_RPU_E, CORE1_POR, 9, 1)
    FIELD(RST_RPU_E, CORE0_POR, 8, 1)
    FIELD(RST_RPU_E, CORE1_RESET, 1, 1)
    FIELD(RST_RPU_E, CORE0_RESET, 0, 1)
REG32(RST_RPU_GD_0, 0x324)
    FIELD(RST_RPU_GD_0, RESET, 1, 1)
    FIELD(RST_RPU_GD_0, TOP_RESET, 0, 1)
REG32(RST_RPU_GD_1, 0x328)
    FIELD(RST_RPU_GD_1, RESET, 1, 1)
    FIELD(RST_RPU_GD_1, TOP_RESET, 0, 1)
REG32(RST_ASU_GD, 0x32c)
    FIELD(RST_ASU_GD, RESET, 1, 1)
    FIELD(RST_ASU_GD, TOP_RESET, 0, 1)
REG32(RST_ADMA, 0x334)
    FIELD(RST_ADMA, RESET, 0, 1)
REG32(RST_SDMA, 0x338)
    FIELD(RST_SDMA, RESET, 0, 1)
REG32(RST_GEM0, 0x33c)
    FIELD(RST_GEM0, RESET, 0, 1)
REG32(RST_GEM1, 0x340)
    FIELD(RST_GEM1, RESET, 0, 1)
REG32(RST_USB0, 0x348)
    FIELD(RST_USB0, RESET, 0, 1)
REG32(RST_USB1, 0x34c)
    FIELD(RST_USB1, RESET, 0, 1)
REG32(RST_UART0, 0x350)
    FIELD(RST_UART0, RESET, 0, 1)
REG32(RST_UART1, 0x354)
    FIELD(RST_UART1, RESET, 0, 1)
REG32(RST_SPI0, 0x358)
    FIELD(RST_SPI0, RESET, 0, 1)
REG32(RST_SPI1, 0x35c)
    FIELD(RST_SPI1, RESET, 0, 1)
REG32(RST_CAN0, 0x360)
    FIELD(RST_CAN0, RESET, 0, 1)
REG32(RST_CAN1, 0x364)
    FIELD(RST_CAN1, RESET, 0, 1)
REG32(RST_CAN2, 0x368)
    FIELD(RST_CAN2, RESET, 0, 1)
REG32(RST_CAN3, 0x36c)
    FIELD(RST_CAN3, RESET, 0, 1)
REG32(RST_I3C0, 0x374)
    FIELD(RST_I3C0, RESET, 0, 1)
REG32(RST_I3C1, 0x378)
    FIELD(RST_I3C1, RESET, 0, 1)
REG32(RST_I3C2, 0x37c)
    FIELD(RST_I3C2, RESET, 0, 1)
REG32(RST_I3C3, 0x380)
    FIELD(RST_I3C3, RESET, 0, 1)
REG32(RST_I3C4, 0x384)
    FIELD(RST_I3C4, RESET, 0, 1)
REG32(RST_I3C5, 0x388)
    FIELD(RST_I3C5, RESET, 0, 1)
REG32(RST_I3C6, 0x38c)
    FIELD(RST_I3C6, RESET, 0, 1)
REG32(RST_I3C7, 0x390)
    FIELD(RST_I3C7, RESET, 0, 1)
REG32(RST_DBG_LPX, 0x398)
    FIELD(RST_DBG_LPX, RESET_HSDP, 1, 1)
    FIELD(RST_DBG_LPX, RESET, 0, 1)
REG32(RST_GPIO, 0x39c)
    FIELD(RST_GPIO, RESET, 0, 1)
REG32(RST_TTC, 0x3a0)
    FIELD(RST_TTC, TTC7_RESET, 7, 1)
    FIELD(RST_TTC, TTC6_RESET, 6, 1)
    FIELD(RST_TTC, TTC5_RESET, 5, 1)
    FIELD(RST_TTC, TTC4_RESET, 4, 1)
    FIELD(RST_TTC, TTC3_RESET, 3, 1)
    FIELD(RST_TTC, TTC2_RESET, 2, 1)
    FIELD(RST_TTC, TTC1_RESET, 1, 1)
    FIELD(RST_TTC, TTC0_RESET, 0, 1)
REG32(RST_TIMESTAMP, 0x3a4)
    FIELD(RST_TIMESTAMP, RESET, 0, 1)
REG32(RST_SWDT0, 0x3a8)
    FIELD(RST_SWDT0, RESET, 0, 1)
REG32(RST_SWDT1, 0x3ac)
    FIELD(RST_SWDT1, RESET, 0, 1)
REG32(RST_SWDT2, 0x3b0)
    FIELD(RST_SWDT2, RESET, 0, 1)
REG32(RST_SWDT3, 0x3b4)
    FIELD(RST_SWDT3, RESET, 0, 1)
REG32(RST_SWDT4, 0x3b8)
    FIELD(RST_SWDT4, RESET, 0, 1)
REG32(RST_IPI, 0x3bc)
    FIELD(RST_IPI, RESET, 0, 1)
REG32(RST_SYSMON, 0x3c0)
    FIELD(RST_SYSMON, CFG_RST, 0, 1)
REG32(ASU_MB_RST_MODE, 0x3c4)
    FIELD(ASU_MB_RST_MODE, WAKEUP, 2, 1)
    FIELD(ASU_MB_RST_MODE, RST_MODE, 0, 2)
REG32(FPX_TOPSW_MUX_CTRL, 0x3c8)
    FIELD(FPX_TOPSW_MUX_CTRL, SELECT, 0, 1)
REG32(RST_FPX, 0x3d0)
    FIELD(RST_FPX, SRST, 1, 1)
    FIELD(RST_FPX, POR, 0, 1)
REG32(RST_MMI, 0x3d4)
    FIELD(RST_MMI, POR, 0, 1)
REG32(RST_OCM, 0x3d8)
    FIELD(RST_OCM, RESET_OCM3, 3, 1)
    FIELD(RST_OCM, RESET_OCM2, 2, 1)
    FIELD(RST_OCM, RESET_OCM1, 1, 1)
    FIELD(RST_OCM, RESET_OCM0, 0, 1)

#define PSXC_CRL_R_MAX (R_RST_OCM + 1)

typedef struct PSXC_CRL {
    SysBusDevice parent_obj;
    MemoryRegion iomem;

    qemu_irq rst_adma;
    qemu_irq rst_gem[2];
    qemu_irq rst_usb[2];
    qemu_irq rst_uart[2];
    qemu_irq rst_spi[2];
    qemu_irq rst_can[4];
    qemu_irq rst_i3c[8];
    qemu_irq rst_dbg_lpd;
    qemu_irq rst_dbg_lpd_hsdp;
    qemu_irq rst_gpio;
    qemu_irq rst_ttc[8];
    qemu_irq rst_timestamp;
    qemu_irq rst_swdt[2];
    qemu_irq rst_ocm[4];
    qemu_irq rst_ipi;
    qemu_irq rst_sysmon;
    qemu_irq rst_fpd_por;
    qemu_irq rst_fpd_srst;
    qemu_irq asu_sleep;
    qemu_irq asu_wakeup;
    qemu_irq asu_reset;
    qemu_irq rpu_rst[10];

    bool por_done;
    uint32_t regs[PSXC_CRL_R_MAX];
    RegisterInfo regs_info[PSXC_CRL_R_MAX];

    bool in_reset_enter;
} PSXC_CRL;

#define PROPAGATE_GPIO(reg, f, irq) { \
    bool val = ARRAY_FIELD_EX32(s->regs, reg, f); \
    qemu_set_irq(irq, val); \
}

static void crl_rst_update(PSXC_CRL *s)
{
    bool val;

    /*
     * It is forbidden by the API to have effect on other devices while in reset
     * enter.
     */
    if (s->in_reset_enter) {
        return;
    }

    PROPAGATE_GPIO(RST_RPU_A, CORE0_RESET, s->rpu_rst[0]);
    PROPAGATE_GPIO(RST_RPU_A, CORE1_RESET, s->rpu_rst[1]);
    PROPAGATE_GPIO(RST_RPU_B, CORE0_RESET, s->rpu_rst[2]);
    PROPAGATE_GPIO(RST_RPU_B, CORE1_RESET, s->rpu_rst[3]);
    PROPAGATE_GPIO(RST_RPU_C, CORE0_RESET, s->rpu_rst[4]);
    PROPAGATE_GPIO(RST_RPU_C, CORE1_RESET, s->rpu_rst[5]);
    PROPAGATE_GPIO(RST_RPU_D, CORE0_RESET, s->rpu_rst[6]);
    PROPAGATE_GPIO(RST_RPU_D, CORE1_RESET, s->rpu_rst[7]);
    PROPAGATE_GPIO(RST_RPU_E, CORE0_RESET, s->rpu_rst[8]);
    PROPAGATE_GPIO(RST_RPU_E, CORE1_RESET, s->rpu_rst[9]);

    PROPAGATE_GPIO(RST_ADMA, RESET, s->rst_adma);
    PROPAGATE_GPIO(RST_GEM0, RESET, s->rst_gem[0]);
    PROPAGATE_GPIO(RST_GEM1, RESET, s->rst_gem[1]);
    PROPAGATE_GPIO(RST_USB0, RESET, s->rst_usb[0]);
    PROPAGATE_GPIO(RST_UART0, RESET, s->rst_uart[0]);
    PROPAGATE_GPIO(RST_UART1, RESET, s->rst_uart[1]);
    PROPAGATE_GPIO(RST_SPI0, RESET, s->rst_spi[0]);
    PROPAGATE_GPIO(RST_SPI1, RESET, s->rst_spi[1]);
    PROPAGATE_GPIO(RST_CAN0, RESET, s->rst_can[0]);
    PROPAGATE_GPIO(RST_CAN1, RESET, s->rst_can[1]);
    PROPAGATE_GPIO(RST_I3C0, RESET, s->rst_i3c[0]);
    PROPAGATE_GPIO(RST_I3C1, RESET, s->rst_i3c[1]);
    PROPAGATE_GPIO(RST_DBG_LPX, RESET, s->rst_dbg_lpd);
    PROPAGATE_GPIO(RST_DBG_LPX, RESET_HSDP, s->rst_dbg_lpd_hsdp);
    PROPAGATE_GPIO(RST_GPIO, RESET, s->rst_gpio);
    PROPAGATE_GPIO(RST_TTC, TTC0_RESET, s->rst_ttc[0]);
    PROPAGATE_GPIO(RST_TTC, TTC1_RESET, s->rst_ttc[1]);
    PROPAGATE_GPIO(RST_TTC, TTC2_RESET, s->rst_ttc[2]);
    PROPAGATE_GPIO(RST_TTC, TTC3_RESET, s->rst_ttc[3]);
    PROPAGATE_GPIO(RST_TIMESTAMP, RESET, s->rst_timestamp);
    PROPAGATE_GPIO(RST_SWDT0, RESET, s->rst_swdt[0]);
    PROPAGATE_GPIO(RST_OCM, RESET_OCM0, s->rst_ocm[0]);
    PROPAGATE_GPIO(RST_IPI, RESET, s->rst_ipi);
    PROPAGATE_GPIO(RST_SYSMON, CFG_RST, s->rst_sysmon);
    PROPAGATE_GPIO(RST_FPX, POR, s->rst_fpd_por);
    PROPAGATE_GPIO(RST_FPX, SRST, s->rst_fpd_srst);
    PROPAGATE_GPIO(RST_USB1, RESET, s->rst_usb[1]);
    PROPAGATE_GPIO(RST_CAN2, RESET, s->rst_can[2]);
    PROPAGATE_GPIO(RST_CAN3, RESET, s->rst_can[3]);
    PROPAGATE_GPIO(RST_I3C2, RESET, s->rst_i3c[2]);
    PROPAGATE_GPIO(RST_I3C3, RESET, s->rst_i3c[3]);
    PROPAGATE_GPIO(RST_I3C4, RESET, s->rst_i3c[4]);
    PROPAGATE_GPIO(RST_I3C5, RESET, s->rst_i3c[5]);
    PROPAGATE_GPIO(RST_I3C6, RESET, s->rst_i3c[6]);
    PROPAGATE_GPIO(RST_I3C7, RESET, s->rst_i3c[7]);
    PROPAGATE_GPIO(RST_TTC, TTC4_RESET, s->rst_ttc[4]);
    PROPAGATE_GPIO(RST_TTC, TTC5_RESET, s->rst_ttc[5]);
    PROPAGATE_GPIO(RST_TTC, TTC6_RESET, s->rst_ttc[6]);
    PROPAGATE_GPIO(RST_TTC, TTC7_RESET, s->rst_ttc[7]);
    PROPAGATE_GPIO(RST_SWDT1, RESET, s->rst_swdt[1]);
    PROPAGATE_GPIO(RST_OCM, RESET_OCM1, s->rst_ocm[1]);
    PROPAGATE_GPIO(RST_OCM, RESET_OCM2, s->rst_ocm[2]);
    PROPAGATE_GPIO(RST_OCM, RESET_OCM3, s->rst_ocm[3]);

    val = ARRAY_FIELD_EX32(s->regs, ASU_MB_RST_MODE, WAKEUP);
    if (val && !s->por_done) {
        s->por_done = true;
        qemu_set_irq(s->asu_reset, 0);
    }
    qemu_set_irq(s->asu_sleep, !val);
    qemu_set_irq(s->asu_wakeup, val);
}

static void crl_rst_postw(RegisterInfo *reg, uint64_t val)
{
    PSXC_CRL *s = XILINX_PSXC_CRL(reg->opaque);

    crl_rst_update(s);
}

static const RegisterAccessInfo psxc_crl_regs_info[] = {
    {   .name = "ERR_CTRL",  .addr = A_ERR_CTRL,
        .reset = 0x1,
    },{ .name = "WPROT",  .addr = A_WPROT,
    },{ .name = "RPLL_CTRL",  .addr = A_RPLL_CTRL,
        .reset = 0x24809,
        .rsvd = 0xf88c00f6,
    },{ .name = "RPLL_CFG",  .addr = A_RPLL_CFG,
        .reset = 0x7e5dcc6c,
        .rsvd = 0x1801210,
    },{ .name = "FLXPLL_CTRL",  .addr = A_FLXPLL_CTRL,
        .reset = 0x24809,
        .rsvd = 0xf88c00f6,
    },{ .name = "FLXPLL_CFG",  .addr = A_FLXPLL_CFG,
        .reset = 0x7e5dcc6c,
        .rsvd = 0x1801210,
    },{ .name = "PLL_STATUS",  .addr = A_PLL_STATUS,
        .reset = 0xf,
        .rsvd = 0xf0,
        .ro = 0xf,
    },{ .name = "RPLL_TO_XPD_CTRL",  .addr = A_RPLL_TO_XPD_CTRL,
        .reset = 0x2000100,
        .rsvd = 0xfdfc00ff,
    },{ .name = "LPX_TOP_SWITCH_CTRL",  .addr = A_LPX_TOP_SWITCH_CTRL,
        .reset = 0xe000300,
        .rsvd = 0xf1fc00f8,
    },{ .name = "LPX_LSBUS_CLK_CTRL",  .addr = A_LPX_LSBUS_CLK_CTRL,
        .reset = 0x2000800,
        .rsvd = 0xfdfc00f8,
    },{ .name = "RPU_CLK_CTRL",  .addr = A_RPU_CLK_CTRL,
        .reset = 0x3f00300,
        .rsvd = 0xfc0c00f8,
    },{ .name = "OCM_CLK_CTRL",  .addr = A_OCM_CLK_CTRL,
        .reset = 0x1e00000,
        .rsvd = 0xfe1fffff,
    },{ .name = "IOU_SWITCH_CLK_CTRL",  .addr = A_IOU_SWITCH_CLK_CTRL,
        .reset = 0x2000500,
        .rsvd = 0xfdfc00f8,
    },{ .name = "GEM0_REF_CTRL",  .addr = A_GEM0_REF_CTRL,
        .reset = 0xe000a00,
        .rsvd = 0xf1fc00f8,
    },{ .name = "GEM1_REF_CTRL",  .addr = A_GEM1_REF_CTRL,
        .reset = 0xe000a00,
        .rsvd = 0xf1fc00f8,
    },{ .name = "GEM_TSU_REF_CLK_CTRL",  .addr = A_GEM_TSU_REF_CLK_CTRL,
        .reset = 0x300,
        .rsvd = 0xfdfc00f8,
    },{ .name = "USB0_BUS_REF_CLK_CTRL",  .addr = A_USB0_BUS_REF_CLK_CTRL,
        .reset = 0x2001900,
        .rsvd = 0xfdfc00f8,
    },{ .name = "USB1_BUS_REF_CLK_CTRL",  .addr = A_USB1_BUS_REF_CLK_CTRL,
        .reset = 0x2001900,
        .rsvd = 0xfdfc00f8,
    },{ .name = "UART0_REF_CLK_CTRL",  .addr = A_UART0_REF_CLK_CTRL,
        .reset = 0xc00,
        .rsvd = 0xfdfc00f8,
    },{ .name = "UART1_REF_CLK_CTRL",  .addr = A_UART1_REF_CLK_CTRL,
        .reset = 0xc00,
        .rsvd = 0xfdfc00f8,
    },{ .name = "SPI0_REF_CLK_CTRL",  .addr = A_SPI0_REF_CLK_CTRL,
        .reset = 0x600,
        .rsvd = 0xfdfc00f8,
    },{ .name = "SPI1_REF_CLK_CTRL",  .addr = A_SPI1_REF_CLK_CTRL,
        .reset = 0x600,
        .rsvd = 0xfdfc00f8,
    },{ .name = "CAN0_REF_2X_CTRL",  .addr = A_CAN0_REF_2X_CTRL,
        .reset = 0xc00,
        .rsvd = 0xfdfc00f8,
    },{ .name = "CAN1_REF_2X_CTRL",  .addr = A_CAN1_REF_2X_CTRL,
        .reset = 0xc00,
        .rsvd = 0xfdfc00f8,
    },{ .name = "CAN2_REF_2X_CTRL",  .addr = A_CAN2_REF_2X_CTRL,
        .reset = 0xc00,
        .rsvd = 0xfdfc00f8,
    },{ .name = "CAN3_REF_2X_CTRL",  .addr = A_CAN3_REF_2X_CTRL,
        .reset = 0xc00,
        .rsvd = 0xfdfc00f8,
    },{ .name = "I3C0_REF_CTRL",  .addr = A_I3C0_REF_CTRL,
        .reset = 0x2000c00,
        .rsvd = 0xfdfc00f8,
    },{ .name = "I3C1_REF_CTRL",  .addr = A_I3C1_REF_CTRL,
        .reset = 0x2000c00,
        .rsvd = 0xfdfc00f8,
    },{ .name = "I3C2_REF_CTRL",  .addr = A_I3C2_REF_CTRL,
        .reset = 0x2000c00,
        .rsvd = 0xfdfc00f8,
    },{ .name = "I3C3_REF_CTRL",  .addr = A_I3C3_REF_CTRL,
        .reset = 0x2000c00,
        .rsvd = 0xfdfc00f8,
    },{ .name = "I3C4_REF_CTRL",  .addr = A_I3C4_REF_CTRL,
        .reset = 0x2000c00,
        .rsvd = 0xfdfc00f8,
    },{ .name = "I3C5_REF_CTRL",  .addr = A_I3C5_REF_CTRL,
        .reset = 0x2000c00,
        .rsvd = 0xfdfc00f8,
    },{ .name = "I3C6_REF_CTRL",  .addr = A_I3C6_REF_CTRL,
        .reset = 0x2000c00,
        .rsvd = 0xfdfc00f8,
    },{ .name = "I3C7_REF_CTRL",  .addr = A_I3C7_REF_CTRL,
        .reset = 0x2000c00,
        .rsvd = 0xfdfc00f8,
    },{ .name = "DBG_LPX_CTRL",  .addr = A_DBG_LPX_CTRL,
        .reset = 0x300,
        .rsvd = 0xfdfc00f8,
    },{ .name = "TIMESTAMP_REF_CTRL",  .addr = A_TIMESTAMP_REF_CTRL,
        .reset = 0x2000c00,
        .rsvd = 0xfdfc00f8,
    },{ .name = "SAFETY_CHK",  .addr = A_SAFETY_CHK,
    },{ .name = "ASU_CLK_CTRL",  .addr = A_ASU_CLK_CTRL,
        .reset = 0x2000f04,
        .rsvd = 0xfdfc00f8,
    },{ .name = "DBG_TSTMP_CLK_CTRL",  .addr = A_DBG_TSTMP_CLK_CTRL,
        .reset = 0x300,
        .rsvd = 0xfdfc00f8,
    },{ .name = "MMI_TOPSW_CLK_CTRL",  .addr = A_MMI_TOPSW_CLK_CTRL,
        .reset = 0x2000300,
        .rsvd = 0xfdfc00f8,
    },{ .name = "WWDT_PLL_CLK_CTRL",  .addr = A_WWDT_PLL_CLK_CTRL,
        .reset = 0xc00,
        .rsvd = 0xfffc00f8,
    },{ .name = "RCLK_CTRL",  .addr = A_RCLK_CTRL,
        .rsvd = 0xc040,
    },{ .name = "RST_RPU_A",  .addr = A_RST_RPU_A,
        .reset = 0x10303,
        .rsvd = 0xfffefcfc,
        .post_write = crl_rst_postw,
    },{ .name = "RST_RPU_B",  .addr = A_RST_RPU_B,
        .reset = 0x10303,
        .rsvd = 0xfffefcfc,
        .post_write = crl_rst_postw,
    },{ .name = "RST_RPU_C",  .addr = A_RST_RPU_C,
        .reset = 0x10303,
        .rsvd = 0xfffefcfc,
        .post_write = crl_rst_postw,
    },{ .name = "RST_RPU_D",  .addr = A_RST_RPU_D,
        .reset = 0x10303,
        .rsvd = 0xfffefcfc,
        .post_write = crl_rst_postw,
    },{ .name = "RST_RPU_E",  .addr = A_RST_RPU_E,
        .reset = 0x10303,
        .rsvd = 0xfffefcfc,
        .post_write = crl_rst_postw,
    },{ .name = "RST_RPU_GD_0",  .addr = A_RST_RPU_GD_0,
        .reset = 0x3,
        .post_write = crl_rst_postw,
    },{ .name = "RST_RPU_GD_1",  .addr = A_RST_RPU_GD_1,
        .reset = 0x3,
        .post_write = crl_rst_postw,
    },{ .name = "RST_ASU_GD",  .addr = A_RST_ASU_GD,
        .reset = 0x3,
        .post_write = crl_rst_postw,
    },{ .name = "RST_ADMA",  .addr = A_RST_ADMA,
        .reset = 0x1,
        .post_write = crl_rst_postw,
    },{ .name = "RST_SDMA",  .addr = A_RST_SDMA,
        .post_write = crl_rst_postw,
        .reset = 0x1,
    },{ .name = "RST_GEM0",  .addr = A_RST_GEM0,
        .reset = 0x1,
        .post_write = crl_rst_postw,
    },{ .name = "RST_GEM1",  .addr = A_RST_GEM1,
        .reset = 0x1,
        .post_write = crl_rst_postw,
    },{ .name = "RST_USB0",  .addr = A_RST_USB0,
        .reset = 0x1,
        .post_write = crl_rst_postw,
    },{ .name = "RST_USB1",  .addr = A_RST_USB1,
        .reset = 0x1,
        .post_write = crl_rst_postw,
    },{ .name = "RST_UART0",  .addr = A_RST_UART0,
        .reset = 0x1,
        .post_write = crl_rst_postw,
    },{ .name = "RST_UART1",  .addr = A_RST_UART1,
        .reset = 0x1,
        .post_write = crl_rst_postw,
    },{ .name = "RST_SPI0",  .addr = A_RST_SPI0,
        .reset = 0x1,
        .post_write = crl_rst_postw,
    },{ .name = "RST_SPI1",  .addr = A_RST_SPI1,
        .reset = 0x1,
        .post_write = crl_rst_postw,
    },{ .name = "RST_CAN0",  .addr = A_RST_CAN0,
        .reset = 0x1,
        .post_write = crl_rst_postw,
    },{ .name = "RST_CAN1",  .addr = A_RST_CAN1,
        .reset = 0x1,
        .post_write = crl_rst_postw,
    },{ .name = "RST_CAN2",  .addr = A_RST_CAN2,
        .reset = 0x1,
        .post_write = crl_rst_postw,
    },{ .name = "RST_CAN3",  .addr = A_RST_CAN3,
        .reset = 0x1,
        .post_write = crl_rst_postw,
    },{ .name = "RST_I3C0",  .addr = A_RST_I3C0,
        .reset = 0x1,
        .post_write = crl_rst_postw,
    },{ .name = "RST_I3C1",  .addr = A_RST_I3C1,
        .reset = 0x1,
        .post_write = crl_rst_postw,
    },{ .name = "RST_I3C2",  .addr = A_RST_I3C2,
        .reset = 0x1,
        .post_write = crl_rst_postw,
    },{ .name = "RST_I3C3",  .addr = A_RST_I3C3,
        .reset = 0x1,
        .post_write = crl_rst_postw,
    },{ .name = "RST_I3C4",  .addr = A_RST_I3C4,
        .reset = 0x1,
        .post_write = crl_rst_postw,
    },{ .name = "RST_I3C5",  .addr = A_RST_I3C5,
        .reset = 0x1,
        .post_write = crl_rst_postw,
    },{ .name = "RST_I3C6",  .addr = A_RST_I3C6,
        .reset = 0x1,
        .post_write = crl_rst_postw,
    },{ .name = "RST_I3C7",  .addr = A_RST_I3C7,
        .reset = 0x1,
        .post_write = crl_rst_postw,
    },{ .name = "RST_DBG_LPX",  .addr = A_RST_DBG_LPX,
        .reset = 0x3,
        .rsvd = 0xfc,
        .post_write = crl_rst_postw,
    },{ .name = "RST_GPIO",  .addr = A_RST_GPIO,
        .reset = 0x1,
        .post_write = crl_rst_postw,
    },{ .name = "RST_TTC",  .addr = A_RST_TTC,
        .reset = 0xff,
        .post_write = crl_rst_postw,
    },{ .name = "RST_TIMESTAMP",  .addr = A_RST_TIMESTAMP,
        .reset = 0x1,
        .post_write = crl_rst_postw,
    },{ .name = "RST_SWDT0",  .addr = A_RST_SWDT0,
        .reset = 0x1,
        .post_write = crl_rst_postw,
    },{ .name = "RST_SWDT1",  .addr = A_RST_SWDT1,
        .reset = 0x1,
        .post_write = crl_rst_postw,
    },{ .name = "RST_SWDT2",  .addr = A_RST_SWDT2,
        .post_write = crl_rst_postw,
        .reset = 0x1,
    },{ .name = "RST_SWDT3",  .addr = A_RST_SWDT3,
        .post_write = crl_rst_postw,
        .reset = 0x1,
    },{ .name = "RST_SWDT4",  .addr = A_RST_SWDT4,
        .post_write = crl_rst_postw,
        .reset = 0x1,
    },{ .name = "RST_IPI",  .addr = A_RST_IPI,
        .post_write = crl_rst_postw,
    },{ .name = "RST_SYSMON",  .addr = A_RST_SYSMON,
        .post_write = crl_rst_postw,
    },{ .name = "ASU_MB_RST_MODE",  .addr = A_ASU_MB_RST_MODE,
        .reset = 0x1,
        .rsvd = 0xf8,
        .post_write = crl_rst_postw,
    },{ .name = "FPX_TOPSW_MUX_CTRL",  .addr = A_FPX_TOPSW_MUX_CTRL,
        .reset = 0x1,
    },{ .name = "RST_FPX",  .addr = A_RST_FPX,
        .post_write = crl_rst_postw,
        .reset = 0x3,
    },{ .name = "RST_MMI",  .addr = A_RST_MMI,
        .post_write = crl_rst_postw,
        .reset = 0x1,
    },{ .name = "RST_OCM",  .addr = A_RST_OCM,
        .post_write = crl_rst_postw,
    }
};

static void psxc_crl_reset_enter(Object *obj, ResetType type)
{
    PSXC_CRL *s = XILINX_PSXC_CRL(obj);
    unsigned int i;

    s->in_reset_enter = true;

    for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
        register_reset(&s->regs_info[i]);
    }

    s->in_reset_enter = false;
}

static void psxc_crl_reset_hold(Object *obj)
{
    PSXC_CRL *s = XILINX_PSXC_CRL(obj);

    /* Now GPIO can be updated.  */
    crl_rst_update(s);
}

static const MemoryRegionOps psxc_crl_ops = {
    .read = register_read_memory,
    .write = register_write_memory,
    .endianness = DEVICE_LITTLE_ENDIAN,
    .valid = {
        .min_access_size = 4,
        .max_access_size = 4,
    },
};

static void psxc_crl_realize(DeviceState *dev, Error **errp)
{
    /* Delete this if you don't need it */
}

static void psxc_crl_init(Object *obj)
{
    PSXC_CRL *s = XILINX_PSXC_CRL(obj);
    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
    RegisterInfoArray *reg_array;

    memory_region_init(&s->iomem, obj,
                       TYPE_XILINX_PSXC_CRL, PSXC_CRL_R_MAX * 4);
    reg_array =
        register_init_block32(DEVICE(obj), psxc_crl_regs_info,
                              ARRAY_SIZE(psxc_crl_regs_info),
                              s->regs_info, s->regs,
                              &psxc_crl_ops,
                              XILINX_PSXC_CRL_ERR_DEBUG,
                              PSXC_CRL_R_MAX * 4);
    memory_region_add_subregion(&s->iomem,
                                0x0,
                                &reg_array->mem);
    sysbus_init_mmio(sbd, &s->iomem);

    qdev_init_gpio_out_named(DEVICE(obj), &s->rst_adma, "rst-adma", 1);
    qdev_init_gpio_out_named(DEVICE(obj), s->rst_gem, "rst-gem", 2);
    qdev_init_gpio_out_named(DEVICE(obj), &s->rst_usb[0], "rst-usb0", 1);
    qdev_init_gpio_out_named(DEVICE(obj), s->rst_uart, "rst-uart", 2);
    qdev_init_gpio_out_named(DEVICE(obj), s->rst_spi, "rst-spi", 2);
    qdev_init_gpio_out_named(DEVICE(obj), &s->rst_can[0], "rst-can", 2);
    qdev_init_gpio_out_named(DEVICE(obj), s->rst_i3c, "rst-i3c", 2);
    qdev_init_gpio_out_named(DEVICE(obj), &s->rst_dbg_lpd, "rst-dbg-lpd", 1);
    qdev_init_gpio_out_named(DEVICE(obj), &s->rst_dbg_lpd_hsdp,
                             "rst-dbg-lpd-hsdp", 1);
    qdev_init_gpio_out_named(DEVICE(obj), &s->rst_gpio, "rst-gpio", 1);
    qdev_init_gpio_out_named(DEVICE(obj), s->rst_ttc, "rst-ttc", 4);
    qdev_init_gpio_out_named(DEVICE(obj), &s->rst_timestamp,
                             "rst-timestamp", 1);
    qdev_init_gpio_out_named(DEVICE(obj), &s->rst_swdt[0], "rst-swdt0", 1);
    qdev_init_gpio_out_named(DEVICE(obj), &s->rst_ocm[0], "rst-ocm", 1);
    qdev_init_gpio_out_named(DEVICE(obj), &s->rst_ipi, "rst-ipi", 1);
    qdev_init_gpio_out_named(DEVICE(obj), &s->rst_sysmon,
                             "rst-sysmon-cfg", 1);
    qdev_init_gpio_out_named(DEVICE(obj), &s->rst_fpd_por, "rst-fpd-por", 1);
    qdev_init_gpio_out_named(DEVICE(obj), &s->rst_fpd_srst, "rst-fpd-srst", 1);
    qdev_init_gpio_out_named(DEVICE(obj), &s->asu_sleep, "asu-sleep", 1);
    qdev_init_gpio_out_named(DEVICE(obj), &s->asu_wakeup, "asu-wakeup", 1);
    qdev_init_gpio_out_named(DEVICE(obj), &s->asu_reset, "asu-rst", 1);
    qdev_init_gpio_out_named(DEVICE(obj), s->rpu_rst, "rpu-rst", 10);
    qdev_init_gpio_out_named(DEVICE(obj), &s->rst_usb[1], "rst-usb1", 1);
    qdev_init_gpio_out_named(DEVICE(obj), &s->rst_can[2], "rst-can2-3", 2);
    qdev_init_gpio_out_named(DEVICE(obj), &s->rst_i3c[2], "rst-i3c2-7", 6);
    qdev_init_gpio_out_named(DEVICE(obj), &s->rst_ttc[4], "rst-ttc4-7", 4);
    qdev_init_gpio_out_named(DEVICE(obj), &s->rst_swdt[1], "rst-swdt1", 1);
    qdev_init_gpio_out_named(DEVICE(obj), &s->rst_ocm[1], "rst-ocm1-3", 3);
}

static const VMStateDescription vmstate_psxc_crl = {
    .name = TYPE_XILINX_PSXC_CRL,
    .version_id = 1,
    .minimum_version_id = 1,
    .fields = (VMStateField[]) {
        VMSTATE_UINT32_ARRAY(regs, PSXC_CRL, PSXC_CRL_R_MAX),
        VMSTATE_END_OF_LIST(),
    }
};

static const FDTGenericGPIOSet crl_gpios[] = {
    {
      .names = &fdt_generic_gpio_name_set_gpio,
      .gpios = (FDTGenericGPIOConnection[]) {
        { .name = "rst-adma", .fdt_index = 0, .range = 1 },
        { .name = "rst-gem", .fdt_index = 1, .range = 2 },
        { .name = "rst-usb0", .fdt_index = 4, .range = 1 },
        { .name = "rst-uart", .fdt_index = 5, .range = 2 },
        { .name = "rst-spi", .fdt_index = 7, .range = 2 },
        { .name = "rst-can", .fdt_index = 9, .range = 2 },
        { .name = "rst-i3c", .fdt_index = 11, .range = 2 },
        { .name = "rst-dbg-lpd", .fdt_index = 13, .range = 1 },
        { .name = "rst-dbg-lpd-hsdp", .fdt_index = 14, .range = 1 },
        { .name = "rst-gpio", .fdt_index = 17, .range = 1 },
        { .name = "rst-ttc", .fdt_index = 18, .range = 4 },
        { .name = "rst-timestamp", .fdt_index = 22, .range = 1 },
        { .name = "rst-swdt", .fdt_index = 23, .range = 1 },
        { .name = "rst-ocm", .fdt_index = 24, .range = 1 },
        { .name = "rst-ipi", .fdt_index = 25, .range = 1 },
        { .name = "rst-sysmon", .fdt_index = 26, .range = 1 },
        { .name = "rst-fpd-por", .fdt_index = 28, .range = 1 },
        { .name = "rst-fpd-srst", .fdt_index = 29, .range = 1 },
        { .name = "asu-sleep", .fdt_index = 30, .range = 1 },
        { .name = "asu-wakeup", .fdt_index = 31, .range = 1 },
        { .name = "asu-rst", .fdt_index = 34, .range = 1 },
        { .name = "rpu-rst", .fdt_index = 35, .range = 10},
        { .name = "rst-usb1", .fdt_index = 45, .range = 1},
        { .name = "rst-can2-3", .fdt_index = 46, .range = 2},
        { .name = "rst-i3c2-7", .fdt_index = 48, .range = 6},
        { .name = "rst-ttc4-7", .fdt_index = 54, .range = 4},
        { .name = "rst-swdt1", .fdt_index = 58, .range = 1},
        { .name = "rst-ocm1-3", .fdt_index = 59, .range = 3},
        { },
      },
    },
    { },
};

static void psxc_crl_class_init(ObjectClass *klass, void *data)
{
    ResettableClass *rc = RESETTABLE_CLASS(klass);
    DeviceClass *dc = DEVICE_CLASS(klass);
    FDTGenericGPIOClass *fggc = FDT_GENERIC_GPIO_CLASS(klass);

    dc->realize = psxc_crl_realize;
    dc->vmsd = &vmstate_psxc_crl;
    rc->phases.enter = psxc_crl_reset_enter;
    rc->phases.hold = psxc_crl_reset_hold;
    fggc->controller_gpios = crl_gpios;
}

static const TypeInfo psxc_crl_info = {
    .name          = TYPE_XILINX_PSXC_CRL,
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(PSXC_CRL),
    .class_init    = psxc_crl_class_init,
    .instance_init = psxc_crl_init,
    .interfaces = (InterfaceInfo[]) {
        { TYPE_FDT_GENERIC_GPIO },
        { }
    },
};

static void psxc_crl_register_types(void)
{
    type_register_static(&psxc_crl_info);
}

type_init(psxc_crl_register_types)
