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_CRIT
"fail to align clk\n");
107 int clk_enable(struct clk
*clk
)
110 if (clk
->ops
&& clk
->ops
->enable
)
111 ret
= clk
->ops
->enable(clk
);
114 EXPORT_SYMBOL(clk_enable
);
116 void clk_disable(struct clk
*clk
)
118 if (clk
->ops
&& clk
->ops
->disable
)
119 clk
->ops
->disable(clk
);
121 EXPORT_SYMBOL(clk_disable
);
123 unsigned long clk_get_rate(struct clk
*clk
)
125 unsigned long ret
= 0;
126 if (clk
->ops
&& clk
->ops
->get_rate
)
127 ret
= clk
->ops
->get_rate(clk
);
130 EXPORT_SYMBOL(clk_get_rate
);
132 long clk_round_rate(struct clk
*clk
, unsigned long rate
)
135 if (clk
->ops
&& clk
->ops
->round_rate
)
136 ret
= clk
->ops
->round_rate(clk
, rate
);
139 EXPORT_SYMBOL(clk_round_rate
);
141 int clk_set_rate(struct clk
*clk
, unsigned long rate
)
144 if (clk
->ops
&& clk
->ops
->set_rate
)
145 ret
= clk
->ops
->set_rate(clk
, rate
);
148 EXPORT_SYMBOL(clk_set_rate
);
150 unsigned long vco_get_rate(struct clk
*clk
)
155 unsigned long pll_get_rate(struct clk
*clk
)
159 u32 ctl
= bfin_read32(CGU0_CTL
);
160 u32 stat
= bfin_read32(CGU0_STAT
);
161 if (stat
& CGU0_STAT_PLLBP
)
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;
169 unsigned long pll_round_rate(struct clk
*clk
, unsigned long rate
)
172 div
= rate
/ clk
->parent
->rate
;
173 return clk
->parent
->rate
* div
;
176 int pll_set_rate(struct clk
*clk
, unsigned long rate
)
179 u32 stat
= bfin_read32(CGU0_STAT
);
180 if (!(stat
& CGU0_STAT_PLLEN
))
182 if (!(stat
& CGU0_STAT_PLLLK
))
184 if (wait_for_pll_align())
186 msel
= rate
/ clk
->parent
->rate
/ 2;
187 clk_reg_write_mask(CGU0_CTL
, msel
<< CGU0_CTL_MSEL_SHIFT
,
193 unsigned long cclk_get_rate(struct clk
*clk
)
196 return clk
->parent
->rate
;
201 unsigned long sys_clk_get_rate(struct clk
*clk
)
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
);
212 if (!strcmp(clk
->parent
->name
, "SYS_CLKIN")) {
213 drate
= clk
->parent
->rate
/ (df
+ 1);
218 clk
->parent
->rate
= clk_get_rate(clk
->parent
);
219 return clk
->parent
->rate
/ div
;
223 unsigned long sys_clk_round_rate(struct clk
*clk
, unsigned long rate
)
225 unsigned long max_rate
;
230 u32 ctl
= bfin_read32(CGU0_CTL
);
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
;
239 for (i
= 1; i
< clk
->mask
; i
++) {
240 drate
= max_rate
/ i
;
247 int sys_clk_set_rate(struct clk
*clk
, unsigned long rate
)
249 u32 div
= bfin_read32(CGU0_DIV
);
250 div
= (div
& clk
->mask
) >> clk
->shift
;
252 rate
= clk_round_rate(clk
, rate
);
257 div
= (clk_get_rate(clk
) * div
) / rate
;
259 if (wait_for_pll_align())
261 clk_reg_write_mask(CGU0_DIV
, div
<< clk
->shift
,
267 static struct clk_ops vco_ops
= {
268 .get_rate
= vco_get_rate
,
271 static struct clk_ops pll_ops
= {
272 .get_rate
= pll_get_rate
,
273 .set_rate
= pll_set_rate
,
276 static struct clk_ops cclk_ops
= {
277 .get_rate
= cclk_get_rate
,
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
,
286 static struct clk sys_clkin
= {
288 .rate
= CONFIG_CLKIN_HZ
,
292 static struct clk pll_clk
= {
295 .parent
= &sys_clkin
,
297 .flags
= NEEDS_INITIALIZATION
,
300 static struct clk cclk
= {
303 .mask
= CGU0_DIV_CSEL_MASK
,
304 .shift
= CGU0_DIV_CSEL_SHIFT
,
305 .parent
= &sys_clkin
,
307 .flags
= NEEDS_INITIALIZATION
,
310 static struct clk cclk0
= {
316 static struct clk cclk1
= {
322 static struct clk sysclk
= {
325 .mask
= CGU0_DIV_SYSSEL_MASK
,
326 .shift
= CGU0_DIV_SYSSEL_SHIFT
,
327 .parent
= &sys_clkin
,
329 .flags
= NEEDS_INITIALIZATION
,
332 static struct clk sclk0
= {
335 .mask
= CGU0_DIV_S0SEL_MASK
,
336 .shift
= CGU0_DIV_S0SEL_SHIFT
,
341 static struct clk sclk1
= {
344 .mask
= CGU0_DIV_S1SEL_MASK
,
345 .shift
= CGU0_DIV_S1SEL_SHIFT
,
350 static struct clk dclk
= {
353 .mask
= CGU0_DIV_DSEL_MASK
,
354 .shift
= CGU0_DIV_DSEL_SHIFT
,
355 .parent
= &sys_clkin
,
359 static struct clk oclk
= {
362 .mask
= CGU0_DIV_OSEL_MASK
,
363 .shift
= CGU0_DIV_OSEL_SHIFT
,
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"),
380 int __init
clk_init(void)
384 for (i
= 0; i
< ARRAY_SIZE(bf609_clks
); i
++) {
385 clkp
= bf609_clks
[i
].clk
;
386 if (clkp
->flags
& NEEDS_INITIALIZATION
)
389 clkdev_add_table(bf609_clks
, ARRAY_SIZE(bf609_clks
));