xref: /openbmc/linux/drivers/clk/clk-multiplier.c (revision c39f2d9db0fd81ea20bb5cce9b3f082ca63753e2)
1e1bd55e5SStephen Boyd // SPDX-License-Identifier: GPL-2.0
2f2e0a532SMaxime Ripard /*
3f2e0a532SMaxime Ripard  * Copyright (C) 2015 Maxime Ripard <maxime.ripard@free-electrons.com>
4f2e0a532SMaxime Ripard  */
5f2e0a532SMaxime Ripard 
6f2e0a532SMaxime Ripard #include <linux/bitops.h>
7f2e0a532SMaxime Ripard #include <linux/clk-provider.h>
8f2e0a532SMaxime Ripard #include <linux/err.h>
9f2e0a532SMaxime Ripard #include <linux/export.h>
10*62e59c4eSStephen Boyd #include <linux/io.h>
11f2e0a532SMaxime Ripard #include <linux/kernel.h>
12f2e0a532SMaxime Ripard #include <linux/of.h>
13f2e0a532SMaxime Ripard #include <linux/slab.h>
14f2e0a532SMaxime Ripard 
clk_mult_readl(struct clk_multiplier * mult)159427b71aSJonas Gorski static inline u32 clk_mult_readl(struct clk_multiplier *mult)
169427b71aSJonas Gorski {
179427b71aSJonas Gorski 	if (mult->flags & CLK_MULTIPLIER_BIG_ENDIAN)
189427b71aSJonas Gorski 		return ioread32be(mult->reg);
199427b71aSJonas Gorski 
205834fd75SJonas Gorski 	return readl(mult->reg);
219427b71aSJonas Gorski }
229427b71aSJonas Gorski 
clk_mult_writel(struct clk_multiplier * mult,u32 val)239427b71aSJonas Gorski static inline void clk_mult_writel(struct clk_multiplier *mult, u32 val)
249427b71aSJonas Gorski {
259427b71aSJonas Gorski 	if (mult->flags & CLK_MULTIPLIER_BIG_ENDIAN)
269427b71aSJonas Gorski 		iowrite32be(val, mult->reg);
279427b71aSJonas Gorski 	else
285834fd75SJonas Gorski 		writel(val, mult->reg);
299427b71aSJonas Gorski }
309427b71aSJonas Gorski 
__get_mult(struct clk_multiplier * mult,unsigned long rate,unsigned long parent_rate)31f2e0a532SMaxime Ripard static unsigned long __get_mult(struct clk_multiplier *mult,
32f2e0a532SMaxime Ripard 				unsigned long rate,
33f2e0a532SMaxime Ripard 				unsigned long parent_rate)
34f2e0a532SMaxime Ripard {
35f2e0a532SMaxime Ripard 	if (mult->flags & CLK_MULTIPLIER_ROUND_CLOSEST)
36f2e0a532SMaxime Ripard 		return DIV_ROUND_CLOSEST(rate, parent_rate);
37f2e0a532SMaxime Ripard 
38f2e0a532SMaxime Ripard 	return rate / parent_rate;
39f2e0a532SMaxime Ripard }
40f2e0a532SMaxime Ripard 
clk_multiplier_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)41f2e0a532SMaxime Ripard static unsigned long clk_multiplier_recalc_rate(struct clk_hw *hw,
42f2e0a532SMaxime Ripard 						unsigned long parent_rate)
43f2e0a532SMaxime Ripard {
44f2e0a532SMaxime Ripard 	struct clk_multiplier *mult = to_clk_multiplier(hw);
45f2e0a532SMaxime Ripard 	unsigned long val;
46f2e0a532SMaxime Ripard 
479427b71aSJonas Gorski 	val = clk_mult_readl(mult) >> mult->shift;
48f2e0a532SMaxime Ripard 	val &= GENMASK(mult->width - 1, 0);
49f2e0a532SMaxime Ripard 
50f2e0a532SMaxime Ripard 	if (!val && mult->flags & CLK_MULTIPLIER_ZERO_BYPASS)
51f2e0a532SMaxime Ripard 		val = 1;
52f2e0a532SMaxime Ripard 
53f2e0a532SMaxime Ripard 	return parent_rate * val;
54f2e0a532SMaxime Ripard }
55f2e0a532SMaxime Ripard 
__is_best_rate(unsigned long rate,unsigned long new,unsigned long best,unsigned long flags)56f2e0a532SMaxime Ripard static bool __is_best_rate(unsigned long rate, unsigned long new,
57f2e0a532SMaxime Ripard 			   unsigned long best, unsigned long flags)
58f2e0a532SMaxime Ripard {
59f2e0a532SMaxime Ripard 	if (flags & CLK_MULTIPLIER_ROUND_CLOSEST)
60f2e0a532SMaxime Ripard 		return abs(rate - new) < abs(rate - best);
61f2e0a532SMaxime Ripard 
62f2e0a532SMaxime Ripard 	return new >= rate && new < best;
63f2e0a532SMaxime Ripard }
64f2e0a532SMaxime Ripard 
__bestmult(struct clk_hw * hw,unsigned long rate,unsigned long * best_parent_rate,u8 width,unsigned long flags)65f2e0a532SMaxime Ripard static unsigned long __bestmult(struct clk_hw *hw, unsigned long rate,
66f2e0a532SMaxime Ripard 				unsigned long *best_parent_rate,
67f2e0a532SMaxime Ripard 				u8 width, unsigned long flags)
68f2e0a532SMaxime Ripard {
6925f77a3aSMaxime Ripard 	struct clk_multiplier *mult = to_clk_multiplier(hw);
70f2e0a532SMaxime Ripard 	unsigned long orig_parent_rate = *best_parent_rate;
71f2e0a532SMaxime Ripard 	unsigned long parent_rate, current_rate, best_rate = ~0;
72f2e0a532SMaxime Ripard 	unsigned int i, bestmult = 0;
7325f77a3aSMaxime Ripard 	unsigned int maxmult = (1 << width) - 1;
74f2e0a532SMaxime Ripard 
7525f77a3aSMaxime Ripard 	if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) {
7625f77a3aSMaxime Ripard 		bestmult = rate / orig_parent_rate;
77f2e0a532SMaxime Ripard 
7825f77a3aSMaxime Ripard 		/* Make sure we don't end up with a 0 multiplier */
7925f77a3aSMaxime Ripard 		if ((bestmult == 0) &&
8025f77a3aSMaxime Ripard 		    !(mult->flags & CLK_MULTIPLIER_ZERO_BYPASS))
8125f77a3aSMaxime Ripard 			bestmult = 1;
8225f77a3aSMaxime Ripard 
8325f77a3aSMaxime Ripard 		/* Make sure we don't overflow the multiplier */
8425f77a3aSMaxime Ripard 		if (bestmult > maxmult)
8525f77a3aSMaxime Ripard 			bestmult = maxmult;
8625f77a3aSMaxime Ripard 
8725f77a3aSMaxime Ripard 		return bestmult;
8825f77a3aSMaxime Ripard 	}
8925f77a3aSMaxime Ripard 
9025f77a3aSMaxime Ripard 	for (i = 1; i < maxmult; i++) {
91f2e0a532SMaxime Ripard 		if (rate == orig_parent_rate * i) {
92f2e0a532SMaxime Ripard 			/*
93f2e0a532SMaxime Ripard 			 * This is the best case for us if we have a
94f2e0a532SMaxime Ripard 			 * perfect match without changing the parent
95f2e0a532SMaxime Ripard 			 * rate.
96f2e0a532SMaxime Ripard 			 */
97f2e0a532SMaxime Ripard 			*best_parent_rate = orig_parent_rate;
98f2e0a532SMaxime Ripard 			return i;
99f2e0a532SMaxime Ripard 		}
100f2e0a532SMaxime Ripard 
101f2e0a532SMaxime Ripard 		parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
102f2e0a532SMaxime Ripard 						rate / i);
103f2e0a532SMaxime Ripard 		current_rate = parent_rate * i;
104f2e0a532SMaxime Ripard 
105f2e0a532SMaxime Ripard 		if (__is_best_rate(rate, current_rate, best_rate, flags)) {
106f2e0a532SMaxime Ripard 			bestmult = i;
107f2e0a532SMaxime Ripard 			best_rate = current_rate;
108f2e0a532SMaxime Ripard 			*best_parent_rate = parent_rate;
109f2e0a532SMaxime Ripard 		}
110f2e0a532SMaxime Ripard 	}
111f2e0a532SMaxime Ripard 
112f2e0a532SMaxime Ripard 	return bestmult;
113f2e0a532SMaxime Ripard }
114f2e0a532SMaxime Ripard 
clk_multiplier_round_rate(struct clk_hw * hw,unsigned long rate,unsigned long * parent_rate)115f2e0a532SMaxime Ripard static long clk_multiplier_round_rate(struct clk_hw *hw, unsigned long rate,
116f2e0a532SMaxime Ripard 				  unsigned long *parent_rate)
117f2e0a532SMaxime Ripard {
118f2e0a532SMaxime Ripard 	struct clk_multiplier *mult = to_clk_multiplier(hw);
119f2e0a532SMaxime Ripard 	unsigned long factor = __bestmult(hw, rate, parent_rate,
120f2e0a532SMaxime Ripard 					  mult->width, mult->flags);
121f2e0a532SMaxime Ripard 
122f2e0a532SMaxime Ripard 	return *parent_rate * factor;
123f2e0a532SMaxime Ripard }
124f2e0a532SMaxime Ripard 
clk_multiplier_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)125f2e0a532SMaxime Ripard static int clk_multiplier_set_rate(struct clk_hw *hw, unsigned long rate,
126f2e0a532SMaxime Ripard 			       unsigned long parent_rate)
127f2e0a532SMaxime Ripard {
128f2e0a532SMaxime Ripard 	struct clk_multiplier *mult = to_clk_multiplier(hw);
129f2e0a532SMaxime Ripard 	unsigned long factor = __get_mult(mult, rate, parent_rate);
130f2e0a532SMaxime Ripard 	unsigned long flags = 0;
131f2e0a532SMaxime Ripard 	unsigned long val;
132f2e0a532SMaxime Ripard 
133f2e0a532SMaxime Ripard 	if (mult->lock)
134f2e0a532SMaxime Ripard 		spin_lock_irqsave(mult->lock, flags);
135f2e0a532SMaxime Ripard 	else
136f2e0a532SMaxime Ripard 		__acquire(mult->lock);
137f2e0a532SMaxime Ripard 
1389427b71aSJonas Gorski 	val = clk_mult_readl(mult);
139f2e0a532SMaxime Ripard 	val &= ~GENMASK(mult->width + mult->shift - 1, mult->shift);
140f2e0a532SMaxime Ripard 	val |= factor << mult->shift;
1419427b71aSJonas Gorski 	clk_mult_writel(mult, val);
142f2e0a532SMaxime Ripard 
143f2e0a532SMaxime Ripard 	if (mult->lock)
144f2e0a532SMaxime Ripard 		spin_unlock_irqrestore(mult->lock, flags);
145f2e0a532SMaxime Ripard 	else
146f2e0a532SMaxime Ripard 		__release(mult->lock);
147f2e0a532SMaxime Ripard 
148f2e0a532SMaxime Ripard 	return 0;
149f2e0a532SMaxime Ripard }
150f2e0a532SMaxime Ripard 
151f2e0a532SMaxime Ripard const struct clk_ops clk_multiplier_ops = {
152f2e0a532SMaxime Ripard 	.recalc_rate	= clk_multiplier_recalc_rate,
153f2e0a532SMaxime Ripard 	.round_rate	= clk_multiplier_round_rate,
154f2e0a532SMaxime Ripard 	.set_rate	= clk_multiplier_set_rate,
155f2e0a532SMaxime Ripard };
156f2e0a532SMaxime Ripard EXPORT_SYMBOL_GPL(clk_multiplier_ops);
157