/*
 * QEMU model of the PMC_GLOBAL This is the database for the
 * PMC Global Register Definitions.
 *
 * Copyright (c) 2017-2022, Xilinx Inc.
 * Copyright (c) 2022-2024, Advanced Micro Devices, Inc.
 *
 * 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.
 */

/* Partially autogenerated by xregqemu.py 2017-03-28.  */

#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 "qemu/error-report.h"
#include "migration/vmstate.h"
#include "sysemu/runstate.h"
#include "hw/qdev-properties.h"
#include "qemu/option.h"
#include "qemu/config-file.h"
#include "hw/misc/xlnx-versal-pmc.h"

#include "hw/fdt_generic_util.h"
#include "hw/nvram/xlnx-efuse.h"
#include "hw/nvram/xlnx-versal-efuse.h"
#include "xlnx-versal-ams.h"

#ifndef XILINX_PMC_GLOBAL_ERR_DEBUG
#define XILINX_PMC_GLOBAL_ERR_DEBUG 0
#endif

#define TYPE_XILINX_PMC_GLOBAL "xlnx.pmc_global"

#define XILINX_PMC_GLOBAL(obj) \
     OBJECT_CHECK(PMC_GLOBAL, (obj), TYPE_XILINX_PMC_GLOBAL)

REG32(GLOBAL_CNTRL, 0x0)
    FIELD(GLOBAL_CNTRL, MB_CLK_EN_FORCE, 18, 1)
    FIELD(GLOBAL_CNTRL, MB_DBG_WAKE, 17, 1)
    FIELD(GLOBAL_CNTRL, MB_SLEEP, 16, 1)
    FIELD(GLOBAL_CNTRL, WRITE_QOS, 12, 4)
    FIELD(GLOBAL_CNTRL, READ_QOS, 8, 4)
    FIELD(GLOBAL_CNTRL, FW_IS_PRESENT, 4, 1)
    FIELD(GLOBAL_CNTRL, COHERENT, 2, 1)
    FIELD(GLOBAL_CNTRL, SLVERR_ENABLE, 1, 1)
    FIELD(GLOBAL_CNTRL, DONT_SLEEP, 0, 1)
REG32(PMC_MULTI_BOOT, 0x4)
REG32(PPU1_TRM_CTRL, 0x8)
    FIELD(PPU1_TRM_CTRL, EN_LMB_UE_FATAL, 0, 1)
REG32(PMC_GLOBAL_ISR, 0x10)
    FIELD(PMC_GLOBAL_ISR, TAMPER_INT, 3, 1)
    FIELD(PMC_GLOBAL_ISR, PUF_ACC_ERROR, 2, 1)
    FIELD(PMC_GLOBAL_ISR, SSS_CFG_ERR, 1, 1)
    FIELD(PMC_GLOBAL_ISR, ADDR_ERR, 0, 1)
REG32(PMC_GLOBAL_IMR, 0x14)
    FIELD(PMC_GLOBAL_IMR, TAMPER_INT, 3, 1)
    FIELD(PMC_GLOBAL_IMR, PUF_ACC_ERROR, 2, 1)
    FIELD(PMC_GLOBAL_IMR, SSS_CFG_ERR, 1, 1)
    FIELD(PMC_GLOBAL_IMR, ADDR_ERR, 0, 1)
REG32(PMC_GLOBAL_IER, 0x18)
    FIELD(PMC_GLOBAL_IER, TAMPER_INT, 3, 1)
    FIELD(PMC_GLOBAL_IER, PUF_ACC_ERROR, 2, 1)
    FIELD(PMC_GLOBAL_IER, SSS_CFG_ERR, 1, 1)
    FIELD(PMC_GLOBAL_IER, ADDR_ERR, 0, 1)
REG32(PMC_GLOBAL_IDR, 0x1c)
    FIELD(PMC_GLOBAL_IDR, TAMPER_INT, 3, 1)
    FIELD(PMC_GLOBAL_IDR, PUF_ACC_ERROR, 2, 1)
    FIELD(PMC_GLOBAL_IDR, SSS_CFG_ERR, 1, 1)
    FIELD(PMC_GLOBAL_IDR, ADDR_ERR_DIS, 0, 1)
REG32(PPU1_DEBUG_CTRL, 0x20)
    FIELD(PPU1_DEBUG_CTRL, EN, 0, 1)
REG32(PPU1_DEBUG_LOCK, 0x24)
    FIELD(PPU1_DEBUG_LOCK, DIS, 0, 1)
REG32(GLOBAL_GEN_STORAGE0, 0x30)
REG32(GLOBAL_GEN_STORAGE1, 0x34)
REG32(GLOBAL_GEN_STORAGE2, 0x38)
REG32(GLOBAL_GEN_STORAGE3, 0x3c)
REG32(GLOBAL_GEN_STORAGE4, 0x40)
REG32(PERS_GLOB_GEN_STORAGE0, 0x50)
REG32(PERS_GLOB_GEN_STORAGE1, 0x54)
REG32(PERS_GLOB_GEN_STORAGE2, 0x58)
REG32(PERS_GLOB_GEN_STORAGE3, 0x5c)
REG32(PERS_GLOB_GEN_STORAGE4, 0x60)
REG32(PMC_GSW_ERR, 0x64)
    FIELD(PMC_GSW_ERR, NCR_FLAG, 31, 1)
    FIELD(PMC_GSW_ERR, CR_FLAG, 30, 1)
    FIELD(PMC_GSW_ERR, DATA, 0, 30)
REG32(PWR_STATUS, 0x100)
    FIELD(PWR_STATUS, VCCAUX_VCCRAM, 18, 1)
    FIELD(PWR_STATUS, VCCRAM_SOC, 17, 1)
    FIELD(PWR_STATUS, VCCAUX_SOC, 16, 1)
    FIELD(PWR_STATUS, PL_SOC, 15, 1)
    FIELD(PWR_STATUS, PMC_SOC, 14, 1)
    FIELD(PWR_STATUS, PMC_SOC_NPI, 13, 1)
    FIELD(PWR_STATUS, PMC_PL, 12, 1)
    FIELD(PWR_STATUS, PMC_PL_TEST, 11, 1)
    FIELD(PWR_STATUS, PMC_PL_CFRAME, 10, 1)
    FIELD(PWR_STATUS, PMC_LPD, 9, 1)
    FIELD(PWR_STATUS, PMC_LPD_DFX, 8, 1)
    FIELD(PWR_STATUS, LPD_SOC, 7, 1)
    FIELD(PWR_STATUS, LPD_PL, 6, 1)
    FIELD(PWR_STATUS, LPD_PL_TEST, 5, 1)
    FIELD(PWR_STATUS, LPD_CPM, 4, 1)
    FIELD(PWR_STATUS, LPD_CPM_DFX, 3, 1)
    FIELD(PWR_STATUS, FPD_SOC, 2, 1)
    FIELD(PWR_STATUS, FPD_PL, 1, 1)
    FIELD(PWR_STATUS, FPD_PL_TEST, 0, 1)
REG32(PWR_SUPPLY_STATUS, 0x10c)
    FIELD(PWR_SUPPLY_STATUS, VCCINT_RAM, 7, 1)
    FIELD(PWR_SUPPLY_STATUS, VCCINT_PL, 6, 1)
    FIELD(PWR_SUPPLY_STATUS, VCCAUX, 5, 1)
    FIELD(PWR_SUPPLY_STATUS, VCCINT_SOC, 4, 1)
    FIELD(PWR_SUPPLY_STATUS, VCCINT_LPD, 3, 1)
    FIELD(PWR_SUPPLY_STATUS, VCCINT_FPD, 2, 1)
    FIELD(PWR_SUPPLY_STATUS, VCCINT_PMC, 1, 1)
    FIELD(PWR_SUPPLY_STATUS, VCCAUX_PMC, 0, 1)
REG32(REQ_PWRUP_STATUS, 0x110)
    FIELD(REQ_PWRUP_STATUS, PL, 2, 1)
    FIELD(REQ_PWRUP_STATUS, SOC, 1, 1)
    FIELD(REQ_PWRUP_STATUS, LPD, 0, 1)
REG32(REQ_PWRUP_INT_MASK, 0x114)
    FIELD(REQ_PWRUP_INT_MASK, PL, 2, 1)
    FIELD(REQ_PWRUP_INT_MASK, SOC, 1, 1)
    FIELD(REQ_PWRUP_INT_MASK, LPD, 0, 1)
REG32(REQ_PWRUP_INT_EN, 0x118)
    FIELD(REQ_PWRUP_INT_EN, PL, 2, 1)
    FIELD(REQ_PWRUP_INT_EN, SOC, 1, 1)
    FIELD(REQ_PWRUP_INT_EN, LPD, 0, 1)
REG32(REQ_PWRUP_INT_DIS, 0x11c)
    FIELD(REQ_PWRUP_INT_DIS, PL, 2, 1)
    FIELD(REQ_PWRUP_INT_DIS, SOC, 1, 1)
    FIELD(REQ_PWRUP_INT_DIS, LPD, 0, 1)
REG32(REQ_PWRUP_TRIG, 0x120)
    FIELD(REQ_PWRUP_TRIG, PL, 2, 1)
    FIELD(REQ_PWRUP_TRIG, SOC, 1, 1)
    FIELD(REQ_PWRUP_TRIG, LPD, 0, 1)
REG32(REQ_PWRDWN_STATUS, 0x210)
    FIELD(REQ_PWRDWN_STATUS, PL, 2, 1)
    FIELD(REQ_PWRDWN_STATUS, SOC, 1, 1)
    FIELD(REQ_PWRDWN_STATUS, LPD, 0, 1)
REG32(REQ_PWRDWN_INT_MASK, 0x214)
    FIELD(REQ_PWRDWN_INT_MASK, PL, 2, 1)
    FIELD(REQ_PWRDWN_INT_MASK, SOC, 1, 1)
    FIELD(REQ_PWRDWN_INT_MASK, LPD, 0, 1)
REG32(REQ_PWRDWN_INT_EN, 0x218)
    FIELD(REQ_PWRDWN_INT_EN, PL, 2, 1)
    FIELD(REQ_PWRDWN_INT_EN, SOC, 1, 1)
    FIELD(REQ_PWRDWN_INT_EN, LPD, 0, 1)
REG32(REQ_PWRDWN_INT_DIS, 0x21c)
    FIELD(REQ_PWRDWN_INT_DIS, PL, 2, 1)
    FIELD(REQ_PWRDWN_INT_DIS, SOC, 1, 1)
    FIELD(REQ_PWRDWN_INT_DIS, LPD, 0, 1)
REG32(REQ_PWRDWN_TRIG, 0x220)
    FIELD(REQ_PWRDWN_TRIG, PL, 2, 1)
    FIELD(REQ_PWRDWN_TRIG, SOC, 1, 1)
    FIELD(REQ_PWRDWN_TRIG, LPD, 0, 1)
REG32(REQ_ISO_STATUS, 0x310)
    FIELD(REQ_ISO_STATUS, PL, 2, 1)
    FIELD(REQ_ISO_STATUS, SOC, 1, 1)
    FIELD(REQ_ISO_STATUS, LPD, 0, 1)
REG32(REQ_ISO_INT_MASK, 0x314)
    FIELD(REQ_ISO_INT_MASK, PL, 2, 1)
    FIELD(REQ_ISO_INT_MASK, SOC, 1, 1)
    FIELD(REQ_ISO_INT_MASK, LPD, 0, 1)
REG32(REQ_ISO_INT_EN, 0x318)
    FIELD(REQ_ISO_INT_EN, PL, 2, 1)
    FIELD(REQ_ISO_INT_EN, SOC, 1, 1)
    FIELD(REQ_ISO_INT_EN, LPD, 0, 1)
REG32(REQ_ISO_INT_DIS, 0x31c)
    FIELD(REQ_ISO_INT_DIS, PL, 2, 1)
    FIELD(REQ_ISO_INT_DIS, SOC, 1, 1)
    FIELD(REQ_ISO_INT_DIS, LPD, 0, 1)
REG32(REQ_ISO_TRIG, 0x320)
    FIELD(REQ_ISO_TRIG, PL, 2, 1)
    FIELD(REQ_ISO_TRIG, SOC, 1, 1)
    FIELD(REQ_ISO_TRIG, LPD, 0, 1)
REG32(DDR_RETENTION, 0x324)
    FIELD(DDR_RETENTION, VALUE, 0, 1)
REG32(USR_GTS, 0x328)
    FIELD(USR_GTS, USR_GTS, 0, 1)
REG32(REQ_SWRST_STATUS, 0x410)
    FIELD(REQ_SWRST_STATUS, PL, 3, 1)
    FIELD(REQ_SWRST_STATUS, SOC, 2, 1)
    FIELD(REQ_SWRST_STATUS, LPD, 1, 1)
    FIELD(REQ_SWRST_STATUS, PS_ONLY, 0, 1)
REG32(REQ_SWRST_INT_MASK, 0x414)
    FIELD(REQ_SWRST_INT_MASK, PL, 3, 1)
    FIELD(REQ_SWRST_INT_MASK, SOC, 2, 1)
    FIELD(REQ_SWRST_INT_MASK, LPD, 1, 1)
    FIELD(REQ_SWRST_INT_MASK, PS_ONLY, 0, 1)
REG32(REQ_SWRST_INT_EN, 0x418)
    FIELD(REQ_SWRST_INT_EN, PL, 3, 1)
    FIELD(REQ_SWRST_INT_EN, SOC, 2, 1)
    FIELD(REQ_SWRST_INT_EN, LPD, 1, 1)
    FIELD(REQ_SWRST_INT_EN, PS_ONLY, 0, 1)
REG32(REQ_SWRST_INT_DIS, 0x41c)
    FIELD(REQ_SWRST_INT_DIS, PL, 3, 1)
    FIELD(REQ_SWRST_INT_DIS, SOC, 2, 1)
    FIELD(REQ_SWRST_INT_DIS, LPD, 1, 1)
    FIELD(REQ_SWRST_INT_DIS, PS_ONLY, 0, 1)
REG32(REQ_SWRST_TRIG, 0x420)
    FIELD(REQ_SWRST_TRIG, PL, 3, 1)
    FIELD(REQ_SWRST_TRIG, SOC, 2, 1)
    FIELD(REQ_SWRST_TRIG, LPD, 1, 1)
    FIELD(REQ_SWRST_TRIG, PS_ONLY, 0, 1)
REG32(WAKEUP_IRQ_STATUS, 0x430)
    FIELD(WAKEUP_IRQ_STATUS, CPM_CORESIGHT, 1, 1)
    FIELD(WAKEUP_IRQ_STATUS, LPD_CORESIGHT, 0, 1)
REG32(WAKEUP_IRQ_MASK, 0x434)
    FIELD(WAKEUP_IRQ_MASK, CPM_CORESIGHT, 1, 1)
    FIELD(WAKEUP_IRQ_MASK, LPD_CORESIGHT, 0, 1)
REG32(WAKEUP_IRQ_EN, 0x438)
    FIELD(WAKEUP_IRQ_EN, CPM_CORESIGHT, 1, 1)
    FIELD(WAKEUP_IRQ_EN, LPD_CORESIGHT, 0, 1)
REG32(WAKEUP_IRQ_DIS, 0x43c)
    FIELD(WAKEUP_IRQ_DIS, CPM_CORESIGHT, 1, 1)
    FIELD(WAKEUP_IRQ_DIS, LPD_CORESIGHT, 0, 1)
REG32(WAKEUP_IRQ_TRIG, 0x440)
    FIELD(WAKEUP_IRQ_TRIG, CPM_CORESIGHT, 1, 1)
    FIELD(WAKEUP_IRQ_TRIG, LPD_CORESIGHT, 0, 1)
REG32(DBG_PWR_ACK, 0x444)
    FIELD(DBG_PWR_ACK, CPM_CORESIGHT, 1, 1)
    FIELD(DBG_PWR_ACK, LPD_CORESIGHT, 0, 1)
REG32(PMC_SSS_CFG, 0x500)
    FIELD(PMC_SSS_CFG, SBI_CFG, 20, 4)
    FIELD(PMC_SSS_CFG, SHA_CFG, 16, 4)
    FIELD(PMC_SSS_CFG, AES_CFG, 12, 4)
    FIELD(PMC_SSS_CFG, PTPI_CFG, 8, 4)
    FIELD(PMC_SSS_CFG, DMA1_CFG, 4, 4)
    FIELD(PMC_SSS_CFG, DMA0_CFG, 0, 4)
REG32(TEST_PATTERN_CFG, 0x514)
    FIELD(TEST_PATTERN_CFG, VALUE, 0, 2)
REG32(PRAM_ZEROIZE_SIZE, 0x518)
REG32(TAMPER_RESP_0, 0x530)
    FIELD(TAMPER_RESP_0, BBRAM_ERASE, 4, 1)
    FIELD(TAMPER_RESP_0, SYS_LOCKDOWN_1, 3, 1)
    FIELD(TAMPER_RESP_0, SYS_LOCKDOWN_0, 2, 1)
    FIELD(TAMPER_RESP_0, SYS_RESET, 1, 1)
    FIELD(TAMPER_RESP_0, SYS_INTERRUPT, 0, 1)
REG32(TAMPER_RESP_1, 0x534)
    FIELD(TAMPER_RESP_1, BBRAM_ERASE, 4, 1)
    FIELD(TAMPER_RESP_1, SYS_LOCKDOWN_1, 3, 1)
    FIELD(TAMPER_RESP_1, SYS_LOCKDOWN_0, 2, 1)
    FIELD(TAMPER_RESP_1, SYS_RESET, 1, 1)
    FIELD(TAMPER_RESP_1, SYS_INTERRUPT, 0, 1)
REG32(TAMPER_RESP_2, 0x538)
    FIELD(TAMPER_RESP_2, BBRAM_ERASE, 4, 1)
    FIELD(TAMPER_RESP_2, SYS_LOCKDOWN_1, 3, 1)
    FIELD(TAMPER_RESP_2, SYS_LOCKDOWN_0, 2, 1)
    FIELD(TAMPER_RESP_2, SYS_RESET, 1, 1)
    FIELD(TAMPER_RESP_2, SYS_INTERRUPT, 0, 1)
REG32(TAMPER_RESP_3, 0x53c)
    FIELD(TAMPER_RESP_3, BBRAM_ERASE, 4, 1)
    FIELD(TAMPER_RESP_3, SYS_LOCKDOWN_1, 3, 1)
    FIELD(TAMPER_RESP_3, SYS_LOCKDOWN_0, 2, 1)
    FIELD(TAMPER_RESP_3, SYS_RESET, 1, 1)
    FIELD(TAMPER_RESP_3, SYS_INTERRUPT, 0, 1)
REG32(TAMPER_RESP_4, 0x540)
    FIELD(TAMPER_RESP_4, BBRAM_ERASE, 4, 1)
    FIELD(TAMPER_RESP_4, SYS_LOCKDOWN_1, 3, 1)
    FIELD(TAMPER_RESP_4, SYS_LOCKDOWN_0, 2, 1)
    FIELD(TAMPER_RESP_4, SYS_RESET, 1, 1)
    FIELD(TAMPER_RESP_4, SYS_INTERRUPT, 0, 1)
REG32(TAMPER_RESP_5, 0x544)
    FIELD(TAMPER_RESP_5, BBRAM_ERASE, 4, 1)
    FIELD(TAMPER_RESP_5, SYS_LOCKDOWN_1, 3, 1)
    FIELD(TAMPER_RESP_5, SYS_LOCKDOWN_0, 2, 1)
    FIELD(TAMPER_RESP_5, SYS_RESET, 1, 1)
    FIELD(TAMPER_RESP_5, SYS_INTERRUPT, 0, 1)
REG32(TAMPER_RESP_6, 0x548)
    FIELD(TAMPER_RESP_6, BBRAM_ERASE, 4, 1)
    FIELD(TAMPER_RESP_6, SYS_LOCKDOWN_1, 3, 1)
    FIELD(TAMPER_RESP_6, SYS_LOCKDOWN_0, 2, 1)
    FIELD(TAMPER_RESP_6, SYS_RESET, 1, 1)
    FIELD(TAMPER_RESP_6, SYS_INTERRUPT, 0, 1)
REG32(TAMPER_RESP_7, 0x54c)
    FIELD(TAMPER_RESP_7, BBRAM_ERASE, 4, 1)
    FIELD(TAMPER_RESP_7, SYS_LOCKDOWN_1, 3, 1)
    FIELD(TAMPER_RESP_7, SYS_LOCKDOWN_0, 2, 1)
    FIELD(TAMPER_RESP_7, SYS_RESET, 1, 1)
    FIELD(TAMPER_RESP_7, SYS_INTERRUPT, 0, 1)
REG32(TAMPER_RESP_8, 0x550)
    FIELD(TAMPER_RESP_8, BBRAM_ERASE, 4, 1)
    FIELD(TAMPER_RESP_8, SYS_LOCKDOWN_1, 3, 1)
    FIELD(TAMPER_RESP_8, SYS_LOCKDOWN_0, 2, 1)
    FIELD(TAMPER_RESP_8, SYS_RESET, 1, 1)
    FIELD(TAMPER_RESP_8, SYS_INTERRUPT, 0, 1)
REG32(TAMPER_RESP_9, 0x554)
    FIELD(TAMPER_RESP_9, BBRAM_ERASE, 4, 1)
    FIELD(TAMPER_RESP_9, SYS_LOCKDOWN_1, 3, 1)
    FIELD(TAMPER_RESP_9, SYS_LOCKDOWN_0, 2, 1)
    FIELD(TAMPER_RESP_9, SYS_RESET, 1, 1)
    FIELD(TAMPER_RESP_9, SYS_INTERRUPT, 0, 1)
REG32(TAMPER_RESP_10, 0x558)
    FIELD(TAMPER_RESP_10, BBRAM_ERASE, 4, 1)
    FIELD(TAMPER_RESP_10, SYS_LOCKDOWN_1, 3, 1)
    FIELD(TAMPER_RESP_10, SYS_LOCKDOWN_0, 2, 1)
    FIELD(TAMPER_RESP_10, SYS_RESET, 1, 1)
    FIELD(TAMPER_RESP_10, SYS_INTERRUPT, 0, 1)
REG32(TAMPER_RESP_11, 0x55c)
    FIELD(TAMPER_RESP_11, BBRAM_ERASE, 4, 1)
    FIELD(TAMPER_RESP_11, SYS_LOCKDOWN_1, 3, 1)
    FIELD(TAMPER_RESP_11, SYS_LOCKDOWN_0, 2, 1)
    FIELD(TAMPER_RESP_11, SYS_RESET, 1, 1)
    FIELD(TAMPER_RESP_11, SYS_INTERRUPT, 0, 1)
REG32(TAMPER_RESP_12, 0x560)
    FIELD(TAMPER_RESP_12, BBRAM_ERASE, 4, 1)
    FIELD(TAMPER_RESP_12, SYS_LOCKDOWN_1, 3, 1)
    FIELD(TAMPER_RESP_12, SYS_LOCKDOWN_0, 2, 1)
    FIELD(TAMPER_RESP_12, SYS_RESET, 1, 1)
    FIELD(TAMPER_RESP_12, SYS_INTERRUPT, 0, 1)
REG32(TAMPER_RESP_13, 0x564)
    FIELD(TAMPER_RESP_13, BBRAM_ERASE, 4, 1)
    FIELD(TAMPER_RESP_13, SYS_LOCKDOWN_1, 3, 1)
    FIELD(TAMPER_RESP_13, SYS_LOCKDOWN_0, 2, 1)
    FIELD(TAMPER_RESP_13, SYS_RESET, 1, 1)
    FIELD(TAMPER_RESP_13, SYS_INTERRUPT, 0, 1)
REG32(TAMPER_TRIG, 0x570)
    FIELD(TAMPER_TRIG, TAMPER, 0, 1)
REG32(PPU0_MB_FATAL, 0x600)
    FIELD(PPU0_MB_FATAL, CPU3, 2, 1)
    FIELD(PPU0_MB_FATAL, CPU2, 1, 1)
    FIELD(PPU0_MB_FATAL, CPU1, 0, 1)
REG32(PPU0_MB1_FT_STATUS, 0x604)
    FIELD(PPU0_MB1_FT_STATUS, CPU3, 14, 1)
    FIELD(PPU0_MB1_FT_STATUS, CPU2, 13, 1)
    FIELD(PPU0_MB1_FT_STATUS, CPU1, 12, 1)
    FIELD(PPU0_MB1_FT_STATUS, FT_STATE, 10, 2)
    FIELD(PPU0_MB1_FT_STATUS, WDT_EXP, 9, 1)
    FIELD(PPU0_MB1_FT_STATUS, UNCORR_ERR, 8, 1)
    FIELD(PPU0_MB1_FT_STATUS, VOTER_ERR, 7, 1)
    FIELD(PPU0_MB1_FT_STATUS, FTL_MISMATCH, 4, 3)
    FIELD(PPU0_MB1_FT_STATUS, LS_RECOVER, 3, 1)
    FIELD(PPU0_MB1_FT_STATUS, LS_MISMATCH, 0, 3)
REG32(PPU0_MB2_FT_STATUS, 0x608)
    FIELD(PPU0_MB2_FT_STATUS, CPU3, 14, 1)
    FIELD(PPU0_MB2_FT_STATUS, CPU2, 13, 1)
    FIELD(PPU0_MB2_FT_STATUS, CPU1, 12, 1)
    FIELD(PPU0_MB2_FT_STATUS, FT_STATE, 10, 2)
    FIELD(PPU0_MB2_FT_STATUS, WDT_EXP, 9, 1)
    FIELD(PPU0_MB2_FT_STATUS, UNCORR_ERR, 8, 1)
    FIELD(PPU0_MB2_FT_STATUS, VOTER_ERR, 7, 1)
    FIELD(PPU0_MB2_FT_STATUS, FTL_MISMATCH, 4, 3)
    FIELD(PPU0_MB2_FT_STATUS, LS_RECOVER, 3, 1)
    FIELD(PPU0_MB2_FT_STATUS, LS_MISMATCH, 0, 3)
REG32(PPU0_MB3_FT_STATUS, 0x60c)
    FIELD(PPU0_MB3_FT_STATUS, CPU3, 14, 1)
    FIELD(PPU0_MB3_FT_STATUS, CPU2, 13, 1)
    FIELD(PPU0_MB3_FT_STATUS, CPU1, 12, 1)
    FIELD(PPU0_MB3_FT_STATUS, FT_STATE, 10, 2)
    FIELD(PPU0_MB3_FT_STATUS, WDT_EXP, 9, 1)
    FIELD(PPU0_MB3_FT_STATUS, UNCORR_ERR, 8, 1)
    FIELD(PPU0_MB3_FT_STATUS, VOTER_ERR, 7, 1)
    FIELD(PPU0_MB3_FT_STATUS, FTL_MISMATCH, 4, 3)
    FIELD(PPU0_MB3_FT_STATUS, LS_RECOVER, 3, 1)
    FIELD(PPU0_MB3_FT_STATUS, LS_MISMATCH, 0, 3)
REG32(PPU1_MB_FATAL, 0x610)
    FIELD(PPU1_MB_FATAL, CPU3, 2, 1)
    FIELD(PPU1_MB_FATAL, CPU2, 1, 1)
    FIELD(PPU1_MB_FATAL, CPU1, 0, 1)
REG32(PPU1_MB1_FT_STATUS, 0x614)
    FIELD(PPU1_MB1_FT_STATUS, CPU3, 14, 1)
    FIELD(PPU1_MB1_FT_STATUS, CPU2, 13, 1)
    FIELD(PPU1_MB1_FT_STATUS, CPU1, 12, 1)
    FIELD(PPU1_MB1_FT_STATUS, FT_STATE, 10, 2)
    FIELD(PPU1_MB1_FT_STATUS, WDT_EXP, 9, 1)
    FIELD(PPU1_MB1_FT_STATUS, UNCORR_ERR, 8, 1)
    FIELD(PPU1_MB1_FT_STATUS, VOTER_ERR, 7, 1)
    FIELD(PPU1_MB1_FT_STATUS, FTL_MISMATCH, 4, 3)
    FIELD(PPU1_MB1_FT_STATUS, LS_RECOVER, 3, 1)
    FIELD(PPU1_MB1_FT_STATUS, LS_MISMATCH, 0, 3)
REG32(PPU1_MB2_FT_STATUS, 0x618)
    FIELD(PPU1_MB2_FT_STATUS, CPU3, 14, 1)
    FIELD(PPU1_MB2_FT_STATUS, CPU2, 13, 1)
    FIELD(PPU1_MB2_FT_STATUS, CPU1, 12, 1)
    FIELD(PPU1_MB2_FT_STATUS, FT_STATE, 10, 2)
    FIELD(PPU1_MB2_FT_STATUS, WDT_EXP, 9, 1)
    FIELD(PPU1_MB2_FT_STATUS, UNCORR_ERR, 8, 1)
    FIELD(PPU1_MB2_FT_STATUS, VOTER_ERR, 7, 1)
    FIELD(PPU1_MB2_FT_STATUS, FTL_MISMATCH, 4, 3)
    FIELD(PPU1_MB2_FT_STATUS, LS_RECOVER, 3, 1)
    FIELD(PPU1_MB2_FT_STATUS, LS_MISMATCH, 0, 3)
REG32(PPU1_MB3_FT_STATUS, 0x61c)
    FIELD(PPU1_MB3_FT_STATUS, CPU3, 14, 1)
    FIELD(PPU1_MB3_FT_STATUS, CPU2, 13, 1)
    FIELD(PPU1_MB3_FT_STATUS, CPU1, 12, 1)
    FIELD(PPU1_MB3_FT_STATUS, FT_STATE, 10, 2)
    FIELD(PPU1_MB3_FT_STATUS, WDT_EXP, 9, 1)
    FIELD(PPU1_MB3_FT_STATUS, UNCORR_ERR, 8, 1)
    FIELD(PPU1_MB3_FT_STATUS, VOTER_ERR, 7, 1)
    FIELD(PPU1_MB3_FT_STATUS, FTL_MISMATCH, 4, 3)
    FIELD(PPU1_MB3_FT_STATUS, LS_RECOVER, 3, 1)
    FIELD(PPU1_MB3_FT_STATUS, LS_MISMATCH, 0, 3)
REG32(PPU_1_RST, 0x620)
    FIELD(PPU_1_RST, RST_N, 0, 1)
REG32(PPU_1_RST_MODE, 0x624)
    FIELD(PPU_1_RST_MODE, WAKEUP, 4, 1)
    FIELD(PPU_1_RST_MODE, RST_MODE, 0, 2)
REG32(PPU0_AXI, 0x630)
    FIELD(PPU0_AXI, ARQOS, 4, 4)
    FIELD(PPU0_AXI, AWQOS, 0, 4)
REG32(PPU1_AXI, 0x634)
    FIELD(PPU1_AXI, ARQOS, 4, 4)
    FIELD(PPU1_AXI, AWQOS, 0, 4)
REG32(ROM_VALIDATION_STATUS, 0x700)
    FIELD(ROM_VALIDATION_STATUS, PASS, 1, 1)
    FIELD(ROM_VALIDATION_STATUS, DONE, 0, 1)
REG32(ROM_VALIDATION_DIGEST_0, 0x704)
REG32(ROM_VALIDATION_DIGEST_1, 0x708)
REG32(ROM_VALIDATION_DIGEST_2, 0x70c)
REG32(ROM_VALIDATION_DIGEST_3, 0x710)
REG32(ROM_VALIDATION_DIGEST_4, 0x714)
REG32(ROM_VALIDATION_DIGEST_5, 0x718)
REG32(ROM_VALIDATION_DIGEST_6, 0x71c)
REG32(ROM_VALIDATION_DIGEST_7, 0x720)
REG32(ROM_VALIDATION_DIGEST_8, 0x724)
REG32(ROM_VALIDATION_DIGEST_9, 0x728)
REG32(ROM_VALIDATION_DIGEST_10, 0x72c)
REG32(ROM_VALIDATION_DIGEST_11, 0x730)
REG32(PMC_FW_AUTH_HASH_0, 0x750)
REG32(PMC_FW_AUTH_HASH_1, 0x754)
REG32(PMC_FW_AUTH_HASH_2, 0x758)
REG32(PMC_FW_AUTH_HASH_3, 0x75c)
REG32(PMC_FW_AUTH_HASH_4, 0x760)
REG32(PMC_FW_AUTH_HASH_5, 0x764)
REG32(PMC_FW_AUTH_HASH_6, 0x768)
REG32(PMC_FW_AUTH_HASH_7, 0x76c)
REG32(PMC_FW_AUTH_HASH_8, 0x770)
REG32(PMC_FW_AUTH_HASH_9, 0x774)
REG32(PMC_FW_AUTH_HASH_10, 0x778)
REG32(PMC_FW_AUTH_HASH_11, 0x77c)
REG32(SAFETY_CHK, 0x800)
REG32(SAFETY_CNTRL, 0x804)
    FIELD(SAFETY_CNTRL, SAFETY_MISSION_DIS, 0, 1)
REG32(PL_STATUS, 0x880)
    FIELD(PL_STATUS, POR_PL_B, 0, 1)
REG32(DONE, 0x884)
    FIELD(DONE, DONE, 0, 1)
REG32(PMC_PL_GPO, 0x900)
REG32(PMC_PPU1_GPI, 0x910)
    FIELD(PMC_PPU1_GPI, GPI_31, 31, 1)
    FIELD(PMC_PPU1_GPI, GPI_30, 30, 1)
    FIELD(PMC_PPU1_GPI, GPI_29, 29, 1)
    FIELD(PMC_PPU1_GPI, GPI_28, 28, 1)
    FIELD(PMC_PPU1_GPI, GPI_27, 27, 1)
    FIELD(PMC_PPU1_GPI, GPI_26, 26, 1)
    FIELD(PMC_PPU1_GPI, GPI_25, 25, 1)
    FIELD(PMC_PPU1_GPI, GPI_24, 24, 1)
    FIELD(PMC_PPU1_GPI, GPI_23, 23, 1)
    FIELD(PMC_PPU1_GPI, GPI_22, 22, 1)
    FIELD(PMC_PPU1_GPI, GPI_21, 21, 1)
    FIELD(PMC_PPU1_GPI, GPI_20, 20, 1)
    FIELD(PMC_PPU1_GPI, GPI_19, 19, 1)
    FIELD(PMC_PPU1_GPI, GPI_18, 18, 1)
    FIELD(PMC_PPU1_GPI, GPI_17, 17, 1)
    FIELD(PMC_PPU1_GPI, GPI_16, 16, 1)
    FIELD(PMC_PPU1_GPI, GPI_15, 15, 1)
    FIELD(PMC_PPU1_GPI, GPI_14, 14, 1)
    FIELD(PMC_PPU1_GPI, GPI_13, 13, 1)
    FIELD(PMC_PPU1_GPI, GPI_12, 12, 1)
    FIELD(PMC_PPU1_GPI, GPI_11, 11, 1)
    FIELD(PMC_PPU1_GPI, GPI_10, 10, 1)
    FIELD(PMC_PPU1_GPI, GPI_9, 9, 1)
    FIELD(PMC_PPU1_GPI, GPI_8, 8, 1)
    FIELD(PMC_PPU1_GPI, GPI_7, 7, 1)
    FIELD(PMC_PPU1_GPI, GPI_6, 6, 1)
    FIELD(PMC_PPU1_GPI, GPI_5, 5, 1)
    FIELD(PMC_PPU1_GPI, GPI_4, 4, 1)
    FIELD(PMC_PPU1_GPI, GPI_3, 3, 1)
    FIELD(PMC_PPU1_GPI, GPI_2, 2, 1)
    FIELD(PMC_PPU1_GPI, GPI_1, 1, 1)
    FIELD(PMC_PPU1_GPI, GPI_0, 0, 1)
REG32(PMC_PPU1_GPI_MASK, 0x914)
    FIELD(PMC_PPU1_GPI_MASK, GPI_31, 31, 1)
    FIELD(PMC_PPU1_GPI_MASK, GPI_30, 30, 1)
    FIELD(PMC_PPU1_GPI_MASK, GPI_29, 29, 1)
    FIELD(PMC_PPU1_GPI_MASK, GPI_28, 28, 1)
    FIELD(PMC_PPU1_GPI_MASK, GPI_27, 27, 1)
    FIELD(PMC_PPU1_GPI_MASK, GPI_26, 26, 1)
    FIELD(PMC_PPU1_GPI_MASK, GPI_25, 25, 1)
    FIELD(PMC_PPU1_GPI_MASK, GPI_24, 24, 1)
    FIELD(PMC_PPU1_GPI_MASK, GPI_23, 23, 1)
    FIELD(PMC_PPU1_GPI_MASK, GPI_22, 22, 1)
    FIELD(PMC_PPU1_GPI_MASK, GPI_21, 21, 1)
    FIELD(PMC_PPU1_GPI_MASK, GPI_20, 20, 1)
    FIELD(PMC_PPU1_GPI_MASK, GPI_19, 19, 1)
    FIELD(PMC_PPU1_GPI_MASK, GPI_18, 18, 1)
    FIELD(PMC_PPU1_GPI_MASK, GPI_17, 17, 1)
    FIELD(PMC_PPU1_GPI_MASK, GPI_16, 16, 1)
    FIELD(PMC_PPU1_GPI_MASK, GPI_15, 15, 1)
    FIELD(PMC_PPU1_GPI_MASK, GPI_14, 14, 1)
    FIELD(PMC_PPU1_GPI_MASK, GPI_13, 13, 1)
    FIELD(PMC_PPU1_GPI_MASK, GPI_12, 12, 1)
    FIELD(PMC_PPU1_GPI_MASK, GPI_11, 11, 1)
    FIELD(PMC_PPU1_GPI_MASK, GPI_10, 10, 1)
    FIELD(PMC_PPU1_GPI_MASK, GPI_9, 9, 1)
    FIELD(PMC_PPU1_GPI_MASK, GPI_8, 8, 1)
    FIELD(PMC_PPU1_GPI_MASK, GPI_7, 7, 1)
    FIELD(PMC_PPU1_GPI_MASK, GPI_6, 6, 1)
    FIELD(PMC_PPU1_GPI_MASK, GPI_5, 5, 1)
    FIELD(PMC_PPU1_GPI_MASK, GPI_4, 4, 1)
    FIELD(PMC_PPU1_GPI_MASK, GPI_3, 3, 1)
    FIELD(PMC_PPU1_GPI_MASK, GPI_2, 2, 1)
    FIELD(PMC_PPU1_GPI_MASK, GPI_1, 1, 1)
    FIELD(PMC_PPU1_GPI_MASK, GPI_0, 0, 1)
REG32(PMC_PPU1_GPI_EN, 0x918)
    FIELD(PMC_PPU1_GPI_EN, GPI_31, 31, 1)
    FIELD(PMC_PPU1_GPI_EN, GPI_30, 30, 1)
    FIELD(PMC_PPU1_GPI_EN, GPI_29, 29, 1)
    FIELD(PMC_PPU1_GPI_EN, GPI_28, 28, 1)
    FIELD(PMC_PPU1_GPI_EN, GPI_27, 27, 1)
    FIELD(PMC_PPU1_GPI_EN, GPI_26, 26, 1)
    FIELD(PMC_PPU1_GPI_EN, GPI_25, 25, 1)
    FIELD(PMC_PPU1_GPI_EN, GPI_24, 24, 1)
    FIELD(PMC_PPU1_GPI_EN, GPI_23, 23, 1)
    FIELD(PMC_PPU1_GPI_EN, GPI_22, 22, 1)
    FIELD(PMC_PPU1_GPI_EN, GPI_21, 21, 1)
    FIELD(PMC_PPU1_GPI_EN, GPI_20, 20, 1)
    FIELD(PMC_PPU1_GPI_EN, GPI_19, 19, 1)
    FIELD(PMC_PPU1_GPI_EN, GPI_18, 18, 1)
    FIELD(PMC_PPU1_GPI_EN, GPI_17, 17, 1)
    FIELD(PMC_PPU1_GPI_EN, GPI_16, 16, 1)
    FIELD(PMC_PPU1_GPI_EN, GPI_15, 15, 1)
    FIELD(PMC_PPU1_GPI_EN, GPI_14, 14, 1)
    FIELD(PMC_PPU1_GPI_EN, GPI_13, 13, 1)
    FIELD(PMC_PPU1_GPI_EN, GPI_12, 12, 1)
    FIELD(PMC_PPU1_GPI_EN, GPI_11, 11, 1)
    FIELD(PMC_PPU1_GPI_EN, GPI_10, 10, 1)
    FIELD(PMC_PPU1_GPI_EN, GPI_9, 9, 1)
    FIELD(PMC_PPU1_GPI_EN, GPI_8, 8, 1)
    FIELD(PMC_PPU1_GPI_EN, GPI_7, 7, 1)
    FIELD(PMC_PPU1_GPI_EN, GPI_6, 6, 1)
    FIELD(PMC_PPU1_GPI_EN, GPI_5, 5, 1)
    FIELD(PMC_PPU1_GPI_EN, GPI_4, 4, 1)
    FIELD(PMC_PPU1_GPI_EN, GPI_3, 3, 1)
    FIELD(PMC_PPU1_GPI_EN, GPI_2, 2, 1)
    FIELD(PMC_PPU1_GPI_EN, GPI_1, 1, 1)
    FIELD(PMC_PPU1_GPI_EN, GPI_0, 0, 1)
REG32(PMC_PPU1_GPI_DIS, 0x91c)
    FIELD(PMC_PPU1_GPI_DIS, GPI_31, 31, 1)
    FIELD(PMC_PPU1_GPI_DIS, GPI_30, 30, 1)
    FIELD(PMC_PPU1_GPI_DIS, GPI_29, 29, 1)
    FIELD(PMC_PPU1_GPI_DIS, GPI_28, 28, 1)
    FIELD(PMC_PPU1_GPI_DIS, GPI_27, 27, 1)
    FIELD(PMC_PPU1_GPI_DIS, GPI_26, 26, 1)
    FIELD(PMC_PPU1_GPI_DIS, GPI_25, 25, 1)
    FIELD(PMC_PPU1_GPI_DIS, GPI_24, 24, 1)
    FIELD(PMC_PPU1_GPI_DIS, GPI_23, 23, 1)
    FIELD(PMC_PPU1_GPI_DIS, GPI_22, 22, 1)
    FIELD(PMC_PPU1_GPI_DIS, GPI_21, 21, 1)
    FIELD(PMC_PPU1_GPI_DIS, GPI_20, 20, 1)
    FIELD(PMC_PPU1_GPI_DIS, GPI_19, 19, 1)
    FIELD(PMC_PPU1_GPI_DIS, GPI_18, 18, 1)
    FIELD(PMC_PPU1_GPI_DIS, GPI_17, 17, 1)
    FIELD(PMC_PPU1_GPI_DIS, GPI_16, 16, 1)
    FIELD(PMC_PPU1_GPI_DIS, GPI_15, 15, 1)
    FIELD(PMC_PPU1_GPI_DIS, GPI_14, 14, 1)
    FIELD(PMC_PPU1_GPI_DIS, GPI_13, 13, 1)
    FIELD(PMC_PPU1_GPI_DIS, GPI_12, 12, 1)
    FIELD(PMC_PPU1_GPI_DIS, GPI_11, 11, 1)
    FIELD(PMC_PPU1_GPI_DIS, GPI_10, 10, 1)
    FIELD(PMC_PPU1_GPI_DIS, GPI_9, 9, 1)
    FIELD(PMC_PPU1_GPI_DIS, GPI_8, 8, 1)
    FIELD(PMC_PPU1_GPI_DIS, GPI_7, 7, 1)
    FIELD(PMC_PPU1_GPI_DIS, GPI_6, 6, 1)
    FIELD(PMC_PPU1_GPI_DIS, GPI_5, 5, 1)
    FIELD(PMC_PPU1_GPI_DIS, GPI_4, 4, 1)
    FIELD(PMC_PPU1_GPI_DIS, GPI_3, 3, 1)
    FIELD(PMC_PPU1_GPI_DIS, GPI_2, 2, 1)
    FIELD(PMC_PPU1_GPI_DIS, GPI_1, 1, 1)
    FIELD(PMC_PPU1_GPI_DIS, GPI_0, 0, 1)
REG32(PMC_PPU1_GPI_TRIG, 0x920)
    FIELD(PMC_PPU1_GPI_TRIG, GPI_31, 31, 1)
    FIELD(PMC_PPU1_GPI_TRIG, GPI_30, 30, 1)
    FIELD(PMC_PPU1_GPI_TRIG, GPI_29, 29, 1)
    FIELD(PMC_PPU1_GPI_TRIG, GPI_28, 28, 1)
    FIELD(PMC_PPU1_GPI_TRIG, GPI_27, 27, 1)
    FIELD(PMC_PPU1_GPI_TRIG, GPI_26, 26, 1)
    FIELD(PMC_PPU1_GPI_TRIG, GPI_25, 25, 1)
    FIELD(PMC_PPU1_GPI_TRIG, GPI_24, 24, 1)
    FIELD(PMC_PPU1_GPI_TRIG, GPI_23, 23, 1)
    FIELD(PMC_PPU1_GPI_TRIG, GPI_22, 22, 1)
    FIELD(PMC_PPU1_GPI_TRIG, GPI_21, 21, 1)
    FIELD(PMC_PPU1_GPI_TRIG, GPI_20, 20, 1)
    FIELD(PMC_PPU1_GPI_TRIG, GPI_19, 19, 1)
    FIELD(PMC_PPU1_GPI_TRIG, GPI_18, 18, 1)
    FIELD(PMC_PPU1_GPI_TRIG, GPI_17, 17, 1)
    FIELD(PMC_PPU1_GPI_TRIG, GPI_16, 16, 1)
    FIELD(PMC_PPU1_GPI_TRIG, GPI_15, 15, 1)
    FIELD(PMC_PPU1_GPI_TRIG, GPI_14, 14, 1)
    FIELD(PMC_PPU1_GPI_TRIG, GPI_13, 13, 1)
    FIELD(PMC_PPU1_GPI_TRIG, GPI_12, 12, 1)
    FIELD(PMC_PPU1_GPI_TRIG, GPI_11, 11, 1)
    FIELD(PMC_PPU1_GPI_TRIG, GPI_10, 10, 1)
    FIELD(PMC_PPU1_GPI_TRIG, GPI_9, 9, 1)
    FIELD(PMC_PPU1_GPI_TRIG, GPI_8, 8, 1)
    FIELD(PMC_PPU1_GPI_TRIG, GPI_7, 7, 1)
    FIELD(PMC_PPU1_GPI_TRIG, GPI_6, 6, 1)
    FIELD(PMC_PPU1_GPI_TRIG, GPI_5, 5, 1)
    FIELD(PMC_PPU1_GPI_TRIG, GPI_4, 4, 1)
    FIELD(PMC_PPU1_GPI_TRIG, GPI_3, 3, 1)
    FIELD(PMC_PPU1_GPI_TRIG, GPI_2, 2, 1)
    FIELD(PMC_PPU1_GPI_TRIG, GPI_1, 1, 1)
    FIELD(PMC_PPU1_GPI_TRIG, GPI_0, 0, 1)
REG32(PMC_PL_IRQ, 0x930)
    FIELD(PMC_PL_IRQ, IRQ_3, 3, 1)
    FIELD(PMC_PL_IRQ, IRQ_2, 2, 1)
    FIELD(PMC_PL_IRQ, IRQ_1, 1, 1)
    FIELD(PMC_PL_IRQ, IRQ_0, 0, 1)
REG32(PMC_PL_IRQ_MASK, 0x934)
    FIELD(PMC_PL_IRQ_MASK, IRQ_3, 3, 1)
    FIELD(PMC_PL_IRQ_MASK, IRQ_2, 2, 1)
    FIELD(PMC_PL_IRQ_MASK, IRQ_1, 1, 1)
    FIELD(PMC_PL_IRQ_MASK, IRQ_0, 0, 1)
REG32(PMC_PL_IRQ_EN, 0x938)
    FIELD(PMC_PL_IRQ_EN, IRQ_3, 3, 1)
    FIELD(PMC_PL_IRQ_EN, IRQ_2, 2, 1)
    FIELD(PMC_PL_IRQ_EN, IRQ_1, 1, 1)
    FIELD(PMC_PL_IRQ_EN, IRQ_0, 0, 1)
REG32(PMC_PL_IRQ_DIS, 0x93c)
    FIELD(PMC_PL_IRQ_DIS, IRQ_3, 3, 1)
    FIELD(PMC_PL_IRQ_DIS, IRQ_2, 2, 1)
    FIELD(PMC_PL_IRQ_DIS, IRQ_1, 1, 1)
    FIELD(PMC_PL_IRQ_DIS, IRQ_0, 0, 1)
REG32(SSIT_NOC_ID, 0x950)
    FIELD(SSIT_NOC_ID, SWITCHID, 0, 14)
REG32(SSIT_SEC_STATUS, 0x954)
    FIELD(SSIT_SEC_STATUS, DEC_EFUSE, 1, 1)
    FIELD(SSIT_SEC_STATUS, DEC_BBRAM, 0, 1)
REG32(SSIT_ERR, 0x958)
    FIELD(SSIT_ERR, IRQ_OUT, 0, 3)
REG32(SEM_CRAM_ATTRIB, 0x1000)
    FIELD(SEM_CRAM_ATTRIB, UNUSED, 9, 7)
    FIELD(SEM_CRAM_ATTRIB, RDBCRC_ONEROW, 8, 1)
    FIELD(SEM_CRAM_ATTRIB, SWCRC_SEL, 7, 1)
    FIELD(SEM_CRAM_ATTRIB, EN_SCAN_CHECK, 6, 1)
    FIELD(SEM_CRAM_ATTRIB, EN_SCAN_POST_CONFIG, 5, 1)
    FIELD(SEM_CRAM_ATTRIB, EN_ERR_INJ, 4, 1)
    FIELD(SEM_CRAM_ATTRIB, SWECC_SEL, 3, 1)
    FIELD(SEM_CRAM_ATTRIB, EN_CORR, 2, 1)
    FIELD(SEM_CRAM_ATTRIB, MODE, 0, 2)
REG32(SEM_NPI_ATTRIB, 0x1004)
    FIELD(SEM_NPI_ATTRIB, UNUSED0, 18, 6)
    FIELD(SEM_NPI_ATTRIB, PERIOD_SCAN_TIME, 8, 10)
    FIELD(SEM_NPI_ATTRIB, UNUSED1, 6, 2)
    FIELD(SEM_NPI_ATTRIB, EN_SCAN_CHECK, 5, 1)
    FIELD(SEM_NPI_ATTRIB, EN_SCAN_POST_CONFIG, 4, 1)
    FIELD(SEM_NPI_ATTRIB, EN_ERR_INJ, 3, 1)
    FIELD(SEM_NPI_ATTRIB, SWSHA_SEL, 2, 1)
    FIELD(SEM_NPI_ATTRIB, MODE, 0, 2)
REG32(SEM_NPI_HDR_ADDR_0, 0x1008)
REG32(SEM_NPI_HDR_ADDR_1, 0x100c)
REG32(SEM_CLASSIFICATION_0, 0x1010)
REG32(SEM_CLASSIFICATION_1, 0x1014)
REG32(SEM_STATUS, 0x1018)
    FIELD(SEM_STATUS, UNUSED0, 27, 5)
    FIELD(SEM_STATUS, NPI_LAST, 26, 1)
    FIELD(SEM_STATUS, NPI_FATAL_STATE, 25, 1)
    FIELD(SEM_STATUS, NPI_INJ_STATE, 24, 1)
    FIELD(SEM_STATUS, NPI_IDLE_STATE, 23, 1)
    FIELD(SEM_STATUS, NPI_CLASS_STATE, 22, 1)
    FIELD(SEM_STATUS, NPI_SCAN_STATE, 21, 1)
    FIELD(SEM_STATUS, NPI_SCANCHK_STATE, 20, 1)
    FIELD(SEM_STATUS, NPI_INIT_STATE, 19, 1)
    FIELD(SEM_STATUS, NPI_FUNC_SUSPENDED, 18, 1)
    FIELD(SEM_STATUS, NPI_FUNC_ACTIVE, 17, 1)
    FIELD(SEM_STATUS, NPI_FUNC_PRESENT, 16, 1)
    FIELD(SEM_STATUS, UNUSED1, 11, 5)
    FIELD(SEM_STATUS, CRAM_FATAL_STATE, 10, 1)
    FIELD(SEM_STATUS, CRAM_INJ_STATE, 9, 1)
    FIELD(SEM_STATUS, CRAM_IDLE_STATE, 8, 1)
    FIELD(SEM_STATUS, CRAM_DETECT_STATE, 7, 1)
    FIELD(SEM_STATUS, CRAM_CLASS_STATE, 6, 1)
    FIELD(SEM_STATUS, CRAM_CORR_STATE, 5, 1)
    FIELD(SEM_STATUS, CRAM_OBS_STATE, 4, 1)
    FIELD(SEM_STATUS, CRAM_SCANCHK_STATE, 3, 1)
    FIELD(SEM_STATUS, CRAM_INIT_STATE, 2, 1)
    FIELD(SEM_STATUS, CRAM_FUNC_ACTIVE, 1, 1)
    FIELD(SEM_STATUS, CRAM_FUNC_PRESENT, 0, 1)
REG32(SEM_ERROR, 0x101c)
    FIELD(SEM_ERROR, UNUSED0, 28, 4)
    FIELD(SEM_ERROR, NPI_HRT_ERR, 27, 1)
    FIELD(SEM_ERROR, NPI_UNCOR_ERR, 26, 1)
    FIELD(SEM_ERROR, NPI_INIT_ERR, 24, 2)
    FIELD(SEM_ERROR, UNUSED1, 18, 6)
    FIELD(SEM_ERROR, CRAM_HRT_ERR, 17, 1)
    FIELD(SEM_ERROR, CRAM_COR_ERR_CNT, 9, 8)
    FIELD(SEM_ERROR, CRAM_RES, 6, 3)
    FIELD(SEM_ERROR, CRAM_COR_ERR, 4, 2)
    FIELD(SEM_ERROR, CRAM_CRC_ERR, 3, 1)
    FIELD(SEM_ERROR, CRAM_UNCOR_ERR, 2, 1)
    FIELD(SEM_ERROR, CRAM_INIT_ERR, 0, 2)
REG32(SEM_CMD_REG0, 0x1020)
    FIELD(SEM_CMD_REG0, CMD_CODE, 8, 20)
    FIELD(SEM_CMD_REG0, UNUSED, 4, 4)
    FIELD(SEM_CMD_REG0, CMD_PROCESSED, 3, 1)
    FIELD(SEM_CMD_REG0, CMD_GO, 2, 1)
    FIELD(SEM_CMD_REG0, CMD_READY, 1, 1)
    FIELD(SEM_CMD_REG0, CMD_VALID, 0, 1)
REG32(SEM_CMD_REG0_EXT, 0x1024)
REG32(SEM_CMD_REG1, 0x1028)
    FIELD(SEM_CMD_REG1, CMD_CODE, 8, 20)
    FIELD(SEM_CMD_REG1, UNUSED, 1, 7)
    FIELD(SEM_CMD_REG1, CMD_VALID, 0, 1)
REG32(SEM_CMD_REG1_EXT, 0x102c)
REG32(SEM_CMD_REG2, 0x1030)
    FIELD(SEM_CMD_REG2, CMD_CODE, 8, 20)
    FIELD(SEM_CMD_REG2, UNUSED, 1, 7)
    FIELD(SEM_CMD_REG2, CMD_VALID, 0, 1)
REG32(SEM_CMD_REG2_EXT, 0x1034)
REG32(SEM_CMD_REG3, 0x1038)
    FIELD(SEM_CMD_REG3, CMD_CODE, 8, 20)
    FIELD(SEM_CMD_REG3, UNUSED, 1, 7)
    FIELD(SEM_CMD_REG3, CMD_VALID, 0, 1)
REG32(SEM_CMD_REG3_EXT, 0x103c)
REG32(SEM_CRAMERR_ADDRL0, 0x1040)
    FIELD(SEM_CRAMERR_ADDRL0, QWORDS, 23, 5)
    FIELD(SEM_CRAMERR_ADDRL0, BITS, 16, 7)
    FIELD(SEM_CRAMERR_ADDRL0, UNUSED, 4, 12)
    FIELD(SEM_CRAMERR_ADDRL0, UNCORRECTABLE, 3, 1)
    FIELD(SEM_CRAMERR_ADDRL0, CLASSIFICATION, 2, 1)
    FIELD(SEM_CRAMERR_ADDRL0, VALID, 0, 2)
REG32(SEM_CRAMERR_ADDRH0, 0x1044)
    FIELD(SEM_CRAMERR_ADDRH0, UNUSED, 30, 2)
    FIELD(SEM_CRAMERR_ADDRH0, SLR, 27, 3)
    FIELD(SEM_CRAMERR_ADDRH0, ROW, 23, 4)
    FIELD(SEM_CRAMERR_ADDRH0, BLOCKTYPE, 20, 3)
    FIELD(SEM_CRAMERR_ADDRH0, FRAME_ADDR, 0, 20)
REG32(SEM_CRAMERR_ADDRL1, 0x1048)
    FIELD(SEM_CRAMERR_ADDRL1, QWORDS, 23, 5)
    FIELD(SEM_CRAMERR_ADDRL1, BITS, 16, 7)
    FIELD(SEM_CRAMERR_ADDRL1, UNUSED, 4, 12)
    FIELD(SEM_CRAMERR_ADDRL1, UNCORRECTABLE, 3, 1)
    FIELD(SEM_CRAMERR_ADDRL1, CLASSIFICATION, 2, 1)
    FIELD(SEM_CRAMERR_ADDRL1, VALID, 0, 2)
REG32(SEM_CRAMERR_ADDRH1, 0x104c)
    FIELD(SEM_CRAMERR_ADDRH1, UNUSED, 30, 2)
    FIELD(SEM_CRAMERR_ADDRH1, SLR, 27, 3)
    FIELD(SEM_CRAMERR_ADDRH1, ROW, 23, 4)
    FIELD(SEM_CRAMERR_ADDRH1, BLOCKTYPE, 20, 3)
    FIELD(SEM_CRAMERR_ADDRH1, FRAME_ADDR, 0, 20)
REG32(SEM_CRAMERR_ADDRL2, 0x1050)
    FIELD(SEM_CRAMERR_ADDRL2, QWORDS, 23, 5)
    FIELD(SEM_CRAMERR_ADDRL2, BITS, 16, 7)
    FIELD(SEM_CRAMERR_ADDRL2, UNUSED, 4, 12)
    FIELD(SEM_CRAMERR_ADDRL2, UNCORRECTABLE, 3, 1)
    FIELD(SEM_CRAMERR_ADDRL2, CLASSIFICATION, 2, 1)
    FIELD(SEM_CRAMERR_ADDRL2, VALID, 0, 2)
REG32(SEM_CRAMERR_ADDRH2, 0x1054)
    FIELD(SEM_CRAMERR_ADDRH2, UNUSED, 30, 2)
    FIELD(SEM_CRAMERR_ADDRH2, SLR, 27, 3)
    FIELD(SEM_CRAMERR_ADDRH2, ROW, 23, 4)
    FIELD(SEM_CRAMERR_ADDRH2, BLOCKTYPE, 20, 3)
    FIELD(SEM_CRAMERR_ADDRH2, FRAME_ADDR, 0, 20)
REG32(SEM_CRAMERR_ADDRL3, 0x1058)
    FIELD(SEM_CRAMERR_ADDRL3, QWORDS, 23, 5)
    FIELD(SEM_CRAMERR_ADDRL3, BITS, 16, 7)
    FIELD(SEM_CRAMERR_ADDRL3, UNUSED, 4, 12)
    FIELD(SEM_CRAMERR_ADDRL3, UNCORRECTABLE, 3, 1)
    FIELD(SEM_CRAMERR_ADDRL3, CLASSIFICATION, 2, 1)
    FIELD(SEM_CRAMERR_ADDRL3, VALID, 0, 2)
REG32(SEM_CRAMERR_ADDRH3, 0x105c)
    FIELD(SEM_CRAMERR_ADDRH3, UNUSED, 30, 2)
    FIELD(SEM_CRAMERR_ADDRH3, SLR, 27, 3)
    FIELD(SEM_CRAMERR_ADDRH3, ROW, 23, 4)
    FIELD(SEM_CRAMERR_ADDRH3, BLOCKTYPE, 20, 3)
    FIELD(SEM_CRAMERR_ADDRH3, FRAME_ADDR, 0, 20)
REG32(SEM_RESERVED_0, 0x1060)
REG32(SEM_RESERVED_1, 0x1064)
REG32(SEM_RESERVED_2, 0x1068)
REG32(SEM_RESERVED_3, 0x106c)
REG32(PMC_MUTEX_0, 0x1100)
REG32(PMC_MUTEX_1, 0x1104)
REG32(PMC_MUTEX_2, 0x1108)
REG32(PMC_MUTEX_3, 0x110c)
REG32(PMC_MUTEX_4, 0x1110)
REG32(PMC_MUTEX_5, 0x1114)
REG32(PMC_MUTEX_6, 0x1118)
REG32(PMC_MUTEX_7, 0x111c)
REG32(PMC_MUTEX_8, 0x1120)
REG32(PMC_MUTEX_9, 0x1124)
REG32(PMC_MUTEX_10, 0x1128)
REG32(PMC_MUTEX_11, 0x112c)
REG32(PMC_MUTEX_12, 0x1130)
REG32(PMC_MUTEX_13, 0x1134)
REG32(PMC_MUTEX_14, 0x1138)
REG32(PMC_MUTEX_15, 0x113c)
REG32(PMC_MUTEX_16, 0x1140)
REG32(PMC_MUTEX_17, 0x1144)
REG32(PMC_MUTEX_18, 0x1148)
REG32(PMC_MUTEX_19, 0x114c)
REG32(PMC_MUTEX_20, 0x1150)
REG32(PMC_MUTEX_21, 0x1154)
REG32(PMC_MUTEX_22, 0x1158)
REG32(PMC_MUTEX_23, 0x115c)
REG32(PMC_MUTEX_24, 0x1160)
REG32(PMC_MUTEX_25, 0x1164)
REG32(PMC_MUTEX_26, 0x1168)
REG32(PMC_MUTEX_27, 0x116c)
REG32(PMC_MUTEX_28, 0x1170)
REG32(PMC_MUTEX_29, 0x1174)
REG32(PMC_MUTEX_30, 0x1178)
REG32(PMC_MUTEX_31, 0x117c)
REG32(PPU_1_RST_LOCK, 0x1200)
    FIELD(PPU_1_RST_LOCK, LOCK, 0, 1)
REG32(POR_LOCK, 0x1204)
    FIELD(POR_LOCK, LOCK, 0, 1)

#define R_MAX (R_POR_LOCK + 1)
#define R_TAMPER_RESP_MAX (R_TAMPER_RESP_13 - R_TAMPER_RESP_0 + 1)

typedef struct PMC_GLOBAL {
    SysBusDevice parent_obj;
    MemoryRegion iomem;
    qemu_irq irq_pmc_ppu1_gpi;
    qemu_irq irq_req_pwrdwn_int;
    qemu_irq irq_wakeup_irq;
    qemu_irq irq_req_swrst_int;
    qemu_irq irq_req_pwrup_int;
    qemu_irq irq_pmc_global_imr;
    qemu_irq irq_pmc_pl_irq;
    qemu_irq irq_req_iso_int;

    qemu_irq tamper_out[R_TAMPER_RESP_MAX];
    qemu_irq ppu1_wakeup;
    qemu_irq ppu1_rst;

    Object *bbram;
    Object *efuse;
    AddressSpace tamper_as;

    uint32_t regs[R_MAX];
    RegisterInfo regs_info[R_MAX];
} PMC_GLOBAL;

PPU1_UPDATE_CTRL(PMC_GLOBAL)

static void pmc_ppu1_gpi_update_irq(PMC_GLOBAL *s)
{
    bool pending = s->regs[R_PMC_PPU1_GPI] & ~s->regs[R_PMC_PPU1_GPI_MASK];
    qemu_set_irq(s->irq_pmc_ppu1_gpi, pending);
}

static void pmc_ppu1_gpi_postw(RegisterInfo *reg, uint64_t val64)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(reg->opaque);
    pmc_ppu1_gpi_update_irq(s);
}

static uint64_t pmc_ppu1_gpi_en_prew(RegisterInfo *reg, uint64_t val64)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(reg->opaque);
    uint32_t val = val64;

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

static uint64_t pmc_ppu1_gpi_dis_prew(RegisterInfo *reg, uint64_t val64)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(reg->opaque);
    uint32_t val = val64;

    s->regs[R_PMC_PPU1_GPI_MASK] |= val;
    pmc_ppu1_gpi_update_irq(s);
    return 0;
}

static uint64_t pmc_ppu1_gpi_trig_prew(RegisterInfo *reg, uint64_t val64)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(reg->opaque);
    uint32_t val = val64;

    s->regs[R_PMC_PPU1_GPI_MASK] |= val;
    pmc_ppu1_gpi_update_irq(s);
    return 0;
}

static void req_pwrdwn_int_update_irq(PMC_GLOBAL *s)
{
    bool pending = s->regs[R_REQ_PWRDWN_STATUS] &
                          s->regs[R_REQ_PWRDWN_INT_MASK];
    qemu_set_irq(s->irq_req_pwrdwn_int, pending);
}

static void req_pwrdwn_status_postw(RegisterInfo *reg, uint64_t val64)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(reg->opaque);
    req_pwrdwn_int_update_irq(s);
}

static uint64_t req_pwrdwn_int_en_prew(RegisterInfo *reg, uint64_t val64)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(reg->opaque);
    uint32_t val = val64;

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

static uint64_t req_pwrdwn_int_dis_prew(RegisterInfo *reg, uint64_t val64)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(reg->opaque);
    uint32_t val = val64;

    s->regs[R_REQ_PWRDWN_INT_MASK] |= val;
    req_pwrdwn_int_update_irq(s);
    return 0;
}

static uint64_t req_pwrdwn_trig_prew(RegisterInfo *reg, uint64_t val64)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(reg->opaque);
    uint32_t val = val64;

    s->regs[R_REQ_PWRDWN_STATUS] |= val;
    req_pwrdwn_int_update_irq(s);
    return 0;
}

static void wakeup_irq_update_irq(PMC_GLOBAL *s)
{
    bool pending = s->regs[R_WAKEUP_IRQ_STATUS] & ~s->regs[R_WAKEUP_IRQ_MASK];
    qemu_set_irq(s->irq_wakeup_irq, pending);
}

static void wakeup_irq_status_postw(RegisterInfo *reg, uint64_t val64)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(reg->opaque);
    wakeup_irq_update_irq(s);
}

static uint64_t wakeup_irq_en_prew(RegisterInfo *reg, uint64_t val64)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(reg->opaque);
    uint32_t val = val64;

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

static uint64_t wakeup_irq_dis_prew(RegisterInfo *reg, uint64_t val64)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(reg->opaque);
    uint32_t val = val64;

    s->regs[R_WAKEUP_IRQ_MASK] |= val;
    wakeup_irq_update_irq(s);
    return 0;
}

static uint64_t wakeup_irq_trig_prew(RegisterInfo *reg, uint64_t val64)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(reg->opaque);
    uint32_t val = val64;

    s->regs[R_WAKEUP_IRQ_STATUS] |= val;
    wakeup_irq_update_irq(s);
    return 0;
}

static void req_swrst_int_update_irq(PMC_GLOBAL *s)
{
    bool pending = s->regs[R_REQ_SWRST_STATUS] & ~s->regs[R_REQ_SWRST_INT_MASK];
    qemu_set_irq(s->irq_req_swrst_int, pending);
}

static void req_swrst_status_postw(RegisterInfo *reg, uint64_t val64)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(reg->opaque);
    req_swrst_int_update_irq(s);
}

static uint64_t req_swrst_int_en_prew(RegisterInfo *reg, uint64_t val64)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(reg->opaque);
    uint32_t val = val64;

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

static uint64_t req_swrst_int_dis_prew(RegisterInfo *reg, uint64_t val64)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(reg->opaque);
    uint32_t val = val64;

    s->regs[R_REQ_SWRST_INT_MASK] |= val;
    req_swrst_int_update_irq(s);
    return 0;
}

static uint64_t req_swrst_trig_prew(RegisterInfo *reg, uint64_t val64)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(reg->opaque);
    uint32_t val = val64;

    s->regs[R_REQ_SWRST_STATUS] |= val;
    req_swrst_int_update_irq(s);
    return 0;
}

static void req_pwrup_int_update_irq(PMC_GLOBAL *s)
{
    bool pending = s->regs[R_REQ_PWRUP_STATUS] & ~s->regs[R_REQ_PWRUP_INT_MASK];
    qemu_set_irq(s->irq_req_pwrup_int, pending);
}

static void req_pwrup_status_postw(RegisterInfo *reg, uint64_t val64)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(reg->opaque);
    req_pwrup_int_update_irq(s);
}

static uint64_t req_pwrup_int_en_prew(RegisterInfo *reg, uint64_t val64)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(reg->opaque);
    uint32_t val = val64;

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

static uint64_t req_pwrup_int_dis_prew(RegisterInfo *reg, uint64_t val64)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(reg->opaque);
    uint32_t val = val64;

    s->regs[R_REQ_PWRUP_INT_MASK] |= val;
    req_pwrup_int_update_irq(s);
    return 0;
}

static uint64_t req_pwrup_trig_prew(RegisterInfo *reg, uint64_t val64)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(reg->opaque);
    uint32_t val = val64;

    s->regs[R_REQ_PWRUP_STATUS] |= val;
    req_pwrup_int_update_irq(s);
    return 0;
}

static void pmc_global_imr_update_irq(PMC_GLOBAL *s)
{
    bool pending = s->regs[R_PMC_GLOBAL_ISR] & ~s->regs[R_PMC_GLOBAL_IMR];
    qemu_set_irq(s->irq_pmc_global_imr, pending);
}

static void pmc_global_isr_postw(RegisterInfo *reg, uint64_t val64)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(reg->opaque);
    pmc_global_imr_update_irq(s);
}

static uint64_t pmc_global_ier_prew(RegisterInfo *reg, uint64_t val64)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(reg->opaque);
    uint32_t val = val64;

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

static uint64_t pmc_global_idr_prew(RegisterInfo *reg, uint64_t val64)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(reg->opaque);
    uint32_t val = val64;

    s->regs[R_PMC_GLOBAL_IMR] |= val;
    pmc_global_imr_update_irq(s);
    return 0;
}

static void pmc_pl_irq_update_irq(PMC_GLOBAL *s)
{
    bool pending = s->regs[R_PMC_PL_IRQ] & ~s->regs[R_PMC_PL_IRQ_MASK];
    qemu_set_irq(s->irq_pmc_pl_irq, pending);
}

static void pmc_pl_irq_postw(RegisterInfo *reg, uint64_t val64)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(reg->opaque);
    pmc_pl_irq_update_irq(s);
}

static uint64_t pmc_pl_irq_en_prew(RegisterInfo *reg, uint64_t val64)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(reg->opaque);
    uint32_t val = val64;

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

static uint64_t pmc_pl_irq_dis_prew(RegisterInfo *reg, uint64_t val64)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(reg->opaque);
    uint32_t val = val64;

    s->regs[R_PMC_PL_IRQ_MASK] |= val;
    pmc_pl_irq_update_irq(s);
    return 0;
}

static void req_iso_int_update_irq(PMC_GLOBAL *s)
{
    bool pending = s->regs[R_REQ_ISO_STATUS] & ~s->regs[R_REQ_ISO_INT_MASK];
    qemu_set_irq(s->irq_req_iso_int, pending);
}

static void req_iso_status_postw(RegisterInfo *reg, uint64_t val64)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(reg->opaque);
    req_iso_int_update_irq(s);
}

static uint64_t req_iso_int_en_prew(RegisterInfo *reg, uint64_t val64)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(reg->opaque);
    uint32_t val = val64;

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

static uint64_t req_iso_int_dis_prew(RegisterInfo *reg, uint64_t val64)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(reg->opaque);
    uint32_t val = val64;

    s->regs[R_REQ_ISO_INT_MASK] |= val;
    req_iso_int_update_irq(s);
    return 0;
}

static uint64_t req_iso_trig_prew(RegisterInfo *reg, uint64_t val64)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(reg->opaque);
    uint32_t val = val64;

    s->regs[R_REQ_ISO_STATUS] |= val;
    req_iso_int_update_irq(s);
    return 0;
}

static void ppu1_rst_x_postw(RegisterInfo *reg, uint64_t val64)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(reg->opaque);
    ppu1_update_ctrl(s);
}

static bool pmc_global_gd_monitor_enabled(PMC_GLOBAL *s)
{
    XlnxEFuse *efuse;
    XlnxEFuseSysmonData data;

    if (!s->efuse) {
        g_autofree char *path = object_get_canonical_path(OBJECT(s));

        warn_report("%s: glitch-detect monitor disabled due to missing "
                    "TYPE_XLNX_EFUSE_SYSMON_DATA_SOURCE.", path);

        return false;
    }

    /* Check for older DTS releases */
    efuse = (XlnxEFuse *)object_dynamic_cast(s->efuse, TYPE_XLNX_EFUSE);
    if (!efuse) {
        efuse = XLNX_VERSAL_EFUSE_CACHE(s->efuse)->efuse;
    }

    if (xlnx_efuse_get_sysmon(efuse, &data)) {
        return !!data.glitch_monitor_en;
    } else {
        return false;
    }
}

static uint32_t pmc_global_tamper_response(PMC_GLOBAL *s, unsigned slot)
{
    hwaddr addr;
    uint32_t data;
    MemTxResult rc;

    addr = R_TAMPER_RESP_0 + slot;

    /*
     * Need to issue an io-read to obtain value from the overlap
     * region holding the dual-ported R_TAMPER_RESP_ registers.
     * 'first_cpu->as' is not used to bypass possible blockage
     * due to SMMU enforcement.
     *
     * This can be removed in the future when the dual-port model
     * is merged into this device.
     */
    if (!s->iomem.container || !s->iomem.addr) {
        return 0;
    }
    if (!s->tamper_as.root) {
        g_autofree char *p = object_get_canonical_path(OBJECT(s));
        g_autofree char *n = g_strdup_printf("%s-tamper-as", p);

        address_space_init(&s->tamper_as, s->iomem.container, n);
    }

    addr = s->iomem.addr + addr * 4;
    rc = address_space_read_full(&s->tamper_as, addr,
                                 MEMTXATTRS_UNSPECIFIED, &data, 4);

    return rc == MEMTX_OK ? data : 0;
}

static void pmc_global_tamper_erase_bbram(PMC_GLOBAL *s, unsigned slot)
{
    g_autofree Error *err = NULL;
    g_autofree char *path = object_get_canonical_path(OBJECT(s));

    if (!s->bbram) {
        warn_report("%s.bbram: Link missing disables "
                    "TAMPER_RESP_%u.BBRAM_ERASE", path, slot);
        return;
    }

    object_property_set_bool(s->bbram, "erase", true, &err);
    if (err) {
        g_autofree char *p = object_get_canonical_path(s->bbram);

        warn_report("%s.bbram: Failed to set %s.erase: %s",
                    path, p, error_get_pretty(err));
    }
}

static void pmc_global_tamper_lockdown(PMC_GLOBAL *s, unsigned slot,
                                       unsigned id)
{
    g_autofree char *path = object_get_canonical_path(OBJECT(s));

    warn_report("%s: TAMPER_RESP_%u.SYS_LOCKDOWN_%u not supported yet!",
                path, slot, id);
}

static void pmc_global_tamper_shutdown(PMC_GLOBAL *s, unsigned slot)
{
    g_autofree char *path = object_get_canonical_path(OBJECT(s));

    info_report("%s: TAMPER_RESP_%u.SYS_RESET triggers system shutdown!",
                path, slot);
    qemu_system_shutdown_request(SHUTDOWN_CAUSE_SUBSYSTEM_RESET);
}

static void pmc_global_tamper_respond(PMC_GLOBAL *s, unsigned slot)
{
    qemu_irq irq;
    uint32_t resp;

    assert(slot < ARRAY_SIZE(s->tamper_out));

    /* Relay to external responder, if one is attached */
    irq = s->tamper_out[slot];
    if (qemu_irq_is_connected(irq)) {
        qemu_irq_pulse(irq);
        return;
    }

    /* Otherwise, apply built-in responses */
    resp = pmc_global_tamper_response(s, slot);

    /* Wipe/lock all selected areas */
    if (FIELD_EX32(resp, TAMPER_RESP_0, BBRAM_ERASE)) {
        pmc_global_tamper_erase_bbram(s, slot);
    }

    if (FIELD_EX32(resp, TAMPER_RESP_0, SYS_LOCKDOWN_1)) {
        pmc_global_tamper_lockdown(s, slot, 1);
    }

    if (FIELD_EX32(resp, TAMPER_RESP_0, SYS_LOCKDOWN_0)) {
        pmc_global_tamper_lockdown(s, slot, 0);
    }

    /* Halt if selected */
    if (FIELD_EX32(resp, TAMPER_RESP_0, SYS_RESET)) {
        pmc_global_tamper_shutdown(s, slot);
        return;
    }

    /* Notify if selected */
    if (FIELD_EX32(resp, TAMPER_RESP_0, SYS_INTERRUPT)) {
        ARRAY_FIELD_DP32(s->regs, PMC_GLOBAL_ISR, TAMPER_INT, 1);
        pmc_global_imr_update_irq(s);
    }
}

static void pmc_global_tamper_event_set(PMC_GLOBAL *s, uint32_t events)
{
    unsigned n;

    static const struct resp_map {
        unsigned slot;
        uint32_t event_mask;
    } resp_map[] = {
        /* In order of decreasing priority */
        { R_TAMPER_RESP_13, XLNX_AMS_VCCINT_GLITCHES_MASK },
        { R_TAMPER_RESP_11, XLNX_AMS_VOLT_7_ALARM_MASK },
        { R_TAMPER_RESP_10, XLNX_AMS_VOLT_6_ALARM_MASK },
        { R_TAMPER_RESP_9,  XLNX_AMS_VOLT_5_ALARM_MASK },
        { R_TAMPER_RESP_8,  XLNX_AMS_VOLT_4_ALARM_MASK },
        { R_TAMPER_RESP_7,  XLNX_AMS_VOLT_3_ALARM_MASK },
        { R_TAMPER_RESP_6,  XLNX_AMS_VOLT_2_ALARM_MASK },
        { R_TAMPER_RESP_5,  XLNX_AMS_VOLT_1_ALARM_MASK },
        { R_TAMPER_RESP_4,  XLNX_AMS_VOLT_0_ALARM_MASK },
        { R_TAMPER_RESP_3,  XLNX_AMS_TEMP_ALARM_MASK },
        { R_TAMPER_RESP_2,  XLNX_AMS_DBG_TAMPER_TRIG_MASK },
        { R_TAMPER_RESP_1,  XLNX_AMS_MIO_TAMPER_TRIG_MASK },
        { R_TAMPER_RESP_0,  XLNX_AMS_SW_TAMPER_TRIG_MASK },
    };

    /*
     * Respond to event in priority order.
     */
    for (n = 0; events && n < ARRAY_SIZE(resp_map); n++) {
        unsigned id = resp_map[n].slot;
        uint32_t em = resp_map[n].event_mask;

        if (!(events & em)) {
            continue;
        }

        if ((id == R_TAMPER_RESP_13) && !pmc_global_gd_monitor_enabled(s)) {
            /* Skip if glitch-detection/-monitoring are disabled */
            continue;
        }

        pmc_global_tamper_respond(s, (id - R_TAMPER_RESP_0));
        events &= ~em;
    }
}

static uint64_t tamper_trig_prew(RegisterInfo *reg, uint64_t val64)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(reg->opaque);

    if (FIELD_EX32(val64, TAMPER_TRIG, TAMPER)) {
        pmc_global_tamper_event_set(s, XLNX_AMS_SW_TAMPER_TRIG_MASK);
    }

    return 0;  /* All bits are write-only */
}

static RegisterAccessInfo pmc_global_regs_info[] = {
    {   .name = "GLOBAL_CNTRL",  .addr = A_GLOBAL_CNTRL,
        .reset = 0x48800,
        .rsvd = 0xfff800e8,
        .ro = 0xfffb00e8,
    },{ .name = "PMC_MULTI_BOOT",  .addr = A_PMC_MULTI_BOOT,
    },{ .name = "PPU1_TRM_CTRL",  .addr = A_PPU1_TRM_CTRL,
        .rsvd = 0xfffffffe,
    },{ .name = "PMC_GLOBAL_ISR",  .addr = A_PMC_GLOBAL_ISR,
        .rsvd = 0xfffffff0,
        .ro = 0xfffffff0,
        .w1c = 0xf,
        .post_write = pmc_global_isr_postw,
    },{ .name = "PMC_GLOBAL_IMR",  .addr = A_PMC_GLOBAL_IMR,
        .reset = 0xf,
        .rsvd = 0xfffffff0,
        .ro = 0xffffffff,
    },{ .name = "PMC_GLOBAL_IER",  .addr = A_PMC_GLOBAL_IER,
        .pre_write = pmc_global_ier_prew,
    },{ .name = "PMC_GLOBAL_IDR",  .addr = A_PMC_GLOBAL_IDR,
        .pre_write = pmc_global_idr_prew,
    },{ .name = "PPU1_DEBUG_CTRL",  .addr = A_PPU1_DEBUG_CTRL,
        .reset = 0x1,
        .rsvd = 0xfffffffe,
        .ro = 0xfffffffe,
    },{ .name = "PPU1_DEBUG_LOCK",  .addr = A_PPU1_DEBUG_LOCK,
        .rsvd = 0xfffffffe,
        .ro = 0xfffffffe,
    },{ .name = "GLOBAL_GEN_STORAGE0",  .addr = A_GLOBAL_GEN_STORAGE0,
    },{ .name = "GLOBAL_GEN_STORAGE1",  .addr = A_GLOBAL_GEN_STORAGE1,
    },{ .name = "GLOBAL_GEN_STORAGE2",  .addr = A_GLOBAL_GEN_STORAGE2,
    },{ .name = "GLOBAL_GEN_STORAGE3",  .addr = A_GLOBAL_GEN_STORAGE3,
    },{ .name = "GLOBAL_GEN_STORAGE4",  .addr = A_GLOBAL_GEN_STORAGE4,
    },{ .name = "PERS_GLOB_GEN_STORAGE0",  .addr = A_PERS_GLOB_GEN_STORAGE0,
    },{ .name = "PERS_GLOB_GEN_STORAGE1",  .addr = A_PERS_GLOB_GEN_STORAGE1,
    },{ .name = "PERS_GLOB_GEN_STORAGE2",  .addr = A_PERS_GLOB_GEN_STORAGE2,
    },{ .name = "PERS_GLOB_GEN_STORAGE3",  .addr = A_PERS_GLOB_GEN_STORAGE3,
    },{ .name = "PERS_GLOB_GEN_STORAGE4",  .addr = A_PERS_GLOB_GEN_STORAGE4,
    },{ .name = "PMC_GSW_ERR",  .addr = A_PMC_GSW_ERR,
    },{ .name = "PWR_STATUS",  .addr = A_PWR_STATUS,
        .rsvd = 0xfff80000,
        .ro = 0xffffffff,
    },{ .name = "PWR_SUPPLY_STATUS",  .addr = A_PWR_SUPPLY_STATUS,
        .rsvd = 0xffffff00,
        .ro = 0xffffffff,
    },{ .name = "REQ_PWRUP_STATUS",  .addr = A_REQ_PWRUP_STATUS,
        .rsvd = 0xfffffff8,
        .ro = 0xfffffff8,
        .w1c = 0x7,
        .post_write = req_pwrup_status_postw,
    },{ .name = "REQ_PWRUP_INT_MASK",  .addr = A_REQ_PWRUP_INT_MASK,
        .reset = 0x7,
        .rsvd = 0xfffffff8,
        .ro = 0xffffffff,
    },{ .name = "REQ_PWRUP_INT_EN",  .addr = A_REQ_PWRUP_INT_EN,
        .pre_write = req_pwrup_int_en_prew,
    },{ .name = "REQ_PWRUP_INT_DIS",  .addr = A_REQ_PWRUP_INT_DIS,
        .pre_write = req_pwrup_int_dis_prew,
    },{ .name = "REQ_PWRUP_TRIG",  .addr = A_REQ_PWRUP_TRIG,
        .pre_write = req_pwrup_trig_prew,
    },{ .name = "REQ_PWRDWN_STATUS",  .addr = A_REQ_PWRDWN_STATUS,
        .rsvd = 0xfffffff8,
        .ro = 0xfffffff8,
        .w1c = 0x7,
        .post_write = req_pwrdwn_status_postw,
    },{ .name = "REQ_PWRDWN_INT_MASK",  .addr = A_REQ_PWRDWN_INT_MASK,
        .reset = 0x7,
        .rsvd = 0xfffffff8,
        .ro = 0xffffffff,
    },{ .name = "REQ_PWRDWN_INT_EN",  .addr = A_REQ_PWRDWN_INT_EN,
        .pre_write = req_pwrdwn_int_en_prew,
    },{ .name = "REQ_PWRDWN_INT_DIS",  .addr = A_REQ_PWRDWN_INT_DIS,
        .pre_write = req_pwrdwn_int_dis_prew,
    },{ .name = "REQ_PWRDWN_TRIG",  .addr = A_REQ_PWRDWN_TRIG,
        .pre_write = req_pwrdwn_trig_prew,
    },{ .name = "REQ_ISO_STATUS",  .addr = A_REQ_ISO_STATUS,
        .rsvd = 0xfffffff8,
        .ro = 0xfffffff8,
        .w1c = 0x7,
        .post_write = req_iso_status_postw,
    },{ .name = "REQ_ISO_INT_MASK",  .addr = A_REQ_ISO_INT_MASK,
        .reset = 0x7,
        .rsvd = 0xfffffff8,
        .ro = 0xffffffff,
    },{ .name = "REQ_ISO_INT_EN",  .addr = A_REQ_ISO_INT_EN,
        .rsvd = 0xfffffff8,
        .pre_write = req_iso_int_en_prew,
    },{ .name = "REQ_ISO_INT_DIS",  .addr = A_REQ_ISO_INT_DIS,
        .rsvd = 0xfffffff8,
        .pre_write = req_iso_int_dis_prew,
    },{ .name = "REQ_ISO_TRIG",  .addr = A_REQ_ISO_TRIG,
        .rsvd = 0xfffffff8,
        .pre_write = req_iso_trig_prew,
    },{ .name = "DDR_RETENTION",  .addr = A_DDR_RETENTION,
    },{ .name = "USR_GTS",  .addr = A_USR_GTS,
    },{ .name = "REQ_SWRST_STATUS",  .addr = A_REQ_SWRST_STATUS,
        .rsvd = 0xfffffff0,
        .ro = 0xfffffff0,
        .w1c = 0xf,
        .post_write = req_swrst_status_postw,
    },{ .name = "REQ_SWRST_INT_MASK",  .addr = A_REQ_SWRST_INT_MASK,
        .reset = 0xf,
        .rsvd = 0xfffffff0,
        .ro = 0xffffffff,
    },{ .name = "REQ_SWRST_INT_EN",  .addr = A_REQ_SWRST_INT_EN,
        .pre_write = req_swrst_int_en_prew,
    },{ .name = "REQ_SWRST_INT_DIS",  .addr = A_REQ_SWRST_INT_DIS,
        .pre_write = req_swrst_int_dis_prew,
    },{ .name = "REQ_SWRST_TRIG",  .addr = A_REQ_SWRST_TRIG,
        .pre_write = req_swrst_trig_prew,
    },{ .name = "WAKEUP_IRQ_STATUS",  .addr = A_WAKEUP_IRQ_STATUS,
        .rsvd = 0xfffffffc,
        .w1c = 0xffffffff,
        .post_write = wakeup_irq_status_postw,
    },{ .name = "WAKEUP_IRQ_MASK",  .addr = A_WAKEUP_IRQ_MASK,
        .reset = 0x3,
        .rsvd = 0xfffffffc,
        .ro = 0xffffffff,
    },{ .name = "WAKEUP_IRQ_EN",  .addr = A_WAKEUP_IRQ_EN,
        .rsvd = 0xfffffffc,
        .pre_write = wakeup_irq_en_prew,
    },{ .name = "WAKEUP_IRQ_DIS",  .addr = A_WAKEUP_IRQ_DIS,
        .rsvd = 0xfffffffc,
        .pre_write = wakeup_irq_dis_prew,
    },{ .name = "WAKEUP_IRQ_TRIG",  .addr = A_WAKEUP_IRQ_TRIG,
        .rsvd = 0xfffffffc,
        .pre_write = wakeup_irq_trig_prew,
    },{ .name = "DBG_PWR_ACK",  .addr = A_DBG_PWR_ACK,
        .rsvd = 0xfffffffc,
    },{ .name = "PMC_SSS_CFG",  .addr = A_PMC_SSS_CFG,
        .rsvd = 0xff000000,
    },{ .name = "TEST_PATTERN_CFG",  .addr = A_TEST_PATTERN_CFG,
        .rsvd = 0xfffffffc,
        .ro = 0xfffffffc,
    },{ .name = "PRAM_ZEROIZE_SIZE",  .addr = A_PRAM_ZEROIZE_SIZE,
    },{ .name = "TAMPER_RESP_0",  .addr = A_TAMPER_RESP_0,
        .rsvd = 0xffffffe0,
    },{ .name = "TAMPER_RESP_1",  .addr = A_TAMPER_RESP_1,
        .rsvd = 0xffffffe0,
    },{ .name = "TAMPER_RESP_2",  .addr = A_TAMPER_RESP_2,
        .rsvd = 0xffffffe0,
    },{ .name = "TAMPER_RESP_3",  .addr = A_TAMPER_RESP_3,
        .rsvd = 0xffffffe0,
    },{ .name = "TAMPER_RESP_4",  .addr = A_TAMPER_RESP_4,
        .rsvd = 0xffffffe0,
    },{ .name = "TAMPER_RESP_5",  .addr = A_TAMPER_RESP_5,
        .rsvd = 0xffffffe0,
    },{ .name = "TAMPER_RESP_6",  .addr = A_TAMPER_RESP_6,
        .rsvd = 0xffffffe0,
    },{ .name = "TAMPER_RESP_7",  .addr = A_TAMPER_RESP_7,
        .rsvd = 0xffffffe0,
    },{ .name = "TAMPER_RESP_8",  .addr = A_TAMPER_RESP_8,
        .rsvd = 0xffffffe0,
    },{ .name = "TAMPER_RESP_9",  .addr = A_TAMPER_RESP_9,
        .rsvd = 0xffffffe0,
    },{ .name = "TAMPER_RESP_10",  .addr = A_TAMPER_RESP_10,
        .rsvd = 0xffffffe0,
    },{ .name = "TAMPER_RESP_11",  .addr = A_TAMPER_RESP_11,
        .rsvd = 0xffffffe0,
    },{ .name = "TAMPER_RESP_12",  .addr = A_TAMPER_RESP_12,
        .rsvd = 0xffffffe0,
    },{ .name = "TAMPER_RESP_13",  .addr = A_TAMPER_RESP_13,
        .rsvd = 0xffffffe0,
    },{ .name = "TAMPER_TRIG",  .addr = A_TAMPER_TRIG,
        .pre_write = tamper_trig_prew,
    },{ .name = "PPU0_MB_FATAL",  .addr = A_PPU0_MB_FATAL,
        .rsvd = 0xfffffff8,
        .ro = 0xffffffff,
    },{ .name = "PPU0_MB1_FT_STATUS",  .addr = A_PPU0_MB1_FT_STATUS,
        .rsvd = 0xffff8000,
        .ro = 0xffffffff,
    },{ .name = "PPU0_MB2_FT_STATUS",  .addr = A_PPU0_MB2_FT_STATUS,
        .rsvd = 0xffff8000,
        .ro = 0xffffffff,
    },{ .name = "PPU0_MB3_FT_STATUS",  .addr = A_PPU0_MB3_FT_STATUS,
        .rsvd = 0xffff8000,
        .ro = 0xffffffff,
    },{ .name = "PPU1_MB_FATAL",  .addr = A_PPU1_MB_FATAL,
        .rsvd = 0xfffff8,
        .ro = 0xffffff,
    },{ .name = "PPU1_MB1_FT_STATUS",  .addr = A_PPU1_MB1_FT_STATUS,
        .rsvd = 0xffff8000,
        .ro = 0xffffffff,
    },{ .name = "PPU1_MB2_FT_STATUS",  .addr = A_PPU1_MB2_FT_STATUS,
        .rsvd = 0xffff8000,
        .ro = 0xffffffff,
    },{ .name = "PPU1_MB3_FT_STATUS",  .addr = A_PPU1_MB3_FT_STATUS,
        .rsvd = 0xffff8000,
        .ro = 0xffffffff,
    },{ .name = "PPU_1_RST",  .addr = A_PPU_1_RST,
        .post_write = ppu1_rst_x_postw,
    },{ .name = "PPU_1_RST_MODE",  .addr = A_PPU_1_RST_MODE,
        .reset = 0x1,
        .rsvd = 0xffffffec,
        .post_write = ppu1_rst_x_postw,
    },{ .name = "PPU0_AXI",  .addr = A_PPU0_AXI,
        .reset = 0xff,
        .rsvd = 0xffffff00,
    },{ .name = "PPU1_AXI",  .addr = A_PPU1_AXI,
        .reset = 0xff,
        .rsvd = 0xffffff00,
    },{ .name = "ROM_VALIDATION_STATUS",  .addr = A_ROM_VALIDATION_STATUS,
        .rsvd = 0xfffffffc,
        .ro = 0xffffffff,
    },{ .name = "ROM_VALIDATION_DIGEST_0",  .addr = A_ROM_VALIDATION_DIGEST_0,
        .reset = 0xffffffff,
        .ro = 0xffffffff,
    },{ .name = "ROM_VALIDATION_DIGEST_1",  .addr = A_ROM_VALIDATION_DIGEST_1,
        .reset = 0xffffffff,
        .ro = 0xffffffff,
    },{ .name = "ROM_VALIDATION_DIGEST_2",  .addr = A_ROM_VALIDATION_DIGEST_2,
        .reset = 0xffffffff,
        .ro = 0xffffffff,
    },{ .name = "ROM_VALIDATION_DIGEST_3",  .addr = A_ROM_VALIDATION_DIGEST_3,
        .reset = 0xffffffff,
        .ro = 0xffffffff,
    },{ .name = "ROM_VALIDATION_DIGEST_4",  .addr = A_ROM_VALIDATION_DIGEST_4,
        .reset = 0xffffffff,
        .ro = 0xffffffff,
    },{ .name = "ROM_VALIDATION_DIGEST_5",  .addr = A_ROM_VALIDATION_DIGEST_5,
        .reset = 0xffffffff,
        .ro = 0xffffffff,
    },{ .name = "ROM_VALIDATION_DIGEST_6",  .addr = A_ROM_VALIDATION_DIGEST_6,
        .reset = 0xffffffff,
        .ro = 0xffffffff,
    },{ .name = "ROM_VALIDATION_DIGEST_7",  .addr = A_ROM_VALIDATION_DIGEST_7,
        .reset = 0xffffffff,
        .ro = 0xffffffff,
    },{ .name = "ROM_VALIDATION_DIGEST_8",  .addr = A_ROM_VALIDATION_DIGEST_8,
        .reset = 0xffffffff,
        .ro = 0xffffffff,
    },{ .name = "ROM_VALIDATION_DIGEST_9",  .addr = A_ROM_VALIDATION_DIGEST_9,
        .reset = 0xffffffff,
        .ro = 0xffffffff,
    },{ .name = "ROM_VALIDATION_DIGEST_10",  .addr = A_ROM_VALIDATION_DIGEST_10,
        .reset = 0xffffffff,
        .ro = 0xffffffff,
    },{ .name = "ROM_VALIDATION_DIGEST_11",  .addr = A_ROM_VALIDATION_DIGEST_11,
        .reset = 0xffffffff,
        .ro = 0xffffffff,
    },{ .name = "PMC_FW_AUTH_HASH_0",  .addr = A_PMC_FW_AUTH_HASH_0,
        .reset = 0xffffffff,
    },{ .name = "PMC_FW_AUTH_HASH_1",  .addr = A_PMC_FW_AUTH_HASH_1,
        .reset = 0xffffffff,
    },{ .name = "PMC_FW_AUTH_HASH_2",  .addr = A_PMC_FW_AUTH_HASH_2,
        .reset = 0xffffffff,
    },{ .name = "PMC_FW_AUTH_HASH_3",  .addr = A_PMC_FW_AUTH_HASH_3,
        .reset = 0xffffffff,
    },{ .name = "PMC_FW_AUTH_HASH_4",  .addr = A_PMC_FW_AUTH_HASH_4,
        .reset = 0xffffffff,
    },{ .name = "PMC_FW_AUTH_HASH_5",  .addr = A_PMC_FW_AUTH_HASH_5,
        .reset = 0xffffffff,
    },{ .name = "PMC_FW_AUTH_HASH_6",  .addr = A_PMC_FW_AUTH_HASH_6,
        .reset = 0xffffffff,
    },{ .name = "PMC_FW_AUTH_HASH_7",  .addr = A_PMC_FW_AUTH_HASH_7,
        .reset = 0xffffffff,
    },{ .name = "PMC_FW_AUTH_HASH_8",  .addr = A_PMC_FW_AUTH_HASH_8,
        .reset = 0xffffffff,
    },{ .name = "PMC_FW_AUTH_HASH_9",  .addr = A_PMC_FW_AUTH_HASH_9,
        .reset = 0xffffffff,
    },{ .name = "PMC_FW_AUTH_HASH_10",  .addr = A_PMC_FW_AUTH_HASH_10,
        .reset = 0xffffffff,
    },{ .name = "PMC_FW_AUTH_HASH_11",  .addr = A_PMC_FW_AUTH_HASH_11,
        .reset = 0xffffffff,
    },{ .name = "SAFETY_CHK",  .addr = A_SAFETY_CHK,
    },{ .name = "SAFETY_CNTRL",  .addr = A_SAFETY_CNTRL,
        .reset = 0x1,
        .rsvd = 0xfffffffe,
        .ro = 0xfffffffe,
    },{ .name = "PL_STATUS",  .addr = A_PL_STATUS,
        .rsvd = 0xfffffffe,
        .ro = 0xffffffff,
    },{ .name = "DONE",  .addr = A_DONE,
    },{ .name = "PMC_PL_GPO",  .addr = A_PMC_PL_GPO,
    },{ .name = "PMC_PPU1_GPI",  .addr = A_PMC_PPU1_GPI,
        .w1c = 0xffffffff,
        .post_write = pmc_ppu1_gpi_postw,
    },{ .name = "PMC_PPU1_GPI_MASK",  .addr = A_PMC_PPU1_GPI_MASK,
        .reset = 0xffffffff,
        .ro = 0xffffffff,
    },{ .name = "PMC_PPU1_GPI_EN",  .addr = A_PMC_PPU1_GPI_EN,
        .pre_write = pmc_ppu1_gpi_en_prew,
    },{ .name = "PMC_PPU1_GPI_DIS",  .addr = A_PMC_PPU1_GPI_DIS,
        .pre_write = pmc_ppu1_gpi_dis_prew,
    },{ .name = "PMC_PPU1_GPI_TRIG",  .addr = A_PMC_PPU1_GPI_TRIG,
        .pre_write = pmc_ppu1_gpi_trig_prew,
    },{ .name = "PMC_PL_IRQ",  .addr = A_PMC_PL_IRQ,
        .w1c = 0xf,
        .post_write = pmc_pl_irq_postw,
    },{ .name = "PMC_PL_IRQ_MASK",  .addr = A_PMC_PL_IRQ_MASK,
        .reset = 0xf,
        .ro = 0xf,
    },{ .name = "PMC_PL_IRQ_EN",  .addr = A_PMC_PL_IRQ_EN,
        .pre_write = pmc_pl_irq_en_prew,
    },{ .name = "PMC_PL_IRQ_DIS",  .addr = A_PMC_PL_IRQ_DIS,
        .pre_write = pmc_pl_irq_dis_prew,
    },{ .name = "SSIT_NOC_ID",  .addr = A_SSIT_NOC_ID,
        .rsvd = 0xffffc000,
        .ro = 0xffffffff,
    },{ .name = "SSIT_SEC_STATUS",  .addr = A_SSIT_SEC_STATUS,
        .rsvd = 0xfffffffc,
        .ro = 0xffffffff,
    },{ .name = "SSIT_ERR",  .addr = A_SSIT_ERR,
        .rsvd = 0xfffffff8,
    },{ .name = "SEM_CRAM_ATTRIB",  .addr = A_SEM_CRAM_ATTRIB,
        .rsvd = 0xffff0000,
    },{ .name = "SEM_NPI_ATTRIB",  .addr = A_SEM_NPI_ATTRIB,
        .rsvd = 0xff000000,
    },{ .name = "SEM_NPI_HDR_ADDR_0",  .addr = A_SEM_NPI_HDR_ADDR_0,
    },{ .name = "SEM_NPI_HDR_ADDR_1",  .addr = A_SEM_NPI_HDR_ADDR_1,
    },{ .name = "SEM_CLASSIFICATION_0",  .addr = A_SEM_CLASSIFICATION_0,
    },{ .name = "SEM_CLASSIFICATION_1",  .addr = A_SEM_CLASSIFICATION_1,
    },{ .name = "SEM_STATUS",  .addr = A_SEM_STATUS,
    },{ .name = "SEM_ERROR",  .addr = A_SEM_ERROR,
    },{ .name = "SEM_CMD_REG0",  .addr = A_SEM_CMD_REG0,
        .rsvd = 0xf0000000,
    },{ .name = "SEM_CMD_REG0_EXT",  .addr = A_SEM_CMD_REG0_EXT,
    },{ .name = "SEM_CMD_REG1",  .addr = A_SEM_CMD_REG1,
        .rsvd = 0xf0000000,
    },{ .name = "SEM_CMD_REG1_EXT",  .addr = A_SEM_CMD_REG1_EXT,
    },{ .name = "SEM_CMD_REG2",  .addr = A_SEM_CMD_REG2,
        .rsvd = 0xf0000000,
    },{ .name = "SEM_CMD_REG2_EXT",  .addr = A_SEM_CMD_REG2_EXT,
    },{ .name = "SEM_CMD_REG3",  .addr = A_SEM_CMD_REG3,
        .rsvd = 0xf0000000,
    },{ .name = "SEM_CMD_REG3_EXT",  .addr = A_SEM_CMD_REG3_EXT,
    },{ .name = "SEM_CRAMERR_ADDRL0",  .addr = A_SEM_CRAMERR_ADDRL0,
        .rsvd = 0xf0000000,
    },{ .name = "SEM_CRAMERR_ADDRH0",  .addr = A_SEM_CRAMERR_ADDRH0,
    },{ .name = "SEM_CRAMERR_ADDRL1",  .addr = A_SEM_CRAMERR_ADDRL1,
        .rsvd = 0xf0000000,
    },{ .name = "SEM_CRAMERR_ADDRH1",  .addr = A_SEM_CRAMERR_ADDRH1,
    },{ .name = "SEM_CRAMERR_ADDRL2",  .addr = A_SEM_CRAMERR_ADDRL2,
        .rsvd = 0xf0000000,
    },{ .name = "SEM_CRAMERR_ADDRH2",  .addr = A_SEM_CRAMERR_ADDRH2,
    },{ .name = "SEM_CRAMERR_ADDRL3",  .addr = A_SEM_CRAMERR_ADDRL3,
        .rsvd = 0xf0000000,
    },{ .name = "SEM_CRAMERR_ADDRH3",  .addr = A_SEM_CRAMERR_ADDRH3,
    },{ .name = "SEM_RESERVED_0",  .addr = A_SEM_RESERVED_0,
    },{ .name = "SEM_RESERVED_1",  .addr = A_SEM_RESERVED_1,
    },{ .name = "SEM_RESERVED_2",  .addr = A_SEM_RESERVED_2,
    },{ .name = "SEM_RESERVED_3",  .addr = A_SEM_RESERVED_3,
    },{ .name = "PMC_MUTEX_0",  .addr = A_PMC_MUTEX_0,
    },{ .name = "PMC_MUTEX_1",  .addr = A_PMC_MUTEX_1,
    },{ .name = "PMC_MUTEX_2",  .addr = A_PMC_MUTEX_2,
    },{ .name = "PMC_MUTEX_3",  .addr = A_PMC_MUTEX_3,
    },{ .name = "PMC_MUTEX_4",  .addr = A_PMC_MUTEX_4,
    },{ .name = "PMC_MUTEX_5",  .addr = A_PMC_MUTEX_5,
    },{ .name = "PMC_MUTEX_6",  .addr = A_PMC_MUTEX_6,
    },{ .name = "PMC_MUTEX_7",  .addr = A_PMC_MUTEX_7,
    },{ .name = "PMC_MUTEX_8",  .addr = A_PMC_MUTEX_8,
    },{ .name = "PMC_MUTEX_9",  .addr = A_PMC_MUTEX_9,
    },{ .name = "PMC_MUTEX_10",  .addr = A_PMC_MUTEX_10,
    },{ .name = "PMC_MUTEX_11",  .addr = A_PMC_MUTEX_11,
    },{ .name = "PMC_MUTEX_12",  .addr = A_PMC_MUTEX_12,
    },{ .name = "PMC_MUTEX_13",  .addr = A_PMC_MUTEX_13,
    },{ .name = "PMC_MUTEX_14",  .addr = A_PMC_MUTEX_14,
    },{ .name = "PMC_MUTEX_15",  .addr = A_PMC_MUTEX_15,
    },{ .name = "PMC_MUTEX_16",  .addr = A_PMC_MUTEX_16,
    },{ .name = "PMC_MUTEX_17",  .addr = A_PMC_MUTEX_17,
    },{ .name = "PMC_MUTEX_18",  .addr = A_PMC_MUTEX_18,
    },{ .name = "PMC_MUTEX_19",  .addr = A_PMC_MUTEX_19,
    },{ .name = "PMC_MUTEX_20",  .addr = A_PMC_MUTEX_20,
    },{ .name = "PMC_MUTEX_21",  .addr = A_PMC_MUTEX_21,
    },{ .name = "PMC_MUTEX_22",  .addr = A_PMC_MUTEX_22,
    },{ .name = "PMC_MUTEX_23",  .addr = A_PMC_MUTEX_23,
    },{ .name = "PMC_MUTEX_24",  .addr = A_PMC_MUTEX_24,
    },{ .name = "PMC_MUTEX_25",  .addr = A_PMC_MUTEX_25,
    },{ .name = "PMC_MUTEX_26",  .addr = A_PMC_MUTEX_26,
    },{ .name = "PMC_MUTEX_27",  .addr = A_PMC_MUTEX_27,
    },{ .name = "PMC_MUTEX_28",  .addr = A_PMC_MUTEX_28,
    },{ .name = "PMC_MUTEX_29",  .addr = A_PMC_MUTEX_29,
    },{ .name = "PMC_MUTEX_30",  .addr = A_PMC_MUTEX_30,
    },{ .name = "PMC_MUTEX_31",  .addr = A_PMC_MUTEX_31,
    },{ .name = "PPU_1_RST_LOCK",  .addr = A_PPU_1_RST_LOCK,
    },{ .name = "POR_LOCK",  .addr = A_POR_LOCK,
    }
};

static void pmc_global_reset(DeviceState *dev)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(dev);
    hwaddr addr;
    unsigned int i;
    QemuOpts *opts = qemu_find_opts_singleton("boot-opts");
    uint32_t boot_mode = qemu_opt_get_number(opts, "mode", 0);

    for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
        if (s->regs_info[i].access) {
            addr = s->regs_info[i].access->addr;
        } else {
            continue;
        }
        switch (addr) {
        case A_PMC_MULTI_BOOT:
        case A_PERS_GLOB_GEN_STORAGE0...A_PERS_GLOB_GEN_STORAGE4:
            continue;
        default:
            register_reset(&s->regs_info[i]);
        }
    }

    /*
     * Update Multi-Boot register for
     * SD0/SD1/SD1_LS and EMMC boot modes;
     */
    switch (boot_mode & 0xF) {
    case 0x3:
    case 0x5:
    case 0xe:
        /*
         * HACK: Default SD to file system mode
         */
        if (!(boot_mode & 0xF000000)) {
            s->regs[R_PMC_MULTI_BOOT] |=
                0xF0000000;
            break;
        }
        /*
         * Fall through and update Multi-boot
         * for non file system boot.
         */
    case 0x6:
        s->regs[R_PMC_MULTI_BOOT] |=
            (boot_mode & 0xF0000000);
        break;
    default:
        break;
    };

    ppu1_update_ctrl(s);
    pmc_ppu1_gpi_update_irq(s);
    req_pwrdwn_int_update_irq(s);
    wakeup_irq_update_irq(s);
    req_swrst_int_update_irq(s);
    req_pwrup_int_update_irq(s);
    pmc_global_imr_update_irq(s);
    pmc_pl_irq_update_irq(s);
    req_iso_int_update_irq(s);
}

static const MemoryRegionOps pmc_global_ops = {
    .read = register_read_memory,
    .write_with_attrs = register_write_memory_with_attrs,
    .endianness = DEVICE_LITTLE_ENDIAN,
    .valid = {
        .min_access_size = 4,
        .max_access_size = 4,
    },
};

static void pmc_global_isr_set_puf_acc_error(void *opaque, int n, int level)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(opaque);

    /* This error is only a positive-edge latch */
    if (!level || ARRAY_FIELD_EX32(s->regs, PMC_GLOBAL_ISR, PUF_ACC_ERROR)) {
        return;
    }

    ARRAY_FIELD_DP32(s->regs, PMC_GLOBAL_ISR, PUF_ACC_ERROR, 1);
    pmc_global_imr_update_irq(s);
}

static void pmc_global_init(Object *obj)
{
    PMC_GLOBAL *s = XILINX_PMC_GLOBAL(obj);
    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
    RegisterInfoArray *reg_array;
    unsigned n;

    memory_region_init(&s->iomem, obj, TYPE_XILINX_PMC_GLOBAL, R_MAX * 4);
    reg_array =
        register_init_block32(DEVICE(obj), pmc_global_regs_info,
                              ARRAY_SIZE(pmc_global_regs_info),
                              s->regs_info, s->regs,
                              &pmc_global_ops,
                              XILINX_PMC_GLOBAL_ERR_DEBUG,
                              R_MAX * 4);
    memory_region_add_subregion(&s->iomem,
                                0x0,
                                &reg_array->mem);
    sysbus_init_mmio(sbd, &s->iomem);

    /* Order according to PPU1 INTC bits.  */
    sysbus_init_irq(sbd, &s->irq_wakeup_irq);
    sysbus_init_irq(sbd, &s->irq_req_iso_int);
    sysbus_init_irq(sbd, &s->irq_req_swrst_int);
    sysbus_init_irq(sbd, &s->irq_req_pwrup_int);
    sysbus_init_irq(sbd, &s->irq_req_pwrdwn_int);
    sysbus_init_irq(sbd, &s->irq_pmc_pl_irq);
    sysbus_init_irq(sbd, &s->irq_pmc_ppu1_gpi);
    sysbus_init_irq(sbd, &s->irq_pmc_global_imr);
    for (n = 0; n < ARRAY_SIZE(s->tamper_out); n++) {
        sysbus_init_irq(sbd, &s->tamper_out[n]);
    }

    /* Out signals.  */
    qdev_init_gpio_out_named(DEVICE(obj), &s->ppu1_rst, "ppu1_rst", 1);
    qdev_init_gpio_out_named(DEVICE(obj), &s->ppu1_wakeup, "ppu1_wakeup", 1);

    /* In signals. */
    qdev_init_gpio_in(DEVICE(obj), pmc_global_isr_set_puf_acc_error, 1);
}

static void pmc_global_prop_tamper_event_set(Object *obj, Visitor *v,
                                             const char *name, void *opaque,
                                             Error **errp)
{
    uint32_t events = 0;

    visit_type_uint32(v, name, &events, errp);
    if (*errp) {
        return;
    }

    pmc_global_tamper_event_set(XILINX_PMC_GLOBAL(obj), events);
}

static void pmc_global_prop_tamper_event_add(ObjectClass *klass)
{
    object_class_property_add(klass, XLNX_AMS_TAMPER_PROP, "Bits:uint",
                              NULL, /* non-gettable */
                              pmc_global_prop_tamper_event_set,
                              NULL, /* nothing to release */
                              NULL);
    object_class_property_set_description(klass, XLNX_AMS_TAMPER_PROP,
                                          "Set to trigger tamper events");
}

static Property pmc_global_properties[] = {
    DEFINE_PROP_LINK("bbram", PMC_GLOBAL, bbram, TYPE_OBJECT, Object *),
    DEFINE_PROP_LINK("efuse", PMC_GLOBAL, efuse, TYPE_OBJECT, Object *),

    DEFINE_PROP_END_OF_LIST(),
};

static const VMStateDescription vmstate_pmc_global = {
    .name = TYPE_XILINX_PMC_GLOBAL,
    .version_id = 1,
    .minimum_version_id = 1,
    .fields = (VMStateField[]) {
        VMSTATE_UINT32_ARRAY(regs, PMC_GLOBAL, R_MAX),
        VMSTATE_END_OF_LIST(),
    }
};

static const FDTGenericGPIOSet ctrl_gpios[] = {
    {
      .names = &fdt_generic_gpio_name_set_gpio,
      .gpios = (FDTGenericGPIOConnection[]) {
        { .name = "ppu1_rst", .fdt_index = 1 },
        { .name = "ppu1_wakeup", .fdt_index = 2 },
        { },
      },
    },
    {
      .names = &fdt_generic_gpio_name_set_interrupts,
      .gpios = (FDTGenericGPIOConnection[]) {
        { .name = SYSBUS_DEVICE_GPIO_IRQ,
          .fdt_index = 0, .range = 8 + R_TAMPER_RESP_MAX },
        { },
      },
    },
    { },
};

static void pmc_global_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);
    FDTGenericGPIOClass *fggc = FDT_GENERIC_GPIO_CLASS(klass);

    dc->reset = pmc_global_reset;
    dc->vmsd = &vmstate_pmc_global;
    fggc->controller_gpios = ctrl_gpios;

    device_class_set_props(dc, pmc_global_properties);
    pmc_global_prop_tamper_event_add(klass);
}

static const TypeInfo pmc_global_info = {
    .name          = TYPE_XILINX_PMC_GLOBAL,
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(PMC_GLOBAL),
    .class_init    = pmc_global_class_init,
    .instance_init = pmc_global_init,
    .interfaces    = (InterfaceInfo[]) {
        { TYPE_FDT_GENERIC_GPIO },
        { }
    },
};

static void pmc_global_register_types(void)
{
    type_register_static(&pmc_global_info);
}

type_init(pmc_global_register_types)
