diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c index 6e53bd89de07cfd610dfe99ac70e83e04c588ab5..852f92763caa6835aab269262ed88684ab5fd7e0 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c +++ b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c @@ -2620,6 +2620,42 @@ enum pm_ret_status pm_api_clock_get_attributes(unsigned int clock_id, return PM_RET_SUCCESS; } +/** + * 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 diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_clock.h b/plat/xilinx/zynqmp/pm_service/pm_api_clock.h index 48f5a5ec4f3bd00404eff3c444a11d8ff79fa8ef..301ed24b65b4099b842429c69d33b28ec1c3727a 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 @@ enum pm_ret_status pm_api_clock_get_parents(unsigned int clock_id, 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 cd6f44f8323bfe98a0def0b7c52b3b7fea9f97d9..b1720d9f6c765b60e0d2b358472adf4fd3acf6ee 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c +++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c @@ -756,6 +756,23 @@ enum pm_ret_status pm_ioctl(enum pm_node_id nid, return pm_api_ioctl(nid, ioctl_id, arg1, arg2, value); } +/** + * 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 @@ enum pm_ret_status pm_query_data(enum pm_query_id qid, 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 56c004339b19956322973fb76ab972beb89af438..ff66d3f024a84dc2173fdae8e208c27f64017e51 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 @@ enum pm_query_id { PM_QID_PINCTRL_GET_FUNCTION_GROUPS, PM_QID_PINCTRL_GET_PIN_GROUPS, PM_QID_CLOCK_GET_NUM_CLOCKS, + PM_QID_CLOCK_GET_MAX_DIVISOR, }; /**********************************************************