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 dummy_get_rate(struct clk
*clk
)
225 clk
->parent
->rate
= clk_get_rate(clk
->parent
);
226 return clk
->parent
->rate
;
229 unsigned long sys_clk_round_rate(struct clk
*clk
, unsigned long rate
)
231 unsigned long max_rate
;
236 u32 ctl
= bfin_read32(CGU0_CTL
);
238 msel
= (ctl
& CGU0_CTL_MSEL_MASK
) >> CGU0_CTL_MSEL_SHIFT
;
239 df
= (ctl
& CGU0_CTL_DF
);
240 max_rate
= clk
->parent
->rate
/ (df
+ 1) * msel
;
245 for (i
= 1; i
< clk
->mask
; i
++) {
246 drate
= max_rate
/ i
;
253 int sys_clk_set_rate(struct clk
*clk
, unsigned long rate
)
255 u32 div
= bfin_read32(CGU0_DIV
);
256 div
= (div
& clk
->mask
) >> clk
->shift
;
258 rate
= clk_round_rate(clk
, rate
);
263 div
= (clk_get_rate(clk
) * div
) / rate
;
265 if (wait_for_pll_align())
267 clk_reg_write_mask(CGU0_DIV
, div
<< clk
->shift
,
273 static struct clk_ops vco_ops
= {
274 .get_rate
= vco_get_rate
,
277 static struct clk_ops pll_ops
= {
278 .get_rate
= pll_get_rate
,
279 .set_rate
= pll_set_rate
,
282 static struct clk_ops cclk_ops
= {
283 .get_rate
= cclk_get_rate
,
286 static struct clk_ops sys_clk_ops
= {
287 .get_rate
= sys_clk_get_rate
,
288 .set_rate
= sys_clk_set_rate
,
289 .round_rate
= sys_clk_round_rate
,
292 static struct clk_ops dummy_clk_ops
= {
293 .get_rate
= dummy_get_rate
,
296 static struct clk sys_clkin
= {
298 .rate
= CONFIG_CLKIN_HZ
,
302 static struct clk pll_clk
= {
305 .parent
= &sys_clkin
,
307 .flags
= NEEDS_INITIALIZATION
,
310 static struct clk cclk
= {
313 .mask
= CGU0_DIV_CSEL_MASK
,
314 .shift
= CGU0_DIV_CSEL_SHIFT
,
315 .parent
= &sys_clkin
,
317 .flags
= NEEDS_INITIALIZATION
,
320 static struct clk cclk0
= {
326 static struct clk cclk1
= {
332 static struct clk sysclk
= {
335 .mask
= CGU0_DIV_SYSSEL_MASK
,
336 .shift
= CGU0_DIV_SYSSEL_SHIFT
,
337 .parent
= &sys_clkin
,
339 .flags
= NEEDS_INITIALIZATION
,
342 static struct clk sclk0
= {
345 .mask
= CGU0_DIV_S0SEL_MASK
,
346 .shift
= CGU0_DIV_S0SEL_SHIFT
,
351 static struct clk sclk1
= {
354 .mask
= CGU0_DIV_S1SEL_MASK
,
355 .shift
= CGU0_DIV_S1SEL_SHIFT
,
360 static struct clk dclk
= {
363 .mask
= CGU0_DIV_DSEL_MASK
,
364 .shift
= CGU0_DIV_DSEL_SHIFT
,
365 .parent
= &sys_clkin
,
369 static struct clk oclk
= {
372 .mask
= CGU0_DIV_OSEL_MASK
,
373 .shift
= CGU0_DIV_OSEL_SHIFT
,
377 static struct clk ethclk
= {
380 .ops
= &dummy_clk_ops
,
383 static struct clk_lookup bf609_clks
[] = {
384 CLK(sys_clkin
, NULL
, "SYS_CLKIN"),
385 CLK(pll_clk
, NULL
, "PLLCLK"),
386 CLK(cclk
, NULL
, "CCLK"),
387 CLK(cclk0
, NULL
, "CCLK0"),
388 CLK(cclk1
, NULL
, "CCLK1"),
389 CLK(sysclk
, NULL
, "SYSCLK"),
390 CLK(sclk0
, NULL
, "SCLK0"),
391 CLK(sclk1
, NULL
, "SCLK1"),
392 CLK(dclk
, NULL
, "DCLK"),
393 CLK(oclk
, NULL
, "OCLK"),
394 CLK(ethclk
, NULL
, "stmmaceth"),
397 int __init
clk_init(void)
401 for (i
= 0; i
< ARRAY_SIZE(bf609_clks
); i
++) {
402 clkp
= bf609_clks
[i
].clk
;
403 if (clkp
->flags
& NEEDS_INITIALIZATION
)
406 clkdev_add_table(bf609_clks
, ARRAY_SIZE(bf609_clks
));
This page took 0.050723 seconds and 5 git commands to generate.