Merge remote-tracking branches 'asoc/topic/cygnus', 'asoc/topic/da7213', 'asoc/topic...
[sfrench/cifs-2.6.git] / arch / blackfin / mach-bf609 / clock.c
1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/module.h>
3 #include <linux/kernel.h>
4 #include <linux/list.h>
5 #include <linux/errno.h>
6 #include <linux/err.h>
7 #include <linux/string.h>
8 #include <linux/clk.h>
9 #include <linux/mutex.h>
10 #include <linux/spinlock.h>
11 #include <linux/debugfs.h>
12 #include <linux/device.h>
13 #include <linux/init.h>
14 #include <linux/timer.h>
15 #include <linux/io.h>
16 #include <linux/seq_file.h>
17 #include <linux/clkdev.h>
18
19 #include <asm/clocks.h>
20
21 #define CGU0_CTL_DF (1 << 0)
22
23 #define CGU0_CTL_MSEL_SHIFT 8
24 #define CGU0_CTL_MSEL_MASK (0x7f << 8)
25
26 #define CGU0_STAT_PLLEN (1 << 0)
27 #define CGU0_STAT_PLLBP (1 << 1)
28 #define CGU0_STAT_PLLLK (1 << 2)
29 #define CGU0_STAT_CLKSALGN (1 << 3)
30 #define CGU0_STAT_CCBF0 (1 << 4)
31 #define CGU0_STAT_CCBF1 (1 << 5)
32 #define CGU0_STAT_SCBF0 (1 << 6)
33 #define CGU0_STAT_SCBF1 (1 << 7)
34 #define CGU0_STAT_DCBF (1 << 8)
35 #define CGU0_STAT_OCBF (1 << 9)
36 #define CGU0_STAT_ADDRERR (1 << 16)
37 #define CGU0_STAT_LWERR (1 << 17)
38 #define CGU0_STAT_DIVERR (1 << 18)
39 #define CGU0_STAT_WDFMSERR (1 << 19)
40 #define CGU0_STAT_WDIVERR (1 << 20)
41 #define CGU0_STAT_PLOCKERR (1 << 21)
42
43 #define CGU0_DIV_CSEL_SHIFT 0
44 #define CGU0_DIV_CSEL_MASK 0x0000001F
45 #define CGU0_DIV_S0SEL_SHIFT 5
46 #define CGU0_DIV_S0SEL_MASK (0x3 << CGU0_DIV_S0SEL_SHIFT)
47 #define CGU0_DIV_SYSSEL_SHIFT 8
48 #define CGU0_DIV_SYSSEL_MASK (0x1f << CGU0_DIV_SYSSEL_SHIFT)
49 #define CGU0_DIV_S1SEL_SHIFT 13
50 #define CGU0_DIV_S1SEL_MASK (0x3 << CGU0_DIV_S1SEL_SHIFT)
51 #define CGU0_DIV_DSEL_SHIFT 16
52 #define CGU0_DIV_DSEL_MASK (0x1f << CGU0_DIV_DSEL_SHIFT)
53 #define CGU0_DIV_OSEL_SHIFT 22
54 #define CGU0_DIV_OSEL_MASK (0x7f << CGU0_DIV_OSEL_SHIFT)
55
56 #define CLK(_clk, _devname, _conname)                   \
57         {                                               \
58                 .clk    = &_clk,                  \
59                 .dev_id = _devname,                     \
60                 .con_id = _conname,                     \
61         }
62
63 #define NEEDS_INITIALIZATION 0x11
64
65 static LIST_HEAD(clk_list);
66
67 static void clk_reg_write_mask(u32 reg, uint32_t val, uint32_t mask)
68 {
69         u32 val2;
70
71         val2 = bfin_read32(reg);
72         val2 &= ~mask;
73         val2 |= val;
74         bfin_write32(reg, val2);
75 }
76
77 int wait_for_pll_align(void)
78 {
79         int i = 10000;
80         while (i-- && (bfin_read32(CGU0_STAT) & CGU0_STAT_CLKSALGN));
81
82         if (bfin_read32(CGU0_STAT) & CGU0_STAT_CLKSALGN) {
83                 printk(KERN_CRIT "fail to align clk\n");
84                 return -1;
85         }
86
87         return 0;
88 }
89
90 int clk_enable(struct clk *clk)
91 {
92         int ret = -EIO;
93         if (clk->ops && clk->ops->enable)
94                 ret = clk->ops->enable(clk);
95         return ret;
96 }
97 EXPORT_SYMBOL(clk_enable);
98
99 void clk_disable(struct clk *clk)
100 {
101         if (!clk)
102                 return;
103
104         if (clk->ops && clk->ops->disable)
105                 clk->ops->disable(clk);
106 }
107 EXPORT_SYMBOL(clk_disable);
108
109
110 unsigned long clk_get_rate(struct clk *clk)
111 {
112         unsigned long ret = 0;
113         if (clk->ops && clk->ops->get_rate)
114                 ret = clk->ops->get_rate(clk);
115         return ret;
116 }
117 EXPORT_SYMBOL(clk_get_rate);
118
119 long clk_round_rate(struct clk *clk, unsigned long rate)
120 {
121         long ret = 0;
122         if (clk->ops && clk->ops->round_rate)
123                 ret = clk->ops->round_rate(clk, rate);
124         return ret;
125 }
126 EXPORT_SYMBOL(clk_round_rate);
127
128 int clk_set_rate(struct clk *clk, unsigned long rate)
129 {
130         int ret = -EIO;
131         if (clk->ops && clk->ops->set_rate)
132                 ret = clk->ops->set_rate(clk, rate);
133         return ret;
134 }
135 EXPORT_SYMBOL(clk_set_rate);
136
137 unsigned long vco_get_rate(struct clk *clk)
138 {
139         return clk->rate;
140 }
141
142 unsigned long pll_get_rate(struct clk *clk)
143 {
144         u32 df;
145         u32 msel;
146         u32 ctl = bfin_read32(CGU0_CTL);
147         u32 stat = bfin_read32(CGU0_STAT);
148         if (stat & CGU0_STAT_PLLBP)
149                 return 0;
150         msel = (ctl & CGU0_CTL_MSEL_MASK) >> CGU0_CTL_MSEL_SHIFT;
151         df = (ctl &  CGU0_CTL_DF);
152         clk->parent->rate = clk_get_rate(clk->parent);
153         return clk->parent->rate / (df + 1) * msel * 2;
154 }
155
156 unsigned long pll_round_rate(struct clk *clk, unsigned long rate)
157 {
158         u32 div;
159         div = rate / clk->parent->rate;
160         return clk->parent->rate * div;
161 }
162
163 int pll_set_rate(struct clk *clk, unsigned long rate)
164 {
165         u32 msel;
166         u32 stat = bfin_read32(CGU0_STAT);
167         if (!(stat & CGU0_STAT_PLLEN))
168                 return -EBUSY;
169         if (!(stat & CGU0_STAT_PLLLK))
170                 return -EBUSY;
171         if (wait_for_pll_align())
172                 return -EBUSY;
173         msel = rate / clk->parent->rate / 2;
174         clk_reg_write_mask(CGU0_CTL, msel << CGU0_CTL_MSEL_SHIFT,
175                 CGU0_CTL_MSEL_MASK);
176         clk->rate = rate;
177         return 0;
178 }
179
180 unsigned long cclk_get_rate(struct clk *clk)
181 {
182         if (clk->parent)
183                 return clk->parent->rate;
184         else
185                 return 0;
186 }
187
188 unsigned long sys_clk_get_rate(struct clk *clk)
189 {
190         unsigned long drate;
191         u32 msel;
192         u32 df;
193         u32 ctl = bfin_read32(CGU0_CTL);
194         u32 div = bfin_read32(CGU0_DIV);
195         div = (div & clk->mask) >> clk->shift;
196         msel = (ctl & CGU0_CTL_MSEL_MASK) >> CGU0_CTL_MSEL_SHIFT;
197         df = (ctl &  CGU0_CTL_DF);
198
199         if (!strcmp(clk->parent->name, "SYS_CLKIN")) {
200                 drate = clk->parent->rate / (df + 1);
201                 drate *=  msel;
202                 drate /= div;
203                 return drate;
204         } else {
205                 clk->parent->rate = clk_get_rate(clk->parent);
206                 return clk->parent->rate / div;
207         }
208 }
209
210 unsigned long dummy_get_rate(struct clk *clk)
211 {
212         clk->parent->rate = clk_get_rate(clk->parent);
213         return clk->parent->rate;
214 }
215
216 unsigned long sys_clk_round_rate(struct clk *clk, unsigned long rate)
217 {
218         unsigned long max_rate;
219         unsigned long drate;
220         int i;
221         u32 msel;
222         u32 df;
223         u32 ctl = bfin_read32(CGU0_CTL);
224
225         msel = (ctl & CGU0_CTL_MSEL_MASK) >> CGU0_CTL_MSEL_SHIFT;
226         df = (ctl &  CGU0_CTL_DF);
227         max_rate = clk->parent->rate / (df + 1) * msel;
228
229         if (rate > max_rate)
230                 return 0;
231
232         for (i = 1; i < clk->mask; i++) {
233                 drate = max_rate / i;
234                 if (rate >= drate)
235                         return drate;
236         }
237         return 0;
238 }
239
240 int sys_clk_set_rate(struct clk *clk, unsigned long rate)
241 {
242         u32 div = bfin_read32(CGU0_DIV);
243         div = (div & clk->mask) >> clk->shift;
244
245         rate = clk_round_rate(clk, rate);
246
247         if (!rate)
248                 return -EINVAL;
249
250         div = (clk_get_rate(clk) * div) / rate;
251
252         if (wait_for_pll_align())
253                 return -EBUSY;
254         clk_reg_write_mask(CGU0_DIV, div << clk->shift,
255                         clk->mask);
256         clk->rate = rate;
257         return 0;
258 }
259
260 static struct clk_ops vco_ops = {
261         .get_rate = vco_get_rate,
262 };
263
264 static struct clk_ops pll_ops = {
265         .get_rate = pll_get_rate,
266         .set_rate = pll_set_rate,
267 };
268
269 static struct clk_ops cclk_ops = {
270         .get_rate = cclk_get_rate,
271 };
272
273 static struct clk_ops sys_clk_ops = {
274         .get_rate = sys_clk_get_rate,
275         .set_rate = sys_clk_set_rate,
276         .round_rate = sys_clk_round_rate,
277 };
278
279 static struct clk_ops dummy_clk_ops = {
280         .get_rate = dummy_get_rate,
281 };
282
283 static struct clk sys_clkin = {
284         .name       = "SYS_CLKIN",
285         .rate       = CONFIG_CLKIN_HZ,
286         .ops        = &vco_ops,
287 };
288
289 static struct clk pll_clk = {
290         .name       = "PLLCLK",
291         .rate       = 500000000,
292         .parent     = &sys_clkin,
293         .ops = &pll_ops,
294         .flags = NEEDS_INITIALIZATION,
295 };
296
297 static struct clk cclk = {
298         .name       = "CCLK",
299         .rate       = 500000000,
300         .mask       = CGU0_DIV_CSEL_MASK,
301         .shift      = CGU0_DIV_CSEL_SHIFT,
302         .parent     = &sys_clkin,
303         .ops        = &sys_clk_ops,
304         .flags = NEEDS_INITIALIZATION,
305 };
306
307 static struct clk cclk0 = {
308         .name       = "CCLK0",
309         .parent     = &cclk,
310         .ops        = &cclk_ops,
311 };
312
313 static struct clk cclk1 = {
314         .name       = "CCLK1",
315         .parent     = &cclk,
316         .ops        = &cclk_ops,
317 };
318
319 static struct clk sysclk = {
320         .name       = "SYSCLK",
321         .rate       = 500000000,
322         .mask       = CGU0_DIV_SYSSEL_MASK,
323         .shift      = CGU0_DIV_SYSSEL_SHIFT,
324         .parent     = &sys_clkin,
325         .ops        = &sys_clk_ops,
326         .flags = NEEDS_INITIALIZATION,
327 };
328
329 static struct clk sclk0 = {
330         .name       = "SCLK0",
331         .rate       = 500000000,
332         .mask       = CGU0_DIV_S0SEL_MASK,
333         .shift      = CGU0_DIV_S0SEL_SHIFT,
334         .parent     = &sysclk,
335         .ops        = &sys_clk_ops,
336 };
337
338 static struct clk sclk1 = {
339         .name       = "SCLK1",
340         .rate       = 500000000,
341         .mask       = CGU0_DIV_S1SEL_MASK,
342         .shift      = CGU0_DIV_S1SEL_SHIFT,
343         .parent     = &sysclk,
344         .ops        = &sys_clk_ops,
345 };
346
347 static struct clk dclk = {
348         .name       = "DCLK",
349         .rate       = 500000000,
350         .mask       = CGU0_DIV_DSEL_MASK,
351         .shift       = CGU0_DIV_DSEL_SHIFT,
352         .parent     = &sys_clkin,
353         .ops        = &sys_clk_ops,
354 };
355
356 static struct clk oclk = {
357         .name       = "OCLK",
358         .rate       = 500000000,
359         .mask       = CGU0_DIV_OSEL_MASK,
360         .shift      = CGU0_DIV_OSEL_SHIFT,
361         .parent     = &pll_clk,
362 };
363
364 static struct clk ethclk = {
365         .name       = "stmmaceth",
366         .parent     = &sclk0,
367         .ops        = &dummy_clk_ops,
368 };
369
370 static struct clk ethpclk = {
371         .name       = "pclk",
372         .parent     = &sclk0,
373         .ops        = &dummy_clk_ops,
374 };
375
376 static struct clk spiclk = {
377         .name       = "spi",
378         .parent     = &sclk1,
379         .ops        = &dummy_clk_ops,
380 };
381
382 static struct clk_lookup bf609_clks[] = {
383         CLK(sys_clkin, NULL, "SYS_CLKIN"),
384         CLK(pll_clk, NULL, "PLLCLK"),
385         CLK(cclk, NULL, "CCLK"),
386         CLK(cclk0, NULL, "CCLK0"),
387         CLK(cclk1, NULL, "CCLK1"),
388         CLK(sysclk, NULL, "SYSCLK"),
389         CLK(sclk0, NULL, "SCLK0"),
390         CLK(sclk1, NULL, "SCLK1"),
391         CLK(dclk, NULL, "DCLK"),
392         CLK(oclk, NULL, "OCLK"),
393         CLK(ethclk, NULL, "stmmaceth"),
394         CLK(ethpclk, NULL, "pclk"),
395         CLK(spiclk, NULL, "spi"),
396 };
397
398 int __init clk_init(void)
399 {
400         int i;
401         struct clk *clkp;
402         for (i = 0; i < ARRAY_SIZE(bf609_clks); i++) {
403                 clkp = bf609_clks[i].clk;
404                 if (clkp->flags & NEEDS_INITIALIZATION)
405                         clk_get_rate(clkp);
406         }
407         clkdev_add_table(bf609_clks, ARRAY_SIZE(bf609_clks));
408         return 0;
409 }