Linux Audio

Check our new training course

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