diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c
index 1fab38fac63c2da3ab6a5b079620c9c2797bbd17..ee8b387386718108b767b435052d20c7f84a98da 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c
@@ -2526,7 +2526,7 @@ static struct pm_pll pm_plls[] = {
  *
  * @return	Pointer to PLL structure if found, NULL otherwise
  */
-static struct pm_pll *pm_clock_get_pll(enum clock_id clock_id)
+struct pm_pll *pm_clock_get_pll(enum clock_id clock_id)
 {
 	uint32_t i;
 
@@ -2679,32 +2679,24 @@ static enum pm_ret_status pm_api_clk_enable_disable(unsigned int clock_id,
 }
 
 /**
- * pm_api_clock_enable() - Enable the clock for given id
- * @clock_id: Id of the clock to be enabled
+ * pm_clock_pll_enable() - "Enable" the PLL clock (lock the PLL)
+ * @pll: PLL to be locked
  *
- * This function is used by master to enable the clock
- * including peripherals and PLL clocks.
+ * This function is used to map IOCTL/linux-based PLL handling to system-level
+ * EEMI APIs
  *
- * Return: Returns status, either success or error+reason.
+ * Return: Error if the argument is not valid or status as returned by PMU
  */
-enum pm_ret_status pm_api_clock_enable(unsigned int clock_id)
+enum pm_ret_status pm_clock_pll_enable(struct pm_pll *pll)
 {
-	enum pm_ret_status ret = PM_RET_SUCCESS;
-
-	if (!pm_clock_valid(clock_id))
+	if (!pll)
 		return PM_RET_ERROR_ARGS;
 
-	if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT)
-		return PM_RET_ERROR_NOTSUPPORTED;
-
-	/*
-	 * PLL type clock should not enable explicitly.
-	 * It is done by FSBL on boot-up and by PMUFW whenever required.
-	 */
-	if (!ISPLL(clock_id))
-		ret = pm_api_clk_enable_disable(clock_id, 1);
+	/* Set the PLL mode according to the buffered mode value */
+	if (pll->mode == PLL_FRAC_MODE)
+		return pm_pll_set_mode(pll->nid, PM_PLL_MODE_FRACTIONAL);
 
-	return ret;
+	return pm_pll_set_mode(pll->nid, PM_PLL_MODE_INTEGER);
 }
 
 /**
@@ -3172,3 +3164,20 @@ enum pm_ret_status pm_clock_get_pll_mode(enum clock_id clock_id,
 
 	return PM_RET_SUCCESS;
 }
+
+/**
+ * pm_clock_id_is_valid() -  Check if given clock ID is valid
+ * @clock_id   ID of the clock to be checked
+ *
+ * @return     Returns success if clock_id is valid, otherwise an error
+ */
+enum pm_ret_status pm_clock_id_is_valid(unsigned int clock_id)
+{
+	if (!pm_clock_valid(clock_id))
+		return PM_RET_ERROR_ARGS;
+
+	if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT)
+		return PM_RET_ERROR_NOTSUPPORTED;
+
+	return PM_RET_SUCCESS;
+}
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_clock.h b/plat/xilinx/zynqmp/pm_service/pm_api_clock.h
index 3a70036f954c5937d38f9aa1aa4cd0d76909ddc0..ab7a8a4051533ca8f6102f26deb6c46942ed6c87 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_clock.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_clock.h
@@ -274,6 +274,8 @@ enum {
 #define	TYPE_DIV2 5U
 #define	TYPE_GATE 6U
 
+struct pm_pll;
+struct pm_pll *pm_clock_get_pll(enum clock_id clock_id);
 
 enum pm_ret_status pm_api_clock_get_name(unsigned int clock_id, char *name);
 enum pm_ret_status pm_api_clock_get_num_clocks(unsigned int *nclocks);
@@ -291,8 +293,9 @@ enum pm_ret_status pm_api_clock_get_attributes(unsigned int clock_id,
 
 enum pm_ret_status pm_clock_get_pll_node_id(enum clock_id clock_id,
 					    enum pm_node_id *node_id);
+enum pm_ret_status pm_clock_id_is_valid(unsigned int clock_id);
 
-enum pm_ret_status pm_api_clock_enable(unsigned int clock_id);
+enum pm_ret_status pm_clock_pll_enable(struct pm_pll *pll);
 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);
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
index 171c7e6c9d6eb2fc38312b4c048bce2c95f683c3..e33761c84d12dd6e3ec8d5f0a603877d0ce395aa 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
@@ -843,6 +843,36 @@ static enum pm_ret_status pm_clock_get_attributes(unsigned int clock_id,
 	return pm_api_clock_get_attributes(clock_id, attr);
 }
 
+/**
+ * pm_clock_gate() - Configure clock gate
+ * @clock_id	Id of the clock to be configured
+ * @enable	Flag 0=disable (gate the clock), !0=enable (activate the clock)
+ *
+ * @return	Error if an argument is not valid or status as returned by the
+ *		PM controller (PMU)
+ */
+static enum pm_ret_status pm_clock_gate(unsigned int clock_id,
+					unsigned char enable)
+{
+	uint32_t payload[PAYLOAD_ARG_CNT];
+	enum pm_ret_status status;
+	enum pm_api_id api_id;
+
+	/* Check if clock ID is valid and return an error if it is not */
+	status = pm_clock_id_is_valid(clock_id);
+	if (status != PM_RET_SUCCESS)
+		return status;
+
+	if (enable)
+		api_id = PM_CLOCK_ENABLE;
+	else
+		api_id = PM_CLOCK_DISABLE;
+
+	/* Send request to the PMU */
+	PM_PACK_PAYLOAD2(payload, api_id, clock_id);
+	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
 /**
  * pm_clock_enable() - Enable the clock for given id
  * @clock_id: Id of the clock to be enabled
@@ -850,12 +880,20 @@ static enum pm_ret_status pm_clock_get_attributes(unsigned int clock_id,
  * This function is used by master to enable the clock
  * including peripherals and PLL clocks.
  *
- * Return: Returns status, either success or error+reason.
+ * @return:	Error if an argument is not valid or status as returned by the
+ *		pm_clock_gate
  */
-
 enum pm_ret_status pm_clock_enable(unsigned int clock_id)
 {
-	return pm_api_clock_enable(clock_id);
+	struct pm_pll *pll;
+
+	/* First try to handle it as a PLL */
+	pll = pm_clock_get_pll(clock_id);
+	if (pll)
+		return pm_clock_pll_enable(pll);
+
+	/* It's an on-chip clock, PMU should configure clock's gate */
+	return pm_clock_gate(clock_id, 1);
 }
 
 /**