From: Rajan Vaja <rajan.vaja@xilinx.com> To: mturquette@baylibre.com, sboyd@kernel.org, robh+dt@kernel.org, mark.rutland@arm.com, michal.simek@xilinx.com, jolly.shah@xilinx.com, m.tretter@pengutronix.de, gustavo@embeddedor.com, tejas.patel@xilinx.com, nava.manne@xilinx.com, mdf@kernel.org Cc: linux-clk@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Rajan Vaja <rajan.vaja@xilinx.com> Subject: [PATCH v3 5/6] clk: zynqmp: Fix divider calculation Date: Wed, 4 Dec 2019 22:35:58 -0800 [thread overview] Message-ID: <1575527759-26452-6-git-send-email-rajan.vaja@xilinx.com> (raw) In-Reply-To: <1575527759-26452-1-git-send-email-rajan.vaja@xilinx.com> zynqmp_clk_divider_round_rate() returns actual divider value after calculating from parent rate and desired rate, even though that rate is not supported by single divider of hardware. It is also possible that such divisor value can be achieved through 2 different dividers. As, Linux tries to set such divisor value(out of range) in single divider set divider is getting failed. Fix the same by computing best possible combination of two divisors which provides more accurate clock rate. Signed-off-by: Michal Simek <michal.simek@xilinx.com> Signed-off-by: Tejas Patel <tejas.patel@xilinx.com> Signed-off-by: Rajan Vaja <rajan.vaja@xilinx.com> --- drivers/clk/zynqmp/divider.c | 46 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/drivers/clk/zynqmp/divider.c b/drivers/clk/zynqmp/divider.c index aea52cd..e0d49cc 100644 --- a/drivers/clk/zynqmp/divider.c +++ b/drivers/clk/zynqmp/divider.c @@ -89,6 +89,42 @@ static unsigned long zynqmp_clk_divider_recalc_rate(struct clk_hw *hw, return DIV_ROUND_UP_ULL(parent_rate, value); } +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); + + if (!pdivider) + return; + + *bestdiv = 1; + for (div1 = 1; div1 <= pdivider->max_div;) { + for (div2 = 1; div2 <= divider->max_div;) { + long new_error = ((parent_rate / div1) / div2) - rate; + + if (abs(new_error) < abs(error)) { + *bestdiv = div2; + error = new_error; + } + if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) + div2 = div2 << 1; + else + div2++; + } + if (pdivider->flags & CLK_DIVIDER_POWER_OF_TWO) + div1 = div1 << 1; + else + div1++; + } +} + /** * zynqmp_clk_divider_round_rate() - Round rate of divider clock * @hw: handle between common and hardware-specific interfaces @@ -126,6 +162,16 @@ static long zynqmp_clk_divider_round_rate(struct clk_hw *hw, bestdiv = zynqmp_divider_get_val(*prate, rate); + /* + * In case of two divisors, compute best divider values and return + * divider2 value based on compute value. div1 will be automatically + * set to optimum based on required total divider value. + */ + if (div_type == TYPE_DIV2 && + (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) { + zynqmp_get_divider2_val(hw, rate, *prate, divider, &bestdiv); + } + if ((clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) && divider->is_frac) bestdiv = rate % *prate ? 1 : bestdiv; *prate = rate * bestdiv; -- 2.7.4
WARNING: multiple messages have this Message-ID (diff)
From: Rajan Vaja <rajan.vaja@xilinx.com> To: mturquette@baylibre.com, sboyd@kernel.org, robh+dt@kernel.org, mark.rutland@arm.com, michal.simek@xilinx.com, jolly.shah@xilinx.com, m.tretter@pengutronix.de, gustavo@embeddedor.com, tejas.patel@xilinx.com, nava.manne@xilinx.com, mdf@kernel.org Cc: devicetree@vger.kernel.org, Rajan Vaja <rajan.vaja@xilinx.com>, linux-clk@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 5/6] clk: zynqmp: Fix divider calculation Date: Wed, 4 Dec 2019 22:35:58 -0800 [thread overview] Message-ID: <1575527759-26452-6-git-send-email-rajan.vaja@xilinx.com> (raw) In-Reply-To: <1575527759-26452-1-git-send-email-rajan.vaja@xilinx.com> zynqmp_clk_divider_round_rate() returns actual divider value after calculating from parent rate and desired rate, even though that rate is not supported by single divider of hardware. It is also possible that such divisor value can be achieved through 2 different dividers. As, Linux tries to set such divisor value(out of range) in single divider set divider is getting failed. Fix the same by computing best possible combination of two divisors which provides more accurate clock rate. Signed-off-by: Michal Simek <michal.simek@xilinx.com> Signed-off-by: Tejas Patel <tejas.patel@xilinx.com> Signed-off-by: Rajan Vaja <rajan.vaja@xilinx.com> --- drivers/clk/zynqmp/divider.c | 46 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/drivers/clk/zynqmp/divider.c b/drivers/clk/zynqmp/divider.c index aea52cd..e0d49cc 100644 --- a/drivers/clk/zynqmp/divider.c +++ b/drivers/clk/zynqmp/divider.c @@ -89,6 +89,42 @@ static unsigned long zynqmp_clk_divider_recalc_rate(struct clk_hw *hw, return DIV_ROUND_UP_ULL(parent_rate, value); } +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); + + if (!pdivider) + return; + + *bestdiv = 1; + for (div1 = 1; div1 <= pdivider->max_div;) { + for (div2 = 1; div2 <= divider->max_div;) { + long new_error = ((parent_rate / div1) / div2) - rate; + + if (abs(new_error) < abs(error)) { + *bestdiv = div2; + error = new_error; + } + if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) + div2 = div2 << 1; + else + div2++; + } + if (pdivider->flags & CLK_DIVIDER_POWER_OF_TWO) + div1 = div1 << 1; + else + div1++; + } +} + /** * zynqmp_clk_divider_round_rate() - Round rate of divider clock * @hw: handle between common and hardware-specific interfaces @@ -126,6 +162,16 @@ static long zynqmp_clk_divider_round_rate(struct clk_hw *hw, bestdiv = zynqmp_divider_get_val(*prate, rate); + /* + * In case of two divisors, compute best divider values and return + * divider2 value based on compute value. div1 will be automatically + * set to optimum based on required total divider value. + */ + if (div_type == TYPE_DIV2 && + (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) { + zynqmp_get_divider2_val(hw, rate, *prate, divider, &bestdiv); + } + if ((clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) && divider->is_frac) bestdiv = rate % *prate ? 1 : bestdiv; *prate = rate * bestdiv; -- 2.7.4 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2019-12-05 6:38 UTC|newest] Thread overview: 72+ messages / expand[flat|nested] mbox.gz Atom feed top 2019-11-12 13:16 [PATCH 0/7] clk: zynqmp: Extend and fix zynqmp clock driver Rajan Vaja 2019-11-12 13:16 ` Rajan Vaja 2019-11-12 13:16 ` [PATCH 1/7] dt-bindings: clock: Add bindings for versal " Rajan Vaja 2019-11-12 13:16 ` Rajan Vaja 2019-11-12 22:51 ` Stephen Boyd 2019-11-12 22:51 ` Stephen Boyd 2019-11-18 17:30 ` Rob Herring 2019-11-18 17:30 ` Rob Herring 2019-11-12 13:16 ` [PATCH 2/7] clk: zynqmp: Extend driver for versal Rajan Vaja 2019-11-12 13:16 ` Rajan Vaja 2019-11-12 13:16 ` [PATCH 3/7] clk: zynqmp: Warn user if clock user are more than allowed Rajan Vaja 2019-11-12 13:16 ` Rajan Vaja 2019-11-21 14:31 ` Michael Tretter 2019-11-21 14:31 ` Michael Tretter 2019-11-12 13:16 ` [PATCH 4/7] clk: zynqmp: Add support for get max divider Rajan Vaja 2019-11-12 13:16 ` Rajan Vaja 2019-11-21 14:33 ` Michael Tretter 2019-11-21 14:33 ` Michael Tretter 2019-11-12 13:16 ` [PATCH 5/7] clk: zynqmp: Fix divider calculation Rajan Vaja 2019-11-12 13:16 ` Rajan Vaja 2019-11-12 13:16 ` [PATCH 6/7] clk: zynqmp: Add support for clock with CLK_DIVIDER_POWER_OF_TWO flag Rajan Vaja 2019-11-12 13:16 ` Rajan Vaja 2019-11-12 13:16 ` [PATCH 7/7] clk: zynqmp: Fix fractional clock check Rajan Vaja 2019-11-12 13:16 ` Rajan Vaja 2019-11-21 14:41 ` Michael Tretter 2019-11-21 14:41 ` Michael Tretter 2019-11-22 9:43 ` [PATCH v2 0/6] clk: zynqmp: Extend and fix zynqmp clock driver Rajan Vaja 2019-11-22 9:43 ` Rajan Vaja 2019-11-22 9:43 ` [PATCH v2 1/6] dt-bindings: clock: Add bindings for versal " Rajan Vaja 2019-11-22 9:43 ` Rajan Vaja 2019-12-04 19:53 ` Rob Herring 2019-12-04 19:53 ` Rob Herring 2019-11-22 9:43 ` [PATCH v2 2/6] clk: zynqmp: Extend driver for versal Rajan Vaja 2019-11-22 9:43 ` Rajan Vaja 2019-11-22 9:43 ` [PATCH v2 3/6] clk: zynqmp: Warn user if clock user are more than allowed Rajan Vaja 2019-11-22 9:43 ` Rajan Vaja 2019-11-22 9:43 ` [PATCH v2 4/6] clk: zynqmp: Add support for get max divider Rajan Vaja 2019-11-22 9:43 ` Rajan Vaja 2019-11-22 9:43 ` [PATCH v2 5/6] clk: zynqmp: Fix divider calculation Rajan Vaja 2019-11-22 9:43 ` Rajan Vaja 2019-11-22 9:43 ` [PATCH v2 6/6] clk: zynqmp: Add support for clock with CLK_DIVIDER_POWER_OF_TWO flag Rajan Vaja 2019-11-22 9:43 ` Rajan Vaja 2019-12-05 6:35 ` [PATCH v3 0/6] clk: zynqmp: Extend and fix zynqmp clock driver Rajan Vaja 2019-12-05 6:35 ` Rajan Vaja 2019-12-05 6:35 ` [PATCH v3 1/6] dt-bindings: clock: Add bindings for versal " Rajan Vaja 2019-12-05 6:35 ` Rajan Vaja 2020-01-23 22:58 ` Stephen Boyd 2020-01-23 22:58 ` Stephen Boyd 2019-12-05 6:35 ` [PATCH v3 2/6] clk: zynqmp: Extend driver for versal Rajan Vaja 2019-12-05 6:35 ` Rajan Vaja 2020-01-23 22:58 ` Stephen Boyd 2020-01-23 22:58 ` Stephen Boyd 2019-12-05 6:35 ` [PATCH v3 3/6] clk: zynqmp: Warn user if clock user are more than allowed Rajan Vaja 2019-12-05 6:35 ` Rajan Vaja 2020-01-23 22:58 ` Stephen Boyd 2020-01-23 22:58 ` Stephen Boyd 2019-12-05 6:35 ` [PATCH v3 4/6] clk: zynqmp: Add support for get max divider Rajan Vaja 2019-12-05 6:35 ` Rajan Vaja 2020-01-23 22:58 ` Stephen Boyd 2020-01-23 22:58 ` Stephen Boyd 2019-12-05 6:35 ` Rajan Vaja [this message] 2019-12-05 6:35 ` [PATCH v3 5/6] clk: zynqmp: Fix divider calculation Rajan Vaja 2020-01-23 22:58 ` Stephen Boyd 2020-01-23 22:58 ` Stephen Boyd 2019-12-05 6:35 ` [PATCH v3 6/6] clk: zynqmp: Add support for clock with CLK_DIVIDER_POWER_OF_TWO flag Rajan Vaja 2019-12-05 6:35 ` Rajan Vaja 2020-01-23 22:59 ` Stephen Boyd 2020-01-23 22:59 ` Stephen Boyd 2019-12-12 15:20 ` [PATCH v3 0/6] clk: zynqmp: Extend and fix zynqmp clock driver Michal Simek 2019-12-12 15:20 ` Michal Simek 2020-01-16 11:41 ` Rajan Vaja 2020-01-16 11:41 ` Rajan Vaja
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=1575527759-26452-6-git-send-email-rajan.vaja@xilinx.com \ --to=rajan.vaja@xilinx.com \ --cc=devicetree@vger.kernel.org \ --cc=gustavo@embeddedor.com \ --cc=jolly.shah@xilinx.com \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=linux-clk@vger.kernel.org \ --cc=linux-kernel@vger.kernel.org \ --cc=m.tretter@pengutronix.de \ --cc=mark.rutland@arm.com \ --cc=mdf@kernel.org \ --cc=michal.simek@xilinx.com \ --cc=mturquette@baylibre.com \ --cc=nava.manne@xilinx.com \ --cc=robh+dt@kernel.org \ --cc=sboyd@kernel.org \ --cc=tejas.patel@xilinx.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.