| From 83b89aa09555c556531f10c1b7abde69ca94d629 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Mon, 5 Jan 2026 16:09:50 +0530 |
| Subject: clk: qcom: rcg2: compute 2d using duty fraction directly |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Taniya Das <taniya.das@oss.qualcomm.com> |
| |
| [ Upstream commit d6205a1878dd4cc9664c4b4829b68a29c0426efc ] |
| |
| The duty-cycle calculation in clk_rcg2_set_duty_cycle() currently |
| derives an intermediate percentage `duty_per = (num * 100) / den` and |
| then computes: |
| |
| d = DIV_ROUND_CLOSEST(n * duty_per * 2, 100); |
| |
| This introduces integer truncation at the percentage step (division by |
| `den`) and a redundant scaling by 100, which can reduce precision for |
| large `den` and skew the final rounding. |
| |
| Compute `2d` directly from the duty fraction to preserve precision and |
| avoid the unnecessary scaling: |
| |
| d = DIV_ROUND_CLOSEST(n * duty->num * 2, duty->den); |
| |
| This keeps the intended formula `d ≈ n * 2 * (num/den)` while performing |
| a single, final rounded division, improving accuracy especially for small |
| duty cycles or large denominators. It also removes the unused `duty_per` |
| variable, simplifying the code. |
| |
| There is no functional changes beyond improved numerical accuracy. |
| |
| Fixes: 7f891faf596ed ("clk: qcom: clk-rcg2: Add support for duty-cycle for RCG") |
| Signed-off-by: Taniya Das <taniya.das@oss.qualcomm.com> |
| Link: https://lore.kernel.org/r/20260105-duty_cycle_precision-v2-1-d1d466a6330a@oss.qualcomm.com |
| Signed-off-by: Bjorn Andersson <andersson@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/clk/qcom/clk-rcg2.c | 6 ++---- |
| 1 file changed, 2 insertions(+), 4 deletions(-) |
| |
| diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c |
| index e46bb60dcda41..0e26f4f0bdbae 100644 |
| --- a/drivers/clk/qcom/clk-rcg2.c |
| +++ b/drivers/clk/qcom/clk-rcg2.c |
| @@ -432,7 +432,7 @@ static int clk_rcg2_get_duty_cycle(struct clk_hw *hw, struct clk_duty *duty) |
| static int clk_rcg2_set_duty_cycle(struct clk_hw *hw, struct clk_duty *duty) |
| { |
| struct clk_rcg2 *rcg = to_clk_rcg2(hw); |
| - u32 notn_m, n, m, d, not2d, mask, duty_per, cfg; |
| + u32 notn_m, n, m, d, not2d, mask, cfg; |
| int ret; |
| |
| /* Duty-cycle cannot be modified for non-MND RCGs */ |
| @@ -451,10 +451,8 @@ static int clk_rcg2_set_duty_cycle(struct clk_hw *hw, struct clk_duty *duty) |
| |
| n = (~(notn_m) + m) & mask; |
| |
| - duty_per = (duty->num * 100) / duty->den; |
| - |
| /* Calculate 2d value */ |
| - d = DIV_ROUND_CLOSEST(n * duty_per * 2, 100); |
| + d = DIV_ROUND_CLOSEST(n * duty->num * 2, duty->den); |
| |
| /* |
| * Check bit widths of 2d. If D is too big reduce duty cycle. |
| -- |
| 2.51.0 |
| |