]> git.sur5r.net Git - u-boot/blobdiff - arch/arm/mach-tegra/clock.c
Merge git://git.denx.de/u-boot-samsung
[u-boot] / arch / arm / mach-tegra / clock.c
index 11c7435505c1d17d53ccf10c4040f640d5a4afde..cdd54388c520d574dd73a69a15730091a65f0282 100644 (file)
@@ -20,6 +20,7 @@
 #include <asm/io.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/tegra.h>
+#include <asm/arch-tegra/ap.h>
 #include <asm/arch-tegra/clk_rst.h>
 #include <asm/arch-tegra/timer.h>
 #include <div64.h>
@@ -80,9 +81,18 @@ static struct clk_pll *get_pll(enum clock_id clkid)
                        (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
 
        assert(clock_id_is_pll(clkid));
+       if (clkid >= (enum clock_id)TEGRA_CLK_PLLS) {
+               debug("%s: Invalid PLL\n", __func__);
+               return NULL;
+       }
        return &clkrst->crc_pll[clkid];
 }
 
+__weak struct clk_pll_simple *clock_get_simple_pll(enum clock_id clkid)
+{
+       return NULL;
+}
+
 int clock_ll_read_pll(enum clock_id clkid, u32 *divm, u32 *divn,
                u32 *divp, u32 *cpcon, u32 *lfcon)
 {
@@ -109,7 +119,7 @@ unsigned long clock_start_pll(enum clock_id clkid, u32 divm, u32 divn,
                u32 divp, u32 cpcon, u32 lfcon)
 {
        struct clk_pll *pll = get_pll(clkid);
-       u32 data;
+       u32 misc_data, data;
 
        /*
         * We cheat by treating all PLL (except PLLU) in the same fashion.
@@ -118,8 +128,7 @@ unsigned long clock_start_pll(enum clock_id clkid, u32 divm, u32 divn,
         * - DCCON is always 0, doesn't conflict
         * - M,N, P of PLLP values are ignored for PLLP
         */
-       data = (cpcon << PLL_CPCON_SHIFT) | (lfcon << PLL_LFCON_SHIFT);
-       writel(data, &pll->pll_misc);
+       misc_data = (cpcon << PLL_CPCON_SHIFT) | (lfcon << PLL_LFCON_SHIFT);
 
        data = (divm << PLL_DIVM_SHIFT) | (divn << PLL_DIVN_SHIFT) |
                        (0 << PLL_BYPASS_SHIFT) | (1 << PLL_ENABLE_SHIFT);
@@ -128,7 +137,19 @@ unsigned long clock_start_pll(enum clock_id clkid, u32 divm, u32 divn,
                data |= divp << PLLU_VCO_FREQ_SHIFT;
        else
                data |= divp << PLL_DIVP_SHIFT;
-       writel(data, &pll->pll_base);
+       if (pll) {
+               writel(misc_data, &pll->pll_misc);
+               writel(data, &pll->pll_base);
+       } else {
+               struct clk_pll_simple *pll = clock_get_simple_pll(clkid);
+
+               if (!pll) {
+                       debug("%s: Uknown simple PLL %d\n", __func__, clkid);
+                       return 0;
+               }
+               writel(misc_data, &pll->pll_misc);
+               writel(data, &pll->pll_base);
+       }
 
        /* calculate the stable time */
        return timer_get_us() + CLOCK_PLL_STABLE_DELAY_US;
@@ -151,12 +172,37 @@ void clock_ll_set_source_divisor(enum periph_id periph_id, unsigned source,
        writel(value, reg);
 }
 
-void clock_ll_set_source(enum periph_id periph_id, unsigned source)
+int clock_ll_set_source_bits(enum periph_id periph_id, int mux_bits,
+                            unsigned source)
 {
        u32 *reg = get_periph_source_reg(periph_id);
 
-       clrsetbits_le32(reg, OUT_CLK_SOURCE_31_30_MASK,
-                       source << OUT_CLK_SOURCE_31_30_SHIFT);
+       switch (mux_bits) {
+       case MASK_BITS_31_30:
+               clrsetbits_le32(reg, OUT_CLK_SOURCE_31_30_MASK,
+                               source << OUT_CLK_SOURCE_31_30_SHIFT);
+               break;
+
+       case MASK_BITS_31_29:
+               clrsetbits_le32(reg, OUT_CLK_SOURCE_31_29_MASK,
+                               source << OUT_CLK_SOURCE_31_29_SHIFT);
+               break;
+
+       case MASK_BITS_31_28:
+               clrsetbits_le32(reg, OUT_CLK_SOURCE_31_28_MASK,
+                               source << OUT_CLK_SOURCE_31_28_SHIFT);
+               break;
+
+       default:
+               return -1;
+       }
+
+       return 0;
+}
+
+void clock_ll_set_source(enum periph_id periph_id, unsigned source)
+{
+       clock_ll_set_source_bits(periph_id, MASK_BITS_31_30, source);
 }
 
 /**
@@ -305,25 +351,7 @@ static int adjust_periph_pll(enum periph_id periph_id, int source,
        if (source < 0)
                return -1;
 
-       switch (mux_bits) {
-       case MASK_BITS_31_30:
-               clrsetbits_le32(reg, OUT_CLK_SOURCE_31_30_MASK,
-                               source << OUT_CLK_SOURCE_31_30_SHIFT);
-               break;
-
-       case MASK_BITS_31_29:
-               clrsetbits_le32(reg, OUT_CLK_SOURCE_31_29_MASK,
-                               source << OUT_CLK_SOURCE_31_29_SHIFT);
-               break;
-
-       case MASK_BITS_31_28:
-               clrsetbits_le32(reg, OUT_CLK_SOURCE_31_28_MASK,
-                               source << OUT_CLK_SOURCE_31_28_SHIFT);
-               break;
-
-       default:
-               return -1;
-       }
+       clock_ll_set_source_bits(periph_id, mux_bits, source);
 
        udelay(2);
        return 0;
@@ -430,6 +458,8 @@ unsigned clock_get_rate(enum clock_id clkid)
                return parent_rate;
 
        pll = get_pll(clkid);
+       if (!pll)
+               return 0;
        base = readl(&pll->pll_base);
 
        /* Oh for bf_unpack()... */
@@ -563,6 +593,7 @@ void clock_init(void)
        pll_rate[CLOCK_ID_MEMORY] = clock_get_rate(CLOCK_ID_MEMORY);
        pll_rate[CLOCK_ID_PERIPH] = clock_get_rate(CLOCK_ID_PERIPH);
        pll_rate[CLOCK_ID_CGENERAL] = clock_get_rate(CLOCK_ID_CGENERAL);
+       pll_rate[CLOCK_ID_DISPLAY] = clock_get_rate(CLOCK_ID_DISPLAY);
        pll_rate[CLOCK_ID_OSC] = clock_get_rate(CLOCK_ID_OSC);
        pll_rate[CLOCK_ID_SFROM32KHZ] = 32768;
        pll_rate[CLOCK_ID_XCPU] = clock_get_rate(CLOCK_ID_XCPU);
@@ -570,10 +601,14 @@ void clock_init(void)
        debug("PLLM = %d\n", pll_rate[CLOCK_ID_MEMORY]);
        debug("PLLP = %d\n", pll_rate[CLOCK_ID_PERIPH]);
        debug("PLLC = %d\n", pll_rate[CLOCK_ID_CGENERAL]);
+       debug("PLLD = %d\n", pll_rate[CLOCK_ID_DISPLAY]);
        debug("PLLX = %d\n", pll_rate[CLOCK_ID_XCPU]);
 
        /* Do any special system timer/TSC setup */
-       arch_timer_init();
+#if defined(CONFIG_TEGRA_SUPPORT_NON_SECURE)
+       if (!tegra_cpu_is_non_secure())
+#endif
+               arch_timer_init();
 }
 
 static void set_avp_clock_source(u32 src)