1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (C) 2015 Maxime Ripard <maxime.ripard@free-electrons.com>
4*4882a593Smuzhiyun */
5*4882a593Smuzhiyun
6*4882a593Smuzhiyun #include <linux/bitops.h>
7*4882a593Smuzhiyun #include <linux/clk-provider.h>
8*4882a593Smuzhiyun #include <linux/err.h>
9*4882a593Smuzhiyun #include <linux/export.h>
10*4882a593Smuzhiyun #include <linux/io.h>
11*4882a593Smuzhiyun #include <linux/kernel.h>
12*4882a593Smuzhiyun #include <linux/of.h>
13*4882a593Smuzhiyun #include <linux/slab.h>
14*4882a593Smuzhiyun
clk_mult_readl(struct clk_multiplier * mult)15*4882a593Smuzhiyun static inline u32 clk_mult_readl(struct clk_multiplier *mult)
16*4882a593Smuzhiyun {
17*4882a593Smuzhiyun if (mult->flags & CLK_MULTIPLIER_BIG_ENDIAN)
18*4882a593Smuzhiyun return ioread32be(mult->reg);
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun return readl(mult->reg);
21*4882a593Smuzhiyun }
22*4882a593Smuzhiyun
clk_mult_writel(struct clk_multiplier * mult,u32 val)23*4882a593Smuzhiyun static inline void clk_mult_writel(struct clk_multiplier *mult, u32 val)
24*4882a593Smuzhiyun {
25*4882a593Smuzhiyun if (mult->flags & CLK_MULTIPLIER_BIG_ENDIAN)
26*4882a593Smuzhiyun iowrite32be(val, mult->reg);
27*4882a593Smuzhiyun else
28*4882a593Smuzhiyun writel(val, mult->reg);
29*4882a593Smuzhiyun }
30*4882a593Smuzhiyun
__get_mult(struct clk_multiplier * mult,unsigned long rate,unsigned long parent_rate)31*4882a593Smuzhiyun static unsigned long __get_mult(struct clk_multiplier *mult,
32*4882a593Smuzhiyun unsigned long rate,
33*4882a593Smuzhiyun unsigned long parent_rate)
34*4882a593Smuzhiyun {
35*4882a593Smuzhiyun if (mult->flags & CLK_MULTIPLIER_ROUND_CLOSEST)
36*4882a593Smuzhiyun return DIV_ROUND_CLOSEST(rate, parent_rate);
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun return rate / parent_rate;
39*4882a593Smuzhiyun }
40*4882a593Smuzhiyun
clk_multiplier_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)41*4882a593Smuzhiyun static unsigned long clk_multiplier_recalc_rate(struct clk_hw *hw,
42*4882a593Smuzhiyun unsigned long parent_rate)
43*4882a593Smuzhiyun {
44*4882a593Smuzhiyun struct clk_multiplier *mult = to_clk_multiplier(hw);
45*4882a593Smuzhiyun unsigned long val;
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun val = clk_mult_readl(mult) >> mult->shift;
48*4882a593Smuzhiyun val &= GENMASK(mult->width - 1, 0);
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun if (!val && mult->flags & CLK_MULTIPLIER_ZERO_BYPASS)
51*4882a593Smuzhiyun val = 1;
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun return parent_rate * val;
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun
__is_best_rate(unsigned long rate,unsigned long new,unsigned long best,unsigned long flags)56*4882a593Smuzhiyun static bool __is_best_rate(unsigned long rate, unsigned long new,
57*4882a593Smuzhiyun unsigned long best, unsigned long flags)
58*4882a593Smuzhiyun {
59*4882a593Smuzhiyun if (flags & CLK_MULTIPLIER_ROUND_CLOSEST)
60*4882a593Smuzhiyun return abs(rate - new) < abs(rate - best);
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun return new >= rate && new < best;
63*4882a593Smuzhiyun }
64*4882a593Smuzhiyun
__bestmult(struct clk_hw * hw,unsigned long rate,unsigned long * best_parent_rate,u8 width,unsigned long flags)65*4882a593Smuzhiyun static unsigned long __bestmult(struct clk_hw *hw, unsigned long rate,
66*4882a593Smuzhiyun unsigned long *best_parent_rate,
67*4882a593Smuzhiyun u8 width, unsigned long flags)
68*4882a593Smuzhiyun {
69*4882a593Smuzhiyun struct clk_multiplier *mult = to_clk_multiplier(hw);
70*4882a593Smuzhiyun unsigned long orig_parent_rate = *best_parent_rate;
71*4882a593Smuzhiyun unsigned long parent_rate, current_rate, best_rate = ~0;
72*4882a593Smuzhiyun unsigned int i, bestmult = 0;
73*4882a593Smuzhiyun unsigned int maxmult = (1 << width) - 1;
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) {
76*4882a593Smuzhiyun bestmult = rate / orig_parent_rate;
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun /* Make sure we don't end up with a 0 multiplier */
79*4882a593Smuzhiyun if ((bestmult == 0) &&
80*4882a593Smuzhiyun !(mult->flags & CLK_MULTIPLIER_ZERO_BYPASS))
81*4882a593Smuzhiyun bestmult = 1;
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun /* Make sure we don't overflow the multiplier */
84*4882a593Smuzhiyun if (bestmult > maxmult)
85*4882a593Smuzhiyun bestmult = maxmult;
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun return bestmult;
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun for (i = 1; i < maxmult; i++) {
91*4882a593Smuzhiyun if (rate == orig_parent_rate * i) {
92*4882a593Smuzhiyun /*
93*4882a593Smuzhiyun * This is the best case for us if we have a
94*4882a593Smuzhiyun * perfect match without changing the parent
95*4882a593Smuzhiyun * rate.
96*4882a593Smuzhiyun */
97*4882a593Smuzhiyun *best_parent_rate = orig_parent_rate;
98*4882a593Smuzhiyun return i;
99*4882a593Smuzhiyun }
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
102*4882a593Smuzhiyun rate / i);
103*4882a593Smuzhiyun current_rate = parent_rate * i;
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun if (__is_best_rate(rate, current_rate, best_rate, flags)) {
106*4882a593Smuzhiyun bestmult = i;
107*4882a593Smuzhiyun best_rate = current_rate;
108*4882a593Smuzhiyun *best_parent_rate = parent_rate;
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun }
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun return bestmult;
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun
clk_multiplier_round_rate(struct clk_hw * hw,unsigned long rate,unsigned long * parent_rate)115*4882a593Smuzhiyun static long clk_multiplier_round_rate(struct clk_hw *hw, unsigned long rate,
116*4882a593Smuzhiyun unsigned long *parent_rate)
117*4882a593Smuzhiyun {
118*4882a593Smuzhiyun struct clk_multiplier *mult = to_clk_multiplier(hw);
119*4882a593Smuzhiyun unsigned long factor = __bestmult(hw, rate, parent_rate,
120*4882a593Smuzhiyun mult->width, mult->flags);
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun return *parent_rate * factor;
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun
clk_multiplier_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)125*4882a593Smuzhiyun static int clk_multiplier_set_rate(struct clk_hw *hw, unsigned long rate,
126*4882a593Smuzhiyun unsigned long parent_rate)
127*4882a593Smuzhiyun {
128*4882a593Smuzhiyun struct clk_multiplier *mult = to_clk_multiplier(hw);
129*4882a593Smuzhiyun unsigned long factor = __get_mult(mult, rate, parent_rate);
130*4882a593Smuzhiyun unsigned long flags = 0;
131*4882a593Smuzhiyun unsigned long val;
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun if (mult->lock)
134*4882a593Smuzhiyun spin_lock_irqsave(mult->lock, flags);
135*4882a593Smuzhiyun else
136*4882a593Smuzhiyun __acquire(mult->lock);
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun val = clk_mult_readl(mult);
139*4882a593Smuzhiyun val &= ~GENMASK(mult->width + mult->shift - 1, mult->shift);
140*4882a593Smuzhiyun val |= factor << mult->shift;
141*4882a593Smuzhiyun clk_mult_writel(mult, val);
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun if (mult->lock)
144*4882a593Smuzhiyun spin_unlock_irqrestore(mult->lock, flags);
145*4882a593Smuzhiyun else
146*4882a593Smuzhiyun __release(mult->lock);
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun return 0;
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun const struct clk_ops clk_multiplier_ops = {
152*4882a593Smuzhiyun .recalc_rate = clk_multiplier_recalc_rate,
153*4882a593Smuzhiyun .round_rate = clk_multiplier_round_rate,
154*4882a593Smuzhiyun .set_rate = clk_multiplier_set_rate,
155*4882a593Smuzhiyun };
156*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(clk_multiplier_ops);
157