In message: [linux-yocto][v6.1/standard/preempt-rt/sdkv6.1/xlnx-soc][PATCH] Revert "drivers: clk: zynqmp: update divider round rate logic" on 10/07/2024 [email protected] wrote:
> From: Quanyang Wang <[email protected]> > > This patch reverts the commit c249ef9d0978a ("drivers: clk: zynqmp: > update divider round rate logic"). > > This is because that there has been a similar commit efe0d3640f6ff > ("drivers: clk: zynqmp: update divider round rate logic") which is > picked from SDK. This commit introduces some problem and the SDK patch > 7e6654b576a00 ("drivers: clk: zynqmp: add hack to use old algorithm > for divider round rate") is to fix it. But when merging, the content of > the commit 7e6654b576a00 is missing. So we need to revert the commit > c249ef9d0978a and bring the content of the commit 7e6654b576a00 back. > > Signed-off-by: Quanyang Wang <[email protected]> > --- > Hi Bruce, > Would you please help merge this patch to the branches: > v6.1/standard/preempt-rt/sdkv6.1/xlnx-soc > v6.1/standard/sdkv6.1/xlnx-soc merged. Bruce > Thanks, > Quanyang > --- > drivers/clk/zynqmp/divider.c | 88 ++++++++++++++++++++++++++++++++++-- > 1 file changed, 83 insertions(+), 5 deletions(-) > > diff --git a/drivers/clk/zynqmp/divider.c b/drivers/clk/zynqmp/divider.c > index a491f19ef7f8b..0ed124ba0ea6b 100644 > --- a/drivers/clk/zynqmp/divider.c > +++ b/drivers/clk/zynqmp/divider.c > @@ -111,6 +111,51 @@ 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, > + struct zynqmp_clk_divider *divider, > + u32 *bestdiv) > +{ > + int div1; > + int div2; > + long error = LONG_MAX; > + unsigned long div1_prate; > + struct clk_hw *div1_parent_hw; > + struct zynqmp_clk_divider *pdivider; > + struct clk_hw *div2_parent_hw = clk_hw_get_parent(hw); > + > + if (!div2_parent_hw) > + return; > + > + 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 = ((div1_prate / 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 > @@ -129,7 +174,8 @@ static long zynqmp_clk_divider_round_rate(struct clk_hw > *hw, > u32 div_type = divider->div_type; > u32 bestdiv; > int ret; > - u8 width = 0; > + u8 width; > + struct device_node *np; > > /* if read only, just return current value */ > if (divider->flags & CLK_DIVIDER_READ_ONLY) { > @@ -149,12 +195,44 @@ static long zynqmp_clk_divider_round_rate(struct clk_hw > *hw, > return DIV_ROUND_UP_ULL((u64)*prate, bestdiv); > } > > - width = fls(divider->max_div); > + /* > + * Hack to use old algorithm for round rate div clocks. Currently PL > + * rate is getting changed because RPLL_TO_FPD clock is changing RPLL > + * rate for DP audio driver. Using old algorithm RPLL rate change is > + * less and its not affecting PL clocks more so as a temporary solution > + * use old algorithm for Versal and ZynqMP platforms. > + * > + * TBD: Remove this hack and use new algorithm for all platform once PL > + * clock issue is fixed with better way. > + */ > + np = of_find_compatible_node(NULL, NULL, "xlnx,versal-net"); > + if (np) { > + width = fls(divider->max_div); > > - rate = divider_round_rate(hw, rate, prate, NULL, width, divider->flags); > + rate = divider_round_rate(hw, rate, prate, NULL, width, > divider->flags); > > - if (divider->is_frac && (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) && > (rate % *prate)) > - *prate = rate; > + if (divider->is_frac && (clk_hw_get_flags(hw) & > CLK_SET_RATE_PARENT) && > + (rate % *prate)) > + *prate = rate; > + } else { > + bestdiv = zynqmp_divider_get_val(*prate, rate, divider->flags); > + > + /* > + * 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, 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; > } > -- > 2.36.1 >
-=-=-=-=-=-=-=-=-=-=-=- Links: You receive all messages sent to this group. View/Reply Online (#14142): https://lists.yoctoproject.org/g/linux-yocto/message/14142 Mute This Topic: https://lists.yoctoproject.org/mt/107138006/21656 Group Owner: [email protected] Unsubscribe: https://lists.yoctoproject.org/g/linux-yocto/unsub [[email protected]] -=-=-=-=-=-=-=-=-=-=-=-
