diff --git a/plat/xilinx/zynqmp/aarch64/zynqmp_common.c b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c
index 1ba301ded132f888ae4d6a7bf11a8061d9ee6b94..60a16058f0ec09fdd2ce57a4c093656fca1578f4 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 d878b86b51191e7655032215f241b0cf2e394de9..c05b094eb21538a3e5b046b19ea8f73c3795b932 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 a35bd12939afa7368310e50398ee302242c5bede..3c1a9e5c8a20d9b831966f4d2a8d165ca109a572 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 56eb742acadbfdfa8afcfcf24271489ac84f7dcb..55227ea9442a29002710ef4b5a18a7c6041bd685 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 9bde5ff661c5a184bdc36ac3744f842be4e011e8..33c55a05ffa01779281dcd071680e595d5b589c2 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 eac7801b058d5d103c3fe92452700702b3c915da..e859ee39ee18afe9ea7c4fe06e332187be656809 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 22bdb4774f293d52d900507e245ae0c871472a48..26d83e75a8dfcaa70faf23584a029e3e3e84de31 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 cf0d5f08d3607cf83e6efae364c5a49186d983d4..b77a1cf0915dde97991e93a60f66d1d6893e24be 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 9483b0d1b87208799973c954de74e630bbd459de..7f80d5b425ad44f6f5982c63599f23a7d2399cb1 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 adeec64bedbdf17dd420d3bbe3cef9f17310f4c5..aec335a5e73f24d18ca6a5588944fd6b6a5f7873 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 e3c25c31cc301fe9dddf4dbf5ff6d3e22df14e51..9c08ffb9a34f029c4f21699cc82f500cd12b15b6 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 4bb332e0c2392ed13bc0f1248f5b8347f7ce9f26..65bc25f821f752a22d49ca3aba423d3350677820 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 ddef37b8f3730d57e659a90d3c622e13fed56fc2..abcdebc39fb59a935dc9b8eecb49a57d95818077 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,