summaryrefslogtreecommitdiffstats
path: root/drivers/clk/tegra/clk-tegra210.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/tegra/clk-tegra210.c')
-rw-r--r--drivers/clk/tegra/clk-tegra210.c2852
1 files changed, 2852 insertions, 0 deletions
diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c
new file mode 100644
index 000000000000..58514c44ea83
--- /dev/null
+++ b/drivers/clk/tegra/clk-tegra210.c
@@ -0,0 +1,2852 @@
+/*
+ * Copyright (c) 2012-2014 NVIDIA CORPORATION. All rights reserved.
+ *
+ * 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/>.
+ */
+
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/delay.h>
+#include <linux/export.h>
+#include <linux/clk/tegra.h>
+#include <dt-bindings/clock/tegra210-car.h>
+
+#include "clk.h"
+#include "clk-id.h"
+
+/*
+ * TEGRA210_CAR_BANK_COUNT: the number of peripheral clock register
+ * banks present in the Tegra210 CAR IP block. The banks are
+ * identified by single letters, e.g.: L, H, U, V, W, X, Y. See
+ * periph_regs[] in drivers/clk/tegra/clk.c
+ */
+#define TEGRA210_CAR_BANK_COUNT 7
+
+#define CLK_SOURCE_CSITE 0x1d4
+#define CLK_SOURCE_EMC 0x19c
+
+#define PLLC_BASE 0x80
+#define PLLC_OUT 0x84
+#define PLLC_MISC0 0x88
+#define PLLC_MISC1 0x8c
+#define PLLC_MISC2 0x5d0
+#define PLLC_MISC3 0x5d4
+
+#define PLLC2_BASE 0x4e8
+#define PLLC2_MISC0 0x4ec
+#define PLLC2_MISC1 0x4f0
+#define PLLC2_MISC2 0x4f4
+#define PLLC2_MISC3 0x4f8
+
+#define PLLC3_BASE 0x4fc
+#define PLLC3_MISC0 0x500
+#define PLLC3_MISC1 0x504
+#define PLLC3_MISC2 0x508
+#define PLLC3_MISC3 0x50c
+
+#define PLLM_BASE 0x90
+#define PLLM_MISC0 0x9c
+#define PLLM_MISC1 0x98
+#define PLLP_BASE 0xa0
+#define PLLP_MISC0 0xac
+#define PLLP_MISC1 0x680
+#define PLLA_BASE 0xb0
+#define PLLA_MISC0 0xbc
+#define PLLA_MISC1 0xb8
+#define PLLA_MISC2 0x5d8
+#define PLLD_BASE 0xd0
+#define PLLD_MISC0 0xdc
+#define PLLD_MISC1 0xd8
+#define PLLU_BASE 0xc0
+#define PLLU_OUTA 0xc4
+#define PLLU_MISC0 0xcc
+#define PLLU_MISC1 0xc8
+#define PLLX_BASE 0xe0
+#define PLLX_MISC0 0xe4
+#define PLLX_MISC1 0x510
+#define PLLX_MISC2 0x514
+#define PLLX_MISC3 0x518
+#define PLLX_MISC4 0x5f0
+#define PLLX_MISC5 0x5f4
+#define PLLE_BASE 0xe8
+#define PLLE_MISC0 0xec
+#define PLLD2_BASE 0x4b8
+#define PLLD2_MISC0 0x4bc
+#define PLLD2_MISC1 0x570
+#define PLLD2_MISC2 0x574
+#define PLLD2_MISC3 0x578
+#define PLLE_AUX 0x48c
+#define PLLRE_BASE 0x4c4
+#define PLLRE_MISC0 0x4c8
+#define PLLDP_BASE 0x590
+#define PLLDP_MISC 0x594
+
+#define PLLC4_BASE 0x5a4
+#define PLLC4_MISC0 0x5a8
+#define PLLC4_OUT 0x5e4
+#define PLLMB_BASE 0x5e8
+#define PLLMB_MISC0 0x5ec
+#define PLLA1_BASE 0x6a4
+#define PLLA1_MISC0 0x6a8
+#define PLLA1_MISC1 0x6ac
+#define PLLA1_MISC2 0x6b0
+#define PLLA1_MISC3 0x6b4
+
+#define PLLU_IDDQ_BIT 31
+#define PLLCX_IDDQ_BIT 27
+#define PLLRE_IDDQ_BIT 24
+#define PLLA_IDDQ_BIT 25
+#define PLLD_IDDQ_BIT 20
+#define PLLSS_IDDQ_BIT 18
+#define PLLM_IDDQ_BIT 5
+#define PLLMB_IDDQ_BIT 17
+#define PLLXP_IDDQ_BIT 3
+
+#define PLLCX_RESET_BIT 30
+
+#define PLL_BASE_LOCK BIT(27)
+#define PLLCX_BASE_LOCK BIT(26)
+#define PLLE_MISC_LOCK BIT(11)
+#define PLLRE_MISC_LOCK BIT(27)
+
+#define PLL_MISC_LOCK_ENABLE 18
+#define PLLC_MISC_LOCK_ENABLE 24
+#define PLLDU_MISC_LOCK_ENABLE 22
+#define PLLU_MISC_LOCK_ENABLE 29
+#define PLLE_MISC_LOCK_ENABLE 9
+#define PLLRE_MISC_LOCK_ENABLE 30
+#define PLLSS_MISC_LOCK_ENABLE 30
+#define PLLP_MISC_LOCK_ENABLE 18
+#define PLLM_MISC_LOCK_ENABLE 4
+#define PLLMB_MISC_LOCK_ENABLE 16
+#define PLLA_MISC_LOCK_ENABLE 28
+#define PLLU_MISC_LOCK_ENABLE 29
+#define PLLD_MISC_LOCK_ENABLE 18
+
+#define PLLA_SDM_DIN_MASK 0xffff
+#define PLLA_SDM_EN_MASK BIT(26)
+
+#define PLLD_SDM_EN_MASK BIT(16)
+
+#define PLLD2_SDM_EN_MASK BIT(31)
+#define PLLD2_SSC_EN_MASK BIT(30)
+
+#define PLLDP_SS_CFG 0x598
+#define PLLDP_SDM_EN_MASK BIT(31)
+#define PLLDP_SSC_EN_MASK BIT(30)
+#define PLLDP_SS_CTRL1 0x59c
+#define PLLDP_SS_CTRL2 0x5a0
+
+#define PMC_PLLM_WB0_OVERRIDE 0x1dc
+#define PMC_PLLM_WB0_OVERRIDE_2 0x2b0
+
+#define UTMIP_PLL_CFG2 0x488
+#define UTMIP_PLL_CFG2_STABLE_COUNT(x) (((x) & 0xfff) << 6)
+#define UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(x) (((x) & 0x3f) << 18)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN BIT(0)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERUP BIT(1)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN BIT(2)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERUP BIT(3)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN BIT(4)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERUP BIT(5)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERDOWN BIT(24)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERUP BIT(25)
+
+#define UTMIP_PLL_CFG1 0x484
+#define UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 27)
+#define UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0)
+#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERUP BIT(17)
+#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN BIT(16)
+#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP BIT(15)
+#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN BIT(14)
+#define UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN BIT(12)
+
+#define UTMIPLL_HW_PWRDN_CFG0 0x52c
+#define UTMIPLL_HW_PWRDN_CFG0_UTMIPLL_LOCK BIT(31)
+#define UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE BIT(25)
+#define UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE BIT(24)
+#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_PD_INCLUDE BIT(7)
+#define UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET BIT(6)
+#define UTMIPLL_HW_PWRDN_CFG0_SEQ_RESET_INPUT_VALUE BIT(5)
+#define UTMIPLL_HW_PWRDN_CFG0_SEQ_IN_SWCTL BIT(4)
+#define UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL BIT(2)
+#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE BIT(1)
+#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL BIT(0)
+
+#define PLLU_HW_PWRDN_CFG0 0x530
+#define PLLU_HW_PWRDN_CFG0_IDDQ_PD_INCLUDE BIT(28)
+#define PLLU_HW_PWRDN_CFG0_SEQ_ENABLE BIT(24)
+#define PLLU_HW_PWRDN_CFG0_USE_SWITCH_DETECT BIT(7)
+#define PLLU_HW_PWRDN_CFG0_USE_LOCKDET BIT(6)
+#define PLLU_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL BIT(2)
+#define PLLU_HW_PWRDN_CFG0_CLK_SWITCH_SWCTL BIT(0)
+
+#define XUSB_PLL_CFG0 0x534
+#define XUSB_PLL_CFG0_UTMIPLL_LOCK_DLY 0x3ff
+#define XUSB_PLL_CFG0_PLLU_LOCK_DLY_MASK (0x3ff << 14)
+
+#define SPARE_REG0 0x55c
+#define CLK_M_DIVISOR_SHIFT 2
+#define CLK_M_DIVISOR_MASK 0x3
+
+/*
+ * SDM fractional divisor is 16-bit 2's complement signed number within
+ * (-2^12 ... 2^12-1) range. Represented in PLL data structure as unsigned
+ * 16-bit value, with "0" divisor mapped to 0xFFFF. Data "0" is used to
+ * indicate that SDM is disabled.
+ *
+ * Effective ndiv value when SDM is enabled: ndiv + 1/2 + sdm_din/2^13
+ */
+#define PLL_SDM_COEFF BIT(13)
+#define sdin_din_to_data(din) ((u16)((din) ? : 0xFFFFU))
+#define sdin_data_to_din(dat) (((dat) == 0xFFFFU) ? 0 : (s16)dat)
+
+/* Tegra CPU clock and reset control regs */
+#define CLK_RST_CONTROLLER_CPU_CMPLX_STATUS 0x470
+
+#ifdef CONFIG_PM_SLEEP
+static struct cpu_clk_suspend_context {
+ u32 clk_csite_src;
+} tegra210_cpu_clk_sctx;
+#endif
+
+static void __iomem *clk_base;
+static void __iomem *pmc_base;
+
+static unsigned long osc_freq;
+static unsigned long pll_ref_freq;
+
+static DEFINE_SPINLOCK(pll_d_lock);
+static DEFINE_SPINLOCK(pll_e_lock);
+static DEFINE_SPINLOCK(pll_re_lock);
+static DEFINE_SPINLOCK(pll_u_lock);
+static DEFINE_SPINLOCK(emc_lock);
+
+/* possible OSC frequencies in Hz */
+static unsigned long tegra210_input_freq[] = {
+ [5] = 38400000,
+ [8] = 12000000,
+};
+
+static const char *mux_pllmcp_clkm[] = {
+ "pll_m", "pll_c", "pll_p", "clk_m", "pll_m_ud", "pll_c2", "pll_c3",
+};
+#define mux_pllmcp_clkm_idx NULL
+
+#define PLL_ENABLE (1 << 30)
+
+#define PLLCX_MISC1_IDDQ (1 << 27)
+#define PLLCX_MISC0_RESET (1 << 30)
+
+#define PLLCX_MISC0_DEFAULT_VALUE 0x40080000
+#define PLLCX_MISC0_WRITE_MASK 0x400ffffb
+#define PLLCX_MISC1_DEFAULT_VALUE 0x08000000
+#define PLLCX_MISC1_WRITE_MASK 0x08003cff
+#define PLLCX_MISC2_DEFAULT_VALUE 0x1f720f05
+#define PLLCX_MISC2_WRITE_MASK 0xffffff17
+#define PLLCX_MISC3_DEFAULT_VALUE 0x000000c4
+#define PLLCX_MISC3_WRITE_MASK 0x00ffffff
+
+/* PLLA */
+#define PLLA_BASE_IDDQ (1 << 25)
+#define PLLA_BASE_LOCK (1 << 27)
+
+#define PLLA_MISC0_LOCK_ENABLE (1 << 28)
+#define PLLA_MISC0_LOCK_OVERRIDE (1 << 27)
+
+#define PLLA_MISC2_EN_SDM (1 << 26)
+#define PLLA_MISC2_EN_DYNRAMP (1 << 25)
+
+#define PLLA_MISC0_DEFAULT_VALUE 0x12000020
+#define PLLA_MISC0_WRITE_MASK 0x7fffffff
+#define PLLA_MISC2_DEFAULT_VALUE 0x0
+#define PLLA_MISC2_WRITE_MASK 0x06ffffff
+
+/* PLLD */
+#define PLLD_MISC0_EN_SDM (1 << 16)
+#define PLLD_MISC0_LOCK_OVERRIDE (1 << 17)
+#define PLLD_MISC0_LOCK_ENABLE (1 << 18)
+#define PLLD_MISC0_IDDQ (1 << 20)
+#define PLLD_MISC0_DSI_CLKENABLE (1 << 21)
+
+#define PLLD_MISC0_DEFAULT_VALUE 0x00140000
+#define PLLD_MISC0_WRITE_MASK 0x3ff7ffff
+#define PLLD_MISC1_DEFAULT_VALUE 0x20
+#define PLLD_MISC1_WRITE_MASK 0x00ffffff
+
+/* PLLD2 and PLLDP and PLLC4 */
+#define PLLDSS_BASE_LOCK (1 << 27)
+#define PLLDSS_BASE_LOCK_OVERRIDE (1 << 24)
+#define PLLDSS_BASE_IDDQ (1 << 18)
+#define PLLDSS_BASE_REF_SEL_SHIFT 25
+#define PLLDSS_BASE_REF_SEL_MASK (0x3 << PLLDSS_BASE_REF_SEL_SHIFT)
+
+#define PLLDSS_MISC0_LOCK_ENABLE (1 << 30)
+
+#define PLLDSS_MISC1_CFG_EN_SDM (1 << 31)
+#define PLLDSS_MISC1_CFG_EN_SSC (1 << 30)
+
+#define PLLD2_MISC0_DEFAULT_VALUE 0x40000020
+#define PLLD2_MISC1_CFG_DEFAULT_VALUE 0x10000000
+#define PLLD2_MISC2_CTRL1_DEFAULT_VALUE 0x0
+#define PLLD2_MISC3_CTRL2_DEFAULT_VALUE 0x0
+
+#define PLLDP_MISC0_DEFAULT_VALUE 0x40000020
+#define PLLDP_MISC1_CFG_DEFAULT_VALUE 0xc0000000
+#define PLLDP_MISC2_CTRL1_DEFAULT_VALUE 0xf400f0da
+#define PLLDP_MISC3_CTRL2_DEFAULT_VALUE 0x2004f400
+
+#define PLLDSS_MISC0_WRITE_MASK 0x47ffffff
+#define PLLDSS_MISC1_CFG_WRITE_MASK 0xf8000000
+#define PLLDSS_MISC2_CTRL1_WRITE_MASK 0xffffffff
+#define PLLDSS_MISC3_CTRL2_WRITE_MASK 0xffffffff
+
+#define PLLC4_MISC0_DEFAULT_VALUE 0x40000000
+
+/* PLLRE */
+#define PLLRE_MISC0_LOCK_ENABLE (1 << 30)
+#define PLLRE_MISC0_LOCK_OVERRIDE (1 << 29)
+#define PLLRE_MISC0_LOCK (1 << 27)
+#define PLLRE_MISC0_IDDQ (1 << 24)
+
+#define PLLRE_BASE_DEFAULT_VALUE 0x0
+#define PLLRE_MISC0_DEFAULT_VALUE 0x41000000
+
+#define PLLRE_BASE_DEFAULT_MASK 0x1c000000
+#define PLLRE_MISC0_WRITE_MASK 0x67ffffff
+
+/* PLLX */
+#define PLLX_USE_DYN_RAMP 1
+#define PLLX_BASE_LOCK (1 << 27)
+
+#define PLLX_MISC0_FO_G_DISABLE (0x1 << 28)
+#define PLLX_MISC0_LOCK_ENABLE (0x1 << 18)
+
+#define PLLX_MISC2_DYNRAMP_STEPB_SHIFT 24
+#define PLLX_MISC2_DYNRAMP_STEPB_MASK (0xFF << PLLX_MISC2_DYNRAMP_STEPB_SHIFT)
+#define PLLX_MISC2_DYNRAMP_STEPA_SHIFT 16
+#define PLLX_MISC2_DYNRAMP_STEPA_MASK (0xFF << PLLX_MISC2_DYNRAMP_STEPA_SHIFT)
+#define PLLX_MISC2_NDIV_NEW_SHIFT 8
+#define PLLX_MISC2_NDIV_NEW_MASK (0xFF << PLLX_MISC2_NDIV_NEW_SHIFT)
+#define PLLX_MISC2_LOCK_OVERRIDE (0x1 << 4)
+#define PLLX_MISC2_DYNRAMP_DONE (0x1 << 2)
+#define PLLX_MISC2_EN_DYNRAMP (0x1 << 0)
+
+#define PLLX_MISC3_IDDQ (0x1 << 3)
+
+#define PLLX_MISC0_DEFAULT_VALUE PLLX_MISC0_LOCK_ENABLE
+#define PLLX_MISC0_WRITE_MASK 0x10c40000
+#define PLLX_MISC1_DEFAULT_VALUE 0x20
+#define PLLX_MISC1_WRITE_MASK 0x00ffffff
+#define PLLX_MISC2_DEFAULT_VALUE 0x0
+#define PLLX_MISC2_WRITE_MASK 0xffffff11
+#define PLLX_MISC3_DEFAULT_VALUE PLLX_MISC3_IDDQ
+#define PLLX_MISC3_WRITE_MASK 0x01ff0f0f
+#define PLLX_MISC4_DEFAULT_VALUE 0x0
+#define PLLX_MISC4_WRITE_MASK 0x8000ffff
+#define PLLX_MISC5_DEFAULT_VALUE 0x0
+#define PLLX_MISC5_WRITE_MASK 0x0000ffff
+
+#define PLLX_HW_CTRL_CFG 0x548
+#define PLLX_HW_CTRL_CFG_SWCTRL (0x1 << 0)
+
+/* PLLMB */
+#define PLLMB_BASE_LOCK (1 << 27)
+
+#define PLLMB_MISC0_LOCK_OVERRIDE (1 << 18)
+#define PLLMB_MISC0_IDDQ (1 << 17)
+#define PLLMB_MISC0_LOCK_ENABLE (1 << 16)
+
+#define PLLMB_MISC0_DEFAULT_VALUE 0x00030000
+#define PLLMB_MISC0_WRITE_MASK 0x0007ffff
+
+/* PLLP */
+#define PLLP_BASE_OVERRIDE (1 << 28)
+#define PLLP_BASE_LOCK (1 << 27)
+
+#define PLLP_MISC0_LOCK_ENABLE (1 << 18)
+#define PLLP_MISC0_LOCK_OVERRIDE (1 << 17)
+#define PLLP_MISC0_IDDQ (1 << 3)
+
+#define PLLP_MISC1_HSIO_EN_SHIFT 29
+#define PLLP_MISC1_HSIO_EN (1 << PLLP_MISC1_HSIO_EN_SHIFT)
+#define PLLP_MISC1_XUSB_EN_SHIFT 28
+#define PLLP_MISC1_XUSB_EN (1 << PLLP_MISC1_XUSB_EN_SHIFT)
+
+#define PLLP_MISC0_DEFAULT_VALUE 0x00040008
+#define PLLP_MISC1_DEFAULT_VALUE 0x0
+
+#define PLLP_MISC0_WRITE_MASK 0xdc6000f
+#define PLLP_MISC1_WRITE_MASK 0x70ffffff
+
+/* PLLU */
+#define PLLU_BASE_LOCK (1 << 27)
+#define PLLU_BASE_OVERRIDE (1 << 24)
+#define PLLU_BASE_CLKENABLE_USB (1 << 21)
+#define PLLU_BASE_CLKENABLE_HSIC (1 << 22)
+#define PLLU_BASE_CLKENABLE_ICUSB (1 << 23)
+#define PLLU_BASE_CLKENABLE_48M (1 << 25)
+#define PLLU_BASE_CLKENABLE_ALL (PLLU_BASE_CLKENABLE_USB |\
+ PLLU_BASE_CLKENABLE_HSIC |\
+ PLLU_BASE_CLKENABLE_ICUSB |\
+ PLLU_BASE_CLKENABLE_48M)
+
+#define PLLU_MISC0_IDDQ (1 << 31)
+#define PLLU_MISC0_LOCK_ENABLE (1 << 29)
+#define PLLU_MISC1_LOCK_OVERRIDE (1 << 0)
+
+#define PLLU_MISC0_DEFAULT_VALUE 0xa0000000
+#define PLLU_MISC1_DEFAULT_VALUE 0x0
+
+#define PLLU_MISC0_WRITE_MASK 0xbfffffff
+#define PLLU_MISC1_WRITE_MASK 0x00000007
+
+static inline void _pll_misc_chk_default(void __iomem *base,
+ struct tegra_clk_pll_params *params,
+ u8 misc_num, u32 default_val, u32 mask)
+{
+ u32 boot_val = readl_relaxed(base + params->ext_misc_reg[misc_num]);
+
+ boot_val &= mask;
+ default_val &= mask;
+ if (boot_val != default_val) {
+ pr_warn("boot misc%d 0x%x: expected 0x%x\n",
+ misc_num, boot_val, default_val);
+ pr_warn(" (comparison mask = 0x%x)\n", mask);
+ params->defaults_set = false;
+ }
+}
+
+/*
+ * PLLCX: PLLC, PLLC2, PLLC3, PLLA1
+ * Hybrid PLLs with dynamic ramp. Dynamic ramp is allowed for any transition
+ * that changes NDIV only, while PLL is already locked.
+ */
+static void pllcx_check_defaults(struct tegra_clk_pll_params *params)
+{
+ u32 default_val;
+
+ default_val = PLLCX_MISC0_DEFAULT_VALUE & (~PLLCX_MISC0_RESET);
+ _pll_misc_chk_default(clk_base, params, 0, default_val,
+ PLLCX_MISC0_WRITE_MASK);
+
+ default_val = PLLCX_MISC1_DEFAULT_VALUE & (~PLLCX_MISC1_IDDQ);
+ _pll_misc_chk_default(clk_base, params, 1, default_val,
+ PLLCX_MISC1_WRITE_MASK);
+
+ default_val = PLLCX_MISC2_DEFAULT_VALUE;
+ _pll_misc_chk_default(clk_base, params, 2, default_val,
+ PLLCX_MISC2_WRITE_MASK);
+
+ default_val = PLLCX_MISC3_DEFAULT_VALUE;
+ _pll_misc_chk_default(clk_base, params, 3, default_val,
+ PLLCX_MISC3_WRITE_MASK);
+}
+
+void tegra210_pllcx_set_defaults(const char *name, struct tegra_clk_pll *pllcx)
+{
+ pllcx->params->defaults_set = true;
+
+ if (readl_relaxed(clk_base + pllcx->params->base_reg) &
+ PLL_ENABLE) {
+ /* PLL is ON: only check if defaults already set */
+ pllcx_check_defaults(pllcx->params);
+ pr_warn("%s already enabled. Postponing set full defaults\n",
+ name);
+ return;
+ }
+
+ /* Defaults assert PLL reset, and set IDDQ */
+ writel_relaxed(PLLCX_MISC0_DEFAULT_VALUE,
+ clk_base + pllcx->params->ext_misc_reg[0]);
+ writel_relaxed(PLLCX_MISC1_DEFAULT_VALUE,
+ clk_base + pllcx->params->ext_misc_reg[1]);
+ writel_relaxed(PLLCX_MISC2_DEFAULT_VALUE,
+ clk_base + pllcx->params->ext_misc_reg[2]);
+ writel_relaxed(PLLCX_MISC3_DEFAULT_VALUE,
+ clk_base + pllcx->params->ext_misc_reg[3]);
+ udelay(1);
+}
+
+void _pllc_set_defaults(struct tegra_clk_pll *pllcx)
+{
+ tegra210_pllcx_set_defaults("PLL_C", pllcx);
+}
+
+void _pllc2_set_defaults(struct tegra_clk_pll *pllcx)
+{
+ tegra210_pllcx_set_defaults("PLL_C2", pllcx);
+}
+
+void _pllc3_set_defaults(struct tegra_clk_pll *pllcx)
+{
+ tegra210_pllcx_set_defaults("PLL_C3", pllcx);
+}
+
+void _plla1_set_defaults(struct tegra_clk_pll *pllcx)
+{
+ tegra210_pllcx_set_defaults("PLL_A1", pllcx);
+}
+
+/*
+ * PLLA
+ * PLL with dynamic ramp and fractional SDM. Dynamic ramp is not used.
+ * Fractional SDM is allowed to provide exact audio rates.
+ */
+void tegra210_plla_set_defaults(struct tegra_clk_pll *plla)
+{
+ u32 mask;
+ u32 val = readl_relaxed(clk_base + plla->params->base_reg);
+
+ plla->params->defaults_set = true;
+
+ if (val & PLL_ENABLE) {
+ /*
+ * PLL is ON: check if defaults already set, then set those
+ * that can be updated in flight.
+ */
+ if (val & PLLA_BASE_IDDQ) {
+ pr_warn("PLL_A boot enabled with IDDQ set\n");
+ plla->params->defaults_set = false;
+ }
+
+ pr_warn("PLL_A already enabled. Postponing set full defaults\n");
+
+ val = PLLA_MISC0_DEFAULT_VALUE; /* ignore lock enable */
+ mask = PLLA_MISC0_LOCK_ENABLE | PLLA_MISC0_LOCK_OVERRIDE;
+ _pll_misc_chk_default(clk_base, plla->params, 0, val,
+ ~mask & PLLA_MISC0_WRITE_MASK);
+
+ val = PLLA_MISC2_DEFAULT_VALUE; /* ignore all but control bit */
+ _pll_misc_chk_default(clk_base, plla->params, 2, val,
+ PLLA_MISC2_EN_DYNRAMP);
+
+ /* Enable lock detect */
+ val = readl_relaxed(clk_base + plla->params->ext_misc_reg[0]);
+ val &= ~mask;
+ val |= PLLA_MISC0_DEFAULT_VALUE & mask;
+ writel_relaxed(val, clk_base + plla->params->ext_misc_reg[0]);
+ udelay(1);
+
+ return;
+ }
+
+ /* set IDDQ, enable lock detect, disable dynamic ramp and SDM */
+ val |= PLLA_BASE_IDDQ;
+ writel_relaxed(val, clk_base + plla->params->base_reg);
+ writel_relaxed(PLLA_MISC0_DEFAULT_VALUE,
+ clk_base + plla->params->ext_misc_reg[0]);
+ writel_relaxed(PLLA_MISC2_DEFAULT_VALUE,
+ clk_base + plla->params->ext_misc_reg[2]);
+ udelay(1);
+}
+
+/*
+ * PLLD
+ * PLL with fractional SDM.
+ */
+void tegra210_plld_set_defaults(struct tegra_clk_pll *plld)
+{
+ u32 val;
+ u32 mask = 0xffff;
+
+ plld->params->defaults_set = true;
+
+ if (readl_relaxed(clk_base + plld->params->base_reg) &
+ PLL_ENABLE) {
+ pr_warn("PLL_D already enabled. Postponing set full defaults\n");
+
+ /*
+ * PLL is ON: check if defaults already set, then set those
+ * that can be updated in flight.
+ */
+ val = PLLD_MISC1_DEFAULT_VALUE;
+ _pll_misc_chk_default(clk_base, plld->params, 1,
+ val, PLLD_MISC1_WRITE_MASK);
+
+ /* ignore lock, DSI and SDM controls, make sure IDDQ not set */
+ val = PLLD_MISC0_DEFAULT_VALUE & (~PLLD_MISC0_IDDQ);
+ mask |= PLLD_MISC0_DSI_CLKENABLE | PLLD_MISC0_LOCK_ENABLE |
+ PLLD_MISC0_LOCK_OVERRIDE | PLLD_MISC0_EN_SDM;
+ _pll_misc_chk_default(clk_base, plld->params, 0, val,
+ ~mask & PLLD_MISC0_WRITE_MASK);
+
+ /* Enable lock detect */
+ mask = PLLD_MISC0_LOCK_ENABLE | PLLD_MISC0_LOCK_OVERRIDE;
+ val = readl_relaxed(clk_base + plld->params->ext_misc_reg[0]);
+ val &= ~mask;
+ val |= PLLD_MISC0_DEFAULT_VALUE & mask;
+ writel_relaxed(val, clk_base + plld->params->ext_misc_reg[0]);
+ udelay(1);
+
+ return;
+ }
+
+ val = readl_relaxed(clk_base + plld->params->ext_misc_reg[0]);
+ val &= PLLD_MISC0_DSI_CLKENABLE;
+ val |= PLLD_MISC0_DEFAULT_VALUE;
+ /* set IDDQ, enable lock detect, disable SDM */
+ writel_relaxed(val, clk_base + plld->params->ext_misc_reg[0]);
+ writel_relaxed(PLLD_MISC1_DEFAULT_VALUE, clk_base +
+ plld->params->ext_misc_reg[1]);
+ udelay(1);
+}
+
+/*
+ * PLLD2, PLLDP
+ * PLL with fractional SDM and Spread Spectrum (SDM is a must if SSC is used).
+ */
+static void plldss_defaults(const char *pll_name, struct tegra_clk_pll *plldss,
+ u32 misc0_val, u32 misc1_val, u32 misc2_val, u32 misc3_val)
+{
+ u32 default_val;
+ u32 val = readl_relaxed(clk_base + plldss->params->base_reg);
+
+ plldss->params->defaults_set = true;
+
+ if (val & PLL_ENABLE) {
+ pr_warn("%s already enabled. Postponing set full defaults\n",
+ pll_name);
+
+ /*
+ * PLL is ON: check if defaults already set, then set those
+ * that can be updated in flight.
+ */
+ if (val & PLLDSS_BASE_IDDQ) {
+ pr_warn("plldss boot enabled with IDDQ set\n");
+ plldss->params->defaults_set = false;
+ }
+
+ /* ignore lock enable */
+ default_val = misc0_val;
+ _pll_misc_chk_default(clk_base, plldss->params, 0, default_val,
+ PLLDSS_MISC0_WRITE_MASK &
+ (~PLLDSS_MISC0_LOCK_ENABLE));
+
+ /*
+ * If SSC is used, check all settings, otherwise just confirm
+ * that SSC is not used on boot as well. Do nothing when using
+ * this function for PLLC4 that has only MISC0.
+ */
+ if (plldss->params->ssc_ctrl_en_mask) {
+ default_val = misc1_val;
+ _pll_misc_chk_default(clk_base, plldss->params, 1,
+ default_val, PLLDSS_MISC1_CFG_WRITE_MASK);
+ default_val = misc2_val;
+ _pll_misc_chk_default(clk_base, plldss->params, 2,
+ default_val, PLLDSS_MISC2_CTRL1_WRITE_MASK);
+ default_val = misc3_val;
+ _pll_misc_chk_default(clk_base, plldss->params, 3,
+ default_val, PLLDSS_MISC3_CTRL2_WRITE_MASK);
+ } else if (plldss->params->ext_misc_reg[1]) {
+ default_val = misc1_val;
+ _pll_misc_chk_default(clk_base, plldss->params, 1,
+ default_val, PLLDSS_MISC1_CFG_WRITE_MASK &
+ (~PLLDSS_MISC1_CFG_EN_SDM));
+ }
+
+ /* Enable lock detect */
+ if (val & PLLDSS_BASE_LOCK_OVERRIDE) {
+ val &= ~PLLDSS_BASE_LOCK_OVERRIDE;
+ writel_relaxed(val, clk_base +
+ plldss->params->base_reg);
+ }
+
+ val = readl_relaxed(clk_base + plldss->params->ext_misc_reg[0]);
+ val &= ~PLLDSS_MISC0_LOCK_ENABLE;
+ val |= misc0_val & PLLDSS_MISC0_LOCK_ENABLE;
+ writel_relaxed(val, clk_base + plldss->params->ext_misc_reg[0]);
+ udelay(1);
+
+ return;
+ }
+
+ /* set IDDQ, enable lock detect, configure SDM/SSC */
+ val |= PLLDSS_BASE_IDDQ;
+ val &= ~PLLDSS_BASE_LOCK_OVERRIDE;
+ writel_relaxed(val, clk_base + plldss->params->base_reg);
+
+ /* When using this function for PLLC4 exit here */
+ if (!plldss->params->ext_misc_reg[1]) {
+ writel_relaxed(misc0_val, clk_base +
+ plldss->params->ext_misc_reg[0]);
+ udelay(1);
+ return;
+ }
+
+ writel_relaxed(misc0_val, clk_base +
+ plldss->params->ext_misc_reg[0]);
+ /* if SSC used set by 1st enable */
+ writel_relaxed(misc1_val & (~PLLDSS_MISC1_CFG_EN_SSC),
+ clk_base + plldss->params->ext_misc_reg[1]);
+ writel_relaxed(misc2_val, clk_base + plldss->params->ext_misc_reg[2]);
+ writel_relaxed(misc3_val, clk_base + plldss->params->ext_misc_reg[3]);
+ udelay(1);
+}
+
+void tegra210_plld2_set_defaults(struct tegra_clk_pll *plld2)
+{
+ plldss_defaults("PLL_D2", plld2, PLLD2_MISC0_DEFAULT_VALUE,
+ PLLD2_MISC1_CFG_DEFAULT_VALUE,
+ PLLD2_MISC2_CTRL1_DEFAULT_VALUE,
+ PLLD2_MISC3_CTRL2_DEFAULT_VALUE);
+}
+
+void tegra210_plldp_set_defaults(struct tegra_clk_pll *plldp)
+{
+ plldss_defaults("PLL_DP", plldp, PLLDP_MISC0_DEFAULT_VALUE,
+ PLLDP_MISC1_CFG_DEFAULT_VALUE,
+ PLLDP_MISC2_CTRL1_DEFAULT_VALUE,
+ PLLDP_MISC3_CTRL2_DEFAULT_VALUE);
+}
+
+/*
+ * PLLC4
+ * Base and misc0 layout is the same as PLLD2/PLLDP, but no SDM/SSC support.
+ * VCO is exposed to the clock tree via fixed 1/3 and 1/5 dividers.
+ */
+void tegra210_pllc4_set_defaults(struct tegra_clk_pll *pllc4)
+{
+ plldss_defaults("PLL_C4", pllc4, PLLC4_MISC0_DEFAULT_VALUE, 0, 0, 0);
+}
+
+/*
+ * PLLRE
+ * VCO is exposed to the clock tree directly along with post-divider output
+ */
+void tegra210_pllre_set_defaults(struct tegra_clk_pll *pllre)
+{
+ u32 mask;
+ u32 val = readl_relaxed(clk_base + pllre->params->base_reg);
+
+ pllre->params->defaults_set = true;
+
+ if (val & PLL_ENABLE) {
+ pr_warn("PLL_RE already enabled. Postponing set full defaults\n");
+
+ /*
+ * PLL is ON: check if defaults already set, then set those
+ * that can be updated in flight.
+ */
+ val &= PLLRE_BASE_DEFAULT_MASK;
+ if (val != PLLRE_BASE_DEFAULT_VALUE) {
+ pr_warn("pllre boot base 0x%x : expected 0x%x\n",
+ val, PLLRE_BASE_DEFAULT_VALUE);
+ pr_warn("(comparison mask = 0x%x)\n",
+ PLLRE_BASE_DEFAULT_MASK);
+ pllre->params->defaults_set = false;
+ }
+
+ /* Ignore lock enable */
+ val = PLLRE_MISC0_DEFAULT_VALUE & (~PLLRE_MISC0_IDDQ);
+ mask = PLLRE_MISC0_LOCK_ENABLE | PLLRE_MISC0_LOCK_OVERRIDE;
+ _pll_misc_chk_default(clk_base, pllre->params, 0, val,
+ ~mask & PLLRE_MISC0_WRITE_MASK);
+
+ /* Enable lock detect */
+ val = readl_relaxed(clk_base + pllre->params->ext_misc_reg[0]);
+ val &= ~mask;
+ val |= PLLRE_MISC0_DEFAULT_VALUE & mask;
+ writel_relaxed(val, clk_base + pllre->params->ext_misc_reg[0]);
+ udelay(1);
+
+ return;
+ }
+
+ /* set IDDQ, enable lock detect */
+ val &= ~PLLRE_BASE_DEFAULT_MASK;
+ val |= PLLRE_BASE_DEFAULT_VALUE & PLLRE_BASE_DEFAULT_MASK;
+ writel_relaxed(val, clk_base + pllre->params->base_reg);
+ writel_relaxed(PLLRE_MISC0_DEFAULT_VALUE,
+ clk_base + pllre->params->ext_misc_reg[0]);
+ udelay(1);
+}
+
+static void pllx_get_dyn_steps(struct clk_hw *hw, u32 *step_a, u32 *step_b)
+{
+ unsigned long input_rate;
+
+ if (!IS_ERR_OR_NULL(hw->clk)) {
+ input_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
+ /* cf rate */
+ input_rate /= tegra_pll_get_fixed_mdiv(hw, input_rate);
+ } else {
+ input_rate = 38400000;
+ }
+
+ switch (input_rate) {
+ case 12000000:
+ case 12800000:
+ case 13000000:
+ *step_a = 0x2B;
+ *step_b = 0x0B;
+ return;
+ case 19200000:
+ *step_a = 0x12;
+ *step_b = 0x08;
+ return;
+ case 38400000:
+ *step_a = 0x04;
+ *step_b = 0x05;
+ return;
+ default:
+ pr_err("%s: Unexpected reference rate %lu\n",
+ __func__, input_rate);
+ BUG();
+ }
+}
+
+static void pllx_check_defaults(struct tegra_clk_pll *pll)
+{
+ u32 default_val;
+
+ default_val = PLLX_MISC0_DEFAULT_VALUE;
+ /* ignore lock enable */
+ _pll_misc_chk_default(clk_base, pll->params, 0, default_val,
+ PLLX_MISC0_WRITE_MASK & (~PLLX_MISC0_LOCK_ENABLE));
+
+ default_val = PLLX_MISC1_DEFAULT_VALUE;
+ _pll_misc_chk_default(clk_base, pll->params, 1, default_val,
+ PLLX_MISC1_WRITE_MASK);
+
+ /* ignore all but control bit */
+ default_val = PLLX_MISC2_DEFAULT_VALUE;
+ _pll_misc_chk_default(clk_base, pll->params, 2,
+ default_val, PLLX_MISC2_EN_DYNRAMP);
+
+ default_val = PLLX_MISC3_DEFAULT_VALUE & (~PLLX_MISC3_IDDQ);
+ _pll_misc_chk_default(clk_base, pll->params, 3, default_val,
+ PLLX_MISC3_WRITE_MASK);
+
+ default_val = PLLX_MISC4_DEFAULT_VALUE;
+ _pll_misc_chk_default(clk_base, pll->params, 4, default_val,
+ PLLX_MISC4_WRITE_MASK);
+
+ default_val = PLLX_MISC5_DEFAULT_VALUE;
+ _pll_misc_chk_default(clk_base, pll->params, 5, default_val,
+ PLLX_MISC5_WRITE_MASK);
+}
+
+void tegra210_pllx_set_defaults(struct tegra_clk_pll *pllx)
+{
+ u32 val;
+ u32 step_a, step_b;
+
+ pllx->params->defaults_set = true;
+
+ /* Get ready dyn ramp state machine settings */
+ pllx_get_dyn_steps(&pllx->hw, &step_a, &step_b);
+ val = PLLX_MISC2_DEFAULT_VALUE & (~PLLX_MISC2_DYNRAMP_STEPA_MASK) &
+ (~PLLX_MISC2_DYNRAMP_STEPB_MASK);
+ val |= step_a << PLLX_MISC2_DYNRAMP_STEPA_SHIFT;
+ val |= step_b << PLLX_MISC2_DYNRAMP_STEPB_SHIFT;
+
+ if (readl_relaxed(clk_base + pllx->params->base_reg) & PLL_ENABLE) {
+ pr_warn("PLL_X already enabled. Postponing set full defaults\n");
+
+ /*
+ * PLL is ON: check if defaults already set, then set those
+ * that can be updated in flight.
+ */
+ pllx_check_defaults(pllx);
+
+ /* Configure dyn ramp, disable lock override */
+ writel_relaxed(val, clk_base + pllx->params->ext_misc_reg[2]);
+
+ /* Enable lock detect */
+ val = readl_relaxed(clk_base + pllx->params->ext_misc_reg[0]);
+ val &= ~PLLX_MISC0_LOCK_ENABLE;
+ val |= PLLX_MISC0_DEFAULT_VALUE & PLLX_MISC0_LOCK_ENABLE;
+ writel_relaxed(val, clk_base + pllx->params->ext_misc_reg[0]);
+ udelay(1);
+
+ return;
+ }
+
+ /* Enable lock detect and CPU output */
+ writel_relaxed(PLLX_MISC0_DEFAULT_VALUE, clk_base +
+ pllx->params->ext_misc_reg[0]);
+
+ /* Setup */
+ writel_relaxed(PLLX_MISC1_DEFAULT_VALUE, clk_base +
+ pllx->params->ext_misc_reg[1]);
+
+ /* Configure dyn ramp state machine, disable lock override */
+ writel_relaxed(val, clk_base + pllx->params->ext_misc_reg[2]);
+
+ /* Set IDDQ */
+ writel_relaxed(PLLX_MISC3_DEFAULT_VALUE, clk_base +
+ pllx->params->ext_misc_reg[3]);
+
+ /* Disable SDM */
+ writel_relaxed(PLLX_MISC4_DEFAULT_VALUE, clk_base +
+ pllx->params->ext_misc_reg[4]);
+ writel_relaxed(PLLX_MISC5_DEFAULT_VALUE, clk_base +
+ pllx->params->ext_misc_reg[5]);
+ udelay(1);
+}
+
+/* PLLMB */
+void tegra210_pllmb_set_defaults(struct tegra_clk_pll *pllmb)
+{
+ u32 mask, val = readl_relaxed(clk_base + pllmb->params->base_reg);
+
+ pllmb->params->defaults_set = true;
+
+ if (val & PLL_ENABLE) {
+ pr_warn("PLL_MB already enabled. Postponing set full defaults\n");
+
+ /*
+ * PLL is ON: check if defaults already set, then set those
+ * that can be updated in flight.
+ */
+ val = PLLMB_MISC0_DEFAULT_VALUE & (~PLLMB_MISC0_IDDQ);
+ mask = PLLMB_MISC0_LOCK_ENABLE | PLLMB_MISC0_LOCK_OVERRIDE;
+ _pll_misc_chk_default(clk_base, pllmb->params, 0, val,
+ ~mask & PLLMB_MISC0_WRITE_MASK);
+
+ /* Enable lock detect */
+ val = readl_relaxed(clk_base + pllmb->params->ext_misc_reg[0]);
+ val &= ~mask;
+ val |= PLLMB_MISC0_DEFAULT_VALUE & mask;
+ writel_relaxed(val, clk_base + pllmb->params->ext_misc_reg[0]);
+ udelay(1);
+
+ return;
+ }
+
+ /* set IDDQ, enable lock detect */
+ writel_relaxed(PLLMB_MISC0_DEFAULT_VALUE,
+ clk_base + pllmb->params->ext_misc_reg[0]);
+ udelay(1);
+}
+
+/*
+ * PLLP
+ * VCO is exposed to the clock tree directly along with post-divider output.
+ * Both VCO and post-divider output rates are fixed at 408MHz and 204MHz,
+ * respectively.
+ */
+static void pllp_check_defaults(struct tegra_clk_pll *pll, bool enabled)
+{
+ u32 val, mask;
+
+ /* Ignore lock enable (will be set), make sure not in IDDQ if enabled */
+ val = PLLP_MISC0_DEFAULT_VALUE & (~PLLP_MISC0_IDDQ);
+ mask = PLLP_MISC0_LOCK_ENABLE | PLLP_MISC0_LOCK_OVERRIDE;
+ if (!enabled)
+ mask |= PLLP_MISC0_IDDQ;
+ _pll_misc_chk_default(clk_base, pll->params, 0, val,
+ ~mask & PLLP_MISC0_WRITE_MASK);
+
+ /* Ignore branch controls */
+ val = PLLP_MISC1_DEFAULT_VALUE;
+ mask = PLLP_MISC1_HSIO_EN | PLLP_MISC1_XUSB_EN;
+ _pll_misc_chk_default(clk_base, pll->params, 1, val,
+ ~mask & PLLP_MISC1_WRITE_MASK);
+}
+
+void tegra210_pllp_set_defaults(struct tegra_clk_pll *pllp)
+{
+ u32 mask;
+ u32 val = readl_relaxed(clk_base + pllp->params->base_reg);
+
+ pllp->params->defaults_set = true;
+
+ if (val & PLL_ENABLE) {
+ pr_warn("PLL_P already enabled. Postponing set full defaults\n");
+
+ /*
+ * PLL is ON: check if defaults already set, then set those
+ * that can be updated in flight.
+ */
+ pllp_check_defaults(pllp, true);
+
+ /* Enable lock detect */
+ val = readl_relaxed(clk_base + pllp->params->ext_misc_reg[0]);
+ mask = PLLP_MISC0_LOCK_ENABLE | PLLP_MISC0_LOCK_OVERRIDE;
+ val &= ~mask;
+ val |= PLLP_MISC0_DEFAULT_VALUE & mask;
+ writel_relaxed(val, clk_base + pllp->params->ext_misc_reg[0]);
+ udelay(1);
+
+ return;
+ }
+
+ /* set IDDQ, enable lock detect */
+ writel_relaxed(PLLP_MISC0_DEFAULT_VALUE,
+ clk_base + pllp->params->ext_misc_reg[0]);
+
+ /* Preserve branch control */
+ val = readl_relaxed(clk_base + pllp->params->ext_misc_reg[1]);
+ mask = PLLP_MISC1_HSIO_EN | PLLP_MISC1_XUSB_EN;
+ val &= mask;
+ val |= ~mask & PLLP_MISC1_DEFAULT_VALUE;
+ writel_relaxed(val, clk_base + pllp->params->ext_misc_reg[1]);
+ udelay(1);
+}
+
+/*
+ * PLLU
+ * VCO is exposed to the clock tree directly along with post-divider output.
+ * Both VCO and post-divider output rates are fixed at 480MHz and 240MHz,
+ * respectively.
+ */
+static void pllu_check_defaults(struct tegra_clk_pll *pll, bool hw_control)
+{
+ u32 val, mask;
+
+ /* Ignore lock enable (will be set) and IDDQ if under h/w control */
+ val = PLLU_MISC0_DEFAULT_VALUE & (~PLLU_MISC0_IDDQ);
+ mask = PLLU_MISC0_LOCK_ENABLE | (hw_control ? PLLU_MISC0_IDDQ : 0);
+ _pll_misc_chk_default(clk_base, pll->params, 0, val,
+ ~mask & PLLU_MISC0_WRITE_MASK);
+
+ val = PLLU_MISC1_DEFAULT_VALUE;
+ mask = PLLU_MISC1_LOCK_OVERRIDE;
+ _pll_misc_chk_default(clk_base, pll->params, 1, val,
+ ~mask & PLLU_MISC1_WRITE_MASK);
+}
+
+void tegra210_pllu_set_defaults(struct tegra_clk_pll *pllu)
+{
+ u32 val = readl_relaxed(clk_base + pllu->params->base_reg);
+
+ pllu->params->defaults_set = true;
+
+ if (val & PLL_ENABLE) {
+ pr_warn("PLL_U already enabled. Postponing set full defaults\n");
+
+ /*
+ * PLL is ON: check if defaults already set, then set those
+ * that can be updated in flight.
+ */
+ pllu_check_defaults(pllu, false);
+
+ /* Enable lock detect */
+ val = readl_relaxed(clk_base + pllu->params->ext_misc_reg[0]);
+ val &= ~PLLU_MISC0_LOCK_ENABLE;
+ val |= PLLU_MISC0_DEFAULT_VALUE & PLLU_MISC0_LOCK_ENABLE;
+ writel_relaxed(val, clk_base + pllu->params->ext_misc_reg[0]);
+
+ val = readl_relaxed(clk_base + pllu->params->ext_misc_reg[1]);
+ val &= ~PLLU_MISC1_LOCK_OVERRIDE;
+ val |= PLLU_MISC1_DEFAULT_VALUE & PLLU_MISC1_LOCK_OVERRIDE;
+ writel_relaxed(val, clk_base + pllu->params->ext_misc_reg[1]);
+ udelay(1);
+
+ return;
+ }
+
+ /* set IDDQ, enable lock detect */
+ writel_relaxed(PLLU_MISC0_DEFAULT_VALUE,
+ clk_base + pllu->params->ext_misc_reg[0]);
+ writel_relaxed(PLLU_MISC1_DEFAULT_VALUE,
+ clk_base + pllu->params->ext_misc_reg[1]);
+ udelay(1);
+}
+
+#define mask(w) ((1 << (w)) - 1)
+#define divm_mask(p) mask(p->params->div_nmp->divm_width)
+#define divn_mask(p) mask(p->params->div_nmp->divn_width)
+#define divp_mask(p) (p->params->flags & TEGRA_PLLU ? PLLU_POST_DIVP_MASK :\
+ mask(p->params->div_nmp->divp_width))
+
+#define divm_shift(p) ((p)->params->div_nmp->divm_shift)
+#define divn_shift(p) ((p)->params->div_nmp->divn_shift)
+#define divp_shift(p) ((p)->params->div_nmp->divp_shift)
+
+#define divm_mask_shifted(p) (divm_mask(p) << divm_shift(p))
+#define divn_mask_shifted(p) (divn_mask(p) << divn_shift(p))
+#define divp_mask_shifted(p) (divp_mask(p) << divp_shift(p))
+
+#define PLL_LOCKDET_DELAY 2 /* Lock detection safety delays */
+static int tegra210_wait_for_mask(struct tegra_clk_pll *pll,
+ u32 reg, u32 mask)
+{
+ int i;
+ u32 val = 0;
+
+ for (i = 0; i < pll->params->lock_delay / PLL_LOCKDET_DELAY + 1; i++) {
+ udelay(PLL_LOCKDET_DELAY);
+ val = readl_relaxed(clk_base + reg);
+ if ((val & mask) == mask) {
+ udelay(PLL_LOCKDET_DELAY);
+ return 0;
+ }
+ }
+ return -ETIMEDOUT;
+}
+
+static int tegra210_pllx_dyn_ramp(struct tegra_clk_pll *pllx,
+ struct tegra_clk_pll_freq_table *cfg)
+{
+ u32 val, base, ndiv_new_mask;
+
+ ndiv_new_mask = (divn_mask(pl