1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright (C) 2014 Intel Corporation |
4 | * |
5 | * Adjustable fractional divider clock implementation. |
6 | * Uses rational best approximation algorithm. |
7 | * |
8 | * Output is calculated as |
9 | * |
10 | * rate = (m / n) * parent_rate (1) |
11 | * |
12 | * This is useful when we have a prescaler block which asks for |
13 | * m (numerator) and n (denominator) values to be provided to satisfy |
14 | * the (1) as much as possible. |
15 | * |
16 | * Since m and n have the limitation by a range, e.g. |
17 | * |
18 | * n >= 1, n < N_width, where N_width = 2^nwidth (2) |
19 | * |
20 | * for some cases the output may be saturated. Hence, from (1) and (2), |
21 | * assuming the worst case when m = 1, the inequality |
22 | * |
23 | * floor(log2(parent_rate / rate)) <= nwidth (3) |
24 | * |
25 | * may be derived. Thus, in cases when |
26 | * |
27 | * (parent_rate / rate) >> N_width (4) |
28 | * |
29 | * we might scale up the rate by 2^scale (see the description of |
30 | * CLK_FRAC_DIVIDER_POWER_OF_TWO_PS for additional information), where |
31 | * |
32 | * scale = floor(log2(parent_rate / rate)) - nwidth (5) |
33 | * |
34 | * and assume that the IP, that needs m and n, has also its own |
35 | * prescaler, which is capable to divide by 2^scale. In this way |
36 | * we get the denominator to satisfy the desired range (2) and |
37 | * at the same time a much better result of m and n than simple |
38 | * saturated values. |
39 | */ |
40 | |
41 | #include <linux/debugfs.h> |
42 | #include <linux/device.h> |
43 | #include <linux/io.h> |
44 | #include <linux/math.h> |
45 | #include <linux/module.h> |
46 | #include <linux/rational.h> |
47 | #include <linux/slab.h> |
48 | |
49 | #include <linux/clk-provider.h> |
50 | |
51 | #include "clk-fractional-divider.h" |
52 | |
53 | static inline u32 clk_fd_readl(struct clk_fractional_divider *fd) |
54 | { |
55 | if (fd->flags & CLK_FRAC_DIVIDER_BIG_ENDIAN) |
56 | return ioread32be(fd->reg); |
57 | |
58 | return readl(addr: fd->reg); |
59 | } |
60 | |
61 | static inline void clk_fd_writel(struct clk_fractional_divider *fd, u32 val) |
62 | { |
63 | if (fd->flags & CLK_FRAC_DIVIDER_BIG_ENDIAN) |
64 | iowrite32be(val, fd->reg); |
65 | else |
66 | writel(val, addr: fd->reg); |
67 | } |
68 | |
69 | static void clk_fd_get_div(struct clk_hw *hw, struct u32_fract *fract) |
70 | { |
71 | struct clk_fractional_divider *fd = to_clk_fd(hw); |
72 | unsigned long flags = 0; |
73 | unsigned long m, n; |
74 | u32 mmask, nmask; |
75 | u32 val; |
76 | |
77 | if (fd->lock) |
78 | spin_lock_irqsave(fd->lock, flags); |
79 | else |
80 | __acquire(fd->lock); |
81 | |
82 | val = clk_fd_readl(fd); |
83 | |
84 | if (fd->lock) |
85 | spin_unlock_irqrestore(lock: fd->lock, flags); |
86 | else |
87 | __release(fd->lock); |
88 | |
89 | mmask = GENMASK(fd->mwidth - 1, 0) << fd->mshift; |
90 | nmask = GENMASK(fd->nwidth - 1, 0) << fd->nshift; |
91 | |
92 | m = (val & mmask) >> fd->mshift; |
93 | n = (val & nmask) >> fd->nshift; |
94 | |
95 | if (fd->flags & CLK_FRAC_DIVIDER_ZERO_BASED) { |
96 | m++; |
97 | n++; |
98 | } |
99 | |
100 | fract->numerator = m; |
101 | fract->denominator = n; |
102 | } |
103 | |
104 | static unsigned long clk_fd_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) |
105 | { |
106 | struct u32_fract fract; |
107 | u64 ret; |
108 | |
109 | clk_fd_get_div(hw, fract: &fract); |
110 | |
111 | if (!fract.numerator || !fract.denominator) |
112 | return parent_rate; |
113 | |
114 | ret = (u64)parent_rate * fract.numerator; |
115 | do_div(ret, fract.denominator); |
116 | |
117 | return ret; |
118 | } |
119 | |
120 | void clk_fractional_divider_general_approximation(struct clk_hw *hw, |
121 | unsigned long rate, |
122 | unsigned long *parent_rate, |
123 | unsigned long *m, unsigned long *n) |
124 | { |
125 | struct clk_fractional_divider *fd = to_clk_fd(hw); |
126 | unsigned long max_m, max_n; |
127 | |
128 | /* |
129 | * Get rate closer to *parent_rate to guarantee there is no overflow |
130 | * for m and n. In the result it will be the nearest rate left shifted |
131 | * by (scale - fd->nwidth) bits. |
132 | * |
133 | * For the detailed explanation see the top comment in this file. |
134 | */ |
135 | if (fd->flags & CLK_FRAC_DIVIDER_POWER_OF_TWO_PS) { |
136 | unsigned long scale = fls_long(l: *parent_rate / rate - 1); |
137 | |
138 | if (scale > fd->nwidth) |
139 | rate <<= scale - fd->nwidth; |
140 | } |
141 | |
142 | if (fd->flags & CLK_FRAC_DIVIDER_ZERO_BASED) { |
143 | max_m = 1 << fd->mwidth; |
144 | max_n = 1 << fd->nwidth; |
145 | } else { |
146 | max_m = GENMASK(fd->mwidth - 1, 0); |
147 | max_n = GENMASK(fd->nwidth - 1, 0); |
148 | } |
149 | |
150 | rational_best_approximation(given_numerator: rate, given_denominator: *parent_rate, max_numerator: max_m, max_denominator: max_n, best_numerator: m, best_denominator: n); |
151 | } |
152 | EXPORT_SYMBOL_GPL(clk_fractional_divider_general_approximation); |
153 | |
154 | static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate, |
155 | unsigned long *parent_rate) |
156 | { |
157 | struct clk_fractional_divider *fd = to_clk_fd(hw); |
158 | unsigned long m, n; |
159 | u64 ret; |
160 | |
161 | if (!rate || (!clk_hw_can_set_rate_parent(hw) && rate >= *parent_rate)) |
162 | return *parent_rate; |
163 | |
164 | if (fd->approximation) |
165 | fd->approximation(hw, rate, parent_rate, &m, &n); |
166 | else |
167 | clk_fractional_divider_general_approximation(hw, rate, parent_rate, &m, &n); |
168 | |
169 | ret = (u64)*parent_rate * m; |
170 | do_div(ret, n); |
171 | |
172 | return ret; |
173 | } |
174 | |
175 | static int clk_fd_set_rate(struct clk_hw *hw, unsigned long rate, |
176 | unsigned long parent_rate) |
177 | { |
178 | struct clk_fractional_divider *fd = to_clk_fd(hw); |
179 | unsigned long flags = 0; |
180 | unsigned long m, n, max_m, max_n; |
181 | u32 mmask, nmask; |
182 | u32 val; |
183 | |
184 | if (fd->flags & CLK_FRAC_DIVIDER_ZERO_BASED) { |
185 | max_m = 1 << fd->mwidth; |
186 | max_n = 1 << fd->nwidth; |
187 | } else { |
188 | max_m = GENMASK(fd->mwidth - 1, 0); |
189 | max_n = GENMASK(fd->nwidth - 1, 0); |
190 | } |
191 | rational_best_approximation(given_numerator: rate, given_denominator: parent_rate, max_numerator: max_m, max_denominator: max_n, best_numerator: &m, best_denominator: &n); |
192 | |
193 | if (fd->flags & CLK_FRAC_DIVIDER_ZERO_BASED) { |
194 | m--; |
195 | n--; |
196 | } |
197 | |
198 | if (fd->lock) |
199 | spin_lock_irqsave(fd->lock, flags); |
200 | else |
201 | __acquire(fd->lock); |
202 | |
203 | mmask = GENMASK(fd->mwidth - 1, 0) << fd->mshift; |
204 | nmask = GENMASK(fd->nwidth - 1, 0) << fd->nshift; |
205 | |
206 | val = clk_fd_readl(fd); |
207 | val &= ~(mmask | nmask); |
208 | val |= (m << fd->mshift) | (n << fd->nshift); |
209 | clk_fd_writel(fd, val); |
210 | |
211 | if (fd->lock) |
212 | spin_unlock_irqrestore(lock: fd->lock, flags); |
213 | else |
214 | __release(fd->lock); |
215 | |
216 | return 0; |
217 | } |
218 | |
219 | #ifdef CONFIG_DEBUG_FS |
220 | static int clk_fd_numerator_get(void *hw, u64 *val) |
221 | { |
222 | struct u32_fract fract; |
223 | |
224 | clk_fd_get_div(hw, fract: &fract); |
225 | |
226 | *val = fract.numerator; |
227 | |
228 | return 0; |
229 | } |
230 | DEFINE_DEBUGFS_ATTRIBUTE(clk_fd_numerator_fops, clk_fd_numerator_get, NULL, "%llu\n" ); |
231 | |
232 | static int clk_fd_denominator_get(void *hw, u64 *val) |
233 | { |
234 | struct u32_fract fract; |
235 | |
236 | clk_fd_get_div(hw, fract: &fract); |
237 | |
238 | *val = fract.denominator; |
239 | |
240 | return 0; |
241 | } |
242 | DEFINE_DEBUGFS_ATTRIBUTE(clk_fd_denominator_fops, clk_fd_denominator_get, NULL, "%llu\n" ); |
243 | |
244 | static void clk_fd_debug_init(struct clk_hw *hw, struct dentry *dentry) |
245 | { |
246 | debugfs_create_file(name: "numerator" , mode: 0444, parent: dentry, data: hw, fops: &clk_fd_numerator_fops); |
247 | debugfs_create_file(name: "denominator" , mode: 0444, parent: dentry, data: hw, fops: &clk_fd_denominator_fops); |
248 | } |
249 | #endif |
250 | |
251 | const struct clk_ops clk_fractional_divider_ops = { |
252 | .recalc_rate = clk_fd_recalc_rate, |
253 | .round_rate = clk_fd_round_rate, |
254 | .set_rate = clk_fd_set_rate, |
255 | #ifdef CONFIG_DEBUG_FS |
256 | .debug_init = clk_fd_debug_init, |
257 | #endif |
258 | }; |
259 | EXPORT_SYMBOL_GPL(clk_fractional_divider_ops); |
260 | |
261 | struct clk_hw *clk_hw_register_fractional_divider(struct device *dev, |
262 | const char *name, const char *parent_name, unsigned long flags, |
263 | void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth, |
264 | u8 clk_divider_flags, spinlock_t *lock) |
265 | { |
266 | struct clk_fractional_divider *fd; |
267 | struct clk_init_data init; |
268 | struct clk_hw *hw; |
269 | int ret; |
270 | |
271 | fd = kzalloc(size: sizeof(*fd), GFP_KERNEL); |
272 | if (!fd) |
273 | return ERR_PTR(error: -ENOMEM); |
274 | |
275 | init.name = name; |
276 | init.ops = &clk_fractional_divider_ops; |
277 | init.flags = flags; |
278 | init.parent_names = parent_name ? &parent_name : NULL; |
279 | init.num_parents = parent_name ? 1 : 0; |
280 | |
281 | fd->reg = reg; |
282 | fd->mshift = mshift; |
283 | fd->mwidth = mwidth; |
284 | fd->nshift = nshift; |
285 | fd->nwidth = nwidth; |
286 | fd->flags = clk_divider_flags; |
287 | fd->lock = lock; |
288 | fd->hw.init = &init; |
289 | |
290 | hw = &fd->hw; |
291 | ret = clk_hw_register(dev, hw); |
292 | if (ret) { |
293 | kfree(objp: fd); |
294 | hw = ERR_PTR(error: ret); |
295 | } |
296 | |
297 | return hw; |
298 | } |
299 | EXPORT_SYMBOL_GPL(clk_hw_register_fractional_divider); |
300 | |
301 | struct clk *clk_register_fractional_divider(struct device *dev, |
302 | const char *name, const char *parent_name, unsigned long flags, |
303 | void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth, |
304 | u8 clk_divider_flags, spinlock_t *lock) |
305 | { |
306 | struct clk_hw *hw; |
307 | |
308 | hw = clk_hw_register_fractional_divider(dev, name, parent_name, flags, |
309 | reg, mshift, mwidth, nshift, nwidth, clk_divider_flags, |
310 | lock); |
311 | if (IS_ERR(ptr: hw)) |
312 | return ERR_CAST(ptr: hw); |
313 | return hw->clk; |
314 | } |
315 | EXPORT_SYMBOL_GPL(clk_register_fractional_divider); |
316 | |
317 | void clk_hw_unregister_fractional_divider(struct clk_hw *hw) |
318 | { |
319 | struct clk_fractional_divider *fd; |
320 | |
321 | fd = to_clk_fd(hw); |
322 | |
323 | clk_hw_unregister(hw); |
324 | kfree(objp: fd); |
325 | } |
326 | |