zynqmp: pm: Add clock control EEMI API and ioctl functions

These are empty functions with no logic right now. Code
will be added in subsequent commits.

Signed-off-by: Rajan Vaja <rajanv@xilinx.com>
Signed-off-by: Jolly Shah <jollys@xilinx.com>
diff --git a/plat/xilinx/zynqmp/platform.mk b/plat/xilinx/zynqmp/platform.mk
index 2abcd28..e49a9cd 100644
--- a/plat/xilinx/zynqmp/platform.mk
+++ b/plat/xilinx/zynqmp/platform.mk
@@ -79,6 +79,7 @@
 				plat/xilinx/zynqmp/pm_service/pm_api_sys.c	\
 				plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c	\
 				plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c	\
+				plat/xilinx/zynqmp/pm_service/pm_api_clock.c	\
 				plat/xilinx/zynqmp/pm_service/pm_ipi.c		\
 				plat/xilinx/zynqmp/pm_service/pm_client.c	\
 				plat/xilinx/zynqmp/ipi_mailbox_service/ipi_mailbox_svc.c
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c
new file mode 100644
index 0000000..4096a81
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c
@@ -0,0 +1,356 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * ZynqMP system level PM-API functions for clock control.
+ */
+
+#include <arch_helpers.h>
+#include <mmio.h>
+#include <platform.h>
+#include <string.h>
+#include "pm_api_clock.h"
+#include "pm_api_sys.h"
+#include "pm_client.h"
+#include "pm_common.h"
+#include "pm_ipi.h"
+
+#define CLK_NODE_MAX			6
+
+/**
+ * struct pm_clock_node - Clock topology node information
+ * @type:	Topology type (mux/div1/div2/gate/pll/fixed factor)
+ * @offset:	Offset in control register
+ * @width:	Width of the specific type in control register
+ * @clkflags:	Clk specific flags
+ * @typeflags:	Type specific flags
+ * @mult:	Multiplier for fixed factor
+ * @div:	Divisor for fixed factor
+ */
+struct pm_clock_node {
+	uint16_t clkflags;
+	uint16_t typeflags;
+	uint8_t type;
+	uint8_t offset;
+	uint8_t width;
+	uint8_t mult:4;
+	uint8_t div:4;
+};
+
+/**
+ * struct pm_clock - Clock structure
+ * @name:	Clock name
+ * @control_reg:	Control register address
+ * @status_reg:	Status register address
+ * @parents:	Parents for first clock node. Lower byte indicates parent
+ *		clock id and upper byte indicate flags for that id.
+ * pm_clock_node:	Clock nodes
+ */
+struct pm_clock {
+	char name[CLK_NAME_LEN];
+	uint8_t num_nodes;
+	unsigned int control_reg;
+	unsigned int status_reg;
+	int32_t (*parents)[];
+	struct pm_clock_node(*nodes)[];
+};
+
+/* Clock array containing clock informaton */
+struct pm_clock clocks[] = {0};
+
+/**
+ * pm_api_clock_get_name() - PM call to request a clock's name
+ * @clock_id	Clock ID
+ * @name	Name of clock (max 16 bytes)
+ *
+ * This function is used by master to get nmae of clock specified
+ * by given clock ID.
+ *
+ * @return	Returns success. In case of error, name data is 0.
+ */
+enum pm_ret_status pm_api_clock_get_name(unsigned int clock_id, char *name)
+{
+	return PM_RET_ERROR_NOTSUPPORTED;
+}
+
+/**
+ * pm_api_clock_get_topology() - PM call to request a clock's topology
+ * @clock_id	Clock ID
+ * @index	Topology index for next toplogy node
+ * @topology	Buffer to store nodes in topology and flags
+ *
+ * This function is used by master to get topology information for the
+ * clock specified by given clock ID. Each response would return 3
+ * topology nodes. To get next nodes, caller needs to call this API with
+ * index of next node. Index starts from 0.
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_api_clock_get_topology(unsigned int clock_id,
+					     unsigned int index,
+					     uint32_t *topology)
+{
+	return PM_RET_ERROR_NOTSUPPORTED;
+}
+
+/**
+ * pm_api_clock_get_fixedfactor_params() - PM call to request a clock's fixed
+ *					   factor parameters for fixed clock
+ * @clock_id	Clock ID
+ * @mul		Multiplication value
+ * @div		Divisor value
+ *
+ * This function is used by master to get fixed factor parameers for the
+ * fixed clock. This API is application only for the fixed clock.
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_api_clock_get_fixedfactor_params(unsigned int clock_id,
+						       uint32_t *mul,
+						       uint32_t *div)
+{
+	return PM_RET_ERROR_NOTSUPPORTED;
+}
+
+/**
+ * pm_api_clock_get_parents() - PM call to request a clock's first 3 parents
+ * @clock_id	Clock ID
+ * @index	Index of next parent
+ * @parents	Parents of the given clock
+ *
+ * This function is used by master to get clock's parents information.
+ * This API will return 3 parents with a single response. To get other
+ * parents, master should call same API in loop with new parent index
+ * till error is returned.
+ *
+ * E.g First call should have index 0 which will return parents 0, 1 and
+ * 2. Next call, index should be 3 which will return parent 3,4 and 5 and
+ * so on.
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_api_clock_get_parents(unsigned int clock_id,
+					    unsigned int index,
+					    uint32_t *parents)
+{
+	return PM_RET_ERROR_NOTSUPPORTED;
+}
+
+/**
+ * pm_api_clock_get_attributes() - PM call to request a clock's attributes
+ * @clock_id	Clock ID
+ * @attr	Clock attributes
+ *
+ * This function is used by master to get clock's attributes
+ * (e.g. valid, clock type, etc).
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_api_clock_get_attributes(unsigned int clock_id,
+					       uint32_t *attr)
+{
+	return PM_RET_ERROR_NOTSUPPORTED;
+}
+
+/**
+ * pm_api_clock_enable() - Enable the clock for given id
+ * @clock_id: Id of the clock to be enabled
+ *
+ * This function is used by master to enable the clock
+ * including peripherals and PLL clocks.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_api_clock_enable(unsigned int clock_id)
+{
+	return PM_RET_ERROR_NOTSUPPORTED;
+}
+
+/**
+ * pm_api_clock_disable - Disable the clock for given id
+ * @clock_id	Id of the clock to be disable
+ *
+ * This function is used by master to disable the clock
+ * including peripherals and PLL clocks.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+
+enum pm_ret_status pm_api_clock_disable(unsigned int clock_id)
+{
+	return PM_RET_ERROR_NOTSUPPORTED;
+}
+
+/**
+ * pm_api_clock_getstate - Get the clock state for given id
+ * @clock_id	Id of the clock to be queried
+ * @state	1/0 (Enabled/Disabled)
+ *
+ * This function is used by master to get the state of clock
+ * including peripherals and PLL clocks.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_api_clock_getstate(unsigned int clock_id,
+					 unsigned int *state)
+{
+	return PM_RET_ERROR_NOTSUPPORTED;
+}
+
+/**
+ * pm_api_clock_setdivider - Set the clock divider for given id
+ * @clock_id	Id of the clock
+ * @divider	Divider value
+ *
+ * This function is used by master to set divider for any clock
+ * to achieve desired rate.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_api_clock_setdivider(unsigned int clock_id,
+					   unsigned int divider)
+{
+	return PM_RET_ERROR_NOTSUPPORTED;
+}
+
+/**
+ * pm_api_clock_getdivider - Get the clock divider for given id
+ * @clock_id	Id of the clock
+ * @divider	Divider value
+ *
+ * This function is used by master to get divider values
+ * for any clock.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_api_clock_getdivider(unsigned int clock_id,
+					   unsigned int *divider)
+{
+	return PM_RET_ERROR_NOTSUPPORTED;
+}
+
+/**
+ * pm_api_clock_setrate - Set the clock rate for given id
+ * @clock_id	Id of the clock
+ * @rate	Rate value in hz
+ *
+ * This function is used by master to set rate for any clock.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_api_clock_setrate(unsigned int clock_id,
+					uint64_t rate)
+{
+	return PM_RET_ERROR_NOTSUPPORTED;
+}
+
+/**
+ * pm_api_clock_getrate - Get the clock rate for given id
+ * @clock_id	Id of the clock
+ * @rate	rate value in hz
+ *
+ * This function is used by master to get rate
+ * for any clock.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_api_clock_getrate(unsigned int clock_id,
+					uint64_t *rate)
+{
+	return PM_RET_ERROR_NOTSUPPORTED;
+}
+
+/**
+ * pm_api_clock_setparent - Set the clock parent for given id
+ * @clock_id	Id of the clock
+ * @parent_id	parent id
+ *
+ * This function is used by master to set parent for any clock.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_api_clock_setparent(unsigned int clock_id,
+					  unsigned int parent_idx)
+{
+	return PM_RET_ERROR_NOTSUPPORTED;
+}
+
+/**
+ * pm_api_clock_getparent - Get the clock parent for given id
+ * @clock_id	Id of the clock
+ * @parent_id	parent id
+ *
+ * This function is used by master to get parent index
+ * for any clock.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_api_clock_getparent(unsigned int clock_id,
+					  unsigned int *parent_idx)
+{
+	return PM_RET_ERROR_NOTSUPPORTED;
+}
+
+/**
+ * pm_api_clk_set_pll_mode() -  Set PLL mode
+ * @pll     PLL id
+ * @mode    Mode fraction/integar
+ *
+ * This function sets PLL mode.
+ *
+ * @return      Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_api_clk_set_pll_mode(unsigned int pll,
+					   unsigned int mode)
+{
+	return PM_RET_ERROR_NOTSUPPORTED;
+}
+
+/**
+ * pm_ioctl_get_pll_mode() -  Get PLL mode
+ * @pll     PLL id
+ * @mode    Mode fraction/integar
+ *
+ * This function returns current PLL mode.
+ *
+ * @return      Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_api_clk_get_pll_mode(unsigned int pll,
+					   unsigned int *mode)
+{
+	return PM_RET_ERROR_NOTSUPPORTED;
+}
+
+/**
+ * pm_api_clk_set_pll_frac_data() -  Set PLL fraction data
+ * @pll     PLL id
+ * @data    fraction data
+ *
+ * This function sets fraction data. It is valid for fraction
+ * mode only.
+ *
+ * @return      Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_api_clk_set_pll_frac_data(unsigned int pll,
+						unsigned int data)
+{
+	return PM_RET_ERROR_NOTSUPPORTED;
+}
+
+/**
+ * pm_api_clk_get_pll_frac_data() - Get PLL fraction data
+ * @pll     PLL id
+ * @data    fraction data
+ *
+ * This function returns fraction data value.
+ *
+ * @return      Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_api_clk_get_pll_frac_data(unsigned int pll,
+						unsigned int *data)
+{
+	return PM_RET_ERROR_NOTSUPPORTED;
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_clock.h b/plat/xilinx/zynqmp/pm_service/pm_api_clock.h
new file mode 100644
index 0000000..2e7260e
--- /dev/null
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_clock.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * ZynqMP system level PM-API functions for clock control.
+ */
+
+#ifndef _PM_API_CLOCK_H_
+#define _PM_API_CLOCK_H_
+
+#include "pm_common.h"
+
+#define CLK_NAME_LEN		15
+
+enum pm_ret_status pm_api_clock_get_name(unsigned int clock_id, char *name);
+enum pm_ret_status pm_api_clock_get_topology(unsigned int clock_id,
+					     unsigned int index,
+					     uint32_t *topology);
+enum pm_ret_status pm_api_clock_get_fixedfactor_params(unsigned int clock_id,
+						       uint32_t *mul,
+						       uint32_t *div);
+enum pm_ret_status pm_api_clock_get_parents(unsigned int clock_id,
+					    unsigned int index,
+					    uint32_t *parents);
+enum pm_ret_status pm_api_clock_get_attributes(unsigned int clock_id,
+					       uint32_t *attr);
+enum pm_ret_status pm_api_clock_enable(unsigned int clock_id);
+enum pm_ret_status pm_api_clock_disable(unsigned int clock_id);
+enum pm_ret_status pm_api_clock_getstate(unsigned int clock_id,
+					 unsigned int *state);
+enum pm_ret_status pm_api_clock_setdivider(unsigned int clock_id,
+					   unsigned int divider);
+enum pm_ret_status pm_api_clock_getdivider(unsigned int clock_id,
+					   unsigned int *divider);
+enum pm_ret_status pm_api_clock_setrate(unsigned int clock_id,
+					uint64_t rate);
+enum pm_ret_status pm_api_clock_getrate(unsigned int clock_id,
+					uint64_t *rate);
+enum pm_ret_status pm_api_clock_setparent(unsigned int clock_id,
+					  unsigned int parent_idx);
+enum pm_ret_status pm_api_clock_getparent(unsigned int clock_id,
+					  unsigned int *parent_idx);
+enum pm_ret_status pm_api_clk_set_pll_mode(unsigned int pll,
+					   unsigned int mode);
+enum pm_ret_status pm_api_clk_get_pll_mode(unsigned int pll,
+					   unsigned int *mode);
+enum pm_ret_status pm_api_clk_set_pll_frac_data(unsigned int pll,
+						unsigned int data);
+enum pm_ret_status pm_api_clk_get_pll_frac_data(unsigned int pll,
+						unsigned int *data);
+#endif /* _PM_API_CLOCK_H_ */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c
index c881d12..7634b8c 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c
@@ -12,6 +12,7 @@
 #include <delay_timer.h>
 #include <mmio.h>
 #include <platform.h>
+#include "pm_api_clock.h"
 #include "pm_api_ioctl.h"
 #include "pm_api_sys.h"
 #include "pm_client.h"
@@ -330,6 +331,71 @@
 }
 
 /**
+ * pm_ioctl_set_pll_frac_mode() -  Ioctl function for
+ *				   setting pll mode
+ * @pll     PLL id
+ * @mode    Mode fraction/integar
+ *
+ * This function sets PLL mode
+ *
+ * @return      Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_set_pll_frac_mode
+			(unsigned int pll, unsigned int mode)
+{
+	return pm_api_clk_set_pll_mode(pll, mode);
+}
+
+/**
+ * pm_ioctl_get_pll_frac_mode() -  Ioctl function for
+ *				   getting pll mode
+ * @pll     PLL id
+ * @mode    Mode fraction/integar
+ *
+ * This function return current PLL mode
+ *
+ * @return      Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_get_pll_frac_mode
+			(unsigned int pll, unsigned int *mode)
+{
+	return pm_api_clk_get_pll_mode(pll, mode);
+}
+
+/**
+ * pm_ioctl_set_pll_frac_data() -  Ioctl function for
+ *				   setting pll fraction data
+ * @pll     PLL id
+ * @data    fraction data
+ *
+ * This function sets fraction data.
+ * It is valid for fraction mode only.
+ *
+ * @return      Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_set_pll_frac_data
+			(unsigned int pll, unsigned int data)
+{
+	return pm_api_clk_set_pll_frac_data(pll, data);
+}
+
+/**
+ * pm_ioctl_get_pll_frac_data() -  Ioctl function for
+ *				   getting pll fraction data
+ * @pll     PLL id
+ * @data    fraction data
+ *
+ * This function returns fraction data value.
+ *
+ * @return      Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_ioctl_get_pll_frac_data
+			(unsigned int pll, unsigned int *data)
+{
+	return pm_api_clk_get_pll_frac_data(pll, data);
+}
+
+/**
  * pm_api_ioctl() -  PM IOCTL API for device control and configs
  * @node_id	Node ID of the device
  * @ioctl_id	ID of the requested IOCTL
@@ -374,6 +440,18 @@
 	case IOCTL_SET_SD_TAPDELAY:
 		ret = pm_ioctl_sd_set_tapdelay(nid, arg1, arg2);
 		break;
+	case IOCTL_SET_PLL_FRAC_MODE:
+		ret = pm_ioctl_set_pll_frac_mode(arg1, arg2);
+		break;
+	case IOCTL_GET_PLL_FRAC_MODE:
+		ret = pm_ioctl_get_pll_frac_mode(arg1, value);
+		break;
+	case IOCTL_SET_PLL_FRAC_DATA:
+		ret = pm_ioctl_set_pll_frac_data(arg1, arg2);
+		break;
+	case IOCTL_GET_PLL_FRAC_DATA:
+		ret = pm_ioctl_get_pll_frac_data(arg1, value);
+		break;
 	default:
 		ret = PM_RET_ERROR_NOTSUPPORTED;
 	}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h
index a7f14a4..b290574 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h
@@ -22,6 +22,11 @@
 	IOCTL_SET_SGMII_MODE,
 	IOCTL_SD_DLL_RESET,
 	IOCTL_SET_SD_TAPDELAY,
+	 /* Ioctl for clock driver */
+	IOCTL_SET_PLL_FRAC_MODE,
+	IOCTL_GET_PLL_FRAC_MODE,
+	IOCTL_SET_PLL_FRAC_DATA,
+	IOCTL_GET_PLL_FRAC_DATA,
 };
 
 enum rpu_oper_mode {
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
index be24371..fcc0c6e 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
@@ -11,6 +11,7 @@
 
 #include <arch_helpers.h>
 #include <platform.h>
+#include "pm_api_clock.h"
 #include "pm_api_ioctl.h"
 #include "pm_api_pinctrl.h"
 #include "pm_api_sys.h"
@@ -658,3 +659,285 @@
 {
 	return pm_api_ioctl(nid, ioctl_id, arg1, arg2, value);
 }
+
+/**
+ * pm_clock_get_name() - PM call to request a clock's name
+ * @clock_id	Clock ID
+ * @name	Name of clock (max 16 bytes)
+ *
+ * This function is used by master to get nmae of clock specified
+ * by given clock ID.
+ *
+ * @return	Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_clock_get_name(unsigned int clock_id, char *name)
+{
+	return pm_api_clock_get_name(clock_id, name);
+}
+
+/**
+ * pm_clock_get_topology() - PM call to request a clock's topology
+ * @clock_id	Clock ID
+ * @index	Topology index for next toplogy node
+ * @topology	Buffer to store nodes in topology and flags
+ *
+ * This function is used by master to get topology information for the
+ * clock specified by given clock ID. Each response would return 3
+ * topology nodes. To get next nodes, caller needs to call this API with
+ * index of next node. Index starts from 0.
+ *
+ * @return	Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_clock_get_topology(unsigned int clock_id,
+						unsigned int index,
+						uint32_t *topology)
+{
+	return pm_api_clock_get_topology(clock_id, index, topology);
+}
+
+/**
+ * pm_clock_get_fixedfactor_params() - PM call to request a clock's fixed factor
+ *				 parameters for fixed clock
+ * @clock_id	Clock ID
+ * @mul		Multiplication value
+ * @div		Divisor value
+ *
+ * This function is used by master to get fixed factor parameers for the
+ * fixed clock. This API is application only for the fixed clock.
+ *
+ * @return	Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_clock_get_fixedfactor_params(unsigned int clock_id,
+							  uint32_t *mul,
+							  uint32_t *div)
+{
+	return pm_api_clock_get_fixedfactor_params(clock_id, mul, div);
+}
+
+/**
+ * pm_clock_get_parents() - PM call to request a clock's first 3 parents
+ * @clock_id	Clock ID
+ * @index	Index of next parent
+ * @parents	Parents of the given clock
+ *
+ * This function is used by master to get clock's parents information.
+ * This API will return 3 parents with a single response. To get other
+ * parents, master should call same API in loop with new parent index
+ * till error is returned.
+ *
+ * E.g First call should have index 0 which will return parents 0, 1 and
+ * 2. Next call, index should be 3 which will return parent 3,4 and 5 and
+ * so on.
+ *
+ * @return	Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_clock_get_parents(unsigned int clock_id,
+					       unsigned int index,
+					       uint32_t *parents)
+{
+	return pm_api_clock_get_parents(clock_id, index, parents);
+}
+
+/**
+ * pm_clock_get_attributes() - PM call to request a clock's attributes
+ * @clock_id	Clock ID
+ * @attr	Clock attributes
+ *
+ * This function is used by master to get clock's attributes
+ * (e.g. valid, clock type, etc).
+ *
+ * @return	Returns status, either success or error+reason
+ */
+static enum pm_ret_status pm_clock_get_attributes(unsigned int clock_id,
+						  uint32_t *attr)
+{
+	return pm_api_clock_get_attributes(clock_id, attr);
+}
+
+/**
+ * pm_clock_enable() - Enable the clock for given id
+ * @clock_id: Id of the clock to be enabled
+ *
+ * This function is used by master to enable the clock
+ * including peripherals and PLL clocks.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+
+enum pm_ret_status pm_clock_enable(unsigned int clock_id)
+{
+	return pm_api_clock_enable(clock_id);
+}
+
+/**
+ * pm_clock_disable - Disable the clock for given id
+ * @clock_id: Id of the clock to be disable
+ *
+ * This function is used by master to disable the clock
+ * including peripherals and PLL clocks.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+
+enum pm_ret_status pm_clock_disable(unsigned int clock_id)
+{
+	return pm_api_clock_disable(clock_id);
+}
+
+/**
+ * pm_clock_getstate - Get the clock state for given id
+ * @clock_id: Id of the clock to be queried
+ * @state: 1/0 (Enabled/Disabled)
+ *
+ * This function is used by master to get the state of clock
+ * including peripherals and PLL clocks.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_clock_getstate(unsigned int clock_id,
+				     unsigned int *state)
+{
+	return pm_api_clock_getstate(clock_id, state);
+}
+
+/**
+ * pm_clock_setdivider - Set the clock divider for given id
+ * @clock_id: Id of the clock
+ * @divider: divider value
+ *
+ * This function is used by master to set divider for any clock
+ * to achieve desired rate.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_clock_setdivider(unsigned int clock_id,
+				       unsigned int divider)
+{
+	return pm_api_clock_setdivider(clock_id, divider);
+}
+
+/**
+ * pm_clock_getdivider - Get the clock divider for given id
+ * @clock_id: Id of the clock
+ * @divider: divider value
+ *
+ * This function is used by master to get divider values
+ * for any clock.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_clock_getdivider(unsigned int clock_id,
+				       unsigned int *divider)
+{
+	return pm_api_clock_getdivider(clock_id, divider);
+}
+
+/**
+ * pm_clock_setrate - Set the clock rate for given id
+ * @clock_id: Id of the clock
+ * @rate: rate value in hz
+ *
+ * This function is used by master to set rate for any clock.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_clock_setrate(unsigned int clock_id,
+				    uint64_t rate)
+{
+	return pm_api_clock_setrate(clock_id, rate);
+}
+
+/**
+ * pm_clock_getrate - Get the clock rate for given id
+ * @clock_id: Id of the clock
+ * @rate: rate value in hz
+ *
+ * This function is used by master to get rate
+ * for any clock.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_clock_getrate(unsigned int clock_id,
+				    uint64_t *rate)
+{
+	return pm_api_clock_getrate(clock_id, rate);
+}
+
+/**
+ * pm_clock_setparent - Set the clock parent for given id
+ * @clock_id: Id of the clock
+ * @parent_id: parent id
+ *
+ * This function is used by master to set parent for any clock.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_clock_setparent(unsigned int clock_id,
+				      unsigned int parent_id)
+{
+	return pm_api_clock_setparent(clock_id, parent_id);
+}
+
+/**
+ * pm_clock_getparent - Get the clock parent for given id
+ * @clock_id: Id of the clock
+ * @parent_id: parent id
+ *
+ * This function is used by master to get parent index
+ * for any clock.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_clock_getparent(unsigned int clock_id,
+				      unsigned int *parent_id)
+{
+	return pm_api_clock_getparent(clock_id, parent_id);
+}
+
+/**
+ * pm_query_data() -  PM API for querying firmware data
+ * @arg1	Argument 1 to requested IOCTL call
+ * @arg2	Argument 2 to requested IOCTL call
+ * @arg3	Argument 3 to requested IOCTL call
+ * @arg4	Argument 4 to requested IOCTL call
+ * @data	Returned output data
+ *
+ * This function returns requested data.
+ *
+ * @return	Returns status, either success or error+reason
+ */
+enum pm_ret_status pm_query_data(enum pm_query_id qid,
+				 unsigned int arg1,
+				 unsigned int arg2,
+				 unsigned int arg3,
+				 unsigned int *data)
+{
+	enum pm_ret_status ret;
+
+	switch (qid) {
+	case PM_QID_CLOCK_GET_NAME:
+		ret = pm_clock_get_name(arg1, (char *)data);
+		break;
+	case PM_QID_CLOCK_GET_TOPOLOGY:
+		ret = pm_clock_get_topology(arg1, arg2, &data[1]);
+		data[0] = ret;
+		break;
+	case PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS:
+		ret = pm_clock_get_fixedfactor_params(arg1, &data[1], &data[2]);
+		data[0] = ret;
+		break;
+	case PM_QID_CLOCK_GET_PARENTS:
+		ret = pm_clock_get_parents(arg1, arg2, &data[1]);
+		data[0] = ret;
+		break;
+	case PM_QID_CLOCK_GET_ATTRIBUTES:
+		ret = pm_clock_get_attributes(arg1, &data[1]);
+		data[0] = ret;
+		break;
+	default:
+		ret = PM_RET_ERROR_ARGS;
+		WARN("Unimplemented query service call: 0x%x\n", qid);
+	}
+
+	return ret;
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
index 1c91e8f..20d80c2 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
@@ -10,6 +10,15 @@
 #include <stdint.h>
 #include "pm_defs.h"
 
+enum pm_query_id {
+	PM_QID_INVALID,
+	PM_QID_CLOCK_GET_NAME,
+	PM_QID_CLOCK_GET_TOPOLOGY,
+	PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS,
+	PM_QID_CLOCK_GET_PARENTS,
+	PM_QID_CLOCK_GET_ATTRIBUTES,
+};
+
 /**********************************************************
  * System-level API function declarations
  **********************************************************/
@@ -110,5 +119,25 @@
 			    unsigned int arg1,
 			    unsigned int arg2,
 			    unsigned int *value);
-
+enum pm_ret_status pm_clock_enable(unsigned int clock_id);
+enum pm_ret_status pm_clock_disable(unsigned int clock_id);
+enum pm_ret_status pm_clock_getstate(unsigned int clock_id,
+				     unsigned int *state);
+enum pm_ret_status pm_clock_setdivider(unsigned int clock_id,
+				       unsigned int divider);
+enum pm_ret_status pm_clock_getdivider(unsigned int clock_id,
+				       unsigned int *divider);
+enum pm_ret_status pm_clock_setrate(unsigned int clock_id,
+				    uint64_t rate);
+enum pm_ret_status pm_clock_getrate(unsigned int clock_id,
+				    uint64_t *rate);
+enum pm_ret_status pm_clock_setparent(unsigned int clock_id,
+				      unsigned int parent_id);
+enum pm_ret_status pm_clock_getparent(unsigned int clock_id,
+				      unsigned int *parent_id);
+enum pm_ret_status pm_query_data(enum pm_query_id qid,
+				 unsigned int arg1,
+				 unsigned int arg2,
+				 unsigned int arg3,
+				 unsigned int *data);
 #endif /* _PM_API_SYS_H_ */
diff --git a/plat/xilinx/zynqmp/pm_service/pm_defs.h b/plat/xilinx/zynqmp/pm_service/pm_defs.h
index afd92f6..45a92e9 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_defs.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_defs.h
@@ -76,6 +76,18 @@
 	PM_PINCTRL_CONFIG_PARAM_GET,
 	PM_PINCTRL_CONFIG_PARAM_SET,
 	PM_IOCTL,
+	/* API to query information from firmware */
+	PM_QUERY_DATA,
+	/* Clock control API functions */
+	PM_CLOCK_ENABLE,
+	PM_CLOCK_DISABLE,
+	PM_CLOCK_GETSTATE,
+	PM_CLOCK_SETDIVIDER,
+	PM_CLOCK_GETDIVIDER,
+	PM_CLOCK_SETRATE,
+	PM_CLOCK_GETRATE,
+	PM_CLOCK_SETPARENT,
+	PM_CLOCK_GETPARENT,
 	PM_API_MAX
 };
 
diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
index 648de24..4fd69b9 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c
@@ -289,6 +289,72 @@
 		SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
 	}
 
+	case PM_QUERY_DATA:
+	{
+		uint32_t data[4];
+
+		ret = pm_query_data(pm_arg[0], pm_arg[1], pm_arg[2],
+				    pm_arg[3], data);
+		SMC_RET2(handle, (uint64_t)data[0]  | ((uint64_t)data[1] << 32),
+			 (uint64_t)data[2] | ((uint64_t)data[3] << 32));
+	}
+
+	case PM_CLOCK_ENABLE:
+		ret = pm_clock_enable(pm_arg[0]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_CLOCK_DISABLE:
+		ret = pm_clock_disable(pm_arg[0]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_CLOCK_GETSTATE:
+	{
+		uint32_t value;
+
+		ret = pm_clock_getstate(pm_arg[0], &value);
+		SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+	}
+
+	case PM_CLOCK_SETDIVIDER:
+		ret = pm_clock_setdivider(pm_arg[0], pm_arg[1]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_CLOCK_GETDIVIDER:
+	{
+		uint32_t value;
+
+		ret = pm_clock_getdivider(pm_arg[0], &value);
+		SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
+	}
+
+	case PM_CLOCK_SETRATE:
+		ret = pm_clock_setrate(pm_arg[0],
+		       ((uint64_t)pm_arg[2]) << 32 | pm_arg[1]);
+
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_CLOCK_GETRATE:
+	{
+		uint64_t value;
+
+		ret = pm_clock_getrate(pm_arg[0], &value);
+		SMC_RET2(handle, (uint64_t)ret | (value & 0xFFFFFFFF) << 32,
+			 (value >> 32) & 0xFFFFFFFF);
+
+	}
+
+	case PM_CLOCK_SETPARENT:
+		ret = pm_clock_setparent(pm_arg[0], pm_arg[1]);
+		SMC_RET1(handle, (uint64_t)ret);
+
+	case PM_CLOCK_GETPARENT:
+	{
+		uint32_t value;
+
+		ret = pm_clock_getparent(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);