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
64static LIST_HEAD(clk_list);
65
66static 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
76int wait_for_pll_align(void)
77{
78	int i = 10000;
79	while (i-- && (bfin_read32(CGU0_STAT) & CGU0_STAT_CLKSALGN));
80
81	if (bfin_read32(CGU0_STAT) & CGU0_STAT_CLKSALGN) {
82		printk(KERN_CRIT "fail to align clk\n");
83		return -1;
84	}
85
86	return 0;
87}
88
89int clk_enable(struct clk *clk)
90{
91	int ret = -EIO;
92	if (clk->ops && clk->ops->enable)
93		ret = clk->ops->enable(clk);
94	return ret;
95}
96EXPORT_SYMBOL(clk_enable);
97
98void clk_disable(struct clk *clk)
99{
100	if (clk->ops && clk->ops->disable)
101		clk->ops->disable(clk);
102}
103EXPORT_SYMBOL(clk_disable);
104
105
106unsigned long clk_get_rate(struct clk *clk)
107{
108	unsigned long ret = 0;
109	if (clk->ops && clk->ops->get_rate)
110		ret = clk->ops->get_rate(clk);
111	return ret;
112}
113EXPORT_SYMBOL(clk_get_rate);
114
115long clk_round_rate(struct clk *clk, unsigned long rate)
116{
117	long ret = 0;
118	if (clk->ops && clk->ops->round_rate)
119		ret = clk->ops->round_rate(clk, rate);
120	return ret;
121}
122EXPORT_SYMBOL(clk_round_rate);
123
124int clk_set_rate(struct clk *clk, unsigned long rate)
125{
126	int ret = -EIO;
127	if (clk->ops && clk->ops->set_rate)
128		ret = clk->ops->set_rate(clk, rate);
129	return ret;
130}
131EXPORT_SYMBOL(clk_set_rate);
132
133unsigned long vco_get_rate(struct clk *clk)
134{
135	return clk->rate;
136}
137
138unsigned long pll_get_rate(struct clk *clk)
139{
140	u32 df;
141	u32 msel;
142	u32 ctl = bfin_read32(CGU0_CTL);
143	u32 stat = bfin_read32(CGU0_STAT);
144	if (stat & CGU0_STAT_PLLBP)
145		return 0;
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;
150}
151
152unsigned long pll_round_rate(struct clk *clk, unsigned long rate)
153{
154	u32 div;
155	div = rate / clk->parent->rate;
156	return clk->parent->rate * div;
157}
158
159int pll_set_rate(struct clk *clk, unsigned long rate)
160{
161	u32 msel;
162	u32 stat = bfin_read32(CGU0_STAT);
163	if (!(stat & CGU0_STAT_PLLEN))
164		return -EBUSY;
165	if (!(stat & CGU0_STAT_PLLLK))
166		return -EBUSY;
167	if (wait_for_pll_align())
168		return -EBUSY;
169	msel = rate / clk->parent->rate / 2;
170	clk_reg_write_mask(CGU0_CTL, msel << CGU0_CTL_MSEL_SHIFT,
171		CGU0_CTL_MSEL_MASK);
172	clk->rate = rate;
173	return 0;
174}
175
176unsigned long cclk_get_rate(struct clk *clk)
177{
178	if (clk->parent)
179		return clk->parent->rate;
180	else
181		return 0;
182}
183
184unsigned long sys_clk_get_rate(struct clk *clk)
185{
186	unsigned long drate;
187	u32 msel;
188	u32 df;
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);
194
195	if (!strcmp(clk->parent->name, "SYS_CLKIN")) {
196		drate = clk->parent->rate / (df + 1);
197		drate *=  msel;
198		drate /= div;
199		return drate;
200	} else {
201		clk->parent->rate = clk_get_rate(clk->parent);
202		return clk->parent->rate / div;
203	}
204}
205
206unsigned long dummy_get_rate(struct clk *clk)
207{
208	clk->parent->rate = clk_get_rate(clk->parent);
209	return clk->parent->rate;
210}
211
212unsigned long sys_clk_round_rate(struct clk *clk, unsigned long rate)
213{
214	unsigned long max_rate;
215	unsigned long drate;
216	int i;
217	u32 msel;
218	u32 df;
219	u32 ctl = bfin_read32(CGU0_CTL);
220
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;
224
225	if (rate > max_rate)
226		return 0;
227
228	for (i = 1; i < clk->mask; i++) {
229		drate = max_rate / i;
230		if (rate >= drate)
231			return drate;
232	}
233	return 0;
234}
235
236int sys_clk_set_rate(struct clk *clk, unsigned long rate)
237{
238	u32 div = bfin_read32(CGU0_DIV);
239	div = (div & clk->mask) >> clk->shift;
240
241	rate = clk_round_rate(clk, rate);
242
243	if (!rate)
244		return -EINVAL;
245
246	div = (clk_get_rate(clk) * div) / rate;
247
248	if (wait_for_pll_align())
249		return -EBUSY;
250	clk_reg_write_mask(CGU0_DIV, div << clk->shift,
251			clk->mask);
252	clk->rate = rate;
253	return 0;
254}
255
256static struct clk_ops vco_ops = {
257	.get_rate = vco_get_rate,
258};
259
260static struct clk_ops pll_ops = {
261	.get_rate = pll_get_rate,
262	.set_rate = pll_set_rate,
263};
264
265static struct clk_ops cclk_ops = {
266	.get_rate = cclk_get_rate,
267};
268
269static 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,
273};
274
275static struct clk_ops dummy_clk_ops = {
276	.get_rate = dummy_get_rate,
277};
278
279static struct clk sys_clkin = {
280	.name       = "SYS_CLKIN",
281	.rate       = CONFIG_CLKIN_HZ,
282	.ops        = &vco_ops,
283};
284
285static struct clk pll_clk = {
286	.name       = "PLLCLK",
287	.rate       = 500000000,
288	.parent     = &sys_clkin,
289	.ops = &pll_ops,
290	.flags = NEEDS_INITIALIZATION,
291};
292
293static struct clk cclk = {
294	.name       = "CCLK",
295	.rate       = 500000000,
296	.mask       = CGU0_DIV_CSEL_MASK,
297	.shift      = CGU0_DIV_CSEL_SHIFT,
298	.parent     = &sys_clkin,
299	.ops	    = &sys_clk_ops,
300	.flags = NEEDS_INITIALIZATION,
301};
302
303static struct clk cclk0 = {
304	.name       = "CCLK0",
305	.parent     = &cclk,
306	.ops	    = &cclk_ops,
307};
308
309static struct clk cclk1 = {
310	.name       = "CCLK1",
311	.parent     = &cclk,
312	.ops	    = &cclk_ops,
313};
314
315static struct clk sysclk = {
316	.name       = "SYSCLK",
317	.rate       = 500000000,
318	.mask       = CGU0_DIV_SYSSEL_MASK,
319	.shift      = CGU0_DIV_SYSSEL_SHIFT,
320	.parent     = &sys_clkin,
321	.ops	    = &sys_clk_ops,
322	.flags = NEEDS_INITIALIZATION,
323};
324
325static struct clk sclk0 = {
326	.name       = "SCLK0",
327	.rate       = 500000000,
328	.mask       = CGU0_DIV_S0SEL_MASK,
329	.shift      = CGU0_DIV_S0SEL_SHIFT,
330	.parent     = &sysclk,
331	.ops	    = &sys_clk_ops,
332};
333
334static struct clk sclk1 = {
335	.name       = "SCLK1",
336	.rate       = 500000000,
337	.mask       = CGU0_DIV_S1SEL_MASK,
338	.shift      = CGU0_DIV_S1SEL_SHIFT,
339	.parent     = &sysclk,
340	.ops	    = &sys_clk_ops,
341};
342
343static struct clk dclk = {
344	.name       = "DCLK",
345	.rate       = 500000000,
346	.mask       = CGU0_DIV_DSEL_MASK,
347	.shift       = CGU0_DIV_DSEL_SHIFT,
348	.parent     = &sys_clkin,
349	.ops	    = &sys_clk_ops,
350};
351
352static struct clk oclk = {
353	.name       = "OCLK",
354	.rate       = 500000000,
355	.mask       = CGU0_DIV_OSEL_MASK,
356	.shift      = CGU0_DIV_OSEL_SHIFT,
357	.parent     = &pll_clk,
358};
359
360static struct clk ethclk = {
361	.name       = "stmmaceth",
362	.parent     = &sclk0,
363	.ops	    = &dummy_clk_ops,
364};
365
366static struct clk ethpclk = {
367	.name       = "pclk",
368	.parent     = &sclk0,
369	.ops	    = &dummy_clk_ops,
370};
371
372static struct clk spiclk = {
373	.name       = "spi",
374	.parent     = &sclk1,
375	.ops        = &dummy_clk_ops,
376};
377
378static 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"),
392};
393
394int __init clk_init(void)
395{
396	int i;
397	struct clk *clkp;
398	for (i = 0; i < ARRAY_SIZE(bf609_clks); i++) {
399		clkp = bf609_clks[i].clk;
400		if (clkp->flags & NEEDS_INITIALIZATION)
401			clk_get_rate(clkp);
402	}
403	clkdev_add_table(bf609_clks, ARRAY_SIZE(bf609_clks));
404	return 0;
405}
406