]> git.karo-electronics.de Git - karo-tx-linux.git/blob - arch/blackfin/mach-bf609/clock.c
jfs: fix error path in ialloc
[karo-tx-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 unsigned long clk_get_rate(struct clk *clk)
124 {
125         unsigned long ret = 0;
126         if (clk->ops && clk->ops->get_rate)
127                 ret = clk->ops->get_rate(clk);
128         return ret;
129 }
130 EXPORT_SYMBOL(clk_get_rate);
131
132 long clk_round_rate(struct clk *clk, unsigned long rate)
133 {
134         long ret = -EIO;
135         if (clk->ops && clk->ops->round_rate)
136                 ret = clk->ops->round_rate(clk, rate);
137         return ret;
138 }
139 EXPORT_SYMBOL(clk_round_rate);
140
141 int clk_set_rate(struct clk *clk, unsigned long rate)
142 {
143         int ret = -EIO;
144         if (clk->ops && clk->ops->set_rate)
145                 ret = clk->ops->set_rate(clk, rate);
146         return ret;
147 }
148 EXPORT_SYMBOL(clk_set_rate);
149
150 unsigned long vco_get_rate(struct clk *clk)
151 {
152         return clk->rate;
153 }
154
155 unsigned long pll_get_rate(struct clk *clk)
156 {
157         u32 df;
158         u32 msel;
159         u32 ctl = bfin_read32(CGU0_CTL);
160         u32 stat = bfin_read32(CGU0_STAT);
161         if (stat & CGU0_STAT_PLLBP)
162                 return 0;
163         msel = (ctl & CGU0_CTL_MSEL_MASK) >> CGU0_CTL_MSEL_SHIFT;
164         df = (ctl &  CGU0_CTL_DF);
165         clk->parent->rate = clk_get_rate(clk->parent);
166         return clk->parent->rate / (df + 1) * msel * 2;
167 }
168
169 unsigned long pll_round_rate(struct clk *clk, unsigned long rate)
170 {
171         u32 div;
172         div = rate / clk->parent->rate;
173         return clk->parent->rate * div;
174 }
175
176 int pll_set_rate(struct clk *clk, unsigned long rate)
177 {
178         u32 msel;
179         u32 stat = bfin_read32(CGU0_STAT);
180         if (!(stat & CGU0_STAT_PLLEN))
181                 return -EBUSY;
182         if (!(stat & CGU0_STAT_PLLLK))
183                 return -EBUSY;
184         if (wait_for_pll_align())
185                 return -EBUSY;
186         msel = rate / clk->parent->rate / 2;
187         clk_reg_write_mask(CGU0_CTL, msel << CGU0_CTL_MSEL_SHIFT,
188                 CGU0_CTL_MSEL_MASK);
189         clk->rate = rate;
190         return 0;
191 }
192
193 unsigned long cclk_get_rate(struct clk *clk)
194 {
195         if (clk->parent)
196                 return clk->parent->rate;
197         else
198                 return 0;
199 }
200
201 unsigned long sys_clk_get_rate(struct clk *clk)
202 {
203         unsigned long drate;
204         u32 msel;
205         u32 df;
206         u32 ctl = bfin_read32(CGU0_CTL);
207         u32 div = bfin_read32(CGU0_DIV);
208         div = (div & clk->mask) >> clk->shift;
209         msel = (ctl & CGU0_CTL_MSEL_MASK) >> CGU0_CTL_MSEL_SHIFT;
210         df = (ctl &  CGU0_CTL_DF);
211
212         if (!strcmp(clk->parent->name, "SYS_CLKIN")) {
213                 drate = clk->parent->rate / (df + 1);
214                 drate *=  msel;
215                 drate /= div;
216                 return drate;
217         } else {
218                 clk->parent->rate = clk_get_rate(clk->parent);
219                 return clk->parent->rate / div;
220         }
221 }
222
223 unsigned long sys_clk_round_rate(struct clk *clk, unsigned long rate)
224 {
225         unsigned long max_rate;
226         unsigned long drate;
227         int i;
228         u32 msel;
229         u32 df;
230         u32 ctl = bfin_read32(CGU0_CTL);
231
232         msel = (ctl & CGU0_CTL_MSEL_MASK) >> CGU0_CTL_MSEL_SHIFT;
233         df = (ctl &  CGU0_CTL_DF);
234         max_rate = clk->parent->rate / (df + 1) * msel;
235
236         if (rate > max_rate)
237                 return 0;
238
239         for (i = 1; i < clk->mask; i++) {
240                 drate = max_rate / i;
241                 if (rate >= drate)
242                         return drate;
243         }
244         return 0;
245 }
246
247 int sys_clk_set_rate(struct clk *clk, unsigned long rate)
248 {
249         u32 div = bfin_read32(CGU0_DIV);
250         div = (div & clk->mask) >> clk->shift;
251
252         rate = clk_round_rate(clk, rate);
253
254         if (!rate)
255                 return -EINVAL;
256
257         div = (clk_get_rate(clk) * div) / rate;
258
259         if (wait_for_pll_align())
260                 return -EBUSY;
261         clk_reg_write_mask(CGU0_DIV, div << clk->shift,
262                         clk->mask);
263         clk->rate = rate;
264         return 0;
265 }
266
267 static struct clk_ops vco_ops = {
268         .get_rate = vco_get_rate,
269 };
270
271 static struct clk_ops pll_ops = {
272         .get_rate = pll_get_rate,
273         .set_rate = pll_set_rate,
274 };
275
276 static struct clk_ops cclk_ops = {
277         .get_rate = cclk_get_rate,
278 };
279
280 static struct clk_ops sys_clk_ops = {
281         .get_rate = sys_clk_get_rate,
282         .set_rate = sys_clk_set_rate,
283         .round_rate = sys_clk_round_rate,
284 };
285
286 static struct clk sys_clkin = {
287         .name       = "SYS_CLKIN",
288         .rate       = CONFIG_CLKIN_HZ,
289         .ops        = &vco_ops,
290 };
291
292 static struct clk pll_clk = {
293         .name       = "PLLCLK",
294         .rate       = 500000000,
295         .parent     = &sys_clkin,
296         .ops = &pll_ops,
297         .flags = NEEDS_INITIALIZATION,
298 };
299
300 static struct clk cclk = {
301         .name       = "CCLK",
302         .rate       = 500000000,
303         .mask       = CGU0_DIV_CSEL_MASK,
304         .shift      = CGU0_DIV_CSEL_SHIFT,
305         .parent     = &sys_clkin,
306         .ops        = &sys_clk_ops,
307         .flags = NEEDS_INITIALIZATION,
308 };
309
310 static struct clk cclk0 = {
311         .name       = "CCLK0",
312         .parent     = &cclk,
313         .ops        = &cclk_ops,
314 };
315
316 static struct clk cclk1 = {
317         .name       = "CCLK1",
318         .parent     = &cclk,
319         .ops        = &cclk_ops,
320 };
321
322 static struct clk sysclk = {
323         .name       = "SYSCLK",
324         .rate       = 500000000,
325         .mask       = CGU0_DIV_SYSSEL_MASK,
326         .shift      = CGU0_DIV_SYSSEL_SHIFT,
327         .parent     = &sys_clkin,
328         .ops        = &sys_clk_ops,
329         .flags = NEEDS_INITIALIZATION,
330 };
331
332 static struct clk sclk0 = {
333         .name       = "SCLK0",
334         .rate       = 500000000,
335         .mask       = CGU0_DIV_S0SEL_MASK,
336         .shift      = CGU0_DIV_S0SEL_SHIFT,
337         .parent     = &sysclk,
338         .ops        = &sys_clk_ops,
339 };
340
341 static struct clk sclk1 = {
342         .name       = "SCLK1",
343         .rate       = 500000000,
344         .mask       = CGU0_DIV_S1SEL_MASK,
345         .shift      = CGU0_DIV_S1SEL_SHIFT,
346         .parent     = &sysclk,
347         .ops        = &sys_clk_ops,
348 };
349
350 static struct clk dclk = {
351         .name       = "DCLK",
352         .rate       = 500000000,
353         .mask       = CGU0_DIV_DSEL_MASK,
354         .shift       = CGU0_DIV_DSEL_SHIFT,
355         .parent     = &sys_clkin,
356         .ops        = &sys_clk_ops,
357 };
358
359 static struct clk oclk = {
360         .name       = "OCLK",
361         .rate       = 500000000,
362         .mask       = CGU0_DIV_OSEL_MASK,
363         .shift      = CGU0_DIV_OSEL_SHIFT,
364         .parent     = &pll_clk,
365 };
366
367 static struct clk_lookup bf609_clks[] = {
368         CLK(sys_clkin, NULL, "SYS_CLKIN"),
369         CLK(pll_clk, NULL, "PLLCLK"),
370         CLK(cclk, NULL, "CCLK"),
371         CLK(cclk0, NULL, "CCLK0"),
372         CLK(cclk1, NULL, "CCLK1"),
373         CLK(sysclk, NULL, "SYSCLK"),
374         CLK(sclk0, NULL, "SCLK0"),
375         CLK(sclk1, NULL, "SCLK1"),
376         CLK(dclk, NULL, "DCLK"),
377         CLK(oclk, NULL, "OCLK"),
378 };
379
380 int __init clk_init(void)
381 {
382         int i;
383         struct clk *clkp;
384         for (i = 0; i < ARRAY_SIZE(bf609_clks); i++) {
385                 clkp = bf609_clks[i].clk;
386                 if (clkp->flags & NEEDS_INITIALIZATION)
387                         clk_get_rate(clkp);
388         }
389         clkdev_add_table(bf609_clks, ARRAY_SIZE(bf609_clks));
390         return 0;
391 }