Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clk: tegra: Refactor fractional divider calculation

Move this to a separate file so it can be used to calculate the sdmmc
clock dividers.

Signed-off-by: Peter De-Schrijver <pdeschrijver@nvidia.com>
Signed-off-by: Aapo Vienamo <avienamo@nvidia.com>
Acked-by: Peter De Schrijver <pdeschrijver@nvidia.com>
Acked-by: Jon Hunter <jonathanh@nvidia.com>
Signed-off-by: Stephen Boyd <sboyd@kernel.org>

authored by

Peter De Schrijver and committed by
Stephen Boyd
cb3ac594 0cbb61a3

+53 -26
+1
drivers/clk/tegra/Makefile
··· 24 24 obj-y += cvb.o 25 25 obj-$(CONFIG_ARCH_TEGRA_210_SOC) += clk-tegra210.o 26 26 obj-$(CONFIG_CLK_TEGRA_BPMP) += clk-bpmp.o 27 + obj-y += clk-utils.o
+6 -26
drivers/clk/tegra/clk-divider.c
··· 32 32 static int get_div(struct tegra_clk_frac_div *divider, unsigned long rate, 33 33 unsigned long parent_rate) 34 34 { 35 - u64 divider_ux1 = parent_rate; 36 - u8 flags = divider->flags; 37 - int mul; 35 + int div; 38 36 39 - if (!rate) 37 + div = div_frac_get(rate, parent_rate, divider->width, 38 + divider->frac_width, divider->flags); 39 + 40 + if (div < 0) 40 41 return 0; 41 42 42 - mul = get_mul(divider); 43 - 44 - if (!(flags & TEGRA_DIVIDER_INT)) 45 - divider_ux1 *= mul; 46 - 47 - if (flags & TEGRA_DIVIDER_ROUND_UP) 48 - divider_ux1 += rate - 1; 49 - 50 - do_div(divider_ux1, rate); 51 - 52 - if (flags & TEGRA_DIVIDER_INT) 53 - divider_ux1 *= mul; 54 - 55 - divider_ux1 -= mul; 56 - 57 - if ((s64)divider_ux1 < 0) 58 - return 0; 59 - 60 - if (divider_ux1 > get_max_div(divider)) 61 - return get_max_div(divider); 62 - 63 - return divider_ux1; 43 + return div; 64 44 } 65 45 66 46 static unsigned long clk_frac_div_recalc_rate(struct clk_hw *hw,
+43
drivers/clk/tegra/clk-utils.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. 4 + */ 5 + 6 + #include <asm/div64.h> 7 + 8 + #include "clk.h" 9 + 10 + #define div_mask(w) ((1 << (w)) - 1) 11 + 12 + int div_frac_get(unsigned long rate, unsigned parent_rate, u8 width, 13 + u8 frac_width, u8 flags) 14 + { 15 + u64 divider_ux1 = parent_rate; 16 + int mul; 17 + 18 + if (!rate) 19 + return 0; 20 + 21 + mul = 1 << frac_width; 22 + 23 + if (!(flags & TEGRA_DIVIDER_INT)) 24 + divider_ux1 *= mul; 25 + 26 + if (flags & TEGRA_DIVIDER_ROUND_UP) 27 + divider_ux1 += rate - 1; 28 + 29 + do_div(divider_ux1, rate); 30 + 31 + if (flags & TEGRA_DIVIDER_INT) 32 + divider_ux1 *= mul; 33 + 34 + if (divider_ux1 < mul) 35 + return 0; 36 + 37 + divider_ux1 -= mul; 38 + 39 + if (divider_ux1 > div_mask(width)) 40 + return div_mask(width); 41 + 42 + return divider_ux1; 43 + }
+3
drivers/clk/tegra/clk.h
··· 812 812 int tegra_pll_wait_for_lock(struct tegra_clk_pll *pll); 813 813 u16 tegra_pll_get_fixed_mdiv(struct clk_hw *hw, unsigned long input_rate); 814 814 int tegra_pll_p_div_to_hw(struct tegra_clk_pll *pll, u8 p_div); 815 + int div_frac_get(unsigned long rate, unsigned parent_rate, u8 width, 816 + u8 frac_width, u8 flags); 817 + 815 818 816 819 /* Combined read fence with delay */ 817 820 #define fence_udelay(delay, reg) \