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 int wait_for_pll_align(void)
79 while (i
-- && (bfin_read32(CGU0_STAT
) & CGU0_STAT_CLKSALGN
));
81 if (bfin_read32(CGU0_STAT
) & CGU0_STAT_CLKSALGN
) {
82 printk(KERN_CRIT
"fail to align clk\n");
89 int clk_enable(struct clk
*clk
)
92 if (clk
->ops
&& clk
->ops
->enable
)
93 ret
= clk
->ops
->enable(clk
);
96 EXPORT_SYMBOL(clk_enable
);
98 void clk_disable(struct clk
*clk
)
100 if (clk
->ops
&& clk
->ops
->disable
)
101 clk
->ops
->disable(clk
);
103 EXPORT_SYMBOL(clk_disable
);
106 unsigned long clk_get_rate(struct clk
*clk
)
108 unsigned long ret
= 0;
109 if (clk
->ops
&& clk
->ops
->get_rate
)
110 ret
= clk
->ops
->get_rate(clk
);
113 EXPORT_SYMBOL(clk_get_rate
);
115 long clk_round_rate(struct clk
*clk
, unsigned long rate
)
118 if (clk
->ops
&& clk
->ops
->round_rate
)
119 ret
= clk
->ops
->round_rate(clk
, rate
);
122 EXPORT_SYMBOL(clk_round_rate
);
124 int clk_set_rate(struct clk
*clk
, unsigned long rate
)
127 if (clk
->ops
&& clk
->ops
->set_rate
)
128 ret
= clk
->ops
->set_rate(clk
, rate
);
131 EXPORT_SYMBOL(clk_set_rate
);
133 unsigned long vco_get_rate(struct clk
*clk
)
138 unsigned long pll_get_rate(struct clk
*clk
)
142 u32 ctl
= bfin_read32(CGU0_CTL
);
143 u32 stat
= bfin_read32(CGU0_STAT
);
144 if (stat
& CGU0_STAT_PLLBP
)
146 msel
= (ctl
& CGU0_CTL_MSEL_MASK
) >> CGU0_CTL_MSEL_SHIFT
;
147 df
= (ctl
& CGU0_CTL_DF
);
148 clk
->parent
->rate
= clk_get_rate(clk
->parent
);
149 return clk
->parent
->rate
/ (df
+ 1) * msel
* 2;
152 unsigned long pll_round_rate(struct clk
*clk
, unsigned long rate
)
155 div
= rate
/ clk
->parent
->rate
;
156 return clk
->parent
->rate
* div
;
159 int pll_set_rate(struct clk
*clk
, unsigned long rate
)
162 u32 stat
= bfin_read32(CGU0_STAT
);
163 if (!(stat
& CGU0_STAT_PLLEN
))
165 if (!(stat
& CGU0_STAT_PLLLK
))
167 if (wait_for_pll_align())
169 msel
= rate
/ clk
->parent
->rate
/ 2;
170 clk_reg_write_mask(CGU0_CTL
, msel
<< CGU0_CTL_MSEL_SHIFT
,
176 unsigned long cclk_get_rate(struct clk
*clk
)
179 return clk
->parent
->rate
;
184 unsigned long sys_clk_get_rate(struct clk
*clk
)
189 u32 ctl
= bfin_read32(CGU0_CTL
);
190 u32 div
= bfin_read32(CGU0_DIV
);
191 div
= (div
& clk
->mask
) >> clk
->shift
;
192 msel
= (ctl
& CGU0_CTL_MSEL_MASK
) >> CGU0_CTL_MSEL_SHIFT
;
193 df
= (ctl
& CGU0_CTL_DF
);
195 if (!strcmp(clk
->parent
->name
, "SYS_CLKIN")) {
196 drate
= clk
->parent
->rate
/ (df
+ 1);
201 clk
->parent
->rate
= clk_get_rate(clk
->parent
);
202 return clk
->parent
->rate
/ div
;
206 unsigned long dummy_get_rate(struct clk
*clk
)
208 clk
->parent
->rate
= clk_get_rate(clk
->parent
);
209 return clk
->parent
->rate
;
212 unsigned long sys_clk_round_rate(struct clk
*clk
, unsigned long rate
)
214 unsigned long max_rate
;
219 u32 ctl
= bfin_read32(CGU0_CTL
);
221 msel
= (ctl
& CGU0_CTL_MSEL_MASK
) >> CGU0_CTL_MSEL_SHIFT
;
222 df
= (ctl
& CGU0_CTL_DF
);
223 max_rate
= clk
->parent
->rate
/ (df
+ 1) * msel
;
228 for (i
= 1; i
< clk
->mask
; i
++) {
229 drate
= max_rate
/ i
;
236 int sys_clk_set_rate(struct clk
*clk
, unsigned long rate
)
238 u32 div
= bfin_read32(CGU0_DIV
);
239 div
= (div
& clk
->mask
) >> clk
->shift
;
241 rate
= clk_round_rate(clk
, rate
);
246 div
= (clk_get_rate(clk
) * div
) / rate
;
248 if (wait_for_pll_align())
250 clk_reg_write_mask(CGU0_DIV
, div
<< clk
->shift
,
256 static struct clk_ops vco_ops
= {
257 .get_rate
= vco_get_rate
,
260 static struct clk_ops pll_ops
= {
261 .get_rate
= pll_get_rate
,
262 .set_rate
= pll_set_rate
,
265 static struct clk_ops cclk_ops
= {
266 .get_rate
= cclk_get_rate
,
269 static struct clk_ops sys_clk_ops
= {
270 .get_rate
= sys_clk_get_rate
,
271 .set_rate
= sys_clk_set_rate
,
272 .round_rate
= sys_clk_round_rate
,
275 static struct clk_ops dummy_clk_ops
= {
276 .get_rate
= dummy_get_rate
,
279 static struct clk sys_clkin
= {
281 .rate
= CONFIG_CLKIN_HZ
,
285 static struct clk pll_clk
= {
288 .parent
= &sys_clkin
,
290 .flags
= NEEDS_INITIALIZATION
,
293 static struct clk cclk
= {
296 .mask
= CGU0_DIV_CSEL_MASK
,
297 .shift
= CGU0_DIV_CSEL_SHIFT
,
298 .parent
= &sys_clkin
,
300 .flags
= NEEDS_INITIALIZATION
,
303 static struct clk cclk0
= {
309 static struct clk cclk1
= {
315 static struct clk sysclk
= {
318 .mask
= CGU0_DIV_SYSSEL_MASK
,
319 .shift
= CGU0_DIV_SYSSEL_SHIFT
,
320 .parent
= &sys_clkin
,
322 .flags
= NEEDS_INITIALIZATION
,
325 static struct clk sclk0
= {
328 .mask
= CGU0_DIV_S0SEL_MASK
,
329 .shift
= CGU0_DIV_S0SEL_SHIFT
,
334 static struct clk sclk1
= {
337 .mask
= CGU0_DIV_S1SEL_MASK
,
338 .shift
= CGU0_DIV_S1SEL_SHIFT
,
343 static struct clk dclk
= {
346 .mask
= CGU0_DIV_DSEL_MASK
,
347 .shift
= CGU0_DIV_DSEL_SHIFT
,
348 .parent
= &sys_clkin
,
352 static struct clk oclk
= {
355 .mask
= CGU0_DIV_OSEL_MASK
,
356 .shift
= CGU0_DIV_OSEL_SHIFT
,
360 static struct clk ethclk
= {
363 .ops
= &dummy_clk_ops
,
366 static struct clk ethpclk
= {
369 .ops
= &dummy_clk_ops
,
372 static struct clk spiclk
= {
375 .ops
= &dummy_clk_ops
,
378 static struct clk_lookup bf609_clks
[] = {
379 CLK(sys_clkin
, NULL
, "SYS_CLKIN"),
380 CLK(pll_clk
, NULL
, "PLLCLK"),
381 CLK(cclk
, NULL
, "CCLK"),
382 CLK(cclk0
, NULL
, "CCLK0"),
383 CLK(cclk1
, NULL
, "CCLK1"),
384 CLK(sysclk
, NULL
, "SYSCLK"),
385 CLK(sclk0
, NULL
, "SCLK0"),
386 CLK(sclk1
, NULL
, "SCLK1"),
387 CLK(dclk
, NULL
, "DCLK"),
388 CLK(oclk
, NULL
, "OCLK"),
389 CLK(ethclk
, NULL
, "stmmaceth"),
390 CLK(ethpclk
, NULL
, "pclk"),
391 CLK(spiclk
, NULL
, "spi"),
394 int __init
clk_init(void)
398 for (i
= 0; i
< ARRAY_SIZE(bf609_clks
); i
++) {
399 clkp
= bf609_clks
[i
].clk
;
400 if (clkp
->flags
& NEEDS_INITIALIZATION
)
403 clkdev_add_table(bf609_clks
, ARRAY_SIZE(bf609_clks
));