diff options
Diffstat (limited to 'drivers/clk/zynqmp')
-rw-r--r-- | drivers/clk/zynqmp/clk-gate-zynqmp.c | 9 | ||||
-rw-r--r-- | drivers/clk/zynqmp/clk-mux-zynqmp.c | 6 | ||||
-rw-r--r-- | drivers/clk/zynqmp/clk-zynqmp.h | 1 | ||||
-rw-r--r-- | drivers/clk/zynqmp/clkc.c | 41 | ||||
-rw-r--r-- | drivers/clk/zynqmp/divider.c | 39 | ||||
-rw-r--r-- | drivers/clk/zynqmp/pll.c | 29 |
6 files changed, 63 insertions, 62 deletions
diff --git a/drivers/clk/zynqmp/clk-gate-zynqmp.c b/drivers/clk/zynqmp/clk-gate-zynqmp.c index 83b236f20fff..10c9b889324f 100644 --- a/drivers/clk/zynqmp/clk-gate-zynqmp.c +++ b/drivers/clk/zynqmp/clk-gate-zynqmp.c @@ -37,9 +37,8 @@ static int zynqmp_clk_gate_enable(struct clk_hw *hw) const char *clk_name = clk_hw_get_name(hw); u32 clk_id = gate->clk_id; int ret; - const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); - ret = eemi_ops->clock_enable(clk_id); + ret = zynqmp_pm_clock_enable(clk_id); if (ret) pr_warn_once("%s() clock enabled failed for %s, ret = %d\n", @@ -58,9 +57,8 @@ static void zynqmp_clk_gate_disable(struct clk_hw *hw) const char *clk_name = clk_hw_get_name(hw); u32 clk_id = gate->clk_id; int ret; - const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); - ret = eemi_ops->clock_disable(clk_id); + ret = zynqmp_pm_clock_disable(clk_id); if (ret) pr_warn_once("%s() clock disable failed for %s, ret = %d\n", @@ -79,9 +77,8 @@ static int zynqmp_clk_gate_is_enabled(struct clk_hw *hw) const char *clk_name = clk_hw_get_name(hw); u32 clk_id = gate->clk_id; int state, ret; - const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); - ret = eemi_ops->clock_getstate(clk_id, &state); + ret = zynqmp_pm_clock_getstate(clk_id, &state); if (ret) { pr_warn_once("%s() clock get state failed for %s, ret = %d\n", __func__, clk_name, ret); diff --git a/drivers/clk/zynqmp/clk-mux-zynqmp.c b/drivers/clk/zynqmp/clk-mux-zynqmp.c index 0af8f74c5fa5..06194149be83 100644 --- a/drivers/clk/zynqmp/clk-mux-zynqmp.c +++ b/drivers/clk/zynqmp/clk-mux-zynqmp.c @@ -47,9 +47,8 @@ static u8 zynqmp_clk_mux_get_parent(struct clk_hw *hw) u32 clk_id = mux->clk_id; u32 val; int ret; - const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); - ret = eemi_ops->clock_getparent(clk_id, &val); + ret = zynqmp_pm_clock_getparent(clk_id, &val); if (ret) pr_warn_once("%s() getparent failed for clock: %s, ret = %d\n", @@ -71,9 +70,8 @@ static int zynqmp_clk_mux_set_parent(struct clk_hw *hw, u8 index) const char *clk_name = clk_hw_get_name(hw); u32 clk_id = mux->clk_id; int ret; - const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); - ret = eemi_ops->clock_setparent(clk_id, index); + ret = zynqmp_pm_clock_setparent(clk_id, index); if (ret) pr_warn_once("%s() set parent failed for clock: %s, ret = %d\n", diff --git a/drivers/clk/zynqmp/clk-zynqmp.h b/drivers/clk/zynqmp/clk-zynqmp.h index fec9a15c8786..5beeb41b29fa 100644 --- a/drivers/clk/zynqmp/clk-zynqmp.h +++ b/drivers/clk/zynqmp/clk-zynqmp.h @@ -30,6 +30,7 @@ struct clock_topology { u32 type; u32 flag; u32 type_flag; + u8 custom_type_flag; }; struct clk_hw *zynqmp_clk_register_pll(const char *name, u32 clk_id, diff --git a/drivers/clk/zynqmp/clkc.c b/drivers/clk/zynqmp/clkc.c index 10e89f23880b..db8d0d7161ce 100644 --- a/drivers/clk/zynqmp/clkc.c +++ b/drivers/clk/zynqmp/clkc.c @@ -84,6 +84,7 @@ struct name_resp { struct topology_resp { #define CLK_TOPOLOGY_TYPE GENMASK(3, 0) +#define CLK_TOPOLOGY_CUSTOM_TYPE_FLAGS GENMASK(7, 4) #define CLK_TOPOLOGY_FLAGS GENMASK(23, 8) #define CLK_TOPOLOGY_TYPE_FLAGS GENMASK(31, 24) u32 topology[CLK_GET_TOPOLOGY_RESP_WORDS]; @@ -134,7 +135,6 @@ static struct clk_hw *(* const clk_topology[]) (const char *name, u32 clk_id, static struct zynqmp_clock *clock; static struct clk_hw_onecell_data *zynqmp_data; static unsigned int clock_max_idx; -static const struct zynqmp_eemi_ops *eemi_ops; /** * zynqmp_is_valid_clock() - Check whether clock is valid or not @@ -206,7 +206,7 @@ static int zynqmp_pm_clock_get_num_clocks(u32 *nclocks) qdata.qid = PM_QID_CLOCK_GET_NUM_CLOCKS; - ret = eemi_ops->query_data(qdata, ret_payload); + ret = zynqmp_pm_query_data(qdata, ret_payload); *nclocks = ret_payload[1]; return ret; @@ -231,7 +231,7 @@ static int zynqmp_pm_clock_get_name(u32 clock_id, qdata.qid = PM_QID_CLOCK_GET_NAME; qdata.arg1 = clock_id; - eemi_ops->query_data(qdata, ret_payload); + zynqmp_pm_query_data(qdata, ret_payload); memcpy(response, ret_payload, sizeof(*response)); return 0; @@ -265,7 +265,7 @@ static int zynqmp_pm_clock_get_topology(u32 clock_id, u32 index, qdata.arg1 = clock_id; qdata.arg2 = index; - ret = eemi_ops->query_data(qdata, ret_payload); + ret = zynqmp_pm_query_data(qdata, ret_payload); memcpy(response, &ret_payload[1], sizeof(*response)); return ret; @@ -296,7 +296,7 @@ struct clk_hw *zynqmp_clk_register_fixed_factor(const char *name, u32 clk_id, qdata.qid = PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS; qdata.arg1 = clk_id; - ret = eemi_ops->query_data(qdata, ret_payload); + ret = zynqmp_pm_query_data(qdata, ret_payload); if (ret) return ERR_PTR(ret); @@ -339,7 +339,7 @@ static int zynqmp_pm_clock_get_parents(u32 clock_id, u32 index, qdata.arg1 = clock_id; qdata.arg2 = index; - ret = eemi_ops->query_data(qdata, ret_payload); + ret = zynqmp_pm_query_data(qdata, ret_payload); memcpy(response, &ret_payload[1], sizeof(*response)); return ret; @@ -364,7 +364,7 @@ static int zynqmp_pm_clock_get_attributes(u32 clock_id, qdata.qid = PM_QID_CLOCK_GET_ATTRIBUTES; qdata.arg1 = clock_id; - ret = eemi_ops->query_data(qdata, ret_payload); + ret = zynqmp_pm_query_data(qdata, ret_payload); memcpy(response, &ret_payload[1], sizeof(*response)); return ret; @@ -396,6 +396,9 @@ static int __zynqmp_clock_get_topology(struct clock_topology *topology, topology[*nnodes].type_flag = FIELD_GET(CLK_TOPOLOGY_TYPE_FLAGS, response->topology[i]); + topology[*nnodes].custom_type_flag = + FIELD_GET(CLK_TOPOLOGY_CUSTOM_TYPE_FLAGS, + response->topology[i]); (*nnodes)++; } @@ -558,7 +561,7 @@ static struct clk_hw *zynqmp_register_clk_topology(int clk_id, char *clk_name, { int j; u32 num_nodes, clk_dev_id; - char *clk_out = NULL; + char *clk_out[MAX_NODES]; struct clock_topology *nodes; struct clk_hw *hw = NULL; @@ -572,16 +575,16 @@ static struct clk_hw *zynqmp_register_clk_topology(int clk_id, char *clk_name, * Intermediate clock names are postfixed with type of clock. */ if (j != (num_nodes - 1)) { - clk_out = kasprintf(GFP_KERNEL, "%s%s", clk_name, + clk_out[j] = kasprintf(GFP_KERNEL, "%s%s", clk_name, clk_type_postfix[nodes[j].type]); } else { - clk_out = kasprintf(GFP_KERNEL, "%s", clk_name); + clk_out[j] = kasprintf(GFP_KERNEL, "%s", clk_name); } if (!clk_topology[nodes[j].type]) continue; - hw = (*clk_topology[nodes[j].type])(clk_out, clk_dev_id, + hw = (*clk_topology[nodes[j].type])(clk_out[j], clk_dev_id, parent_names, num_parents, &nodes[j]); @@ -590,9 +593,12 @@ static struct clk_hw *zynqmp_register_clk_topology(int clk_id, char *clk_name, __func__, clk_dev_id, clk_name, PTR_ERR(hw)); - parent_names[0] = clk_out; + parent_names[0] = clk_out[j]; } - kfree(clk_out); + + for (j = 0; j < num_nodes; j++) + kfree(clk_out[j]); + return hw; } @@ -663,6 +669,11 @@ static void zynqmp_get_clock_info(void) continue; clock[i].valid = FIELD_GET(CLK_ATTR_VALID, attr.attr[0]); + /* skip query for Invalid clock */ + ret = zynqmp_is_valid_clock(i); + if (ret != CLK_ATTR_VALID) + continue; + clock[i].type = FIELD_GET(CLK_ATTR_TYPE, attr.attr[0]) ? CLK_TYPE_EXTERNAL : CLK_TYPE_OUTPUT; @@ -738,10 +749,6 @@ static int zynqmp_clock_probe(struct platform_device *pdev) int ret; struct device *dev = &pdev->dev; - eemi_ops = zynqmp_pm_get_eemi_ops(); - if (IS_ERR(eemi_ops)) - return PTR_ERR(eemi_ops); - ret = zynqmp_clk_setup(dev->of_node); return ret; diff --git a/drivers/clk/zynqmp/divider.c b/drivers/clk/zynqmp/divider.c index 4be2cc76aa2e..66da02b83d39 100644 --- a/drivers/clk/zynqmp/divider.c +++ b/drivers/clk/zynqmp/divider.c @@ -25,7 +25,8 @@ #define to_zynqmp_clk_divider(_hw) \ container_of(_hw, struct zynqmp_clk_divider, hw) -#define CLK_FRAC BIT(13) /* has a fractional parent */ +#define CLK_FRAC BIT(13) /* has a fractional parent */ +#define CUSTOM_FLAG_CLK_FRAC BIT(0) /* has a fractional parent in custom type flag */ /** * struct zynqmp_clk_divider - adjustable divider clock @@ -83,9 +84,8 @@ static unsigned long zynqmp_clk_divider_recalc_rate(struct clk_hw *hw, u32 div_type = divider->div_type; u32 div, value; int ret; - const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); - ret = eemi_ops->clock_getdivider(clk_id, &div); + ret = zynqmp_pm_clock_getdivider(clk_id, &div); if (ret) pr_warn_once("%s() get divider failed for %s, ret = %d\n", @@ -111,23 +111,30 @@ static unsigned long zynqmp_clk_divider_recalc_rate(struct clk_hw *hw, static void zynqmp_get_divider2_val(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate, struct zynqmp_clk_divider *divider, int *bestdiv) { int div1; int div2; long error = LONG_MAX; - struct clk_hw *parent_hw = clk_hw_get_parent(hw); - struct zynqmp_clk_divider *pdivider = to_zynqmp_clk_divider(parent_hw); + unsigned long div1_prate; + struct clk_hw *div1_parent_hw; + struct clk_hw *div2_parent_hw = clk_hw_get_parent(hw); + struct zynqmp_clk_divider *pdivider = + to_zynqmp_clk_divider(div2_parent_hw); if (!pdivider) return; + div1_parent_hw = clk_hw_get_parent(div2_parent_hw); + if (!div1_parent_hw) + return; + + div1_prate = clk_hw_get_rate(div1_parent_hw); *bestdiv = 1; for (div1 = 1; div1 <= pdivider->max_div;) { for (div2 = 1; div2 <= divider->max_div;) { - long new_error = ((parent_rate / div1) / div2) - rate; + long new_error = ((div1_prate / div1) / div2) - rate; if (abs(new_error) < abs(error)) { *bestdiv = div2; @@ -163,11 +170,10 @@ static long zynqmp_clk_divider_round_rate(struct clk_hw *hw, u32 div_type = divider->div_type; u32 bestdiv; int ret; - const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); /* if read only, just return current value */ if (divider->flags & CLK_DIVIDER_READ_ONLY) { - ret = eemi_ops->clock_getdivider(clk_id, &bestdiv); + ret = zynqmp_pm_clock_getdivider(clk_id, &bestdiv); if (ret) pr_warn_once("%s() get divider failed for %s, ret = %d\n", @@ -192,11 +198,13 @@ static long zynqmp_clk_divider_round_rate(struct clk_hw *hw, */ if (div_type == TYPE_DIV2 && (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) { - zynqmp_get_divider2_val(hw, rate, *prate, divider, &bestdiv); + zynqmp_get_divider2_val(hw, rate, divider, &bestdiv); } if ((clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) && divider->is_frac) bestdiv = rate % *prate ? 1 : bestdiv; + + bestdiv = min_t(u32, bestdiv, divider->max_div); *prate = rate * bestdiv; return rate; @@ -219,7 +227,6 @@ static int zynqmp_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, u32 div_type = divider->div_type; u32 value, div; int ret; - const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); value = zynqmp_divider_get_val(parent_rate, rate, divider->flags); if (div_type == TYPE_DIV1) { @@ -233,7 +240,7 @@ static int zynqmp_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) div = __ffs(div); - ret = eemi_ops->clock_setdivider(clk_id, div); + ret = zynqmp_pm_clock_setdivider(clk_id, div); if (ret) pr_warn_once("%s() set divider failed for %s, ret = %d\n", @@ -256,9 +263,8 @@ static const struct clk_ops zynqmp_clk_divider_ops = { * Return: Maximum divisor of a clock if query data is successful * U16_MAX in case of query data is not success */ -u32 zynqmp_clk_get_max_divisor(u32 clk_id, u32 type) +static u32 zynqmp_clk_get_max_divisor(u32 clk_id, u32 type) { - const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); struct zynqmp_pm_query_data qdata = {0}; u32 ret_payload[PAYLOAD_ARG_CNT]; int ret; @@ -266,7 +272,7 @@ u32 zynqmp_clk_get_max_divisor(u32 clk_id, u32 type) qdata.qid = PM_QID_CLOCK_GET_MAX_DIVISOR; qdata.arg1 = clk_id; qdata.arg2 = type; - ret = eemi_ops->query_data(qdata, ret_payload); + ret = zynqmp_pm_query_data(qdata, ret_payload); /* * To maintain backward compatibility return maximum possible value * (0xFFFF) if query for max divisor is not successful. @@ -311,7 +317,8 @@ struct clk_hw *zynqmp_clk_register_divider(const char *name, init.num_parents = 1; /* struct clk_divider assignments */ - div->is_frac = !!(nodes->flag & CLK_FRAC); + div->is_frac = !!((nodes->flag & CLK_FRAC) | + (nodes->custom_type_flag & CUSTOM_FLAG_CLK_FRAC)); div->flags = nodes->type_flag; div->hw.init = &init; div->clk_id = clk_id; diff --git a/drivers/clk/zynqmp/pll.c b/drivers/clk/zynqmp/pll.c index 89b599530105..92f449ed38e5 100644 --- a/drivers/clk/zynqmp/pll.c +++ b/drivers/clk/zynqmp/pll.c @@ -50,10 +50,8 @@ static inline enum pll_mode zynqmp_pll_get_mode(struct clk_hw *hw) const char *clk_name = clk_hw_get_name(hw); u32 ret_payload[PAYLOAD_ARG_CNT]; int ret; - const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); - ret = eemi_ops->ioctl(0, IOCTL_GET_PLL_FRAC_MODE, clk_id, 0, - ret_payload); + ret = zynqmp_pm_get_pll_frac_mode(clk_id, ret_payload); if (ret) pr_warn_once("%s() PLL get frac mode failed for %s, ret = %d\n", __func__, clk_name, ret); @@ -73,14 +71,13 @@ static inline void zynqmp_pll_set_mode(struct clk_hw *hw, bool on) const char *clk_name = clk_hw_get_name(hw); int ret; u32 mode; - const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); if (on) mode = PLL_MODE_FRAC; else mode = PLL_MODE_INT; - ret = eemi_ops->ioctl(0, IOCTL_SET_PLL_FRAC_MODE, clk_id, mode, NULL); + ret = zynqmp_pm_set_pll_frac_mode(clk_id, mode); if (ret) pr_warn_once("%s() PLL set frac mode failed for %s, ret = %d\n", __func__, clk_name, ret); @@ -139,17 +136,15 @@ static unsigned long zynqmp_pll_recalc_rate(struct clk_hw *hw, unsigned long rate, frac; u32 ret_payload[PAYLOAD_ARG_CNT]; int ret; - const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); - ret = eemi_ops->clock_getdivider(clk_id, &fbdiv); + ret = zynqmp_pm_clock_getdivider(clk_id, &fbdiv); if (ret) pr_warn_once("%s() get divider failed for %s, ret = %d\n", __func__, clk_name, ret); rate = parent_rate * fbdiv; if (zynqmp_pll_get_mode(hw) == PLL_MODE_FRAC) { - eemi_ops->ioctl(0, IOCTL_GET_PLL_FRAC_DATA, clk_id, 0, - ret_payload); + zynqmp_pm_get_pll_frac_data(clk_id, ret_payload); data = ret_payload[1]; frac = (parent_rate * data) / FRAC_DIV; rate = rate + frac; @@ -177,7 +172,6 @@ static int zynqmp_pll_set_rate(struct clk_hw *hw, unsigned long rate, u32 fbdiv; long rate_div, frac, m, f; int ret; - const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); if (zynqmp_pll_get_mode(hw) == PLL_MODE_FRAC) { rate_div = (rate * FRAC_DIV) / parent_rate; @@ -187,21 +181,21 @@ static int zynqmp_pll_set_rate(struct clk_hw *hw, unsigned long rate, rate = parent_rate * m; frac = (parent_rate * f) / FRAC_DIV; - ret = eemi_ops->clock_setdivider(clk_id, m); + ret = zynqmp_pm_clock_setdivider(clk_id, m); if (ret == -EUSERS) WARN(1, "More than allowed devices are using the %s, which is forbidden\n", clk_name); else if (ret) pr_warn_once("%s() set divider failed for %s, ret = %d\n", __func__, clk_name, ret); - eemi_ops->ioctl(0, IOCTL_SET_PLL_FRAC_DATA, clk_id, f, NULL); + zynqmp_pm_set_pll_frac_data(clk_id, f); return rate + frac; } fbdiv = DIV_ROUND_CLOSEST(rate, parent_rate); fbdiv = clamp_t(u32, fbdiv, PLL_FBDIV_MIN, PLL_FBDIV_MAX); - ret = eemi_ops->clock_setdivider(clk_id, fbdiv); + ret = zynqmp_pm_clock_setdivider(clk_id, fbdiv); if (ret) pr_warn_once("%s() set divider failed for %s, ret = %d\n", __func__, clk_name, ret); @@ -222,9 +216,8 @@ static int zynqmp_pll_is_enabled(struct clk_hw *hw) u32 clk_id = clk->clk_id; unsigned int state; int ret; - const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); - ret = eemi_ops->clock_getstate(clk_id, &state); + ret = zynqmp_pm_clock_getstate(clk_id, &state); if (ret) { pr_warn_once("%s() clock get state failed for %s, ret = %d\n", __func__, clk_name, ret); @@ -246,12 +239,11 @@ static int zynqmp_pll_enable(struct clk_hw *hw) const char *clk_name = clk_hw_get_name(hw); u32 clk_id = clk->clk_id; int ret; - const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); if (zynqmp_pll_is_enabled(hw)) return 0; - ret = eemi_ops->clock_enable(clk_id); + ret = zynqmp_pm_clock_enable(clk_id); if (ret) pr_warn_once("%s() clock enable failed for %s, ret = %d\n", __func__, clk_name, ret); @@ -269,12 +261,11 @@ static void zynqmp_pll_disable(struct clk_hw *hw) const char *clk_name = clk_hw_get_name(hw); u32 clk_id = clk->clk_id; int ret; - const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); if (!zynqmp_pll_is_enabled(hw)) return; - ret = eemi_ops->clock_disable(clk_id); + ret = zynqmp_pm_clock_disable(clk_id); if (ret) pr_warn_once("%s() clock disable failed for %s, ret = %d\n", __func__, clk_name, ret); |