]> git.sur5r.net Git - u-boot/commitdiff
Tegra: PLL: use per-SoC pllinfo table instead of PLL_DIVM/N/P, etc.
authorTom Warren <twarren@nvidia.com>
Thu, 25 Jun 2015 16:50:44 +0000 (09:50 -0700)
committerTom Warren <twarren@nvidia.com>
Wed, 5 Aug 2015 22:22:51 +0000 (15:22 -0700)
Added PLL variables (dividers mask/shift, lock enable/detect, etc.)
to new pllinfo struct for each Soc/PLL. PLLA/C/D/E/M/P/U/X.

Used pllinfo struct in all clock functions, validated on T210.
Should be equivalent to prior code on T124/114/30/20. Thanks
to Marcel Ziswiler for corrections to the T20/T30 values.

Signed-off-by: Marcel Ziswiler <marcel.ziswiler@toradex.com>
Tested-by: Marcel Ziswiler <marcel.ziswiler@toradex.com>
Signed-off-by: Tom Warren <twarren@nvidia.com>
12 files changed:
arch/arm/include/asm/arch-tegra/clk_rst.h
arch/arm/include/asm/arch-tegra/clock.h
arch/arm/include/asm/arch-tegra210/clock-tables.h
arch/arm/mach-tegra/clock.c
arch/arm/mach-tegra/cpu.c
arch/arm/mach-tegra/tegra114/clock.c
arch/arm/mach-tegra/tegra114/cpu.c
arch/arm/mach-tegra/tegra124/clock.c
arch/arm/mach-tegra/tegra124/cpu.c
arch/arm/mach-tegra/tegra20/clock.c
arch/arm/mach-tegra/tegra210/clock.c
arch/arm/mach-tegra/tegra30/clock.c

index f69026002b41da7d10d9d03977c5d6adb8269f7b..ee9436e2e53dc5970b66a3ff5a1fa89229fc9fac 100644 (file)
@@ -249,17 +249,6 @@ struct clk_rst_ctlr {
 #define PLL_LOCK_SHIFT         27
 #define PLL_LOCK_MASK          (1U << PLL_LOCK_SHIFT)
 
-#define PLL_DIVP_SHIFT         20
-#define PLL_DIVP_MASK          (7U << PLL_DIVP_SHIFT)
-/* Special case for T210 PLLU DIVP */
-#define PLLU_DIVP_SHIFT                16
-
-#define PLL_DIVN_SHIFT         8
-#define PLL_DIVN_MASK          (0x3ffU << PLL_DIVN_SHIFT)
-
-#define PLL_DIVM_SHIFT         0
-#define PLL_DIVM_MASK          (0x1f << PLL_DIVM_SHIFT)
-
 /* CLK_RST_CONTROLLER_PLLx_OUTx_0 */
 #define PLL_OUT_RSTN           (1 << 0)
 #define PLL_OUT_CLKEN          (1 << 1)
@@ -272,24 +261,6 @@ struct clk_rst_ctlr {
 #define PLL_DCCON_SHIFT                20
 #define PLL_DCCON_MASK         (1U << PLL_DCCON_SHIFT)
 
-#define PLL_LOCK_ENABLE_SHIFT  18
-#define PLL_LOCK_ENABLE_MASK   (1U << PLL_LOCK_ENABLE_SHIFT)
-
-#define PLL_CPCON_SHIFT                8
-#define PLL_CPCON_MASK         (15U << PLL_CPCON_SHIFT)
-
-#define PLL_LFCON_SHIFT                4
-#define PLL_LFCON_MASK         (15U << PLL_LFCON_SHIFT)
-
-/* CPCON/LFCON replaced by KCP/KVCO in T210 PLLU */
-#define PLLU_KVCO_SHIFT                24
-#define PLLU_KVCO_MASK         (3U << PLLU_KVCO_SHIFT)
-#define PLLU_KCP_SHIFT         25
-#define PLLU_KCP_MASK          (1U << PLLU_KCP_SHIFT)
-
-#define PLLU_VCO_FREQ_SHIFT    20
-#define PLLU_VCO_FREQ_MASK     (1U << PLLU_VCO_FREQ_SHIFT)
-
 #define PLLP_OUT1_OVR          (1 << 2)
 #define PLLP_OUT2_OVR          (1 << 18)
 #define PLLP_OUT3_OVR          (1 << 2)
@@ -475,4 +446,7 @@ enum {
 #define PLLDP_SS_CFG_UNDOCUMENTED      (1 << 24)
 #define PLLDP_SS_CFG_DITHER            (1 << 28)
 
+/* CLK_RST_PLLD_MISC */
+#define PLLD_CLKENABLE                 30
+
 #endif /* _TEGRA_CLK_RST_H_ */
index 2274b14f3320c7836fbede6ad6a6ded7009f5564..d570d7f134a8d32e9fb63be42ee920ea13d1cd88 100644 (file)
@@ -338,6 +338,27 @@ void arch_timer_init(void);
 
 void tegra30_set_up_pllp(void);
 
+/* Number of PLL-based clocks (i.e. not OSC or 32KHz) */
+#define CLOCK_ID_PLL_COUNT     (CLOCK_ID_COUNT - 2)
+
+struct clk_pll_info {
+       u32     m_shift:5;      /* DIVM_SHIFT */
+       u32     n_shift:5;      /* DIVN_SHIFT */
+       u32     p_shift:5;      /* DIVP_SHIFT */
+       u32     kcp_shift:5;    /* KCP/cpcon SHIFT */
+       u32     kvco_shift:5;   /* KVCO/lfcon SHIFT */
+       u32     lock_ena:6;     /* LOCK_ENABLE/EN_LOCKDET shift */
+       u32     rsvd:1;
+       u32     m_mask:10;      /* DIVM_MASK */
+       u32     n_mask:12;      /* DIVN_MASK */
+       u32     p_mask:10;      /* DIVP_MASK or VCO_MASK */
+       u32     kcp_mask:10;    /* KCP/CPCON MASK */
+       u32     kvco_mask:10;   /* KVCO/LFCON MASK */
+       u32     lock_det:6;     /* LOCK_DETECT/LOCKED shift */
+       u32     rsvd2:6;
+};
+extern struct clk_pll_info tegra_pll_info_table[CLOCK_ID_PLL_COUNT];
+
 /**
  * Enable output clock for external peripherals
  *
index b62e0702a59250a85f7285c76f99c01f4fe3e9b6..175040dae618a4e9f02e1a775704e6681609b262 100644 (file)
@@ -25,6 +25,7 @@ enum clock_id {
        CLOCK_ID_XCPU = CLOCK_ID_FIRST_SIMPLE,
        CLOCK_ID_EPCI,
        CLOCK_ID_SFROM32KHZ,
+       CLOCK_ID_DP,
 
        /* These are the base clocks (inputs to the Tegra SoC) */
        CLOCK_ID_32KHZ,
index d0eebd21c1e57a05d12293a7027f65dc9db33755..3b2b4ffd2a72b4804742cdd961c8d73b91cc53c4 100644 (file)
@@ -101,6 +101,7 @@ int clock_ll_read_pll(enum clock_id clkid, u32 *divm, u32 *divn,
                u32 *divp, u32 *cpcon, u32 *lfcon)
 {
        struct clk_pll *pll = get_pll(clkid);
+       struct clk_pll_info *pllinfo = &tegra_pll_info_table[clkid];
        u32 data;
 
        assert(clkid != CLOCK_ID_USB);
@@ -109,17 +110,14 @@ int clock_ll_read_pll(enum clock_id clkid, u32 *divm, u32 *divn,
        if (!clock_id_is_pll(clkid) || clkid == CLOCK_ID_USB)
                return -1;
        data = readl(&pll->pll_base);
-       *divm = (data & PLL_DIVM_MASK) >> PLL_DIVM_SHIFT;
-       *divn = (data & PLL_DIVN_MASK) >> PLL_DIVN_SHIFT;
-       *divp = (data & PLL_DIVP_MASK) >> PLL_DIVP_SHIFT;
+       *divm = (data >> pllinfo->m_shift) & pllinfo->m_mask;
+       *divn = (data >> pllinfo->n_shift) & pllinfo->n_mask;
+       *divp = (data >> pllinfo->p_shift) & pllinfo->p_mask;
        data = readl(&pll->pll_misc);
-       *cpcon = (data & PLL_CPCON_MASK) >> PLL_CPCON_SHIFT;
-       *lfcon = (data & PLL_LFCON_MASK) >> PLL_LFCON_SHIFT;
-#if defined(CONFIG_TEGRA210)
-       /* T210 PLLU uses KCP/KVCO instead of CPCON/LFCON */
-       *cpcon = (data & PLLU_KCP_MASK) >> PLLU_KCP_SHIFT;
-       *lfcon = (data & PLLU_KVCO_MASK) >> PLLU_KVCO_SHIFT;
-#endif
+       /* NOTE: On T210, cpcon/lfcon no longer exist, moved to KCP/KVCO */
+       *cpcon = (data >> pllinfo->kcp_shift) & pllinfo->kcp_mask;
+       *lfcon = (data >> pllinfo->kvco_shift) & pllinfo->kvco_mask;
+
        return 0;
 }
 
@@ -127,41 +125,25 @@ unsigned long clock_start_pll(enum clock_id clkid, u32 divm, u32 divn,
                u32 divp, u32 cpcon, u32 lfcon)
 {
        struct clk_pll *pll = NULL;
+       struct clk_pll_info *pllinfo = &tegra_pll_info_table[clkid];
        u32 misc_data, data;
 
        if (clkid < (enum clock_id)TEGRA_CLK_PLLS)
                pll = get_pll(clkid);
 
        /*
-        * We cheat by treating all PLL (except PLLU) in the same fashion.
-        * This works only because:
-        * - same fields are always mapped at same offsets, except DCCON
-        * - DCCON is always 0, doesn't conflict
-        * - M,N, P of PLLP values are ignored for PLLP
-        * NOTE: Above is no longer true with T210 - TBD: FIX THIS
+        * 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.
         */
-       misc_data = (cpcon << PLL_CPCON_SHIFT) | (lfcon << PLL_LFCON_SHIFT);
-
-#if defined(CONFIG_TEGRA210)
-       /* T210 PLLU uses KCP/KVCO instead of cpcon/lfcon */
-       if (clkid == CLOCK_ID_USB) {
-               /* preserve EN_LOCKDET, set by default */
-               misc_data = readl(&pll->pll_misc);
-               misc_data |= (cpcon << PLLU_KCP_SHIFT) |
-                       (lfcon << PLLU_KVCO_SHIFT);
-       }
-#endif
-       data = (divm << PLL_DIVM_SHIFT) | (divn << PLL_DIVN_SHIFT) |
-                       (0 << PLL_BYPASS_SHIFT) | (1 << PLL_ENABLE_SHIFT);
-
-       if (clkid == CLOCK_ID_USB)
-#if defined(CONFIG_TEGRA210)
-               data |= divp << PLLU_DIVP_SHIFT;
-#else
-               data |= divp << PLLU_VCO_FREQ_SHIFT;
-#endif
-       else
-               data |= divp << PLL_DIVP_SHIFT;
+       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);
+
+       data = (divm << pllinfo->m_shift) | (divn << pllinfo->n_shift);
+       data |= divp << pllinfo->p_shift;
+       data |= (1 << PLL_ENABLE_SHIFT);        /* BYPASS s/b 0 already */
+
        if (pll) {
                writel(misc_data, &pll->pll_misc);
                writel(data, &pll->pll_base);
@@ -473,10 +455,9 @@ void reset_cmplx_set_enable(int cpu, int which, int reset)
 unsigned clock_get_rate(enum clock_id clkid)
 {
        struct clk_pll *pll;
-       u32 base;
-       u32 divm;
-       u64 parent_rate;
-       u64 rate;
+       u32 base, divm;
+       u64 parent_rate, rate;
+       struct clk_pll_info *pllinfo = &tegra_pll_info_table[clkid];
 
        parent_rate = osc_freq[clock_get_osc_freq()];
        if (clkid == CLOCK_ID_OSC)
@@ -487,13 +468,13 @@ unsigned clock_get_rate(enum clock_id clkid)
                return 0;
        base = readl(&pll->pll_base);
 
-       /* Oh for bf_unpack()... */
-       rate = parent_rate * ((base & PLL_DIVN_MASK) >> PLL_DIVN_SHIFT);
-       divm = (base & PLL_DIVM_MASK) >> PLL_DIVM_SHIFT;
-       if (clkid == CLOCK_ID_USB)
-               divm <<= (base & PLLU_VCO_FREQ_MASK) >> PLLU_VCO_FREQ_SHIFT;
-       else
-               divm <<= (base & PLL_DIVP_MASK) >> PLL_DIVP_SHIFT;
+       rate = parent_rate * ((base >> pllinfo->n_shift) & pllinfo->n_mask);
+       divm = (base >> pllinfo->m_shift) & pllinfo->m_mask;
+       /*
+        * 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;
        do_div(rate, divm);
        return rate;
 }
@@ -517,23 +498,23 @@ unsigned clock_get_rate(enum clock_id clkid)
  */
 int clock_set_rate(enum clock_id clkid, u32 n, u32 m, u32 p, u32 cpcon)
 {
-       u32 base_reg;
-       u32 misc_reg;
+       u32 base_reg, misc_reg;
        struct clk_pll *pll;
+       struct clk_pll_info *pllinfo = &tegra_pll_info_table[clkid];
 
        pll = get_pll(clkid);
 
        base_reg = readl(&pll->pll_base);
 
        /* Set BYPASS, m, n and p to PLL_BASE */
-       base_reg &= ~PLL_DIVM_MASK;
-       base_reg |= m << PLL_DIVM_SHIFT;
+       base_reg &= ~(pllinfo->m_mask << pllinfo->m_shift);
+       base_reg |= m << pllinfo->m_shift;
 
-       base_reg &= ~PLL_DIVN_MASK;
-       base_reg |= n << PLL_DIVN_SHIFT;
+       base_reg &= ~(pllinfo->n_mask << pllinfo->n_shift);
+       base_reg |= n << pllinfo->n_shift;
 
-       base_reg &= ~PLL_DIVP_MASK;
-       base_reg |= p << PLL_DIVP_SHIFT;
+       base_reg &= ~(pllinfo->p_mask << pllinfo->p_shift);
+       base_reg |= p << pllinfo->p_shift;
 
        if (clkid == CLOCK_ID_PERIPH) {
                /*
@@ -552,17 +533,10 @@ int clock_set_rate(enum clock_id clkid, u32 n, u32 m, u32 p, u32 cpcon)
        base_reg |= PLL_BYPASS_MASK;
        writel(base_reg, &pll->pll_base);
 
-       /* Set cpcon to PLL_MISC */
+       /* Set cpcon (KCP) to PLL_MISC */
        misc_reg = readl(&pll->pll_misc);
-#if !defined(CONFIG_TEGRA210)
-       misc_reg &= ~PLL_CPCON_MASK;
-       misc_reg |= cpcon << PLL_CPCON_SHIFT;
-#else
-       /* T210 uses KCP instead, use the most common bit shift (PLLA/U/D2) */
-       misc_reg &= ~PLLU_KCP_MASK;
-       misc_reg |= cpcon << PLLU_KCP_SHIFT;
-#endif
-
+       misc_reg &= ~(pllinfo->kcp_mask << pllinfo->kcp_shift);
+       misc_reg |= cpcon << pllinfo->kcp_shift;
        writel(misc_reg, &pll->pll_misc);
 
        /* Enable PLL */
index b9391d6933cab46a95ce54828cb3ea2dc79d9162..ba04a56be765df9dfa98223796978fa55e386b72 100644 (file)
@@ -181,6 +181,7 @@ static inline void pllx_set_iddq(void)
 int pllx_set_rate(struct clk_pll_simple *pll , u32 divn, u32 divm,
                u32 divp, u32 cpcon)
 {
+       struct clk_pll_info *pllinfo = &tegra_pll_info_table[CLOCK_ID_XCPU];
        int chip = tegra_get_chip();
        u32 reg;
        debug("%s entry\n", __func__);
@@ -194,17 +195,21 @@ int pllx_set_rate(struct clk_pll_simple *pll , u32 divn, u32 divm,
        pllx_set_iddq();
 
        /* Set BYPASS, m, n and p to PLLX_BASE */
-       reg = PLL_BYPASS_MASK | (divm << PLL_DIVM_SHIFT);
-       reg |= ((divn << PLL_DIVN_SHIFT) | (divp << PLL_DIVP_SHIFT));
+       reg = PLL_BYPASS_MASK | (divm << pllinfo->m_shift);
+       reg |= (divn << pllinfo->n_shift) | (divp << pllinfo->p_shift);
        writel(reg, &pll->pll_base);
 
        /* Set cpcon to PLLX_MISC */
        if (chip == CHIPID_TEGRA20 || chip == CHIPID_TEGRA30)
-               reg = (cpcon << PLL_CPCON_SHIFT);
+               reg = (cpcon << pllinfo->kcp_shift);
        else
                reg = 0;
 
-       /* Set dccon to PLLX_MISC if freq > 600MHz */
+       /*
+        * TODO(twarren@nvidia.com) Check which SoCs use DCCON
+        * and add to pllinfo table if needed!
+        */
+        /* Set dccon to PLLX_MISC if freq > 600MHz */
        if (divn > 600)
                reg |= (1 << PLL_DCCON_SHIFT);
        writel(reg, &pll->pll_misc);
@@ -215,9 +220,10 @@ int pllx_set_rate(struct clk_pll_simple *pll , u32 divn, u32 divm,
        writel(reg, &pll->pll_base);
        debug("%s: base = 0x%08X\n", __func__, reg);
 
-       /* Set lock_enable to PLLX_MISC */
+       /* Set lock_enable to PLLX_MISC if lock_ena is valid (i.e. 0-31) */
        reg = readl(&pll->pll_misc);
-       reg |= PLL_LOCK_ENABLE_MASK;
+       if (pllinfo->lock_ena < 32)
+               reg |= (1 << pllinfo->lock_ena);
        writel(reg, &pll->pll_misc);
        debug("%s: misc = 0x%08X\n", __func__, reg);
 
index d5194e11b5fd88e8269b64b6de704922cdddf2e1..f1831d385d02f1e23699029ce8f361a0e334a6a6 100644 (file)
@@ -1,17 +1,8 @@
 /*
- * Copyright (c) 2010-2014, NVIDIA CORPORATION.  All rights reserved.
+ * (C) Copyright 2010-2015
+ * NVIDIA Corporation <www.nvidia.com>
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier:     GPL-2.0+
  */
 
 /* Tegra114 Clock control functions */
@@ -434,6 +425,36 @@ static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = {
        NONE(EMC1),
 };
 
+/*
+ * PLL divider shift/mask tables for all PLL IDs.
+ */
+struct clk_pll_info tegra_pll_info_table[CLOCK_ID_PLL_COUNT] = {
+       /*
+        * T114: some deviations from T2x/T30.
+        * NOTE: If kcp_mask/kvco_mask == 0, they're not used in that PLL (PLLX, etc.)
+        *       If lock_ena or lock_det are >31, they're not used in that PLL.
+        */
+
+       { .m_shift = 0, .m_mask = 0xFF, .n_shift = 8, .n_mask = 0xFF,  .p_shift = 20, .p_mask = 0x0F,
+         .lock_ena = 24, .lock_det = 27, .kcp_shift = 28, .kcp_mask = 3, .kvco_shift = 27, .kvco_mask = 1 },   /* PLLC */
+       { .m_shift = 0, .m_mask = 0xFF, .n_shift = 8, .n_mask = 0xFF,  .p_shift = 0,  .p_mask = 0,
+         .lock_ena = 0,  .lock_det = 27, .kcp_shift = 1, .kcp_mask = 3, .kvco_shift = 0, .kvco_mask = 1 },     /* PLLM */
+       { .m_shift = 0, .m_mask = 0x1F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x07,
+         .lock_ena = 18, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF }, /* PLLP */
+       { .m_shift = 0, .m_mask = 0x1F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x07,
+         .lock_ena = 18, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF }, /* PLLA */
+       { .m_shift = 0, .m_mask = 0x1F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x01,
+         .lock_ena = 22, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF }, /* PLLU */
+       { .m_shift = 0, .m_mask = 0x1F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x07,
+         .lock_ena = 22, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF }, /* PLLD */
+       { .m_shift = 0, .m_mask = 0xFF, .n_shift = 8, .n_mask = 0xFF,  .p_shift = 20, .p_mask = 0x0F,
+         .lock_ena = 18, .lock_det = 27, .kcp_shift = 0, .kcp_mask = 0, .kvco_shift = 0, .kvco_mask = 0 },     /* PLLX */
+       { .m_shift = 0, .m_mask = 0xFF, .n_shift = 8, .n_mask = 0xFF,  .p_shift = 0,  .p_mask = 0,
+         .lock_ena = 9,  .lock_det = 11, .kcp_shift = 6, .kcp_mask = 3, .kvco_shift = 0, .kvco_mask = 1 },     /* PLLE */
+       { .m_shift = 0, .m_mask = 0x0F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x07,
+         .lock_ena = 18, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF }, /* PLLS (RESERVED) */
+};
+
 /*
  * Get the oscillator frequency, from the corresponding hardware configuration
  * field. Note that T30/T114 support 3 new higher freqs, but we map back
@@ -603,6 +624,8 @@ void clock_early_init(void)
 {
        struct clk_rst_ctlr *clkrst =
                (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+       struct clk_pll_info *pllinfo;
+       u32 data;
 
        tegra30_set_up_pllp();
 
@@ -639,11 +662,15 @@ void clock_early_init(void)
        writel(0x00561600, &clkrst->crc_pll[CLOCK_ID_CGENERAL].pll_out[1]);
 
        /* PLLC_MISC: Set LOCK_ENABLE */
-       writel(0x01000000, &clkrst->crc_pll[CLOCK_ID_CGENERAL].pll_misc);
+       pllinfo = &tegra_pll_info_table[CLOCK_ID_CGENERAL];
+       setbits_le32(&clkrst->crc_pll[CLOCK_ID_CGENERAL].pll_misc, (1 << pllinfo->lock_ena));
        udelay(2);
 
-       /* PLLD_MISC: Set CLKENABLE, CPCON 12, LFCON 1 */
-       writel(0x40000C10, &clkrst->crc_pll[CLOCK_ID_DISPLAY].pll_misc);
+       /* PLLD_MISC: Set CLKENABLE, CPCON 12, LFCON 1, and enable lock */
+       pllinfo = &tegra_pll_info_table[CLOCK_ID_DISPLAY];
+       data = (12 << pllinfo->kcp_shift) | (1 << pllinfo->kvco_shift);
+       data |= (1 << PLLD_CLKENABLE) | (1 << pllinfo->lock_ena);
+       writel(data, &clkrst->crc_pll[CLOCK_ID_DISPLAY].pll_misc);
        udelay(2);
 }
 
index 18dc1af1b44bde423a05adc2c8ee2487deb78963..272a2ea281ee1486fd3425c861268fe68de6a465 100644 (file)
@@ -1,17 +1,8 @@
 /*
- * Copyright (c) 2010-2014, NVIDIA CORPORATION.  All rights reserved.
+ * (C) Copyright 2010-2014
+ * NVIDIA Corporation <www.nvidia.com>
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier:     GPL-2.0+
  */
 
 #include <common.h>
@@ -31,7 +22,7 @@ static void enable_cpu_power_rail(void)
        struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
        u32 reg;
 
-       debug("enable_cpu_power_rail entry\n");
+       debug("%s entry\n", __func__);
 
        /* un-tristate PWR_I2C SCL/SDA, rest of the defaults are correct */
        pinmux_tristate_disable(PMUX_PINGRP_PWR_I2C_SCL_PZ6);
@@ -61,14 +52,15 @@ static void enable_cpu_power_rail(void)
 static void enable_cpu_clocks(void)
 {
        struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+       struct clk_pll_info *pllinfo = &tegra_pll_info_table[CLOCK_ID_XCPU];
        u32 reg;
 
-       debug("enable_cpu_clocks entry\n");
+       debug("%s entry\n", __func__);
 
        /* Wait for PLL-X to lock */
        do {
                reg = readl(&clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base);
-       } while ((reg & PLL_LOCK_MASK) == 0);
+       } while ((reg & (1 << pllinfo->lock_det)) == 0);
 
        /* Wait until all clocks are stable */
        udelay(PLL_STABILIZATION_DELAY);
@@ -87,7 +79,7 @@ static void remove_cpu_resets(void)
        struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
        u32 reg;
 
-       debug("remove_cpu_resets entry\n");
+       debug("%s entry\n", __func__);
        /* Take the slow non-CPU partition out of reset */
        reg = readl(&clkrst->crc_rst_cpulp_cmplx_clr);
        writel((reg | CLR_NONCPURESET), &clkrst->crc_rst_cpulp_cmplx_clr);
@@ -111,7 +103,7 @@ static void remove_cpu_resets(void)
 }
 
 /**
- * The T114 requires some special clock initialization, including setting up
+ * Tegra114 requires some special clock initialization, including setting up
  * the DVC I2C, turning on MSELECT and selecting the G CPU cluster
  */
 void t114_init_clocks(void)
@@ -121,7 +113,7 @@ void t114_init_clocks(void)
        struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE;
        u32 val;
 
-       debug("t114_init_clocks entry\n");
+       debug("%s entry\n", __func__);
 
        /* Set active CPU cluster to G */
        clrbits_le32(&flow->cluster_control, 1);
@@ -189,7 +181,7 @@ void t114_init_clocks(void)
        reset_set_enable(PERIPH_ID_MC1, 0);
        reset_set_enable(PERIPH_ID_DVFS, 0);
 
-       debug("t114_init_clocks exit\n");
+       debug("%s exit\n", __func__);
 }
 
 static bool is_partition_powered(u32 partid)
@@ -238,10 +230,9 @@ static void power_partition(u32 partid)
 
 void powerup_cpus(void)
 {
-       debug("powerup_cpus entry\n");
-
        /* We boot to the fast cluster */
-       debug("powerup_cpus entry: G cluster\n");
+       debug("%s entry: G cluster\n", __func__);
+
        /* Power up the fast cluster rail partition */
        power_partition(CRAIL);
 
@@ -256,7 +247,7 @@ void start_cpu(u32 reset_vector)
 {
        u32 imme, inst;
 
-       debug("start_cpu entry, reset_vector = %x\n", reset_vector);
+       debug("%s entry, reset_vector = %x\n", __func__, reset_vector);
 
        t114_init_clocks();
 
@@ -302,7 +293,7 @@ void start_cpu(u32 reset_vector)
        inst |= 0xea000000;
        writel(inst, 0x4003fffc);
 
-       /* Write to orignal location for compatibility */
+       /* Write to original location for compatibility */
        writel(reset_vector, EXCEP_VECTOR_CPU_RESET_VECTOR);
 
        /* If the CPU(s) don't already have power, power 'em up */
index b9558484b0709ed6098af8f504737d79f8bc6dfa..912621863a206f8ebaf670b4ea4e04d2263be770 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * (C) Copyright 2013
+ * (C) Copyright 2013-2015
  * NVIDIA Corporation <www.nvidia.com>
  *
  * SPDX-License-Identifier:     GPL-2.0+
@@ -565,6 +565,36 @@ static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = {
        NONE(X_RESERVED31),
 };
 
+/*
+ * PLL divider shift/mask tables for all PLL IDs.
+ */
+struct clk_pll_info tegra_pll_info_table[CLOCK_ID_PLL_COUNT] = {
+       /*
+        * T124: same as T114, some deviations from T2x/T30.
+        * NOTE: If kcp_mask/kvco_mask == 0, they're not used in that PLL (PLLX, etc.)
+        *       If lock_ena or lock_det are >31, they're not used in that PLL.
+        */
+
+       { .m_shift = 0, .m_mask = 0xFF, .n_shift = 8, .n_mask = 0xFF,  .p_shift = 20, .p_mask = 0x0F,
+         .lock_ena = 24, .lock_det = 27, .kcp_shift = 28, .kcp_mask = 3, .kvco_shift = 27, .kvco_mask = 1 },   /* PLLC */
+       { .m_shift = 0, .m_mask = 0xFF, .n_shift = 8, .n_mask = 0xFF,  .p_shift = 0,  .p_mask = 0,
+         .lock_ena = 0,  .lock_det = 27, .kcp_shift = 1, .kcp_mask = 3, .kvco_shift = 0, .kvco_mask = 1 },     /* PLLM */
+       { .m_shift = 0, .m_mask = 0x1F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x07,
+         .lock_ena = 18, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF }, /* PLLP */
+       { .m_shift = 0, .m_mask = 0x1F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x07,
+         .lock_ena = 18, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF }, /* PLLA */
+       { .m_shift = 0, .m_mask = 0x1F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x01,
+         .lock_ena = 22, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF }, /* PLLU */
+       { .m_shift = 0, .m_mask = 0x1F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x07,
+         .lock_ena = 22, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF }, /* PLLD */
+       { .m_shift = 0, .m_mask = 0xFF, .n_shift = 8, .n_mask = 0xFF,  .p_shift = 20, .p_mask = 0x0F,
+         .lock_ena = 18, .lock_det = 27, .kcp_shift = 0, .kcp_mask = 0, .kvco_shift = 0, .kvco_mask = 0 },     /* PLLX */
+       { .m_shift = 0, .m_mask = 0xFF, .n_shift = 8, .n_mask = 0xFF,  .p_shift = 0,  .p_mask = 0,
+         .lock_ena = 9,  .lock_det = 11, .kcp_shift = 6, .kcp_mask = 3, .kvco_shift = 0, .kvco_mask = 1 },     /* PLLE */
+       { .m_shift = 0, .m_mask = 0x0F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x07,
+         .lock_ena = 18, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF }, /* PLLS (RESERVED) */
+};
+
 /*
  * Get the oscillator frequency, from the corresponding hardware configuration
  * field. Note that Tegra30+ support 3 new higher freqs, but we map back
@@ -772,6 +802,8 @@ void clock_early_init(void)
 {
        struct clk_rst_ctlr *clkrst =
                (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+       struct clk_pll_info *pllinfo;
+       u32 data;
 
        tegra30_set_up_pllp();
 
@@ -808,11 +840,15 @@ void clock_early_init(void)
        writel(0x00561600, &clkrst->crc_pll[CLOCK_ID_CGENERAL].pll_out[1]);
 
        /* PLLC_MISC: Set LOCK_ENABLE */
-       writel(0x01000000, &clkrst->crc_pll[CLOCK_ID_CGENERAL].pll_misc);
+       pllinfo = &tegra_pll_info_table[CLOCK_ID_CGENERAL];
+       setbits_le32(&clkrst->crc_pll[CLOCK_ID_CGENERAL].pll_misc, (1 << pllinfo->lock_ena));
        udelay(2);
 
-       /* PLLD_MISC: Set CLKENABLE, CPCON 12, LFCON 1 */
-       writel(0x40000C10, &clkrst->crc_pll[CLOCK_ID_DISPLAY].pll_misc);
+       /* PLLD_MISC: Set CLKENABLE, CPCON 12, LFCON 1, and enable lock */
+       pllinfo = &tegra_pll_info_table[CLOCK_ID_DISPLAY];
+       data = (12 << pllinfo->kcp_shift) | (1 << pllinfo->kvco_shift);
+       data |= (1 << PLLD_CLKENABLE) | (1 << pllinfo->lock_ena);
+       writel(data, &clkrst->crc_pll[CLOCK_ID_DISPLAY].pll_misc);
        udelay(2);
 }
 
index 974f203f12b6ee8fd7b231d7ef398f8f20efe925..0aca6583bacd66b863995db588215bf8be979ee8 100644 (file)
@@ -23,7 +23,7 @@ static void enable_cpu_power_rail(void)
 {
        struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
 
-       debug("enable_cpu_power_rail entry\n");
+       debug("%s entry\n", __func__);
 
        /* un-tristate PWR_I2C SCL/SDA, rest of the defaults are correct */
        pinmux_tristate_disable(PMUX_PINGRP_PWR_I2C_SCL_PZ6);
@@ -45,15 +45,16 @@ static void enable_cpu_power_rail(void)
 static void enable_cpu_clocks(void)
 {
        struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+       struct clk_pll_info *pllinfo = &tegra_pll_info_table[CLOCK_ID_XCPU];
        u32 reg;
 
-       debug("enable_cpu_clocks entry\n");
+       debug("%s entry\n", __func__);
 
        /* Wait for PLL-X to lock */
        do {
                reg = readl(&clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base);
                debug("%s: PLLX base = 0x%08X\n", __func__, reg);
-       } while ((reg & PLL_LOCK_MASK) == 0);
+       } while ((reg & (1 << pllinfo->lock_det)) == 0);
 
        debug("%s: PLLX locked, delay for stable clocks\n", __func__);
        /* Wait until all clocks are stable */
@@ -83,7 +84,7 @@ static void remove_cpu_resets(void)
        struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
        u32 reg;
 
-       debug("remove_cpu_resets entry\n");
+       debug("%s entry\n", __func__);
 
        /* Take the slow and fast partitions out of reset */
        reg = CLR_NONCPURESET;
@@ -105,7 +106,7 @@ static void remove_cpu_resets(void)
 }
 
 /**
- * The Tegra124 requires some special clock initialization, including setting up
+ * Tegra124 requires some special clock initialization, including setting up
  * the DVC I2C, turning on MSELECT and selecting the G CPU cluster
  */
 void tegra124_init_clocks(void)
@@ -116,7 +117,7 @@ void tegra124_init_clocks(void)
                        (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
        u32 val;
 
-       debug("tegra124_init_clocks entry\n");
+       debug("%s entry\n", __func__);
 
        /* Set active CPU cluster to G */
        clrbits_le32(&flow->cluster_control, 1);
@@ -188,7 +189,7 @@ void tegra124_init_clocks(void)
        reset_set_enable(PERIPH_ID_MSELECT, 0);
        reset_set_enable(PERIPH_ID_DVFS, 0);
 
-       debug("tegra124_init_clocks exit\n");
+       debug("%s exit\n", __func__);
 }
 
 static bool is_partition_powered(u32 partid)
@@ -223,31 +224,29 @@ static void power_partition(u32 partid)
 
 void powerup_cpus(void)
 {
-       debug("powerup_cpus entry\n");
-
        /* We boot to the fast cluster */
-       debug("powerup_cpus entry: G cluster\n");
+       debug("%s entry: G cluster\n", __func__);
 
        /* Power up the fast cluster rail partition */
-       debug("powerup_cpus: CRAIL\n");
+       debug("%s: CRAIL\n", __func__);
        power_partition(CRAIL);
 
        /* Power up the fast cluster non-CPU partition */
-       debug("powerup_cpus: C0NC\n");
+       debug("%s: C0NC\n", __func__);
        power_partition(C0NC);
 
        /* Power up the fast cluster CPU0 partition */
-       debug("powerup_cpus: CE0\n");
+       debug("%s: CE0\n", __func__);
        power_partition(CE0);
 
-       debug("powerup_cpus: done\n");
+       debug("%s: done\n", __func__);
 }
 
 void start_cpu(u32 reset_vector)
 {
        struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
 
-       debug("start_cpu entry, reset_vector = %x\n", reset_vector);
+       debug("%s entry, reset_vector = %x\n", __func__, reset_vector);
 
        tegra124_init_clocks();
 
@@ -261,5 +260,5 @@ void start_cpu(u32 reset_vector)
        remove_cpu_resets();
        writel(reset_vector, EXCEP_VECTOR_CPU_RESET_VECTOR);
        powerup_cpus();
-       debug("start_cpu exit, should continue @ reset_vector\n");
+       debug("%s exit, should continue @ reset_vector\n", __func__);
 }
index 7b9e10cd93ae37e7b42a4f3763a58029a1696767..dea459b164be4c3ada7f7d4caa742cb1fb1261ad 100644 (file)
@@ -1,5 +1,7 @@
 /*
  * Copyright (c) 2011 The Chromium OS Authors.
+ * (C) Copyright 2010-2015
+ * NVIDIA Corporation <www.nvidia.com>
  *
  * SPDX-License-Identifier:    GPL-2.0+
  */
@@ -354,6 +356,36 @@ static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = {
        NONE(CRAM2),
 };
 
+/*
+ * PLL divider shift/mask tables for all PLL IDs.
+ */
+struct clk_pll_info tegra_pll_info_table[CLOCK_ID_PLL_COUNT] = {
+       /*
+        * T20 and T25
+        * NOTE: If kcp_mask/kvco_mask == 0, they're not used in that PLL (PLLX, etc.)
+        *       If lock_ena or lock_det are >31, they're not used in that PLL.
+        */
+
+       { .m_shift = 0, .m_mask = 0xFF, .n_shift = 8, .n_mask = 0x3FF,  .p_shift = 20, .p_mask = 0x0F,
+         .lock_ena = 24, .lock_det = 27, .kcp_shift = 28, .kcp_mask = 3, .kvco_shift = 27, .kvco_mask = 1 },   /* PLLC */
+       { .m_shift = 0, .m_mask = 0xFF, .n_shift = 8, .n_mask = 0x3FF,  .p_shift = 0,  .p_mask = 0,
+         .lock_ena = 0,  .lock_det = 27, .kcp_shift = 1, .kcp_mask = 3, .kvco_shift = 0, .kvco_mask = 1 },     /* PLLM */
+       { .m_shift = 0, .m_mask = 0x1F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x07,
+         .lock_ena = 18, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF }, /* PLLP */
+       { .m_shift = 0, .m_mask = 0x1F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x07,
+         .lock_ena = 18, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF }, /* PLLA */
+       { .m_shift = 0, .m_mask = 0x1F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x01,
+         .lock_ena = 22, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF }, /* PLLU */
+       { .m_shift = 0, .m_mask = 0x1F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x07,
+         .lock_ena = 22, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF }, /* PLLD */
+       { .m_shift = 0, .m_mask = 0x1F, .n_shift = 8, .n_mask = 0x3FF,  .p_shift = 20, .p_mask = 0x0F,
+         .lock_ena = 18, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 0, .kvco_mask = 0 },   /* PLLX */
+       { .m_shift = 0, .m_mask = 0xFF, .n_shift = 8, .n_mask = 0xFF,  .p_shift = 0,  .p_mask = 0,
+         .lock_ena = 9,  .lock_det = 11, .kcp_shift = 6, .kcp_mask = 3, .kvco_shift = 0, .kvco_mask = 1 },     /* PLLE */
+       { .m_shift = 0, .m_mask = 0x0F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x07,
+         .lock_ena = 18, .lock_det = 0, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF },  /* PLLS */
+};
+
 /*
  * Get the oscillator frequency, from the corresponding hardware configuration
  * field. T20 has 4 frequencies that it supports.
index 7ac2a06f5e4cfb6e289f810668660c7d2421bb84..a7b3a949fc34606ba8d8bf2d97f4b68a2452a42e 100644 (file)
@@ -630,6 +630,34 @@ static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = {
        NONE(Y_RESERVED31),
 };
 
+/*
+ * PLL divider shift/mask tables for all PLL IDs.
+ */
+struct clk_pll_info tegra_pll_info_table[CLOCK_ID_PLL_COUNT] = {
+       /*
+        * NOTE: If kcp_mask/kvco_mask == 0, they're not used in that PLL (PLLC, etc.)
+        *       If lock_ena or lock_det are >31, they're not used in that PLL (PLLC, etc.)
+        */
+       { .m_shift = 0, .m_mask = 0xFF, .n_shift = 10, .n_mask = 0xFF, .p_shift = 20, .p_mask = 0x1F,
+         .lock_ena = 32,  .lock_det = 27, .kcp_shift = 0, .kcp_mask = 0, .kvco_shift = 0, .kvco_mask = 0 },    /* PLLC */
+       { .m_shift = 0, .m_mask = 0xFF, .n_shift = 8,  .n_mask = 0xFF, .p_shift = 20, .p_mask = 0x1F,
+         .lock_ena = 4,  .lock_det = 27, .kcp_shift = 1, .kcp_mask = 3, .kvco_shift = 0, .kvco_mask = 1 },     /* PLLM */
+       { .m_shift = 0, .m_mask = 0xFF, .n_shift = 10, .n_mask = 0xFF, .p_shift = 20, .p_mask = 0x1F,
+         .lock_ena = 18, .lock_det = 27, .kcp_shift = 0, .kcp_mask = 3, .kvco_shift = 2, .kvco_mask = 1 },     /* PLLP */
+       { .m_shift = 0, .m_mask = 0xFF, .n_shift = 8,  .n_mask = 0xFF, .p_shift = 20, .p_mask = 0x1F,
+         .lock_ena = 28, .lock_det = 27, .kcp_shift = 25, .kcp_mask = 3, .kvco_shift = 24, .kvco_mask = 1 },   /* PLLA */
+       { .m_shift = 0, .m_mask = 0xFF, .n_shift = 8,  .n_mask = 0xFF, .p_shift = 16, .p_mask = 0x1F,
+         .lock_ena = 29, .lock_det = 27, .kcp_shift = 25, .kcp_mask = 3, .kvco_shift = 24, .kvco_mask = 1 },   /* PLLU */
+       { .m_shift = 0, .m_mask = 0xFF, .n_shift = 11, .n_mask = 0xFF, .p_shift = 20, .p_mask = 0x07,
+         .lock_ena = 18, .lock_det = 27, .kcp_shift = 23, .kcp_mask = 3, .kvco_shift = 22, .kvco_mask = 1 },   /* PLLD */
+       { .m_shift = 0, .m_mask = 0xFF, .n_shift = 8,  .n_mask = 0xFF, .p_shift = 20, .p_mask = 0x1F,
+         .lock_ena = 18, .lock_det = 27, .kcp_shift = 1, .kcp_mask = 3, .kvco_shift = 0, .kvco_mask = 1 },     /* PLLX */
+       { .m_shift = 0, .m_mask = 0xFF, .n_shift = 8,  .n_mask = 0xFF, .p_shift = 0,  .p_mask = 0,
+         .lock_ena = 9,  .lock_det = 11, .kcp_shift = 6, .kcp_mask = 3, .kvco_shift = 0, .kvco_mask = 1 },     /* PLLE */
+       { .m_shift = 0, .m_mask = 0, .n_shift = 0, .n_mask = 0, .p_shift = 0, .p_mask = 0,
+         .lock_ena = 0, .lock_det = 0, .kcp_shift = 0, .kcp_mask = 0, .kvco_shift = 0, .kvco_mask = 0 },       /* PLLS (gone)*/
+};
+
 /*
  * Get the oscillator frequency, from the corresponding hardware configuration
  * field. Note that Tegra30+ support 3 new higher freqs, but we map back
@@ -903,6 +931,7 @@ void clock_early_init(void)
 {
        struct clk_rst_ctlr *clkrst =
                (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
+       struct clk_pll_info *pllinfo = &tegra_pll_info_table[CLOCK_ID_DISPLAY];
        u32 data;
 
        tegra210_setup_pllp();
@@ -957,7 +986,7 @@ void clock_early_init(void)
        udelay(2);
 
        /* PLLD_MISC: Set CLKENABLE and LOCK_DETECT bits */
-       data = (1 << PLLD_ENABLE_CLK) | (1 << PLLD_EN_LCKDET);
+       data = (1 << PLLD_ENABLE_CLK) | (1 << pllinfo->lock_ena);
        writel(data, &clkrst->crc_pll[CLOCK_ID_DISPLAY].pll_misc);
        udelay(2);
 }
index 0eb0f0ade37c518ae27707ba0c433fc4db12da01..3ce508b0b25b56011168dbc2d1f9a15beba5c557 100644 (file)
@@ -1,17 +1,8 @@
 /*
- * Copyright (c) 2010-2014, NVIDIA CORPORATION.  All rights reserved.
+ * (C) Copyright 2010-2015
+ * NVIDIA Corporation <www.nvidia.com>
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier:     GPL-2.0+
  */
 
 /* Tegra30 Clock control functions */
@@ -414,6 +405,36 @@ static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = {
        NONE(EX_RESERVED47),
 };
 
+/*
+ * PLL divider shift/mask tables for all PLL IDs.
+ */
+struct clk_pll_info tegra_pll_info_table[CLOCK_ID_PLL_COUNT] = {
+       /*
+        * T30: some deviations from T2x.
+        * NOTE: If kcp_mask/kvco_mask == 0, they're not used in that PLL (PLLX, etc.)
+        *       If lock_ena or lock_det are >31, they're not used in that PLL.
+        */
+
+       { .m_shift = 0, .m_mask = 0xFF, .n_shift = 8, .n_mask = 0x3FF,  .p_shift = 20, .p_mask = 0x0F,
+         .lock_ena = 24, .lock_det = 27, .kcp_shift = 28, .kcp_mask = 3, .kvco_shift = 27, .kvco_mask = 1 },   /* PLLC */
+       { .m_shift = 0, .m_mask = 0xFF, .n_shift = 8, .n_mask = 0x3FF,  .p_shift = 0,  .p_mask = 0,
+         .lock_ena = 0,  .lock_det = 27, .kcp_shift = 1, .kcp_mask = 3, .kvco_shift = 0, .kvco_mask = 1 },     /* PLLM */
+       { .m_shift = 0, .m_mask = 0x1F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x07,
+         .lock_ena = 18, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF }, /* PLLP */
+       { .m_shift = 0, .m_mask = 0x1F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x07,
+         .lock_ena = 18, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF }, /* PLLA */
+       { .m_shift = 0, .m_mask = 0x1F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x01,
+         .lock_ena = 22, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF }, /* PLLU */
+       { .m_shift = 0, .m_mask = 0x1F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x07,
+         .lock_ena = 22, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF }, /* PLLD */
+       { .m_shift = 0, .m_mask = 0xFF, .n_shift = 8, .n_mask = 0xFF,  .p_shift = 20, .p_mask = 0x0F,
+         .lock_ena = 18, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 0, .kvco_mask = 0 },   /* PLLX */
+       { .m_shift = 0, .m_mask = 0xFF, .n_shift = 8, .n_mask = 0xFF,  .p_shift = 0,  .p_mask = 0,
+         .lock_ena = 9,  .lock_det = 11, .kcp_shift = 6, .kcp_mask = 3, .kvco_shift = 0, .kvco_mask = 1 },     /* PLLE */
+       { .m_shift = 0, .m_mask = 0x0F, .n_shift = 8, .n_mask = 0x3FF, .p_shift = 20, .p_mask = 0x07,
+         .lock_ena = 18, .lock_det = 27, .kcp_shift = 8, .kcp_mask = 0xF, .kvco_shift = 4, .kvco_mask = 0xF }, /* PLLS (RESERVED) */
+};
+
 /*
  * Get the oscillator frequency, from the corresponding hardware configuration
  * field. Note that T30 supports 3 new higher freqs, but we map back