/*
 * QEMU model of the PSMX_LOCAL_REG This is the database for the PSMX Local Regs
 *
 * Copyright (c) 2022 Xilinx Inc.
 *
 * Autogenerated by xregqemu.py 2022-01-27.
 *
 * 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 "migration/vmstate.h"
#include "hw/irq.h"
#include "hw/fdt_generic_util.h"
#include "hw/arm/linux-boot-if.h"

#ifndef XILINX_PSMX_LOCAL_REG_ERR_DEBUG
#define XILINX_PSMX_LOCAL_REG_ERR_DEBUG 0
#endif

#define TYPE_XILINX_PSMX_LOCAL_REG "xlnx.psmx_local_reg"

#define XILINX_PSMX_LOCAL_REG(obj) \
     OBJECT_CHECK(PSMX_LOCAL_REG, (obj), TYPE_XILINX_PSMX_LOCAL_REG)

REG32(APU0_CORE0_PWR_CNTRL, 0x0)
    FIELD(APU0_CORE0_PWR_CNTRL, ISOLATION, 4, 1)
    FIELD(APU0_CORE0_PWR_CNTRL, PWR_GATES, 0, 4)
REG32(APU0_CORE0_PWR_STATUS, 0x4)
    FIELD(APU0_CORE0_PWR_STATUS, PWR_GATES, 0, 4)
REG32(APU0_CORE1_PWR_CNTRL, 0x8)
    FIELD(APU0_CORE1_PWR_CNTRL, ISOLATION, 4, 1)
    FIELD(APU0_CORE1_PWR_CNTRL, PWR_GATES, 0, 4)
REG32(APU0_CORE1_PWR_STATUS, 0xc)
    FIELD(APU0_CORE1_PWR_STATUS, PWR_GATES, 0, 4)
REG32(APU0_CORE2_PWR_CNTRL, 0x10)
    FIELD(APU0_CORE2_PWR_CNTRL, ISOLATION, 4, 1)
    FIELD(APU0_CORE2_PWR_CNTRL, PWR_GATES, 0, 4)
REG32(APU0_CORE2_PWR_STATUS, 0x14)
    FIELD(APU0_CORE2_PWR_STATUS, PWR_GATES, 0, 4)
REG32(APU0_CORE3_PWR_CNTRL, 0x18)
    FIELD(APU0_CORE3_PWR_CNTRL, ISOLATION, 4, 1)
    FIELD(APU0_CORE3_PWR_CNTRL, PWR_GATES, 0, 4)
REG32(APU0_CORE3_PWR_STATUS, 0x1c)
    FIELD(APU0_CORE3_PWR_STATUS, PWR_GATES, 0, 4)
REG32(APU1_CORE0_PWR_CNTRL, 0x20)
    FIELD(APU1_CORE0_PWR_CNTRL, ISOLATION, 4, 1)
    FIELD(APU1_CORE0_PWR_CNTRL, PWR_GATES, 0, 4)
REG32(APU1_CORE0_PWR_STATUS, 0x24)
    FIELD(APU1_CORE0_PWR_STATUS, PWR_GATES, 0, 4)
REG32(APU1_CORE1_PWR_CNTRL, 0x28)
    FIELD(APU1_CORE1_PWR_CNTRL, ISOLATION, 4, 1)
    FIELD(APU1_CORE1_PWR_CNTRL, PWR_GATES, 0, 4)
REG32(APU1_CORE1_PWR_STATUS, 0x2c)
    FIELD(APU1_CORE1_PWR_STATUS, PWR_GATES, 0, 4)
REG32(APU1_CORE2_PWR_CNTRL, 0x30)
    FIELD(APU1_CORE2_PWR_CNTRL, ISOLATION, 4, 1)
    FIELD(APU1_CORE2_PWR_CNTRL, PWR_GATES, 0, 4)
REG32(APU1_CORE2_PWR_STATUS, 0x34)
    FIELD(APU1_CORE2_PWR_STATUS, PWR_GATES, 0, 4)
REG32(APU1_CORE3_PWR_CNTRL, 0x38)
    FIELD(APU1_CORE3_PWR_CNTRL, ISOLATION, 4, 1)
    FIELD(APU1_CORE3_PWR_CNTRL, PWR_GATES, 0, 4)
REG32(APU1_CORE3_PWR_STATUS, 0x3c)
    FIELD(APU1_CORE3_PWR_STATUS, PWR_GATES, 0, 4)
REG32(APU2_CORE0_PWR_CNTRL, 0x40)
    FIELD(APU2_CORE0_PWR_CNTRL, ISOLATION, 4, 1)
    FIELD(APU2_CORE0_PWR_CNTRL, PWR_GATES, 0, 4)
REG32(APU2_CORE0_PWR_STATUS, 0x44)
    FIELD(APU2_CORE0_PWR_STATUS, PWR_GATES, 0, 4)
REG32(APU2_CORE1_PWR_CNTRL, 0x48)
    FIELD(APU2_CORE1_PWR_CNTRL, ISOLATION, 4, 1)
    FIELD(APU2_CORE1_PWR_CNTRL, PWR_GATES, 0, 4)
REG32(APU2_CORE1_PWR_STATUS, 0x4c)
    FIELD(APU2_CORE1_PWR_STATUS, PWR_GATES, 0, 4)
REG32(APU2_CORE2_PWR_CNTRL, 0x50)
    FIELD(APU2_CORE2_PWR_CNTRL, ISOLATION, 4, 1)
    FIELD(APU2_CORE2_PWR_CNTRL, PWR_GATES, 0, 4)
REG32(APU2_CORE2_PWR_STATUS, 0x54)
    FIELD(APU2_CORE2_PWR_STATUS, PWR_GATES, 0, 4)
REG32(APU2_CORE3_PWR_CNTRL, 0x58)
    FIELD(APU2_CORE3_PWR_CNTRL, ISOLATION, 4, 1)
    FIELD(APU2_CORE3_PWR_CNTRL, PWR_GATES, 0, 4)
REG32(APU2_CORE3_PWR_STATUS, 0x5c)
    FIELD(APU2_CORE3_PWR_STATUS, PWR_GATES, 0, 4)
REG32(APU3_CORE0_PWR_CNTRL, 0x60)
    FIELD(APU3_CORE0_PWR_CNTRL, ISOLATION, 4, 1)
    FIELD(APU3_CORE0_PWR_CNTRL, PWR_GATES, 0, 4)
REG32(APU3_CORE0_PWR_STATUS, 0x64)
    FIELD(APU3_CORE0_PWR_STATUS, PWR_GATES, 0, 4)
REG32(APU3_CORE1_PWR_CNTRL, 0x68)
    FIELD(APU3_CORE1_PWR_CNTRL, ISOLATION, 4, 1)
    FIELD(APU3_CORE1_PWR_CNTRL, PWR_GATES, 0, 4)
REG32(APU3_CORE1_PWR_STATUS, 0x6c)
    FIELD(APU3_CORE1_PWR_STATUS, PWR_GATES, 0, 4)
REG32(APU3_CORE2_PWR_CNTRL, 0x70)
    FIELD(APU3_CORE2_PWR_CNTRL, ISOLATION, 4, 1)
    FIELD(APU3_CORE2_PWR_CNTRL, PWR_GATES, 0, 4)
REG32(APU3_CORE2_PWR_STATUS, 0x74)
    FIELD(APU3_CORE2_PWR_STATUS, PWR_GATES, 0, 4)
REG32(APU3_CORE3_PWR_CNTRL, 0x78)
    FIELD(APU3_CORE3_PWR_CNTRL, ISOLATION, 4, 1)
    FIELD(APU3_CORE3_PWR_CNTRL, PWR_GATES, 0, 4)
REG32(APU3_CORE3_PWR_STATUS, 0x7c)
    FIELD(APU3_CORE3_PWR_STATUS, PWR_GATES, 0, 4)
REG32(RPU_A_CORE0_PWR_CNTRL, 0x100)
    FIELD(RPU_A_CORE0_PWR_CNTRL, ISOLATION, 4, 1)
    FIELD(RPU_A_CORE0_PWR_CNTRL, PWR_GATES, 0, 4)
REG32(RPU_A_CORE0_PWR_STATUS, 0x104)
    FIELD(RPU_A_CORE0_PWR_STATUS, PWR_GATES, 0, 4)
REG32(RPU_A_CORE1_PWR_CNTRL, 0x108)
    FIELD(RPU_A_CORE1_PWR_CNTRL, ISOLATION, 4, 1)
    FIELD(RPU_A_CORE1_PWR_CNTRL, PWR_GATES, 0, 4)
REG32(RPU_A_CORE1_PWR_STATUS, 0x10c)
    FIELD(RPU_A_CORE1_PWR_STATUS, PWR_GATES, 0, 4)
REG32(RPU_B_CORE0_PWR_CNTRL, 0x110)
    FIELD(RPU_B_CORE0_PWR_CNTRL, ISOLATION, 4, 1)
    FIELD(RPU_B_CORE0_PWR_CNTRL, PWR_GATES, 0, 4)
REG32(RPU_B_CORE0_PWR_STATUS, 0x114)
    FIELD(RPU_B_CORE0_PWR_STATUS, PWR_GATES, 0, 4)
REG32(RPU_B_CORE1_PWR_CNTRL, 0x118)
    FIELD(RPU_B_CORE1_PWR_CNTRL, ISOLATION, 4, 1)
    FIELD(RPU_B_CORE1_PWR_CNTRL, PWR_GATES, 0, 4)
REG32(RPU_B_CORE1_PWR_STATUS, 0x11c)
    FIELD(RPU_B_CORE1_PWR_STATUS, PWR_GATES, 0, 4)
REG32(APU0_DSU_L3_PWR_CNTRL, 0x150)
    FIELD(APU0_DSU_L3_PWR_CNTRL, LTDB, 8, 1)
    FIELD(APU0_DSU_L3_PWR_CNTRL, SF, 7, 1)
    FIELD(APU0_DSU_L3_PWR_CNTRL, VICTIM, 6, 1)
    FIELD(APU0_DSU_L3_PWR_CNTRL, DATA1, 5, 1)
    FIELD(APU0_DSU_L3_PWR_CNTRL, DATA0, 4, 1)
    FIELD(APU0_DSU_L3_PWR_CNTRL, TAG3, 3, 1)
    FIELD(APU0_DSU_L3_PWR_CNTRL, TAG2, 2, 1)
    FIELD(APU0_DSU_L3_PWR_CNTRL, TAG1, 1, 1)
    FIELD(APU0_DSU_L3_PWR_CNTRL, TAG0, 0, 1)
REG32(APU0_DSU_L3_CE_CNTRL, 0x154)
    FIELD(APU0_DSU_L3_CE_CNTRL, LTDB, 8, 1)
    FIELD(APU0_DSU_L3_CE_CNTRL, SF, 7, 1)
    FIELD(APU0_DSU_L3_CE_CNTRL, VICTIM, 6, 1)
    FIELD(APU0_DSU_L3_CE_CNTRL, DATA1, 5, 1)
    FIELD(APU0_DSU_L3_CE_CNTRL, DATA0, 4, 1)
    FIELD(APU0_DSU_L3_CE_CNTRL, TAG3, 3, 1)
    FIELD(APU0_DSU_L3_CE_CNTRL, TAG2, 2, 1)
    FIELD(APU0_DSU_L3_CE_CNTRL, TAG1, 1, 1)
    FIELD(APU0_DSU_L3_CE_CNTRL, TAG0, 0, 1)
REG32(APU0_DSU_L3_PWR_STATUS, 0x158)
    FIELD(APU0_DSU_L3_PWR_STATUS, LTDB, 8, 1)
    FIELD(APU0_DSU_L3_PWR_STATUS, SF, 7, 1)
    FIELD(APU0_DSU_L3_PWR_STATUS, VICTIM, 6, 1)
    FIELD(APU0_DSU_L3_PWR_STATUS, DATA1, 5, 1)
    FIELD(APU0_DSU_L3_PWR_STATUS, DATA0, 4, 1)
    FIELD(APU0_DSU_L3_PWR_STATUS, TAG3, 3, 1)
    FIELD(APU0_DSU_L3_PWR_STATUS, TAG2, 2, 1)
    FIELD(APU0_DSU_L3_PWR_STATUS, TAG1, 1, 1)
    FIELD(APU0_DSU_L3_PWR_STATUS, TAG0, 0, 1)
REG32(APU1_DSU_L3_PWR_CNTRL, 0x15c)
    FIELD(APU1_DSU_L3_PWR_CNTRL, LTDB, 8, 1)
    FIELD(APU1_DSU_L3_PWR_CNTRL, SF, 7, 1)
    FIELD(APU1_DSU_L3_PWR_CNTRL, VICTIM, 6, 1)
    FIELD(APU1_DSU_L3_PWR_CNTRL, DATA1, 5, 1)
    FIELD(APU1_DSU_L3_PWR_CNTRL, DATA0, 4, 1)
    FIELD(APU1_DSU_L3_PWR_CNTRL, TAG3, 3, 1)
    FIELD(APU1_DSU_L3_PWR_CNTRL, TAG2, 2, 1)
    FIELD(APU1_DSU_L3_PWR_CNTRL, TAG1, 1, 1)
    FIELD(APU1_DSU_L3_PWR_CNTRL, TAG0, 0, 1)
REG32(APU1_DSU_L3_CE_CNTRL, 0x160)
    FIELD(APU1_DSU_L3_CE_CNTRL, LTDB, 8, 1)
    FIELD(APU1_DSU_L3_CE_CNTRL, SF, 7, 1)
    FIELD(APU1_DSU_L3_CE_CNTRL, VICTIM, 6, 1)
    FIELD(APU1_DSU_L3_CE_CNTRL, DATA1, 5, 1)
    FIELD(APU1_DSU_L3_CE_CNTRL, DATA0, 4, 1)
    FIELD(APU1_DSU_L3_CE_CNTRL, TAG3, 3, 1)
    FIELD(APU1_DSU_L3_CE_CNTRL, TAG2, 2, 1)
    FIELD(APU1_DSU_L3_CE_CNTRL, TAG1, 1, 1)
    FIELD(APU1_DSU_L3_CE_CNTRL, TAG0, 0, 1)
REG32(APU1_DSU_L3_PWR_STATUS, 0x164)
    FIELD(APU1_DSU_L3_PWR_STATUS, LTDB, 8, 1)
    FIELD(APU1_DSU_L3_PWR_STATUS, SF, 7, 1)
    FIELD(APU1_DSU_L3_PWR_STATUS, VICTIM, 6, 1)
    FIELD(APU1_DSU_L3_PWR_STATUS, DATA1, 5, 1)
    FIELD(APU1_DSU_L3_PWR_STATUS, DATA0, 4, 1)
    FIELD(APU1_DSU_L3_PWR_STATUS, TAG3, 3, 1)
    FIELD(APU1_DSU_L3_PWR_STATUS, TAG2, 2, 1)
    FIELD(APU1_DSU_L3_PWR_STATUS, TAG1, 1, 1)
    FIELD(APU1_DSU_L3_PWR_STATUS, TAG0, 0, 1)
REG32(APU2_DSU_L3_PWR_CNTRL, 0x168)
    FIELD(APU2_DSU_L3_PWR_CNTRL, LTDB, 8, 1)
    FIELD(APU2_DSU_L3_PWR_CNTRL, SF, 7, 1)
    FIELD(APU2_DSU_L3_PWR_CNTRL, VICTIM, 6, 1)
    FIELD(APU2_DSU_L3_PWR_CNTRL, DATA1, 5, 1)
    FIELD(APU2_DSU_L3_PWR_CNTRL, DATA0, 4, 1)
    FIELD(APU2_DSU_L3_PWR_CNTRL, TAG3, 3, 1)
    FIELD(APU2_DSU_L3_PWR_CNTRL, TAG2, 2, 1)
    FIELD(APU2_DSU_L3_PWR_CNTRL, TAG1, 1, 1)
    FIELD(APU2_DSU_L3_PWR_CNTRL, TAG0, 0, 1)
REG32(APU2_DSU_L3_CE_CNTRL, 0x16c)
    FIELD(APU2_DSU_L3_CE_CNTRL, LTDB, 8, 1)
    FIELD(APU2_DSU_L3_CE_CNTRL, SF, 7, 1)
    FIELD(APU2_DSU_L3_CE_CNTRL, VICTIM, 6, 1)
    FIELD(APU2_DSU_L3_CE_CNTRL, DATA1, 5, 1)
    FIELD(APU2_DSU_L3_CE_CNTRL, DATA0, 4, 1)
    FIELD(APU2_DSU_L3_CE_CNTRL, TAG3, 3, 1)
    FIELD(APU2_DSU_L3_CE_CNTRL, TAG2, 2, 1)
    FIELD(APU2_DSU_L3_CE_CNTRL, TAG1, 1, 1)
    FIELD(APU2_DSU_L3_CE_CNTRL, TAG0, 0, 1)
REG32(APU2_DSU_L3_PWR_STATUS, 0x170)
    FIELD(APU2_DSU_L3_PWR_STATUS, LTDB, 8, 1)
    FIELD(APU2_DSU_L3_PWR_STATUS, SF, 7, 1)
    FIELD(APU2_DSU_L3_PWR_STATUS, VICTIM, 6, 1)
    FIELD(APU2_DSU_L3_PWR_STATUS, DATA1, 5, 1)
    FIELD(APU2_DSU_L3_PWR_STATUS, DATA0, 4, 1)
    FIELD(APU2_DSU_L3_PWR_STATUS, TAG3, 3, 1)
    FIELD(APU2_DSU_L3_PWR_STATUS, TAG2, 2, 1)
    FIELD(APU2_DSU_L3_PWR_STATUS, TAG1, 1, 1)
    FIELD(APU2_DSU_L3_PWR_STATUS, TAG0, 0, 1)
REG32(APU3_DSU_L3_PWR_CNTRL, 0x174)
    FIELD(APU3_DSU_L3_PWR_CNTRL, LTDB, 8, 1)
    FIELD(APU3_DSU_L3_PWR_CNTRL, SF, 7, 1)
    FIELD(APU3_DSU_L3_PWR_CNTRL, VICTIM, 6, 1)
    FIELD(APU3_DSU_L3_PWR_CNTRL, DATA1, 5, 1)
    FIELD(APU3_DSU_L3_PWR_CNTRL, DATA0, 4, 1)
    FIELD(APU3_DSU_L3_PWR_CNTRL, TAG3, 3, 1)
    FIELD(APU3_DSU_L3_PWR_CNTRL, TAG2, 2, 1)
    FIELD(APU3_DSU_L3_PWR_CNTRL, TAG1, 1, 1)
    FIELD(APU3_DSU_L3_PWR_CNTRL, TAG0, 0, 1)
REG32(APU3_DSU_L3_CE_CNTRL, 0x178)
    FIELD(APU3_DSU_L3_CE_CNTRL, LTDB, 8, 1)
    FIELD(APU3_DSU_L3_CE_CNTRL, SF, 7, 1)
    FIELD(APU3_DSU_L3_CE_CNTRL, VICTIM, 6, 1)
    FIELD(APU3_DSU_L3_CE_CNTRL, DATA1, 5, 1)
    FIELD(APU3_DSU_L3_CE_CNTRL, DATA0, 4, 1)
    FIELD(APU3_DSU_L3_CE_CNTRL, TAG3, 3, 1)
    FIELD(APU3_DSU_L3_CE_CNTRL, TAG2, 2, 1)
    FIELD(APU3_DSU_L3_CE_CNTRL, TAG1, 1, 1)
    FIELD(APU3_DSU_L3_CE_CNTRL, TAG0, 0, 1)
REG32(APU3_DSU_L3_PWR_STATUS, 0x17c)
    FIELD(APU3_DSU_L3_PWR_STATUS, LTDB, 8, 1)
    FIELD(APU3_DSU_L3_PWR_STATUS, SF, 7, 1)
    FIELD(APU3_DSU_L3_PWR_STATUS, VICTIM, 6, 1)
    FIELD(APU3_DSU_L3_PWR_STATUS, DATA1, 5, 1)
    FIELD(APU3_DSU_L3_PWR_STATUS, DATA0, 4, 1)
    FIELD(APU3_DSU_L3_PWR_STATUS, TAG3, 3, 1)
    FIELD(APU3_DSU_L3_PWR_STATUS, TAG2, 2, 1)
    FIELD(APU3_DSU_L3_PWR_STATUS, TAG1, 1, 1)
    FIELD(APU3_DSU_L3_PWR_STATUS, TAG0, 0, 1)
REG32(RPU_CACHE_PWR_CNTRL, 0x200)
    FIELD(RPU_CACHE_PWR_CNTRL, B1, 3, 1)
    FIELD(RPU_CACHE_PWR_CNTRL, B0, 2, 1)
    FIELD(RPU_CACHE_PWR_CNTRL, A1, 1, 1)
    FIELD(RPU_CACHE_PWR_CNTRL, A0, 0, 1)
REG32(RPU_CACHE_CE_CNTRL, 0x204)
    FIELD(RPU_CACHE_CE_CNTRL, B1, 3, 1)
    FIELD(RPU_CACHE_CE_CNTRL, B0, 2, 1)
    FIELD(RPU_CACHE_CE_CNTRL, A1, 1, 1)
    FIELD(RPU_CACHE_CE_CNTRL, A0, 0, 1)
REG32(RPU_CACHE_PWR_STATUS, 0x208)
    FIELD(RPU_CACHE_PWR_STATUS, B1, 3, 1)
    FIELD(RPU_CACHE_PWR_STATUS, B0, 2, 1)
    FIELD(RPU_CACHE_PWR_STATUS, A1, 1, 1)
    FIELD(RPU_CACHE_PWR_STATUS, A0, 0, 1)
REG32(OCM_PWR_CNTRL, 0x250)
    FIELD(OCM_PWR_CNTRL, B1_I3, 11, 1)
    FIELD(OCM_PWR_CNTRL, B1_I2, 10, 1)
    FIELD(OCM_PWR_CNTRL, B1_I1, 9, 1)
    FIELD(OCM_PWR_CNTRL, B1_I0, 8, 1)
    FIELD(OCM_PWR_CNTRL, B0_I3, 3, 1)
    FIELD(OCM_PWR_CNTRL, B0_I2, 2, 1)
    FIELD(OCM_PWR_CNTRL, B0_I1, 1, 1)
    FIELD(OCM_PWR_CNTRL, B0_I0, 0, 1)
REG32(OCM_RET_CNTRL, 0x254)
    FIELD(OCM_RET_CNTRL, B1_I3, 11, 1)
    FIELD(OCM_RET_CNTRL, B1_I2, 10, 1)
    FIELD(OCM_RET_CNTRL, B1_I1, 9, 1)
    FIELD(OCM_RET_CNTRL, B1_I0, 8, 1)
    FIELD(OCM_RET_CNTRL, B0_I3, 3, 1)
    FIELD(OCM_RET_CNTRL, B0_I2, 2, 1)
    FIELD(OCM_RET_CNTRL, B0_I1, 1, 1)
    FIELD(OCM_RET_CNTRL, B0_I0, 0, 1)
REG32(OCM_CE_CNTRL, 0x258)
    FIELD(OCM_CE_CNTRL, B1_I3, 11, 1)
    FIELD(OCM_CE_CNTRL, B1_I2, 10, 1)
    FIELD(OCM_CE_CNTRL, B1_I1, 9, 1)
    FIELD(OCM_CE_CNTRL, B1_I0, 8, 1)
    FIELD(OCM_CE_CNTRL, B0_I3, 3, 1)
    FIELD(OCM_CE_CNTRL, B0_I2, 2, 1)
    FIELD(OCM_CE_CNTRL, B0_I1, 1, 1)
    FIELD(OCM_CE_CNTRL, B0_I0, 0, 1)
REG32(OCM_PWR_STATUS, 0x25c)
    FIELD(OCM_PWR_STATUS, B1_I3, 11, 1)
    FIELD(OCM_PWR_STATUS, B1_I2, 10, 1)
    FIELD(OCM_PWR_STATUS, B1_I1, 9, 1)
    FIELD(OCM_PWR_STATUS, B1_I0, 8, 1)
    FIELD(OCM_PWR_STATUS, B0_I3, 3, 1)
    FIELD(OCM_PWR_STATUS, B0_I2, 2, 1)
    FIELD(OCM_PWR_STATUS, B0_I1, 1, 1)
    FIELD(OCM_PWR_STATUS, B0_I0, 0, 1)
REG32(TCM_PWR_CNTRL, 0x300)
    FIELD(TCM_PWR_CNTRL, TCMB1, 24, 1)
    FIELD(TCM_PWR_CNTRL, TCMB0, 16, 1)
    FIELD(TCM_PWR_CNTRL, TCMA1, 8, 1)
    FIELD(TCM_PWR_CNTRL, TCMA0, 0, 1)
REG32(TCM_RET_CNTRL, 0x304)
    FIELD(TCM_RET_CNTRL, TCMB1, 24, 1)
    FIELD(TCM_RET_CNTRL, TCMB0, 16, 1)
    FIELD(TCM_RET_CNTRL, TCMA1, 8, 1)
    FIELD(TCM_RET_CNTRL, TCMA0, 0, 1)
REG32(TCM_CE_CNTRL, 0x308)
    FIELD(TCM_CE_CNTRL, TCMB1, 24, 1)
    FIELD(TCM_CE_CNTRL, TCMB0, 16, 1)
    FIELD(TCM_CE_CNTRL, TCMA1, 8, 1)
    FIELD(TCM_CE_CNTRL, TCMA0, 0, 1)
REG32(TCM_PWR_STATUS, 0x30c)
    FIELD(TCM_PWR_STATUS, TCMB1, 24, 1)
    FIELD(TCM_PWR_STATUS, TCMB0, 16, 1)
    FIELD(TCM_PWR_STATUS, TCMA1, 8, 1)
    FIELD(TCM_PWR_STATUS, TCMA0, 0, 1)
REG32(GEM_PWR_CNTRL, 0x350)
    FIELD(GEM_PWR_CNTRL, GEM1, 8, 1)
    FIELD(GEM_PWR_CNTRL, GEM0, 0, 1)
REG32(GEM_CE_CNTRL, 0x354)
    FIELD(GEM_CE_CNTRL, GEM1, 1, 1)
    FIELD(GEM_CE_CNTRL, GEM0, 0, 1)
REG32(GEM_PWR_STATUS, 0x358)
    FIELD(GEM_PWR_STATUS, GEM1, 8, 1)
    FIELD(GEM_PWR_STATUS, GEM0, 0, 1)
REG32(DOMAIN_ISO_CNTRL, 0x400)
    FIELD(DOMAIN_ISO_CNTRL, FPD_CPM5_DFX, 5, 1)
    FIELD(DOMAIN_ISO_CNTRL, FPD_CPM5, 4, 1)
    FIELD(DOMAIN_ISO_CNTRL, LPD_OCM2_DFX, 3, 1)
    FIELD(DOMAIN_ISO_CNTRL, LPD_OCM2, 2, 1)
    FIELD(DOMAIN_ISO_CNTRL, LPD_FPD_DFX, 1, 1)
    FIELD(DOMAIN_ISO_CNTRL, LPD_FPD, 0, 1)
REG32(LOC_PWR_STATE0, 0x410)
    FIELD(LOC_PWR_STATE0, OCM_B1_I3, 31, 1)
    FIELD(LOC_PWR_STATE0, OCM_B1_I2, 30, 1)
    FIELD(LOC_PWR_STATE0, OCM_B1_I1, 29, 1)
    FIELD(LOC_PWR_STATE0, OCM_B1_I0, 28, 1)
    FIELD(LOC_PWR_STATE0, OCM_B0_I3, 27, 1)
    FIELD(LOC_PWR_STATE0, OCM_B0_I2, 26, 1)
    FIELD(LOC_PWR_STATE0, OCM_B0_I1, 25, 1)
    FIELD(LOC_PWR_STATE0, OCM_B0_I0, 24, 1)
    FIELD(LOC_PWR_STATE0, TCMB1, 23, 1)
    FIELD(LOC_PWR_STATE0, TCMB0, 22, 1)
    FIELD(LOC_PWR_STATE0, TCMA1, 21, 1)
    FIELD(LOC_PWR_STATE0, TCMA0, 20, 1)
    FIELD(LOC_PWR_STATE0, RPU_B_CORE1, 19, 1)
    FIELD(LOC_PWR_STATE0, RPU_B_CORE0, 18, 1)
    FIELD(LOC_PWR_STATE0, RPU_A_CORE1, 17, 1)
    FIELD(LOC_PWR_STATE0, RPU_A_CORE0, 16, 1)
    FIELD(LOC_PWR_STATE0, APU3_CORE3, 15, 1)
    FIELD(LOC_PWR_STATE0, APU3_CORE2, 14, 1)
    FIELD(LOC_PWR_STATE0, APU3_CORE1, 13, 1)
    FIELD(LOC_PWR_STATE0, APU3_CORE0, 12, 1)
    FIELD(LOC_PWR_STATE0, APU2_CORE3, 11, 1)
    FIELD(LOC_PWR_STATE0, APU2_CORE2, 10, 1)
    FIELD(LOC_PWR_STATE0, APU2_CORE1, 9, 1)
    FIELD(LOC_PWR_STATE0, APU2_CORE0, 8, 1)
    FIELD(LOC_PWR_STATE0, APU1_CORE3, 7, 1)
    FIELD(LOC_PWR_STATE0, APU1_CORE2, 6, 1)
    FIELD(LOC_PWR_STATE0, APU1_CORE1, 5, 1)
    FIELD(LOC_PWR_STATE0, APU1_CORE0, 4, 1)
    FIELD(LOC_PWR_STATE0, APU0_CORE3, 3, 1)
    FIELD(LOC_PWR_STATE0, APU0_CORE2, 2, 1)
    FIELD(LOC_PWR_STATE0, APU0_CORE1, 1, 1)
    FIELD(LOC_PWR_STATE0, APU0_CORE0, 0, 1)
REG32(LOC_PWR_STATE1, 0x414)
    FIELD(LOC_PWR_STATE1, FP, 2, 1)
    FIELD(LOC_PWR_STATE1, GEM1, 1, 1)
    FIELD(LOC_PWR_STATE1, GEM0, 0, 1)
REG32(LOC_AUX_PWR_STATE, 0x420)
    FIELD(LOC_AUX_PWR_STATE, OCM_B1_I3, 31, 1)
    FIELD(LOC_AUX_PWR_STATE, OCM_B1_I2, 30, 1)
    FIELD(LOC_AUX_PWR_STATE, OCM_B1_I1, 29, 1)
    FIELD(LOC_AUX_PWR_STATE, OCM_B1_I0, 28, 1)
    FIELD(LOC_AUX_PWR_STATE, OCM_B0_I3, 27, 1)
    FIELD(LOC_AUX_PWR_STATE, OCM_B0_I2, 26, 1)
    FIELD(LOC_AUX_PWR_STATE, OCM_B0_I1, 25, 1)
    FIELD(LOC_AUX_PWR_STATE, OCM_B0_I0, 24, 1)
    FIELD(LOC_AUX_PWR_STATE, TCMB1, 23, 1)
    FIELD(LOC_AUX_PWR_STATE, TCMB0, 22, 1)
    FIELD(LOC_AUX_PWR_STATE, TCMA1, 21, 1)
    FIELD(LOC_AUX_PWR_STATE, TCMA0, 20, 1)
    FIELD(LOC_AUX_PWR_STATE, RPU_B_CORE1, 19, 1)
    FIELD(LOC_AUX_PWR_STATE, RPU_B_CORE0, 18, 1)
    FIELD(LOC_AUX_PWR_STATE, RPU_A_CORE1, 17, 1)
    FIELD(LOC_AUX_PWR_STATE, RPU_A_CORE0, 16, 1)
    FIELD(LOC_AUX_PWR_STATE, APU3_CORE3, 15, 1)
    FIELD(LOC_AUX_PWR_STATE, APU3_CORE2, 14, 1)
    FIELD(LOC_AUX_PWR_STATE, APU3_CORE1, 13, 1)
    FIELD(LOC_AUX_PWR_STATE, APU3_CORE0, 12, 1)
    FIELD(LOC_AUX_PWR_STATE, APU2_CORE3, 11, 1)
    FIELD(LOC_AUX_PWR_STATE, APU2_CORE2, 10, 1)
    FIELD(LOC_AUX_PWR_STATE, APU2_CORE1, 9, 1)
    FIELD(LOC_AUX_PWR_STATE, APU2_CORE0, 8, 1)
    FIELD(LOC_AUX_PWR_STATE, APU1_CORE3, 7, 1)
    FIELD(LOC_AUX_PWR_STATE, APU1_CORE2, 6, 1)
    FIELD(LOC_AUX_PWR_STATE, APU1_CORE1, 5, 1)
    FIELD(LOC_AUX_PWR_STATE, APU1_CORE0, 4, 1)
    FIELD(LOC_AUX_PWR_STATE, APU0_CORE3, 3, 1)
    FIELD(LOC_AUX_PWR_STATE, APU0_CORE2, 2, 1)
    FIELD(LOC_AUX_PWR_STATE, APU0_CORE1, 1, 1)
    FIELD(LOC_AUX_PWR_STATE, APU0_CORE0, 0, 1)
REG32(LOCAL_GEN_STORAGE0, 0x430)
REG32(LOCAL_GEN_STORAGE1, 0x434)
REG32(LOCAL_GEN_STORAGE2, 0x438)
REG32(LOCAL_GEN_STORAGE3, 0x43c)
REG32(PERS_LOC_GEN_STORAGE0, 0x440)
REG32(PERS_LOC_GEN_STORAGE1, 0x444)
REG32(PERS_LOC_GEN_STORAGE2, 0x448)
REG32(PERS_LOC_GEN_STORAGE3, 0x44c)
REG32(ADDR_ERROR_STATUS, 0x450)
    FIELD(ADDR_ERROR_STATUS, STATUS, 0, 1)
REG32(ADDR_ERROR_INT_MASK, 0x454)
    FIELD(ADDR_ERROR_INT_MASK, MASK, 0, 1)
REG32(ADDR_ERROR_INT_EN, 0x458)
    FIELD(ADDR_ERROR_INT_EN, EN, 0, 1)
REG32(ADDR_ERROR_INT_DIS, 0x45c)
    FIELD(ADDR_ERROR_INT_DIS, DIS, 0, 1)
REG32(PSM_GLOBAL_APB, 0x600)
    FIELD(PSM_GLOBAL_APB, RST_N, 4, 1)
    FIELD(PSM_GLOBAL_APB, POWER_IDLEREQ, 3, 1)
    FIELD(PSM_GLOBAL_APB, POWER_IDLEACK, 2, 1)
    FIELD(PSM_GLOBAL_APB, POWER_IDLE, 1, 1)
    FIELD(PSM_GLOBAL_APB, MAINEXTEN, 0, 1)
REG32(ECO_2, 0x804)
    FIELD(ECO_2, CPM5_LPD_DFX, 31, 1)
    FIELD(ECO_2, CPM5_LPD, 30, 1)
    FIELD(ECO_2, CPM5_GT_DFX, 29, 1)
    FIELD(ECO_2, CPM5_GT, 28, 1)
    FIELD(ECO_2, CPM5_PL_DFX, 27, 1)
    FIELD(ECO_2, CPM5_PL, 26, 1)

#define PSMX_LOCAL_REG_R_MAX (R_ECO_2 + 1)

typedef struct PSMX_LOCAL_REG {
    SysBusDevice parent_obj;
    MemoryRegion iomem;
    qemu_irq irq_addr_error_int;

    qemu_irq pwr_apu0[4];
    qemu_irq pwr_apu1[4];
    qemu_irq pwr_apu2[4];
    qemu_irq pwr_apu3[4];
    qemu_irq pwr_rpu_a[2];
    qemu_irq pwr_rpu_b[2];
    qemu_irq pwr_tcm[4];
    qemu_irq pwr_ocm[8];
    qemu_irq pwr_gem[2];
    qemu_irq pwr_fp;
    qemu_irq loc_pwr_state0[32];
    qemu_irq loc_pwr_state1[3];
    qemu_irq loc_aux_pwr_state[32];

    bool linux_direct_boot;
    uint32_t regs[PSMX_LOCAL_REG_R_MAX];
    RegisterInfo regs_info[PSMX_LOCAL_REG_R_MAX];
} PSMX_LOCAL_REG;

#define PROPAGATE_FIELD1(s, sreg, sf, dreg, df, irq) {           \
    unsigned int val = ARRAY_FIELD_EX32((s)->regs, sreg, sf);    \
    ARRAY_FIELD_DP32((s)->regs, dreg, df, val);                  \
    qemu_set_irq(irq, val);                                      \
}

#define PROPAGATE_REG32(s, reg, irq) {                           \
    unsigned int val = (s)->regs[R_ ## reg];                     \
    unsigned int i;                                              \
                                                                 \
    assert(ARRAY_SIZE(irq) == sizeof((s)->regs[0]) * 8);         \
    for (i = 0; i < sizeof((s)->regs[0]) * 8; i++) {             \
        qemu_set_irq(irq[i], (val >> i) & 1);                    \
    }                                                            \
}

static void psmx_update_pwr_status(PSMX_LOCAL_REG *s)
{
    if (!s->linux_direct_boot) {
        /* APU0 */
        PROPAGATE_FIELD1(s, APU0_CORE0_PWR_CNTRL, PWR_GATES,
                           APU0_CORE0_PWR_STATUS, PWR_GATES, s->pwr_apu0[0]);
        PROPAGATE_FIELD1(s, APU0_CORE1_PWR_CNTRL, PWR_GATES,
                           APU0_CORE1_PWR_STATUS, PWR_GATES, s->pwr_apu0[1]);
        PROPAGATE_FIELD1(s, APU0_CORE2_PWR_CNTRL, PWR_GATES,
                           APU0_CORE2_PWR_STATUS, PWR_GATES, s->pwr_apu0[2]);
        PROPAGATE_FIELD1(s, APU0_CORE3_PWR_CNTRL, PWR_GATES,
                           APU0_CORE3_PWR_STATUS, PWR_GATES, s->pwr_apu0[3]);
        /* APU1 */
        PROPAGATE_FIELD1(s, APU1_CORE0_PWR_CNTRL, PWR_GATES,
                           APU1_CORE0_PWR_STATUS, PWR_GATES, s->pwr_apu1[0]);
        PROPAGATE_FIELD1(s, APU1_CORE1_PWR_CNTRL, PWR_GATES,
                           APU1_CORE1_PWR_STATUS, PWR_GATES, s->pwr_apu1[1]);
        PROPAGATE_FIELD1(s, APU1_CORE2_PWR_CNTRL, PWR_GATES,
                           APU1_CORE2_PWR_STATUS, PWR_GATES, s->pwr_apu1[2]);
        PROPAGATE_FIELD1(s, APU1_CORE3_PWR_CNTRL, PWR_GATES,
                           APU1_CORE3_PWR_STATUS, PWR_GATES, s->pwr_apu1[3]);
        /* APU2 */
        PROPAGATE_FIELD1(s, APU2_CORE0_PWR_CNTRL, PWR_GATES,
                           APU2_CORE0_PWR_STATUS, PWR_GATES, s->pwr_apu2[0]);
        PROPAGATE_FIELD1(s, APU2_CORE1_PWR_CNTRL, PWR_GATES,
                           APU2_CORE1_PWR_STATUS, PWR_GATES, s->pwr_apu2[1]);
        PROPAGATE_FIELD1(s, APU2_CORE2_PWR_CNTRL, PWR_GATES,
                           APU2_CORE2_PWR_STATUS, PWR_GATES, s->pwr_apu2[2]);
        PROPAGATE_FIELD1(s, APU2_CORE3_PWR_CNTRL, PWR_GATES,
                           APU2_CORE3_PWR_STATUS, PWR_GATES, s->pwr_apu2[3]);
        /* APU3 */
        PROPAGATE_FIELD1(s, APU3_CORE0_PWR_CNTRL, PWR_GATES,
                           APU3_CORE0_PWR_STATUS, PWR_GATES, s->pwr_apu3[0]);
        PROPAGATE_FIELD1(s, APU3_CORE1_PWR_CNTRL, PWR_GATES,
                           APU3_CORE1_PWR_STATUS, PWR_GATES, s->pwr_apu3[1]);
        PROPAGATE_FIELD1(s, APU3_CORE2_PWR_CNTRL, PWR_GATES,
                           APU3_CORE2_PWR_STATUS, PWR_GATES, s->pwr_apu3[2]);
        PROPAGATE_FIELD1(s, APU3_CORE3_PWR_CNTRL, PWR_GATES,
                           APU3_CORE3_PWR_STATUS, PWR_GATES, s->pwr_apu3[3]);
        /* RPU A */
        PROPAGATE_FIELD1(s, RPU_A_CORE0_PWR_CNTRL, PWR_GATES,
                           RPU_A_CORE0_PWR_STATUS, PWR_GATES, s->pwr_rpu_a[0]);
        PROPAGATE_FIELD1(s, RPU_A_CORE1_PWR_CNTRL, PWR_GATES,
                           RPU_A_CORE1_PWR_STATUS, PWR_GATES, s->pwr_rpu_a[1]);
        /* RPU B */
        PROPAGATE_FIELD1(s, RPU_B_CORE0_PWR_CNTRL, PWR_GATES,
                           RPU_B_CORE0_PWR_STATUS, PWR_GATES, s->pwr_rpu_b[0]);
        PROPAGATE_FIELD1(s, RPU_B_CORE1_PWR_CNTRL, PWR_GATES,
                           RPU_B_CORE1_PWR_STATUS, PWR_GATES, s->pwr_rpu_b[1]);
    }

    s->regs[R_APU0_DSU_L3_PWR_STATUS] = s->regs[R_APU0_DSU_L3_PWR_CNTRL];
    s->regs[R_APU1_DSU_L3_PWR_STATUS] = s->regs[R_APU1_DSU_L3_PWR_CNTRL];
    s->regs[R_APU2_DSU_L3_PWR_STATUS] = s->regs[R_APU2_DSU_L3_PWR_CNTRL];
    s->regs[R_APU3_DSU_L3_PWR_STATUS] = s->regs[R_APU3_DSU_L3_PWR_CNTRL];

    s->regs[R_RPU_CACHE_PWR_STATUS] = s->regs[R_RPU_CACHE_PWR_CNTRL];

    PROPAGATE_FIELD1(s, OCM_PWR_CNTRL, B0_I0,
                     OCM_PWR_STATUS, B0_I0, s->pwr_ocm[0]);
    PROPAGATE_FIELD1(s, OCM_PWR_CNTRL, B0_I1,
                     OCM_PWR_STATUS, B0_I1, s->pwr_ocm[1]);
    PROPAGATE_FIELD1(s, OCM_PWR_CNTRL, B0_I2,
                     OCM_PWR_STATUS, B0_I2, s->pwr_ocm[2]);
    PROPAGATE_FIELD1(s, OCM_PWR_CNTRL, B0_I3,
                     OCM_PWR_STATUS, B0_I3, s->pwr_ocm[3]);
    PROPAGATE_FIELD1(s, OCM_PWR_CNTRL, B1_I0,
                     OCM_PWR_STATUS, B1_I0, s->pwr_ocm[4]);
    PROPAGATE_FIELD1(s, OCM_PWR_CNTRL, B1_I1,
                     OCM_PWR_STATUS, B1_I1, s->pwr_ocm[5]);
    PROPAGATE_FIELD1(s, OCM_PWR_CNTRL, B1_I2,
                     OCM_PWR_STATUS, B1_I2, s->pwr_ocm[6]);
    PROPAGATE_FIELD1(s, OCM_PWR_CNTRL, B1_I3,
                     OCM_PWR_STATUS, B1_I3, s->pwr_ocm[7]);

    PROPAGATE_FIELD1(s, TCM_PWR_CNTRL, TCMA0,
                     TCM_PWR_STATUS, TCMA0, s->pwr_tcm[0]);
    PROPAGATE_FIELD1(s, TCM_PWR_CNTRL, TCMA1,
                     TCM_PWR_STATUS, TCMA1, s->pwr_tcm[1]);
    PROPAGATE_FIELD1(s, TCM_PWR_CNTRL, TCMB0,
                     TCM_PWR_STATUS, TCMB0, s->pwr_tcm[2]);
    PROPAGATE_FIELD1(s, TCM_PWR_CNTRL, TCMB1,
                     TCM_PWR_STATUS, TCMB1, s->pwr_tcm[3]);

    PROPAGATE_FIELD1(s, GEM_PWR_CNTRL, GEM0,
                     GEM_PWR_CNTRL, GEM0, s->pwr_gem[0]);
    PROPAGATE_FIELD1(s, GEM_PWR_CNTRL, GEM1,
                     GEM_PWR_CNTRL, GEM1, s->pwr_gem[1]);

    PROPAGATE_REG32(s, LOC_PWR_STATE0, s->loc_pwr_state0);
    qemu_set_irq(s->loc_pwr_state1[0], ARRAY_FIELD_EX32(s->regs,
                                       LOC_PWR_STATE1, GEM0));
    qemu_set_irq(s->loc_pwr_state1[1], ARRAY_FIELD_EX32(s->regs,
                                       LOC_PWR_STATE1, GEM1));
    qemu_set_irq(s->loc_pwr_state1[2], ARRAY_FIELD_EX32(s->regs,
                                       LOC_PWR_STATE1, FP));

    PROPAGATE_REG32(s, LOC_AUX_PWR_STATE, s->loc_aux_pwr_state);
}

static void addr_error_int_update_irq(PSMX_LOCAL_REG *s)
{
    bool pending = s->regs[R_ADDR_ERROR_STATUS] &
                   ~s->regs[R_ADDR_ERROR_INT_MASK];
    qemu_set_irq(s->irq_addr_error_int, pending);
}

static void addr_error_status_postw(RegisterInfo *reg, uint64_t val64)
{
    PSMX_LOCAL_REG *s = XILINX_PSMX_LOCAL_REG(reg->opaque);
    addr_error_int_update_irq(s);
}

static uint64_t addr_error_int_en_prew(RegisterInfo *reg, uint64_t val64)
{
    PSMX_LOCAL_REG *s = XILINX_PSMX_LOCAL_REG(reg->opaque);
    uint32_t val = val64;

    s->regs[R_ADDR_ERROR_INT_MASK] &= ~val;
    addr_error_int_update_irq(s);
    return 0;
}

static uint64_t addr_error_int_dis_prew(RegisterInfo *reg, uint64_t val64)
{
    PSMX_LOCAL_REG *s = XILINX_PSMX_LOCAL_REG(reg->opaque);
    uint32_t val = val64;

    s->regs[R_ADDR_ERROR_INT_MASK] |= val;
    addr_error_int_update_irq(s);
    return 0;
}

static void psmx_local_postw(RegisterInfo *reg, uint64_t val64)
{
    PSMX_LOCAL_REG *s = XILINX_PSMX_LOCAL_REG(reg->opaque);

    psmx_update_pwr_status(s);
}

static const RegisterAccessInfo psmx_local_reg_regs_info[] = {
    {   .name = "APU0_CORE0_PWR_CNTRL",  .addr = A_APU0_CORE0_PWR_CNTRL,
        .reset = 0xf,
        .rsvd = 0xffffffe0,
        .ro = 0xffffffe0,
        .post_write = psmx_local_postw,
    },{ .name = "APU0_CORE0_PWR_STATUS",  .addr = A_APU0_CORE0_PWR_STATUS,
        .reset = 0xf,
        .rsvd = 0xfffffff0,
        .ro = 0xffffffff,
    },{ .name = "APU0_CORE1_PWR_CNTRL",  .addr = A_APU0_CORE1_PWR_CNTRL,
        .reset = 0xf,
        .rsvd = 0xffffffe0,
        .ro = 0xffffffe0,
        .post_write = psmx_local_postw,
    },{ .name = "APU0_CORE1_PWR_STATUS",  .addr = A_APU0_CORE1_PWR_STATUS,
        .reset = 0xf,
        .rsvd = 0xfffffff0,
        .ro = 0xffffffff,
    },{ .name = "APU0_CORE2_PWR_CNTRL",  .addr = A_APU0_CORE2_PWR_CNTRL,
        .reset = 0xf,
        .rsvd = 0xffffffe0,
        .ro = 0xffffffe0,
        .post_write = psmx_local_postw,
    },{ .name = "APU0_CORE2_PWR_STATUS",  .addr = A_APU0_CORE2_PWR_STATUS,
        .reset = 0xf,
        .rsvd = 0xfffffff0,
        .ro = 0xffffffff,
    },{ .name = "APU0_CORE3_PWR_CNTRL",  .addr = A_APU0_CORE3_PWR_CNTRL,
        .reset = 0xf,
        .rsvd = 0xffffffe0,
        .ro = 0xffffffe0,
        .post_write = psmx_local_postw,
    },{ .name = "APU0_CORE3_PWR_STATUS",  .addr = A_APU0_CORE3_PWR_STATUS,
        .reset = 0xf,
        .rsvd = 0xfffffff0,
        .ro = 0xffffffff,
    },{ .name = "APU1_CORE0_PWR_CNTRL",  .addr = A_APU1_CORE0_PWR_CNTRL,
        .reset = 0xf,
        .rsvd = 0xffffffe0,
        .ro = 0xffffffe0,
        .post_write = psmx_local_postw,
    },{ .name = "APU1_CORE0_PWR_STATUS",  .addr = A_APU1_CORE0_PWR_STATUS,
        .reset = 0xf,
        .rsvd = 0xfffffff0,
        .ro = 0xffffffff,
    },{ .name = "APU1_CORE1_PWR_CNTRL",  .addr = A_APU1_CORE1_PWR_CNTRL,
        .reset = 0xf,
        .rsvd = 0xffffffe0,
        .ro = 0xffffffe0,
        .post_write = psmx_local_postw,
    },{ .name = "APU1_CORE1_PWR_STATUS",  .addr = A_APU1_CORE1_PWR_STATUS,
        .reset = 0xf,
        .rsvd = 0xfffffff0,
        .ro = 0xffffffff,
    },{ .name = "APU1_CORE2_PWR_CNTRL",  .addr = A_APU1_CORE2_PWR_CNTRL,
        .reset = 0xf,
        .rsvd = 0xffffffe0,
        .ro = 0xffffffe0,
        .post_write = psmx_local_postw,
    },{ .name = "APU1_CORE2_PWR_STATUS",  .addr = A_APU1_CORE2_PWR_STATUS,
        .reset = 0xf,
        .rsvd = 0xfffffff0,
        .ro = 0xffffffff,
    },{ .name = "APU1_CORE3_PWR_CNTRL",  .addr = A_APU1_CORE3_PWR_CNTRL,
        .reset = 0xf,
        .rsvd = 0xffffffe0,
        .ro = 0xffffffe0,
        .post_write = psmx_local_postw,
    },{ .name = "APU1_CORE3_PWR_STATUS",  .addr = A_APU1_CORE3_PWR_STATUS,
        .reset = 0xf,
        .rsvd = 0xfffffff0,
        .ro = 0xffffffff,
    },{ .name = "APU2_CORE0_PWR_CNTRL",  .addr = A_APU2_CORE0_PWR_CNTRL,
        .reset = 0xf,
        .rsvd = 0xffffffe0,
        .ro = 0xffffffe0,
        .post_write = psmx_local_postw,
    },{ .name = "APU2_CORE0_PWR_STATUS",  .addr = A_APU2_CORE0_PWR_STATUS,
        .reset = 0xf,
        .rsvd = 0xfffffff0,
        .ro = 0xffffffff,
    },{ .name = "APU2_CORE1_PWR_CNTRL",  .addr = A_APU2_CORE1_PWR_CNTRL,
        .reset = 0xf,
        .rsvd = 0xffffffe0,
        .ro = 0xffffffe0,
        .post_write = psmx_local_postw,
    },{ .name = "APU2_CORE1_PWR_STATUS",  .addr = A_APU2_CORE1_PWR_STATUS,
        .reset = 0xf,
        .rsvd = 0xfffffff0,
        .ro = 0xffffffff,
    },{ .name = "APU2_CORE2_PWR_CNTRL",  .addr = A_APU2_CORE2_PWR_CNTRL,
        .reset = 0xf,
        .rsvd = 0xffffffe0,
        .ro = 0xffffffe0,
        .post_write = psmx_local_postw,
    },{ .name = "APU2_CORE2_PWR_STATUS",  .addr = A_APU2_CORE2_PWR_STATUS,
        .reset = 0xf,
        .rsvd = 0xfffffff0,
        .ro = 0xffffffff,
    },{ .name = "APU2_CORE3_PWR_CNTRL",  .addr = A_APU2_CORE3_PWR_CNTRL,
        .reset = 0xf,
        .rsvd = 0xffffffe0,
        .ro = 0xffffffe0,
        .post_write = psmx_local_postw,
    },{ .name = "APU2_CORE3_PWR_STATUS",  .addr = A_APU2_CORE3_PWR_STATUS,
        .reset = 0xf,
        .rsvd = 0xfffffff0,
        .ro = 0xffffffff,
    },{ .name = "APU3_CORE0_PWR_CNTRL",  .addr = A_APU3_CORE0_PWR_CNTRL,
        .reset = 0xf,
        .rsvd = 0xffffffe0,
        .ro = 0xffffffe0,
        .post_write = psmx_local_postw,
    },{ .name = "APU3_CORE0_PWR_STATUS",  .addr = A_APU3_CORE0_PWR_STATUS,
        .reset = 0xf,
        .rsvd = 0xfffffff0,
        .ro = 0xffffffff,
    },{ .name = "APU3_CORE1_PWR_CNTRL",  .addr = A_APU3_CORE1_PWR_CNTRL,
        .reset = 0xf,
        .rsvd = 0xffffffe0,
        .ro = 0xffffffe0,
        .post_write = psmx_local_postw,
    },{ .name = "APU3_CORE1_PWR_STATUS",  .addr = A_APU3_CORE1_PWR_STATUS,
        .reset = 0xf,
        .rsvd = 0xfffffff0,
        .ro = 0xffffffff,
    },{ .name = "APU3_CORE2_PWR_CNTRL",  .addr = A_APU3_CORE2_PWR_CNTRL,
        .reset = 0xf,
        .rsvd = 0xffffffe0,
        .ro = 0xffffffe0,
        .post_write = psmx_local_postw,
    },{ .name = "APU3_CORE2_PWR_STATUS",  .addr = A_APU3_CORE2_PWR_STATUS,
        .reset = 0xf,
        .rsvd = 0xfffffff0,
        .ro = 0xffffffff,
    },{ .name = "APU3_CORE3_PWR_CNTRL",  .addr = A_APU3_CORE3_PWR_CNTRL,
        .reset = 0xf,
        .rsvd = 0xffffffe0,
        .ro = 0xffffffe0,
        .post_write = psmx_local_postw,
    },{ .name = "APU3_CORE3_PWR_STATUS",  .addr = A_APU3_CORE3_PWR_STATUS,
        .reset = 0xf,
        .rsvd = 0xfffffff0,
        .ro = 0xffffffff,
    },{ .name = "RPU_A_CORE0_PWR_CNTRL",  .addr = A_RPU_A_CORE0_PWR_CNTRL,
        .reset = 0xf,
        .rsvd = 0xffffffe0,
        .ro = 0xffffffe0,
        .post_write = psmx_local_postw,
    },{ .name = "RPU_A_CORE0_PWR_STATUS",  .addr = A_RPU_A_CORE0_PWR_STATUS,
        .reset = 0xf,
        .rsvd = 0xfffffff0,
        .ro = 0xffffffff,
    },{ .name = "RPU_A_CORE1_PWR_CNTRL",  .addr = A_RPU_A_CORE1_PWR_CNTRL,
        .reset = 0xf,
        .rsvd = 0xffffffe0,
        .ro = 0xffffffe0,
        .post_write = psmx_local_postw,
    },{ .name = "RPU_A_CORE1_PWR_STATUS",  .addr = A_RPU_A_CORE1_PWR_STATUS,
        .reset = 0xf,
        .rsvd = 0xfffffff0,
        .ro = 0xffffffff,
    },{ .name = "RPU_B_CORE0_PWR_CNTRL",  .addr = A_RPU_B_CORE0_PWR_CNTRL,
        .reset = 0xf,
        .rsvd = 0xffffffe0,
        .ro = 0xffffffe0,
        .post_write = psmx_local_postw,
    },{ .name = "RPU_B_CORE0_PWR_STATUS",  .addr = A_RPU_B_CORE0_PWR_STATUS,
        .reset = 0xf,
        .rsvd = 0xfffffff0,
        .ro = 0xffffffff,
    },{ .name = "RPU_B_CORE1_PWR_CNTRL",  .addr = A_RPU_B_CORE1_PWR_CNTRL,
        .reset = 0xf,
        .rsvd = 0xffffffe0,
        .ro = 0xffffffe0,
        .post_write = psmx_local_postw,
    },{ .name = "RPU_B_CORE1_PWR_STATUS",  .addr = A_RPU_B_CORE1_PWR_STATUS,
        .reset = 0xf,
        .rsvd = 0xfffffff0,
        .ro = 0xffffffff,
    },{ .name = "APU0_DSU_L3_PWR_CNTRL",  .addr = A_APU0_DSU_L3_PWR_CNTRL,
        .reset = 0x1ff,
        .rsvd = 0xfffffe00,
        .ro = 0xfffffe00,
        .post_write = psmx_local_postw,
    },{ .name = "APU0_DSU_L3_CE_CNTRL",  .addr = A_APU0_DSU_L3_CE_CNTRL,
        .reset = 0x1ff,
        .rsvd = 0xfffffe00,
        .ro = 0xfffffe00,
    },{ .name = "APU0_DSU_L3_PWR_STATUS",  .addr = A_APU0_DSU_L3_PWR_STATUS,
        .reset = 0x1ff,
        .rsvd = 0xfffffe00,
        .ro = 0xffffffff,
    },{ .name = "APU1_DSU_L3_PWR_CNTRL",  .addr = A_APU1_DSU_L3_PWR_CNTRL,
        .reset = 0x1ff,
        .rsvd = 0xfffffe00,
        .ro = 0xfffffe00,
        .post_write = psmx_local_postw,
    },{ .name = "APU1_DSU_L3_CE_CNTRL",  .addr = A_APU1_DSU_L3_CE_CNTRL,
        .reset = 0x1ff,
        .rsvd = 0xfffffe00,
        .ro = 0xfffffe00,
    },{ .name = "APU1_DSU_L3_PWR_STATUS",  .addr = A_APU1_DSU_L3_PWR_STATUS,
        .reset = 0x1ff,
        .rsvd = 0xfffffe00,
        .ro = 0xffffffff,
    },{ .name = "APU2_DSU_L3_PWR_CNTRL",  .addr = A_APU2_DSU_L3_PWR_CNTRL,
        .reset = 0x1ff,
        .rsvd = 0xfffffe00,
        .ro = 0xfffffe00,
        .post_write = psmx_local_postw,
    },{ .name = "APU2_DSU_L3_CE_CNTRL",  .addr = A_APU2_DSU_L3_CE_CNTRL,
        .reset = 0x1ff,
        .rsvd = 0xfffffe00,
        .ro = 0xfffffe00,
    },{ .name = "APU2_DSU_L3_PWR_STATUS",  .addr = A_APU2_DSU_L3_PWR_STATUS,
        .reset = 0x1ff,
        .rsvd = 0xfffffe00,
        .ro = 0xffffffff,
    },{ .name = "APU3_DSU_L3_PWR_CNTRL",  .addr = A_APU3_DSU_L3_PWR_CNTRL,
        .reset = 0x1ff,
        .rsvd = 0xfffffe00,
        .ro = 0xfffffe00,
        .post_write = psmx_local_postw,
    },{ .name = "APU3_DSU_L3_CE_CNTRL",  .addr = A_APU3_DSU_L3_CE_CNTRL,
        .reset = 0x1ff,
        .rsvd = 0xfffffe00,
        .ro = 0xfffffe00,
    },{ .name = "APU3_DSU_L3_PWR_STATUS",  .addr = A_APU3_DSU_L3_PWR_STATUS,
        .reset = 0x1ff,
        .rsvd = 0xfffffe00,
        .ro = 0xffffffff,
    },{ .name = "RPU_CACHE_PWR_CNTRL",  .addr = A_RPU_CACHE_PWR_CNTRL,
        .reset = 0xf,
        .rsvd = 0xfffffff0,
        .ro = 0xfffffff0,
        .post_write = psmx_local_postw,
    },{ .name = "RPU_CACHE_CE_CNTRL",  .addr = A_RPU_CACHE_CE_CNTRL,
        .reset = 0xf,
        .rsvd = 0xfffffff0,
        .ro = 0xfffffff0,
    },{ .name = "RPU_CACHE_PWR_STATUS",  .addr = A_RPU_CACHE_PWR_STATUS,
        .rsvd = 0xfffffff0,
        .ro = 0xffffffff,
    },{ .name = "OCM_PWR_CNTRL",  .addr = A_OCM_PWR_CNTRL,
        .reset = 0xf0f,
        .rsvd = 0xfffff0f0,
        .ro = 0xfffff0f0,
        .post_write = psmx_local_postw,
    },{ .name = "OCM_RET_CNTRL",  .addr = A_OCM_RET_CNTRL,
        .rsvd = 0xfffff0f0,
        .ro = 0xfffff0f0,
    },{ .name = "OCM_CE_CNTRL",  .addr = A_OCM_CE_CNTRL,
        .reset = 0xf0f,
        .rsvd = 0xfffff0f0,
        .ro = 0xfffff0f0,
    },{ .name = "OCM_PWR_STATUS",  .addr = A_OCM_PWR_STATUS,
        .reset = 0xf0f,
        .rsvd = 0xfffff0f0,
        .ro = 0xffffffff,
    },{ .name = "TCM_PWR_CNTRL",  .addr = A_TCM_PWR_CNTRL,
        .reset = 0x1010101,
        .rsvd = 0xfefefefe,
        .ro = 0xfefefefe,
        .post_write = psmx_local_postw,
    },{ .name = "TCM_RET_CNTRL",  .addr = A_TCM_RET_CNTRL,
        .rsvd = 0xfefefefe,
        .ro = 0xfefefefe,
    },{ .name = "TCM_CE_CNTRL",  .addr = A_TCM_CE_CNTRL,
        .reset = 0x1010101,
        .rsvd = 0xfefefefe,
        .ro = 0xfefefefe,
    },{ .name = "TCM_PWR_STATUS",  .addr = A_TCM_PWR_STATUS,
        .rsvd = 0xfefefefe,
        .ro = 0xffffffff,
    },{ .name = "GEM_PWR_CNTRL",  .addr = A_GEM_PWR_CNTRL,
        .reset = 0x101,
        .rsvd = 0xfffffefe,
        .ro = 0xfffffefe,
        .post_write = psmx_local_postw,
    },{ .name = "GEM_CE_CNTRL",  .addr = A_GEM_CE_CNTRL,
        .reset = 0x3,
        .rsvd = 0xfffffffc,
        .ro = 0xfffffffc,
    },{ .name = "GEM_PWR_STATUS",  .addr = A_GEM_PWR_STATUS,
        .reset = 0x101,
        .rsvd = 0xfffffefe,
        .ro = 0xffffffff,
    },{ .name = "DOMAIN_ISO_CNTRL",  .addr = A_DOMAIN_ISO_CNTRL,
        .reset = 0x7f,
        .rsvd = 0xffffffc0,
        .ro = 0xffffffc0,
    },{ .name = "LOC_PWR_STATE0",  .addr = A_LOC_PWR_STATE0,
        .reset = 0xffffffff,
        .post_write = psmx_local_postw,
    },{ .name = "LOC_PWR_STATE1",  .addr = A_LOC_PWR_STATE1,
        .reset = 0x7,
        .rsvd = 0xfffffff8,
        .post_write = psmx_local_postw,
    },{ .name = "LOC_AUX_PWR_STATE",  .addr = A_LOC_AUX_PWR_STATE,
        .post_write = psmx_local_postw,
    },{ .name = "LOCAL_GEN_STORAGE0",  .addr = A_LOCAL_GEN_STORAGE0,
    },{ .name = "LOCAL_GEN_STORAGE1",  .addr = A_LOCAL_GEN_STORAGE1,
    },{ .name = "LOCAL_GEN_STORAGE2",  .addr = A_LOCAL_GEN_STORAGE2,
    },{ .name = "LOCAL_GEN_STORAGE3",  .addr = A_LOCAL_GEN_STORAGE3,
    },{ .name = "PERS_LOC_GEN_STORAGE0",  .addr = A_PERS_LOC_GEN_STORAGE0,
    },{ .name = "PERS_LOC_GEN_STORAGE1",  .addr = A_PERS_LOC_GEN_STORAGE1,
    },{ .name = "PERS_LOC_GEN_STORAGE2",  .addr = A_PERS_LOC_GEN_STORAGE2,
    },{ .name = "PERS_LOC_GEN_STORAGE3",  .addr = A_PERS_LOC_GEN_STORAGE3,
    },{ .name = "ADDR_ERROR_STATUS",  .addr = A_ADDR_ERROR_STATUS,
        .w1c = 0x1,
        .post_write = addr_error_status_postw,
    },{ .name = "ADDR_ERROR_INT_MASK",  .addr = A_ADDR_ERROR_INT_MASK,
        .reset = 0x1,
        .ro = 0x1,
    },{ .name = "ADDR_ERROR_INT_EN",  .addr = A_ADDR_ERROR_INT_EN,
        .pre_write = addr_error_int_en_prew,
    },{ .name = "ADDR_ERROR_INT_DIS",  .addr = A_ADDR_ERROR_INT_DIS,
        .pre_write = addr_error_int_dis_prew,
    },{ .name = "PSM_GLOBAL_APB",  .addr = A_PSM_GLOBAL_APB,
        .reset = 0x16,
        .rsvd = 0xffffffe0,
        .ro = 0x6,
    },{ .name = "ECO_2",  .addr = A_ECO_2,
        .reset = 0xfc000000,
    }
};

static void psmx_local_reg_reset_enter(Object *obj, ResetType type)
{
    PSMX_LOCAL_REG *s = XILINX_PSMX_LOCAL_REG(obj);
    unsigned int i;

    for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
        switch (i) {
        case A_PERS_LOC_GEN_STORAGE0...A_PERS_LOC_GEN_STORAGE3:
            break;
        default:
            register_reset(&s->regs_info[i]);
        };
    }
}

static void psmx_local_reg_reset_hold(Object *obj)
{
    PSMX_LOCAL_REG *s = XILINX_PSMX_LOCAL_REG(obj);

    addr_error_int_update_irq(s);
    psmx_update_pwr_status(s);
}

static void psmx_local_linux_boot_if_init(ARMLinuxBootIf *obj, bool secure_boot)
{
    PSMX_LOCAL_REG *s = XILINX_PSMX_LOCAL_REG(obj);

    ARRAY_FIELD_DP32(s->regs, APU0_CORE0_PWR_CNTRL, PWR_GATES, 0);
    ARRAY_FIELD_DP32(s->regs, APU0_CORE1_PWR_CNTRL, PWR_GATES, 0);
    ARRAY_FIELD_DP32(s->regs, APU0_CORE2_PWR_CNTRL, PWR_GATES, 0);
    ARRAY_FIELD_DP32(s->regs, APU0_CORE3_PWR_CNTRL, PWR_GATES, 0);

    ARRAY_FIELD_DP32(s->regs, APU1_CORE0_PWR_CNTRL, PWR_GATES, 0);
    ARRAY_FIELD_DP32(s->regs, APU1_CORE1_PWR_CNTRL, PWR_GATES, 0);
    ARRAY_FIELD_DP32(s->regs, APU1_CORE2_PWR_CNTRL, PWR_GATES, 0);
    ARRAY_FIELD_DP32(s->regs, APU1_CORE3_PWR_CNTRL, PWR_GATES, 0);

    ARRAY_FIELD_DP32(s->regs, APU2_CORE0_PWR_CNTRL, PWR_GATES, 0);
    ARRAY_FIELD_DP32(s->regs, APU2_CORE1_PWR_CNTRL, PWR_GATES, 0);
    ARRAY_FIELD_DP32(s->regs, APU2_CORE2_PWR_CNTRL, PWR_GATES, 0);
    ARRAY_FIELD_DP32(s->regs, APU2_CORE3_PWR_CNTRL, PWR_GATES, 0);

    ARRAY_FIELD_DP32(s->regs, APU3_CORE0_PWR_CNTRL, PWR_GATES, 0);
    ARRAY_FIELD_DP32(s->regs, APU3_CORE1_PWR_CNTRL, PWR_GATES, 0);
    ARRAY_FIELD_DP32(s->regs, APU3_CORE2_PWR_CNTRL, PWR_GATES, 0);
    ARRAY_FIELD_DP32(s->regs, APU3_CORE3_PWR_CNTRL, PWR_GATES, 0);

    ARRAY_FIELD_DP32(s->regs, RPU_A_CORE0_PWR_CNTRL, PWR_GATES, 0);
    ARRAY_FIELD_DP32(s->regs, RPU_A_CORE1_PWR_CNTRL, PWR_GATES, 0);

    ARRAY_FIELD_DP32(s->regs, RPU_B_CORE0_PWR_CNTRL, PWR_GATES, 0);
    ARRAY_FIELD_DP32(s->regs, RPU_B_CORE1_PWR_CNTRL, PWR_GATES, 0);
    psmx_update_pwr_status(s);

    s->linux_direct_boot = true;
}

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

static void psmx_local_reg_init(Object *obj)
{
    PSMX_LOCAL_REG *s = XILINX_PSMX_LOCAL_REG(obj);
    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
    RegisterInfoArray *reg_array;

    memory_region_init(&s->iomem, obj, TYPE_XILINX_PSMX_LOCAL_REG,
                       PSMX_LOCAL_REG_R_MAX * 4);
    reg_array =
        register_init_block32(DEVICE(obj), psmx_local_reg_regs_info,
                              ARRAY_SIZE(psmx_local_reg_regs_info),
                              s->regs_info, s->regs,
                              &psmx_local_reg_ops,
                              XILINX_PSMX_LOCAL_REG_ERR_DEBUG,
                              PSMX_LOCAL_REG_R_MAX * 4);
    memory_region_add_subregion(&s->iomem,
                                0x0,
                                &reg_array->mem);
    sysbus_init_mmio(sbd, &s->iomem);
    sysbus_init_irq(sbd, &s->irq_addr_error_int);
    qdev_init_gpio_out_named(DEVICE(obj), s->pwr_apu0, "pwr-apu0", 4);
    qdev_init_gpio_out_named(DEVICE(obj), s->pwr_apu1, "pwr-apu1", 4);
    qdev_init_gpio_out_named(DEVICE(obj), s->pwr_apu2, "pwr-apu2", 4);
    qdev_init_gpio_out_named(DEVICE(obj), s->pwr_apu3, "pwr-apu3", 4);
    qdev_init_gpio_out_named(DEVICE(obj), s->pwr_rpu_a, "pwr-rpu-a", 2);
    qdev_init_gpio_out_named(DEVICE(obj), s->pwr_rpu_b, "pwr-rpu-b", 2);
    qdev_init_gpio_out_named(DEVICE(obj), s->pwr_tcm, "pwr-tcm", 4);
    qdev_init_gpio_out_named(DEVICE(obj), s->pwr_ocm, "pwr-ocm", 8);
    qdev_init_gpio_out_named(DEVICE(obj), s->pwr_gem, "pwr-gem", 2);
    qdev_init_gpio_out_named(DEVICE(obj), &s->pwr_fp, "pwr-fp", 1);
    qdev_init_gpio_out_named(DEVICE(obj), s->loc_pwr_state0,
                                          "loc-pwr-state0", 32);
    qdev_init_gpio_out_named(DEVICE(obj), s->loc_pwr_state1,
                                          "loc-pwr-state1", 3);
    qdev_init_gpio_out_named(DEVICE(obj), s->loc_aux_pwr_state,
                                          "loc-aux-pwr-state", 32);
}

static const VMStateDescription vmstate_psmx_local_reg = {
    .name = TYPE_XILINX_PSMX_LOCAL_REG,
    .version_id = 1,
    .minimum_version_id = 1,
    .fields = (VMStateField[]) {
        VMSTATE_UINT32_ARRAY(regs, PSMX_LOCAL_REG, PSMX_LOCAL_REG_R_MAX),
        VMSTATE_END_OF_LIST(),
    }
};

static const FDTGenericGPIOSet psmx_local_reg_gpios[] = {
    {
        .names = &fdt_generic_gpio_name_set_gpio,
        .gpios = (FDTGenericGPIOConnection[]) {
          { .name = "pwr-apu0", .fdt_index = 0, .range = 4 },
          { .name = "pwr-apu1", .fdt_index = 4, .range = 4 },
          { .name = "pwr-apu2", .fdt_index = 8, .range = 4 },
          { .name = "pwr-apu3", .fdt_index = 12, .range = 4 },
          { .name = "pwr-rpu-a", .fdt_index = 16, .range = 2 },
          { .name = "pwr-rpu-b", .fdt_index = 18, .range = 2 },
          { .name = "pwr-tcm", .fdt_index = 20, .range = 4 },
          { .name = "pwr-ocm", .fdt_index = 24, .range = 8 },
          { .name = "pwr-gem", .fdt_index = 32, .range = 2 },
          { .name = "pwr-fp", .fdt_index = 34, .range = 1 },
          { .name = "loc-pwr-state0", .fdt_index = 35, .range = 32 },
          { .name = "loc-pwr-state1", .fdt_index = 67, .range = 3},
          { .name = "loc-aux-pwr-state", .fdt_index = 70, .range = 32 },
          { },
        },
    },
    { },
};

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

    dc->vmsd = &vmstate_psmx_local_reg;
    rc->phases.enter = psmx_local_reg_reset_enter;
    rc->phases.hold = psmx_local_reg_reset_hold;
    fggc->controller_gpios = psmx_local_reg_gpios;
    albifc->arm_linux_init = psmx_local_linux_boot_if_init;
}

static const TypeInfo psmx_local_reg_info = {
    .name          = TYPE_XILINX_PSMX_LOCAL_REG,
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(PSMX_LOCAL_REG),
    .class_init    = psmx_local_reg_class_init,
    .instance_init = psmx_local_reg_init,
    .interfaces    = (InterfaceInfo[]) {
        { TYPE_FDT_GENERIC_GPIO },
        { TYPE_ARM_LINUX_BOOT_IF },
        { }
    },
};

static void psmx_local_reg_register_types(void)
{
    type_register_static(&psmx_local_reg_info);
}

type_init(psmx_local_reg_register_types)
