diff options
author | Peter De Schrijver <pdeschrijver@nvidia.com> | 2018-07-12 07:53:00 -0400 |
---|---|---|
committer | Stephen Boyd <sboyd@kernel.org> | 2018-07-25 16:43:34 -0400 |
commit | cb3ac5947afb3bb7e2f89c1b59f61dcf3e115fe1 (patch) | |
tree | 7111e58446fef9a299069b9104c9e32a09732a11 | |
parent | 0cbb61a313979b53d6b2dc838a92f07471440708 (diff) |
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>
-rw-r--r-- | drivers/clk/tegra/Makefile | 1 | ||||
-rw-r--r-- | drivers/clk/tegra/clk-divider.c | 30 | ||||
-rw-r--r-- | drivers/clk/tegra/clk-utils.c | 43 | ||||
-rw-r--r-- | drivers/clk/tegra/clk.h | 3 |
4 files changed, 52 insertions, 25 deletions
diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile index b71692391bd6..c77d072eb333 100644 --- a/drivers/clk/tegra/Makefile +++ b/drivers/clk/tegra/Makefile | |||
@@ -24,3 +24,4 @@ obj-$(CONFIG_ARCH_TEGRA_132_SOC) += clk-tegra124.o | |||
24 | obj-y += cvb.o | 24 | obj-y += cvb.o |
25 | obj-$(CONFIG_ARCH_TEGRA_210_SOC) += clk-tegra210.o | 25 | obj-$(CONFIG_ARCH_TEGRA_210_SOC) += clk-tegra210.o |
26 | obj-$(CONFIG_CLK_TEGRA_BPMP) += clk-bpmp.o | 26 | obj-$(CONFIG_CLK_TEGRA_BPMP) += clk-bpmp.o |
27 | obj-y += clk-utils.o | ||
diff --git a/drivers/clk/tegra/clk-divider.c b/drivers/clk/tegra/clk-divider.c index 16e0aee14773..8f175ff62f73 100644 --- a/drivers/clk/tegra/clk-divider.c +++ b/drivers/clk/tegra/clk-divider.c | |||
@@ -32,35 +32,15 @@ | |||
32 | static int get_div(struct tegra_clk_frac_div *divider, unsigned long rate, | 32 | static int get_div(struct tegra_clk_frac_div *divider, unsigned long rate, |
33 | unsigned long parent_rate) | 33 | unsigned long parent_rate) |
34 | { | 34 | { |
35 | u64 divider_ux1 = parent_rate; | 35 | int div; |
36 | u8 flags = divider->flags; | ||
37 | int mul; | ||
38 | |||
39 | if (!rate) | ||
40 | return 0; | ||
41 | |||
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 | 36 | ||
55 | divider_ux1 -= mul; | 37 | div = div_frac_get(rate, parent_rate, divider->width, |
38 | divider->frac_width, divider->flags); | ||
56 | 39 | ||
57 | if ((s64)divider_ux1 < 0) | 40 | if (div < 0) |
58 | return 0; | 41 | return 0; |
59 | 42 | ||
60 | if (divider_ux1 > get_max_div(divider)) | 43 | return div; |
61 | return get_max_div(divider); | ||
62 | |||
63 | return divider_ux1; | ||
64 | } | 44 | } |
65 | 45 | ||
66 | static unsigned long clk_frac_div_recalc_rate(struct clk_hw *hw, | 46 | static unsigned long clk_frac_div_recalc_rate(struct clk_hw *hw, |
diff --git a/drivers/clk/tegra/clk-utils.c b/drivers/clk/tegra/clk-utils.c new file mode 100644 index 000000000000..1a5daae4e501 --- /dev/null +++ b/drivers/clk/tegra/clk-utils.c | |||
@@ -0,0 +1,43 @@ | |||
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 | } | ||
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index e3b9c22ad8b2..c733841aa6db 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h | |||
@@ -812,6 +812,9 @@ extern tegra_clk_apply_init_table_func tegra_clk_apply_init_table; | |||
812 | int tegra_pll_wait_for_lock(struct tegra_clk_pll *pll); | 812 | int tegra_pll_wait_for_lock(struct tegra_clk_pll *pll); |
813 | u16 tegra_pll_get_fixed_mdiv(struct clk_hw *hw, unsigned long input_rate); | 813 | u16 tegra_pll_get_fixed_mdiv(struct clk_hw *hw, unsigned long input_rate); |
814 | int tegra_pll_p_div_to_hw(struct tegra_clk_pll *pll, u8 p_div); | 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 | /* Combined read fence with delay */ | 819 | /* Combined read fence with delay */ |
817 | #define fence_udelay(delay, reg) \ | 820 | #define fence_udelay(delay, reg) \ |