Root/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 clock 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#include <asm/mach-jz4740/clock.h>
26#include "clock.h"
27
28#define JZ_REG_CLOCK_CTRL 0x00
29#define JZ_REG_CLOCK_LOW_POWER 0x04
30#define JZ_REG_CLOCK_PLL 0x10
31#define JZ_REG_CLOCK_GATE 0x20
32#define JZ_REG_CLOCK_SLEEP_CTRL 0x24
33#define JZ_REG_CLOCK_I2S 0x60
34#define JZ_REG_CLOCK_LCD 0x64
35#define JZ_REG_CLOCK_MMC 0x68
36#define JZ_REG_CLOCK_UHC 0x6C
37#define JZ_REG_CLOCK_SPI 0x74
38
39#define JZ_CLOCK_CTRL_I2S_SRC_PLL BIT(31)
40#define JZ_CLOCK_CTRL_KO_ENABLE BIT(30)
41#define JZ_CLOCK_CTRL_UDC_SRC_PLL BIT(29)
42#define JZ_CLOCK_CTRL_UDIV_MASK 0x1f800000
43#define JZ_CLOCK_CTRL_CHANGE_ENABLE BIT(22)
44#define JZ_CLOCK_CTRL_PLL_HALF BIT(21)
45#define JZ_CLOCK_CTRL_LDIV_MASK 0x001f0000
46#define JZ_CLOCK_CTRL_UDIV_OFFSET 23
47#define JZ_CLOCK_CTRL_LDIV_OFFSET 16
48#define JZ_CLOCK_CTRL_MDIV_OFFSET 12
49#define JZ_CLOCK_CTRL_PDIV_OFFSET 8
50#define JZ_CLOCK_CTRL_HDIV_OFFSET 4
51#define JZ_CLOCK_CTRL_CDIV_OFFSET 0
52
53#define JZ_CLOCK_GATE_UART0 BIT(0)
54#define JZ_CLOCK_GATE_TCU BIT(1)
55#define JZ_CLOCK_GATE_RTC BIT(2)
56#define JZ_CLOCK_GATE_I2C BIT(3)
57#define JZ_CLOCK_GATE_SPI BIT(4)
58#define JZ_CLOCK_GATE_AIC BIT(5)
59#define JZ_CLOCK_GATE_I2S BIT(6)
60#define JZ_CLOCK_GATE_MMC BIT(7)
61#define JZ_CLOCK_GATE_ADC BIT(8)
62#define JZ_CLOCK_GATE_CIM BIT(9)
63#define JZ_CLOCK_GATE_LCD BIT(10)
64#define JZ_CLOCK_GATE_UDC BIT(11)
65#define JZ_CLOCK_GATE_DMAC BIT(12)
66#define JZ_CLOCK_GATE_IPU BIT(13)
67#define JZ_CLOCK_GATE_UHC BIT(14)
68#define JZ_CLOCK_GATE_UART1 BIT(15)
69
70#define JZ_CLOCK_I2S_DIV_MASK 0x01ff
71
72#define JZ_CLOCK_LCD_DIV_MASK 0x01ff
73
74#define JZ_CLOCK_MMC_DIV_MASK 0x001f
75
76#define JZ_CLOCK_UHC_DIV_MASK 0x000f
77
78#define JZ_CLOCK_SPI_SRC_PLL BIT(31)
79#define JZ_CLOCK_SPI_DIV_MASK 0x000f
80
81#define JZ_CLOCK_PLL_M_MASK 0x01ff
82#define JZ_CLOCK_PLL_N_MASK 0x001f
83#define JZ_CLOCK_PLL_OD_MASK 0x0003
84#define JZ_CLOCK_PLL_STABLE BIT(10)
85#define JZ_CLOCK_PLL_BYPASS BIT(9)
86#define JZ_CLOCK_PLL_ENABLED BIT(8)
87#define JZ_CLOCK_PLL_STABLIZE_MASK 0x000f
88#define JZ_CLOCK_PLL_M_OFFSET 23
89#define JZ_CLOCK_PLL_N_OFFSET 18
90#define JZ_CLOCK_PLL_OD_OFFSET 16
91
92#define JZ_CLOCK_LOW_POWER_MODE_DOZE BIT(2)
93#define JZ_CLOCK_LOW_POWER_MODE_SLEEP BIT(0)
94
95#define JZ_CLOCK_SLEEP_CTRL_SUSPEND_UHC BIT(7)
96#define JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC BIT(6)
97
98static void __iomem *jz_clock_base;
99static spinlock_t jz_clock_lock;
100static LIST_HEAD(jz_clocks);
101
102struct main_clk {
103    struct clk clk;
104    uint32_t div_offset;
105};
106
107struct divided_clk {
108    struct clk clk;
109    uint32_t reg;
110    uint32_t mask;
111};
112
113struct static_clk {
114    struct clk clk;
115    unsigned long rate;
116};
117
118static uint32_t jz_clk_reg_read(int reg)
119{
120    return readl(jz_clock_base + reg);
121}
122
123static void jz_clk_reg_write_mask(int reg, uint32_t val, uint32_t mask)
124{
125    uint32_t val2;
126
127    spin_lock(&jz_clock_lock);
128    val2 = readl(jz_clock_base + reg);
129    val2 &= ~mask;
130    val2 |= val;
131    writel(val2, jz_clock_base + reg);
132    spin_unlock(&jz_clock_lock);
133}
134
135static void jz_clk_reg_set_bits(int reg, uint32_t mask)
136{
137    uint32_t val;
138
139    spin_lock(&jz_clock_lock);
140    val = readl(jz_clock_base + reg);
141    val |= mask;
142    writel(val, jz_clock_base + reg);
143    spin_unlock(&jz_clock_lock);
144}
145
146static void jz_clk_reg_clear_bits(int reg, uint32_t mask)
147{
148    uint32_t val;
149
150    spin_lock(&jz_clock_lock);
151    val = readl(jz_clock_base + reg);
152    val &= ~mask;
153    writel(val, jz_clock_base + reg);
154    spin_unlock(&jz_clock_lock);
155}
156
157static int jz_clk_enable_gating(struct clk *clk)
158{
159    if (clk->gate_bit == JZ4740_CLK_NOT_GATED)
160        return -EINVAL;
161
162    jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, clk->gate_bit);
163    return 0;
164}
165
166static int jz_clk_disable_gating(struct clk *clk)
167{
168    if (clk->gate_bit == JZ4740_CLK_NOT_GATED)
169        return -EINVAL;
170
171    jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, clk->gate_bit);
172    return 0;
173}
174
175static int jz_clk_is_enabled_gating(struct clk *clk)
176{
177    if (clk->gate_bit == JZ4740_CLK_NOT_GATED)
178        return 1;
179
180    return !(jz_clk_reg_read(JZ_REG_CLOCK_GATE) & clk->gate_bit);
181}
182
183static unsigned long jz_clk_static_get_rate(struct clk *clk)
184{
185    return ((struct static_clk*)clk)->rate;
186}
187
188static int jz_clk_ko_enable(struct clk *clk)
189{
190    jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_KO_ENABLE);
191    return 0;
192}
193
194static int jz_clk_ko_disable(struct clk *clk)
195{
196    jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_KO_ENABLE);
197    return 0;
198}
199
200static int jz_clk_ko_is_enabled(struct clk *clk)
201{
202    return !!(jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_KO_ENABLE);
203}
204
205static const int pllno[] = {1, 2, 2, 4};
206
207static unsigned long jz_clk_pll_get_rate(struct clk *clk)
208{
209    uint32_t val;
210    int m;
211    int n;
212    int od;
213
214    val = jz_clk_reg_read(JZ_REG_CLOCK_PLL);
215
216    if (val & JZ_CLOCK_PLL_BYPASS)
217        return clk_get_rate(clk->parent);
218
219    m = ((val >> 23) & 0x1ff) + 2;
220    n = ((val >> 18) & 0x1f) + 2;
221    od = (val >> 16) & 0x3;
222
223    return clk_get_rate(clk->parent) * (m / n) / pllno[od];
224}
225
226static unsigned long jz_clk_pll_half_get_rate(struct clk *clk)
227{
228    uint32_t reg;
229
230    reg = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
231    if (reg & JZ_CLOCK_CTRL_PLL_HALF)
232        return jz_clk_pll_get_rate(clk->parent);
233    return jz_clk_pll_get_rate(clk->parent) >> 1;
234}
235
236static const int jz_clk_main_divs[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
237
238static unsigned long jz_clk_main_round_rate(struct clk *clk, unsigned long rate)
239{
240    unsigned long parent_rate = jz_clk_pll_get_rate(clk->parent);
241    int div;
242
243    div = parent_rate / rate;
244    if (div > 32)
245        return parent_rate / 32;
246    else if (div < 1)
247        return parent_rate;
248
249    div &= (0x3 << (ffs(div) - 1));
250
251    return parent_rate / div;
252}
253
254static unsigned long jz_clk_main_get_rate(struct clk *clk) {
255    struct main_clk *mclk = (struct main_clk*)clk;
256    uint32_t div;
257
258    div = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
259
260    div >>= mclk->div_offset;
261    div &= 0xf;
262
263    if (div >= ARRAY_SIZE(jz_clk_main_divs))
264        div = ARRAY_SIZE(jz_clk_main_divs) - 1;
265
266    return jz_clk_pll_get_rate(clk->parent) / jz_clk_main_divs[div];
267}
268
269static int jz_clk_main_set_rate(struct clk *clk, unsigned long rate)
270{
271    struct main_clk *mclk = (struct main_clk*)clk;
272    int i;
273    int div;
274    unsigned long parent_rate = jz_clk_pll_get_rate(clk->parent);
275
276    rate = jz_clk_main_round_rate(clk, rate);
277
278    div = parent_rate / rate;
279
280    i = (ffs(div) - 1) << 1;
281    if (i > 0 && !(div & BIT(i-1)))
282        i -= 1;
283
284    jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, i << mclk->div_offset,
285                0xf << mclk->div_offset);
286
287    return 0;
288}
289
290static struct clk_ops jz_clk_static_ops = {
291    .get_rate = jz_clk_static_get_rate,
292    .enable = jz_clk_enable_gating,
293    .disable = jz_clk_disable_gating,
294    .is_enabled = jz_clk_is_enabled_gating,
295};
296
297static struct static_clk jz_clk_ext = {
298    .clk = {
299        .name = "ext",
300        .gate_bit = JZ4740_CLK_NOT_GATED,
301        .ops = &jz_clk_static_ops,
302    },
303};
304
305static struct clk_ops jz_clk_pll_ops = {
306    .get_rate = jz_clk_static_get_rate,
307};
308
309static struct clk jz_clk_pll = {
310    .name = "pll",
311    .parent = &jz_clk_ext.clk,
312    .ops = &jz_clk_pll_ops,
313};
314
315static struct clk_ops jz_clk_pll_half_ops = {
316    .get_rate = jz_clk_pll_half_get_rate,
317};
318
319static struct clk jz_clk_pll_half = {
320    .name = "pll half",
321    .parent = &jz_clk_pll,
322    .ops = &jz_clk_pll_half_ops,
323};
324
325static const struct clk_ops jz_clk_main_ops = {
326    .get_rate = jz_clk_main_get_rate,
327    .set_rate = jz_clk_main_set_rate,
328    .round_rate = jz_clk_main_round_rate,
329};
330
331static struct main_clk jz_clk_cpu = {
332    .clk = {
333        .name = "cclk",
334        .parent = &jz_clk_pll,
335        .ops = &jz_clk_main_ops,
336    },
337    .div_offset = JZ_CLOCK_CTRL_CDIV_OFFSET,
338};
339
340static struct main_clk jz_clk_memory = {
341    .clk = {
342        .name = "mclk",
343        .parent = &jz_clk_pll,
344        .ops = &jz_clk_main_ops,
345    },
346    .div_offset = JZ_CLOCK_CTRL_MDIV_OFFSET,
347};
348
349static struct main_clk jz_clk_high_speed_peripheral = {
350    .clk = {
351        .name = "hclk",
352        .parent = &jz_clk_pll,
353        .ops = &jz_clk_main_ops,
354    },
355    .div_offset = JZ_CLOCK_CTRL_HDIV_OFFSET,
356};
357
358
359static struct main_clk jz_clk_low_speed_peripheral = {
360    .clk = {
361        .name = "pclk",
362        .parent = &jz_clk_pll,
363        .ops = &jz_clk_main_ops,
364    },
365    .div_offset = JZ_CLOCK_CTRL_PDIV_OFFSET,
366};
367
368static const struct clk_ops jz_clk_ko_ops = {
369    .enable = jz_clk_ko_enable,
370    .disable = jz_clk_ko_disable,
371    .is_enabled = jz_clk_ko_is_enabled,
372};
373
374static struct clk jz_clk_ko = {
375    .name = "cko",
376    .parent = &jz_clk_memory.clk,
377    .ops = &jz_clk_ko_ops,
378};
379
380static int jz_clk_spi_set_parent(struct clk *clk, struct clk *parent)
381{
382    if (parent == &jz_clk_pll)
383        jz_clk_reg_set_bits(JZ_CLOCK_SPI_SRC_PLL, JZ_REG_CLOCK_SPI);
384    else if(parent == &jz_clk_ext.clk)
385        jz_clk_reg_clear_bits(JZ_CLOCK_SPI_SRC_PLL, JZ_REG_CLOCK_SPI);
386    else
387        return -EINVAL;
388
389    clk->parent = parent;
390
391    return 0;
392}
393
394static int jz_clk_i2s_set_parent(struct clk *clk, struct clk *parent)
395{
396    if (parent == &jz_clk_pll_half)
397        jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_I2S_SRC_PLL);
398    else if(parent == &jz_clk_ext.clk)
399        jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_I2S_SRC_PLL);
400    else
401        return -EINVAL;
402
403    clk->parent = parent;
404
405    return 0;
406}
407
408static int jz_clk_udc_enable(struct clk *clk)
409{
410    jz_clk_reg_set_bits(JZ_REG_CLOCK_SLEEP_CTRL,
411            JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC);
412
413    return 0;
414}
415
416static int jz_clk_udc_disable(struct clk *clk)
417{
418    jz_clk_reg_clear_bits(JZ_REG_CLOCK_SLEEP_CTRL,
419            JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC);
420
421    return 0;
422}
423
424static int jz_clk_udc_is_enabled(struct clk *clk)
425{
426    return !!(jz_clk_reg_read(JZ_REG_CLOCK_SLEEP_CTRL) &
427            JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC);
428}
429static int jz_clk_udc_set_parent(struct clk *clk, struct clk *parent)
430{
431    if (parent == &jz_clk_pll_half)
432        jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_UDC_SRC_PLL);
433    else if(parent == &jz_clk_ext.clk)
434        jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_UDC_SRC_PLL);
435    else
436        return -EINVAL;
437
438    clk->parent = parent;
439
440    return 0;
441}
442
443static int jz_clk_udc_set_rate(struct clk *clk, unsigned long rate)
444{
445    int div;
446
447    if (clk->parent == &jz_clk_ext.clk)
448        return -EINVAL;
449
450    div = clk_get_rate(clk->parent) / rate - 1;
451
452    if (div < 0)
453        div = 0;
454    else if (div > 63)
455        div = 63;
456
457    jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, div << JZ_CLOCK_CTRL_UDIV_OFFSET,
458                JZ_CLOCK_CTRL_UDIV_MASK);
459    return 0;
460}
461
462static unsigned long jz_clk_udc_get_rate(struct clk *clk)
463{
464    int div;
465
466    if (clk->parent == &jz_clk_ext.clk)
467        return clk_get_rate(clk->parent);
468
469    div = (jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_UDIV_MASK);
470    div >>= JZ_CLOCK_CTRL_UDIV_OFFSET;
471    div += 1;
472
473    return clk_get_rate(clk->parent) / div;
474}
475
476static unsigned long jz_clk_divided_get_rate(struct clk *clk)
477{
478    struct divided_clk *dclk = (struct divided_clk*)clk;
479    int div;
480
481    if (clk->parent == &jz_clk_ext.clk)
482        return clk_get_rate(clk->parent);
483
484    div = (jz_clk_reg_read(dclk->reg) & dclk->mask) + 1;
485
486    return clk_get_rate(clk->parent) / div;
487}
488
489static int jz_clk_divided_set_rate(struct clk *clk, unsigned long rate)
490{
491    struct divided_clk *dclk = (struct divided_clk*)clk;
492    int div;
493
494    if (clk->parent == &jz_clk_ext.clk)
495        return -EINVAL;
496
497    div = clk_get_rate(clk->parent) / rate - 1;
498
499    if (div < 0)
500        div = 0;
501    else if(div > dclk->mask)
502        div = dclk->mask;
503
504    jz_clk_reg_write_mask(dclk->reg, div, dclk->mask);
505
506    return 0;
507}
508
509static unsigned long jz_clk_ldclk_round_rate(struct clk *clk, unsigned long rate)
510{
511    int div;
512    unsigned long parent_rate = jz_clk_pll_half_get_rate(clk->parent);
513
514    if (rate > 150000000)
515        return 150000000;
516
517    div = parent_rate / rate;
518    if (div < 1)
519        div = 1;
520    else if(div > 32)
521        div = 32;
522
523    return parent_rate / div;
524}
525
526static int jz_clk_ldclk_set_rate(struct clk *clk, unsigned long rate)
527{
528    int div;
529
530    if (rate > 150000000)
531        return -EINVAL;
532
533    div = jz_clk_pll_half_get_rate(clk->parent) / rate - 1;
534    if (div < 0)
535        div = 0;
536    else if(div > 31)
537        div = 31;
538
539    jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, div << JZ_CLOCK_CTRL_LDIV_OFFSET,
540                JZ_CLOCK_CTRL_LDIV_MASK);
541
542    return 0;
543}
544
545static unsigned long jz_clk_ldclk_get_rate(struct clk *clk)
546{
547    int div;
548
549    div = jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_LDIV_MASK;
550    div >>= JZ_CLOCK_CTRL_LDIV_OFFSET;
551
552    return jz_clk_pll_half_get_rate(clk->parent) / (div + 1);
553}
554
555static const struct clk_ops jz_clk_ops_ld = {
556    .set_rate = jz_clk_ldclk_set_rate,
557    .get_rate = jz_clk_ldclk_get_rate,
558    .round_rate = jz_clk_ldclk_round_rate,
559    .enable = jz_clk_enable_gating,
560    .disable = jz_clk_disable_gating,
561    .is_enabled = jz_clk_is_enabled_gating,
562};
563
564static struct clk jz_clk_ld = {
565    .name = "lcd",
566    .gate_bit = JZ_CLOCK_GATE_LCD,
567    .parent = &jz_clk_pll_half,
568    .ops = &jz_clk_ops_ld,
569};
570
571/* TODO: ops!!! */
572static struct clk jz_clk_cim_mclk = {
573    .name = "cim_mclk",
574    .parent = &jz_clk_high_speed_peripheral.clk,
575};
576
577static struct static_clk jz_clk_cim_pclk = {
578    .clk = {
579        .name = "cim_pclk",
580        .gate_bit = JZ_CLOCK_GATE_CIM,
581        .ops = &jz_clk_static_ops,
582    },
583};
584
585static const struct clk_ops jz_clk_i2s_ops =
586{
587    .set_rate = jz_clk_divided_set_rate,
588    .get_rate = jz_clk_divided_get_rate,
589    .enable = jz_clk_enable_gating,
590    .disable = jz_clk_disable_gating,
591    .is_enabled = jz_clk_is_enabled_gating,
592    .set_parent = jz_clk_i2s_set_parent,
593};
594
595static const struct clk_ops jz_clk_spi_ops =
596{
597    .set_rate = jz_clk_divided_set_rate,
598    .get_rate = jz_clk_divided_get_rate,
599    .enable = jz_clk_enable_gating,
600    .disable = jz_clk_disable_gating,
601    .is_enabled = jz_clk_is_enabled_gating,
602    .set_parent = jz_clk_spi_set_parent,
603};
604
605static const struct clk_ops jz_clk_divided_ops =
606{
607    .set_rate = jz_clk_divided_set_rate,
608    .get_rate = jz_clk_divided_get_rate,
609    .enable = jz_clk_enable_gating,
610    .disable = jz_clk_disable_gating,
611    .is_enabled = jz_clk_is_enabled_gating,
612};
613
614static struct divided_clk jz4740_clock_divided_clks[] = {
615    {
616        .clk = {
617            .name = "lcd_pclk",
618            .parent = &jz_clk_pll_half,
619            .gate_bit = JZ4740_CLK_NOT_GATED,
620            .ops = &jz_clk_divided_ops,
621        },
622        .reg = JZ_REG_CLOCK_LCD,
623        .mask = JZ_CLOCK_LCD_DIV_MASK,
624    },
625    {
626        .clk = {
627            .name = "i2s",
628            .parent = &jz_clk_ext.clk,
629            .gate_bit = JZ_CLOCK_GATE_I2S,
630            .ops = &jz_clk_i2s_ops,
631        },
632        .reg = JZ_REG_CLOCK_I2S,
633        .mask = JZ_CLOCK_I2S_DIV_MASK,
634    },
635    {
636        .clk = {
637            .name = "spi",
638            .parent = &jz_clk_ext.clk,
639            .gate_bit = JZ_CLOCK_GATE_SPI,
640            .ops = &jz_clk_spi_ops,
641        },
642        .reg = JZ_REG_CLOCK_SPI,
643        .mask = JZ_CLOCK_SPI_DIV_MASK,
644    },
645    {
646        .clk = {
647            .name = "mmc",
648            .parent = &jz_clk_pll_half,
649            .gate_bit = JZ_CLOCK_GATE_MMC,
650            .ops = &jz_clk_divided_ops,
651        },
652        .reg = JZ_REG_CLOCK_MMC,
653        .mask = JZ_CLOCK_MMC_DIV_MASK,
654    },
655    {
656        .clk = {
657            .name = "uhc",
658            .parent = &jz_clk_pll_half,
659            .gate_bit = JZ_CLOCK_GATE_UHC,
660            .ops = &jz_clk_divided_ops,
661        },
662        .reg = JZ_REG_CLOCK_UHC,
663        .mask = JZ_CLOCK_UHC_DIV_MASK,
664    },
665};
666
667static const struct clk_ops jz_clk_udc_ops = {
668    .set_parent = jz_clk_udc_set_parent,
669    .set_rate = jz_clk_udc_set_rate,
670    .get_rate = jz_clk_udc_get_rate,
671    .enable = jz_clk_udc_enable,
672    .disable = jz_clk_udc_disable,
673    .is_enabled = jz_clk_udc_is_enabled,
674};
675
676static const struct clk_ops jz_clk_simple_ops = {
677    .enable = jz_clk_enable_gating,
678    .disable = jz_clk_disable_gating,
679    .is_enabled = jz_clk_is_enabled_gating,
680};
681
682static struct clk jz4740_clock_simple_clks[] = {
683    {
684        .name = "udc",
685        .parent = &jz_clk_ext.clk,
686        .ops = &jz_clk_udc_ops,
687    },
688    {
689        .name = "uart0",
690        .parent = &jz_clk_ext.clk,
691        .gate_bit = JZ_CLOCK_GATE_UART0,
692        .ops = &jz_clk_simple_ops,
693    },
694    {
695        .name = "uart1",
696        .parent = &jz_clk_ext.clk,
697        .gate_bit = JZ_CLOCK_GATE_UART1,
698        .ops = &jz_clk_simple_ops,
699    },
700    {
701        .name = "dma",
702        .parent = &jz_clk_high_speed_peripheral.clk,
703        .gate_bit = JZ_CLOCK_GATE_UART0,
704        .ops = &jz_clk_simple_ops,
705    },
706    {
707        .name = "ipu",
708        .parent = &jz_clk_high_speed_peripheral.clk,
709        .gate_bit = JZ_CLOCK_GATE_IPU,
710        .ops = &jz_clk_simple_ops,
711    },
712    {
713        .name = "adc",
714        .parent = &jz_clk_ext.clk,
715        .gate_bit = JZ_CLOCK_GATE_ADC,
716        .ops = &jz_clk_simple_ops,
717    },
718    {
719        .name = "i2c",
720        .parent = &jz_clk_ext.clk,
721        .gate_bit = JZ_CLOCK_GATE_I2C,
722        .ops = &jz_clk_simple_ops,
723    },
724    {
725        .name = "aic",
726        .parent = &jz_clk_ext.clk,
727        .gate_bit = JZ_CLOCK_GATE_AIC,
728        .ops = &jz_clk_simple_ops,
729    },
730};
731
732static struct static_clk jz_clk_rtc = {
733    .clk = {
734        .name = "rtc",
735        .gate_bit = JZ_CLOCK_GATE_RTC,
736        .ops = &jz_clk_static_ops,
737    },
738    .rate = 32768,
739};
740
741int clk_enable(struct clk *clk)
742{
743    if (!clk->ops->enable)
744        return -EINVAL;
745
746    return clk->ops->enable(clk);
747}
748EXPORT_SYMBOL_GPL(clk_enable);
749
750void clk_disable(struct clk *clk)
751{
752    if (clk->ops->disable)
753        clk->ops->disable(clk);
754}
755EXPORT_SYMBOL_GPL(clk_disable);
756
757int clk_is_enabled(struct clk *clk)
758{
759    if (clk->ops->is_enabled)
760        return clk->ops->is_enabled(clk);
761
762    return 1;
763}
764
765unsigned long clk_get_rate(struct clk *clk)
766{
767    if (clk->ops->get_rate)
768        return clk->ops->get_rate(clk);
769    if (clk->parent)
770        return clk_get_rate(clk->parent);
771
772    return -EINVAL;
773}
774EXPORT_SYMBOL_GPL(clk_get_rate);
775
776int clk_set_rate(struct clk *clk, unsigned long rate)
777{
778    if (!clk->ops->set_rate)
779        return -EINVAL;
780    return clk->ops->set_rate(clk, rate);
781}
782EXPORT_SYMBOL_GPL(clk_set_rate);
783
784long clk_round_rate(struct clk *clk, unsigned long rate)
785{
786    if (clk->ops->round_rate)
787        return clk->ops->round_rate(clk, rate);
788
789    return -EINVAL;
790}
791EXPORT_SYMBOL_GPL(clk_round_rate);
792
793int clk_set_parent(struct clk *clk, struct clk *parent)
794{
795    int ret;
796
797    if (!clk->ops->set_parent)
798        return -EINVAL;
799
800    clk_disable(clk);
801    ret = clk->ops->set_parent(clk, parent);
802    clk_enable(clk);
803
804    jz4740_clock_debugfs_update_parent(clk);
805
806    return ret;
807}
808EXPORT_SYMBOL_GPL(clk_set_parent);
809
810struct clk *clk_get(struct device *dev, const char *name)
811{
812    struct clk *clk;
813
814    list_for_each_entry(clk, &jz_clocks, list) {
815        if (strcmp(clk->name, name) == 0)
816            return clk;
817    }
818    return ERR_PTR(-ENOENT);
819}
820EXPORT_SYMBOL_GPL(clk_get);
821
822void clk_put(struct clk *clk)
823{
824}
825EXPORT_SYMBOL_GPL(clk_put);
826
827
828inline static void clk_add(struct clk *clk)
829{
830    list_add_tail(&clk->list, &jz_clocks);
831
832    jz4740_clock_debugfs_add_clk(clk);
833}
834
835static void clk_register_clks(void)
836{
837    size_t i;
838
839    clk_add(&jz_clk_ext.clk);
840    clk_add(&jz_clk_pll);
841    clk_add(&jz_clk_pll_half);
842    clk_add(&jz_clk_cpu.clk);
843    clk_add(&jz_clk_high_speed_peripheral.clk);
844    clk_add(&jz_clk_low_speed_peripheral.clk);
845    clk_add(&jz_clk_ko);
846    clk_add(&jz_clk_ld);
847    clk_add(&jz_clk_cim_mclk);
848    clk_add(&jz_clk_cim_pclk.clk);
849    clk_add(&jz_clk_rtc.clk);
850
851    for (i = 0; i < ARRAY_SIZE(jz4740_clock_divided_clks); ++i)
852        clk_add(&jz4740_clock_divided_clks[i].clk);
853
854    for (i = 0; i < ARRAY_SIZE(jz4740_clock_simple_clks); ++i)
855        clk_add(&jz4740_clock_simple_clks[i]);
856}
857
858void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode)
859{
860    switch (mode) {
861    case JZ4740_WAIT_MODE_IDLE:
862        jz_clk_reg_clear_bits(JZ_REG_CLOCK_LOW_POWER, JZ_CLOCK_LOW_POWER_MODE_SLEEP);
863        break;
864    case JZ4740_WAIT_MODE_SLEEP:
865        jz_clk_reg_set_bits(JZ_REG_CLOCK_LOW_POWER, JZ_CLOCK_LOW_POWER_MODE_SLEEP);
866        break;
867    }
868}
869
870void jz4740_clock_udc_disable_auto_suspend(void)
871{
872    jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, JZ_CLOCK_GATE_UDC);
873}
874EXPORT_SYMBOL_GPL(jz4740_clock_udc_disable_auto_suspend);
875
876void jz4740_clock_udc_enable_auto_suspend(void)
877{
878    jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, JZ_CLOCK_GATE_UDC);
879}
880EXPORT_SYMBOL_GPL(jz4740_clock_udc_enable_auto_suspend);
881
882void jz4740_clock_suspend(void)
883{
884    jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE,
885        JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0);
886
887    jz_clk_reg_clear_bits(JZ_REG_CLOCK_PLL, JZ_CLOCK_PLL_ENABLED);
888}
889
890void jz4740_clock_resume(void)
891{
892    jz_clk_reg_set_bits(JZ_REG_CLOCK_PLL, JZ_CLOCK_PLL_ENABLED);
893    while ((jz_clk_reg_read(JZ_REG_CLOCK_PLL) & JZ_CLOCK_PLL_STABLE) == 0);
894
895    jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE,
896        JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0);
897}
898
899int jz4740_clock_init(void)
900{
901    uint32_t val;
902
903    jz_clock_base = ioremap(CPHYSADDR(CPM_BASE), 0x100);
904    if (!jz_clock_base)
905        return -EBUSY;
906
907    spin_lock_init(&jz_clock_lock);
908
909    jz_clk_ext.rate = jz4740_clock_bdata.ext_rate;
910    jz_clk_rtc.rate = jz4740_clock_bdata.rtc_rate;
911
912    val = jz_clk_reg_read(JZ_REG_CLOCK_SPI);
913
914    if (val & JZ_CLOCK_SPI_SRC_PLL)
915        jz4740_clock_divided_clks[1].clk.parent = &jz_clk_pll_half;
916
917    val = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
918
919    if (val & JZ_CLOCK_CTRL_I2S_SRC_PLL)
920        jz4740_clock_divided_clks[0].clk.parent = &jz_clk_pll_half;
921
922    if (val & JZ_CLOCK_CTRL_UDC_SRC_PLL)
923        jz4740_clock_simple_clks[0].parent = &jz_clk_pll_half;
924
925    jz4740_clock_debugfs_init();
926
927    clk_register_clks();
928
929    return 0;
930}
931

Archive Download this file



interactive