1 #include <linux/module.h>
2 #include <linux/kernel.h>
3 #include <linux/list.h>
4 #include <linux/errno.h>
6 #include <linux/string.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>
15 #include <linux/seq_file.h>
16 #include <linux/clkdev.h>
18 #include <asm/clocks.h>
20 #define CGU0_CTL_DF (1 << 0)
22 #define CGU0_CTL_MSEL_SHIFT 8
23 #define CGU0_CTL_MSEL_MASK (0x7f << 8)
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)
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)
55 #define CLK(_clk, _devname, _conname) \
62 #define NEEDS_INITIALIZATION 0x11
64 static LIST_HEAD(clk_list);
66 static void clk_reg_write_mask(u32 reg, uint32_t val, uint32_t mask)
70 val2 = bfin_read32(reg);
73 bfin_write32(reg, val2);
76 static void clk_reg_set_bits(u32 reg, uint32_t mask)
80 val = bfin_read32(reg);
82 bfin_write32(reg, val);
85 static void clk_reg_clear_bits(u32 reg, uint32_t mask)
89 val = bfin_read32(reg);
91 bfin_write32(reg, val);
94 int wait_for_pll_align(void)
97 while (i-- && (bfin_read32(CGU0_STAT) & CGU0_STAT_CLKSALGN));
99 if (bfin_read32(CGU0_STAT) & CGU0_STAT_CLKSALGN) {
100 printk(KERN_DEBUG "fail to align clk\n");
106 int clk_enable(struct clk *clk)
109 if (clk->ops && clk->ops->enable)
110 ret = clk->ops->enable(clk);
113 EXPORT_SYMBOL(clk_enable);
115 void clk_disable(struct clk *clk)
117 if (clk->ops && clk->ops->disable)
118 clk->ops->disable(clk);
120 EXPORT_SYMBOL(clk_disable);
122 unsigned long clk_get_rate(struct clk *clk)
124 unsigned long ret = 0;
125 if (clk->ops && clk->ops->get_rate)
126 ret = clk->ops->get_rate(clk);
129 EXPORT_SYMBOL(clk_get_rate);
131 long clk_round_rate(struct clk *clk, unsigned long rate)
134 if (clk->ops && clk->ops->round_rate)
135 ret = clk->ops->round_rate(clk, rate);
138 EXPORT_SYMBOL(clk_round_rate);
140 int clk_set_rate(struct clk *clk, unsigned long rate)
143 if (clk->ops && clk->ops->set_rate)
144 ret = clk->ops->set_rate(clk, rate);
147 EXPORT_SYMBOL(clk_set_rate);
149 unsigned long vco_get_rate(struct clk *clk)
154 unsigned long pll_get_rate(struct clk *clk)
158 u32 ctl = bfin_read32(CGU0_CTL);
159 u32 stat = bfin_read32(CGU0_STAT);
160 if (stat & CGU0_STAT_PLLBP)
162 msel = (ctl & CGU0_CTL_MSEL_MASK) >> CGU0_CTL_MSEL_SHIFT;
163 df = (ctl & CGU0_CTL_DF);
164 clk->parent->rate = clk_get_rate(clk->parent);
165 return clk->parent->rate / (df + 1) * msel * 2;
168 unsigned long pll_round_rate(struct clk *clk, unsigned long rate)
171 div = rate / clk->parent->rate;
172 return clk->parent->rate * div;
175 int pll_set_rate(struct clk *clk, unsigned long rate)
178 u32 stat = bfin_read32(CGU0_STAT);
179 if (!(stat & CGU0_STAT_PLLEN))
181 if (!(stat & CGU0_STAT_PLLLK))
183 if (wait_for_pll_align())
185 msel = rate / clk->parent->rate / 2;
186 clk_reg_write_mask(CGU0_CTL, msel << CGU0_CTL_MSEL_SHIFT,
192 unsigned long cclk_get_rate(struct clk *clk)
195 return clk->parent->rate;
200 unsigned long sys_clk_get_rate(struct clk *clk)
205 u32 ctl = bfin_read32(CGU0_CTL);
206 u32 div = bfin_read32(CGU0_DIV);
207 div = (div & clk->mask) >> clk->shift;
208 msel = (ctl & CGU0_CTL_MSEL_MASK) >> CGU0_CTL_MSEL_SHIFT;
209 df = (ctl & CGU0_CTL_DF);
211 if (!strcmp(clk->parent->name, "SYS_CLKIN")) {
212 drate = clk->parent->rate / (df + 1);
217 clk->parent->rate = clk_get_rate(clk->parent);
218 return clk->parent->rate / div;
222 unsigned long sys_clk_round_rate(struct clk *clk, unsigned long rate)
224 unsigned long max_rate;
229 u32 ctl = bfin_read32(CGU0_CTL);
231 msel = (ctl & CGU0_CTL_MSEL_MASK) >> CGU0_CTL_MSEL_SHIFT;
232 df = (ctl & CGU0_CTL_DF);
233 max_rate = clk->parent->rate / (df + 1) * msel;
238 for (i = 1; i < clk->mask; i++) {
239 drate = max_rate / i;
246 int sys_clk_set_rate(struct clk *clk, unsigned long rate)
248 u32 div = bfin_read32(CGU0_DIV);
249 div = (div & clk->mask) >> clk->shift;
251 rate = clk_round_rate(clk, rate);
256 div = (clk_get_rate(clk) * div) / rate;
258 if (wait_for_pll_align())
260 clk_reg_write_mask(CGU0_DIV, div << clk->shift,
266 static struct clk_ops vco_ops = {
267 .get_rate = vco_get_rate,
270 static struct clk_ops pll_ops = {
271 .get_rate = pll_get_rate,
272 .set_rate = pll_set_rate,
275 static struct clk_ops cclk_ops = {
276 .get_rate = cclk_get_rate,
279 static struct clk_ops sys_clk_ops = {
280 .get_rate = sys_clk_get_rate,
281 .set_rate = sys_clk_set_rate,
282 .round_rate = sys_clk_round_rate,
285 static struct clk sys_clkin = {
287 .rate = CONFIG_CLKIN_HZ,
291 static struct clk pll_clk = {
294 .parent = &sys_clkin,
296 .flags = NEEDS_INITIALIZATION,
299 static struct clk cclk = {
302 .mask = CGU0_DIV_CSEL_MASK,
303 .shift = CGU0_DIV_CSEL_SHIFT,
304 .parent = &sys_clkin,
306 .flags = NEEDS_INITIALIZATION,
309 static struct clk cclk0 = {
315 static struct clk cclk1 = {
321 static struct clk sysclk = {
324 .mask = CGU0_DIV_SYSSEL_MASK,
325 .shift = CGU0_DIV_SYSSEL_SHIFT,
326 .parent = &sys_clkin,
328 .flags = NEEDS_INITIALIZATION,
331 static struct clk sclk0 = {
334 .mask = CGU0_DIV_S0SEL_MASK,
335 .shift = CGU0_DIV_S0SEL_SHIFT,
340 static struct clk sclk1 = {
343 .mask = CGU0_DIV_S1SEL_MASK,
344 .shift = CGU0_DIV_S1SEL_SHIFT,
349 static struct clk dclk = {
352 .mask = CGU0_DIV_DSEL_MASK,
353 .shift = CGU0_DIV_DSEL_SHIFT,
354 .parent = &sys_clkin,
358 static struct clk oclk = {
361 .mask = CGU0_DIV_OSEL_MASK,
362 .shift = CGU0_DIV_OSEL_SHIFT,
366 static struct clk_lookup bf609_clks[] = {
367 CLK(sys_clkin, NULL, "SYS_CLKIN"),
368 CLK(pll_clk, NULL, "PLLCLK"),
369 CLK(cclk, NULL, "CCLK"),
370 CLK(cclk0, NULL, "CCLK0"),
371 CLK(cclk1, NULL, "CCLK1"),
372 CLK(sysclk, NULL, "SYSCLK"),
373 CLK(sclk0, NULL, "SCLK0"),
374 CLK(sclk1, NULL, "SCLK1"),
375 CLK(dclk, NULL, "DCLK"),
376 CLK(oclk, NULL, "OCLK"),
379 int __init clk_init(void)
383 for (i = 0; i < ARRAY_SIZE(bf609_clks); i++) {
384 clkp = bf609_clks[i].clk;
385 if (clkp->flags & NEEDS_INITIALIZATION)
388 clkdev_add_table(bf609_clks, ARRAY_SIZE(bf609_clks));