Add support for Xilinx Zynq UltraScale+ MPSOC

The Xilinx Zynq UltraScale+ MPSOC containes a quad A53 cluster. This
patch adds the platform port for that SoC.

Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com>
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
new file mode 100644
index 0000000..2f2e2ed
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
@@ -0,0 +1,485 @@
+/*
+ * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * ZynqMP system level PM-API functions and communication with PMU via
+ * IPI interrupts
+ */
+
+#include <arch_helpers.h>
+#include <platform.h>
+#include "pm_client.h"
+#include "pm_common.h"
+#include "pm_api_sys.h"
+
+/**
+ * Assigning of argument values into array elements.
+ */
+#define PM_PACK_PAYLOAD1(pl, arg0) {	\
+	pl[0] = (uint32_t)(arg0);	\
+}
+
+#define PM_PACK_PAYLOAD2(pl, arg0, arg1) {	\
+	pl[1] = (uint32_t)(arg1);		\
+	PM_PACK_PAYLOAD1(pl, arg0);		\
+}
+
+#define PM_PACK_PAYLOAD3(pl, arg0, arg1, arg2) {	\
+	pl[2] = (uint32_t)(arg2);			\
+	PM_PACK_PAYLOAD2(pl, arg0, arg1);		\
+}
+
+#define PM_PACK_PAYLOAD4(pl, arg0, arg1, arg2, arg3) {	\
+	pl[3] = (uint32_t)(arg3);			\
+	PM_PACK_PAYLOAD3(pl, arg0, arg1, arg2);		\
+}
+
+#define PM_PACK_PAYLOAD5(pl, arg0, arg1, arg2, arg3, arg4) {	\
+	pl[4] = (uint32_t)(arg4);				\
+	PM_PACK_PAYLOAD4(pl, arg0, arg1, arg2, arg3);		\
+}
+
+#define PM_PACK_PAYLOAD6(pl, arg0, arg1, arg2, arg3, arg4, arg5) {	\
+	pl[5] = (uint32_t)(arg5);					\
+	PM_PACK_PAYLOAD5(pl, arg0, arg1, arg2, arg3, arg4);		\
+}
+
+/**
+ * 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)
+ * @address	Resume address
+ *
+ * This is a blocking call, it will return only once PMU has responded.
+ * On a wakeup, resume address will be automatically set by PMU.
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_self_suspend(enum pm_node_id nid,
+				   unsigned int latency,
+				   unsigned int state,
+				   uintptr_t address)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+	unsigned int cpuid = plat_my_core_pos();
+	const struct pm_proc *proc = pm_get_proc(cpuid);
+
+	/*
+	 * Do client specific suspend operations
+	 * (e.g. set powerdown request bit)
+	 */
+	pm_client_suspend(proc);
+	/* Send request to the PMU */
+	PM_PACK_PAYLOAD6(payload, PM_SELF_SUSPEND, proc->node_id, latency,
+			 state, address, (address >> 32));
+	return pm_ipi_send_sync(proc, payload, NULL);
+}
+
+/**
+ * pm_req_suspend() - PM call to request for another PU or subsystem to
+ *		      be suspended gracefully.
+ * @target	Node id of the targeted PU or subsystem
+ * @ack		Flag to specify whether acknowledge is requested
+ * @latency	Requested wakeup latency (not supported)
+ * @state	Requested state (not supported)
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_req_suspend(enum pm_node_id target,
+				  enum pm_request_ack ack,
+				  unsigned int latency, unsigned int state)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	/* Send request to the PMU */
+	PM_PACK_PAYLOAD5(payload, PM_REQ_SUSPEND, target, ack, latency, state);
+	if (ack == REQ_ACK_BLOCKING)
+		return pm_ipi_send_sync(primary_proc, payload, NULL);
+	else
+		return pm_ipi_send(primary_proc, payload);
+}
+
+/**
+ * pm_req_wakeup() - PM call for processor to wake up selected processor
+ *		     or subsystem
+ * @target	Node id of the processor or subsystem to wake up
+ * @ack		Flag to specify whether acknowledge requested
+ * @set_address	Resume address presence indicator
+ *				1 resume address specified, 0 otherwise
+ * @address	Resume address
+ *
+ * This API function is either used to power up another APU core for SMP
+ * (by PSCI) or to power up an entirely different PU or subsystem, such
+ * as RPU0, RPU, or PL_CORE_xx. Resume address for the target PU will be
+ * automatically set by PMU.
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_req_wakeup(enum pm_node_id target,
+				 unsigned int set_address,
+				 uintptr_t address,
+				 enum pm_request_ack ack)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+	uint64_t encoded_address;
+	const struct pm_proc *proc = pm_get_proc_by_node(target);
+
+	/* invoke APU-specific code for waking up another APU core */
+	pm_client_wakeup(proc);
+
+	/* encode set Address into 1st bit of address */
+	encoded_address = address;
+	encoded_address |= !!set_address;
+
+	/* Send request to the PMU to perform the wake of the PU */
+	PM_PACK_PAYLOAD5(payload, PM_REQ_WAKEUP, target, encoded_address,
+			 encoded_address >> 32, ack);
+
+	if (ack == REQ_ACK_BLOCKING)
+		return pm_ipi_send_sync(primary_proc, payload, NULL);
+	else
+		return pm_ipi_send(primary_proc, payload);
+}
+
+/**
+ * pm_force_powerdown() - PM call to request for another PU or subsystem to
+ *			  be powered down forcefully
+ * @target	Node id of the targeted PU or subsystem
+ * @ack		Flag to specify whether acknowledge is requested
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_force_powerdown(enum pm_node_id target,
+				      enum pm_request_ack ack)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	/* Send request to the PMU */
+	PM_PACK_PAYLOAD3(payload, PM_FORCE_POWERDOWN, target, ack);
+
+	if (ack == REQ_ACK_BLOCKING)
+		return pm_ipi_send_sync(primary_proc, payload, NULL);
+	else
+		return pm_ipi_send(primary_proc, payload);
+}
+
+/**
+ * pm_abort_suspend() - PM call to announce that a prior suspend request
+ *			is to be aborted.
+ * @reason	Reason for the abort
+ *
+ * Calling PU expects the PMU to abort the initiated suspend procedure.
+ * This is a non-blocking call without any acknowledge.
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	/*
+	 * Do client specific abort suspend operations
+	 * (e.g. enable interrupts and clear powerdown request bit)
+	 */
+	pm_client_abort_suspend();
+	/* Send request to the PMU */
+	/* TODO: allow passing the node ID of the affected CPU */
+	PM_PACK_PAYLOAD3(payload, PM_ABORT_SUSPEND, reason,
+			 primary_proc->node_id);
+	return pm_ipi_send(primary_proc, payload);
+}
+
+/**
+ * pm_set_wakeup_source() - PM call to specify the wakeup source while suspended
+ * @target	Node id of the targeted PU or subsystem
+ * @wkup_node	Node id of the wakeup peripheral
+ * @enable	Enable or disable the specified peripheral as wake source
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_set_wakeup_source(enum pm_node_id target,
+					enum pm_node_id wkup_node,
+					unsigned int enable)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	PM_PACK_PAYLOAD4(payload, PM_SET_WAKEUP_SOURCE, target, wkup_node,
+			 enable);
+	return pm_ipi_send(primary_proc, payload);
+}
+
+/**
+ * pm_system_shutdown() - PM call to request a system shutdown or restart
+ * @restart	Shutdown or restart? 0 for shutdown, 1 for restart
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_system_shutdown(unsigned int restart)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	PM_PACK_PAYLOAD2(payload, PM_SYSTEM_SHUTDOWN, restart);
+	return pm_ipi_send(primary_proc, payload);
+}
+
+/* APIs for managing PM slaves: */
+
+/**
+ * pm_req_node() - PM call to request a node with specific capabilities
+ * @nid		Node id of the slave
+ * @capabilities Requested capabilities of the slave
+ * @qos		Quality of service (not supported)
+ * @ack		Flag to specify whether acknowledge is requested
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_req_node(enum pm_node_id nid,
+			       unsigned int capabilities,
+			       unsigned int qos,
+			       enum pm_request_ack ack)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	PM_PACK_PAYLOAD5(payload, PM_REQ_NODE, nid, capabilities, qos, ack);
+
+	if (ack == REQ_ACK_BLOCKING)
+		return pm_ipi_send_sync(primary_proc, payload, NULL);
+	else
+		return pm_ipi_send(primary_proc, payload);
+}
+
+/**
+ * pm_set_requirement() - PM call to set requirement for PM slaves
+ * @nid		Node id of the slave
+ * @capabilities Requested capabilities of the slave
+ * @qos		Quality of service (not supported)
+ * @ack		Flag to specify whether acknowledge is requested
+ *
+ * This API function is to be used for slaves a PU already has requested
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_set_requirement(enum pm_node_id nid,
+				      unsigned int capabilities,
+				      unsigned int qos,
+				      enum pm_request_ack ack)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	PM_PACK_PAYLOAD5(payload, PM_SET_REQUIREMENT, nid, capabilities, qos,
+			 ack);
+
+	if (ack == REQ_ACK_BLOCKING)
+		return pm_ipi_send_sync(primary_proc, payload, NULL);
+	else
+		return pm_ipi_send(primary_proc, payload);
+}
+
+/**
+ * pm_release_node() - PM call to release a node
+ * @nid		Node id of the slave
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_release_node(enum pm_node_id nid)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	PM_PACK_PAYLOAD2(payload, PM_RELEASE_NODE, nid);
+	return pm_ipi_send(primary_proc, payload);
+}
+
+/**
+ * pm_set_max_latency() - PM call to set wakeup latency requirements
+ * @nid		Node id of the slave
+ * @latency	Requested maximum wakeup latency
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_set_max_latency(enum pm_node_id nid,
+				      unsigned int latency)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	PM_PACK_PAYLOAD3(payload, PM_SET_MAX_LATENCY, nid, latency);
+	return pm_ipi_send(primary_proc, payload);
+}
+
+/* Miscellaneous API functions */
+
+/**
+ * pm_get_api_version() - Get version number of PMU PM firmware
+ * @version	Returns 32-bit version number of PMU Power Management Firmware
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_get_api_version(unsigned int *version)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	/* Send request to the PMU */
+	PM_PACK_PAYLOAD1(payload, PM_GET_API_VERSION);
+	return pm_ipi_send_sync(primary_proc, payload, version);
+}
+
+/**
+ * pm_set_configuration() - PM call to set system configuration
+ * @phys_addr	Physical 32-bit address of data structure in memory
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_set_configuration(unsigned int phys_addr)
+{
+	return PM_RET_ERROR_NOTSUPPORTED;
+}
+
+/**
+ * pm_get_node_status() - PM call to request a node's current power state
+ * @nid		Node id of the slave
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_get_node_status(enum pm_node_id nid)
+{
+	/* TODO: Add power state argument!! */
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	PM_PACK_PAYLOAD2(payload, PM_GET_NODE_STATUS, nid);
+	return pm_ipi_send(primary_proc, payload);
+}
+
+/**
+ * pm_register_notifier() - Register the PU to be notified of PM events
+ * @nid		Node id of the slave
+ * @event	The event to be notified about
+ * @wake	Wake up on event
+ * @enable	Enable or disable the notifier
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_register_notifier(enum pm_node_id nid,
+					unsigned int event,
+					unsigned int wake,
+					unsigned int enable)
+{
+	return PM_RET_ERROR_NOTSUPPORTED;
+}
+
+/**
+ * pm_get_op_characteristic() - PM call to get a particular operating
+ *				characteristic of a node
+ * @nid	Node ID
+ * @type	Operating characterstic type to be returned
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_get_op_characteristic(enum pm_node_id nid,
+					    enum pm_opchar_type type)
+{
+	return PM_RET_ERROR_NOTSUPPORTED;
+}
+
+/* Direct-Control API functions */
+
+/**
+ * pm_reset_assert() - Assert reset
+ * @reset	Reset ID
+ * @assert	Assert (1) or de-assert (0)
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_reset_assert(unsigned int reset,
+				   unsigned int assert)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	/* Send request to the PMU */
+	PM_PACK_PAYLOAD3(payload, PM_RESET_ASSERT, reset, assert);
+	return pm_ipi_send(primary_proc, payload);
+}
+
+/**
+ * pm_reset_get_status() - Get current status of a reset line
+ * @reset	Reset ID
+ * @reset_status Returns current status of selected reset line
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_reset_get_status(unsigned int reset,
+				       unsigned int *reset_status)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	/* Send request to the PMU */
+	PM_PACK_PAYLOAD2(payload, PM_RESET_GET_STATUS, reset);
+	return pm_ipi_send_sync(primary_proc, payload, reset_status);
+}
+
+/**
+ * pm_mmio_write() - Perform write to protected mmio
+ * @address	Address to write to
+ * @mask	Mask to apply
+ * @value	Value to write
+ *
+ * This function provides access to PM-related control registers
+ * that may not be directly accessible by a particular PU.
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_mmio_write(uintptr_t address,
+				 unsigned int mask,
+				 unsigned int value)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	/* Send request to the PMU */
+	PM_PACK_PAYLOAD4(payload, PM_MMIO_WRITE, address, mask, value);
+	return pm_ipi_send(primary_proc, payload);
+}
+
+/**
+ * pm_mmio_read() - Read value from protected mmio
+ * @address	Address to write to
+ * @value	Value to write
+ *
+ * This function provides access to PM-related control registers
+ * that may not be directly accessible by a particular PU.
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_mmio_read(uintptr_t address, unsigned int *value)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+
+	/* Send request to the PMU */
+	PM_PACK_PAYLOAD2(payload, PM_MMIO_READ, address);
+	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
new file mode 100644
index 0000000..f0365cd
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _PM_API_SYS_H_
+#define _PM_API_SYS_H_
+
+#include <stdint.h>
+#include "pm_defs.h"
+
+/**********************************************************
+ * System-level API function declarations
+ **********************************************************/
+enum pm_ret_status pm_req_suspend(enum pm_node_id nid,
+				  enum pm_request_ack ack,
+				  unsigned int latency,
+				  unsigned int state);
+
+enum pm_ret_status pm_self_suspend(enum pm_node_id nid,
+				   unsigned int latency,
+				   unsigned int state,
+				   uintptr_t address);
+
+enum pm_ret_status pm_force_powerdown(enum pm_node_id nid,
+				      enum pm_request_ack ack);
+
+enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason);
+
+enum pm_ret_status pm_req_wakeup(enum pm_node_id nid,
+				 unsigned int set_address,
+				 uintptr_t address,
+				 enum pm_request_ack ack);
+
+enum pm_ret_status pm_set_wakeup_source(enum pm_node_id target,
+					enum pm_node_id wkup_node,
+					unsigned int enable);
+
+enum pm_ret_status pm_system_shutdown(unsigned int restart);
+
+enum pm_ret_status pm_init_suspend_cb(enum pm_suspend_reason reason,
+				      unsigned int latency,
+				      unsigned int state,
+				      unsigned int timeout);
+
+/* API functions for managing PM Slaves */
+enum pm_ret_status pm_req_node(enum pm_node_id nid,
+			       unsigned int capabilities,
+			       unsigned int qos,
+			       enum pm_request_ack ack);
+enum pm_ret_status pm_release_node(enum pm_node_id nid);
+
+enum pm_ret_status pm_set_requirement(enum pm_node_id nid,
+				      unsigned int capabilities,
+				      unsigned int qos,
+				      enum pm_request_ack ack);
+enum pm_ret_status pm_set_max_latency(enum pm_node_id nid,
+				      unsigned int latency);
+
+/* Miscellaneous API functions */
+enum pm_ret_status pm_get_api_version(unsigned int *version);
+enum pm_ret_status pm_set_configuration(unsigned int phys_addr);
+enum pm_ret_status pm_get_node_status(enum pm_node_id node);
+enum pm_ret_status pm_register_notifier(enum pm_node_id nid,
+					unsigned int event,
+					unsigned int wake,
+					unsigned int enable);
+enum pm_ret_status pm_get_op_characteristic(enum pm_node_id nid,
+					    enum pm_opchar_type type);
+enum pm_ret_status pm_acknowledge_cb(enum pm_node_id nid,
+				     enum pm_ret_status status,
+				     unsigned int oppoint);
+enum pm_ret_status pm_notify_cb(enum pm_node_id nid,
+				unsigned int event,
+				unsigned int oppoint);
+
+/* Direct-Control API functions */
+enum pm_ret_status pm_reset_assert(unsigned int reset_id,
+				   unsigned int assert);
+enum pm_ret_status pm_reset_get_status(unsigned int reset_id,
+				       unsigned int *reset_status);
+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);
+#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
new file mode 100644
index 0000000..eb986bc
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_client.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * APU specific definition of processors in the subsystem as well as functions
+ * for getting information about and changing state of the APU.
+ */
+
+#include <gicv2.h>
+#include <bl_common.h>
+#include <mmio.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 UNDEFINED_CPUID		(~0)
+
+/* 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 */
+static const struct pm_proc const pm_procs_all[] = {
+	{
+		.node_id = NODE_APU_0,
+		.pwrdn_mask = APU_0_PWRCTL_CPUPWRDWNREQ_MASK,
+		.ipi = &apu_ipi,
+	},
+	{
+		.node_id = NODE_APU_1,
+		.pwrdn_mask = APU_1_PWRCTL_CPUPWRDWNREQ_MASK,
+		.ipi = &apu_ipi,
+	},
+	{
+		.node_id = NODE_APU_2,
+		.pwrdn_mask = APU_2_PWRCTL_CPUPWRDWNREQ_MASK,
+		.ipi = &apu_ipi,
+	},
+	{
+		.node_id = NODE_APU_3,
+		.pwrdn_mask = APU_3_PWRCTL_CPUPWRDWNREQ_MASK,
+		.ipi = &apu_ipi,
+	},
+};
+
+/**
+ * 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.
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+enum pm_ret_status set_ocm_retention(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;
+}
+
+/**
+ * pm_get_proc() - returns pointer to the proc structure
+ * @cpuid:	id of the cpu whose proc struct pointer should be returned
+ *
+ * Return: pointer to a proc structure if proc is found, otherwise NULL
+ */
+const struct pm_proc *pm_get_proc(unsigned int cpuid)
+{
+	if (cpuid < ARRAY_SIZE(pm_procs_all))
+		return &pm_procs_all[cpuid];
+
+	return NULL;
+}
+
+/**
+ * pm_get_proc_by_node() - returns pointer to the proc structure
+ * @nid:	node id of the processor
+ *
+ * Return: pointer to a proc structure if proc is found, otherwise NULL
+ */
+const struct pm_proc *pm_get_proc_by_node(enum pm_node_id nid)
+{
+	for (size_t i = 0; i < ARRAY_SIZE(pm_procs_all); i++) {
+		if (nid == pm_procs_all[i].node_id)
+			return &pm_procs_all[i];
+	}
+	return NULL;
+}
+
+/**
+ * pm_get_cpuid() - get the local cpu ID for a global node ID
+ * @nid:	node id of the processor
+ *
+ * Return: the cpu ID (starting from 0) for the subsystem
+ */
+static unsigned int pm_get_cpuid(enum pm_node_id nid)
+{
+	for (size_t i = 0; i < ARRAY_SIZE(pm_procs_all); i++) {
+		if (pm_procs_all[i].node_id == nid)
+			return i;
+	}
+	return UNDEFINED_CPUID;
+}
+
+const struct pm_proc *primary_proc = &pm_procs_all[0];
+
+/**
+ * pm_client_suspend() - Client-specific suspend actions
+ *
+ * This function should contain any PU-specific actions
+ * required prior to sending suspend request to PMU
+ */
+void pm_client_suspend(const struct pm_proc *proc)
+{
+	/* Set powerdown request */
+	mmio_write_32(APU_PWRCTL, mmio_read_32(APU_PWRCTL) | proc->pwrdn_mask);
+}
+
+
+/**
+ * pm_client_abort_suspend() - Client-specific abort-suspend actions
+ *
+ * This function should contain any PU-specific actions
+ * required for aborting a prior suspend request
+ */
+void pm_client_abort_suspend(void)
+{
+	/* Enable interrupts at processor level (for current cpu) */
+	gicv2_cpuif_enable();
+	/* Clear powerdown request */
+	mmio_write_32(APU_PWRCTL,
+		 mmio_read_32(APU_PWRCTL) & ~primary_proc->pwrdn_mask);
+}
+
+/**
+ * pm_client_wakeup() - Client-specific wakeup actions
+ *
+ * This function should contain any PU-specific actions
+ * required for waking up another APU core
+ */
+void pm_client_wakeup(const struct pm_proc *proc)
+{
+	unsigned int cpuid = pm_get_cpuid(proc->node_id);
+
+	if (cpuid == UNDEFINED_CPUID)
+		return;
+
+	/* clear powerdown bit for affected cpu */
+	uint32_t val = mmio_read_32(APU_PWRCTL);
+	val &= ~(proc->pwrdn_mask);
+	mmio_write_32(APU_PWRCTL, val);
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_client.h b/plat/xilinx/zynqmp/pm_service/pm_client.h
new file mode 100644
index 0000000..b9f196d
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_client.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Contains APU specific macros and macros to be defined depending on
+ * the execution environment.
+ */
+
+#ifndef _PM_CLIENT_H_
+#define _PM_CLIENT_H_
+
+#include "pm_defs.h"
+#include "pm_common.h"
+
+/* Functions to be implemented by each PU */
+enum pm_ret_status pm_ipi_send(const struct pm_proc *proc,
+			       uint32_t payload[PAYLOAD_ARG_CNT]);
+enum pm_ret_status pm_ipi_send_sync(const struct pm_proc *proc,
+				    uint32_t payload[PAYLOAD_ARG_CNT],
+				    uint32_t *val);
+void pm_client_suspend(const struct pm_proc *proc);
+void pm_client_abort_suspend(void);
+void pm_client_wakeup(const struct pm_proc *proc);
+enum pm_ret_status set_ocm_retention(void);
+
+/* Global variables to be set in pm_client.c */
+extern const struct pm_proc *primary_proc;
+
+#endif /* _PM_CLIENT_H_ */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_common.h b/plat/xilinx/zynqmp/pm_service/pm_common.h
new file mode 100644
index 0000000..b432a83
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_common.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Contains definitions of commonly used macros and data types needed
+ * for PU Power Management. This file should be common for all PU's.
+ */
+
+#ifndef _PM_COMMON_H_
+#define _PM_COMMON_H_
+
+#include <debug.h>
+#include <stdint.h>
+#include "pm_defs.h"
+
+#define PAYLOAD_ARG_CNT		6U
+#define PAYLOAD_ARG_SIZE	4U	/* size in bytes */
+
+/**
+ * pm_ipi - struct for capturing IPI-channel specific info
+ * @mask	mask for enabling/disabling and triggering the IPI
+ * @base	base address for IPI
+ * @buffer_base	base address for payload buffer
+ */
+struct pm_ipi {
+	const unsigned int mask;
+	const uintptr_t base;
+	const uintptr_t buffer_base;
+};
+
+/**
+ * pm_proc - struct for capturing processor related info
+ * @node_id	node-ID of the processor
+ * @pwrdn_mask	cpu-specific mask to be used for power control register
+ * @ipi		pointer to IPI channel structure
+ *		(in APU all processors share one IPI channel)
+ */
+struct pm_proc {
+	const enum pm_node_id node_id;
+	const unsigned int pwrdn_mask;
+	const struct pm_ipi *ipi;
+};
+
+const struct pm_proc *pm_get_proc(unsigned int cpuid);
+const struct pm_proc *pm_get_proc_by_node(enum pm_node_id nid);
+
+#endif /* _PM_COMMON_H_ */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_defs.h b/plat/xilinx/zynqmp/pm_service/pm_defs.h
new file mode 100644
index 0000000..08f4aab
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_defs.h
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* ZynqMP power management enums and defines */
+
+#ifndef _PM_DEFS_H_
+#define _PM_DEFS_H_
+
+/*********************************************************************
+ * Macro definitions
+ ********************************************************************/
+
+/*
+ * 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
+
+/*********************************************************************
+ * Enum definitions
+ ********************************************************************/
+
+enum pm_api_id {
+	/* Miscellaneous API functions: */
+	PM_GET_API_VERSION = 1, /* Do not change or move */
+	PM_SET_CONFIGURATION,
+	PM_GET_NODE_STATUS,
+	PM_GET_OP_CHARACTERISTIC,
+	PM_REGISTER_NOTIFIER,
+	/* API for suspending of PUs: */
+	PM_REQ_SUSPEND,
+	PM_SELF_SUSPEND,
+	PM_FORCE_POWERDOWN,
+	PM_ABORT_SUSPEND,
+	PM_REQ_WAKEUP,
+	PM_SET_WAKEUP_SOURCE,
+	PM_SYSTEM_SHUTDOWN,
+	/* API for managing PM slaves: */
+	PM_REQ_NODE,
+	PM_RELEASE_NODE,
+	PM_SET_REQUIREMENT,
+	PM_SET_MAX_LATENCY,
+	/* Direct control API functions: */
+	PM_RESET_ASSERT,
+	PM_RESET_GET_STATUS,
+	PM_MMIO_WRITE,
+	PM_MMIO_READ,
+	PM_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,
+};
+
+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_ENERGY,
+	PM_OPCHAR_TYPE_TEMP,
+};
+
+/**
+ * @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,
+};
+
+#endif /* _PM_DEFS_H_ */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_ipi.c b/plat/xilinx/zynqmp/pm_service/pm_ipi.c
new file mode 100644
index 0000000..ef2b4fe
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_ipi.c
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <bakery_lock.h>
+#include <mmio.h>
+#include <platform.h>
+#include <arch_helpers.h>
+#include "pm_ipi.h"
+#include "../zynqmp_private.h"
+
+/* IPI message buffers */
+#define IPI_BUFFER_BASEADDR	0xFF990000U
+
+#define IPI_BUFFER_RPU_0_BASE	(IPI_BUFFER_BASEADDR + 0x0U)
+#define IPI_BUFFER_RPU_1_BASE	(IPI_BUFFER_BASEADDR + 0x200U)
+#define IPI_BUFFER_APU_BASE	(IPI_BUFFER_BASEADDR + 0x400U)
+#define IPI_BUFFER_PL_0_BASE	(IPI_BUFFER_BASEADDR + 0x600U)
+#define IPI_BUFFER_PL_1_BASE	(IPI_BUFFER_BASEADDR + 0x800U)
+#define IPI_BUFFER_PL_2_BASE	(IPI_BUFFER_BASEADDR + 0xA00U)
+#define IPI_BUFFER_PL_3_BASE	(IPI_BUFFER_BASEADDR + 0xC00U)
+#define IPI_BUFFER_PMU_BASE	(IPI_BUFFER_BASEADDR + 0xE00U)
+
+#define IPI_BUFFER_TARGET_RPU_0_OFFSET	0x0U
+#define IPI_BUFFER_TARGET_RPU_1_OFFSET	0x40U
+#define IPI_BUFFER_TARGET_APU_OFFSET	0x80U
+#define IPI_BUFFER_TARGET_PL_0_OFFSET	0xC0U
+#define IPI_BUFFER_TARGET_PL_1_OFFSET	0x100U
+#define IPI_BUFFER_TARGET_PL_2_OFFSET	0x140U
+#define IPI_BUFFER_TARGET_PL_3_OFFSET	0x180U
+#define IPI_BUFFER_TARGET_PMU_OFFSET	0x1C0U
+
+#define IPI_BUFFER_REQ_OFFSET	0x0U
+#define IPI_BUFFER_RESP_OFFSET	0x20U
+
+/* IPI Base Address */
+#define IPI_BASEADDR		0XFF300000
+
+/* APU's IPI registers */
+#define IPI_APU_ISR		(IPI_BASEADDR + 0X00000010)
+#define IPI_APU_IER		(IPI_BASEADDR + 0X00000018)
+#define IPI_APU_IDR		(IPI_BASEADDR + 0X0000001C)
+#define IPI_APU_ISR_PMU_0_MASK		0X00010000
+#define IPI_APU_IER_PMU_0_MASK		0X00010000
+
+#define IPI_TRIG_OFFSET		0
+#define IPI_OBS_OFFSET		4
+
+/* Power Management IPI interrupt number */
+#define PM_INT_NUM		0
+#define IPI_PMU_PM_INT_BASE	(IPI_PMU_0_TRIG + (PM_INT_NUM * 0x1000))
+#define IPI_PMU_PM_INT_MASK	(IPI_APU_ISR_PMU_0_MASK << PM_INT_NUM)
+#if (PM_INT_NUM < 0 || PM_INT_NUM > 3)
+	#error PM_INT_NUM value out of range
+#endif
+
+#define IPI_APU_MASK		1U
+
+static bakery_lock_t pm_secure_lock;
+
+const struct pm_ipi apu_ipi = {
+	.mask = IPI_APU_MASK,
+	.base = IPI_BASEADDR,
+	.buffer_base = IPI_BUFFER_APU_BASE,
+};
+
+/**
+ * pm_ipi_init() - Initialize IPI peripheral for communication with PMU
+ *
+ * @return	On success, the initialization function must return 0.
+ *		Any other return value will cause the framework to ignore
+ *		the service
+ *
+ * Enable interrupts at registered entrance in IPI peripheral
+ * Called from pm_setup initialization function
+ */
+int pm_ipi_init(void)
+{
+	bakery_lock_init(&pm_secure_lock);
+
+	/* IPI Interrupts Clear & Disable */
+	mmio_write_32(IPI_APU_ISR, 0xffffffff);
+	mmio_write_32(IPI_APU_IDR, 0xffffffff);
+
+	return 0;
+}
+
+/**
+ * pm_ipi_wait() - wait for pmu to handle request
+ * @proc	proc which is waiting for PMU to handle request
+ */
+static enum pm_ret_status pm_ipi_wait(const struct pm_proc *proc)
+{
+	int status;
+
+	/* Wait until previous interrupt is handled by PMU */
+	do {
+		status = mmio_read_32(proc->ipi->base + IPI_OBS_OFFSET) &
+					IPI_PMU_PM_INT_MASK;
+		/* TODO: 1) Use timer to add delay between read attempts */
+		/* TODO: 2) Return PM_RET_ERR_TIMEOUT if this times out */
+	} while (status);
+
+	return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_ipi_send_common() - Sends IPI request to the PMU
+ * @proc	Pointer to the processor who is initiating request
+ * @payload	API id and call arguments to be written in IPI buffer
+ *
+ * Send an IPI request to the power controller. Caller needs to hold
+ * the 'pm_secure_lock' lock.
+ *
+ * @return	Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ipi_send_common(const struct pm_proc *proc,
+					     uint32_t payload[PAYLOAD_ARG_CNT])
+{
+	unsigned int offset = 0;
+	uintptr_t buffer_base = proc->ipi->buffer_base +
+					IPI_BUFFER_TARGET_PMU_OFFSET +
+					IPI_BUFFER_REQ_OFFSET;
+
+	/* Wait until previous interrupt is handled by PMU */
+	pm_ipi_wait(proc);
+
+	/* Write payload into IPI buffer */
+	for (size_t i = 0; i < PAYLOAD_ARG_CNT; i++) {
+		mmio_write_32(buffer_base + offset, payload[i]);
+		offset += PAYLOAD_ARG_SIZE;
+	}
+	/* Generate IPI to PMU */
+	mmio_write_32(proc->ipi->base + IPI_TRIG_OFFSET, IPI_PMU_PM_INT_MASK);
+
+	return PM_RET_SUCCESS;
+}
+
+/**
+ * pm_ipi_send() - Sends IPI request to the PMU
+ * @proc	Pointer to the processor who is initiating request
+ * @payload	API id and call arguments to be written in IPI buffer
+ *
+ * Send an IPI request to the power controller.
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_ipi_send(const struct pm_proc *proc,
+			       uint32_t payload[PAYLOAD_ARG_CNT])
+{
+	enum pm_ret_status ret;
+
+	bakery_lock_get(&pm_secure_lock);
+
+	ret = pm_ipi_send_common(proc, payload);
+
+	bakery_lock_release(&pm_secure_lock);
+
+	return ret;
+}
+
+
+/**
+ * pm_ipi_buff_read() - Reads IPI response after PMU has handled interrupt
+ * @proc	Pointer to the processor who is waiting and reading response
+ * @value	Used to return value from 2nd IPI buffer element (optional)
+ *
+ * @return	Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ipi_buff_read(const struct pm_proc *proc,
+					   unsigned int *value)
+{
+	uintptr_t buffer_base = proc->ipi->buffer_base +
+				IPI_BUFFER_TARGET_PMU_OFFSET +
+				IPI_BUFFER_RESP_OFFSET;
+
+	pm_ipi_wait(proc);
+
+	/*
+	 * Read response from IPI buffer
+	 * buf-0: success or error+reason
+	 * buf-1: value
+	 * buf-2: unused
+	 * buf-3: unused
+	 */
+	if (value != NULL)
+		*value = mmio_read_32(buffer_base + PAYLOAD_ARG_SIZE);
+
+	return mmio_read_32(buffer_base);
+}
+
+/**
+ * pm_ipi_send_sync() - Sends IPI request to the PMU
+ * @proc	Pointer to the processor who is initiating request
+ * @payload	API id and call arguments to be written in IPI buffer
+ * @value	Used to return value from 2nd IPI buffer element (optional)
+ *
+ * Send an IPI request to the power controller and wait for it to be handled.
+ *
+ * @return	Returns status, either success or error+reason and, optionally,
+ *		@value
+ */
+enum pm_ret_status pm_ipi_send_sync(const struct pm_proc *proc,
+				    uint32_t payload[PAYLOAD_ARG_CNT],
+				    unsigned int *value)
+{
+	enum pm_ret_status ret;
+
+	bakery_lock_get(&pm_secure_lock);
+
+	ret = pm_ipi_send_common(proc, payload);
+	if (ret != PM_RET_SUCCESS)
+		goto unlock;
+
+	ret = pm_ipi_buff_read(proc, value);
+
+unlock:
+	bakery_lock_release(&pm_secure_lock);
+
+	return ret;
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_ipi.h b/plat/xilinx/zynqmp/pm_service/pm_ipi.h
new file mode 100644
index 0000000..d92e648
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_ipi.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _PM_IPI_H_
+#define _PM_IPI_H_
+
+#include "pm_common.h"
+
+int pm_ipi_init(void);
+
+enum pm_ret_status pm_ipi_send(const struct pm_proc *proc,
+			       uint32_t payload[PAYLOAD_ARG_CNT]);
+enum pm_ret_status pm_ipi_send_sync(const struct pm_proc *proc,
+				    uint32_t payload[PAYLOAD_ARG_CNT],
+				    unsigned int *value);
+
+#endif /* _PM_IPI_H_ */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
new file mode 100644
index 0000000..6744065
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Top-level SMC handler for ZynqMP power management calls and
+ * IPI setup functions for communication with PMU.
+ */
+
+#include <errno.h>
+#include <gic_common.h>
+#include <runtime_svc.h>
+#include <string.h>
+#include "pm_api_sys.h"
+#include "pm_client.h"
+#include "pm_ipi.h"
+#include "../zynqmp_private.h"
+
+/* 0 - UP, !0 - DOWN */
+static int32_t pm_down = !0;
+
+/**
+ * pm_context - Structure which contains data for power management
+ * @api_version		version of PM API, must match with one on PMU side
+ * @payload		payload array used to store received
+ *			data from ipi buffer registers
+ */
+static struct {
+	uint32_t api_version;
+	uint32_t payload[PAYLOAD_ARG_CNT];
+} pm_ctx;
+
+/**
+ * pm_setup() - PM service setup
+ *
+ * @return	On success, the initialization function must return 0.
+ *		Any other return value will cause the framework to ignore
+ *		the service
+ *
+ * Initialization functions for ZynqMP power management for
+ * communicaton with PMU.
+ *
+ * Called from sip_svc_setup initialization function with the
+ * rt_svc_init signature.
+ *
+ */
+int pm_setup(void)
+{
+	int status;
+
+	if (!zynqmp_is_pmu_up())
+		return -ENODEV;
+
+	status = pm_ipi_init();
+
+	if (status == 0)
+		INFO("BL31: PM Service Init Complete: API v%d.%d\n",
+		     PM_VERSION_MAJOR, PM_VERSION_MINOR);
+	else
+		INFO("BL31: PM Service Init Failed, Error Code %d!\n", status);
+
+	pm_down = status;
+
+	return status;
+}
+
+/**
+ * pm_smc_handler() - SMC handler for PM-API calls coming from EL1/EL2.
+ * @smc_fid - Function Identifier
+ * @x1 - x4 - Arguments
+ * @cookie  - Unused
+ * @handler - Pointer to caller's context structure
+ *
+ * @return  - Unused
+ *
+ * Determines that smc_fid is valid and supported PM SMC Function ID from the
+ * list of pm_api_ids, otherwise completes the request with
+ * the unknown SMC Function ID
+ *
+ * The SMC calls for PM service are forwarded from SIP Service SMC handler
+ * function with rt_svc_handle signature
+ */
+uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
+			uint64_t x4, void *cookie, void *handle, uint64_t flags)
+{
+	enum pm_ret_status ret;
+
+	uint32_t pm_arg[4];
+
+	/* Handle case where PM wasn't initialized properly */
+	if (pm_down)
+		SMC_RET1(handle, SMC_UNK);
+
+	pm_arg[0] = (uint32_t)x1;
+	pm_arg[1] = (uint32_t)(x1 >> 32);
+	pm_arg[2] = (uint32_t)x2;
+	pm_arg[3] = (uint32_t)(x2 >> 32);
+
+	switch (smc_fid & FUNCID_NUM_MASK) {
+	/* PM API Functions */
+	case PM_SELF_SUSPEND:
+		ret = pm_self_suspend(pm_arg[0], pm_arg[1], pm_arg[2],
+				      pm_arg[3]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_REQ_SUSPEND:
+		ret = pm_req_suspend(pm_arg[0], pm_arg[1], pm_arg[2],
+				     pm_arg[3]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_REQ_WAKEUP:
+		ret = pm_req_wakeup(pm_arg[0], pm_arg[1], pm_arg[2],
+				    pm_arg[3]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_FORCE_POWERDOWN:
+		ret = pm_force_powerdown(pm_arg[0], pm_arg[1]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_ABORT_SUSPEND:
+		ret = pm_abort_suspend(pm_arg[0]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_SET_WAKEUP_SOURCE:
+		ret = pm_set_wakeup_source(pm_arg[0], pm_arg[1], pm_arg[2]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_SYSTEM_SHUTDOWN:
+		ret = pm_system_shutdown(pm_arg[0]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_REQ_NODE:
+		ret = pm_req_node(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_RELEASE_NODE:
+		ret = pm_release_node(pm_arg[0]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_SET_REQUIREMENT:
+		ret = pm_set_requirement(pm_arg[0], pm_arg[1], pm_arg[2],
+					 pm_arg[3]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_SET_MAX_LATENCY:
+		ret = pm_set_max_latency(pm_arg[0], pm_arg[1]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_GET_API_VERSION:
+		/* Check is PM API version already verified */
+		if (pm_ctx.api_version == PM_VERSION)
+			SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS |
+				 ((uint64_t)PM_VERSION << 32));
+
+		ret = pm_get_api_version(&pm_ctx.api_version);
+		SMC_RET1(handle, (uint64_t)ret |
+			 ((uint64_t)pm_ctx.api_version << 32));
+
+	case PM_SET_CONFIGURATION:
+		ret = pm_set_configuration(pm_arg[0]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_GET_NODE_STATUS:
+		ret = pm_get_node_status(pm_arg[0]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_GET_OP_CHARACTERISTIC:
+		ret = pm_get_op_characteristic(pm_arg[0], pm_arg[1]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_REGISTER_NOTIFIER:
+		ret = pm_register_notifier(pm_arg[0], pm_arg[1], pm_arg[2],
+					   pm_arg[3]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_RESET_ASSERT:
+		ret = pm_reset_assert(pm_arg[0], pm_arg[1]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_RESET_GET_STATUS:
+	{
+		uint32_t reset_status;
+
+		ret = pm_reset_get_status(pm_arg[0], &reset_status);
+		SMC_RET1(handle, (uint64_t)ret |
+			 ((uint64_t)reset_status << 32));
+	}
+
+	/* PM memory access functions */
+	case PM_MMIO_WRITE:
+		ret = pm_mmio_write(pm_arg[0], pm_arg[1], pm_arg[2]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_MMIO_READ:
+	{
+		uint32_t value;
+
+		ret = pm_mmio_read(pm_arg[0], &value);
+		SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+	}
+	default:
+		WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid);
+		SMC_RET1(handle, SMC_UNK);
+	}
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.h b/plat/xilinx/zynqmp/pm_service/pm_svc_main.h
new file mode 100644
index 0000000..26985a2
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _PM_SVC_MAIN_H_
+#define _PM_SVC_MAIN_H_
+
+#include "pm_common.h"
+
+int pm_setup(void);
+uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
+			uint64_t x4, void *cookie, void *handle,
+			uint64_t flags);
+
+#endif /*  _PM_SVC_MAIN_H_ */