1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
4 */
5 #include "ccu.h"
6
7 /*
8 * DOC: basic fixed multiplier and divider clock that cannot gate
9 *
10 * Traits of this clock:
11 * prepare - clk_prepare only ensures that parents are prepared
12 * enable - clk_enable only ensures that parents are enabled
13 * rate - rate is fixed. clk->rate = parent->rate / div * mult
14 * parent - fixed parent. No clk_set_parent support
15 */
16
clk_factor_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)17 static unsigned long clk_factor_recalc_rate(struct clk_hw *hw,
18 unsigned long parent_rate)
19 {
20 struct clk_fixed_factor *fix = to_clk_fixed_factor(hw);
21 unsigned long long int rate;
22
23 rate = (unsigned long long int)parent_rate * fix->mult;
24 rate /= fix->div;
25 return (unsigned long)rate;
26 }
27
clk_factor_round_rate(struct clk_hw * hw,unsigned long rate,unsigned long * prate)28 static long clk_factor_round_rate(struct clk_hw *hw, unsigned long rate,
29 unsigned long *prate)
30 {
31 struct clk_fixed_factor *fix = to_clk_fixed_factor(hw);
32
33 if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)
34 {
35 unsigned long best_parent;
36
37 best_parent = (rate / fix->mult) * fix->div;
38 *prate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent);
39 }
40
41 return (*prate / fix->div) * fix->mult;
42 }
43
clk_factor_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)44 static int clk_factor_set_rate(struct clk_hw *hw, unsigned long rate,
45 unsigned long parent_rate)
46 {
47 struct clk_fixed_factor *fix = to_clk_fixed_factor(hw);
48 /*
49 * We must report success but we can do so unconditionally because
50 * clk_factor_round_rate returns values that ensure this call is a
51 * nop.
52 */
53 if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)
54 {
55 unsigned long p_rate;
56
57 p_rate = (rate / fix->mult) * fix->div;
58 return clk_hw_set_rate(clk_hw_get_parent(hw), p_rate);
59
60 }
61
62 return 0;
63 }
64
65 const struct clk_ops clk_fixed_factor_ops =
66 {
67 .round_rate = clk_factor_round_rate,
68 .set_rate = clk_factor_set_rate,
69 .recalc_rate = clk_factor_recalc_rate,
70 };
71