Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma
[linux-2.6-microblaze.git] / drivers / clk / clk-fractional-divider.c
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 much much better result of m and n than simple
38  * saturated values.
39  */
40
41 #include <linux/clk-provider.h>
42 #include <linux/io.h>
43 #include <linux/module.h>
44 #include <linux/device.h>
45 #include <linux/slab.h>
46 #include <linux/rational.h>
47
48 #include "clk-fractional-divider.h"
49
50 static inline u32 clk_fd_readl(struct clk_fractional_divider *fd)
51 {
52         if (fd->flags & CLK_FRAC_DIVIDER_BIG_ENDIAN)
53                 return ioread32be(fd->reg);
54
55         return readl(fd->reg);
56 }
57
58 static inline void clk_fd_writel(struct clk_fractional_divider *fd, u32 val)
59 {
60         if (fd->flags & CLK_FRAC_DIVIDER_BIG_ENDIAN)
61                 iowrite32be(val, fd->reg);
62         else
63                 writel(val, fd->reg);
64 }
65
66 static unsigned long clk_fd_recalc_rate(struct clk_hw *hw,
67                                         unsigned long parent_rate)
68 {
69         struct clk_fractional_divider *fd = to_clk_fd(hw);
70         unsigned long flags = 0;
71         unsigned long m, n;
72         u32 val;
73         u64 ret;
74
75         if (fd->lock)
76                 spin_lock_irqsave(fd->lock, flags);
77         else
78                 __acquire(fd->lock);
79
80         val = clk_fd_readl(fd);
81
82         if (fd->lock)
83                 spin_unlock_irqrestore(fd->lock, flags);
84         else
85                 __release(fd->lock);
86
87         m = (val & fd->mmask) >> fd->mshift;
88         n = (val & fd->nmask) >> fd->nshift;
89
90         if (fd->flags & CLK_FRAC_DIVIDER_ZERO_BASED) {
91                 m++;
92                 n++;
93         }
94
95         if (!n || !m)
96                 return parent_rate;
97
98         ret = (u64)parent_rate * m;
99         do_div(ret, n);
100
101         return ret;
102 }
103
104 void clk_fractional_divider_general_approximation(struct clk_hw *hw,
105                                                   unsigned long rate,
106                                                   unsigned long *parent_rate,
107                                                   unsigned long *m, unsigned long *n)
108 {
109         struct clk_fractional_divider *fd = to_clk_fd(hw);
110
111         /*
112          * Get rate closer to *parent_rate to guarantee there is no overflow
113          * for m and n. In the result it will be the nearest rate left shifted
114          * by (scale - fd->nwidth) bits.
115          *
116          * For the detailed explanation see the top comment in this file.
117          */
118         if (fd->flags & CLK_FRAC_DIVIDER_POWER_OF_TWO_PS) {
119                 unsigned long scale = fls_long(*parent_rate / rate - 1);
120
121                 if (scale > fd->nwidth)
122                         rate <<= scale - fd->nwidth;
123         }
124
125         rational_best_approximation(rate, *parent_rate,
126                         GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0),
127                         m, n);
128 }
129
130 static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate,
131                               unsigned long *parent_rate)
132 {
133         struct clk_fractional_divider *fd = to_clk_fd(hw);
134         unsigned long m, n;
135         u64 ret;
136
137         if (!rate || (!clk_hw_can_set_rate_parent(hw) && rate >= *parent_rate))
138                 return *parent_rate;
139
140         if (fd->approximation)
141                 fd->approximation(hw, rate, parent_rate, &m, &n);
142         else
143                 clk_fractional_divider_general_approximation(hw, rate, parent_rate, &m, &n);
144
145         ret = (u64)*parent_rate * m;
146         do_div(ret, n);
147
148         return ret;
149 }
150
151 static int clk_fd_set_rate(struct clk_hw *hw, unsigned long rate,
152                            unsigned long parent_rate)
153 {
154         struct clk_fractional_divider *fd = to_clk_fd(hw);
155         unsigned long flags = 0;
156         unsigned long m, n;
157         u32 val;
158
159         rational_best_approximation(rate, parent_rate,
160                         GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0),
161                         &m, &n);
162
163         if (fd->flags & CLK_FRAC_DIVIDER_ZERO_BASED) {
164                 m--;
165                 n--;
166         }
167
168         if (fd->lock)
169                 spin_lock_irqsave(fd->lock, flags);
170         else
171                 __acquire(fd->lock);
172
173         val = clk_fd_readl(fd);
174         val &= ~(fd->mmask | fd->nmask);
175         val |= (m << fd->mshift) | (n << fd->nshift);
176         clk_fd_writel(fd, val);
177
178         if (fd->lock)
179                 spin_unlock_irqrestore(fd->lock, flags);
180         else
181                 __release(fd->lock);
182
183         return 0;
184 }
185
186 const struct clk_ops clk_fractional_divider_ops = {
187         .recalc_rate = clk_fd_recalc_rate,
188         .round_rate = clk_fd_round_rate,
189         .set_rate = clk_fd_set_rate,
190 };
191 EXPORT_SYMBOL_GPL(clk_fractional_divider_ops);
192
193 struct clk_hw *clk_hw_register_fractional_divider(struct device *dev,
194                 const char *name, const char *parent_name, unsigned long flags,
195                 void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth,
196                 u8 clk_divider_flags, spinlock_t *lock)
197 {
198         struct clk_fractional_divider *fd;
199         struct clk_init_data init;
200         struct clk_hw *hw;
201         int ret;
202
203         fd = kzalloc(sizeof(*fd), GFP_KERNEL);
204         if (!fd)
205                 return ERR_PTR(-ENOMEM);
206
207         init.name = name;
208         init.ops = &clk_fractional_divider_ops;
209         init.flags = flags;
210         init.parent_names = parent_name ? &parent_name : NULL;
211         init.num_parents = parent_name ? 1 : 0;
212
213         fd->reg = reg;
214         fd->mshift = mshift;
215         fd->mwidth = mwidth;
216         fd->mmask = GENMASK(mwidth - 1, 0) << mshift;
217         fd->nshift = nshift;
218         fd->nwidth = nwidth;
219         fd->nmask = GENMASK(nwidth - 1, 0) << nshift;
220         fd->flags = clk_divider_flags;
221         fd->lock = lock;
222         fd->hw.init = &init;
223
224         hw = &fd->hw;
225         ret = clk_hw_register(dev, hw);
226         if (ret) {
227                 kfree(fd);
228                 hw = ERR_PTR(ret);
229         }
230
231         return hw;
232 }
233 EXPORT_SYMBOL_GPL(clk_hw_register_fractional_divider);
234
235 struct clk *clk_register_fractional_divider(struct device *dev,
236                 const char *name, const char *parent_name, unsigned long flags,
237                 void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth,
238                 u8 clk_divider_flags, spinlock_t *lock)
239 {
240         struct clk_hw *hw;
241
242         hw = clk_hw_register_fractional_divider(dev, name, parent_name, flags,
243                         reg, mshift, mwidth, nshift, nwidth, clk_divider_flags,
244                         lock);
245         if (IS_ERR(hw))
246                 return ERR_CAST(hw);
247         return hw->clk;
248 }
249 EXPORT_SYMBOL_GPL(clk_register_fractional_divider);
250
251 void clk_hw_unregister_fractional_divider(struct clk_hw *hw)
252 {
253         struct clk_fractional_divider *fd;
254
255         fd = to_clk_fd(hw);
256
257         clk_hw_unregister(hw);
258         kfree(fd);
259 }