arm: tegra: Move driver files to drivers/platform
[linux-3.10.git] / drivers / platform / tegra / tegra21_clocks.c
index b85061f..64dd550 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/platform_data/tegra_bpmp.h>
 
 #include <asm/clkdev.h>
+#include <asm/arch_timer.h>
 
 #include <mach/edp.h>
 #include <mach/hardware.h>
 
 #include <tegra/mc.h>
 
-#include "clock.h"
+#include <linux/platform/tegra/clock.h>
 #include "tegra_clocks_ops.h"
-#include "dvfs.h"
+#include <linux/platform/tegra/dvfs.h>
 #include "pm.h"
 #include "sleep.h"
 #include "devices.h"
-#include "tegra_cl_dvfs.h"
-#include "cpu-tegra.h"
+#include <linux/platform/tegra/tegra_cl_dvfs.h>
+#include <linux/platform/tegra/cpu-tegra.h>
 
 /* FIXME: Disable for initial Si bringup */
 #undef USE_PLLE_SS
 #define PLLA_MISC2_EN_SDM              (1 << 26)
 #define PLLA_MISC2_EN_DYNRAMP          (1 << 25)
 
-#define PLLA_MISC0_DEFAULT_VALUE       0x12000000
+#define PLLA_MISC0_DEFAULT_VALUE       0x12000020
 #define PLLA_MISC0_WRITE_MASK          0x7fffffff
 #define PLLA_MISC2_DEFAULT_VALUE       0x0
 #define PLLA_MISC2_WRITE_MASK          0x06ffffff
 
 #define PLLD_MISC0_DEFAULT_VALUE       0x00140000
 #define PLLD_MISC0_WRITE_MASK          0x3ff7ffff
-#define PLLD_MISC1_DEFAULT_VALUE       0x0
+#define PLLD_MISC1_DEFAULT_VALUE       0x20
 #define PLLD_MISC1_WRITE_MASK          0x00ffffff
 
 /* PLLD2 and PLLDP  and PLLC4 */
 #define PLLDSS_MISC1_CFG_EN_SDM                (1 << 31)
 #define PLLDSS_MISC1_CFG_EN_SSC                (1 << 30)
 
-#define PLLD2_MISC0_DEFAULT_VALUE      0x40000000
+#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      0x40000000
+#define PLLDP_MISC0_DEFAULT_VALUE      0x40000020
 #define PLLDP_MISC1_CFG_DEFAULT_VALUE  0xc0000000
-#define PLLDP_MISC2_CTRL1_DEFAULT_VALUE        0xf000e5ec
-#define PLLDP_MISC3_CTRL2_DEFAULT_VALUE        0x101BF000
+#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 PLLX_MISC0_DEFAULT_VALUE       PLLX_MISC0_LOCK_ENABLE
 #define PLLX_MISC0_WRITE_MASK          0x10c40000
-#define PLLX_MISC1_DEFAULT_VALUE       0x0
+#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 PLLE_AUX_CML_SATA_ENABLE       (1<<1)
 #define PLLE_AUX_CML_PCIE_ENABLE       (1<<0)
 
+#define SOURCE_SATA                    0x424
+
 /* USB PLLs PD HW controls */
 #define XUSBIO_PLL_CFG0                                0x51c
 #define XUSBIO_PLL_CFG0_SEQ_START_STATE                (1<<25)
 #define PLLP_DEFAULT_FIXED_RATE                408000000
 
 /* Use PLL_RE as PLLE input (default - OSC via pll reference divider) */
-#define USE_PLLE_INPUT_PLLRE    1
+#define USE_PLLE_INPUT_PLLRE    0
 
 static void pllc4_set_fixed_rates(unsigned long cf);
 static void tegra21_dfll_cpu_late_init(struct clk *c);
@@ -626,7 +629,7 @@ static const struct utmi_clk_param utmi_parameters[] =
 
        {19200000,      0x03,           0x4B,           0x06,           0xBB},
        /* HACK!!! FIXME!!! following entry for 38.4MHz is a stub */
-       {38400000,      0x03,           0x4B,           0x06,           0xBB},
+       {38400000,      0x03,           0x4B,           0x06,           0x80}
 };
 
 static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
@@ -1524,7 +1527,13 @@ static int tegra21_cpu_cmplx_clk_set_parent(struct clk *c, struct clk *p)
         * in advanvce before the switch happens. If target p_source is DFLL it
         * is switched here to open loop mode.
         */
-       tegra_clk_prepare_enable(p);
+       ret = tegra_clk_prepare_enable(p);
+       if (ret) {
+               pr_err("%s: Failed to enable parent clock %s\n",
+                       __func__, p->name);
+               goto abort;
+       }
+
        if (c_source == dfll)
                tegra_dvfs_dfll_mode_clear(c->parent->dvfs, rate);
 
@@ -1733,6 +1742,10 @@ static void sbus_build_round_table_one(struct clk *c, unsigned long rate, int j)
                c, sel.src, flags, rate, false, &sel.div);
        sbus_round_table[j] = sel;
 
+       /* Don't use high frequency source above threshold */
+       if (rate <= c->u.system.threshold)
+               return;
+
        sel.src = c->u.system.sclk_high;
        sel.rate = fixed_src_bus_round_updown(
                c, sel.src, flags, rate, false, &sel.div);
@@ -2226,35 +2239,21 @@ static void tegra21_utmi_param_configure(struct clk *c)
                return;
        }
 
-       reg = clk_readl(UTMIP_PLL_CFG2);
+       reg = clk_readl(UTMIPLL_HW_PWRDN_CFG0);
+       reg &= ~UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE;
+       pll_writel_delay(reg, UTMIPLL_HW_PWRDN_CFG0);
 
+       reg = clk_readl(UTMIP_PLL_CFG2);
        /* Program UTMIP PLL stable and active counts */
        /* [FIXME] arclk_rst.h says WRONG! This should be 1ms -> 0x50 Check! */
        reg &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0);
        reg |= UTMIP_PLL_CFG2_STABLE_COUNT(
                        utmi_parameters[i].stable_count);
-
-       reg &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0);
-
-       reg |= UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(
-                       utmi_parameters[i].active_delay_count);
-
-       /* Remove power downs from UTMIP PLL control bits */
-       reg |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERUP;
-       reg |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERUP;
-       reg |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERUP;
-       reg |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERUP;
-       reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN;
-       reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN;
-       reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN;
-       reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERDOWN;
-
        clk_writel(reg, UTMIP_PLL_CFG2);
 
        /* Program UTMIP PLL delay and oscillator frequency counts */
        reg = clk_readl(UTMIP_PLL_CFG1);
        reg &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0);
-
        reg |= UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(
                utmi_parameters[i].enable_delay_count);
 
@@ -2263,29 +2262,34 @@ static void tegra21_utmi_param_configure(struct clk *c)
                utmi_parameters[i].xtal_freq_count);
 
        /* Remove power downs from UTMIP PLL control bits */
-       reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
-       reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN;
-       reg &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERUP;
-       reg &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN;
+       reg |= UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN;
        clk_writel(reg, UTMIP_PLL_CFG1);
 
-       /* Setup HW control of UTMIPLL */
-       reg = clk_readl(UTMIPLL_HW_PWRDN_CFG0);
-       reg |= UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET;
-       reg &= ~UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL;
-       reg |= UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE;
-       clk_writel(reg, UTMIPLL_HW_PWRDN_CFG0);
+       /* Enable PLL with SW programming */
+       reg = clk_readl(UTMIP_PLL_CFG1);
+       reg |= UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP;
+       reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
+       pll_writel_delay(reg, UTMIP_PLL_CFG1);
+
+       /* Enable Samplers for SNPS IP, XUSB_HOST, XUSB_DEV */
+       reg = clk_readl(UTMIP_PLL_CFG2);
+       reg |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERUP;
+       reg |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERUP;
+       reg |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERUP;
+       reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN;
+       reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN;
+       reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERDOWN;
+       clk_writel(reg, UTMIP_PLL_CFG2);
 
+       /* Enable HW Power Sequencer */
        reg = clk_readl(UTMIP_PLL_CFG1);
        reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP;
        reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
-       pll_writel_delay(reg, UTMIP_PLL_CFG1);
+       clk_writel(reg, UTMIP_PLL_CFG1);
 
-       /* Setup SW override of UTMIPLL assuming USB2.0
-          ports are assigned to USB2 */
        reg = clk_readl(UTMIPLL_HW_PWRDN_CFG0);
-       reg |= UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL;
-       reg |= UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE;
+       reg &= ~UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL;
+       reg |= UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET;
        pll_writel_delay(reg, UTMIPLL_HW_PWRDN_CFG0);
 
        /* Enable HW control UTMIPLL */
@@ -3456,17 +3460,27 @@ static struct clk_ops tegra_pllmb_ops = {
  * PLLE
  * Analog interpolator based SS PLL (with optional SDM SS - not used).
  */
-static inline void select_pll_e_input(struct clk *c)
+static void select_pll_e_input(struct clk *c)
 {
+       struct clk *p;
        u32 aux_reg = clk_readl(PLLE_AUX);
+
 #if USE_PLLE_INPUT_PLLRE
        aux_reg |= PLLE_AUX_PLLRE_SEL;
-       c->parent = c->inputs[2].input;
+       p = c->inputs[2].input;
 #else
        aux_reg &= ~(PLLE_AUX_PLLRE_SEL | PLLE_AUX_PLLP_SEL);
-       c->parent = c->inputs[0].input;
+       p = c->inputs[0].input;
 #endif
+       if (p != c->parent)
+               clk_prepare_enable(p);
+
        pll_writel_delay(aux_reg, PLLE_AUX);
+
+       if (p != c->parent) {
+               tegra_clk_disable_unprepare(c->parent);
+               clk_reparent(c, p);
+       }
 }
 
 static void tegra21_plle_clk_init(struct clk *c)
@@ -4798,6 +4812,76 @@ static struct clk_ops tegra_dsi_clk_ops = {
        .reset                  = &tegra21_periph_clk_reset,
 };
 
+static void tegra21_dpaux_clk_init(struct clk *c)
+{
+       c->mul = 1;
+       c->div = 17;;
+       tegra21_periph_clk_init(c);
+}
+
+static struct clk_ops tegra_dpaux_clk_ops = {
+       .init                   = &tegra21_dpaux_clk_init,
+       .enable                 = &tegra21_periph_clk_enable,
+       .disable                = &tegra21_periph_clk_disable,
+       .set_parent             = &tegra21_periph_clk_set_parent,
+       .set_rate               = &tegra21_periph_clk_set_rate,
+       .reset                  = &tegra21_periph_clk_reset,
+};
+
+/* XUSB SS clock ops */
+static DEFINE_SPINLOCK(xusb_ss_lock);
+
+static int tegra21_xusb_ss_set_rate(struct clk *c, unsigned long rate)
+{
+       int ret;
+       unsigned long flags;
+
+       spin_lock_irqsave(&xusb_ss_lock, flags);
+       ret = tegra21_periph_clk_set_rate(c, rate);
+       spin_unlock_irqrestore(&xusb_ss_lock, flags);
+       return ret;
+}
+
+static int tegra21_xusb_ss_set_parent(struct clk *c, struct clk *p)
+{
+       u32 val;
+       unsigned long flags;
+       const struct clk_mux_sel *sel;
+       pr_debug("%s: %s %s\n", __func__, c->name, p->name);
+
+       for (sel = c->inputs; sel->input != NULL; sel++) {
+               if (sel->input == p) {
+                       if (c->refcnt)
+                               tegra_clk_prepare_enable(p);
+
+                       spin_lock_irqsave(&xusb_ss_lock, flags);
+                       val = clk_readl(c->reg);
+                       val &= ~periph_clk_source_mask(c);
+                       val |= (sel->value << periph_clk_source_shift(c));
+                       clk_writel_delay(val, c->reg);
+                       spin_unlock_irqrestore(&xusb_ss_lock, flags);
+
+                       if (c->refcnt && c->parent)
+                               tegra_clk_disable_unprepare(c->parent);
+
+                       clk_reparent(c, p);
+                       return 0;
+               }
+       }
+
+       return -EINVAL;
+}
+
+static struct clk_ops tegra_xusb_ss_ops = {
+       .init                   = &tegra21_periph_clk_init,
+       .enable                 = &tegra21_periph_clk_enable,
+       .disable                = &tegra21_periph_clk_disable,
+       .set_parent             = &tegra21_xusb_ss_set_parent,
+       .set_rate               = &tegra21_xusb_ss_set_rate,
+       .round_rate             = &tegra21_periph_clk_round_rate,
+       .reset                  = &tegra21_periph_clk_reset,
+};
+
 /* pciex clock support only reset function */
 static void tegra21_pciex_clk_init(struct clk *c)
 {
@@ -4844,8 +4928,171 @@ static struct clk_ops tegra_pciex_clk_ops = {
        .reset    = tegra21_periph_clk_reset,
 };
 
-/* Output clock ops */
 
+/* SDMMC2 and SDMMC4 ops */
+static u32 sdmmc24_input_to_lj[] = {
+       /* 0, 1, 2, 3, 4, 5, 6, 7 */
+          0, 1, 2, 1, 5, 5, 6, 2
+};
+
+static u32 sdmmc24_input_from_lj[] = {
+       /* 0, 1, 2, 3, 4, 5, 6, 7 */
+          0, 3, 7, 3, 4, 4, 6, 7
+};
+
+/*
+ * The same PLLC4 output branches connected to the low jitter (LJ) and divided
+ * inputs of the SDMMC2/4 source selection mux. The difference is that clock
+ * from LJ input does not go through SDMMC2/4 divider. Although it is possible
+ * to run output clock at the same rate as source from divided input (with
+ * divider 1:1 setting), the implementation below automatically switches to LJ
+ * input when SDMMC2/4 clock rate is set equal to the source rate, and one of
+ * PLLC4 branches is used as a source. Changing SDMMC rate-to-source ratio
+ * from 1:1 automatically selects divided input. This switching mechanism has
+ * no effect when PLLP or CLK_M is used as clock source.
+ *
+ * See also mux_pllp_clk_m_pllc4_out2_out1_out0_lj definition for detailed list
+ * of LJ and divided inputs.
+*/
+
+static void sdmmc24_remap_inputs(struct clk *c)
+{
+       u32 sel_out, sel_in;
+       u32 val = clk_readl(c->reg);
+
+       sel_in = (val & periph_clk_source_mask(c)) >>
+               periph_clk_source_shift(c);
+
+       sel_out = (c->mul == c->div) ? sdmmc24_input_to_lj[sel_in] :
+               sdmmc24_input_from_lj[sel_in];
+
+       if (sel_out != sel_in) {
+               val &= ~periph_clk_source_mask(c);
+               val |= (sel_out << periph_clk_source_shift(c));
+
+               clk_writel_delay(val, c->reg);
+       }
+
+}
+
+static void tegra21_sdmmc24_clk_init(struct clk *c)
+{
+       tegra21_periph_clk_init(c);
+       sdmmc24_remap_inputs(c);
+}
+
+static int tegra21_sdmmc24_clk_set_rate(struct clk *c, unsigned long rate)
+{
+       int ret = tegra21_periph_clk_set_rate(c, rate);
+       if (!ret)
+               sdmmc24_remap_inputs(c);
+       return ret;
+}
+
+static int tegra21_sdmmc24_clk_set_parent(struct clk *c, struct clk *p)
+{
+       u32 val, sel_val;
+       const struct clk_mux_sel *sel;
+       pr_debug("%s: %s %s\n", __func__, c->name, p->name);
+
+       for (sel = c->inputs; sel->input != NULL; sel++) {
+               if (sel->input == p) {
+                       sel_val = (c->mul == c->div) ?
+                               sdmmc24_input_to_lj[sel->value] :
+                               sdmmc24_input_from_lj[sel->value];
+
+                       val = clk_readl(c->reg);
+                       val &= ~periph_clk_source_mask(c);
+                       val |= (sel_val << periph_clk_source_shift(c));
+
+                       if (c->refcnt)
+                               tegra_clk_prepare_enable(p);
+
+                       clk_writel_delay(val, c->reg);
+
+                       if (c->refcnt && c->parent)
+                               tegra_clk_disable_unprepare(c->parent);
+
+                       clk_reparent(c, p);
+                       return 0;
+               }
+       }
+       return -EINVAL;
+}
+
+static struct clk_ops tegra_sdmmc24_clk_ops = {
+       .init                   = &tegra21_sdmmc24_clk_init,
+       .enable                 = &tegra21_periph_clk_enable,
+       .disable                = &tegra21_periph_clk_disable,
+       .set_parent             = &tegra21_sdmmc24_clk_set_parent,
+       .set_rate               = &tegra21_sdmmc24_clk_set_rate,
+       .round_rate             = &tegra21_periph_clk_round_rate,
+       .reset                  = &tegra21_periph_clk_reset,
+};
+
+/* SLCG clock ops */
+static DEFINE_SPINLOCK(clk_slcg_lock);
+
+static void tegra21_clk_slcg_init(struct clk *c)
+{
+       char *end;
+       char root_name[32];
+       u32 val = clk_readl(c->reg);
+
+       c->state = (val & (0x1 << c->u.periph.clk_num)) ? ON : OFF;
+
+       strcpy(root_name, c->name);
+       end = strstr(root_name, "_slcg_ovr");
+       if (end) {
+               *end = '\0';
+               c->parent = tegra_get_clock_by_name(root_name);
+       }
+
+       if (WARN(!c->parent, "%s: %s parent %s not found\n",
+                __func__, c->name, root_name))
+               return;
+
+       c->max_rate = c->parent->max_rate;
+}
+
+
+static int tegra21_clk_slcg_enable(struct clk *c)
+{
+       u32 val;
+       unsigned long flags;
+
+       pr_debug("%s on clock %s\n", __func__, c->name);
+
+       spin_lock_irqsave(&clk_slcg_lock, flags);
+       val = clk_readl(c->reg);
+       val |= (0x1 << c->u.periph.clk_num);
+       clk_writel_delay(val, c->reg);
+       spin_unlock_irqrestore(&clk_slcg_lock, flags);
+
+       return 0;
+}
+
+static void tegra21_clk_slcg_disable(struct clk *c)
+{
+       u32 val;
+       unsigned long flags;
+
+       pr_debug("%s on clock %s\n", __func__, c->name);
+
+       spin_lock_irqsave(&clk_slcg_lock, flags);
+       val = clk_readl(c->reg);
+       val &= ~(0x1 << c->u.periph.clk_num);
+       clk_writel_delay(val, c->reg);
+       spin_unlock_irqrestore(&clk_slcg_lock, flags);
+}
+
+static struct clk_ops tegra_clk_slcg_ops = {
+       .init                   = &tegra21_clk_slcg_init,
+       .enable                 = &tegra21_clk_slcg_enable,
+       .disable                = &tegra21_clk_slcg_disable,
+};
+
+/* Output clock ops */
 static DEFINE_SPINLOCK(clk_out_lock);
 
 static void tegra21_clk_out_init(struct clk *c)
@@ -5053,6 +5300,22 @@ static struct clk_ops tegra_mc_clk_ops = {
        .disable                = &tegra21_periph_clk_disable,
 };
 
+#ifdef CONFIG_PM_SLEEP
+static void tegra21_emc_clk_suspend(struct clk *c, unsigned long rate)
+{
+       /* No change in emc configuration for LP1 */
+       if (!tegra_is_lp0_suspend_mode())
+               return;
+
+       /*
+        * Scale EMC rate at/below boot rate - required for entering SC7(LP0)
+        * on LPDDR4, but applied to LPDDR3 as well.
+        * FIXME: keep it general or check for LPDDR4 below?
+        */
+       if (rate > c->boot_rate)
+               tegra21_emc_clk_set_rate(c, c->boot_rate);
+}
+#endif
 
 /* Clock doubler ops (non-atomic shared register access) */
 static DEFINE_SPINLOCK(doubler_lock);
@@ -5180,17 +5443,30 @@ static void tegra21_cml_clk_init(struct clk *c)
 
 static int tegra21_cml_clk_enable(struct clk *c)
 {
-       u32 val = clk_readl(c->reg);
+       u32 val;
+       unsigned long flags;
+       struct clk *parent = c->parent;
+
+       clk_lock_save(parent, &flags);
+       val = clk_readl(c->reg);
        val |= (0x1 << c->u.periph.clk_num);
        clk_writel(val, c->reg);
+       clk_unlock_restore(parent, &flags);
+
        return 0;
 }
 
 static void tegra21_cml_clk_disable(struct clk *c)
 {
-       u32 val = clk_readl(c->reg);
+       u32 val;
+       unsigned long flags;
+       struct clk *parent = c->parent;
+
+       clk_lock_save(parent, &flags);
+       val = clk_readl(c->reg);
        val &= ~(0x1 << c->u.periph.clk_num);
        clk_writel(val, c->reg);
+       clk_unlock_restore(parent, &flags);
 }
 
 static struct clk_ops tegra_cml_clk_ops = {
@@ -5199,7 +5475,6 @@ static struct clk_ops tegra_cml_clk_ops = {
        .disable                = &tegra21_cml_clk_disable,
 };
 
-
 /* cbus ops */
 /*
  * Some clocks require dynamic re-locking of source PLL in order to
@@ -6330,7 +6605,7 @@ static struct clk tegra_pll_a_out0 = {
        .parent    = &tegra_pll_a,
        .reg       = 0xb4,
        .reg_shift = 0,
-       .max_rate  = 100000000,
+       .max_rate  = 600000000,
 };
 
 static struct clk_pll_freq_table tegra_pll_d_freq_table[] = {
@@ -6464,7 +6739,7 @@ static struct clk tegra_pll_d2 = {
 static struct clk_pll_freq_table tegra_pll_dp_freq_table[] = {
        { 12000000, 270000000,  90, 1, 4},
        { 13000000, 270000000,  83, 1, 4},      /* actual: 269.8 MHz */
-       { 38400000, 270000000,  84, 3, 4},      /* actual: 268.8 MHz */
+       { 38400000, 270000000,  28, 1, 4},      /* actual: 268.8 MHz */
        { 0, 0, 0, 0, 0, 0 },
 };
 
@@ -6725,9 +7000,19 @@ static struct clk tegra_pll_x = {
 };
 
 static struct clk_pll_freq_table tegra_pll_m_freq_table[] = {
-       { 12000000, 800000000, 66, 1, 1},       /* actual: 792.0 MHz */
-       { 13000000, 800000000, 61, 1, 1},       /* actual: 793.0 MHz */
-       { 38400000, 800000000, 83, 4, 1},       /* actual: 796.8 MHz */
+       { 12000000,  800000000,  66, 1, 1},     /* actual: 792.0 MHz */
+       { 13000000,  800000000,  61, 1, 1},     /* actual: 793.0 MHz */
+       { 38400000,  297600000,  93, 4, 3},
+       { 38400000,  400000000, 125, 4, 3},
+       { 38400000,  532800000, 111, 4, 2},
+       { 38400000,  665600000, 104, 3, 2},
+       { 38400000,  800000000, 125, 3, 2},
+       { 38400000,  931200000,  97, 4, 1},
+       { 38400000, 1065600000, 111, 4, 1},
+       { 38400000, 1200000000, 125, 4, 1},
+       { 38400000, 1331200000, 104, 3, 1},
+       { 38400000, 1459200000,  76, 2, 1},
+       { 38400000, 1600000000, 125, 3, 1},
        { 0, 0, 0, 0, 0, 0 },
 };
 
@@ -6969,7 +7254,7 @@ struct clk_pll_controls pllu_controls = {
 };
 
 static struct clk tegra_pll_u_vco = {
-       .name      = "pll_u_vco",
+       .name      = "pll_u",
        .flags     = PLLU | PLL_FIXED,
        .ops       = &tegra_pllu_vco_ops,
        .reg       = 0xc0,
@@ -7234,18 +7519,13 @@ static struct clk tegra_clk_audio_list[] = {
                },                                              \
        }
 static struct clk tegra_clk_audio_2x_list[] = {
-       AUDIO_SYNC_2X_CLK(audio0, tegra210-i2s.0, 0),
-       AUDIO_SYNC_2X_CLK(audio1, tegra210-i2s.1, 1),
-       AUDIO_SYNC_2X_CLK(audio2, tegra210-i2s.2, 2),
-       AUDIO_SYNC_2X_CLK(audio3, tegra210-i2s.3, 3),
-       AUDIO_SYNC_2X_CLK(audio4, tegra210-i2s.4, 4),
        AUDIO_SYNC_2X_CLK(audio, tegra210-spdif, 5),    /* SPDIF */
 };
 
 #define MUX_I2S_SPDIF(_id, _index)                                     \
-static struct clk_mux_sel mux_pllaout0_##_id##_2x_pllp_clkm[] = {      \
+static struct clk_mux_sel mux_pllaout0_##_id##_pllp_clkm[] = {         \
        {.input = &tegra_pll_a_out0, .value = 0},                       \
-       {.input = &tegra_clk_audio_2x_list[(_index)], .value = 2},      \
+       {.input = &tegra_clk_audio_list[(_index)], .value = 2},         \
        {.input = &tegra_pll_p, .value = 4},                            \
        {.input = &tegra_clk_m, .value = 6},                            \
        { 0, 0},                                                        \
@@ -7255,7 +7535,15 @@ MUX_I2S_SPDIF(audio1, 1);
 MUX_I2S_SPDIF(audio2, 2);
 MUX_I2S_SPDIF(audio3, 3);
 MUX_I2S_SPDIF(audio4, 4);
-MUX_I2S_SPDIF(audio, 5);               /* SPDIF */
+
+/* SPDIF */
+static struct clk_mux_sel mux_pllaout0_audio_2x_pllp_clkm[] = {
+       {.input = &tegra_pll_a_out0, .value = 0},
+       {.input = &tegra_clk_audio_2x_list[0], .value = 2},
+       {.input = &tegra_pll_p, .value = 4},
+       {.input = &tegra_clk_m, .value = 6},
+       { 0, 0},
+};
 
 /* Audio sync dmic clocks */
 #define AUDIO_SYNC_DMIC_CLK(_id, _dev, _reg)           \
@@ -7280,7 +7568,7 @@ static struct clk tegra_clk_audio_dmic_list[] = {
 #define MUX_AUDIO_DMIC(_id, _index)                                    \
 static struct clk_mux_sel mux_pllaout0_##_id##_dmic_pllp_clkm[] = {    \
        {.input = &tegra_pll_a_out0, .value = 0},                       \
-       {.input = &tegra_clk_audio_2x_list[(_index)], .value = 1},      \
+       {.input = &tegra_clk_audio_list[(_index)], .value = 1},         \
        {.input = &tegra_pll_p, .value = 2},                            \
        {.input = &tegra_clk_m, .value = 3},                            \
        { 0, 0},                                                        \
@@ -7394,9 +7682,12 @@ static void tegra21_adsp_clk_reset(struct clk *c, bool assert)
 {
        unsigned long reg = assert ? RST_DEVICES_SET_Y : RST_DEVICES_CLR_Y;
        u32 val = ADSP_NEON | ADSP_SCU | ADSP_WDT | ADSP_DBG
-               | ADSP_PERIPH | ADSP_INTF | ADSP_CORE;
+               | ADSP_PERIPH | ADSP_CORE;
 
        pr_debug("%s %s\n", __func__, assert ? "assert" : "deassert");
+
+       clk_writel_delay(ADSP_INTF, reg);
+       udelay(50);
        clk_writel_delay(val, reg);
 }
 
@@ -7691,12 +7982,11 @@ static struct clk_mux_sel mux_pllc_pllp_plla[] = {
        { 0, 0},
 };
 
-static struct clk_mux_sel mux_pllc_pllp_plla_pllc4[] = {
+static struct clk_mux_sel mux_clkm_pllc_pllp_plla[] = {
+       { .input = &tegra_clk_m, .value = 0},
        { .input = &tegra_pll_c, .value = 1},
        { .input = &tegra_pll_p, .value = 2},
        { .input = &tegra_pll_a_out0, .value = 3},
-       /* Skip C2(4) */
-       { .input = &tegra_pll_c4_out0, .value = 5},
        { 0, 0},
 };
 
@@ -7710,11 +8000,12 @@ static struct clk_mux_sel mux_pllc_pllp_plla1_pllc2_c3_clkm[] = {
        { 0, 0},
 };
 
-static struct clk_mux_sel mux_pllc2_c_c3_pllp_plla1_pllc4[] = {
+static struct clk_mux_sel mux_pllc2_c_c3_pllp_clkm_plla1_pllc4[] = {
        { .input = &tegra_pll_c2, .value = 1},
        { .input = &tegra_pll_c, .value = 2},
        { .input = &tegra_pll_c3, .value = 3},
        { .input = &tegra_pll_p, .value = 4},
+       { .input = &tegra_clk_m, .value = 5},
        { .input = &tegra_pll_a1, .value = 6},
        { .input = &tegra_pll_c4_out0, .value = 7},
        { 0, 0},
@@ -7857,8 +8148,9 @@ static struct clk_mux_sel mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2[]
        { 0, 0},
 };
 
-static struct clk_mux_sel mux_pllp_pllc_pllc4_out2_pllc4_out1_clkm_pllc4_out0[] = {
+static struct clk_mux_sel mux_pllp_pllc_pllc_out1_pllc4_out2_pllc4_out1_clkm_pllc4_out0[] = {
        {.input = &tegra_pll_p,             .value = 0},
+       {.input = &tegra_pll_c_out1,        .value = 1},
        {.input = &tegra_pll_c,             .value = 2},
        {.input = &tegra_pll_c4_out2,       .value = 4},
        {.input = &tegra_pll_c4_out1,       .value = 5},
@@ -7876,6 +8168,18 @@ static struct clk_mux_sel mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0[] = {
        { 0, 0},
 };
 
+static struct clk_mux_sel mux_pllp_clk_m_pllc4_out2_out1_out0_lj[] = {
+       {.input = &tegra_pll_p,             .value = 0},
+       {.input = &tegra_pll_c4_out2,       .value = 1},  /* LJ input */
+       {.input = &tegra_pll_c4_out0,       .value = 2},  /* LJ input */
+       {.input = &tegra_pll_c4_out2,       .value = 3},
+       {.input = &tegra_pll_c4_out1,       .value = 4},
+       {.input = &tegra_pll_c4_out1,       .value = 5},  /* LJ input */
+       {.input = &tegra_clk_m,             .value = 6},
+       {.input = &tegra_pll_c4_out0,       .value = 7},
+       { 0, 0},
+};
+
 static struct clk_mux_sel mux_pllp_pllc2_c_c3_clkm[] = {
        { .input = &tegra_pll_p,  .value = 0},
        { .input = &tegra_pll_c2, .value = 1},
@@ -7885,9 +8189,10 @@ static struct clk_mux_sel mux_pllp_pllc2_c_c3_clkm[] = {
        { 0, 0},
 };
 
-static struct clk_mux_sel mux_pllp_pllc[] = {
+static struct clk_mux_sel mux_pllp_pllc_clkm_1[] = {
        {.input = &tegra_pll_p,     .value = 0},
-       {.input = &tegra_pll_c,     .value = 1},
+       {.input = &tegra_pll_c,     .value = 2},
+       {.input = &tegra_clk_m,     .value = 5},
        { 0, 0},
 };
 
@@ -7897,9 +8202,11 @@ static struct clk_mux_sel mux_pllp_clkm_2[] = {
        { 0, 0},
 };
 
-static struct clk_mux_sel mux_pllp_clkm_1[] = {
+static struct clk_mux_sel mux_pllp_clkm_clk32_plle[] = {
        { .input = &tegra_pll_p, .value = 0},
        { .input = &tegra_clk_m, .value = 2},
+       { .input = &tegra_clk_32k, .value = 4},
+       { .input = &tegra_pll_e, .value = 6},
        { 0, 0},
 };
 
@@ -8020,6 +8327,32 @@ static struct clk_mux_sel mux_plld[] = {
 
 static struct raw_notifier_head emc_rate_change_nh;
 
+static struct clk tegra_clk_sata = {
+       .name      = "sata",
+       .lookup    = {
+               .dev_id = "tegra_sata",
+       },
+       .ops       = &tegra_periph_clk_ops,
+       .reg       = SOURCE_SATA,
+       .max_rate  = 216000000,
+       .u.periph  = {
+               .clk_num = 124,
+       },
+       .inputs    = mux_pllp_pllc_clkm,
+       .flags     = MUX | DIV_U71 | PERIPH_ON_APB,
+};
+
+static struct clk tegra_sata_aux_clk = {
+       .name      = "sata_aux",
+       .parent    = &tegra_clk_sata,
+       .ops       = &tegra_cml_clk_ops,
+       .reg       = SOURCE_SATA,
+       .max_rate  = 216000000,
+       .u.periph  = {
+               .clk_num = 24,
+       },
+};
+
 static struct clk tegra_clk_emc = {
        .name = "emc",
        .ops = &tegra_emc_clk_ops,
@@ -8320,6 +8653,12 @@ static void tegra21_camera_mclk_init(struct clk *c)
        } else if (!strcmp(c->name, "mclk2")) {
                c->parent = tegra_get_clock_by_name("vi_sensor2");
                c->max_rate = c->parent->max_rate;
+       } else if (!strcmp(c->name, "mclk3")) {
+               c->parent = tegra_get_clock_by_name("extern3");
+               c->max_rate = c->parent->max_rate;
+       } else if (!strcmp(c->name, "cam-mipi-cal")) {
+               c->parent = tegra_get_clock_by_name("uart_mipi_cal");
+               c->max_rate = c->parent->max_rate;
        }
 }
 
@@ -8353,6 +8692,32 @@ static struct clk tegra_camera_mclk2 = {
        .flags = PERIPH_NO_RESET,
 };
 
+static struct clk tegra_camera_mipical = {
+       .name = "cam-mipi-cal",
+       .ops = &tegra_camera_mclk_ops,
+       .u.periph = {
+               .clk_num = 56, /* mipi_cal */
+       },
+       .flags = PERIPH_NO_RESET,
+};
+
+static struct clk_ops tegra_camera_mclk3_ops = {
+       .init           = &tegra21_camera_mclk_init,
+       .enable         = &tegra21_clk_out_enable,
+       .disable        = &tegra21_clk_out_disable,
+       .set_rate       = &tegra21_camera_mclk_set_rate,
+};
+
+static struct clk tegra_camera_mclk3 = {
+       .name = "mclk3",
+       .ops = &tegra_camera_mclk3_ops,
+       .reg = 0x1a8,
+       .flags = MUX_CLK_OUT,
+       .u.periph = {
+               .clk_num   = (3 - 1) * 8 + 2,
+       },
+};
+
 static struct clk tegra_clk_isp = {
        .name = "isp",
        .ops = &tegra_periph_clk_ops,
@@ -8548,41 +8913,40 @@ struct clk tegra_list_clks[] = {
        PERIPH_CLK("fuse_burn", "fuse-tegra",    "fuse_burn",   39,     0,      38400000,  mux_clk_m,                   PERIPH_ON_APB),
 
        PERIPH_CLK("apbif",     "tegra210-admaif",      NULL,   107,    0,      38400000,  mux_clk_m,                   PERIPH_NO_RESET | PERIPH_ON_APB),
-       PERIPH_CLK("i2s0",      "tegra210-i2s.0",       NULL,   30,     0x1d8,  204000000,  mux_pllaout0_audio0_2x_pllp_clkm,   MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
-       PERIPH_CLK("i2s1",      "tegra210-i2s.1",       NULL,   11,     0x100,  204000000,  mux_pllaout0_audio1_2x_pllp_clkm,   MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
-       PERIPH_CLK("i2s2",      "tegra210-i2s.2",       NULL,   18,     0x104,  204000000,  mux_pllaout0_audio2_2x_pllp_clkm,   MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
-       PERIPH_CLK("i2s3",      "tegra210-i2s.3",       NULL,   101,    0x3bc,  204000000,  mux_pllaout0_audio3_2x_pllp_clkm,   MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
-       PERIPH_CLK("i2s4",      "tegra210-i2s.4",       NULL,   102,    0x3c0,  204000000,  mux_pllaout0_audio4_2x_pllp_clkm,   MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
+       PERIPH_CLK("i2s0",      "tegra210-i2s.0",       NULL,   30,     0x1d8,  204000000,  mux_pllaout0_audio0_pllp_clkm,      MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
+       PERIPH_CLK("i2s1",      "tegra210-i2s.1",       NULL,   11,     0x100,  204000000,  mux_pllaout0_audio1_pllp_clkm,      MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
+       PERIPH_CLK("i2s2",      "tegra210-i2s.2",       NULL,   18,     0x104,  204000000,  mux_pllaout0_audio2_pllp_clkm,      MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
+       PERIPH_CLK("i2s3",      "tegra210-i2s.3",       NULL,   101,    0x3bc,  204000000,  mux_pllaout0_audio3_pllp_clkm,      MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
+       PERIPH_CLK("i2s4",      "tegra210-i2s.4",       NULL,   102,    0x3c0,  204000000,  mux_pllaout0_audio4_pllp_clkm,      MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
        PERIPH_CLK("spdif_out", "tegra210-spdif", "spdif_out",  10,     0x108,   49152000, mux_pllaout0_audio_2x_pllp_clkm,     MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
-       PERIPH_CLK("spdif_in",  "tegra210-spdif",  "spdif_in",  10,     0x10c,  408000000, mux_pllp_pllc,                       MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
+       PERIPH_CLK("spdif_in",  "tegra210-spdif",  "spdif_in",  10,     0x10c,  408000000, mux_pllp_pllc_clkm_1,                MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
        PERIPH_CLK("dmic1",     "tegra210-dmic.0",      NULL,   161,    0x64c,  24576000, mux_pllaout0_audio0_dmic_pllp_clkm,   MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
        PERIPH_CLK("dmic2",     "tegra210-dmic.1",      NULL,   162,    0x650,  24576000, mux_pllaout0_audio1_dmic_pllp_clkm,   MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
        PERIPH_CLK("dmic3",     "tegra210-dmic.2",      NULL,   197,    0x6bc,  24576000, mux_pllaout0_audio2_dmic_pllp_clkm,   MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
        PERIPH_CLK("ape",       NULL,                   "ape",  198,    0x6c0,  300000000, mux_plla_pllc4_out0_pllc_pllc4_out1_pllp_clkm_pllc4_out2, MUX | DIV_U71 | PERIPH_ON_APB),
        PERIPH_CLK("maud",      "maud",                 NULL,   202,    0x6d4,  300000000, mux_pllp_pllp_out3_clkm_clk32k_plla, MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
-       PERIPH_CLK("pwm",       "pwm",                  NULL,   17,     0x110,  48000000, mux_pllp_pllc_clk32_clkm,             MUX | DIV_U71 | PERIPH_ON_APB),
+       PERIPH_CLK("pwm",       "tegra-pwm",                    NULL,   17,     0x110,  48000000, mux_pllp_pllc_clk32_clkm,             MUX | DIV_U71 | PERIPH_ON_APB),
        D_AUDIO_CLK("d_audio",  "tegra210-axbar",       "ahub", 106,    0x3d0,  102000000,  mux_d_audio_clk,                    MUX | DIV_U71 | PERIPH_ON_APB),
        PERIPH_CLK("hda",       "tegra30-hda",          "hda",  125,    0x428,  102000000, mux_pllp_pllc_clkm,                  MUX | DIV_U71 | PERIPH_ON_APB),
        PERIPH_CLK("hda2codec_2x", "tegra30-hda", "hda2codec",  111,    0x3e4,  102000000,  mux_pllp_pllc_plla_clkm,            MUX | DIV_U71 | PERIPH_ON_APB),
        PERIPH_CLK("hda2hdmi",  "tegra30-hda",     "hda2hdmi",  128,    0,      408000000,  mux_clk_m,                          PERIPH_ON_APB),
 
-       PERIPH_CLK("qspi",      "qspi",                 NULL,   211,    0x6c4, 166000000, mux_pllp_pllc_pllc4_out2_pllc4_out1_clkm_pllc4_out0, MUX | DIV_U71 | PERIPH_ON_APB),
-       PERIPH_CLK("vi_i2c",    "vi_i2c",               NULL,   208,    0x6c8, 136000000, mux_pllp_pllc_clkm,   MUX | DIV_U151 | PERIPH_ON_APB),
+       PERIPH_CLK("qspi",      "qspi",                 NULL,   211,    0x6c4, 166000000, mux_pllp_pllc_pllc_out1_pllc4_out2_pllc4_out1_clkm_pllc4_out0, MUX | DIV_U71 | PERIPH_ON_APB),
+       PERIPH_CLK("vii2c",     "vii2c",                NULL,   208,    0x6c8, 136000000, mux_pllp_pllc_clkm,   MUX | DIV_U16 | PERIPH_ON_APB),
        PERIPH_CLK("sbc1",      "spi-tegra114.0",       NULL,   41,     0x134,  51000000, mux_pllp_pllc_clkm,   MUX | DIV_U71 | PERIPH_ON_APB),
        PERIPH_CLK("sbc2",      "spi-tegra114.1",       NULL,   44,     0x118,  51000000, mux_pllp_pllc_clkm,   MUX | DIV_U71 | PERIPH_ON_APB),
        PERIPH_CLK("sbc3",      "spi-tegra114.2",       NULL,   46,     0x11c,  51000000, mux_pllp_pllc_clkm,   MUX | DIV_U71 | PERIPH_ON_APB),
        PERIPH_CLK("sbc4",      "spi-tegra114.3",       NULL,   68,     0x1b4,  51000000, mux_pllp_pllc_clkm,   MUX | DIV_U71 | PERIPH_ON_APB),
        PERIPH_CLK("sata_oob",  "tegra_sata_oob",       NULL,   123,    0x420,  216000000, mux_pllp_pllc_clkm,  MUX | DIV_U71 | PERIPH_ON_APB),
-       PERIPH_CLK("sata",      "tegra_sata",           NULL,   124,    0x424,  216000000, mux_pllp_pllc_clkm,  MUX | DIV_U71 | PERIPH_ON_APB),
        PERIPH_CLK("sata_cold", "tegra_sata_cold",      NULL,   129,    0,      48000000,  mux_clk_m,           PERIPH_ON_APB),
-       PERIPH_CLK("sdmmc1",    "sdhci-tegra.0",        NULL,   14,     0x150,  208000000, mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0,              MUX | DIV_U71 | PERIPH_ON_APB),
-       PERIPH_CLK("sdmmc2",    "sdhci-tegra.1",        NULL,   9,      0x154,  333000000, mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0,              MUX | DIV_U71 | PERIPH_ON_APB),
-       PERIPH_CLK("sdmmc3",    "sdhci-tegra.2",        NULL,   69,     0x1bc,  208000000, mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0,              MUX | DIV_U71 | PERIPH_ON_APB),
-       PERIPH_CLK("sdmmc4",    "sdhci-tegra.3",        NULL,   15,     0x164,  333000000, mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0,              MUX | DIV_U71 | PERIPH_ON_APB),
+       PERIPH_CLK("sdmmc1",    "sdhci-tegra.0",        NULL,   14,     0x150,  208000000, mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0,      MUX | DIV_U71 | PERIPH_ON_APB),
+       PERIPH_CLK("sdmmc3",    "sdhci-tegra.2",        NULL,   69,     0x1bc,  208000000, mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0,      MUX | DIV_U71 | PERIPH_ON_APB),
        PERIPH_CLK("sdmmc1_ddr", "sdhci-tegra.0",       "ddr",  14,     0x150,  100000000, mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0,      MUX | DIV_U71 | DIV_U71_INT | PERIPH_ON_APB),
-       PERIPH_CLK("sdmmc2_ddr", "sdhci-tegra.1",       "ddr",  9,      0x154,  333000000, mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0,      MUX | DIV_U71 | DIV_U71_INT | PERIPH_ON_APB),
        PERIPH_CLK("sdmmc3_ddr", "sdhci-tegra.2",       "ddr",  69,     0x1bc,  100000000, mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0,      MUX | DIV_U71 | DIV_U71_INT | PERIPH_ON_APB),
-       PERIPH_CLK("sdmmc4_ddr", "sdhci-tegra.3",       "ddr",  15,     0x164,  333000000, mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0,      MUX | DIV_U71 | DIV_U71_INT | PERIPH_ON_APB),
+       PERIPH_CLK_EX("sdmmc2", "sdhci-tegra.1",        NULL,   9,      0x154,  333000000, mux_pllp_clk_m_pllc4_out2_out1_out0_lj,      MUX | DIV_U71 | PERIPH_ON_APB, &tegra_sdmmc24_clk_ops),
+       PERIPH_CLK_EX("sdmmc4", "sdhci-tegra.3",        NULL,   15,     0x164,  333000000, mux_pllp_clk_m_pllc4_out2_out1_out0_lj,      MUX | DIV_U71 | PERIPH_ON_APB, &tegra_sdmmc24_clk_ops),
+       PERIPH_CLK_EX("sdmmc2_ddr", "sdhci-tegra.1",    "ddr",  9,      0x154,  333000000, mux_pllp_clk_m_pllc4_out2_out1_out0_lj,      MUX | DIV_U71 | DIV_U71_INT | PERIPH_ON_APB, &tegra_sdmmc24_clk_ops),
+       PERIPH_CLK_EX("sdmmc4_ddr", "sdhci-tegra.3",    "ddr",  15,     0x164,  333000000, mux_pllp_clk_m_pllc4_out2_out1_out0_lj,      MUX | DIV_U71 | DIV_U71_INT | PERIPH_ON_APB, &tegra_sdmmc24_clk_ops),
        PERIPH_CLK("sdmmc_legacy", "sdmmc_legacy",      NULL,   193,    0x694,  208000000, mux_pllp_out3_clkm_pllp_pllc4, MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
 
        PERIPH_CLK("vcp",       "nvavp",                "vcp",  29,     0,      250000000, mux_clk_m,                   0),
@@ -8614,8 +8978,8 @@ struct clk tegra_list_clks[] = {
        PERIPH_CLK("disp2",     "tegradc.1",            NULL,   26,     0x13c,  800000000, mux_pllp_plld_plld2_clkm,    MUX),
        PERIPH_CLK_EX("sor0",   "sor0",                 NULL,   182,    0x414,  600000000, mux_pllp_sor_sor0_brick,             MUX,    &tegra_sor0_clk_ops),
        PERIPH_CLK_EX("sor1",   "sor1",                 NULL,   183,    0x410,  600000000, mux_pllp_sor_sor1_brick_sor1_src,    MUX,    &tegra_sor1_clk_ops),
-       PERIPH_CLK("dpaux",     "dpaux",                NULL,   181,    0,      408000000, mux_pllp,                    0),
-       PERIPH_CLK("dpaux1",    "dpaux1",               NULL,   207,    0,      408000000, mux_pllp,                    0),
+       PERIPH_CLK_EX("dpaux",  "dpaux",                NULL,   181,    0,       24000000, mux_pllp,                    0, &tegra_dpaux_clk_ops),
+       PERIPH_CLK_EX("dpaux1", "dpaux1",               NULL,   207,    0,       24000000, mux_pllp,                    0, &tegra_dpaux_clk_ops),
 
        PERIPH_CLK("usbd",      "tegra-udc.0",          NULL,   22,     0,      480000000, mux_clk_m,                   0),
        PERIPH_CLK("usb2",      "tegra-ehci.1",         NULL,   58,     0,      480000000, mux_clk_m,                   0),
@@ -8636,8 +9000,8 @@ struct clk tegra_list_clks[] = {
        PERIPH_CLK("dsialp",    "tegradc.0",        "dsialp",   147,    0x620,  204000000, mux_pllp_pllc_clkm,          MUX | DIV_U71 | PERIPH_NO_RESET),
        PERIPH_CLK("dsiblp",    "tegradc.1",        "dsiblp",   148,    0x624,  204000000, mux_pllp_pllc_clkm,          MUX | DIV_U71 | PERIPH_NO_RESET),
 
-       PERIPH_CLK("entropy",   "entropy",              NULL,   149,    0x628,  102000000, mux_pllp_clkm_1,             MUX | DIV_U71),
-       PERIPH_CLK("uart_mipi_cal", "uart_mipi_cal",    NULL,   177,    0x66c,  102000000, mux_pllp_out3_pllp_pllc_clkm, MUX | DIV_U71 | PERIPH_NO_RESET),
+       PERIPH_CLK("entropy",   "entropy",              NULL,   149,    0x628,  102000000, mux_pllp_clkm_clk32_plle,            MUX | DIV_U71),
+       PERIPH_CLK("uart_mipi_cal", "uart_mipi_cal",    NULL,   177,    0x66c,  102000000, mux_pllp_out3_pllp_pllc_clkm,        MUX | DIV_U71 | PERIPH_NO_RESET),
        PERIPH_CLK("dbgapb",    "dbgapb",               NULL,   185,    0x718,  136000000, mux_pllp_clkm_2,             MUX | DIV_U71 | PERIPH_NO_RESET),
        PERIPH_CLK("tsensor",   "tegra-tsensor",        NULL,   100,    0x3b8,  216000000, mux_pllp_pllc_clkm_clk32,    MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
        PERIPH_CLK("actmon",    "actmon",               NULL,   119,    0x3e8,  216000000, mux_pllp_pllc_clk32_clkm,    MUX | DIV_U71),
@@ -8649,7 +9013,7 @@ struct clk tegra_list_clks[] = {
        PERIPH_CLK("afi",       "tegra-pcie",           "afi",  72,     0,      250000000, mux_clk_m,                   0),
        PERIPH_CLK("cl_dvfs_ref", "tegra_cl_dvfs",      "ref",  155,    0x62c,  54000000,  mux_pllp_clkm,               MUX | DIV_U71 | DIV_U71_INT | PERIPH_ON_APB),
        PERIPH_CLK("cl_dvfs_soc", "tegra_cl_dvfs",      "soc",  155,    0x630,  54000000,  mux_pllp_clkm,               MUX | DIV_U71 | DIV_U71_INT | PERIPH_ON_APB),
-       PERIPH_CLK("soc_therm", "soc_therm",            NULL,   78,     0x644,  408000000, mux_pllc_pllp_plla_pllc4,    MUX | DIV_U71 | PERIPH_ON_APB),
+       PERIPH_CLK("soc_therm", "soc_therm",            NULL,   78,     0x644,  408000000, mux_clkm_pllc_pllp_plla,     MUX | DIV_U71 | PERIPH_ON_APB),
 
        PERIPH_CLK("dp2",       "dp2",                  NULL,   152,    0,      38400000, mux_clk_m,                    PERIPH_ON_APB),
        PERIPH_CLK("mc_bbc",    "mc_bbc",               NULL,   170,    0,      1066000000, mux_clk_mc,                 PERIPH_NO_RESET),
@@ -8672,7 +9036,7 @@ struct clk tegra_list_clks[] = {
        PERIPH_CLK_SKIP("tsecb", "tsecb",       NULL,   206,    0x6d8,  0x70c,  700000000, mux_pllp_pllc2_c_c3_clkm,    MUX | DIV_U71 | DIV_U71_INT),
        PERIPH_CLK_SKIP("ispa", "isp",          "ispa", 23,     0,      0x6f8,  700000000, mux_isp,                             PERIPH_ON_APB),
        PERIPH_CLK_SKIP("ispb", "isp",          "ispb", 3,      0,      0x6fc,  700000000, mux_isp,                             PERIPH_ON_APB),
-       PERIPH_CLK_EX("vi",     "vi",           "vi",   20,     0x148,          700000000, mux_pllc2_c_c3_pllp_plla1_pllc4,     MUX | DIV_U71 | DIV_U71_INT, &tegra_vi_clk_ops),
+       PERIPH_CLK_EX("vi",     "vi",           "vi",   20,     0x148,          700000000, mux_pllc2_c_c3_pllp_clkm_plla1_pllc4,        MUX | DIV_U71 | DIV_U71_INT, &tegra_vi_clk_ops),
        SUPER_SKIP_CLK("vi_skip", "vi",         "skip",         0x6ec,             NULL, 0),
 
        SHARED_CLK("avp.sclk",  "nvavp",                "sclk", &tegra_clk_sbus_cmplx, NULL, 0, 0),
@@ -8722,6 +9086,7 @@ struct clk tegra_list_clks[] = {
        SHARED_EMC_CLK("floor.emc",     "floor.emc",    NULL,   &tegra_clk_emc, NULL, 0, 0, 0),
        SHARED_EMC_CLK("override.emc", "override.emc",  NULL,   &tegra_clk_emc, NULL, 0, SHARED_OVERRIDE, 0),
        SHARED_EMC_CLK("vic.emc",       "tegra_vic03",  "emc",  &tegra_clk_emc, NULL, 0, 0, 0),
+       SHARED_EMC_CLK("vic_shared.emc",        "tegra_vic03",  "emc_shared",  &tegra_clk_emc, NULL, 0, SHARED_BW, 0),
        SHARED_EMC_CLK("ape.emc", "ape", "emc",  &tegra_clk_emc, NULL, 0, 0, 0),
 
        DUAL_CBUS_CLK("nvjpg.cbus",     "tegra_nvjpg",          "nvjpg", &tegra_clk_c2bus, "nvjpg", 0, 0),
@@ -8810,11 +9175,34 @@ static struct clk tegra_xusb_source_clks[] = {
        PERIPH_CLK("xusb_host_src",     XUSB_ID, "host_src",    143,    0x600,  120000000, mux_clkm_pllp_pllre,         MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
        PERIPH_CLK("xusb_falcon_src",   XUSB_ID, "falcon_src",  143,    0x604,  350000000, mux_clkm_pllp_pllre,         MUX | DIV_U71 | PERIPH_NO_RESET),
        PERIPH_CLK("xusb_fs_src",       NULL, "fs_src", 143,    0x608,   48000000, mux_clkm_48M_pllp_480M,      MUX | DIV_U71 | PERIPH_NO_RESET),
-       PERIPH_CLK("xusb_ss_src",       NULL, "ss_src", 143,    0x610,  120000000, mux_clkm_pllre_clk32_480M_pllc_ref,  MUX | DIV_U71 | PERIPH_NO_RESET),
+       PERIPH_CLK_EX("xusb_ss_src",    NULL, "ss_src", 143,    0x610,  120000000, mux_clkm_pllre_clk32_480M_pllc_ref,  MUX | DIV_U71 | PERIPH_NO_RESET, &tegra_xusb_ss_ops),
        PERIPH_CLK("xusb_dev_src",      XUDC_ID, "dev_src",     95,     0x60c,  120000000, mux_clkm_pllp_pllre,         MUX | DIV_U71 | PERIPH_ON_APB),
        SHARED_EMC_CLK("xusb.emc",      XUSB_ID, "emc", &tegra_clk_emc, NULL,   0,      SHARED_BW, 0),
 };
 
+static struct clk_mux_sel mux_ss_clk_m[] = {
+       { .input = &tegra_xusb_source_clks[3], .value = 0},
+       { .input = &tegra_clk_m,               .value = 1},
+       { 0, 0},
+};
+
+static struct clk tegra_xusb_ssp_src = {
+       .name      = "xusb_ssp_src",
+       .lookup    = {
+               .dev_id    = NULL,
+               .con_id    = "ssp_src",
+       },
+       .ops       = &tegra_xusb_ss_ops,
+       .reg       = 0x610,
+       .inputs    = mux_ss_clk_m,
+       .flags     = MUX | PERIPH_NO_ENB | PERIPH_NO_RESET,
+       .max_rate  = 120000000,
+       .u.periph = {
+               .src_mask  = 0x1 << 24,
+               .src_shift = 24,
+       },
+};
+
 static struct clk tegra_xusb_ss_div2 = {
        .name      = "xusb_ss_div2",
        .ops       = &tegra_clk_m_div_ops,
@@ -8839,7 +9227,7 @@ static struct clk tegra_xusb_hs_src = {
                .dev_id    = NULL,
                .con_id    = "hs_src",
        },
-       .ops       = &tegra_periph_clk_ops,
+       .ops       = &tegra_xusb_ss_ops,
        .reg       = 0x610,
        .inputs    = mux_ss_div2_pllu_60M,
        .flags     = MUX | PLLU | PERIPH_NO_ENB | PERIPH_NO_RESET,
@@ -8859,7 +9247,7 @@ static struct clk_mux_sel mux_xusb_host[] = {
 };
 
 static struct clk_mux_sel mux_xusb_ss[] = {
-       { .input = &tegra_xusb_source_clks[3], .value = 3},
+       { .input = &tegra_xusb_ssp_src,        .value = 3},
        { .input = &tegra_xusb_source_clks[0], .value = 0},
        { .input = &tegra_xusb_source_clks[1], .value = 1},
        { 0, 0},
@@ -8868,7 +9256,8 @@ static struct clk_mux_sel mux_xusb_ss[] = {
 static struct clk_mux_sel mux_xusb_dev[] = {
        { .input = &tegra_xusb_source_clks[4], .value = 4},
        { .input = &tegra_xusb_source_clks[2], .value = 2},
-       { .input = &tegra_xusb_source_clks[3], .value = 3},
+       { .input = &tegra_xusb_ssp_src,        .value = 3},
+       { .input = &tegra_xusb_hs_src,         .value = 5},
        { 0, 0},
 };
 
@@ -8878,6 +9267,45 @@ static struct clk tegra_xusb_coupled_clks[] = {
        PERIPH_CLK_EX("xusb_dev",  XUDC_ID, "dev",  95, 0, 120000000, mux_xusb_dev,  0, &tegra_clk_coupled_gate_ops),
 };
 
+#define SLCG_CLK(_root_name, _name_ext, _dev, _con, _reg, _bit)                \
+       {                                                               \
+               .name      = _root_name "_slcg_ovr" _name_ext,          \
+               .lookup = {                                             \
+                       .dev_id = _dev,                                 \
+                       .con_id = _con,                                 \
+               },                                                      \
+               .ops       = &tegra_clk_slcg_ops,                       \
+               .reg       = _reg,                                      \
+               .max_rate  = 38400000, /* replaced by root max */       \
+               .u.periph = {                                           \
+                       .clk_num   = _bit,                              \
+               },                                                      \
+       }
+
+static struct clk tegra_slcg_clks[] = {
+       SLCG_CLK("disp2",       "",     "tegradc.1",    "slcg",         0xf8,   2),
+       SLCG_CLK("disp1",       "",     "tegradc.0",    "slcg",         0xf8,   1),
+
+       SLCG_CLK("vi",          "",     "tegra_vi",     "slcg",         0xf8,   15),
+       SLCG_CLK("ispa",        "",     "tegra_isp.0",  "slcg",         0x554,  3),
+       SLCG_CLK("ispb",        "",     "tegra_isp.1",  "slcg",         0x3a4,  22),
+
+       SLCG_CLK("nvdec",       "",     "tegra_nvdec",  "slcg",         0x554,  31),
+       SLCG_CLK("msenc",       "",     "tegra_msenc",  "slcg",         0x554,  29),
+       SLCG_CLK("nvjpg",       "",     "tegra_nvjpg",  "slcg",         0x554,  9),
+       SLCG_CLK("vic03",       "",     "tegra_vic03",  "slcg",         0x554,  5),
+
+       SLCG_CLK("xusb_dev",    "",     XUDC_ID,        "slcg",         0x3a0,  31),
+       SLCG_CLK("xusb_host",   "",     XUSB_ID,        "slcg",         0x3a0,  30),
+       SLCG_CLK("sata",        "_fpci", "tegra_sata",  "slcg_fpci",    0x3a0,  19),
+       SLCG_CLK("sata",        "_ipfs", "tegra_sata",  "slcg_ipfs",    0x3a0,  17),
+       SLCG_CLK("sata",        "",     "tegra_sata",   "slcg",         0x3a0,  0),
+
+       SLCG_CLK("d_audio",     "",   "tegra210-axbar", "slcg",         0x3a0,  1),
+       SLCG_CLK("adsp",        "",     NULL,           "slcg_adsp",    0x554,  11),
+       SLCG_CLK("ape",         "",     NULL,           "slcg_ape",     0x554,  10),
+};
+
 #define CLK_DUPLICATE(_name, _dev, _con)               \
        {                                               \
                .name   = _name,                        \
@@ -8892,7 +9320,6 @@ static struct clk tegra_xusb_coupled_clks[] = {
  * table under two names.
  */
 struct clk_duplicate tegra_clk_duplicates[] = {
-       CLK_DUPLICATE("pll_u_vco",  NULL, "pll_u"),
        CLK_DUPLICATE("uarta",  "serial8250.0", NULL),
        CLK_DUPLICATE("uartb",  "serial8250.1", NULL),
        CLK_DUPLICATE("uartc",  "serial8250.2", NULL),
@@ -8943,8 +9370,15 @@ struct clk_duplicate tegra_clk_duplicates[] = {
        CLK_DUPLICATE("actmon", "tegra_host1x", "actmon"),
        CLK_DUPLICATE("gpu_ref", "tegra_gpu.0", "PLLG_ref"),
        CLK_DUPLICATE("pll_p_out5", "tegra_gpu.0", "pwr"),
-       CLK_DUPLICATE("ispa.isp.cbus", "tegra_isp", "isp"),
+       CLK_DUPLICATE("ispa.isp.cbus", "tegra_isp.0", "isp"),
        CLK_DUPLICATE("ispb.isp.cbus", "tegra_isp.1", "isp"),
+       CLK_DUPLICATE("vii2c", "tegra_vi-i2c", "vii2c"),
+       CLK_DUPLICATE("vii2c", "tegra_vi", "vii2c"),
+       CLK_DUPLICATE("i2cslow", "tegra_vi-i2c", "i2cslow"),
+       CLK_DUPLICATE("i2cslow", "tegra_vi", "i2cslow"),
+       CLK_DUPLICATE("mclk3", NULL, "cam_mclk1"),
+       CLK_DUPLICATE("mclk", NULL, "cam_mclk2"),
+       CLK_DUPLICATE("mclk2", NULL, "cam_mclk3"),
 #ifdef CONFIG_VI_ONE_DEVICE
        CLK_DUPLICATE("vi.cbus", "tegra_vi", "vi"),
        CLK_DUPLICATE("csi", "tegra_vi", "csi"),
@@ -8986,14 +9420,20 @@ struct clk_duplicate tegra_clk_duplicates[] = {
        CLK_DUPLICATE("d_audio", "tegra210-mvc.0", NULL),
        CLK_DUPLICATE("d_audio", "tegra210-mvc.1", NULL),
        CLK_DUPLICATE("d_audio", "tegra210-mixer", NULL),
+       CLK_DUPLICATE("d_audio", "tegra210-ope.0", NULL),
+       CLK_DUPLICATE("d_audio", "tegra210-ope.1", NULL),
        CLK_DUPLICATE("mclk", NULL, "default_mclk"),
        CLK_DUPLICATE("uart_mipi_cal", "clk72mhz", NULL),
 };
 
-struct clk *tegra_ptr_clks[] = {
+
+struct clk *tegra_main_clks[] = {
        &tegra_clk_32k,
        &tegra_clk_osc,
        &tegra_clk_m,
+};
+
+struct clk *tegra_ptr_clks[] = {
        &tegra_clk_m_div2,
        &tegra_clk_m_div4,
        &tegra_pll_ref,
@@ -9075,6 +9515,8 @@ struct clk *tegra_ptr_clks[] = {
        &tegra_clk_sor0_brick,
        &tegra_clk_sor1_brick,
        &tegra_clk_xusb_padctl,
+       &tegra_clk_sata,
+       &tegra_sata_aux_clk,
        &tegra_clk_sata_uphy,
        &tegra_clk_usb2_hsic_trk,
 };
@@ -9082,8 +9524,35 @@ struct clk *tegra_ptr_clks[] = {
 struct clk *tegra_ptr_camera_mclks[] = {
        &tegra_camera_mclk,
        &tegra_camera_mclk2,
+       &tegra_camera_mclk3,
+       &tegra_camera_mipical,
 };
 
+#ifdef CONFIG_DEBUG_FS
+static struct tegra_pto_table ptodefs[] = {
+       { .name = "pll_c",  .divider = 2, .pto_id = 1,   .presel_reg = 0x088, .presel_value = BIT(3),  .presel_mask = BIT(3) },
+       { .name = "pll_a1", .divider = 2, .pto_id = 85,  .presel_reg = 0x6a8, .presel_value = BIT(3),  .presel_mask = BIT(3) },
+       { .name = "pll_c2", .divider = 2, .pto_id = 88,  .presel_reg = 0x4ec, .presel_value = BIT(3),  .presel_mask = BIT(3) },
+       { .name = "pll_c3", .divider = 2, .pto_id = 89,  .presel_reg = 0x500, .presel_value = BIT(3),  .presel_mask = BIT(3) },
+
+       { .name = "pll_a",  .divider = 2, .pto_id = 4,   .presel_reg = 0x0bc, .presel_value = BIT(29), .presel_mask = BIT(29) },
+       { .name = "pll_x",  .divider = 2, .pto_id = 5,   .presel_reg = 0x0e4, .presel_value = BIT(22), .presel_mask = BIT(22) },
+
+       { .name = "pll_d",  .divider = 2, .pto_id = 203, .presel_reg = 0x0dc, .presel_value = BIT(25), .presel_mask = BIT(25) },
+       { .name = "pll_d2", .divider = 2, .pto_id = 205, .presel_reg = 0x4b8, .presel_value = BIT(16), .presel_mask = BIT(16) },
+       { .name = "pll_dp", .divider = 2, .pto_id = 207, .presel_reg = 0x590, .presel_value = BIT(16), .presel_mask = BIT(16) },
+       { .name = "pll_c4", .divider = 2, .pto_id = 81,  .presel_reg = 0x5a4, .presel_value = BIT(16), .presel_mask = BIT(16) },
+
+       { .name = "pll_m",  .divider = 2, .pto_id = 2,   .presel_reg = 0x9c,  .presel_value = BIT(8),  .presel_mask = BIT(8) },
+       { .name = "pll_mb", .divider = 2, .pto_id = 37,  .presel_reg = 0x9c,  .presel_value = BIT(9),  .presel_mask = BIT(9) },
+
+       { .name = "pll_u", .divider = 2,  .pto_id = 269, .presel_reg = 0xcc,  .presel_value = BIT(27), .presel_mask = BIT(27) },
+       { .name = "pll_re_vco", .divider = 2, .pto_id = 271, .presel_reg = 0x4c8, .presel_value = BIT(26), .presel_mask = BIT(26) },
+
+       { .name = NULL, },
+};
+#endif
+
 /*
  * Handle special clocks to check if they can be set to safe rate
  */
@@ -9231,6 +9700,7 @@ static void tegra21_pllp_init_dependencies(unsigned long pllp_rate)
                tegra_pll_p_out3.u.pll_div.default_rate = 72000000;
                tegra_pll_p_out4.u.pll_div.default_rate = 108000000;
                tegra_pll_p_out5.u.pll_div.default_rate = 108000000;
+               tegra_clk_sbus_cmplx.u.system.threshold = 108000000;
                tegra_clk_host1x.u.periph.threshold = 108000000;
                tegra_clk_aclk_adsp.u.cclk.div71 = 2; /* reg settings */
                break;
@@ -9238,6 +9708,7 @@ static void tegra21_pllp_init_dependencies(unsigned long pllp_rate)
                tegra_pll_p_out3.u.pll_div.default_rate = 102000000;
                tegra_pll_p_out4.u.pll_div.default_rate = 204000000;
                tegra_pll_p_out5.u.pll_div.default_rate = 204000000;
+               tegra_clk_sbus_cmplx.u.system.threshold = 204000000;
                tegra_clk_host1x.u.periph.threshold = 204000000;
                tegra_clk_aclk_adsp.u.cclk.div71 = 2; /* reg settings */
                break;
@@ -9245,6 +9716,7 @@ static void tegra21_pllp_init_dependencies(unsigned long pllp_rate)
                tegra_pll_p_out3.u.pll_div.default_rate = 102000000;
                tegra_pll_p_out4.u.pll_div.default_rate = 204000000;
                tegra_pll_p_out5.u.pll_div.default_rate = 204000000;
+               tegra_clk_sbus_cmplx.u.system.threshold = 204000000;
                tegra_clk_host1x.u.periph.threshold = 204000000;
                tegra_clk_aclk_adsp.u.cclk.div71 = 0; /* reg settings */
                break;
@@ -9586,7 +10058,8 @@ static int tegra21_clk_suspend(void)
        *ctx++ = clk_readl(tegra_clk_cclk_lp.reg);
        *ctx++ = clk_readl(tegra_clk_cclk_lp.reg + SUPER_CLK_DIVIDER);
 
-       *ctx++ = clk_get_rate_all_locked(&tegra_clk_emc);
+       *ctx = clk_get_rate_all_locked(&tegra_clk_emc);
+       tegra21_emc_clk_suspend(&tegra_clk_emc, *ctx++);
 
        pr_debug("%s: suspend entries: %d, suspend array: %u\n", __func__,
                (s32)(ctx - clk_rst_suspend), (u32)ARRAY_SIZE(clk_rst_suspend));
@@ -9875,11 +10348,67 @@ static void tegra21_init_xusb_clocks(void)
 
        tegra21_init_one_clock(&tegra_xusb_ss_div2);
        tegra21_init_one_clock(&tegra_xusb_hs_src);
+       tegra21_init_one_clock(&tegra_xusb_ssp_src);
 
        for (i = 0; i < ARRAY_SIZE(tegra_xusb_coupled_clks); i++)
                tegra21_init_one_clock(&tegra_xusb_coupled_clks[i]);
 }
 
+/*
+ * Check if arch timer frequency specified either in DT or in CNTFRQ register is
+ * matching actual clk_m rate.
+ */
+static void tegra21_check_timer_clock(u32 clk_m_rate)
+{
+
+       struct device_node *dn;
+       u32 dt_rate = 0;
+       u32 timer_rate = 0;
+
+       for_each_compatible_node(dn, NULL, "arm,armv8-timer") {
+               if (!of_device_is_available(dn))
+                       continue;
+
+               if (!of_property_read_u32(dn, "clock-frequency", &dt_rate))
+                       timer_rate = dt_rate;
+               break;
+       }
+
+       if (!dn) {
+               WARN(1, "No arch timer node in DT\n");
+               return;
+       }
+
+       if (!timer_rate)
+               timer_rate = arch_timer_get_cntfrq();
+
+       if (timer_rate == clk_m_rate)
+               return;
+
+       WARN(1, "Arch timer %s rate %u doesn't match clk_m %u - kernel timing is broken\n",
+               dt_rate ? "DT" : "CNTFRQ", timer_rate, clk_m_rate);
+}
+
+/*
+ * The udelay() is implemented based on arch timers, using loops_per_jiffy as
+ * scaling factor. To make it functional during early clock initialization -
+ *  before timers are initialized - set loops_per_jiffy here.
+ */
+static void tegra21_init_main_clock(void)
+{
+       int i;
+       unsigned long clk_m_rate;
+
+       for (i = 0; i < ARRAY_SIZE(tegra_main_clks); i++)
+               tegra21_init_one_clock(tegra_main_clks[i]);
+
+       clk_m_rate = clk_get_rate_all_locked(&tegra_clk_m);
+
+       loops_per_jiffy = clk_m_rate / HZ;
+
+       tegra21_check_timer_clock(clk_m_rate);
+}
+
 void __init tegra21x_init_clocks(void)
 {
        int i;
@@ -9888,6 +10417,8 @@ void __init tegra21x_init_clocks(void)
 #ifndef        CONFIG_TEGRA_DUAL_CBUS
        BUILD_BUG()
 #endif
+       tegra21_init_main_clock();
+
        for (i = 0; i < ARRAY_SIZE(tegra_ptr_clks); i++)
                tegra21_init_one_clock(tegra_ptr_clks[i]);
 
@@ -9915,6 +10446,9 @@ void __init tegra21x_init_clocks(void)
 
        tegra21_init_xusb_clocks();
 
+       for (i = 0; i < ARRAY_SIZE(tegra_slcg_clks); i++)
+               tegra21_init_one_clock(&tegra_slcg_clks[i]);
+
        for (i = 0; i < ARRAY_SIZE(tegra_clk_duplicates); i++) {
                c = tegra_get_clock_by_name(tegra_clk_duplicates[i].name);
                if (!c) {
@@ -9939,6 +10473,10 @@ void __init tegra21x_init_clocks(void)
 #ifdef CONFIG_PM_SLEEP
        register_syscore_ops(&tegra_clk_syscore_ops);
 #endif
+
+#ifdef CONFIG_DEBUG_FS
+       tegra_clk_add_pto_entries(ptodefs);
+#endif
 }
 
 static int __init tegra21x_clk_late_init(void)