summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordavidcunado-arm <david.cunado@arm.com>2016-09-16 13:57:10 +0100
committerGitHub <noreply@github.com>2016-09-16 13:57:10 +0100
commita8de89c97461b7cc13a596db8771c30843b06405 (patch)
tree1e6760497bb823412be803361d69bc8ea212cd5e
parente69c1956cabfe4137c3efd646ce6575a2b972c58 (diff)
parent8787c0e00cfde59e81f6f89c84cef89d422cfabb (diff)
Merge pull request #709 from Xilinx/zynqmp-2016-09
xilinx: ZynqMP updates - new SIP calls for bitstream programming - new SIP call to discover the SOC silicon version - support the delay timer
-rw-r--r--plat/xilinx/zynqmp/aarch64/zynqmp_common.c27
-rw-r--r--plat/xilinx/zynqmp/bl31_zynqmp_setup.c20
-rw-r--r--plat/xilinx/zynqmp/include/platform_def.h9
-rw-r--r--plat/xilinx/zynqmp/plat_psci.c34
-rw-r--r--plat/xilinx/zynqmp/platform.mk3
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_api_sys.c50
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_api_sys.h6
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_client.c181
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_client.h2
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_defs.h14
-rw-r--r--plat/xilinx/zynqmp/pm_service/pm_svc_main.c16
-rw-r--r--plat/xilinx/zynqmp/zynqmp_def.h4
-rw-r--r--plat/xilinx/zynqmp/zynqmp_private.h1
13 files changed, 303 insertions, 64 deletions
diff --git a/plat/xilinx/zynqmp/aarch64/zynqmp_common.c b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c
index 1ba301de..60a16058 100644
--- a/plat/xilinx/zynqmp/aarch64/zynqmp_common.c
+++ b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c
@@ -29,6 +29,7 @@
*/
#include <debug.h>
+#include <generic_delay_timer.h>
#include <mmio.h>
#include <platform.h>
#include <xlat_tables.h>
@@ -89,6 +90,18 @@ static unsigned int zynqmp_get_system_timer_freq(void)
return 100000000;
}
+unsigned int zynqmp_get_silicon_id(void)
+{
+ uint32_t id;
+
+ id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET);
+
+ id &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK | ZYNQMP_CSU_IDCODE_SVD_MASK;
+ id >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT;
+
+ return id;
+}
+
#if LOG_LEVEL >= LOG_LEVEL_NOTICE
static const struct {
unsigned int id;
@@ -140,18 +153,6 @@ static const struct {
},
};
-static unsigned int zynqmp_get_silicon_id(void)
-{
- uint32_t id;
-
- id = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET);
-
- id &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK | ZYNQMP_CSU_IDCODE_SVD_MASK;
- id >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT;
-
- return id;
-}
-
static char *zynqmp_get_silicon_idcode_name(void)
{
unsigned int id;
@@ -289,6 +290,8 @@ void zynqmp_config_setup(void)
/* Program freq register in System counter and enable system counter. */
mmio_write_32(IOU_SCNTRS_BASEFREQ, zynqmp_get_system_timer_freq());
mmio_write_32(IOU_SCNTRS_CONTROL, IOU_SCNTRS_CONTROL_EN);
+
+ generic_delay_timer_init();
}
unsigned int plat_get_syscnt_freq2(void)
diff --git a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
index d878b86b..c05b094e 100644
--- a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
+++ b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c
@@ -118,11 +118,31 @@ void bl31_early_platform_setup(bl31_params_t *from_bl2,
NOTICE("BL31: Non secure code at 0x%lx\n", bl33_image_ep_info.pc);
}
+/* Enable the test setup */
+#ifndef ZYNQMP_TESTING
+static void zynqmp_testing_setup(void) { }
+#else
+static void zynqmp_testing_setup(void)
+{
+ uint32_t actlr_el3, actlr_el2;
+
+ /* Enable CPU ACTLR AND L2ACTLR RW access from non-secure world */
+ actlr_el3 = read_actlr_el3();
+ actlr_el2 = read_actlr_el2();
+
+ actlr_el3 |= ACTLR_EL3_L2ACTLR_BIT | ACTLR_EL3_CPUACTLR_BIT;
+ actlr_el2 |= ACTLR_EL3_L2ACTLR_BIT | ACTLR_EL3_CPUACTLR_BIT;
+ write_actlr_el3(actlr_el3);
+ write_actlr_el2(actlr_el2);
+}
+#endif
+
void bl31_platform_setup(void)
{
/* Initialize the gic cpu and distributor interfaces */
plat_arm_gic_driver_init();
plat_arm_gic_init();
+ zynqmp_testing_setup();
}
void bl31_plat_runtime_setup(void)
diff --git a/plat/xilinx/zynqmp/include/platform_def.h b/plat/xilinx/zynqmp/include/platform_def.h
index a35bd129..3c1a9e5c 100644
--- a/plat/xilinx/zynqmp/include/platform_def.h
+++ b/plat/xilinx/zynqmp/include/platform_def.h
@@ -56,8 +56,7 @@
* little space for growth.
*/
#ifndef ZYNQMP_ATF_MEM_BASE
-# define BL31_BASE 0xfffe5000
-# define BL31_PROGBITS_LIMIT 0xffffa000
+# define BL31_BASE 0xfffea000
# define BL31_LIMIT 0xffffffff
#else
# define BL31_BASE (ZYNQMP_ATF_MEM_BASE)
@@ -101,11 +100,7 @@
******************************************************************************/
#define ADDR_SPACE_SIZE (1ull << 32)
#define MAX_MMAP_REGIONS 7
-#if IMAGE_BL32
-# define MAX_XLAT_TABLES 5
-#else
-# define MAX_XLAT_TABLES 4
-#endif
+#define MAX_XLAT_TABLES 5
#define CACHE_WRITEBACK_SHIFT 6
#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
diff --git a/plat/xilinx/zynqmp/plat_psci.c b/plat/xilinx/zynqmp/plat_psci.c
index 56eb742a..55227ea9 100644
--- a/plat/xilinx/zynqmp/plat_psci.c
+++ b/plat/xilinx/zynqmp/plat_psci.c
@@ -147,7 +147,7 @@ static void zynqmp_pwr_domain_off(const psci_power_state_t *target_state)
* invoking CPU_on function, during which resume address will
* be set.
*/
- pm_self_suspend(proc->node_id, MAX_LATENCY, 0, 0);
+ pm_self_suspend(proc->node_id, MAX_LATENCY, PM_STATE_CPU_IDLE, 0);
}
static void zynqmp_nopmu_pwr_domain_suspend(const psci_power_state_t *target_state)
@@ -179,6 +179,7 @@ static void zynqmp_nopmu_pwr_domain_suspend(const psci_power_state_t *target_sta
static void zynqmp_pwr_domain_suspend(const psci_power_state_t *target_state)
{
+ unsigned int state;
unsigned int cpu_id = plat_my_core_pos();
const struct pm_proc *proc = pm_get_proc(cpu_id);
@@ -186,15 +187,14 @@ static void zynqmp_pwr_domain_suspend(const psci_power_state_t *target_state)
VERBOSE("%s: target_state->pwr_domain_state[%lu]=%x\n",
__func__, i, target_state->pwr_domain_state[i]);
+ state = target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE ?
+ PM_STATE_SUSPEND_TO_RAM : PM_STATE_CPU_IDLE;
+
/* Send request to PMU to suspend this core */
- pm_self_suspend(proc->node_id, MAX_LATENCY, 0, zynqmp_sec_entry);
+ pm_self_suspend(proc->node_id, MAX_LATENCY, state, zynqmp_sec_entry);
/* APU is to be turned off */
if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) {
- /* Power down L2 cache */
- pm_set_requirement(NODE_L2, 0, 0, REQ_ACK_NO);
- /* Send request for OCM retention state */
- set_ocm_retention();
/* disable coherency */
plat_arm_interconnect_exit_coherency();
}
@@ -242,6 +242,13 @@ static void zynqmp_pwr_domain_suspend_finish(const psci_power_state_t *target_st
/* enable coherency */
plat_arm_interconnect_enter_coherency();
+ /* APU was turned off */
+ if (target_state->pwr_domain_state[1] > PLAT_MAX_RET_STATE) {
+ plat_arm_gic_init();
+ } else {
+ gicv2_cpuif_enable();
+ gicv2_pcpu_distif_init();
+ }
}
/*******************************************************************************
@@ -308,7 +315,20 @@ int zynqmp_validate_power_state(unsigned int power_state,
{
VERBOSE("%s: power_state: 0x%x\n", __func__, power_state);
- /* FIXME: populate req_state */
+ int pstate = psci_get_pstate_type(power_state);
+
+ assert(req_state);
+
+ /* Sanity check the requested state */
+ if (pstate == PSTATE_TYPE_STANDBY)
+ req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_RET_STATE;
+ else
+ req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_OFF_STATE;
+
+ /* We expect the 'state id' to be zero */
+ if (psci_get_pstate_id(power_state))
+ return PSCI_E_INVALID_PARAMS;
+
return PSCI_E_SUCCESS;
}
diff --git a/plat/xilinx/zynqmp/platform.mk b/plat/xilinx/zynqmp/platform.mk
index 9bde5ff6..33c55a05 100644
--- a/plat/xilinx/zynqmp/platform.mk
+++ b/plat/xilinx/zynqmp/platform.mk
@@ -31,6 +31,7 @@ PROGRAMMABLE_RESET_ADDRESS := 1
PSCI_EXTENDED_STATE_ID := 1
A53_DISABLE_NON_TEMPORAL_HINT := 0
SEPARATE_CODE_AND_RODATA := 1
+RESET_TO_BL31 := 1
ifdef ZYNQMP_ATF_MEM_BASE
$(eval $(call add_define,ZYNQMP_ATF_MEM_BASE))
@@ -64,6 +65,8 @@ PLAT_INCLUDES := -Iinclude/plat/arm/common/ \
PLAT_BL_COMMON_SOURCES := lib/xlat_tables/xlat_tables_common.c \
lib/xlat_tables/aarch64/xlat_tables.c \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
drivers/arm/gic/common/gic_common.c \
drivers/arm/gic/v2/gicv2_main.c \
drivers/arm/gic/v2/gicv2_helpers.c \
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
index eac7801b..e859ee39 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
@@ -76,7 +76,7 @@
* pm_self_suspend() - PM call for processor to suspend itself
* @nid Node id of the processor or subsystem
* @latency Requested maximum wakeup latency (not supported)
- * @state Requested state (not supported)
+ * @state Requested state
* @address Resume address
*
* This is a blocking call, it will return only once PMU has responded.
@@ -97,7 +97,7 @@ enum pm_ret_status pm_self_suspend(enum pm_node_id nid,
* Do client specific suspend operations
* (e.g. set powerdown request bit)
*/
- pm_client_suspend(proc);
+ pm_client_suspend(proc, state);
/* Send request to the PMU */
PM_PACK_PAYLOAD6(payload, PM_SELF_SUSPEND, proc->node_id, latency,
state, address, (address >> 32));
@@ -476,7 +476,7 @@ enum pm_ret_status pm_mmio_write(uintptr_t address,
/* Send request to the PMU */
PM_PACK_PAYLOAD4(payload, PM_MMIO_WRITE, address, mask, value);
- return pm_ipi_send(primary_proc, payload);
+ return pm_ipi_send_sync(primary_proc, payload, NULL);
}
/**
@@ -497,3 +497,47 @@ enum pm_ret_status pm_mmio_read(uintptr_t address, unsigned int *value)
PM_PACK_PAYLOAD2(payload, PM_MMIO_READ, address);
return pm_ipi_send_sync(primary_proc, payload, value);
}
+
+/**
+ * pm_fpga_load() - Load the bitstream into the PL.
+ *
+ * This function provides access to the xilfpga library to load
+ * the Bit-stream into PL.
+ *
+ * address_low: lower 32-bit Linear memory space address
+ *
+ * address_high: higher 32-bit Linear memory space address
+ *
+ * size: Number of 32bit words
+ *
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_fpga_load(uint32_t address_low,
+ uint32_t address_high,
+ uint32_t size,
+ uint32_t flags)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD5(payload, PM_FPGA_LOAD, address_high, address_low,
+ size, flags);
+ return pm_ipi_send(primary_proc, payload);
+}
+
+/**
+ * pm_fpga_get_status() - Read value from fpga status register
+ * @value Value to read
+ *
+ * This function provides access to the xilfpga library to get
+ * the fpga status
+ * @return Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_fpga_get_status(unsigned int *value)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD1(payload, PM_FPGA_GET_STATUS);
+ return pm_ipi_send_sync(primary_proc, payload, value);
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
index 22bdb477..26d83e75 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
@@ -109,4 +109,10 @@ enum pm_ret_status pm_mmio_write(uintptr_t address,
unsigned int mask,
unsigned int value);
enum pm_ret_status pm_mmio_read(uintptr_t address, unsigned int *value);
+enum pm_ret_status pm_fpga_load(uint32_t address_high,
+ uint32_t address_low,
+ uint32_t size,
+ uint32_t flags);
+enum pm_ret_status pm_fpga_get_status(unsigned int *value);
+
#endif /* _PM_API_SYS_H_ */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_client.c b/plat/xilinx/zynqmp/pm_service/pm_client.c
index cf0d5f08..b77a1cf0 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_client.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_client.c
@@ -33,26 +33,25 @@
* for getting information about and changing state of the APU.
*/
+#include <assert.h>
#include <bakery_lock.h>
#include <gicv2.h>
+#include <gic_common.h>
#include <bl_common.h>
#include <mmio.h>
+#include <string.h>
#include <utils.h>
#include "pm_api_sys.h"
#include "pm_client.h"
#include "pm_ipi.h"
#include "../zynqmp_def.h"
-#define OCM_BANK_0 0xFFFC0000
-#define OCM_BANK_1 (OCM_BANK_0 + 0x10000)
-#define OCM_BANK_2 (OCM_BANK_1 + 0x10000)
-#define OCM_BANK_3 (OCM_BANK_2 + 0x10000)
-
+#define IRQ_MAX 84
+#define NUM_GICD_ISENABLER ((IRQ_MAX >> 5) + 1)
#define UNDEFINED_CPUID (~0)
+
DEFINE_BAKERY_LOCK(pm_client_secure_lock);
-/* Declaration of linker defined symbol */
-extern unsigned long __BL31_END__;
extern const struct pm_ipi apu_ipi;
/* Order in pm_procs_all array must match cpu ids */
@@ -79,36 +78,146 @@ static const struct pm_proc const pm_procs_all[] = {
},
};
+/* Interrupt to PM node ID map */
+static enum pm_node_id irq_node_map[IRQ_MAX + 1] = {
+ NODE_UNKNOWN,
+ NODE_UNKNOWN,
+ NODE_UNKNOWN,
+ NODE_UNKNOWN, /* 3 */
+ NODE_UNKNOWN,
+ NODE_UNKNOWN,
+ NODE_UNKNOWN,
+ NODE_UNKNOWN, /* 7 */
+ NODE_UNKNOWN,
+ NODE_UNKNOWN,
+ NODE_UNKNOWN,
+ NODE_UNKNOWN, /* 11 */
+ NODE_UNKNOWN,
+ NODE_UNKNOWN,
+ NODE_NAND,
+ NODE_QSPI, /* 15 */
+ NODE_GPIO,
+ NODE_I2C_0,
+ NODE_I2C_1,
+ NODE_SPI_0, /* 19 */
+ NODE_SPI_1,
+ NODE_UART_0,
+ NODE_UART_1,
+ NODE_CAN_0, /* 23 */
+ NODE_CAN_1,
+ NODE_UNKNOWN,
+ NODE_RTC,
+ NODE_RTC, /* 27 */
+ NODE_UNKNOWN,
+ NODE_UNKNOWN,
+ NODE_UNKNOWN,
+ NODE_UNKNOWN, /* 31 */
+ NODE_UNKNOWN,
+ NODE_UNKNOWN,
+ NODE_UNKNOWN,
+ NODE_UNKNOWN, /* 35, NODE_IPI_APU */
+ NODE_TTC_0,
+ NODE_TTC_0,
+ NODE_TTC_0,
+ NODE_TTC_1, /* 39 */
+ NODE_TTC_1,
+ NODE_TTC_1,
+ NODE_TTC_2,
+ NODE_TTC_2, /* 43 */
+ NODE_TTC_2,
+ NODE_TTC_3,
+ NODE_TTC_3,
+ NODE_TTC_3, /* 47 */
+ NODE_SD_0,
+ NODE_SD_1,
+ NODE_SD_0,
+ NODE_SD_1, /* 51 */
+ NODE_UNKNOWN,
+ NODE_UNKNOWN,
+ NODE_UNKNOWN,
+ NODE_UNKNOWN, /* 55 */
+ NODE_UNKNOWN,
+ NODE_ETH_0,
+ NODE_ETH_0,
+ NODE_ETH_1, /* 59 */
+ NODE_ETH_1,
+ NODE_ETH_2,
+ NODE_ETH_2,
+ NODE_ETH_3, /* 63 */
+ NODE_ETH_3,
+ NODE_USB_0,
+ NODE_USB_0,
+ NODE_USB_0, /* 67 */
+ NODE_USB_0,
+ NODE_USB_0,
+ NODE_USB_1,
+ NODE_USB_1, /* 71 */
+ NODE_USB_1,
+ NODE_USB_1,
+ NODE_USB_1,
+ NODE_USB_0, /* 75 */
+ NODE_USB_0,
+ NODE_ADMA,
+ NODE_ADMA,
+ NODE_ADMA, /* 79 */
+ NODE_ADMA,
+ NODE_ADMA,
+ NODE_ADMA,
+ NODE_ADMA, /* 83 */
+ NODE_ADMA,
+};
+
/**
- * set_ocm_retention() - Configure OCM memory banks for retention
- *
- * APU specific requirements for suspend action:
- * OCM has to enter retention state in order to preserve saved
- * context after suspend request. OCM banks are determined by
- * __BL31_END__ linker symbol.
+ * irq_to_pm_node - Get PM node ID corresponding to the interrupt number
+ * @irq: Interrupt number
*
- * Return: Returns status, either success or error+reason
+ * Return: PM node ID corresponding to the specified interrupt
+ */
+static enum pm_node_id irq_to_pm_node(unsigned int irq)
+{
+ assert(irq <= IRQ_MAX);
+ return irq_node_map[irq];
+}
+
+/**
+ * pm_client_set_wakeup_sources - Set all slaves with enabled interrupts as wake
+ * sources in the PMU firmware
*/
-enum pm_ret_status set_ocm_retention(void)
+static void pm_client_set_wakeup_sources(void)
{
- enum pm_ret_status ret;
-
- /* OCM_BANK_0 will always be occupied */
- ret = pm_set_requirement(NODE_OCM_BANK_0, PM_CAP_CONTEXT, 0,
- REQ_ACK_NO);
-
- /* Check for other OCM banks */
- if ((unsigned long)&__BL31_END__ >= OCM_BANK_1)
- ret = pm_set_requirement(NODE_OCM_BANK_1, PM_CAP_CONTEXT, 0,
- REQ_ACK_NO);
- if ((unsigned long)&__BL31_END__ >= OCM_BANK_2)
- ret = pm_set_requirement(NODE_OCM_BANK_2, PM_CAP_CONTEXT, 0,
- REQ_ACK_NO);
- if ((unsigned long)&__BL31_END__ >= OCM_BANK_3)
- ret = pm_set_requirement(NODE_OCM_BANK_3, PM_CAP_CONTEXT, 0,
- REQ_ACK_NO);
-
- return ret;
+ uint32_t reg_num;
+ uint8_t pm_wakeup_nodes_set[NODE_MAX];
+ uintptr_t isenabler1 = BASE_GICD_BASE + GICD_ISENABLER + 4;
+
+ memset(&pm_wakeup_nodes_set, 0, sizeof(pm_wakeup_nodes_set));
+
+ for (reg_num = 0; reg_num < NUM_GICD_ISENABLER; reg_num++) {
+ uint32_t base_irq = reg_num << ISENABLER_SHIFT;
+ uint32_t reg = mmio_read_32(isenabler1 + (reg_num << 2));
+
+ if (!reg)
+ continue;
+
+ while (reg) {
+ enum pm_node_id node;
+ uint32_t idx, ret, irq, lowest_set = reg & (-reg);
+
+ idx = __builtin_ctz(lowest_set);
+ irq = base_irq + idx;
+
+ if (irq > IRQ_MAX)
+ break;
+
+ node = irq_to_pm_node(irq);
+ reg &= ~lowest_set;
+
+ if ((node != NODE_UNKNOWN) &&
+ (!pm_wakeup_nodes_set[node])) {
+ ret = pm_set_wakeup_source(NODE_APU, node, 1);
+ pm_wakeup_nodes_set[node] = !ret;
+ }
+ }
+ }
}
/**
@@ -162,11 +271,15 @@ const struct pm_proc *primary_proc = &pm_procs_all[0];
*
* This function should contain any PU-specific actions
* required prior to sending suspend request to PMU
+ * Actions taken depend on the state system is suspending to.
*/
-void pm_client_suspend(const struct pm_proc *proc)
+void pm_client_suspend(const struct pm_proc *proc, unsigned int state)
{
bakery_lock_get(&pm_client_secure_lock);
+ if (state == PM_STATE_SUSPEND_TO_RAM)
+ pm_client_set_wakeup_sources();
+
/* Set powerdown request */
mmio_write_32(APU_PWRCTL, mmio_read_32(APU_PWRCTL) | proc->pwrdn_mask);
diff --git a/plat/xilinx/zynqmp/pm_service/pm_client.h b/plat/xilinx/zynqmp/pm_service/pm_client.h
index 9483b0d1..7f80d5b4 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_client.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_client.h
@@ -40,7 +40,7 @@
#include "pm_common.h"
/* Functions to be implemented by each PU */
-void pm_client_suspend(const struct pm_proc *proc);
+void pm_client_suspend(const struct pm_proc *proc, unsigned int state);
void pm_client_abort_suspend(void);
void pm_client_wakeup(const struct pm_proc *proc);
enum pm_ret_status set_ocm_retention(void);
diff --git a/plat/xilinx/zynqmp/pm_service/pm_defs.h b/plat/xilinx/zynqmp/pm_service/pm_defs.h
index adeec64b..aec335a5 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_defs.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_defs.h
@@ -53,6 +53,10 @@
#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 definitions
********************************************************************/
@@ -82,6 +86,10 @@ enum pm_api_id {
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
};
@@ -143,6 +151,12 @@ enum pm_node_id {
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 {
diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
index e3c25c31..9c08ffb9 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
@@ -228,6 +228,22 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
ret = pm_mmio_read(pm_arg[0], &value);
SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
}
+
+ case PM_FPGA_LOAD:
+ ret = pm_fpga_load(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3]);
+ SMC_RET1(handle, (uint64_t)ret);
+
+ case PM_FPGA_GET_STATUS:
+ {
+ uint32_t value;
+
+ ret = pm_fpga_get_status(&value);
+ SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+ }
+
+ case PM_GET_CHIPID:
+ SMC_RET1(handle, zynqmp_get_silicon_id());
+
default:
WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid);
SMC_RET1(handle, SMC_UNK);
diff --git a/plat/xilinx/zynqmp/zynqmp_def.h b/plat/xilinx/zynqmp/zynqmp_def.h
index 4bb332e0..65bc25f8 100644
--- a/plat/xilinx/zynqmp/zynqmp_def.h
+++ b/plat/xilinx/zynqmp/zynqmp_def.h
@@ -201,4 +201,8 @@
#define ZYNQMP_CSU_VERSION_OFFSET 0x44
+/* Access control register defines */
+#define ACTLR_EL3_L2ACTLR_BIT (1 << 6)
+#define ACTLR_EL3_CPUACTLR_BIT (1 << 0)
+
#endif /* __ZYNQMP_DEF_H__ */
diff --git a/plat/xilinx/zynqmp/zynqmp_private.h b/plat/xilinx/zynqmp/zynqmp_private.h
index ddef37b8..abcdebc3 100644
--- a/plat/xilinx/zynqmp/zynqmp_private.h
+++ b/plat/xilinx/zynqmp/zynqmp_private.h
@@ -39,6 +39,7 @@ void zynqmp_config_setup(void);
unsigned int zynqmp_get_uart_clk(void);
int zynqmp_is_pmu_up(void);
unsigned int zynqmp_get_bootmode(void);
+unsigned int zynqmp_get_silicon_id(void);
/* For FSBL handover */
void fsbl_atf_handover(entry_point_info_t *bl32_image_ep_info,