]> git.sur5r.net Git - u-boot/blobdiff - arch/arm/mach-tegra/clock.c
dts: zc706: Enable zynq qspi controller node
[u-boot] / arch / arm / mach-tegra / clock.c
index 3b2b4ffd2a72b4804742cdd961c8d73b91cc53c4..f75c6c664a25a0071c68197f3fcf527b889c3582 100644 (file)
@@ -126,19 +126,34 @@ unsigned long clock_start_pll(enum clock_id clkid, u32 divm, u32 divn,
 {
        struct clk_pll *pll = NULL;
        struct clk_pll_info *pllinfo = &tegra_pll_info_table[clkid];
+       struct clk_pll_simple *simple_pll = NULL;
        u32 misc_data, data;
 
-       if (clkid < (enum clock_id)TEGRA_CLK_PLLS)
+       if (clkid < (enum clock_id)TEGRA_CLK_PLLS) {
                pll = get_pll(clkid);
+       } else {
+               simple_pll = clock_get_simple_pll(clkid);
+               if (!simple_pll) {
+                       debug("%s: Uknown simple PLL %d\n", __func__, clkid);
+                       return 0;
+               }
+       }
 
        /*
         * pllinfo has the m/n/p and kcp/kvco mask and shift
         * values for all of the PLLs used in U-Boot, with any
         * SoC differences accounted for.
+        *
+        * Preserve EN_LOCKDET, etc.
         */
-       misc_data = readl(&pll->pll_misc);      /* preserve EN_LOCKDET, etc. */
-       misc_data &= ~(pllinfo->kcp_mask << pllinfo->kcp_shift) | (cpcon << pllinfo->kcp_shift);
-       misc_data &= ~(pllinfo->kvco_mask << pllinfo->kvco_shift) | (lfcon << pllinfo->kvco_shift);
+       if (pll)
+               misc_data = readl(&pll->pll_misc);
+       else
+               misc_data = readl(&simple_pll->pll_misc);
+       misc_data &= ~(pllinfo->kcp_mask << pllinfo->kcp_shift);
+       misc_data |= cpcon << pllinfo->kcp_shift;
+       misc_data &= ~(pllinfo->kvco_mask << pllinfo->kvco_shift);
+       misc_data |= lfcon << pllinfo->kvco_shift;
 
        data = (divm << pllinfo->m_shift) | (divn << pllinfo->n_shift);
        data |= divp << pllinfo->p_shift;
@@ -148,14 +163,8 @@ unsigned long clock_start_pll(enum clock_id clkid, u32 divm, u32 divn,
                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);
+               writel(misc_data, &simple_pll->pll_misc);
+               writel(data, &simple_pll->pll_base);
        }
 
        /* calculate the stable time */
@@ -452,6 +461,11 @@ void reset_cmplx_set_enable(int cpu, int which, int reset)
                writel(mask, &clkrst->crc_cpu_cmplx_clr);
 }
 
+unsigned int __weak clk_m_get_rate(unsigned int parent_rate)
+{
+       return parent_rate;
+}
+
 unsigned clock_get_rate(enum clock_id clkid)
 {
        struct clk_pll *pll;
@@ -463,6 +477,9 @@ unsigned clock_get_rate(enum clock_id clkid)
        if (clkid == CLOCK_ID_OSC)
                return parent_rate;
 
+       if (clkid == CLOCK_ID_CLK_M)
+               return clk_m_get_rate(parent_rate);
+
        pll = get_pll(clkid);
        if (!pll)
                return 0;
@@ -474,7 +491,16 @@ unsigned clock_get_rate(enum clock_id clkid)
         * PLLU uses p_mask/p_shift for VCO on all but T210,
         * T210 uses normal DIVP. Handled in pllinfo table.
         */
-       divm <<= (base >> pllinfo->p_shift) & pllinfo->p_mask;
+#ifdef CONFIG_TEGRA210
+       /*
+        * PLLP's primary output (pllP_out0) on T210 is the VCO, and divp is
+        * not applied. pllP_out2 does have divp applied. All other pllP_outN
+        * are divided down from pllP_out0. We only support pllP_out0 in
+        * U-Boot at the time of writing this comment.
+        */
+       if (clkid != CLOCK_ID_PERIPH)
+#endif
+               divm <<= (base >> pllinfo->p_shift) & pllinfo->p_mask;
        do_div(rate, divm);
        return rate;
 }
@@ -564,7 +590,7 @@ void clock_ll_start_uart(enum periph_id periph_id)
        reset_set_enable(periph_id, 0);
 }
 
-#ifdef CONFIG_OF_CONTROL
+#if CONFIG_IS_ENABLED(OF_CONTROL)
 int clock_decode_periph_id(const void *blob, int node)
 {
        enum periph_id id;
@@ -579,7 +605,7 @@ int clock_decode_periph_id(const void *blob, int node)
        assert(clock_periph_id_isvalid(id));
        return id;
 }
-#endif /* CONFIG_OF_CONTROL */
+#endif /* CONFIG_IS_ENABLED(OF_CONTROL) */
 
 int clock_verify(void)
 {
@@ -604,8 +630,10 @@ void clock_init(void)
        pll_rate[CLOCK_ID_XCPU] = clock_get_rate(CLOCK_ID_XCPU);
        pll_rate[CLOCK_ID_SFROM32KHZ] = 32768;
        pll_rate[CLOCK_ID_OSC] = clock_get_rate(CLOCK_ID_OSC);
+       pll_rate[CLOCK_ID_CLK_M] = clock_get_rate(CLOCK_ID_CLK_M);
 
        debug("Osc = %d\n", pll_rate[CLOCK_ID_OSC]);
+       debug("CLKM = %d\n", pll_rate[CLOCK_ID_CLK_M]);
        debug("PLLC = %d\n", pll_rate[CLOCK_ID_CGENERAL]);
        debug("PLLM = %d\n", pll_rate[CLOCK_ID_MEMORY]);
        debug("PLLP = %d\n", pll_rate[CLOCK_ID_PERIPH]);