xref: /linux/drivers/clk/clk-divider.c (revision 26b0d14106954ae46d2f4f7eec3481828a210f7d)
1 /*
2  * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
3  * Copyright (C) 2011 Richard Zhao, Linaro <richard.zhao@linaro.org>
4  * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * Adjustable divider clock implementation
11  */
12 
13 #include <linux/clk-provider.h>
14 #include <linux/module.h>
15 #include <linux/slab.h>
16 #include <linux/io.h>
17 #include <linux/err.h>
18 #include <linux/string.h>
19 
20 /*
21  * DOC: basic adjustable divider clock that cannot gate
22  *
23  * Traits of this clock:
24  * prepare - clk_prepare only ensures that parents are prepared
25  * enable - clk_enable only ensures that parents are enabled
26  * rate - rate is adjustable.  clk->rate = parent->rate / divisor
27  * parent - fixed parent.  No clk_set_parent support
28  */
29 
30 #define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
31 
32 #define div_mask(d)	((1 << (d->width)) - 1)
33 
34 static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
35 		unsigned long parent_rate)
36 {
37 	struct clk_divider *divider = to_clk_divider(hw);
38 	unsigned int div;
39 
40 	div = readl(divider->reg) >> divider->shift;
41 	div &= div_mask(divider);
42 
43 	if (!(divider->flags & CLK_DIVIDER_ONE_BASED))
44 		div++;
45 
46 	return parent_rate / div;
47 }
48 
49 /*
50  * The reverse of DIV_ROUND_UP: The maximum number which
51  * divided by m is r
52  */
53 #define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1)
54 
55 static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
56 		unsigned long *best_parent_rate)
57 {
58 	struct clk_divider *divider = to_clk_divider(hw);
59 	int i, bestdiv = 0;
60 	unsigned long parent_rate, best = 0, now, maxdiv;
61 
62 	if (!rate)
63 		rate = 1;
64 
65 	maxdiv = (1 << divider->width);
66 
67 	if (divider->flags & CLK_DIVIDER_ONE_BASED)
68 		maxdiv--;
69 
70 	if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
71 		parent_rate = *best_parent_rate;
72 		bestdiv = DIV_ROUND_UP(parent_rate, rate);
73 		bestdiv = bestdiv == 0 ? 1 : bestdiv;
74 		bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv;
75 		return bestdiv;
76 	}
77 
78 	/*
79 	 * The maximum divider we can use without overflowing
80 	 * unsigned long in rate * i below
81 	 */
82 	maxdiv = min(ULONG_MAX / rate, maxdiv);
83 
84 	for (i = 1; i <= maxdiv; i++) {
85 		parent_rate = __clk_round_rate(__clk_get_parent(hw->clk),
86 				MULT_ROUND_UP(rate, i));
87 		now = parent_rate / i;
88 		if (now <= rate && now > best) {
89 			bestdiv = i;
90 			best = now;
91 			*best_parent_rate = parent_rate;
92 		}
93 	}
94 
95 	if (!bestdiv) {
96 		bestdiv = (1 << divider->width);
97 		if (divider->flags & CLK_DIVIDER_ONE_BASED)
98 			bestdiv--;
99 		*best_parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), 1);
100 	}
101 
102 	return bestdiv;
103 }
104 
105 static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
106 				unsigned long *prate)
107 {
108 	int div;
109 	div = clk_divider_bestdiv(hw, rate, prate);
110 
111 	return *prate / div;
112 }
113 
114 static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
115 				unsigned long parent_rate)
116 {
117 	struct clk_divider *divider = to_clk_divider(hw);
118 	unsigned int div;
119 	unsigned long flags = 0;
120 	u32 val;
121 
122 	div = parent_rate / rate;
123 
124 	if (!(divider->flags & CLK_DIVIDER_ONE_BASED))
125 		div--;
126 
127 	if (div > div_mask(divider))
128 		div = div_mask(divider);
129 
130 	if (divider->lock)
131 		spin_lock_irqsave(divider->lock, flags);
132 
133 	val = readl(divider->reg);
134 	val &= ~(div_mask(divider) << divider->shift);
135 	val |= div << divider->shift;
136 	writel(val, divider->reg);
137 
138 	if (divider->lock)
139 		spin_unlock_irqrestore(divider->lock, flags);
140 
141 	return 0;
142 }
143 
144 const struct clk_ops clk_divider_ops = {
145 	.recalc_rate = clk_divider_recalc_rate,
146 	.round_rate = clk_divider_round_rate,
147 	.set_rate = clk_divider_set_rate,
148 };
149 EXPORT_SYMBOL_GPL(clk_divider_ops);
150 
151 /**
152  * clk_register_divider - register a divider clock with the clock framework
153  * @dev: device registering this clock
154  * @name: name of this clock
155  * @parent_name: name of clock's parent
156  * @flags: framework-specific flags
157  * @reg: register address to adjust divider
158  * @shift: number of bits to shift the bitfield
159  * @width: width of the bitfield
160  * @clk_divider_flags: divider-specific flags for this clock
161  * @lock: shared register lock for this clock
162  */
163 struct clk *clk_register_divider(struct device *dev, const char *name,
164 		const char *parent_name, unsigned long flags,
165 		void __iomem *reg, u8 shift, u8 width,
166 		u8 clk_divider_flags, spinlock_t *lock)
167 {
168 	struct clk_divider *div;
169 	struct clk *clk;
170 	struct clk_init_data init;
171 
172 	/* allocate the divider */
173 	div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
174 	if (!div) {
175 		pr_err("%s: could not allocate divider clk\n", __func__);
176 		return ERR_PTR(-ENOMEM);
177 	}
178 
179 	init.name = name;
180 	init.ops = &clk_divider_ops;
181 	init.flags = flags;
182 	init.parent_names = (parent_name ? &parent_name: NULL);
183 	init.num_parents = (parent_name ? 1 : 0);
184 
185 	/* struct clk_divider assignments */
186 	div->reg = reg;
187 	div->shift = shift;
188 	div->width = width;
189 	div->flags = clk_divider_flags;
190 	div->lock = lock;
191 	div->hw.init = &init;
192 
193 	/* register the clock */
194 	clk = clk_register(dev, &div->hw);
195 
196 	if (IS_ERR(clk))
197 		kfree(div);
198 
199 	return clk;
200 }
201