Merge xburst target.
[librecmc/librecmc.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);