Root/arch/mips/jz4740/clock.c

Source at commit bf21f890cc3c03d9dbf7cb2fa33fdabf752659a4 created 8 years 6 months ago.
By Maarten ter Huurne, MIPS: JZ4740: Correct clock gate bit for DMA controller
1/*
2 * Copyright (c) 2006-2007, Ingenic Semiconductor Inc.
3 * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
4 * Copyright (c) 2010, Ulrich Hecht <ulrich.hecht@gmail.com>
5 * Copyright (c) 2010, Maarten ter Huurne <maarten@treewalker.org>
6 * JZ4740 SoC clock support
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 675 Mass Ave, Cambridge, MA 02139, USA.
16 *
17 */
18
19#include <linux/kernel.h>
20#include <linux/errno.h>
21#include <linux/clk.h>
22#include <linux/spinlock.h>
23#include <linux/io.h>
24#include <linux/module.h>
25#include <linux/list.h>
26#include <linux/err.h>
27
28#include <asm/mach-jz4740/clock.h>
29#include <asm/mach-jz4740/base.h>
30
31#include "clock.h"
32
33#define JZ_REG_CLOCK_CTRL 0x00
34#define JZ_REG_CLOCK_LOW_POWER 0x04
35#define JZ_REG_CLOCK_PLL 0x10
36#define JZ_REG_CLOCK_GATE 0x20
37#define JZ_REG_CLOCK_SLEEP_CTRL 0x24
38#define JZ_REG_CLOCK_I2S 0x60
39#define JZ_REG_CLOCK_LCD 0x64
40#define JZ_REG_CLOCK_MMC 0x68
41#define JZ_REG_CLOCK_UHC 0x6C
42#define JZ_REG_CLOCK_SPI 0x74
43
44#define JZ_CLOCK_CTRL_I2S_SRC_PLL BIT(31)
45#define JZ_CLOCK_CTRL_KO_ENABLE BIT(30)
46#define JZ_CLOCK_CTRL_UDC_SRC_PLL BIT(29)
47#define JZ_CLOCK_CTRL_CHANGE_ENABLE BIT(22)
48#define JZ_CLOCK_CTRL_PLL_HALF BIT(21)
49#define JZ_CLOCK_CTRL_UDIV_OFFSET 23
50#define JZ_CLOCK_CTRL_LDIV_OFFSET 16
51#define JZ_CLOCK_CTRL_MDIV_OFFSET 12
52#define JZ_CLOCK_CTRL_PDIV_OFFSET 8
53#define JZ_CLOCK_CTRL_HDIV_OFFSET 4
54#define JZ_CLOCK_CTRL_CDIV_OFFSET 0
55#define JZ_CLOCK_CTRL_UDIV_MASK (0x3f << JZ_CLOCK_CTRL_UDIV_OFFSET)
56#define JZ_CLOCK_CTRL_LDIV_MASK (0x1f << JZ_CLOCK_CTRL_LDIV_OFFSET)
57#define JZ_CLOCK_CTRL_MDIV_MASK (0x0f << JZ_CLOCK_CTRL_MDIV_OFFSET)
58#define JZ_CLOCK_CTRL_PDIV_MASK (0x0f << JZ_CLOCK_CTRL_PDIV_OFFSET)
59#define JZ_CLOCK_CTRL_HDIV_MASK (0x0f << JZ_CLOCK_CTRL_HDIV_OFFSET)
60#define JZ_CLOCK_CTRL_CDIV_MASK (0x0f << JZ_CLOCK_CTRL_CDIV_OFFSET)
61
62#define JZ_CLOCK_GATE_UART0 BIT(0)
63#define JZ_CLOCK_GATE_TCU BIT(1)
64#define JZ_CLOCK_GATE_RTC BIT(2)
65#define JZ_CLOCK_GATE_I2C BIT(3)
66#define JZ_CLOCK_GATE_SPI BIT(4)
67#define JZ_CLOCK_GATE_AIC BIT(5)
68#define JZ_CLOCK_GATE_I2S BIT(6)
69#define JZ_CLOCK_GATE_MMC BIT(7)
70#define JZ_CLOCK_GATE_ADC BIT(8)
71#define JZ_CLOCK_GATE_CIM BIT(9)
72#define JZ_CLOCK_GATE_LCD BIT(10)
73#define JZ_CLOCK_GATE_UDC BIT(11)
74#define JZ_CLOCK_GATE_DMAC BIT(12)
75#define JZ_CLOCK_GATE_IPU BIT(13)
76#define JZ_CLOCK_GATE_UHC BIT(14)
77#define JZ_CLOCK_GATE_UART1 BIT(15)
78
79#define JZ_CLOCK_I2S_DIV_MASK 0x01ff
80
81#define JZ_CLOCK_LCD_DIV_MASK 0x01ff
82
83#define JZ_CLOCK_MMC_DIV_MASK 0x001f
84
85#define JZ_CLOCK_UHC_DIV_MASK 0x000f
86
87#define JZ_CLOCK_SPI_SRC_PLL BIT(31)
88#define JZ_CLOCK_SPI_DIV_MASK 0x000f
89
90#define JZ_CLOCK_PLL_M_MASK 0x01ff
91#define JZ_CLOCK_PLL_N_MASK 0x001f
92#define JZ_CLOCK_PLL_OD_MASK 0x0003
93#define JZ_CLOCK_PLL_STABLE BIT(10)
94#define JZ_CLOCK_PLL_BYPASS BIT(9)
95#define JZ_CLOCK_PLL_ENABLED BIT(8)
96#define JZ_CLOCK_PLL_STABLIZE_MASK 0x000f
97#define JZ_CLOCK_PLL_M_OFFSET 23
98#define JZ_CLOCK_PLL_N_OFFSET 18
99#define JZ_CLOCK_PLL_OD_OFFSET 16
100#define JZ_CLOCK_PLL_STABILIZE_OFFSET 0
101
102#define JZ_CLOCK_LOW_POWER_MODE_DOZE BIT(2)
103#define JZ_CLOCK_LOW_POWER_MODE_SLEEP BIT(0)
104
105#define JZ_CLOCK_SLEEP_CTRL_SUSPEND_UHC BIT(7)
106#define JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC BIT(6)
107
108#define JZ_REG_EMC_RTCNT 0x88
109#define JZ_REG_EMC_RTCOR 0x8C
110
111static void __iomem *jz_clock_base;
112static spinlock_t jz_clock_lock;
113static LIST_HEAD(jz_clocks);
114
115static void __iomem *jz_emc_base;
116
117struct main_clk {
118    struct clk clk;
119    uint32_t div_offset;
120};
121
122struct divided_clk {
123    struct clk clk;
124    uint32_t reg;
125    uint32_t mask;
126};
127
128struct static_clk {
129    struct clk clk;
130    unsigned long rate;
131};
132
133static uint32_t jz_clk_reg_read(int reg)
134{
135    return readl(jz_clock_base + reg);
136}
137
138static void jz_clk_reg_write_mask(int reg, uint32_t val, uint32_t mask)
139{
140    uint32_t val2;
141
142    spin_lock(&jz_clock_lock);
143    val2 = readl(jz_clock_base + reg);
144    val2 &= ~mask;
145    val2 |= val;
146    writel(val2, jz_clock_base + reg);
147    spin_unlock(&jz_clock_lock);
148}
149
150static void jz_clk_reg_set_bits(int reg, uint32_t mask)
151{
152    uint32_t val;
153
154    spin_lock(&jz_clock_lock);
155    val = readl(jz_clock_base + reg);
156    val |= mask;
157    writel(val, jz_clock_base + reg);
158    spin_unlock(&jz_clock_lock);
159}
160
161static void jz_clk_reg_clear_bits(int reg, uint32_t mask)
162{
163    uint32_t val;
164
165    spin_lock(&jz_clock_lock);
166    val = readl(jz_clock_base + reg);
167    val &= ~mask;
168    writel(val, jz_clock_base + reg);
169    spin_unlock(&jz_clock_lock);
170}
171
172static int jz_clk_enable_gating(struct clk *clk)
173{
174    if (clk->gate_bit == JZ4740_CLK_NOT_GATED)
175        return -EINVAL;
176
177    jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, clk->gate_bit);
178    return 0;
179}
180
181static int jz_clk_disable_gating(struct clk *clk)
182{
183    if (clk->gate_bit == JZ4740_CLK_NOT_GATED)
184        return -EINVAL;
185
186    jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, clk->gate_bit);
187    return 0;
188}
189
190static int jz_clk_is_enabled_gating(struct clk *clk)
191{
192    if (clk->gate_bit == JZ4740_CLK_NOT_GATED)
193        return 1;
194
195    return !(jz_clk_reg_read(JZ_REG_CLOCK_GATE) & clk->gate_bit);
196}
197
198static unsigned long jz_clk_static_get_rate(struct clk *clk)
199{
200    return ((struct static_clk *)clk)->rate;
201}
202
203static int jz_clk_ko_enable(struct clk *clk)
204{
205    jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_KO_ENABLE);
206    return 0;
207}
208
209static int jz_clk_ko_disable(struct clk *clk)
210{
211    jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_KO_ENABLE);
212    return 0;
213}
214
215static int jz_clk_ko_is_enabled(struct clk *clk)
216{
217    return !!(jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_KO_ENABLE);
218}
219
220static struct static_clk jz_clk_ext;
221
222static unsigned long jz_clk_pll_calc_rate(
223    unsigned int in_div, unsigned int feedback, unsigned int out_div)
224{
225    return ((jz_clk_ext.rate / in_div) * feedback) / out_div;
226}
227
228static void jz_clk_pll_calc_dividers(unsigned long rate,
229    unsigned int *in_div, unsigned int *feedback, unsigned int *out_div)
230{
231    unsigned int target;
232
233    /* The frequency after the input divider must be between 1 and 15 MHz.
234       The highest divider yields the best resolution. */
235    *in_div = jz_clk_ext.rate / 1000000;
236    if (*in_div >= 34)
237        *in_div = 33;
238
239    /* The frequency before the output divider must be between 100 and
240       500 MHz. The lowest target rate is more energy efficient. */
241    if (rate < 25000000) {
242        *out_div = 4;
243        target = 25000000 * 4;
244    } else if (rate <= 50000000) {
245        *out_div = 4;
246        target = rate * 4;
247    } else if (rate <= 100000000) {
248        *out_div = 2;
249        target = rate * 2;
250    } else if (rate <= 500000000) {
251        *out_div = 1;
252        target = rate;
253    } else {
254        *out_div = 1;
255        target = 500000000;
256    }
257
258    /* Compute the feedback divider.
259       Since the divided input is at least 1 MHz and the target frequency
260       at most 500 MHz, the feedback will be at most 500 and will therefore
261       always fit in the 9-bit register.
262       Similarly, the divided input is at most 15 MHz and the target
263       frequency at least 100 MHz, so the feedback will be at least 6
264       where the minimum supported value is 2. */
265    *feedback = ((target / 1000) * *in_div) / (jz_clk_ext.rate / 1000);
266}
267
268static unsigned long jz_clk_pll_round_rate(struct clk *clk, unsigned long rate)
269{
270    unsigned int in_div, feedback, out_div;
271    /* The PLL frequency must be a multiple of 24 MHz, since the LCD pixel
272     * clock must be exactly 12 MHz for the TV-out to work.
273     * TODO: A multiple of 12 MHz for the PLL would work if the PLL would
274     * not be divided by 2 before being passed to the set of derived
275     * clocks that includes the LCD pixel clock.
276     * TODO: Systemwide decisions like this should be made by the board
277     * support code, so add some kind of hook for that.
278     */
279    unsigned long rate24 = (rate / 24000000) * 24000000;
280
281    jz_clk_pll_calc_dividers(rate24, &in_div, &feedback, &out_div);
282    return jz_clk_pll_calc_rate(in_div, feedback, out_div);
283}
284
285static const int pllno[] = {1, 2, 2, 4};
286
287static unsigned long jz_clk_pll_get_rate(struct clk *clk)
288{
289    uint32_t val;
290    unsigned int in_div, feedback, out_div;
291
292    val = jz_clk_reg_read(JZ_REG_CLOCK_PLL);
293
294    if (val & JZ_CLOCK_PLL_BYPASS)
295        return clk_get_rate(clk->parent);
296
297    feedback = ((val >> 23) & 0x1ff) + 2;
298    in_div = ((val >> 18) & 0x1f) + 2;
299    out_div = pllno[(val >> 16) & 0x3];
300
301    return jz_clk_pll_calc_rate(in_div, feedback, out_div);
302}
303
304static unsigned long jz_clk_pll_half_get_rate(struct clk *clk)
305{
306    uint32_t reg;
307
308    reg = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
309    if (reg & JZ_CLOCK_CTRL_PLL_HALF)
310        return jz_clk_pll_get_rate(clk->parent);
311    return jz_clk_pll_get_rate(clk->parent) >> 1;
312}
313
314#define SDRAM_TREF 15625 /* Refresh period: 4096 refresh cycles/64ms */
315
316static void sdram_set_pll(unsigned int pllin)
317{
318    unsigned int ns, sdramclock;
319
320    ns = 1000000000 / pllin;
321    sdramclock = (SDRAM_TREF / ns) / 64 + 1;
322    if (sdramclock > 0xff) sdramclock = 0xff;
323    /* Set refresh registers */
324    writew(sdramclock, jz_emc_base + JZ_REG_EMC_RTCOR);
325    writew(sdramclock, jz_emc_base + JZ_REG_EMC_RTCNT);
326}
327
328static int jz_clk_pll_set_rate(struct clk *clk, unsigned long rate)
329{
330    unsigned int ctrl, plcr1;
331    unsigned int feedback, in_div, out_div, pllout, pllout2;
332
333    jz_clk_pll_calc_dividers(rate, &in_div, &feedback, &out_div);
334
335    ctrl = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
336    pllout = jz_clk_pll_calc_rate(in_div, feedback, out_div);
337    pllout2 = (ctrl & JZ_CLOCK_CTRL_PLL_HALF) ? pllout : (pllout / 2);
338
339    /* Init UHC clock */
340    writel(pllout2 / 48000000 - 1, jz_clock_base + JZ_REG_CLOCK_UHC);
341
342    plcr1 = ((feedback - 2) << JZ_CLOCK_PLL_M_OFFSET) |
343        ((in_div - 2) << JZ_CLOCK_PLL_N_OFFSET) |
344        ((out_div - 1) << JZ_CLOCK_PLL_OD_OFFSET) |
345        (0x20 << JZ_CLOCK_PLL_STABILIZE_OFFSET) |
346        JZ_CLOCK_PLL_ENABLED;
347
348    sdram_set_pll(pllout);
349
350    /* LCD pixclock */
351    writel(pllout2 / 12000000 - 1, jz_clock_base + JZ_REG_CLOCK_LCD);
352
353    /* configure PLL */
354    __asm__ __volatile__(
355        ".set noreorder\n\t"
356        ".align 5\n"
357        "sw %1,0(%0)\n\t"
358        "nop\n\t"
359        "nop\n\t"
360        "nop\n\t"
361        "nop\n\t"
362        "nop\n\t"
363        "nop\n\t"
364        "nop\n\t"
365        ".set reorder\n\t"
366        :
367        : "r" (jz_clock_base + JZ_REG_CLOCK_PLL), "r" (plcr1));
368
369    /* MtH: For some reason the MSC will have problems if this flag is not
370            restored, even though the MSC is supposedly the only divider
371            that is not affected by this flag. */
372    jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_CHANGE_ENABLE);
373
374    return 0;
375}
376
377static const unsigned int jz_clk_main_divs[] = {
378    1, 2, 3, 4, 6, 8, 12, 16, 24, 32
379};
380static const unsigned int jz_clk_main_divs_inv[] = {
381    -1, 0, 1, 2, 3, -1, 4, -1, 5, -1, -1, -1, 6, -1, -1, -1,
382     7, -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, -1, -1, -1, -1, -1,
383     9
384};
385
386static unsigned long jz_clk_main_round_rate(struct clk *clk, unsigned long rate)
387{
388    unsigned long parent_rate = jz_clk_pll_get_rate(clk->parent);
389    int div;
390
391    div = parent_rate / rate;
392    if (div > 32)
393        return parent_rate / 32;
394    else if (div < 1)
395        return parent_rate;
396
397    div &= (0x3 << (ffs(div) - 1));
398
399    return parent_rate / div;
400}
401
402static unsigned long jz_clk_main_get_rate(struct clk *clk)
403{
404    struct main_clk *mclk = (struct main_clk *)clk;
405    uint32_t div;
406
407    div = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
408
409    div >>= mclk->div_offset;
410    div &= 0xf;
411
412    if (div >= ARRAY_SIZE(jz_clk_main_divs))
413        div = ARRAY_SIZE(jz_clk_main_divs) - 1;
414
415    return jz_clk_pll_get_rate(clk->parent) / jz_clk_main_divs[div];
416}
417
418static int jz_clk_main_set_rate(struct clk *clk, unsigned long rate)
419{
420    struct main_clk *mclk = (struct main_clk *)clk;
421    int i;
422    int div;
423    unsigned long parent_rate = jz_clk_pll_get_rate(clk->parent);
424
425    rate = jz_clk_main_round_rate(clk, rate);
426
427    div = parent_rate / rate;
428
429    i = (ffs(div) - 1) << 1;
430    if (i > 0 && !(div & BIT(i-1)))
431        i -= 1;
432
433    jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, i << mclk->div_offset,
434                0xf << mclk->div_offset);
435
436    return 0;
437}
438
439static struct main_clk jz_clk_cpu;
440
441int clk_main_set_dividers(bool immediate, unsigned int cdiv, unsigned int hdiv,
442              unsigned int mdiv, unsigned int pdiv)
443{
444    unsigned int cdiv_enc, hdiv_enc, mdiv_enc, pdiv_enc;
445    unsigned int ctrl;
446    unsigned int tmp, wait;
447
448    if (cdiv >= ARRAY_SIZE(jz_clk_main_divs_inv) ||
449        hdiv >= ARRAY_SIZE(jz_clk_main_divs_inv) ||
450        mdiv >= ARRAY_SIZE(jz_clk_main_divs_inv) ||
451        pdiv >= ARRAY_SIZE(jz_clk_main_divs_inv))
452        return -EINVAL;
453    cdiv_enc = jz_clk_main_divs_inv[cdiv];
454    hdiv_enc = jz_clk_main_divs_inv[hdiv];
455    mdiv_enc = jz_clk_main_divs_inv[mdiv];
456    pdiv_enc = jz_clk_main_divs_inv[pdiv];
457    if (cdiv_enc == (unsigned int)-1 ||
458        hdiv_enc == (unsigned int)-1 ||
459        mdiv_enc == (unsigned int)-1 ||
460        pdiv_enc == (unsigned int)-1)
461        return -EINVAL;
462
463    ctrl = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
464    ctrl &= ~(JZ_CLOCK_CTRL_CHANGE_ENABLE |
465          JZ_CLOCK_CTRL_CDIV_MASK | JZ_CLOCK_CTRL_HDIV_MASK |
466          JZ_CLOCK_CTRL_MDIV_MASK | JZ_CLOCK_CTRL_PDIV_MASK);
467    if (immediate) ctrl |= JZ_CLOCK_CTRL_CHANGE_ENABLE;
468    ctrl |= (cdiv_enc << JZ_CLOCK_CTRL_CDIV_OFFSET) |
469        (hdiv_enc << JZ_CLOCK_CTRL_HDIV_OFFSET) |
470        (mdiv_enc << JZ_CLOCK_CTRL_MDIV_OFFSET) |
471        (pdiv_enc << JZ_CLOCK_CTRL_PDIV_OFFSET);
472
473    /* set dividers */
474    /* delay loops lifted from the old Ingenic cpufreq driver */
475    wait = ((clk_get_rate(&jz_clk_cpu.clk) / 1000000) * 500) / 1000;
476    __asm__ __volatile__(
477        ".set noreorder\n\t"
478        ".align 5\n"
479        "sw %2,0(%1)\n\t"
480        "li %0,0\n\t"
481        "1:\n\t"
482        "bne %0,%3,1b\n\t"
483        "addi %0, 1\n\t"
484        "nop\n\t"
485        "nop\n\t"
486        "nop\n\t"
487        "nop\n\t"
488        ".set reorder\n\t"
489        : "=r" (tmp)
490        : "r" (jz_clock_base + JZ_REG_CLOCK_CTRL), "r" (ctrl),
491          "r" (wait));
492
493    return 0;
494}
495EXPORT_SYMBOL_GPL(clk_main_set_dividers);
496
497static struct clk_ops jz_clk_static_ops = {
498    .get_rate = jz_clk_static_get_rate,
499    .enable = jz_clk_enable_gating,
500    .disable = jz_clk_disable_gating,
501    .is_enabled = jz_clk_is_enabled_gating,
502};
503
504static struct static_clk jz_clk_ext = {
505    .clk = {
506        .name = "ext",
507        .gate_bit = JZ4740_CLK_NOT_GATED,
508        .ops = &jz_clk_static_ops,
509    },
510};
511
512static struct clk_ops jz_clk_pll_ops = {
513    .get_rate = jz_clk_pll_get_rate,
514    .set_rate = jz_clk_pll_set_rate,
515    .round_rate = jz_clk_pll_round_rate,
516};
517
518static struct clk jz_clk_pll = {
519    .name = "pll",
520    .parent = &jz_clk_ext.clk,
521    .ops = &jz_clk_pll_ops,
522};
523
524static struct clk_ops jz_clk_pll_half_ops = {
525    .get_rate = jz_clk_pll_half_get_rate,
526};
527
528static struct clk jz_clk_pll_half = {
529    .name = "pll half",
530    .parent = &jz_clk_pll,
531    .ops = &jz_clk_pll_half_ops,
532};
533
534static const struct clk_ops jz_clk_main_ops = {
535    .get_rate = jz_clk_main_get_rate,
536    .set_rate = jz_clk_main_set_rate,
537    .round_rate = jz_clk_main_round_rate,
538};
539
540static struct main_clk jz_clk_cpu = {
541    .clk = {
542        .name = "cclk",
543        .parent = &jz_clk_pll,
544        .ops = &jz_clk_main_ops,
545    },
546    .div_offset = JZ_CLOCK_CTRL_CDIV_OFFSET,
547};
548
549static struct main_clk jz_clk_memory = {
550    .clk = {
551        .name = "mclk",
552        .parent = &jz_clk_pll,
553        .ops = &jz_clk_main_ops,
554    },
555    .div_offset = JZ_CLOCK_CTRL_MDIV_OFFSET,
556};
557
558static struct main_clk jz_clk_high_speed_peripheral = {
559    .clk = {
560        .name = "hclk",
561        .parent = &jz_clk_pll,
562        .ops = &jz_clk_main_ops,
563    },
564    .div_offset = JZ_CLOCK_CTRL_HDIV_OFFSET,
565};
566
567
568static struct main_clk jz_clk_low_speed_peripheral = {
569    .clk = {
570        .name = "pclk",
571        .parent = &jz_clk_pll,
572        .ops = &jz_clk_main_ops,
573    },
574    .div_offset = JZ_CLOCK_CTRL_PDIV_OFFSET,
575};
576
577static const struct clk_ops jz_clk_ko_ops = {
578    .enable = jz_clk_ko_enable,
579    .disable = jz_clk_ko_disable,
580    .is_enabled = jz_clk_ko_is_enabled,
581};
582
583static struct clk jz_clk_ko = {
584    .name = "cko",
585    .parent = &jz_clk_memory.clk,
586    .ops = &jz_clk_ko_ops,
587};
588
589static int jz_clk_spi_set_parent(struct clk *clk, struct clk *parent)
590{
591    if (parent == &jz_clk_pll)
592        jz_clk_reg_set_bits(JZ_CLOCK_SPI_SRC_PLL, JZ_REG_CLOCK_SPI);
593    else if (parent == &jz_clk_ext.clk)
594        jz_clk_reg_clear_bits(JZ_CLOCK_SPI_SRC_PLL, JZ_REG_CLOCK_SPI);
595    else
596        return -EINVAL;
597
598    clk->parent = parent;
599
600    return 0;
601}
602
603static int jz_clk_i2s_set_parent(struct clk *clk, struct clk *parent)
604{
605    if (parent == &jz_clk_pll_half)
606        jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_I2S_SRC_PLL);
607    else if (parent == &jz_clk_ext.clk)
608        jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_I2S_SRC_PLL);
609    else
610        return -EINVAL;
611
612    clk->parent = parent;
613
614    return 0;
615}
616
617static int jz_clk_udc_enable(struct clk *clk)
618{
619    jz_clk_reg_set_bits(JZ_REG_CLOCK_SLEEP_CTRL,
620            JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC);
621
622    return 0;
623}
624
625static int jz_clk_udc_disable(struct clk *clk)
626{
627    jz_clk_reg_clear_bits(JZ_REG_CLOCK_SLEEP_CTRL,
628            JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC);
629
630    return 0;
631}
632
633static int jz_clk_udc_is_enabled(struct clk *clk)
634{
635    return !!(jz_clk_reg_read(JZ_REG_CLOCK_SLEEP_CTRL) &
636            JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC);
637}
638
639static int jz_clk_udc_set_parent(struct clk *clk, struct clk *parent)
640{
641    if (parent == &jz_clk_pll_half)
642        jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_UDC_SRC_PLL);
643    else if (parent == &jz_clk_ext.clk)
644        jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_UDC_SRC_PLL);
645    else
646        return -EINVAL;
647
648    clk->parent = parent;
649
650    return 0;
651}
652
653static int jz_clk_udc_set_rate(struct clk *clk, unsigned long rate)
654{
655    int div;
656
657    if (clk->parent == &jz_clk_ext.clk)
658        return -EINVAL;
659
660    div = clk_get_rate(clk->parent) / rate - 1;
661
662    if (div < 0)
663        div = 0;
664    else if (div > 63)
665        div = 63;
666
667    jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, div << JZ_CLOCK_CTRL_UDIV_OFFSET,
668                JZ_CLOCK_CTRL_UDIV_MASK);
669    return 0;
670}
671
672static unsigned long jz_clk_udc_get_rate(struct clk *clk)
673{
674    int div;
675
676    if (clk->parent == &jz_clk_ext.clk)
677        return clk_get_rate(clk->parent);
678
679    div = (jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_UDIV_MASK);
680    div >>= JZ_CLOCK_CTRL_UDIV_OFFSET;
681    div += 1;
682
683    return clk_get_rate(clk->parent) / div;
684}
685
686static unsigned long jz_clk_divided_get_rate(struct clk *clk)
687{
688    struct divided_clk *dclk = (struct divided_clk *)clk;
689    int div;
690
691    if (clk->parent == &jz_clk_ext.clk)
692        return clk_get_rate(clk->parent);
693
694    div = (jz_clk_reg_read(dclk->reg) & dclk->mask) + 1;
695
696    return clk_get_rate(clk->parent) / div;
697}
698
699static int jz_clk_divided_set_rate(struct clk *clk, unsigned long rate)
700{
701    struct divided_clk *dclk = (struct divided_clk *)clk;
702    int div;
703
704    if (clk->parent == &jz_clk_ext.clk)
705        return -EINVAL;
706
707    div = clk_get_rate(clk->parent) / rate - 1;
708
709    if (div < 0)
710        div = 0;
711    else if (div > dclk->mask)
712        div = dclk->mask;
713
714    jz_clk_reg_write_mask(dclk->reg, div, dclk->mask);
715
716    return 0;
717}
718
719static unsigned long jz_clk_ldclk_round_rate(struct clk *clk, unsigned long rate)
720{
721    int div;
722    unsigned long parent_rate = jz_clk_pll_half_get_rate(clk->parent);
723
724    if (rate > 150000000)
725        return 150000000;
726
727    div = parent_rate / rate;
728    if (div < 1)
729        div = 1;
730    else if (div > 32)
731        div = 32;
732
733    return parent_rate / div;
734}
735
736static int jz_clk_ldclk_set_rate(struct clk *clk, unsigned long rate)
737{
738    int div;
739
740    if (rate > 150000000)
741        return -EINVAL;
742
743    div = jz_clk_pll_half_get_rate(clk->parent) / rate - 1;
744    if (div < 0)
745        div = 0;
746    else if (div > 31)
747        div = 31;
748
749    jz_clk_reg_write_mask(JZ_REG_CLOCK_CTRL, div << JZ_CLOCK_CTRL_LDIV_OFFSET,
750                JZ_CLOCK_CTRL_LDIV_MASK);
751
752    return 0;
753}
754
755static unsigned long jz_clk_ldclk_get_rate(struct clk *clk)
756{
757    int div;
758
759    div = jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_LDIV_MASK;
760    div >>= JZ_CLOCK_CTRL_LDIV_OFFSET;
761
762    return jz_clk_pll_half_get_rate(clk->parent) / (div + 1);
763}
764
765static const struct clk_ops jz_clk_ops_ld = {
766    .set_rate = jz_clk_ldclk_set_rate,
767    .get_rate = jz_clk_ldclk_get_rate,
768    .round_rate = jz_clk_ldclk_round_rate,
769    .enable = jz_clk_enable_gating,
770    .disable = jz_clk_disable_gating,
771    .is_enabled = jz_clk_is_enabled_gating,
772};
773
774static struct clk jz_clk_ld = {
775    .name = "lcd",
776    .gate_bit = JZ_CLOCK_GATE_LCD,
777    .parent = &jz_clk_pll_half,
778    .ops = &jz_clk_ops_ld,
779};
780
781static const struct clk_ops jz_clk_i2s_ops = {
782    .set_rate = jz_clk_divided_set_rate,
783    .get_rate = jz_clk_divided_get_rate,
784    .enable = jz_clk_enable_gating,
785    .disable = jz_clk_disable_gating,
786    .is_enabled = jz_clk_is_enabled_gating,
787    .set_parent = jz_clk_i2s_set_parent,
788};
789
790static const struct clk_ops jz_clk_spi_ops = {
791    .set_rate = jz_clk_divided_set_rate,
792    .get_rate = jz_clk_divided_get_rate,
793    .enable = jz_clk_enable_gating,
794    .disable = jz_clk_disable_gating,
795    .is_enabled = jz_clk_is_enabled_gating,
796    .set_parent = jz_clk_spi_set_parent,
797};
798
799static const struct clk_ops jz_clk_divided_ops = {
800    .set_rate = jz_clk_divided_set_rate,
801    .get_rate = jz_clk_divided_get_rate,
802    .enable = jz_clk_enable_gating,
803    .disable = jz_clk_disable_gating,
804    .is_enabled = jz_clk_is_enabled_gating,
805};
806
807static struct divided_clk jz4740_clock_divided_clks[] = {
808    [0] = {
809        .clk = {
810            .name = "i2s",
811            .parent = &jz_clk_ext.clk,
812            .gate_bit = JZ_CLOCK_GATE_I2S,
813            .ops = &jz_clk_i2s_ops,
814        },
815        .reg = JZ_REG_CLOCK_I2S,
816        .mask = JZ_CLOCK_I2S_DIV_MASK,
817    },
818    [1] = {
819        .clk = {
820            .name = "spi",
821            .parent = &jz_clk_ext.clk,
822            .gate_bit = JZ_CLOCK_GATE_SPI,
823            .ops = &jz_clk_spi_ops,
824        },
825        .reg = JZ_REG_CLOCK_SPI,
826        .mask = JZ_CLOCK_SPI_DIV_MASK,
827    },
828    [2] = {
829        .clk = {
830            .name = "lcd_pclk",
831            .parent = &jz_clk_pll_half,
832            .gate_bit = JZ4740_CLK_NOT_GATED,
833            .ops = &jz_clk_divided_ops,
834        },
835        .reg = JZ_REG_CLOCK_LCD,
836        .mask = JZ_CLOCK_LCD_DIV_MASK,
837    },
838    [3] = {
839        .clk = {
840            .name = "mmc",
841            .parent = &jz_clk_pll_half,
842            .gate_bit = JZ_CLOCK_GATE_MMC,
843            .ops = &jz_clk_divided_ops,
844        },
845        .reg = JZ_REG_CLOCK_MMC,
846        .mask = JZ_CLOCK_MMC_DIV_MASK,
847    },
848    [4] = {
849        .clk = {
850            .name = "uhc",
851            .parent = &jz_clk_pll_half,
852            .gate_bit = JZ_CLOCK_GATE_UHC,
853            .ops = &jz_clk_divided_ops,
854        },
855        .reg = JZ_REG_CLOCK_UHC,
856        .mask = JZ_CLOCK_UHC_DIV_MASK,
857    },
858};
859
860static const struct clk_ops jz_clk_udc_ops = {
861    .set_parent = jz_clk_udc_set_parent,
862    .set_rate = jz_clk_udc_set_rate,
863    .get_rate = jz_clk_udc_get_rate,
864    .enable = jz_clk_udc_enable,
865    .disable = jz_clk_udc_disable,
866    .is_enabled = jz_clk_udc_is_enabled,
867};
868
869static const struct clk_ops jz_clk_simple_ops = {
870    .enable = jz_clk_enable_gating,
871    .disable = jz_clk_disable_gating,
872    .is_enabled = jz_clk_is_enabled_gating,
873};
874
875static struct clk jz4740_clock_simple_clks[] = {
876    [0] = {
877        .name = "udc",
878        .parent = &jz_clk_ext.clk,
879        .ops = &jz_clk_udc_ops,
880    },
881    [1] = {
882        .name = "uart0",
883        .parent = &jz_clk_ext.clk,
884        .gate_bit = JZ_CLOCK_GATE_UART0,
885        .ops = &jz_clk_simple_ops,
886    },
887    [2] = {
888        .name = "uart1",
889        .parent = &jz_clk_ext.clk,
890        .gate_bit = JZ_CLOCK_GATE_UART1,
891        .ops = &jz_clk_simple_ops,
892    },
893    [3] = {
894        .name = "dma",
895        .parent = &jz_clk_high_speed_peripheral.clk,
896        .gate_bit = JZ_CLOCK_GATE_DMAC,
897        .ops = &jz_clk_simple_ops,
898    },
899    [4] = {
900        .name = "ipu",
901        .parent = &jz_clk_high_speed_peripheral.clk,
902        .gate_bit = JZ_CLOCK_GATE_IPU,
903        .ops = &jz_clk_simple_ops,
904    },
905    [5] = {
906        .name = "adc",
907        .parent = &jz_clk_ext.clk,
908        .gate_bit = JZ_CLOCK_GATE_ADC,
909        .ops = &jz_clk_simple_ops,
910    },
911    [6] = {
912        .name = "i2c",
913        .parent = &jz_clk_ext.clk,
914        .gate_bit = JZ_CLOCK_GATE_I2C,
915        .ops = &jz_clk_simple_ops,
916    },
917    [7] = {
918        .name = "aic",
919        .parent = &jz_clk_ext.clk,
920        .gate_bit = JZ_CLOCK_GATE_AIC,
921        .ops = &jz_clk_simple_ops,
922    },
923};
924
925static struct static_clk jz_clk_rtc = {
926    .clk = {
927        .name = "rtc",
928        .gate_bit = JZ_CLOCK_GATE_RTC,
929        .ops = &jz_clk_static_ops,
930    },
931    .rate = 32768,
932};
933
934int clk_enable(struct clk *clk)
935{
936    if (!clk->ops->enable)
937        return -EINVAL;
938
939    return clk->ops->enable(clk);
940}
941EXPORT_SYMBOL_GPL(clk_enable);
942
943void clk_disable(struct clk *clk)
944{
945    if (clk->ops->disable)
946        clk->ops->disable(clk);
947}
948EXPORT_SYMBOL_GPL(clk_disable);
949
950int clk_is_enabled(struct clk *clk)
951{
952    if (clk->ops->is_enabled)
953        return clk->ops->is_enabled(clk);
954
955    return 1;
956}
957
958unsigned long clk_get_rate(struct clk *clk)
959{
960    if (clk->ops->get_rate)
961        return clk->ops->get_rate(clk);
962    if (clk->parent)
963        return clk_get_rate(clk->parent);
964
965    return -EINVAL;
966}
967EXPORT_SYMBOL_GPL(clk_get_rate);
968
969int clk_set_rate(struct clk *clk, unsigned long rate)
970{
971    if (!clk->ops->set_rate)
972        return -EINVAL;
973    return clk->ops->set_rate(clk, rate);
974}
975EXPORT_SYMBOL_GPL(clk_set_rate);
976
977long clk_round_rate(struct clk *clk, unsigned long rate)
978{
979    if (clk->ops->round_rate)
980        return clk->ops->round_rate(clk, rate);
981
982    return -EINVAL;
983}
984EXPORT_SYMBOL_GPL(clk_round_rate);
985
986int clk_set_parent(struct clk *clk, struct clk *parent)
987{
988    int ret;
989    int enabled;
990
991    if (!clk->ops->set_parent)
992        return -EINVAL;
993
994    enabled = clk_is_enabled(clk);
995    if (enabled)
996        clk_disable(clk);
997    ret = clk->ops->set_parent(clk, parent);
998    if (enabled)
999        clk_enable(clk);
1000
1001    jz4740_clock_debugfs_update_parent(clk);
1002
1003    return ret;
1004}
1005EXPORT_SYMBOL_GPL(clk_set_parent);
1006
1007struct clk *clk_get(struct device *dev, const char *name)
1008{
1009    struct clk *clk;
1010
1011    list_for_each_entry(clk, &jz_clocks, list) {
1012        if (strcmp(clk->name, name) == 0)
1013            return clk;
1014    }
1015    return ERR_PTR(-ENXIO);
1016}
1017EXPORT_SYMBOL_GPL(clk_get);
1018
1019void clk_put(struct clk *clk)
1020{
1021}
1022EXPORT_SYMBOL_GPL(clk_put);
1023
1024static inline void clk_add(struct clk *clk)
1025{
1026    list_add_tail(&clk->list, &jz_clocks);
1027
1028    jz4740_clock_debugfs_add_clk(clk);
1029}
1030
1031static void clk_register_clks(void)
1032{
1033    size_t i;
1034
1035    clk_add(&jz_clk_ext.clk);
1036    clk_add(&jz_clk_pll);
1037    clk_add(&jz_clk_pll_half);
1038    clk_add(&jz_clk_cpu.clk);
1039    clk_add(&jz_clk_high_speed_peripheral.clk);
1040    clk_add(&jz_clk_low_speed_peripheral.clk);
1041    clk_add(&jz_clk_ko);
1042    clk_add(&jz_clk_ld);
1043    clk_add(&jz_clk_rtc.clk);
1044
1045    for (i = 0; i < ARRAY_SIZE(jz4740_clock_divided_clks); ++i)
1046        clk_add(&jz4740_clock_divided_clks[i].clk);
1047
1048    for (i = 0; i < ARRAY_SIZE(jz4740_clock_simple_clks); ++i)
1049        clk_add(&jz4740_clock_simple_clks[i]);
1050}
1051
1052void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode)
1053{
1054    switch (mode) {
1055    case JZ4740_WAIT_MODE_IDLE:
1056        jz_clk_reg_clear_bits(JZ_REG_CLOCK_LOW_POWER, JZ_CLOCK_LOW_POWER_MODE_SLEEP);
1057        break;
1058    case JZ4740_WAIT_MODE_SLEEP:
1059        jz_clk_reg_set_bits(JZ_REG_CLOCK_LOW_POWER, JZ_CLOCK_LOW_POWER_MODE_SLEEP);
1060        break;
1061    }
1062}
1063
1064void jz4740_clock_udc_disable_auto_suspend(void)
1065{
1066    jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, JZ_CLOCK_GATE_UDC);
1067}
1068EXPORT_SYMBOL_GPL(jz4740_clock_udc_disable_auto_suspend);
1069
1070void jz4740_clock_udc_enable_auto_suspend(void)
1071{
1072    jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, JZ_CLOCK_GATE_UDC);
1073}
1074EXPORT_SYMBOL_GPL(jz4740_clock_udc_enable_auto_suspend);
1075
1076void jz4740_clock_suspend(void)
1077{
1078    jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE,
1079        JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0);
1080
1081    jz_clk_reg_clear_bits(JZ_REG_CLOCK_PLL, JZ_CLOCK_PLL_ENABLED);
1082}
1083
1084void jz4740_clock_resume(void)
1085{
1086    uint32_t pll;
1087
1088    jz_clk_reg_set_bits(JZ_REG_CLOCK_PLL, JZ_CLOCK_PLL_ENABLED);
1089
1090    do {
1091        pll = jz_clk_reg_read(JZ_REG_CLOCK_PLL);
1092    } while (!(pll & JZ_CLOCK_PLL_STABLE));
1093
1094    jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE,
1095        JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0);
1096}
1097
1098static int jz4740_clock_init(void)
1099{
1100    uint32_t val;
1101
1102    jz_clock_base = ioremap(JZ4740_CPM_BASE_ADDR, 0x100);
1103    if (!jz_clock_base)
1104        return -EBUSY;
1105
1106    jz_emc_base = ioremap(JZ4740_EMC_BASE_ADDR, 0x100);
1107    if (!jz_emc_base)
1108        return -EBUSY;
1109
1110    spin_lock_init(&jz_clock_lock);
1111
1112    jz_clk_ext.rate = jz4740_clock_bdata.ext_rate;
1113    jz_clk_rtc.rate = jz4740_clock_bdata.rtc_rate;
1114
1115    val = jz_clk_reg_read(JZ_REG_CLOCK_SPI);
1116
1117    if (val & JZ_CLOCK_SPI_SRC_PLL)
1118        jz4740_clock_divided_clks[1].clk.parent = &jz_clk_pll_half;
1119
1120    val = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
1121
1122    if (val & JZ_CLOCK_CTRL_I2S_SRC_PLL)
1123        jz4740_clock_divided_clks[0].clk.parent = &jz_clk_pll_half;
1124
1125    if (val & JZ_CLOCK_CTRL_UDC_SRC_PLL)
1126        jz4740_clock_simple_clks[0].parent = &jz_clk_pll_half;
1127
1128    jz4740_clock_debugfs_init();
1129
1130    clk_register_clks();
1131
1132    return 0;
1133}
1134arch_initcall(jz4740_clock_init);
1135

Archive Download this file



interactive