zynqmp: pm_service: Add support to query max divisor

Add new QID to get maximum supported divisor by clock.

Signed-off-by: Rajan Vaja <rajan.vaja@xilinx.com>
Signed-off-by: Tejas Patel <tejas.patel@xilinx.com>
Signed-off-by: Jolly Shah <jolly.shah@xilinx.com>
Change-Id: I35fc92457e522f3f0614d983c21e55c2b0b8e80a
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c
index 6e53bd8..852f927 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c
@@ -2621,6 +2621,42 @@
 }
 
 /**
+ * pm_api_clock_get_max_divisor - PM call to get max divisor
+ * @clock_id	Clock ID
+ * @div_type	Divisor Type (TYPE_DIV1 or TYPE_DIV2)
+ * @max_div	Maximum supported divisor
+ *
+ * This function is used by master to get maximum supported value.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+enum pm_ret_status pm_api_clock_get_max_divisor(enum clock_id clock_id,
+						uint8_t div_type,
+						uint32_t *max_div)
+{
+	uint32_t i;
+	struct pm_clock_node *nodes;
+
+	if (clock_id >= CLK_MAX_OUTPUT_CLK)
+		return PM_RET_ERROR_ARGS;
+
+	nodes = *clocks[clock_id].nodes;
+	for (i = 0; i < clocks[clock_id].num_nodes; i++) {
+		if (nodes[i].type == div_type) {
+			if (CLK_DIVIDER_POWER_OF_TWO &
+					nodes[i].typeflags) {
+				*max_div = (1 << (BIT(nodes[i].width) - 1));
+			} else {
+				*max_div = BIT(nodes[i].width) - 1;
+			}
+			return PM_RET_SUCCESS;
+		}
+	}
+
+	return PM_RET_ERROR_ARGS;
+}
+
+/**
  * struct pm_pll - PLL related data required to map IOCTL-based PLL control
  * implemented by linux to system-level EEMI APIs
  * @nid:	PLL node ID
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_clock.h b/plat/xilinx/zynqmp/pm_service/pm_api_clock.h
index 48f5a5e..301ed24 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_clock.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_clock.h
@@ -307,6 +307,9 @@
 					    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_get_max_divisor(enum clock_id clock_id,
+						uint8_t div_type,
+						uint32_t *max_div);
 
 enum pm_ret_status pm_clock_get_pll_node_id(enum clock_id clock_id,
 					    enum pm_node_id *node_id);
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
index cd6f44f..b1720d9 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c
@@ -757,6 +757,23 @@
 }
 
 /**
+ * pm_clock_get_max_divisor - PM call to get max divisor
+ * @clock_id	Clock ID
+ * @div_type	Divisor ID (TYPE_DIV1 or TYPE_DIV2)
+ * @max_div	Maximum supported divisor
+ *
+ * This function is used by master to get maximum supported value.
+ *
+ * Return: Returns status, either success or error+reason.
+ */
+static enum pm_ret_status pm_clock_get_max_divisor(unsigned int clock_id,
+						   uint8_t div_type,
+						   uint32_t *max_div)
+{
+	return pm_api_clock_get_max_divisor(clock_id, div_type, max_div);
+}
+
+/**
  * pm_clock_get_num_clocks - PM call to request number of clocks
  * @nclockss: Number of clocks
  *
@@ -1338,6 +1355,11 @@
 		ret = pm_clock_get_num_clocks(&data[1]);
 		data[0] = (unsigned int)ret;
 		break;
+
+	case PM_QID_CLOCK_GET_MAX_DIVISOR:
+		ret = pm_clock_get_max_divisor(arg1, arg2, &data[1]);
+		data[0] = (unsigned int)ret;
+		break;
 	default:
 		ret = PM_RET_ERROR_ARGS;
 		WARN("Unimplemented query service call: 0x%x\n", qid);
diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
index 56c0043..ff66d3f 100644
--- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
+++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h
@@ -25,6 +25,7 @@
 	PM_QID_PINCTRL_GET_FUNCTION_GROUPS,
 	PM_QID_PINCTRL_GET_PIN_GROUPS,
 	PM_QID_CLOCK_GET_NUM_CLOCKS,
+	PM_QID_CLOCK_GET_MAX_DIVISOR,
 };
 
 /**********************************************************