[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [RFC v2 5/6] xen/arm: zynqmp: Forward plaform specific firmware calls
On Tue, 7 Feb 2017, Edgar E. Iglesias wrote: > From: "Edgar E. Iglesias" <edgar.iglesias@xxxxxxxxxx> > > Implement an EEMI mediator and forward platform specific > firmware calls from guests to firmware. > > The EEMI mediator is responsible for implementing access > controls modifying or blocking calls that try to operate > on setup for devices that are not under the calling guest's > control. > > EEMI: > https://www.xilinx.com/support/documentation/user_guides/ug1200-eemi-api.pdf > > Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xxxxxxxxxx> > --- > xen/arch/arm/platforms/Makefile | 1 + > xen/arch/arm/platforms/xilinx-zynqmp-eemi.c | 794 > +++++++++++++++++++++ > xen/arch/arm/platforms/xilinx-zynqmp.c | 18 + > xen/include/asm-arm/platforms/xilinx-zynqmp-eemi.h | 337 +++++++++ > xen/include/asm-arm/platforms/xilinx-zynqmp-mm.h | 284 ++++++++ > 5 files changed, 1434 insertions(+) > create mode 100644 xen/arch/arm/platforms/xilinx-zynqmp-eemi.c > create mode 100644 xen/include/asm-arm/platforms/xilinx-zynqmp-eemi.h > create mode 100644 xen/include/asm-arm/platforms/xilinx-zynqmp-mm.h > > 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@xxxxxxxxxx> > + * > + * 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 ^ input > + * 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. */ If the hardware domain gets access regardless, I don't think we need this struct field, right? If fact, is_hardware_domain() is basically used as a blank check in Xen. I would remove hwdom_access, use is_hardware_domain() instead, and simply comment out any entries we don't want dom0 to have access to. For now that would be fine, but in the future we'll need a way to prevent dom0 access to something, if it has been assigned to another guest. > +}; > + > +/* > + * 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. */ ^ all > + [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. */ Please clarify the comment. What is this mask for exactly? > + enum pm_node_id node; > + bool hwdom_access; same here > + 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); I would write this function as: mfn = paddr_to_pfn(acl[idx].addr); if ( mfn != 0 ) return iomem_access_permitted(d, mfn, mfn); return is_hardware_domain(d); This way if addr is valid, then the domain need to have iomem access for it. Otherwise, it needs to be the the hardware domain. > +} > + > +/* 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; > + } Would it make sense to order the entries, so that if addr > pm_mmio_access[i].start, we can return immediately? > + 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 ); This is confusing: bits are set in the mask to allow write access, except in the case of 0, which actually means 0xFFFFFFFF. Did I get this right? If so, please choose one of the following: - mask bits are set to allow write access, no exception: instead of 0, we would have 0xFFFFFFFF to give full access - mask bits are set to deny write access: 0 means full access, 0xFFFFFFFF means no access. Then you just need to apply the mask inverted: ~pm_mmio_access[i].mask > + 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; Instead of break, I would just return ret; > + > + /* 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) I think you can declare them as uint64_t, given that the API actually requires 64bit registers. Also, I would probably just pass "struct cpu_user_regs *regs" as argument for simplicity. > +{ > + 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) code style > + { > + /* > + * 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; This is something in addition of the guest calling WFI, right? In that case we don't actually need to do anything to implement it, correct? > + 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: I cannot easily tell what is the permission check for these functions. To which pm_node_access entries do they correspond to? > + if ( !domain_has_node_access(current->domain, pm_arg[0]) ) { code style (bracket on newline) > + 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]) ) { code style > + 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]) ) { code style > + 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) ) { Code style. > + 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: */ Code style: no tabs please > + 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 > -- > 2.7.4 > _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |