Merge xburst target.
[openwrt/svn-archive/archive.git] / target / linux / xburst / files-2.6.32 / arch / mips / jz4740 / clock.c
1 /*
2 * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
3 * JZ4740 SoC TCU support
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 *
10 * You should have received a copy of the GNU General Public License along
11 * with this program; if not, write to the Free Software Foundation, Inc.,
12 * 675 Mass Ave, Cambridge, MA 02139, USA.
13 *
14 */
15
16 #include <linux/kernel.h>
17 #include <linux/errno.h>
18 #include <linux/clk.h>
19 #include <linux/spinlock.h>
20 #include <linux/io.h>
21 #include <linux/module.h>
22 #include <linux/list.h>
23 #include <linux/err.h>
24
25 #define JZ_REG_CLOCK_CTRL 0x00
26 #define JZ_REG_CLOCK_PLL 0x10
27 #define JZ_REG_CLOCK_GATE 0x20
28 #define JZ_REG_CLOCK_I2S 0x60
29 #define JZ_REG_CLOCK_LCD 0x64
30 #define JZ_REG_CLOCK_MMC 0x68
31 #define JZ_REG_CLOCK_UHC 0x6C
32 #define JZ_REG_CLOCK_SPI 0x74
33
34 #define JZ_CLOCK_CTRL_I2S_SRC_PLL BIT(31)
35 #define JZ_CLOCK_CTRL_KO_ENABLE BIT(30)
36 #define JZ_CLOCK_CTRL_UDC_SRC_PLL BIT(29)
37 #define JZ_CLOCK_CTRL_UDIV_MASK 0x1f800000
38 #define JZ_CLOCK_CTRL_CHANGE_ENABLE BIT(22)
39 #define JZ_CLOCK_CTRL_PLL_HALF BIT(21)
40 #define JZ_CLOCK_CTRL_LDIV_MASK 0x001f0000
41 #define JZ_CLOCK_CTRL_UDIV_OFFSET 23
42 #define JZ_CLOCK_CTRL_LDIV_OFFSET 16
43 #define JZ_CLOCK_CTRL_MDIV_OFFSET 12
44 #define JZ_CLOCK_CTRL_PDIV_OFFSET 8
45 #define JZ_CLOCK_CTRL_HDIV_OFFSET 4
46 #define JZ_CLOCK_CTRL_CDIV_OFFSET 0
47
48 #define JZ_CLOCK_GATE_UART0 BIT(0)
49 #define JZ_CLOCK_GATE_TCU BIT(1)
50 #define JZ_CLOCK_GATE_RTC BIT(2)
51 #define JZ_CLOCK_GATE_I2C BIT(3)
52 #define JZ_CLOCK_GATE_SPI BIT(4)
53 #define JZ_CLOCK_GATE_AIC_PCLK BIT(5)
54 #define JZ_CLOCK_GATE_AIC BIT(6)
55 #define JZ_CLOCK_GATE_MMC BIT(7)
56 #define JZ_CLOCK_GATE_ADC BIT(8)
57 #define JZ_CLOCK_GATE_CIM BIT(9)
58 #define JZ_CLOCK_GATE_LCD BIT(10)
59 #define JZ_CLOCK_GATE_UDC BIT(11)
60 #define JZ_CLOCK_GATE_DMAC BIT(12)
61 #define JZ_CLOCK_GATE_IPU BIT(13)
62 #define JZ_CLOCK_GATE_UHC BIT(14)
63 #define JZ_CLOCK_GATE_UART1 BIT(15)
64
65 #define JZ_CLOCK_I2S_DIV_MASK 0x01ff
66
67 #define JZ_CLOCK_LCD_DIV_MASK 0x01ff
68
69 #define JZ_CLOCK_MMC_DIV_MASK 0x001f
70
71 #define JZ_CLOCK_UHC_DIV_MASK 0x000f
72
73 #define JZ_CLOCK_SPI_SRC_PLL BIT(31)
74 #define JZ_CLOCK_SPI_DIV_MASK 0x000f
75
76 #define JZ_CLOCK_PLL_M_MASK 0x01ff
77 #define JZ_CLOCK_PLL_N_MASK 0x001f
78 #define JZ_CLOCK_PLL_OD_MASK 0x0003
79 #define JZ_CLOCK_PLL_STABLE BIT(10)
80 #define JZ_CLOCK_PLL_BYPASS BIT(9)
81 #define JZ_CLOCK_PLL_ENABLED BIT(8)
82 #define JZ_CLOCK_PLL_STABLIZE_MASK 0x000f
83 #define JZ_CLOCK_PLL_M_OFFSET 23
84 #define JZ_CLOCK_PLL_N_OFFSET 18
85 #define JZ_CLOCK_PLL_OD_OFFSET 16
86
87 static void __iomem *jz_clock_base;
88 static spinlock_t jz_clock_lock;
89 static LIST_HEAD(jz_clocks);
90
91 struct clk {
92 const char *name;
93 struct clk* parent;
94
95 uint32_t gate_bit;
96
97 unsigned long (*get_rate)(struct clk* clk);
98 unsigned long (*round_rate)(struct clk *clk, unsigned long rate);
99 int (*set_rate)(struct clk* clk, unsigned long rate);
100 int (*enable)(struct clk* clk);
101 int (*disable)(struct clk* clk);
102
103 int (*set_parent)(struct clk* clk, struct clk *parent);
104 struct list_head list;
105 };
106
107 struct main_clk {
108 struct clk clk;
109 uint32_t div_offset;
110 };
111
112 struct divided_clk {
113 struct clk clk;
114 uint32_t reg;
115 uint32_t mask;
116 };
117
118 struct static_clk {
119 struct clk clk;
120 unsigned long rate;
121 };
122
123 static uint32_t jz_clk_reg_read(int reg)
124 {
125 return readl(jz_clock_base + reg);
126 }
127
128 static void jz_clk_reg_write_mask(int reg, uint32_t val, uint32_t mask)
129 {
130 uint32_t val2;
131
132 spin_lock(&jz_clock_lock);
133 val2 = readl(jz_clock_base + reg);
134 val2 &= ~mask;
135 val2 |= val;
136 writel(val2, jz_clock_base + reg);
137 spin_unlock(&jz_clock_lock);
138 }
139
140 static void jz_clk_reg_set_bits(int reg, uint32_t mask)
141 {
142 uint32_t val;
143
144 spin_lock(&jz_clock_lock);
145 val = readl(jz_clock_base + reg);
146 val |= mask;
147 writel(val, jz_clock_base + reg);
148 spin_unlock(&jz_clock_lock);
149 }
150
151 static void jz_clk_reg_clear_bits(int reg, uint32_t mask)
152 {
153 uint32_t val;
154
155 spin_lock(&jz_clock_lock);
156 val = readl(jz_clock_base + reg);
157 val &= ~mask;
158 writel(val, jz_clock_base + reg);
159 spin_unlock(&jz_clock_lock);
160 }
161
162 static int jz_clk_enable_gating(struct clk *clk)
163 {
164 jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, clk->gate_bit);
165 return 0;
166 }
167
168 static int jz_clk_disable_gating(struct clk *clk)
169 {
170 jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, clk->gate_bit);
171 return 0;
172 }
173
174 static unsigned long jz_clk_static_get_rate(struct clk *clk)
175 {
176 return ((struct static_clk*)clk)->rate;
177 }
178
179 static int jz_clk_ko_enable(struct clk* clk)
180 {
181 jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_KO_ENABLE);
182 return 0;
183 }
184
185 static int jz_clk_ko_disable(struct clk* clk)
186 {
187 jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_KO_ENABLE);
188 return 0;
189 }
190
191
192 static const int pllno[] = {1, 2, 2, 4};
193
194 static unsigned long jz_clk_pll_get_rate(struct clk *clk)
195 {
196 uint32_t val;
197 int m;
198 int n;
199 int od;
200
201 val = jz_clk_reg_read(JZ_REG_CLOCK_PLL);
202
203 if (val & JZ_CLOCK_PLL_BYPASS)
204 return clk_get_rate(clk->parent);
205
206 m = ((val >> 23) & 0x1ff) + 2;
207 n = ((val >> 18) & 0x1f) + 2;
208 od = (val >> 16) & 0x3;
209
210 return clk_get_rate(clk->parent) * (m / n) / pllno[od];
211 }
212
213 static unsigned long jz_clk_pll_half_get_rate(struct clk *clk)
214 {
215 uint32_t reg;
216
217 reg = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
218 if (reg & JZ_CLOCK_CTRL_PLL_HALF)
219 return jz_clk_pll_get_rate(clk->parent);
220 return jz_clk_pll_get_rate(clk->parent) >> 1;
221 }
222
223
224
225 static const int jz_clk_main_divs[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
226
227 static unsigned long jz_clk_main_round_rate(struct clk *clk, unsigned long rate)
228 {
229 unsigned long parent_rate = jz_clk_pll_get_rate(clk->parent);
230 int div;
231
232 div = parent_rate / rate;
233 if (div > 32)
234 return parent_rate / 32;
235 else if (div < 1)
236 return parent_rate;
237
238 div &= (0x3 << (ffs(div) - 1));
239
240 return parent_rate / div;
241 }
242
243 static unsigned long jz_clk_main_get_rate(struct clk *clk) {
244 struct main_clk *mclk = (struct main_clk*)clk;
245 uint32_t div;
246
247 div = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
248
249 div >>= mclk->div_offset;
250 div &= 0xf;
251
252 if (div >= ARRAY_SIZE(jz_clk_main_divs))
253 div = ARRAY_SIZE(jz_clk_main_divs) - 1;
254
255 return jz_clk_pll_get_rate(clk->parent) / jz_clk_main_divs[div];
256 }
257
258 static int jz_clk_main_set_rate(struct clk *clk, unsigned long rate)
259 {
260 struct main_clk *mclk = (struct main_clk*)clk;
261 int i;
262 int div;
263 unsigned long parent_rate = jz_clk_pll_get_rate(clk->parent);
264
265 rate = jz_clk_main_round_rate(clk, rate);
266
267 div = parent_rate / rate;
268
269 i = (ffs(div) - 1) << 1;
270 if (i > 0 && !(div & BIT(i-1)))
271 i -= 1;
272
273 jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, i << mclk->div_offset,
274 0xf << mclk->div_offset);
275
276 return 0;
277 }
278
279
280 static struct static_clk jz_clk_ext = {
281 .clk = {
282 .name = "ext",
283 .get_rate = jz_clk_static_get_rate,
284 },
285 };
286
287 static struct clk jz_clk_pll = {
288 .name = "pll",
289 .parent = &jz_clk_ext.clk,
290 .get_rate = jz_clk_pll_get_rate,
291 };
292
293 static struct clk jz_clk_pll_half = {
294 .name = "pll half",
295 .parent = &jz_clk_pll,
296 .get_rate = jz_clk_pll_half_get_rate,
297 };
298
299 static struct main_clk jz_clk_cpu = {
300 .clk = {
301 .name = "cclk",
302 .parent = &jz_clk_pll,
303 .get_rate = jz_clk_main_get_rate,
304 .set_rate = jz_clk_main_set_rate,
305 .round_rate = jz_clk_main_round_rate,
306 },
307 .div_offset = JZ_CLOCK_CTRL_CDIV_OFFSET,
308 };
309
310 static struct main_clk jz_clk_memory = {
311 .clk = {
312 .name = "mclk",
313 .parent = &jz_clk_pll,
314 .get_rate = jz_clk_main_get_rate,
315 .set_rate = jz_clk_main_set_rate,
316 .round_rate = jz_clk_main_round_rate,
317 },
318 .div_offset = JZ_CLOCK_CTRL_MDIV_OFFSET,
319 };
320
321 static struct main_clk jz_clk_high_speed_peripheral = {
322 .clk = {
323 .name = "hclk",
324 .parent = &jz_clk_pll,
325 .get_rate = jz_clk_main_get_rate,
326 .set_rate = jz_clk_main_set_rate,
327 .round_rate = jz_clk_main_round_rate,
328 },
329 .div_offset = JZ_CLOCK_CTRL_HDIV_OFFSET,
330 };
331
332
333 static struct main_clk jz_clk_low_speed_peripheral = {
334 .clk = {
335 .name = "pclk",
336 .parent = &jz_clk_pll,
337 .get_rate = jz_clk_main_get_rate,
338 .set_rate = jz_clk_main_set_rate,
339 },
340 .div_offset = JZ_CLOCK_CTRL_PDIV_OFFSET,
341 };
342
343 static struct clk jz_clk_ko = {
344 .name = "cko",
345 .parent = &jz_clk_memory.clk,
346 .enable = jz_clk_ko_enable,
347 .disable = jz_clk_ko_disable,
348 };
349
350 static int jz_clk_spi_set_parent(struct clk *clk, struct clk *parent)
351 {
352 if (parent == &jz_clk_pll)
353 jz_clk_reg_set_bits(JZ_CLOCK_SPI_SRC_PLL, JZ_REG_CLOCK_SPI);
354 else if(parent == &jz_clk_ext.clk)
355 jz_clk_reg_clear_bits(JZ_CLOCK_SPI_SRC_PLL, JZ_REG_CLOCK_SPI);
356 else
357 return -EINVAL;
358
359 clk->parent = parent;
360
361 return 0;
362 }
363
364 static int jz_clk_i2s_set_parent(struct clk *clk, struct clk *parent)
365 {
366 if (parent == &jz_clk_pll_half)
367 jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_I2S_SRC_PLL);
368 else if(parent == &jz_clk_ext.clk)
369 jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_I2S_SRC_PLL);
370 else
371 return -EINVAL;
372
373 clk->parent = parent;
374
375 return 0;
376 }
377
378 static int jz_clk_udc_set_parent(struct clk *clk, struct clk *parent)
379 {
380 if (parent == &jz_clk_pll_half)
381 jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_UDC_SRC_PLL);
382 else if(parent == &jz_clk_ext.clk)
383 jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_UDC_SRC_PLL);
384 else
385 return -EINVAL;
386
387 clk->parent = parent;
388
389 return 0;
390 }
391
392 static int jz_clk_udc_set_rate(struct clk *clk, unsigned long rate)
393 {
394 int div;
395
396 if (clk->parent == &jz_clk_ext.clk)
397 return -EINVAL;
398
399 div = clk_get_rate(clk->parent) / rate - 1;
400
401 if (div < 0)
402 div = 0;
403 else if (div > 63)
404 div = 63;
405
406 jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, div << JZ_CLOCK_CTRL_UDIV_OFFSET,
407 JZ_CLOCK_CTRL_UDIV_MASK);
408 return 0;
409 }
410
411 static unsigned long jz_clk_udc_get_rate(struct clk *clk)
412 {
413 int div;
414
415 if (clk->parent == &jz_clk_ext.clk)
416 return clk_get_rate(clk->parent);
417
418 div = (jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_UDIV_MASK);
419 div >>= JZ_CLOCK_CTRL_UDIV_OFFSET;
420 div += 1;
421
422 return clk_get_rate(clk->parent) / div;
423 }
424
425 static unsigned long jz_clk_divided_get_rate(struct clk *clk)
426 {
427 struct divided_clk *dclk = (struct divided_clk*)clk;
428 int div;
429
430 if (clk->parent == &jz_clk_ext.clk)
431 return clk_get_rate(clk->parent);
432
433 div = (jz_clk_reg_read(dclk->reg) & dclk->mask) + 1;
434
435 return clk_get_rate(clk->parent) / div;
436 }
437
438 static int jz_clk_divided_set_rate(struct clk *clk, unsigned long rate)
439 {
440 struct divided_clk *dclk = (struct divided_clk*)clk;
441 int div;
442
443 if (clk->parent == &jz_clk_ext.clk)
444 return -EINVAL;
445
446 div = clk_get_rate(clk->parent) / rate - 1;
447
448 if (div < 0)
449 div = 0;
450 else if(div > dclk->mask)
451 div = dclk->mask;
452
453 jz_clk_reg_write_mask(dclk->reg, div, dclk->mask);
454
455 return 0;
456 }
457
458 static unsigned long jz_clk_ldclk_round_rate(struct clk *clk, unsigned long rate)
459 {
460 int div;
461 unsigned long parent_rate = jz_clk_pll_half_get_rate(clk->parent);
462
463 if (rate > 150000000)
464 return 150000000;
465
466 div = parent_rate / rate;
467 if (div < 1)
468 div = 1;
469 else if(div > 32)
470 div = 32;
471
472 return parent_rate / div;
473 }
474
475 static int jz_clk_ldclk_set_rate(struct clk *clk, unsigned long rate)
476 {
477 int div;
478
479 if (rate > 150000000)
480 return -EINVAL;
481
482 div = jz_clk_pll_half_get_rate(clk->parent) / rate - 1;
483 if (div < 0)
484 div = 0;
485 else if(div > 31)
486 div = 31;
487
488 jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, div << JZ_CLOCK_CTRL_LDIV_OFFSET,
489 JZ_CLOCK_CTRL_LDIV_MASK);
490
491 return 0;
492 }
493
494 static unsigned long jz_clk_ldclk_get_rate(struct clk *clk)
495 {
496 int div;
497
498 div = jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_LDIV_MASK;
499 div >>= JZ_CLOCK_CTRL_LDIV_OFFSET;
500
501 return jz_clk_pll_half_get_rate(clk->parent) / (div + 1);
502 }
503
504 static struct clk jz_clk_ld = {
505 .name = "lcd",
506 .parent = &jz_clk_pll_half,
507 .set_rate = jz_clk_ldclk_set_rate,
508 .get_rate = jz_clk_ldclk_get_rate,
509 .round_rate = jz_clk_ldclk_round_rate,
510 };
511
512 static struct divided_clk jz_clk_lp = {
513 .clk = {
514 .name = "lcd_pclk",
515 .parent = &jz_clk_pll_half,
516 },
517 .reg = JZ_REG_CLOCK_LCD,
518 .mask = JZ_CLOCK_LCD_DIV_MASK,
519 };
520
521 static struct clk jz_clk_cim_mclk = {
522 .name = "cim_mclk",
523 .parent = &jz_clk_high_speed_peripheral.clk,
524 };
525
526 static struct static_clk jz_clk_cim_pclk = {
527 .clk = {
528 .name = "cim_pclk",
529 .gate_bit = JZ_CLOCK_GATE_CIM,
530 .get_rate = jz_clk_static_get_rate,
531 .enable = jz_clk_enable_gating,
532 .disable = jz_clk_disable_gating,
533 },
534 };
535
536 static struct divided_clk jz_clk_i2s = {
537 .clk = {
538 .name = "i2s",
539 .parent = &jz_clk_ext.clk,
540 .gate_bit = JZ_CLOCK_GATE_AIC,
541 .set_rate = jz_clk_divided_set_rate,
542 .get_rate = jz_clk_divided_get_rate,
543 .enable = jz_clk_enable_gating,
544 .disable = jz_clk_disable_gating,
545 .set_parent = jz_clk_i2s_set_parent,
546 },
547 .reg = JZ_REG_CLOCK_I2S,
548 .mask = JZ_CLOCK_I2S_DIV_MASK,
549 };
550
551 static struct divided_clk jz_clk_mmc = {
552 .clk = {
553 .name = "mmc",
554 .parent = &jz_clk_pll_half,
555 .gate_bit = JZ_CLOCK_GATE_MMC,
556 .set_rate = jz_clk_divided_set_rate,
557 .get_rate = jz_clk_divided_get_rate,
558 .enable = jz_clk_enable_gating,
559 .disable = jz_clk_disable_gating,
560 },
561 .reg = JZ_REG_CLOCK_MMC,
562 .mask = JZ_CLOCK_MMC_DIV_MASK,
563 };
564
565 static struct divided_clk jz_clk_uhc = {
566 .clk = {
567 .name = "uhc",
568 .parent = &jz_clk_pll_half,
569 .gate_bit = JZ_CLOCK_GATE_UHC,
570 .set_rate = jz_clk_divided_set_rate,
571 .get_rate = jz_clk_divided_get_rate,
572 .enable = jz_clk_enable_gating,
573 .disable = jz_clk_disable_gating,
574 },
575 .reg = JZ_REG_CLOCK_UHC,
576 .mask = JZ_CLOCK_UHC_DIV_MASK,
577 };
578
579 static struct clk jz_clk_udc = {
580 .name = "udc",
581 .parent = &jz_clk_ext.clk,
582 .set_parent = jz_clk_udc_set_parent,
583 .set_rate = jz_clk_udc_set_rate,
584 .get_rate = jz_clk_udc_get_rate,
585 };
586
587 static struct divided_clk jz_clk_spi = {
588 .clk = {
589 .name = "spi",
590 .parent = &jz_clk_ext.clk,
591 .gate_bit = JZ_CLOCK_GATE_SPI,
592 .set_rate = jz_clk_divided_set_rate,
593 .get_rate = jz_clk_divided_get_rate,
594 .enable = jz_clk_enable_gating,
595 .disable = jz_clk_disable_gating,
596 .set_parent = jz_clk_spi_set_parent,
597 },
598 .reg = JZ_REG_CLOCK_SPI,
599 .mask = JZ_CLOCK_SPI_DIV_MASK,
600 };
601
602 static struct clk jz_clk_uart0 = {
603 .name = "uart0",
604 .parent = &jz_clk_ext.clk,
605 .gate_bit = JZ_CLOCK_GATE_UART0,
606 .enable = jz_clk_enable_gating,
607 .disable = jz_clk_disable_gating,
608 };
609
610 static struct clk jz_clk_uart1 = {
611 .name = "uart1",
612 .parent = &jz_clk_ext.clk,
613 .gate_bit = JZ_CLOCK_GATE_UART1,
614 .enable = jz_clk_enable_gating,
615 .disable = jz_clk_disable_gating,
616 };
617
618 static struct clk jz_clk_dma = {
619 .name = "dma",
620 .parent = &jz_clk_high_speed_peripheral.clk,
621 .gate_bit = JZ_CLOCK_GATE_UART0,
622 .enable = jz_clk_enable_gating,
623 .disable = jz_clk_disable_gating,
624 };
625
626 static struct clk jz_clk_ipu = {
627 .name = "ipu",
628 .parent = &jz_clk_high_speed_peripheral.clk,
629 .gate_bit = JZ_CLOCK_GATE_IPU,
630 .enable = jz_clk_enable_gating,
631 .disable = jz_clk_disable_gating,
632 };
633
634 static struct clk jz_clk_adc = {
635 .name = "adc",
636 .parent = &jz_clk_ext.clk,
637 .gate_bit = JZ_CLOCK_GATE_ADC,
638 .enable = jz_clk_enable_gating,
639 .disable = jz_clk_disable_gating,
640 };
641
642 static struct clk jz_clk_i2c = {
643 .name = "i2c",
644 .parent = &jz_clk_ext.clk,
645 .gate_bit = JZ_CLOCK_GATE_I2C,
646 .enable = jz_clk_enable_gating,
647 .disable = jz_clk_disable_gating,
648 };
649
650 static struct static_clk jz_clk_rtc = {
651 .clk = {
652 .name = "rtc",
653 .gate_bit = JZ_CLOCK_GATE_RTC,
654 .enable = jz_clk_enable_gating,
655 .disable = jz_clk_disable_gating,
656 },
657 .rate = 32768,
658 };
659
660 int clk_enable(struct clk *clk)
661 {
662 if (!clk->enable)
663 return -EINVAL;
664
665 return clk->enable(clk);
666 }
667 EXPORT_SYMBOL_GPL(clk_enable);
668
669 void clk_disable(struct clk *clk)
670 {
671 if (clk->disable)
672 clk->disable(clk);
673 }
674 EXPORT_SYMBOL_GPL(clk_disable);
675
676 unsigned long clk_get_rate(struct clk *clk)
677 {
678 if (clk->get_rate)
679 return clk->get_rate(clk);
680 if (clk->parent)
681 return clk_get_rate(clk->parent);
682
683 return -EINVAL;
684 }
685 EXPORT_SYMBOL_GPL(clk_get_rate);
686
687 int clk_set_rate(struct clk *clk, unsigned long rate)
688 {
689 if (!clk->set_rate)
690 return -EINVAL;
691 return clk->set_rate(clk, rate);
692 }
693 EXPORT_SYMBOL_GPL(clk_set_rate);
694
695 long clk_round_rate(struct clk *clk, unsigned long rate)
696 {
697 if (clk->round_rate)
698 return clk->round_rate(clk, rate);
699
700 return -EINVAL;
701 }
702 EXPORT_SYMBOL_GPL(clk_round_rate);
703
704 int clk_set_parent(struct clk *clk, struct clk *parent)
705 {
706 int ret;
707
708 if (!clk->set_parent)
709 return -EINVAL;
710
711 clk->disable(clk);
712 ret = clk->set_parent(clk, parent);
713 clk->enable(clk);
714
715 return ret;
716 }
717 EXPORT_SYMBOL_GPL(clk_set_parent);
718
719
720 struct clk *clk_get(struct device *dev, const char *name)
721 {
722 struct clk *clk;
723
724 list_for_each_entry(clk, &jz_clocks, list) {
725 if (strcmp(clk->name, name) == 0)
726 return clk;
727 }
728 return ERR_PTR(-ENOENT);
729 }
730 EXPORT_SYMBOL_GPL(clk_get);
731
732 void clk_put(struct clk *clk)
733 {
734 }
735 EXPORT_SYMBOL_GPL(clk_put);
736
737 inline static void clk_add(struct clk *clk)
738 {
739 list_add_tail(&clk->list, &jz_clocks);
740 }
741
742 static void clk_register_clks(void)
743 {
744 clk_add(&jz_clk_ext.clk);
745 clk_add(&jz_clk_pll);
746 clk_add(&jz_clk_pll_half);
747 clk_add(&jz_clk_cpu.clk);
748 clk_add(&jz_clk_high_speed_peripheral.clk);
749 clk_add(&jz_clk_low_speed_peripheral.clk);
750 clk_add(&jz_clk_ko);
751 clk_add(&jz_clk_ld);
752 clk_add(&jz_clk_lp.clk);
753 clk_add(&jz_clk_cim_mclk);
754 clk_add(&jz_clk_cim_pclk.clk);
755 clk_add(&jz_clk_i2s.clk);
756 clk_add(&jz_clk_mmc.clk);
757 clk_add(&jz_clk_uhc.clk);
758 clk_add(&jz_clk_udc);
759 clk_add(&jz_clk_uart0);
760 clk_add(&jz_clk_uart1);
761 clk_add(&jz_clk_dma);
762 clk_add(&jz_clk_ipu);
763 clk_add(&jz_clk_adc);
764 clk_add(&jz_clk_i2c);
765 clk_add(&jz_clk_rtc.clk);
766 }
767
768 int jz_init_clocks(unsigned long ext_rate)
769 {
770 uint32_t val;
771
772 jz_clock_base = ioremap(0x10000000, 0x100);
773 if (!jz_clock_base)
774 return -EBUSY;
775
776 jz_clk_ext.rate = ext_rate;
777
778 val = jz_clk_reg_read(JZ_REG_CLOCK_SPI);
779
780 if (val & JZ_CLOCK_SPI_SRC_PLL)
781 jz_clk_spi.clk.parent = &jz_clk_pll_half;
782
783 val = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
784
785 if (val & JZ_CLOCK_CTRL_I2S_SRC_PLL)
786 jz_clk_i2s.clk.parent = &jz_clk_pll_half;
787
788 if (val & JZ_CLOCK_CTRL_UDC_SRC_PLL)
789 jz_clk_udc.parent = &jz_clk_pll_half;
790
791 clk_register_clks();
792
793 return 0;
794 }
795 EXPORT_SYMBOL_GPL(jz_init_clocks);