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