diff --git a/xen/arch/arm/platforms/Makefile b/xen/arch/arm/platforms/Makefile
index 49fa683..b58b71f 100644
--- a/xen/arch/arm/platforms/Makefile
+++ b/xen/arch/arm/platforms/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_ARM_64) += seattle.o
 obj-$(CONFIG_ARM_32) += sunxi.o
 obj-$(CONFIG_ARM_64) += xgene-storm.o
 obj-$(CONFIG_ARM_64) += xilinx-zynqmp.o
+obj-$(CONFIG_ARM_64) += xilinx-zynqmp-eemi.o
diff --git a/xen/arch/arm/platforms/xilinx-zynqmp-eemi.c b/xen/arch/arm/platforms/xilinx-zynqmp-eemi.c
new file mode 100644
index 0000000..c2c184d
--- /dev/null
+++ b/xen/arch/arm/platforms/xilinx-zynqmp-eemi.c
@@ -0,0 +1,794 @@
+/*
+ * xen/arch/arm/platforms/xilinx-zynqmp-eemi.c
+ *
+ * Xilinx ZynqMP EEMI API mediator.
+ *
+ * Copyright (c) 2017 Xilinx Inc.
+ * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ * Mediator for the EEMI Power Mangement API.
+ *
+ * Refs:
+ * https://www.xilinx.com/support/documentation/user_guides/ug1200-eemi-api.pdf
+ *
+ * Background:
+ * The ZynqMP has a subsystem named the PMU with a CPU and special devices
+ * dedicated to running Power Management Firmware. Other masters in the
+ * system need to send requests to the PMU in order to for example:
+ * * Manage power state
+ * * Configure clocks
+ * * Program bitstreams for the programmable logic
+ * * etc
+ *
+ * Allthough the details of the setup are configurable, in the common case
+ * the PMU lives in the Secure world. NS World cannot directly communicate
+ * with it and must use proxy services from ARM Trusted Firmware to reach
+ * the PMU.
+ *
+ * Power Management on the ZynqMP is implemented in a layered manner.
+ * The PMU knows about various masters and will enforce access controls
+ * based on a pre-configured partitioning. This configuration dictates
+ * which devices are owned by the various masters and the PMU FW makes sure
+ * that a given master cannot turn off a device that it does not own or that
+ * is in use by other masters.
+ *
+ * The PMU is not aware of multiple execution states in masters.
+ * For example, it treats the ARMv8 cores as single units and does not
+ * distinguish between Secure vs NS OS:s nor does it know about Hypervisors
+ * and multiple guests. It is up to software on the ARMv8 cores to present
+ * a unified view of its power requirements.
+ *
+ * To implement this unified view, ARM Trusted Firmware at EL3 provides
+ * access to the PM API via SMC calls. ARM Trusted Firmware is responsible
+ * for mediating between the Secure and the NS world, rejecting SMC calls
+ * that request changes that are not allowed.
+ *
+ * Xen running above ATF owns the NS world and is responsible for presenting
+ * unified PM requests taking all guests and the hypervisor into account.
+ *
+ * Implementation:
+ * The PM API contains different classes of calls.
+ * Certain calls are harmless to expose to any guest.
+ * These include calls to get the PM API Version, or to read out the version
+ * of the chip we're running on.
+ *
+ * Other calls are more problematic. Here're some:
+ * * Power requests for nodes (i.e turn on or off a given device)
+ * * Reset line control (i.e reset a given device)
+ * * MMIO access (i.e directly access clock and reset registers)
+ *
+ * Power requests for nodes:
+ * In order to correctly mediate these calls, we need to know if
+ * guests issuing these calls have ownership of the given device.
+ * The approach taken here is to map PM API Nodes identifying
+ * a device into base addresses for registers that belong to that
+ * same device.
+ *
+ * If the guest has access to a devices registers, we give the guest
+ * access to PM API calls that affect that device. This is implemented
+ * by pm_node_access and domain_has_node_access().
+ *
+ * Reset lines:
+ * Reset lines are identified by a list of identifiers that do not relate
+ * to device nodes. We can use the same approach here as for nodes, except
+ * that we need a separate table mapping reset lines to base addresses.
+ * This is implemented by pm_reset_access.
+ *
+ * MMIO access:
+ * These calls allow guests to access certain memory ranges. These ranges
+ * are typically protected for secure-world access only and also from
+ * certain masters only, so guests cannot access them directly.
+ * Registers within the memory regions affect certain nodes. In this case,
+ * our imput is an address and we map that address into a node. If the
+ * guest has ownership of that node, the access is allowed.
+ * Some registers contain bitfields and a single register may contain
+ * bits that affect multiple nodes.
+ *
+ * Some of the calls act on more global state. For example acting on
+ * NODE_PS, which affects many a lot of nodes. This higher level
+ * orchestrating is left for the hardware-domain only.
+ */
+
+#include <xen/iocap.h>
+#include <asm/platform.h>
+#include <asm/platforms/xilinx-zynqmp-eemi.h>
+#include <asm/platforms/xilinx-zynqmp-mm.h>
+
+struct pm_access
+{
+    uint64_t addr;
+    bool hwdom_access;    /* HW domain gets access regardless.  */
+};
+
+/*
+ * This table maps a node into a memory address.
+ * If a guest has access to the address, it has enough control
+ * over the node to grant it access to EEMI calls for that node.
+ */
+static const struct pm_access pm_node_access[] = {
+    /* MM_RPU grants access to alll RPU Nodes.  */
+    [NODE_RPU] = { MM_RPU },
+    [NODE_RPU_0] = { MM_RPU },
+    [NODE_RPU_1] = { MM_RPU },
+    [NODE_IPI_RPU_0] = { MM_RPU },
+
+    /* GPU nodes.  */
+    [NODE_GPU] = { MM_GPU },
+    [NODE_GPU_PP_0] = { MM_GPU },
+    [NODE_GPU_PP_1] = { MM_GPU },
+
+    [NODE_USB_0] = { MM_USB3_0 },
+    [NODE_USB_1] = { MM_USB3_1 },
+    [NODE_TTC_0] = { MM_TTC0 },
+    [NODE_TTC_1] = { MM_TTC1 },
+    [NODE_TTC_2] = { MM_TTC2 },
+    [NODE_TTC_3] = { MM_TTC3 },
+    [NODE_SATA] = { MM_SATA_AHCI_HBA },
+    [NODE_ETH_0] = { MM_GEM0 },
+    [NODE_ETH_1] = { MM_GEM1 },
+    [NODE_ETH_2] = { MM_GEM2 },
+    [NODE_ETH_3] = { MM_GEM3 },
+    [NODE_UART_0] = { MM_UART0 },
+    [NODE_UART_1] = { MM_UART1 },
+    [NODE_SPI_0] = { MM_SPI0 },
+    [NODE_SPI_1] = { MM_SPI1 },
+    [NODE_I2C_0] = { MM_I2C0 },
+    [NODE_I2C_1] = { MM_I2C1 },
+    [NODE_SD_0] = { MM_SD0 },
+    [NODE_SD_1] = { MM_SD1 },
+    [NODE_DP] = { MM_DP },
+
+    /* Guest with GDMA Channel 0 gets PM access. Other guests don't.  */
+    [NODE_GDMA] = { MM_GDMA_CH0 },
+    /* Guest with ADMA Channel 0 gets PM access. Other guests don't.  */
+    [NODE_ADMA] = { MM_ADMA_CH0 },
+
+    [NODE_NAND] = { MM_NAND },
+    [NODE_QSPI] = { MM_QSPI },
+    [NODE_GPIO] = { MM_GPIO },
+    [NODE_CAN_0] = { MM_CAN0 },
+    [NODE_CAN_1] = { MM_CAN1 },
+
+    /* Dom0 only.  */
+    [NODE_AFI] = { .hwdom_access = true },
+    [NODE_APLL] = { .hwdom_access = true },
+    [NODE_VPLL] = { .hwdom_access = true },
+    [NODE_DPLL] = { .hwdom_access = true },
+    [NODE_RPLL] = { .hwdom_access = true },
+    [NODE_IOPLL] = { .hwdom_access = true },
+    [NODE_DDR] = { .hwdom_access = true },
+    [NODE_IPI_APU] = { .hwdom_access = true },
+    [NODE_PCAP] = { .hwdom_access = true },
+
+    [NODE_PCIE] = { MM_PCIE_ATTRIB },
+    [NODE_RTC] = { MM_RTC },
+};
+
+/*
+ * This table maps reset line IDs into a memory address.
+ * If a guest has access to the address, it has enough control
+ * over the affected node to grant it access to EEMI calls for
+ * resetting that node.
+ */
+#define PM_RESET_IDX(n) (n - PM_RESET_PCIE_CFG)
+static const struct pm_access pm_reset_access[] = {
+    [PM_RESET_IDX(PM_RESET_PCIE_CFG)] = { MM_AXIPCIE_MAIN },
+    [PM_RESET_IDX(PM_RESET_PCIE_BRIDGE)] = { MM_PCIE_ATTRIB },
+    [PM_RESET_IDX(PM_RESET_PCIE_CTRL)] = { MM_PCIE_ATTRIB },
+
+    [PM_RESET_IDX(PM_RESET_DP)] = { MM_DP },
+    [PM_RESET_IDX(PM_RESET_SWDT_CRF)] = { MM_SWDT },
+    [PM_RESET_IDX(PM_RESET_AFI_FM5)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_AFI_FM4)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_AFI_FM3)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_AFI_FM2)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_AFI_FM1)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_AFI_FM0)] = { .hwdom_access = true },
+
+    /* Channel 0 grants PM access.  */
+    [PM_RESET_IDX(PM_RESET_GDMA)] = { MM_GDMA_CH0 },
+    [PM_RESET_IDX(PM_RESET_GPU_PP1)] = { MM_GPU },
+    [PM_RESET_IDX(PM_RESET_GPU_PP0)] = { MM_GPU },
+    [PM_RESET_IDX(PM_RESET_GT)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_SATA)] = { MM_SATA_AHCI_HBA },
+
+    /* We don't allow anyone to turn on/off the ACPUs.  */
+    [PM_RESET_IDX(PM_RESET_ACPU3_PWRON)] = { 0 },
+    [PM_RESET_IDX(PM_RESET_ACPU2_PWRON)] = { 0 },
+    [PM_RESET_IDX(PM_RESET_ACPU1_PWRON)] = { 0 },
+    [PM_RESET_IDX(PM_RESET_ACPU0_PWRON)] = { 0 },
+    [PM_RESET_IDX(PM_RESET_APU_L2)] = { 0 },
+    [PM_RESET_IDX(PM_RESET_ACPU3)] = { 0 },
+    [PM_RESET_IDX(PM_RESET_ACPU2)] = { 0 },
+    [PM_RESET_IDX(PM_RESET_ACPU1)] = { 0 },
+    [PM_RESET_IDX(PM_RESET_ACPU0)] = { 0 },
+
+    [PM_RESET_IDX(PM_RESET_DDR)] = { 0 },
+
+    [PM_RESET_IDX(PM_RESET_APM_FPD)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_SOFT)] = { .hwdom_access = true },
+
+    [PM_RESET_IDX(PM_RESET_GEM0)] = { MM_GEM0 },
+    [PM_RESET_IDX(PM_RESET_GEM1)] = { MM_GEM1 },
+    [PM_RESET_IDX(PM_RESET_GEM2)] = { MM_GEM2 },
+    [PM_RESET_IDX(PM_RESET_GEM3)] = { MM_GEM3 },
+
+    [PM_RESET_IDX(PM_RESET_QSPI)] = { MM_QSPI },
+    [PM_RESET_IDX(PM_RESET_UART0)] = { MM_UART0 },
+    [PM_RESET_IDX(PM_RESET_UART1)] = { MM_UART1 },
+    [PM_RESET_IDX(PM_RESET_SPI0)] = { MM_SPI0 },
+    [PM_RESET_IDX(PM_RESET_SPI1)] = { MM_SPI1 },
+    [PM_RESET_IDX(PM_RESET_SDIO0)] = { MM_SD0 },
+    [PM_RESET_IDX(PM_RESET_SDIO1)] = { MM_SD1 },
+    [PM_RESET_IDX(PM_RESET_CAN0)] = { MM_CAN0 },
+    [PM_RESET_IDX(PM_RESET_CAN1)] = { MM_CAN1 },
+    [PM_RESET_IDX(PM_RESET_I2C0)] = { MM_I2C0 },
+    [PM_RESET_IDX(PM_RESET_I2C1)] = { MM_I2C1 },
+    [PM_RESET_IDX(PM_RESET_TTC0)] = { MM_TTC0 },
+    [PM_RESET_IDX(PM_RESET_TTC1)] = { MM_TTC1 },
+    [PM_RESET_IDX(PM_RESET_TTC2)] = { MM_TTC2 },
+    [PM_RESET_IDX(PM_RESET_TTC3)] = { MM_TTC3 },
+    [PM_RESET_IDX(PM_RESET_SWDT_CRL)] = { MM_SWDT },
+    [PM_RESET_IDX(PM_RESET_NAND)] = { MM_NAND },
+    /* ADMA Channel 0 grants access to pull the reset signal.  */
+    [PM_RESET_IDX(PM_RESET_ADMA)] = { MM_ADMA_CH0 },
+    [PM_RESET_IDX(PM_RESET_GPIO)] = { MM_GPIO },
+    /* FIXME: What is this?  */
+    [PM_RESET_IDX(PM_RESET_IOU_CC)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_TIMESTAMP)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_RPU_R50)] = { MM_RPU },
+    [PM_RESET_IDX(PM_RESET_RPU_R51)] = { MM_RPU },
+    [PM_RESET_IDX(PM_RESET_RPU_AMBA)] = { MM_RPU },
+    [PM_RESET_IDX(PM_RESET_OCM)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_RPU_PGE)] = { MM_RPU },
+
+    [PM_RESET_IDX(PM_RESET_USB0_CORERESET)] = { MM_USB3_0 },
+    [PM_RESET_IDX(PM_RESET_USB0_HIBERRESET)] = { MM_USB3_0 },
+    [PM_RESET_IDX(PM_RESET_USB0_APB)] = { MM_USB3_0 },
+
+    [PM_RESET_IDX(PM_RESET_USB1_CORERESET)] = { MM_USB3_1 },
+    [PM_RESET_IDX(PM_RESET_USB1_HIBERRESET)] = { MM_USB3_1 },
+    [PM_RESET_IDX(PM_RESET_USB1_APB)] = { MM_USB3_1 },
+
+    [PM_RESET_IDX(PM_RESET_IPI)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_APM_LPD)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_RTC)] = { MM_RTC },
+    [PM_RESET_IDX(PM_RESET_SYSMON)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_AFI_FM6)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_LPD_SWDT)] = { MM_SWDT },
+    [PM_RESET_IDX(PM_RESET_FPD)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_RPU_DBG1)] = { MM_RPU },
+    [PM_RESET_IDX(PM_RESET_RPU_DBG0)] = { MM_RPU },
+    [PM_RESET_IDX(PM_RESET_DBG_LPD)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_DBG_FPD)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_APLL)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_DPLL)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_VPLL)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_IOPLL)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_RPLL)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_0)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_1)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_2)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_3)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_4)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_5)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_6)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_7)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_8)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_9)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_10)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_11)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_12)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_13)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_14)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_15)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_16)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_17)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_18)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_19)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_20)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_21)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_22)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_23)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_24)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_25)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_26)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_27)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_28)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_29)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_30)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_31)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_RPU_LS)] = { MM_RPU },
+    [PM_RESET_IDX(PM_RESET_PS_ONLY)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_PL)] = { .hwdom_access = true },
+};
+
+/*
+ * This table maps reset line IDs into a memory address.
+ * If a guest has access to the address, it has enough control
+ * over the affected node to grant it access to EEMI calls for
+ * resetting that node.
+ */
+static const struct {
+    uint64_t start;
+    uint64_t end;    /* Inclusive. If not set, single reg entry.  */
+    uint32_t mask;   /* Zero means no mask, i.e all bits.  */
+    enum pm_node_id node;
+    bool hwdom_access;
+    bool readonly;
+} pm_mmio_access[] = {
+    {
+        .start = MM_CRF_APB + R_CRF_APLL_CTRL,
+        .end = MM_CRF_APB + R_CRF_ACPU_CTRL,
+        .hwdom_access = true
+    },
+    {
+        .start = MM_CRL_APB + R_CRL_IOPLL_CTRL,
+        .end = MM_CRL_APB + R_CRL_RPLL_TO_FPD_CTRL,
+        .hwdom_access = true
+    },
+    { .start = MM_CRF_APB + R_CRF_DP_VIDEO_REF_CTRL, .node = NODE_DP },
+    { .start = MM_CRF_APB + R_CRF_DP_STC_REF_CTRL, .node = NODE_DP },
+    { .start = MM_CRF_APB + R_CRF_GPU_REF_CTRL, .node = NODE_GPU },
+    { .start = MM_CRF_APB + R_CRF_SATA_REF_CTRL, .node = NODE_SATA },
+    { .start = MM_CRF_APB + R_CRF_PCIE_REF_CTRL, .node = NODE_PCIE },
+    { .start = MM_CRF_APB + R_CRF_GDMA_REF_CTRL, .node = NODE_GDMA },
+    { .start = MM_CRF_APB + R_CRF_DPDMA_REF_CTRL, .node = NODE_DP },
+    { .start = MM_CRL_APB + R_CRL_USB3_DUAL_REF_CTRL, .node = NODE_USB_0 },
+    { .start = MM_CRL_APB + R_CRL_USB0_BUS_REF_CTRL, .node = NODE_USB_0 },
+    { .start = MM_CRL_APB + R_CRL_USB1_BUS_REF_CTRL, .node = NODE_USB_1 },
+    { .start = MM_CRL_APB + R_CRL_USB1_BUS_REF_CTRL, .node = NODE_USB_1 },
+    { .start = MM_CRL_APB + R_CRL_GEM0_REF_CTRL, .node = NODE_ETH_0 },
+    { .start = MM_CRL_APB + R_CRL_GEM1_REF_CTRL, .node = NODE_ETH_1 },
+    { .start = MM_CRL_APB + R_CRL_GEM2_REF_CTRL, .node = NODE_ETH_2 },
+    { .start = MM_CRL_APB + R_CRL_GEM3_REF_CTRL, .node = NODE_ETH_3 },
+    { .start = MM_CRL_APB + R_CRL_QSPI_REF_CTRL, .node = NODE_QSPI },
+    { .start = MM_CRL_APB + R_CRL_SDIO0_REF_CTRL, .node = NODE_SD_0 },
+    { .start = MM_CRL_APB + R_CRL_SDIO1_REF_CTRL, .node = NODE_SD_1 },
+    { .start = MM_CRL_APB + R_CRL_UART0_REF_CTRL, .node = NODE_UART_0 },
+    { .start = MM_CRL_APB + R_CRL_UART1_REF_CTRL, .node = NODE_UART_1 },
+    { .start = MM_CRL_APB + R_CRL_SPI0_REF_CTRL, .node = NODE_SPI_0 },
+    { .start = MM_CRL_APB + R_CRL_SPI1_REF_CTRL, .node = NODE_SPI_1 },
+    { .start = MM_CRL_APB + R_CRL_CAN0_REF_CTRL, .node = NODE_CAN_0 },
+    { .start = MM_CRL_APB + R_CRL_CAN1_REF_CTRL, .node = NODE_CAN_1 },
+    { .start = MM_CRL_APB + R_CRL_CPU_R5_CTRL, .node = NODE_RPU },
+    { .start = MM_CRL_APB + R_CRL_IOU_SWITCH_CTRL, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_CSU_PLL_CTRL, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_PCAP_CTRL, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_LPD_SWITCH_CTRL, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_LPD_LSBUS_CTRL, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_DBG_LPD_CTRL, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_NAND_REF_CTRL, .node = NODE_NAND },
+    { .start = MM_CRL_APB + R_CRL_ADMA_REF_CTRL, .node = NODE_ADMA },
+    { .start = MM_CRL_APB + R_CRL_PL0_REF_CTRL, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_PL1_REF_CTRL, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_PL2_REF_CTRL, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_PL3_REF_CTRL, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_PL0_THR_CTRL, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_PL1_THR_CTRL, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_PL2_THR_CTRL, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_PL3_THR_CTRL, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_PL0_THR_CNT, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_PL1_THR_CNT, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_PL2_THR_CNT, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_PL3_THR_CNT, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_GEM_TSU_REF_CTRL, .node = NODE_ETH_0 },
+    { .start = MM_CRL_APB + R_CRL_DLL_REF_CTRL, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_AMS_REF_CTRL, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_I2C0_REF_CTRL, .node = NODE_I2C_0 },
+    { .start = MM_CRL_APB + R_CRL_I2C1_REF_CTRL, .node = NODE_I2C_1 },
+    { .start = MM_CRL_APB + R_CRL_TIMESTAMP_REF_CTRL, .hwdom_access = true },
+    { .start = MM_IOU_SLCR + R_IOU_SLCR_WDT_CLK_SEL, .hwdom_access = true },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_CAN_MIO_CTRL,
+        .mask = 0x1ff, .node = NODE_CAN_0
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_CAN_MIO_CTRL,
+        .mask = 0x1ff << 15, .node = NODE_CAN_1
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_GEM_CLK_CTRL,
+        .mask = 0xf, .node = NODE_ETH_0
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_GEM_CLK_CTRL,
+        .mask = 0xf << 5, .node = NODE_ETH_1
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_GEM_CLK_CTRL,
+        .mask = 0xf << 10, .node = NODE_ETH_2
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_GEM_CLK_CTRL,
+        .mask = 0xf << 15, .node = NODE_ETH_3
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_GEM_CLK_CTRL,
+        .mask = 0x7 << 20, .hwdom_access = true
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_SDIO_CLK_CTRL,
+        .mask = 0x7, .node = NODE_SD_0
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_SDIO_CLK_CTRL,
+        .mask = 0x7 << 17, .node = NODE_SD_1
+    },
+
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_CTRL_REG_SD,
+        .mask = 0x1, .node = NODE_SD_0
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_CTRL_REG_SD,
+        .mask = 0x1 << 15, .node = NODE_SD_1
+    },
+    /* A series of SD regs with the same layout.  */
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_SD_ITAPDLY,
+        .end = MM_IOU_SLCR + R_IOU_SLCR_SD_CDN_CTRL,
+        .mask = 0x3ff << 0, .node = NODE_SD_0
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_SD_ITAPDLY,
+        .end = MM_IOU_SLCR + R_IOU_SLCR_SD_CDN_CTRL,
+        .mask = 0x3ff << 16, .node = NODE_SD_1
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_GEM_CTRL,
+        .mask = 0x3 << 0, .node = NODE_ETH_0
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_GEM_CTRL,
+        .mask = 0x3 << 2, .node = NODE_ETH_1
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_GEM_CTRL,
+        .mask = 0x3 << 4, .node = NODE_ETH_2
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_GEM_CTRL,
+        .mask = 0x3 << 6, .node = NODE_ETH_3
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_TTC_APB_CLK,
+        .mask = 0x3 << 0, .node = NODE_TTC_0
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_TTC_APB_CLK,
+        .mask = 0x3 << 2, .node = NODE_TTC_1
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_TTC_APB_CLK,
+        .mask = 0x3 << 4, .node = NODE_TTC_2
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_TTC_APB_CLK,
+        .mask = 0x3 << 6, .node = NODE_TTC_3
+    },
+
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_TAPDLY_BYPASS,
+        .mask = 0x3, .node = NODE_NAND
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_TAPDLY_BYPASS,
+        .mask = 0x1 << 2, .node = NODE_QSPI
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_COHERENT_CTRL,
+        .mask = 0xf << 0, .node = NODE_ETH_0
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_COHERENT_CTRL,
+        .mask = 0xf << 4, .node = NODE_ETH_1
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_COHERENT_CTRL,
+        .mask = 0xf << 8, .node = NODE_ETH_2
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_COHERENT_CTRL,
+        .mask = 0xf << 12, .node = NODE_ETH_3
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_COHERENT_CTRL,
+        .mask = 0xf << 16, .node = NODE_SD_0
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_COHERENT_CTRL,
+        .mask = 0xf << 20, .node = NODE_SD_1
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_COHERENT_CTRL,
+        .mask = 0xf << 24, .node = NODE_NAND
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_COHERENT_CTRL,
+        .mask = 0xf << 28, .node = NODE_QSPI
+    },
+    { .start = MM_IOU_SLCR + R_IOU_SLCR_VIDEO_PSS_CLK_SEL, .hwdom_access = true },
+    /* No access to R_IOU_SLCR_IOU_INTERCONNECT_ROUTE at all.  */
+    { .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_RAM_GEM0, .node = NODE_ETH_0 },
+    { .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_RAM_GEM1, .node = NODE_ETH_1 },
+    { .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_RAM_GEM2, .node = NODE_ETH_2 },
+    { .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_RAM_GEM3, .node = NODE_ETH_3 },
+    { .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_RAM_SD0, .node = NODE_SD_0 },
+    { .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_RAM_SD1, .node = NODE_SD_1 },
+    { .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_RAM_CAN0, .node = NODE_CAN_0 },
+    { .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_RAM_CAN1, .node = NODE_CAN_1 },
+    { .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_RAM_LQSPI, .node = NODE_QSPI },
+    { .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_RAM_NAND, .node = NODE_NAND },
+    {
+        .start = MM_PMU_GLOBAL + R_PMU_GLOBAL_PWR_STATE,
+        .readonly = true,
+    },
+    {
+        .start = MM_PMU_GLOBAL + R_PMU_GLOBAL_GLOBAL_GEN_STORAGE0,
+        .end = MM_PMU_GLOBAL + R_PMU_GLOBAL_PERS_GLOB_GEN_STORAGE7,
+        .readonly = true,
+    },
+    {
+        /* Universal read-only access to CRF. Linux CCF needs this.  */
+        .start = MM_CRF_APB, .end = MM_CRF_APB + 0x104,
+        .readonly = true,
+    },
+    {
+        /* Universal read-only access to CRL. Linux CCF needs this.  */
+        .start = MM_CRL_APB, .end = MM_CRL_APB + 0x284,
+        .readonly = true,
+    }
+};
+
+static bool pm_check_access(const struct pm_access *acl, struct domain *d, int idx)
+{
+    unsigned long mfn;
+
+    if ( acl[idx].hwdom_access && is_hardware_domain(d) )
+        return true;
+
+    mfn = paddr_to_pfn(acl[idx].addr);
+    if ( !mfn )
+        return false;
+
+    return iomem_access_permitted(d, mfn, mfn);
+}
+
+/* Check if a domain has access to a node.  */
+static bool domain_has_node_access(struct domain *d, enum pm_node_id node)
+{
+    if ( node <= 0 || node > ARRAY_SIZE(pm_node_access) )
+        return false;
+
+    /* NODE_UNKNOWN is treated as a wildcard.  */
+    if ( node == NODE_UNKNOWN )
+        return true;
+
+    return pm_check_access(pm_node_access, d, node);
+}
+
+/* Check if a domain has access to a reset line.  */
+static bool domain_has_reset_access(struct domain *d, enum pm_reset rst)
+{
+    int rst_idx = PM_RESET_IDX(rst);
+
+    if ( rst_idx < 0 || rst_idx > ARRAY_SIZE(pm_reset_access) )
+        return false;
+
+    return pm_check_access(pm_reset_access, d, rst_idx);
+}
+
+/*
+ * Check if a given domain has access to perform an indirect
+ * MMIO access.
+ *
+ * If the provided mask is invalid, it will be fixed up.
+ */
+static bool domain_mediate_mmio_access(struct domain *d,
+                                       bool write, uint64_t addr,
+                                       uint32_t *mask)
+{
+    unsigned int i;
+    bool ret = false;
+    uint32_t prot_mask = 0;
+
+    ASSERT(mask);
+
+    /*
+     * The hardware domain gets read access to everything.
+     * Lower layers will do further filtering.
+     */
+    if ( !write && is_hardware_domain(d) )
+        return true;
+
+    /* Scan the ACL.  */
+    for ( i = 0; i < ARRAY_SIZE(pm_mmio_access); i++ ) {
+        bool r;
+
+        /* Check if the address is OK.  */
+        if ( pm_mmio_access[i].end ) {
+            /* Memory range.  */
+            if ( addr < pm_mmio_access[i].start )
+                continue;
+            if ( addr > pm_mmio_access[i].end )
+                continue;
+        } else {
+            /* Single register.  */
+            if ( addr != pm_mmio_access[i].start )
+                continue;
+        }
+
+        if ( write && pm_mmio_access[i].readonly )
+            continue;
+        if ( pm_mmio_access[i].hwdom_access && !is_hardware_domain(d) )
+            continue;
+
+        /* Unlimited access is represented by a zero mask.  */
+        ASSERT( pm_mmio_access[i].mask != 0xFFFFFFFF );
+
+        r = domain_has_node_access(d, pm_mmio_access[i].node);
+        if ( r ) {
+            /* We've got access to this reg (or parts of it).  */
+            ret = true;
+            /* Masking only applies to writes, so reads can exit here.  */
+            if ( !write )
+                break;
+
+            /* Permit write access to selected bits.  */
+            prot_mask |= pm_mmio_access[i].mask ? pm_mmio_access[i].mask : ~0;
+            printk("match: mask=%x prot_mask=%x\n",
+                   pm_mmio_access[i].mask, prot_mask);
+            if ( prot_mask == 0xFFFFFFFF )
+                break; /* Full access, we're done.  */
+        } else {
+            if ( !pm_mmio_access[i].mask ) {
+                /*
+                 * The entire reg is tied to a device that we don't have
+                 * access to. No point in continuing.
+                 */
+                return false;
+            }
+        }
+    }
+
+    /* Masking only applies to writes.  */
+    if ( write )
+        *mask &= prot_mask;
+    return ret;
+}
+
+bool zynqmp_eemi_mediate(register_t fid,
+                         register_t a0,
+                         register_t a1,
+                         register_t a2,
+                         register_t a3,
+                         register_t a4,
+                         register_t a5,
+                         register_t *ret)
+{
+    bool is_mmio_write = false;
+    unsigned int pm_fn = fid & 0xFFFF;
+    uint32_t pm_arg[4];
+
+    /* Decode pm args.  */
+    pm_arg[0] = a0;
+    pm_arg[1] = a0 >> 32;
+    pm_arg[2] = a1;
+    pm_arg[3] = a1 >> 32;
+
+    ASSERT(ret);
+
+    switch (pm_fn)
+    {
+    /*
+     * We can't allow CPUs to suspend without Xen knowing about it.
+     * We accept but ignore the request and wait for the guest to issue
+     * a WFI which Xen will trap and act accordingly upon.
+     */
+    case PM_SELF_SUSPEND:
+        ret[0] = PM_RET_SUCCESS;
+        goto done;
+
+    case PM_GET_NODE_STATUS:
+    /* API for PUs.  */
+    case PM_REQ_SUSPEND:
+    case PM_FORCE_POWERDOWN:
+    case PM_ABORT_SUSPEND:
+    case PM_REQ_WAKEUP:
+    case PM_SET_WAKEUP_SOURCE:
+    /* API for slaves.  */
+    case PM_REQ_NODE:
+    case PM_RELEASE_NODE:
+    case PM_SET_REQUIREMENT:
+    case PM_SET_MAX_LATENCY:
+        if ( !domain_has_node_access(current->domain, pm_arg[0]) ) {
+            printk("zynqmp-pm: fn=%d No access to node %d\n", pm_fn, pm_arg[0]);
+            ret[0] = PM_RET_ERROR_ACCESS;
+            goto done;
+        }
+        goto forward_to_fw;
+
+    case PM_RESET_ASSERT:
+    case PM_RESET_GET_STATUS:
+        if ( !domain_has_reset_access(current->domain, pm_arg[0]) ) {
+            printk("zynqmp-pm: fn=%d No access to reset %d\n", pm_fn, pm_arg[0]);
+            ret[0] = PM_RET_ERROR_ACCESS;
+            goto done;
+        }
+        goto forward_to_fw;
+
+    /* These calls are safe and always allowed.  */
+    case ZYNQMP_SIP_SVC_CALL_COUNT:
+    case ZYNQMP_SIP_SVC_UID:
+    case ZYNQMP_SIP_SVC_VERSION:
+    case PM_GET_API_VERSION:
+    case PM_GET_CHIPID:
+        goto forward_to_fw;
+
+    /* Mediated MMIO access.  */
+    case PM_MMIO_WRITE:
+        is_mmio_write = true;
+    /* Fallthrough.  */
+    case PM_MMIO_READ:
+        if ( !domain_mediate_mmio_access(current->domain,
+                                         is_mmio_write,
+                                         pm_arg[0], &pm_arg[1]) ) {
+            printk("eemi: fn=%d No access to MMIO %s %x\n",
+                   pm_fn, is_mmio_write ? "write" : "read", pm_arg[0]);
+            ret[0] = PM_RET_ERROR_ACCESS;
+            goto done;
+        }
+        goto forward_to_fw;
+
+    /* Exclusive to Dom0.  */
+    case PM_INIT:
+    case PM_SET_CONFIGURATION:
+    case PM_FPGA_LOAD:
+    case PM_FPGA_GET_STATUS:
+        if ( !is_hardware_domain(current->domain) ) {
+            printk("eemi: fn=%d No access", pm_fn);
+            ret[0] = PM_RET_ERROR_ACCESS;
+            goto done;
+        }
+        goto forward_to_fw;
+
+    /* These calls are never allowed.  */
+    case PM_SYSTEM_SHUTDOWN:
+        ret[0] = PM_RET_ERROR_ACCESS;
+        goto done;
+
+    default:
+        printk("zynqmp-pm: Unhandled PM Call: %d\n", (u32)fid);
+        return false;
+    }
+
+forward_to_fw:
+    /* Re-encode pm args.  */
+    a0 = ((uint64_t)pm_arg[1] << 32) | pm_arg[0];
+    a1 = ((uint64_t)pm_arg[3] << 32) | pm_arg[2];
+    call_smcc64(fid, a0, a1, a2, a3, a4, a5, ret);
+done:
+    return true;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/platforms/xilinx-zynqmp.c b/xen/arch/arm/platforms/xilinx-zynqmp.c
index 2adee91..d826282 100644
--- a/xen/arch/arm/platforms/xilinx-zynqmp.c
+++ b/xen/arch/arm/platforms/xilinx-zynqmp.c
@@ -18,6 +18,7 @@
  */
 
 #include <asm/platform.h>
+#include <asm/platforms/xilinx-zynqmp-eemi.h>
 
 static const char * const zynqmp_dt_compat[] __initconst =
 {
@@ -32,8 +33,25 @@ static const struct dt_device_match zynqmp_blacklist_dev[] __initconst =
     { /* sentinel */ },
 };
 
+bool zynqmp_hvc(struct cpu_user_regs *regs)
+{
+    register_t ret[4] = { 0 };
+
+    if ( !zynqmp_eemi_mediate(regs->x0, regs->x1, regs->x2, regs->x3,
+                              regs->x4, regs->x5, regs->x6, ret) )
+        return false;
+
+    /* Transfer return values into guest registers.  */
+    regs->x0 = ret[0];
+    regs->x1 = ret[1];
+    regs->x2 = ret[2];
+    regs->x3 = ret[3];
+    return true;
+}
+
 PLATFORM_START(xgene_storm, "Xilinx ZynqMP")
     .compatible = zynqmp_dt_compat,
+    .hvc = zynqmp_hvc,
     .blacklist_dev = zynqmp_blacklist_dev,
 PLATFORM_END
 
diff --git a/xen/include/asm-arm/platforms/xilinx-zynqmp-eemi.h b/xen/include/asm-arm/platforms/xilinx-zynqmp-eemi.h
new file mode 100644
index 0000000..774593c
--- /dev/null
+++ b/xen/include/asm-arm/platforms/xilinx-zynqmp-eemi.h
@@ -0,0 +1,337 @@
+/* Xen specifics:  */
+/* Main PM Mediator entry.  */
+bool zynqmp_eemi_mediate(register_t fid,
+                         register_t a0,
+                         register_t a1,
+                         register_t a2,
+                         register_t a3,
+                         register_t a4,
+                         register_t a5,
+                         register_t *ret);
+
+/* Service calls.  */
+#define SVC_MASK             0x3F000000
+#define SVC_SIP              0x02000000    /* SoC Implementation Specific.  */
+#define PM_SIP_SVC           0xC2000000
+
+/* SMC function IDs for SiP Service queries */
+#define ZYNQMP_SIP_SVC_CALL_COUNT       0xff00
+#define ZYNQMP_SIP_SVC_UID              0xff01
+#define ZYNQMP_SIP_SVC_VERSION          0xff03
+
+/* Generic PM defs:  */
+/*
+ * Version number is a 32bit value, like:
+ * (PM_VERSION_MAJOR << 16) | PM_VERSION_MINOR
+ */
+#define PM_VERSION_MAJOR	0
+#define PM_VERSION_MINOR	2
+
+#define PM_VERSION	((PM_VERSION_MAJOR << 16) | PM_VERSION_MINOR)
+
+/* Capabilities for RAM */
+#define PM_CAP_ACCESS	0x1U
+#define PM_CAP_CONTEXT	0x2U
+
+#define MAX_LATENCY	(~0U)
+#define MAX_QOS		100U
+
+/* State arguments of the self suspend */
+#define PM_STATE_CPU_IDLE		0x0U
+#define PM_STATE_SUSPEND_TO_RAM		0xFU
+
+enum pm_api_id {
+	/* Miscellaneous API functions: */
+	PM_GET_API_VERSION = 1, /* Do not change or move */
+	PM_SET_CONFIGURATION,
+	PM_GET_NODE_STATUS,
+	PM_GET_OP_CHARACTERISTIC,
+	PM_REGISTER_NOTIFIER,
+	/* API for suspending of PUs: */
+	PM_REQ_SUSPEND,
+	PM_SELF_SUSPEND,
+	PM_FORCE_POWERDOWN,
+	PM_ABORT_SUSPEND,
+	PM_REQ_WAKEUP,
+	PM_SET_WAKEUP_SOURCE,
+	PM_SYSTEM_SHUTDOWN,
+	/* API for managing PM slaves: */
+	PM_REQ_NODE,
+	PM_RELEASE_NODE,
+	PM_SET_REQUIREMENT,
+	PM_SET_MAX_LATENCY,
+	/* Direct control API functions: */
+	PM_RESET_ASSERT,
+	PM_RESET_GET_STATUS,
+	PM_MMIO_WRITE,
+	PM_MMIO_READ,
+	PM_INIT,
+	PM_FPGA_LOAD,
+	PM_FPGA_GET_STATUS,
+	PM_GET_CHIPID,
+	PM_API_MAX
+};
+
+enum pm_node_id {
+	NODE_UNKNOWN = 0,
+	NODE_APU,
+	NODE_APU_0,
+	NODE_APU_1,
+	NODE_APU_2,
+	NODE_APU_3,
+	NODE_RPU,
+	NODE_RPU_0,
+	NODE_RPU_1,
+	NODE_PL,
+	NODE_FPD,
+	NODE_OCM_BANK_0,
+	NODE_OCM_BANK_1,
+	NODE_OCM_BANK_2,
+	NODE_OCM_BANK_3,
+	NODE_TCM_0_A,
+	NODE_TCM_0_B,
+	NODE_TCM_1_A,
+	NODE_TCM_1_B,
+	NODE_L2,
+	NODE_GPU_PP_0,
+	NODE_GPU_PP_1,
+	NODE_USB_0,
+	NODE_USB_1,
+	NODE_TTC_0,
+	NODE_TTC_1,
+	NODE_TTC_2,
+	NODE_TTC_3,
+	NODE_SATA,
+	NODE_ETH_0,
+	NODE_ETH_1,
+	NODE_ETH_2,
+	NODE_ETH_3,
+	NODE_UART_0,
+	NODE_UART_1,
+	NODE_SPI_0,
+	NODE_SPI_1,
+	NODE_I2C_0,
+	NODE_I2C_1,
+	NODE_SD_0,
+	NODE_SD_1,
+	NODE_DP,
+	NODE_GDMA,
+	NODE_ADMA,
+	NODE_NAND,
+	NODE_QSPI,
+	NODE_GPIO,
+	NODE_CAN_0,
+	NODE_CAN_1,
+	NODE_AFI,
+	NODE_APLL,
+	NODE_VPLL,
+	NODE_DPLL,
+	NODE_RPLL,
+	NODE_IOPLL,
+	NODE_DDR,
+	NODE_IPI_APU,
+	NODE_IPI_RPU_0,
+	NODE_GPU,
+	NODE_PCIE,
+	NODE_PCAP,
+	NODE_RTC,
+	NODE_MAX
+};
+
+enum pm_request_ack {
+	REQ_ACK_NO = 1,
+	REQ_ACK_BLOCKING,
+	REQ_ACK_NON_BLOCKING,
+};
+
+enum pm_abort_reason {
+	ABORT_REASON_WKUP_EVENT = 100,
+	ABORT_REASON_PU_BUSY,
+	ABORT_REASON_NO_PWRDN,
+	ABORT_REASON_UNKNOWN,
+};
+
+enum pm_suspend_reason {
+	SUSPEND_REASON_PU_REQ = 201,
+	SUSPEND_REASON_ALERT,
+	SUSPEND_REASON_SYS_SHUTDOWN,
+};
+
+enum pm_ram_state {
+	PM_RAM_STATE_OFF = 1,
+	PM_RAM_STATE_RETENTION,
+	PM_RAM_STATE_ON,
+};
+
+enum pm_opchar_type {
+	PM_OPCHAR_TYPE_POWER = 1,
+	PM_OPCHAR_TYPE_TEMP,
+	PM_OPCHAR_TYPE_LATENCY,
+};
+
+/**
+ * @PM_RET_SUCCESS:		success
+ * @PM_RET_ERROR_ARGS:		illegal arguments provided
+ * @PM_RET_ERROR_ACCESS:	access rights violation
+ * @PM_RET_ERROR_TIMEOUT:	timeout in communication with PMU
+ * @PM_RET_ERROR_NOTSUPPORTED:	feature not supported
+ * @PM_RET_ERROR_PROC:		node is not a processor node
+ * @PM_RET_ERROR_API_ID:	illegal API ID
+ * @PM_RET_ERROR_OTHER:		other error
+ */
+enum pm_ret_status {
+	PM_RET_SUCCESS,
+	PM_RET_ERROR_ARGS,
+	PM_RET_ERROR_ACCESS,
+	PM_RET_ERROR_TIMEOUT,
+	PM_RET_ERROR_NOTSUPPORTED,
+	PM_RET_ERROR_PROC,
+	PM_RET_ERROR_API_ID,
+	PM_RET_ERROR_FAILURE,
+	PM_RET_ERROR_COMMUNIC,
+	PM_RET_ERROR_DOUBLEREQ,
+	PM_RET_ERROR_OTHER,
+};
+
+/**
+ * @PM_INITIAL_BOOT:	boot is a fresh system startup
+ * @PM_RESUME:		boot is a resume
+ * @PM_BOOT_ERROR:	error, boot cause cannot be identified
+ */
+enum pm_boot_status {
+	PM_INITIAL_BOOT,
+	PM_RESUME,
+	PM_BOOT_ERROR,
+};
+
+enum pm_shutdown_type {
+	PMF_SHUTDOWN_TYPE_SHUTDOWN,
+	PMF_SHUTDOWN_TYPE_RESET,
+};
+
+enum pm_shutdown_subtype {
+	PMF_SHUTDOWN_SUBTYPE_SUBSYSTEM,
+	PMF_SHUTDOWN_SUBTYPE_PS_ONLY,
+	PMF_SHUTDOWN_SUBTYPE_SYSTEM,
+};
+
+enum pm_reset {
+	PM_RESET_START = 999,
+	PM_RESET_PCIE_CFG,
+	PM_RESET_PCIE_BRIDGE,
+	PM_RESET_PCIE_CTRL,
+	PM_RESET_DP,
+	PM_RESET_SWDT_CRF,
+	PM_RESET_AFI_FM5,
+	PM_RESET_AFI_FM4,
+	PM_RESET_AFI_FM3,
+	PM_RESET_AFI_FM2,
+	PM_RESET_AFI_FM1,
+	PM_RESET_AFI_FM0,
+	PM_RESET_GDMA,
+	PM_RESET_GPU_PP1,
+	PM_RESET_GPU_PP0,
+	PM_RESET_GPU,
+	PM_RESET_GT,
+	PM_RESET_SATA,
+	PM_RESET_ACPU3_PWRON,
+	PM_RESET_ACPU2_PWRON,
+	PM_RESET_ACPU1_PWRON,
+	PM_RESET_ACPU0_PWRON,
+	PM_RESET_APU_L2,
+	PM_RESET_ACPU3,
+	PM_RESET_ACPU2,
+	PM_RESET_ACPU1,
+	PM_RESET_ACPU0,
+	PM_RESET_DDR,
+	PM_RESET_APM_FPD,
+	PM_RESET_SOFT,
+	PM_RESET_GEM0,
+	PM_RESET_GEM1,
+	PM_RESET_GEM2,
+	PM_RESET_GEM3,
+	PM_RESET_QSPI,
+	PM_RESET_UART0,
+	PM_RESET_UART1,
+	PM_RESET_SPI0,
+	PM_RESET_SPI1,
+	PM_RESET_SDIO0,
+	PM_RESET_SDIO1,
+	PM_RESET_CAN0,
+	PM_RESET_CAN1,
+	PM_RESET_I2C0,
+	PM_RESET_I2C1,
+	PM_RESET_TTC0,
+	PM_RESET_TTC1,
+	PM_RESET_TTC2,
+	PM_RESET_TTC3,
+	PM_RESET_SWDT_CRL,
+	PM_RESET_NAND,
+	PM_RESET_ADMA,
+	PM_RESET_GPIO,
+	PM_RESET_IOU_CC,
+	PM_RESET_TIMESTAMP,
+	PM_RESET_RPU_R50,
+	PM_RESET_RPU_R51,
+	PM_RESET_RPU_AMBA,
+	PM_RESET_OCM,
+	PM_RESET_RPU_PGE,
+	PM_RESET_USB0_CORERESET,
+	PM_RESET_USB1_CORERESET,
+	PM_RESET_USB0_HIBERRESET,
+	PM_RESET_USB1_HIBERRESET,
+	PM_RESET_USB0_APB,
+	PM_RESET_USB1_APB,
+	PM_RESET_IPI,
+	PM_RESET_APM_LPD,
+	PM_RESET_RTC,
+	PM_RESET_SYSMON,
+	PM_RESET_AFI_FM6,
+	PM_RESET_LPD_SWDT,
+	PM_RESET_FPD,
+	PM_RESET_RPU_DBG1,
+	PM_RESET_RPU_DBG0,
+	PM_RESET_DBG_LPD,
+	PM_RESET_DBG_FPD,
+	PM_RESET_APLL,
+	PM_RESET_DPLL,
+	PM_RESET_VPLL,
+	PM_RESET_IOPLL,
+	PM_RESET_RPLL,
+	PM_RESET_GPO3_PL_0,
+	PM_RESET_GPO3_PL_1,
+	PM_RESET_GPO3_PL_2,
+	PM_RESET_GPO3_PL_3,
+	PM_RESET_GPO3_PL_4,
+	PM_RESET_GPO3_PL_5,
+	PM_RESET_GPO3_PL_6,
+	PM_RESET_GPO3_PL_7,
+	PM_RESET_GPO3_PL_8,
+	PM_RESET_GPO3_PL_9,
+	PM_RESET_GPO3_PL_10,
+	PM_RESET_GPO3_PL_11,
+	PM_RESET_GPO3_PL_12,
+	PM_RESET_GPO3_PL_13,
+	PM_RESET_GPO3_PL_14,
+	PM_RESET_GPO3_PL_15,
+	PM_RESET_GPO3_PL_16,
+	PM_RESET_GPO3_PL_17,
+	PM_RESET_GPO3_PL_18,
+	PM_RESET_GPO3_PL_19,
+	PM_RESET_GPO3_PL_20,
+	PM_RESET_GPO3_PL_21,
+	PM_RESET_GPO3_PL_22,
+	PM_RESET_GPO3_PL_23,
+	PM_RESET_GPO3_PL_24,
+	PM_RESET_GPO3_PL_25,
+	PM_RESET_GPO3_PL_26,
+	PM_RESET_GPO3_PL_27,
+	PM_RESET_GPO3_PL_28,
+	PM_RESET_GPO3_PL_29,
+	PM_RESET_GPO3_PL_30,
+	PM_RESET_GPO3_PL_31,
+	PM_RESET_RPU_LS,
+	PM_RESET_PS_ONLY,
+	PM_RESET_PL,
+	PM_RESET_END
+};
diff --git a/xen/include/asm-arm/platforms/xilinx-zynqmp-mm.h b/xen/include/asm-arm/platforms/xilinx-zynqmp-mm.h
new file mode 100644
index 0000000..4fb1695
--- /dev/null
+++ b/xen/include/asm-arm/platforms/xilinx-zynqmp-mm.h
@@ -0,0 +1,284 @@
+/*
+ * Merge of various auto-generated memory map and register
+ * definition files.
+ */
+
+/* Selected set of memory-map definitions:  */
+#define MM_IOU_S	0xff000000
+#define MM_IPI	0xff300000
+#define MM_LPD_SLCR	0xff410000
+#define MM_LPD_SLCR_SECURE	0xff4b0000
+#define MM_CRL_APB	0xff5e0000
+#define MM_OCM	0xff960000
+#define MM_LPD_XPPU	0xff980000
+#define MM_RPU	0xff9a0000
+#define MM_AFIFM6	0xff9b0000
+#define MM_LPD_XPPU_SINK	0xff9c0000
+#define MM_USB3_0	0xff9d0000
+#define MM_USB3_1	0xff9e0000
+#define MM_APM_INTC_OCM	0xffa00000
+#define MM_APM_LPD_FPD	0xffa10000
+#define MM_AMS_CTRL	0xffa50000
+#define MM_AMS_PS_SYSMON	0xffa50800
+#define MM_AMS_PL_SYSMON	0xffa50c00
+#define MM_RTC	0xffa60000
+#define MM_OCM_XMPU_CFG	0xffa70000
+#define MM_ADMA_CH0	0xffa80000
+#define MM_ADMA_CH1	0xffa90000
+#define MM_ADMA_CH2	0xffaa0000
+#define MM_ADMA_CH3	0xffab0000
+#define MM_ADMA_CH4	0xffac0000
+#define MM_ADMA_CH5	0xffad0000
+#define MM_ADMA_CH6	0xffae0000
+
+#define MM_IOU_GPV	0xfe0fffff
+#define MM_LPD_GPV	0xfe1fffff
+#define MM_USB3_0_XHCI	0xfe2fffff
+#define MM_USB3_1_XHCI	0xfe3fffff
+#define MM_CORESIGHT_SOC_ROM	0xfe80ffff
+#define MM_CORESIGHT_SOC_TSGEN	0xfe90ffff
+#define MM_CORESIGHT_SOC_FUNN_0	0xfe91ffff
+#define MM_CORESIGHT_SOC_FUNN_1	0xfe92ffff
+#define MM_CORESIGHT_SOC_FUNN_2	0xfe93ffff
+#define MM_CORESIGHT_SOC_ETF_1	0xfe94ffff
+#define MM_CORESIGHT_SOC_ETF_2	0xfe95ffff
+#define MM_CORESIGHT_SOC_REPLIC	0xfe96ffff
+#define MM_CORESIGHT_SOC_ETR	0xfe97ffff
+#define MM_CORESIGHT_SOC_TPIU	0xfe98ffff
+#define MM_CORESIGHT_SOC_CTI_0	0xfe99ffff
+#define MM_CORESIGHT_SOC_CTI_1	0xfe9affff
+#define MM_CORESIGHT_SOC_CTI_2	0xfe9bffff
+#define MM_CORESIGHT_SOC_STM	0xfe9cffff
+#define MM_CORESIGHT_SOC_FTM	0xfe9dffff
+#define MM_CORESIGHT_SOC_ATM_0	0xfe9effff
+#define MM_CORESIGHT_SOC_ATM_1	0xfe9fffff
+#define MM_CORESIGHT_R5_ROM	0xfebe0fff
+#define MM_CORESIGHT_R5_DBG_0	0xfebf0fff
+#define MM_CORESIGHT_R5_PMU_0	0xfebf1fff
+#define MM_CORESIGHT_R5_DBG_1	0xfebf2fff
+#define MM_CORESIGHT_R5_PMU_1	0xfebf3fff
+#define MM_CORESIGHT_R5_CTI_0	0xfebf8fff
+#define MM_CORESIGHT_R5_CTI_1	0xfebf9fff
+#define MM_CORESIGHT_R5_ETM_0	0xfebfcfff
+#define MM_CORESIGHT_R5_ETM_1	0xfebfdfff
+#define MM_CORESIGHT_A53_ROM	0xfec0ffff
+#define MM_CORESIGHT_A53_DBG_0	0xfec1ffff
+#define MM_CORESIGHT_A53_CTI_0	0xfec2ffff
+#define MM_CORESIGHT_A53_PMU_0	0xfec3ffff
+#define MM_CORESIGHT_A53_ETM_0	0xfec4ffff
+#define MM_CORESIGHT_A53_DBG_1	0xfed1ffff
+#define MM_CORESIGHT_A53_CTI_1	0xfed2ffff
+#define MM_CORESIGHT_A53_PMU_1	0xfed3ffff
+#define MM_CORESIGHT_A53_ETM_1	0xfed4ffff
+#define MM_CORESIGHT_A53_DBG_2	0xfee1ffff
+#define MM_CORESIGHT_A53_CTI_2	0xfee2ffff
+#define MM_CORESIGHT_A53_PMU_2	0xfee3ffff
+#define MM_CORESIGHT_A53_ETM_2	0xfee4ffff
+#define MM_CORESIGHT_A53_DBG_3	0xfef1ffff
+#define MM_CORESIGHT_A53_CTI_3	0xfef2ffff
+#define MM_CORESIGHT_A53_PMU_3	0xfef3ffff
+
+#define MM_DDRSS	0xfd000000
+#define MM_SATA_AHCI_HBA	0xfd0c0000
+#define MM_SATA_AHCI_VENDOR	0xfd0c00a0
+#define MM_SATA_AHCI_PORT0_CNTRL	0xfd0c0100
+#define MM_SATA_AHCI_PORT1_CNTRL	0xfd0c0180
+#define MM_AXIPCIE_MAIN	0xfd0e0000
+#define MM_AXIPCIE_INGRESS0	0xfd0e0800
+#define MM_AXIPCIE_INGRESS1	0xfd0e0820
+#define MM_AXIPCIE_INGRESS2	0xfd0e0840
+#define MM_AXIPCIE_INGRESS3	0xfd0e0860
+#define MM_AXIPCIE_INGRESS4	0xfd0e0880
+#define MM_AXIPCIE_INGRESS5	0xfd0e08a0
+#define MM_AXIPCIE_INGRESS6	0xfd0e08c0
+#define MM_AXIPCIE_INGRESS7	0xfd0e08e0
+#define MM_AXIPCIE_EGRESS0	0xfd0e0c00
+#define MM_AXIPCIE_EGRESS1	0xfd0e0c20
+#define MM_AXIPCIE_EGRESS2	0xfd0e0c40
+#define MM_AXIPCIE_EGRESS3	0xfd0e0c60
+#define MM_AXIPCIE_EGRESS4	0xfd0e0c80
+#define MM_AXIPCIE_EGRESS5	0xfd0e0ca0
+#define MM_AXIPCIE_EGRESS6	0xfd0e0cc0
+#define MM_AXIPCIE_EGRESS7	0xfd0e0ce0
+#define MM_AXIPCIE_DMA0	0xfd0f0000
+#define MM_AXIPCIE_DMA1	0xfd0f0080
+#define MM_AXIPCIE_DMA2	0xfd0f0100
+#define MM_AXIPCIE_DMA3	0xfd0f0180
+#define MM_AXIPCIE_MSIX_TABLE	0xfd0f1000
+#define MM_AXIPCIE_MSIX_PBA	0xfd0f2000
+#define MM_CRF_APB	0xfd1a0000
+#define MM_AFIFM0	0xfd360000
+#define MM_AFIFM1	0xfd370000
+#define MM_AFIFM2	0xfd380000
+#define MM_AFIFM3	0xfd390000
+#define MM_AFIFM4	0xfd3a0000
+#define MM_AFIFM5	0xfd3b0000
+#define MM_SIOU	0xfd3d0000
+#define MM_SERDES	0xfd400000
+#define MM_PCIE_ATTRIB	0xfd480000
+#define MM_APM_CCI_INTC	0xfd490000
+#define MM_DP	0xfd4a0000
+#define MM_GPU	0xfd4b0000
+#define MM_DPDMA	0xfd4c0000
+#define MM_WDT	0xfd4d0000
+#define MM_FPD_XMPU_SINK	0xfd4f0000
+#define MM_GDMA_CH0	0xfd500000
+#define MM_GDMA_CH1	0xfd510000
+#define MM_GDMA_CH2	0xfd520000
+#define MM_GDMA_CH3	0xfd530000
+#define MM_GDMA_CH4	0xfd540000
+#define MM_GDMA_CH5	0xfd550000
+#define MM_GDMA_CH6	0xfd560000
+#define MM_GDMA_CH7	0xfd570000
+#define MM_APU	0xfd5c0000
+#define MM_FPD_XMPU_CFG	0xfd5d0000
+#define MM_CCI_REG	0xfd5e0000
+#define MM_SMMU_REG	0xfd5f0000
+#define MM_FPD_SLCR	0xfd610000
+#define MM_FPD_SLCR_SECURE	0xfd690000
+#define MM_CCI_GPV	0xfd6e0000
+#define MM_FPD_GPV	0xfd700000
+
+#define MM_QSPI_Linear_Address	0xc0000000
+#define MM_UART0	0xff000000
+#define MM_UART1	0xff010000
+#define MM_I2C0	0xff020000
+#define MM_I2C1	0xff030000
+#define MM_SPI0	0xff040000
+#define MM_SPI1	0xff050000
+#define MM_CAN0	0xff060000
+#define MM_CAN1	0xff070000
+#define MM_GPIO	0xff0a0000
+#define MM_GEM0	0xff0b0000
+#define MM_GEM1	0xff0c0000
+#define MM_GEM2	0xff0d0000
+#define MM_GEM3	0xff0e0000
+#define MM_QSPI	0xff0f0000
+#define MM_NAND	0xff100000
+#define MM_TTC0	0xff110000
+#define MM_TTC1	0xff120000
+#define MM_TTC2	0xff130000
+#define MM_TTC3	0xff140000
+#define MM_SWDT	0xff150000
+#define MM_SD0	0xff160000
+#define MM_SD1	0xff170000
+#define MM_IOU_SLCR	0xff180000
+#define MM_IOU_SECURE_SLCR	0xff240000
+#define MM_IOU_SCNTR	0xff250000
+
+#define MM_alg_vcu_enc_top	0xa0000000
+#define MM_alg_vcu_dec_top	0xa0020000
+
+#define MM_PMU_GLOBAL           0xffd80000
+#define MM_CSU                  0xffca0000
+
+/* Selected set of register definitions:  */
+#define R_CRF_APLL_CTRL           0x20
+#define R_CRF_ACPU_CTRL           0x60
+#define R_CRF_DP_VIDEO_REF_CTRL   0x70
+#define R_CRF_DP_STC_REF_CTRL     0x7c
+#define R_CRF_GPU_REF_CTRL        0x84
+#define R_CRF_SATA_REF_CTRL       0xa0
+#define R_CRF_PCIE_REF_CTRL       0xb4
+#define R_CRF_GDMA_REF_CTRL       0xb8
+#define R_CRF_DPDMA_REF_CTRL      0xbc
+
+#define R_CRL_IOPLL_CTRL          0x20
+#define R_CRL_IOPLL_CFG           0x24
+#define R_CRL_IOPLL_FRAC_CFG      0x28
+#define R_CRL_RPLL_CTRL           0x30
+#define R_CRL_RPLL_CFG            0x34
+#define R_CRL_RPLL_FRAC_CFG       0x38
+#define R_CRL_PLL_STATUS          0x40
+#define R_CRL_IOPLL_TO_FPD_CTRL   0x44
+#define R_CRL_RPLL_TO_FPD_CTRL    0x48
+#define R_CRL_USB3_DUAL_REF_CTRL  0x4c
+#define R_CRL_GEM0_REF_CTRL       0x50
+#define R_CRL_GEM1_REF_CTRL       0x54
+#define R_CRL_GEM2_REF_CTRL       0x58
+#define R_CRL_GEM3_REF_CTRL       0x5c
+#define R_CRL_USB0_BUS_REF_CTRL   0x60
+#define R_CRL_USB1_BUS_REF_CTRL   0x64
+#define R_CRL_QSPI_REF_CTRL       0x68
+#define R_CRL_SDIO0_REF_CTRL      0x6c
+#define R_CRL_SDIO1_REF_CTRL      0x70
+#define R_CRL_UART0_REF_CTRL      0x74
+#define R_CRL_UART1_REF_CTRL      0x78
+#define R_CRL_SPI0_REF_CTRL       0x7c
+#define R_CRL_SPI1_REF_CTRL       0x80
+#define R_CRL_CAN0_REF_CTRL       0x84
+#define R_CRL_CAN1_REF_CTRL       0x88
+#define R_CRL_CPU_R5_CTRL         0x90
+#define R_CRL_IOU_SWITCH_CTRL     0x9c
+#define R_CRL_CSU_PLL_CTRL        0xa0
+#define R_CRL_PCAP_CTRL           0xa4
+#define R_CRL_LPD_SWITCH_CTRL     0xa8
+#define R_CRL_LPD_LSBUS_CTRL      0xac
+#define R_CRL_DBG_LPD_CTRL        0xb0
+#define R_CRL_NAND_REF_CTRL       0xb4
+#define R_CRL_ADMA_REF_CTRL       0xb8
+#define R_CRL_PL0_REF_CTRL        0xc0
+#define R_CRL_PL1_REF_CTRL        0xc4
+#define R_CRL_PL2_REF_CTRL        0xc8
+#define R_CRL_PL3_REF_CTRL        0xcc
+#define R_CRL_PL0_THR_CTRL        0xd0
+#define R_CRL_PL0_THR_CNT         0xd4
+#define R_CRL_PL1_THR_CTRL        0xd8
+#define R_CRL_PL1_THR_CNT         0xdc
+#define R_CRL_PL2_THR_CTRL        0xe0
+#define R_CRL_PL2_THR_CNT         0xe4
+#define R_CRL_PL3_THR_CTRL        0xe8
+#define R_CRL_PL3_THR_CNT         0xfc
+#define R_CRL_GEM_TSU_REF_CTRL    0x100
+#define R_CRL_DLL_REF_CTRL        0x104
+#define R_CRL_AMS_REF_CTRL        0x108
+#define R_CRL_I2C0_REF_CTRL       0x120
+#define R_CRL_I2C1_REF_CTRL       0x124
+#define R_CRL_TIMESTAMP_REF_CTRL  0x128
+
+#define R_PMU_GLOBAL_GLOBAL_GEN_STORAGE0    0x30
+#define R_PMU_GLOBAL_PERS_GLOB_GEN_STORAGE7 0x6c
+
+#define R_PMU_GLOBAL_PWR_STATE              0x100
+
+#define R_CSU_IDCODE                        0x40
+
+#define R_IOU_SLCR_WDT_CLK_SEL            0x300
+#define R_IOU_SLCR_CAN_MIO_CTRL           0x304
+#define R_IOU_SLCR_GEM_CLK_CTRL           0x308
+#define R_IOU_SLCR_SDIO_CLK_CTRL          0x30c
+#define R_IOU_SLCR_CTRL_REG_SD	          0x310
+#define R_IOU_SLCR_SD_ITAPDLY	          0x314
+#define R_IOU_SLCR_SD_OTAPDLYSEL          0x318
+#define R_IOU_SLCR_SD_CONFIG_REG1         0x31c
+#define R_IOU_SLCR_SD_CONFIG_REG2         0x320
+#define R_IOU_SLCR_SD_CONFIG_REG3         0x324
+#define R_IOU_SLCR_SD_INITPRESET          0x328
+#define R_IOU_SLCR_SD_DSPPRESET	          0x32c
+#define R_IOU_SLCR_SD_HSPDPRESET          0x330
+#define R_IOU_SLCR_SD_SDR12PRESET         0x334
+#define R_IOU_SLCR_SD_SDR25PRESET         0x338
+#define R_IOU_SLCR_SD_SDR50PRSET          0x33c
+#define R_IOU_SLCR_SD_SDR104PRST          0x340
+#define R_IOU_SLCR_SD_DDR50PRESET         0x344
+#define R_IOU_SLCR_SD_MAXCUR1P8           0x34c
+#define R_IOU_SLCR_SD_MAXCUR3P0           0x350
+#define R_IOU_SLCR_SD_MAXCUR3P3           0x354
+#define R_IOU_SLCR_SD_DLL_CTRL            0x358
+#define R_IOU_SLCR_SD_CDN_CTRL            0x35c
+#define R_IOU_SLCR_GEM_CTRL               0x360
+#define R_IOU_SLCR_IOU_TTC_APB_CLK        0x380
+#define R_IOU_SLCR_IOU_TAPDLY_BYPASS      0x390
+#define R_IOU_SLCR_IOU_COHERENT_CTRL      0x400
+#define R_IOU_SLCR_VIDEO_PSS_CLK_SEL      0x404
+#define R_IOU_SLCR_IOU_INTERCONNECT_ROUTE 0x408
+#define R_IOU_SLCR_IOU_RAM_GEM0           0x500
+#define R_IOU_SLCR_IOU_RAM_GEM1           0x504
+#define R_IOU_SLCR_IOU_RAM_GEM2           0x508
+#define R_IOU_SLCR_IOU_RAM_GEM3           0x50c
+#define R_IOU_SLCR_IOU_RAM_SD0            0x510
+#define R_IOU_SLCR_IOU_RAM_SD1            0x514
+#define R_IOU_SLCR_IOU_RAM_CAN0           0x518
+#define R_IOU_SLCR_IOU_RAM_CAN1           0x51c
+#define R_IOU_SLCR_IOU_RAM_LQSPI          0x520
+#define R_IOU_SLCR_IOU_RAM_NAND           0x524
