arm: tegra: Move driver files to drivers/platform
[linux-3.10.git] / drivers / platform / tegra / tegra21_clocks.c
index 3bddeef..64dd550 100644 (file)
 #include <linux/cpufreq.h>
 #include <linux/syscore_ops.h>
 #include <linux/platform_device.h>
+#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 <mach/mc.h>
 #include <mach/tegra_emc.h>
 
-#include "clock.h"
+#include <tegra/mc.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
@@ -87,7 +90,7 @@
 #define CLK_OUT_ENB_U_RESET_MASK       0xf3fed3fa
 #define CLK_OUT_ENB_V_RESET_MASK       0xffc18cfb
 #define CLK_OUT_ENB_W_RESET_MASK       0x793fb7ff
-#define CLK_OUT_ENB_X_RESET_MASK       0x3e66fff
+#define CLK_OUT_ENB_X_RESET_MASK       0x3fe66fff
 #define CLK_OUT_ENB_Y_RESET_MASK       0xfc1fc7ff
 
 #define RST_DEVICES_V_SWR_CPULP_RST_DIS        (0x1 << 1) /* Reserved on Tegra11 */
 #define SPARE_REG_CLK_M_DIVISOR_SHIFT  2
 #define SPARE_REG_CLK_M_DIVISOR_MASK   (3 << SPARE_REG_CLK_M_DIVISOR_SHIFT)
 
+#define AUDIO_SYNC_CLK_DMIC1           0x560
+#define AUDIO_SYNC_CLK_DMIC2           0x564
+#define PERIPH_CLK_SOURCE_NUM4 \
+       ((AUDIO_SYNC_CLK_DMIC2 - AUDIO_SYNC_CLK_DMIC1) / 4 + 1)
+
 #define PERIPH_CLK_SOURCE_XUSB_HOST    0x600
+#define PERIPH_CLK_SOURCE_EMC_DLL      0x664
 #define PERIPH_CLK_SOURCE_VIC          0x678
-#define PERIPH_CLK_SOURCE_NUM4 \
-       ((PERIPH_CLK_SOURCE_VIC - PERIPH_CLK_SOURCE_XUSB_HOST) / 4 + 1)
+#define PERIPH_CLK_SOURCE_NUM5 \
+       ((PERIPH_CLK_SOURCE_VIC - PERIPH_CLK_SOURCE_XUSB_HOST) / 4)
+
+#define PERIPH_CLK_SOURCE_SDMMC_LEGACY 0x694
+#define PERIPH_CLK_SOURCE_NVENC                0x6a0
+#define PERIPH_CLK_SOURCE_NUM6 \
+       ((PERIPH_CLK_SOURCE_NVENC - PERIPH_CLK_SOURCE_SDMMC_LEGACY) / 4 + 1)
+
+#define AUDIO_SYNC_CLK_DMIC3           0x6b8
+#define PERIPH_CLK_SOURCE_DBGAPB       0x718
+#define PERIPH_CLK_SOURCE_NUM7 \
+       ((PERIPH_CLK_SOURCE_DBGAPB - AUDIO_SYNC_CLK_DMIC3) / 4 + 1)
 
 #define PERIPH_CLK_SOURCE_NUM          (PERIPH_CLK_SOURCE_NUM1 + \
                                         PERIPH_CLK_SOURCE_NUM2 + \
                                         PERIPH_CLK_SOURCE_NUM3 + \
-                                        PERIPH_CLK_SOURCE_NUM4)
+                                        PERIPH_CLK_SOURCE_NUM4 + \
+                                        PERIPH_CLK_SOURCE_NUM5 + \
+                                        PERIPH_CLK_SOURCE_NUM6 + \
+                                        PERIPH_CLK_SOURCE_NUM7)
 
 #define CPU_SOFTRST_CTRL               0x380
 #define CPU_SOFTRST_CTRL1              0x384
 #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 SUPER_STATE_RUN                        (0x2 << SUPER_STATE_SHIFT)
 #define SUPER_STATE_IRQ                        (0x3 << SUPER_STATE_SHIFT)
 #define SUPER_STATE_FIQ                        (0x4 << SUPER_STATE_SHIFT)
-#define SUPER_LP_DIV2_BYPASS           (0x1 << 16)
 #define SUPER_SOURCE_MASK              0xF
 #define        SUPER_FIQ_SOURCE_SHIFT          12
 #define        SUPER_IRQ_SOURCE_SHIFT          8
 #define PLLE_AUX_PLLRE_SEL             (1<<28)
 #define PLLE_AUX_SEQ_STATE_SHIFT       26
 #define PLLE_AUX_SEQ_STATE_MASK                (0x3<<PLLE_AUX_SEQ_STATE_SHIFT)
+#define PLLE_AUX_SS_SEQ_INCLUDE                (1<<31)
 #define PLLE_AUX_SEQ_START_STATE       (1<<25)
 #define PLLE_AUX_SEQ_ENABLE            (1<<24)
 #define PLLE_AUX_SS_SWCTL              (1<<6)
 #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 UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL       (1<<0)
 
 #define PLLU_HW_PWRDN_CFG0                     0x530
+#define PLLU_HW_PWRDN_CFG0_IDDQ_PD_INCLUDE     (1<<28)
 #define PLLU_HW_PWRDN_CFG0_SEQ_START_STATE     (1<<25)
 #define PLLU_HW_PWRDN_CFG0_SEQ_ENABLE          (1<<24)
+#define PLLU_HW_PWRDN_CFG0_USE_SWITCH_DETECT   (1<<7)
 #define PLLU_HW_PWRDN_CFG0_USE_LOCKDET         (1<<6)
 #define PLLU_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL    (1<<2)
 #define PLLU_HW_PWRDN_CFG0_CLK_SWITCH_SWCTL    (1<<0)
 
-#define USB_PLLS_SEQ_START_STATE               (1<<25)
-#define USB_PLLS_SEQ_ENABLE                    (1<<24)
-#define USB_PLLS_USE_LOCKDET                   (1<<6)
-#define USB_PLLS_ENABLE_SWCTL                  ((1<<2) | (1<<0))
-
-/* XUSB PLL PAD controls */
-#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0         0x40
-#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0_PLL_PWR_OVRD    (1<<3)
-#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0_PLL_IDDQ        (1<<0)
+#define XUSB_PLL_CFG0                          0x534
+#define XUSB_PLL_CFG0_PLLU_LOCK_DLY_SHIFT      14
+#define XUSB_PLL_CFG0_PLLU_LOCK_DLY_MASK       \
+       (0x3ff<<XUSB_PLL_CFG0_PLLU_LOCK_DLY_SHIFT)
 
 /* DFLL */
 #define DFLL_BASE                              0x2f4
 /* Use PLL_RE as PLLE input (default - OSC via pll reference divider) */
 #define USE_PLLE_INPUT_PLLRE    0
 
-static bool tegra21_is_dyn_ramp(struct clk *c,
-                               unsigned long rate, bool from_vco_min);
 static void pllc4_set_fixed_rates(unsigned long cf);
 static void tegra21_dfll_cpu_late_init(struct clk *c);
 static void tegra21_pllp_init_dependencies(unsigned long pllp_rate);
@@ -610,12 +629,11 @@ 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);
 static void __iomem *misc_gp_base = IO_ADDRESS(TEGRA_APB_MISC_BASE);
-static void __iomem *reg_xusb_padctl_base = IO_ADDRESS(TEGRA_XUSB_PADCTL_BASE);
 
 #define MISC_GP_HIDREV                         0x804
 #define MISC_GP_TRANSACTOR_SCRATCH_0           0x864
@@ -629,10 +647,6 @@ static void __iomem *reg_xusb_padctl_base = IO_ADDRESS(TEGRA_XUSB_PADCTL_BASE);
        readl(reg_pmc_base + (reg))
 #define chipid_readl() \
        __raw_readl(misc_gp_base + MISC_GP_HIDREV)
-#define xusb_padctl_writel(value, reg) \
-        __raw_writel(value, reg_xusb_padctl_base + (reg))
-#define xusb_padctl_readl(reg) \
-       readl(reg_xusb_padctl_base + (reg))
 
 /*
  * Some peripheral clocks share an enable bit, so refcount the enable bits
@@ -768,6 +782,21 @@ static inline bool bus_user_request_is_lower(struct clk *a, struct clk *b)
                b->u.shared_bus_user.rate;
 }
 
+static void super_clk_set_u71_div_no_skip(struct clk *c)
+{
+       clk_writel_delay(c->u.cclk.div71 << SUPER_CLOCK_DIV_U71_SHIFT,
+                        c->reg + SUPER_CLK_DIVIDER);
+       c->mul = 2;
+       c->div = c->u.cclk.div71 + 2;
+}
+
+static void super_clk_clr_u71_div_no_skip(struct clk *c)
+{
+       clk_writel_delay(0, c->reg + SUPER_CLK_DIVIDER);
+       c->mul = 2;
+       c->div = 2;
+}
+
 /* clk_m functions */
 static unsigned long tegra21_osc_autodetect_rate(struct clk *c)
 {
@@ -800,6 +829,7 @@ static void tegra21_osc_init(struct clk *c)
 {
        pr_debug("%s on clock %s\n", __func__, c->name);
        tegra21_osc_autodetect_rate(c);
+       c->state = ON;
 }
 
 static int tegra21_osc_enable(struct clk *c)
@@ -975,19 +1005,19 @@ static int tegra21_super_clk_set_parent(struct clk *c, struct clk *p)
                        val &= ~(SUPER_SOURCE_MASK << shift);
                        val |= (sel->value & SUPER_SOURCE_MASK) << shift;
 
-                       if (c->flags & DIV_U71) {
+                       if ((c->flags & DIV_U71) && !c->u.cclk.div71) {
                                /* Make sure 7.1 divider is 1:1 */
                                u32 div = clk_readl(c->reg + SUPER_CLK_DIVIDER);
                                BUG_ON(div & SUPER_CLOCK_DIV_U71_MASK);
                        }
 
                        if (c->refcnt)
-                               clk_enable(p);
+                               tegra_clk_prepare_enable(p);
 
                        clk_writel_delay(val, c->reg);
 
                        if (c->refcnt && c->parent)
-                               clk_disable(c->parent);
+                               tegra_clk_disable_unprepare(c->parent);
 
                        clk_reparent(c, p);
                        return 0;
@@ -1005,11 +1035,10 @@ static int tegra21_super_clk_set_parent(struct clk *c, struct clk *p)
  */
 static int tegra21_super_clk_set_rate(struct clk *c, unsigned long rate)
 {
-       /* In tegra21_cpu_clk_set_plls() and  tegra21_sbus_cmplx_set_rate()
-        * this call is skipped by directly setting rate of source plls. If we
-        * ever use 7.1 divider at other than 1:1 setting, or exercise s/w
-        * skipper control, not only this function, but cpu and sbus set_rate
-        * APIs should be changed accordingly.
+       /*
+        * In tegra21_cpu_clk_set_plls(), tegra21_sbus_cmplx_set_rate(), and
+        * tegra21_adsp_cpu_clk_set_rate() this interface is skipped by directly
+        * setting rate of source plls.
         */
        return clk_set_rate(c->parent, rate);
 }
@@ -1063,7 +1092,7 @@ static int tegra21_cpu_clk_set_plls(struct clk *c, unsigned long rate,
         * backup source.
         */
        if (c->parent->parent == main_pll) {
-               clk_enable(main_pll);
+               tegra_clk_prepare_enable(main_pll);
                on_main = true;
                main_rate = rate;
 
@@ -1143,7 +1172,7 @@ static int tegra21_cpu_clk_set_plls(struct clk *c, unsigned long rate,
 
 out:
        if (on_main)
-               clk_disable(main_pll);
+               tegra_clk_disable_unprepare(main_pll);
 
        return ret;
 }
@@ -1498,14 +1527,20 @@ 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.
         */
-       clk_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);
 
        /* switch CPU mode */
        ret = tegra_cluster_control(delay, flags);
        if (ret) {
-               clk_disable(p);
+               tegra_clk_disable_unprepare(p);
                pr_err("%s: Failed to switch %s mode to %s\n",
                       __func__, c->name, p->name);
                goto abort;
@@ -1524,7 +1559,7 @@ static int tegra21_cpu_cmplx_clk_set_parent(struct clk *c, struct clk *p)
        }
 
        /* Disabling old parent scales old mode voltage rail */
-       clk_disable(c->parent);
+       tegra_clk_disable_unprepare(c->parent);
 
        clk_reparent(c, p);
 
@@ -1707,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);
@@ -1987,8 +2026,117 @@ static struct clk_ops tegra_sbus_cmplx_ops = {
        .shared_bus_update = tegra21_clk_sbus_update,
 };
 
-/* Blink output functions */
+/*
+ * Virtual ADSP CPU clock operations. Used to hide the sequence of changing
+ * and re-locking ADSP source PLLA1 in flight to configure requested ADSP
+ * target rate.
+ */
+static void tegra21_adsp_cpu_clk_init(struct clk *c)
+{
+       c->state = c->parent->state;
+       c->min_rate = c->u.cpu.main->min_rate;
+}
+
+static int tegra21_adsp_cpu_clk_enable(struct clk *c)
+{
+       return 0;
+}
+
+static void tegra21_adsp_cpu_clk_disable(struct clk *c)
+{
+}
+
+static int tegra21_adsp_cpu_clk_set_rate(struct clk *c, unsigned long rate)
+{
+       int ret = 0;
+       struct clk *main_pll = c->u.cpu.main;
+
+       /*
+        * If ADSP clock is disabled or it is not on main pll (may happen after
+        * boot), set main pll rate, and make sure it is selected as adsp clock
+        * source.
+        */
+       if (!c->refcnt || (c->parent->parent != main_pll)) {
+               ret = clk_set_rate(main_pll, rate);
+               if (ret) {
+                       pr_err("Failed to set adsp rate %lu on %s\n",
+                              rate, main_pll->name);
+                       return ret;
+               }
+
+               if (c->parent->parent == main_pll)
+                       return ret;
+
+               ret = clk_set_parent(c->parent, main_pll);
+               if (ret)
+                       pr_err("Failed to switch adsp to %s\n", main_pll->name);
+
+               return ret;
+       }
+
+       /*
+        * Take an extra reference to the main pll so it doesn't turn off when
+        * we move the cpu off of it. If possible, use main pll dynamic ramp
+        * to reach target rate in one shot. Otherwise use backup source while
+        * re-locking main.
+        */
+       tegra_clk_prepare_enable(main_pll);
+
+       if (tegra_pll_can_ramp_to_rate(main_pll, rate)) {
+               ret = clk_set_rate(main_pll, rate);
+               if (ret)
+                       pr_err("Failed to ramp %s to adsp rate %lu\n",
+                              main_pll->name, rate);
+               goto out;
+       }
+
+       /* Set backup divider, and switch to backup source */
+       super_clk_set_u71_div_no_skip(c->parent);
+       ret = clk_set_parent(c->parent, c->u.cpu.backup);
+       if (ret) {
+               super_clk_clr_u71_div_no_skip(c->parent);
+               pr_err("Failed to switch adsp to %s\n", c->u.cpu.backup->name);
+               goto out;
+       }
+
+       /* Set main pll rate, switch back to main, and clear backup divider */
+       ret = clk_set_rate(main_pll, rate);
+       if (ret) {
+               pr_err("Failed set adsp rate %lu on %s\n",
+                      rate, main_pll->name);
+               goto out;
+       }
+
+       ret = clk_set_parent(c->parent, main_pll);
+       if (ret) {
+               pr_err("Failed to switch adsp to %s\n", main_pll->name);
+               goto out;
+       }
+       super_clk_clr_u71_div_no_skip(c->parent);
+
+out:
+       tegra_clk_disable_unprepare(main_pll);
+       return ret;
+}
+
+static long tegra21_adsp_cpu_clk_round_rate(struct clk *c, unsigned long rate)
+{
+       if (rate > c->max_rate)
+               rate = c->max_rate;
+       else if (rate < c->min_rate)
+               rate = c->min_rate;
+       return rate;
+}
+
+static struct clk_ops tegra_adsp_cpu_ops = {
+       .init     = tegra21_adsp_cpu_clk_init,
+       .enable   = tegra21_adsp_cpu_clk_enable,
+       .disable  = tegra21_adsp_cpu_clk_disable,
+       .set_rate = tegra21_adsp_cpu_clk_set_rate,
+       .round_rate = tegra21_adsp_cpu_clk_round_rate,
+};
 
+/* Blink output functions */
 static void tegra21_blink_clk_init(struct clk *c)
 {
        u32 val;
@@ -2022,6 +2170,7 @@ static int tegra21_blink_clk_enable(struct clk *c)
 
        val = pmc_readl(PMC_CTRL);
        pmc_writel(val | PMC_CTRL_BLINK_ENB, PMC_CTRL);
+       pmc_readl(PMC_CTRL);
 
        return 0;
 }
@@ -2035,6 +2184,7 @@ static void tegra21_blink_clk_disable(struct clk *c)
 
        val = pmc_readl(PMC_DPD_PADS_ORIDE);
        pmc_writel(val & ~PMC_DPD_PADS_ORIDE_BLINK_ENB, PMC_DPD_PADS_ORIDE);
+       pmc_readl(PMC_DPD_PADS_ORIDE);
 }
 
 static int tegra21_blink_clk_set_rate(struct clk *c, unsigned long rate)
@@ -2058,6 +2208,7 @@ static int tegra21_blink_clk_set_rate(struct clk *c, unsigned long rate)
                val |= PMC_BLINK_TIMER_ENB;
                pmc_writel(val, c->reg);
        }
+       pmc_readl(c->reg);
 
        return 0;
 }
@@ -2070,18 +2221,6 @@ static struct clk_ops tegra_blink_clk_ops = {
 };
 
 /* UTMIP PLL configuration */
-static void usb_plls_hw_control_enable(u32 reg)
-{
-       u32 val = clk_readl(reg);
-       val |= USB_PLLS_USE_LOCKDET | USB_PLLS_SEQ_START_STATE;
-       val &= ~USB_PLLS_ENABLE_SWCTL;
-       val |= USB_PLLS_SEQ_START_STATE;
-       pll_writel_delay(val, reg);
-
-       val |= USB_PLLS_SEQ_ENABLE;
-       pll_writel_delay(val, reg);
-}
-
 static void tegra21_utmi_param_configure(struct clk *c)
 {
        u32 reg;
@@ -2100,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);
 
@@ -2137,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 */
@@ -2253,9 +2383,9 @@ static void pllcx_set_defaults(struct clk *c, unsigned long input_rate)
        pll_writel_delay(PLLCX_MISC3_DEFAULT_VALUE, c->reg + c->u.pll.misc3);
 }
 
+#if PLLCX_USE_DYN_RAMP
 static int pllcx_dyn_ramp(struct clk *c, struct clk_pll_freq_table *cfg)
 {
-#if PLLCX_USE_DYN_RAMP
        u32 reg;
        struct clk_pll_controls *ctrl = c->u.pll.controls;
        struct clk_pll_div_layout *divs = c->u.pll.div_layout;
@@ -2269,10 +2399,10 @@ static int pllcx_dyn_ramp(struct clk *c, struct clk_pll_freq_table *cfg)
        tegra_pll_clk_wait_for_lock(c, reg, ctrl->lock_mask);
 
        return 0;
+}
 #else
-       return -ENOSYS;
+#define pllcx_dyn_ramp NULL
 #endif
-}
 
 static void tegra21_pllcx_clk_init(struct clk *c)
 {
@@ -2753,6 +2883,7 @@ static void tegra21_pllu_vco_init(struct clk *c)
                pll_clk_set_gain(c, &cfg);
 
                pll_clk_verify_fixed_rate(c);
+               pr_info("%s: boot with h/w control already set\n", c->name);
                return;
        }
 
@@ -2760,9 +2891,52 @@ static void tegra21_pllu_vco_init(struct clk *c)
        tegra_pll_clk_init(c);
 }
 
+static void tegra21_pllu_hw_ctrl_set(struct clk *c)
+{
+       u32 val = clk_readl(c->reg);
+
+       /* Put PLLU under h/w control (if not already) */
+       if (val & PLLU_BASE_OVERRIDE) {
+               val &= ~PLLU_BASE_OVERRIDE;
+               pll_writel_delay(val, c->reg);
+
+               val = clk_readl(PLLU_HW_PWRDN_CFG0);
+               val |= PLLU_HW_PWRDN_CFG0_IDDQ_PD_INCLUDE |
+                       PLLU_HW_PWRDN_CFG0_USE_SWITCH_DETECT |
+                       PLLU_HW_PWRDN_CFG0_USE_LOCKDET;
+               val &= ~(PLLU_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL |
+                        PLLU_HW_PWRDN_CFG0_CLK_SWITCH_SWCTL);
+               clk_writel(val, PLLU_HW_PWRDN_CFG0);
+
+               val = clk_readl(XUSB_PLL_CFG0);
+               val &= ~XUSB_PLL_CFG0_PLLU_LOCK_DLY_MASK;
+               pll_writel_delay(val, XUSB_PLL_CFG0);
+
+               val = clk_readl(PLLU_HW_PWRDN_CFG0);
+               val |= PLLU_HW_PWRDN_CFG0_SEQ_ENABLE;
+               pll_writel_delay(val, PLLU_HW_PWRDN_CFG0);
+       }
+
+
+       /* Put UTMI PLL under h/w control  (if not already) */
+       val = clk_readl(UTMIPLL_HW_PWRDN_CFG0);
+       if (!(val & UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE))
+               tegra21_utmi_param_configure(c);
+}
+
+int tegra21_pllu_clk_enable(struct clk *c)
+{
+       int ret = tegra_pll_clk_enable(c);
+       if (ret)
+               return ret;
+
+       tegra21_pllu_hw_ctrl_set(c);
+       return 0;
+}
+
 static struct clk_ops tegra_pllu_vco_ops = {
        .init                   = tegra21_pllu_vco_init,
-       .enable                 = tegra_pll_clk_enable,
+       .enable                 = tegra21_pllu_clk_enable,
        .disable                = tegra_pll_clk_disable,
        .set_rate               = tegra_pll_clk_set_rate,
 };
@@ -3286,14 +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(u32 aux_reg)
+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;
+       p = c->inputs[2].input;
 #else
        aux_reg &= ~(PLLE_AUX_PLLRE_SEL | PLLE_AUX_PLLP_SEL);
+       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)
@@ -3323,9 +3510,6 @@ static void tegra21_plle_clk_init(struct clk *c)
                if (c->state == ON) {
                        WARN(1, "%s: pll_e is left enabled with %s input\n",
                             __func__, c->parent->name);
-               } else {
-                       c->parent = ref;
-                       select_pll_e_input(val);
                }
        }
 }
@@ -3343,16 +3527,6 @@ static void tegra21_plle_clk_disable(struct clk *c)
        val = clk_readl(c->reg + c->u.pll.misc0);
        val |= PLLE_MISC_IDDQ_SW_CTRL | PLLE_MISC_IDDQ_SW_VALUE;
        pll_writel_delay(val, c->reg + c->u.pll.misc0);
-
-/* FIXME: Disable for initial Si bringup */
-#if 0
-       /* Set XUSB PLL pad pwr override and iddq */
-       val = xusb_padctl_readl(XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0);
-       val |= XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0_PLL_PWR_OVRD;
-       val |= XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0_PLL_IDDQ;
-       xusb_padctl_writel(val, XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0);
-       xusb_padctl_readl(XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0);
-#endif
 }
 
 static int tegra21_plle_clk_enable(struct clk *c)
@@ -3369,6 +3543,10 @@ static int tegra21_plle_clk_enable(struct clk *c)
                return 0;
        }
 
+       /* Fixed per prod settings input */
+       select_pll_e_input(c);
+       input_rate = clk_get_rate(c->parent);
+
        /* PLLE config must be tabulated */
        for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) {
                if (sel->input_rate == input_rate && sel->output_rate == rate)
@@ -3438,42 +3616,15 @@ static int tegra21_plle_clk_enable(struct clk *c)
        clk_writel(val, c->reg + c->u.pll.misc0);
 
        val = clk_readl(PLLE_AUX);
-       val |= PLLE_AUX_USE_LOCKDET;
-       val &= ~PLLE_AUX_ENABLE_SWCTL;
+       val |= PLLE_AUX_USE_LOCKDET | PLLE_AUX_SS_SEQ_INCLUDE;
+       val &= ~(PLLE_AUX_ENABLE_SWCTL | PLLE_AUX_SS_SWCTL);
        pll_writel_delay(val, PLLE_AUX);
        val |= PLLE_AUX_SEQ_ENABLE;
        pll_writel_delay(val, PLLE_AUX);
 #endif
-
-/* FIXME: Disable for initial Si bringup */
-#if 0
-       /* clear XUSB PLL pad pwr override and iddq */
-       val = xusb_padctl_readl(XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0);
-       val &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0_PLL_PWR_OVRD;
-       val &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0_PLL_IDDQ;
-       xusb_padctl_writel(val, XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0);
-       xusb_padctl_readl(XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0);
-#endif
-
-       /* enable hw control of xusb brick pll */
-       usb_plls_hw_control_enable(XUSBIO_PLL_CFG0);
-
        return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static void tegra21_plle_clk_resume(struct clk *c)
-{
-       u32 val = clk_readl(c->reg);
-       if (val & PLLE_BASE_ENABLE)
-               return;         /* already resumed */
-
-       /* Restore parent */
-       val = clk_readl(PLLE_AUX);
-       select_pll_e_input(val);
-}
-#endif
-
 static struct clk_ops tegra_plle_ops = {
        .init                   = tegra21_plle_clk_init,
        .enable                 = tegra21_plle_clk_enable,
@@ -3630,35 +3781,6 @@ static struct clk_ops tegra_pll_out_fixed_ops = {
        .enable                 = tegra_pll_out_clk_enable,
 };
 
-static void tegra21_pllu_hw_ctrl_set(struct clk *c)
-{
-       u32 val = clk_readl(c->reg);
-
-       /* Put UTMI PLL under h/w control */
-       tegra21_utmi_param_configure(c);
-
-       /* Put PLLU under h/w control */
-       usb_plls_hw_control_enable(PLLU_HW_PWRDN_CFG0);
-
-       if (val & PLLU_BASE_OVERRIDE) {
-               val &= ~PLLU_BASE_OVERRIDE;
-               pll_writel_delay(val, c->reg);
-       } else {
-               /* FIXME: should it be WARN() ? */
-               pr_info("%s: boot with h/w control already set\n", c->name);
-       }
-
-/* FIXME: Disable for initial Si bringup */
-#if 0
-       /* Set XUSB PLL pad pwr override and iddq */
-       val = xusb_padctl_readl(XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0);
-       val |= XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0_PLL_PWR_OVRD;
-       val |= XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0_PLL_IDDQ;
-       xusb_padctl_writel(val, XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0);
-       xusb_padctl_readl(XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0);
-#endif
-}
-
 static void tegra21_pllu_out_clk_init(struct clk *c)
 {
        u32 p, val;
@@ -3687,9 +3809,6 @@ static void tegra21_pllu_out_clk_init(struct clk *c)
                /* Complete PLLU output s/w controlled initialization */
                tegra_pll_out_clk_init(c);
        }
-
-       /* Put USB plls under h/w control */
-       tegra21_pllu_hw_ctrl_set(pll);
 }
 
 static struct clk_ops tegra_pllu_out_ops = {
@@ -3757,7 +3876,8 @@ static void tegra21_pll_div_clk_init(struct clk *c)
 {
        if (c->flags & DIV_U71) {
                u32 val, divu71;
-               if (c->parent->state == OFF)
+               if ((c->parent->state == OFF) || (!c->parent->ops->disable &&
+                    (c->parent->parent->state == OFF)))
                        c->ops->disable(c);
 
                val = clk_readl(c->reg);
@@ -3952,6 +4072,36 @@ static inline u32 periph_clk_source_shift(struct clk *c)
                return 29;
 }
 
+static void periph_clk_state_init(struct clk *c)
+{
+       if (c->flags & PERIPH_NO_ENB) {
+               c->state = c->parent->state;
+               return;
+       }
+
+       c->state = ON;
+
+       if (!(clk_readl(PERIPH_CLK_TO_ENB_REG(c)) & PERIPH_CLK_TO_BIT(c)))
+               c->state = OFF;
+       if (!(c->flags & PERIPH_NO_RESET))
+               if (clk_readl(PERIPH_CLK_TO_RST_REG(c)) & PERIPH_CLK_TO_BIT(c))
+                       c->state = OFF;
+}
+
+static bool periph_clk_can_force_safe_rate(struct clk *c)
+{
+       /*
+        * As a general rule, force safe rate always for clocks supplied
+        * to peripherals under reset. If clock does not have associated reset
+        * at all, force safe rate if clock is disabled (can do it on Tegra21
+        * that allow to change dividers of the disabled clocks).
+        */
+       if (c->flags & PERIPH_NO_RESET)
+                       return c->state == OFF;
+
+       return clk_readl(PERIPH_CLK_TO_RST_REG(c)) & PERIPH_CLK_TO_BIT(c);
+}
+
 static void tegra21_periph_clk_init(struct clk *c)
 {
        u32 val = clk_readl(c->reg);
@@ -3967,21 +4117,9 @@ static void tegra21_periph_clk_init(struct clk *c)
 
                c->parent = mux->input;
        } else {
-               if (c->flags & PLLU) {
-                       /* for xusb_hs clock enforce SS div2 source */
-                       val &= ~periph_clk_source_mask(c);
-                       clk_writel_delay(val, c->reg);
-               }
                c->parent = c->inputs[0].input;
        }
 
-       /* if peripheral is left under reset - enforce safe rate */
-       if (!(c->flags & PERIPH_NO_RESET) &&
-           (clk_readl(PERIPH_CLK_TO_RST_REG(c)) & PERIPH_CLK_TO_BIT(c))) {
-               tegra_periph_clk_safe_rate_init(c);
-               val = clk_readl(c->reg);
-       }
-
        if (c->flags & DIV_U71) {
                u32 divu71 = val & PERIPH_CLK_SOURCE_DIVU71_MASK;
                if (c->flags & DIV_U71_IDLE) {
@@ -4010,18 +4148,11 @@ static void tegra21_periph_clk_init(struct clk *c)
                c->mul = 1;
        }
 
-       if (c->flags & PERIPH_NO_ENB) {
-               c->state = c->parent->state;
-               return;
-       }
+       periph_clk_state_init(c);
 
-       c->state = ON;
-
-       if (!(clk_readl(PERIPH_CLK_TO_ENB_REG(c)) & PERIPH_CLK_TO_BIT(c)))
-               c->state = OFF;
-       if (!(c->flags & PERIPH_NO_RESET))
-               if (clk_readl(PERIPH_CLK_TO_RST_REG(c)) & PERIPH_CLK_TO_BIT(c))
-                       c->state = OFF;
+       /* if peripheral is left under reset - enforce safe rate */
+       if (periph_clk_can_force_safe_rate(c))
+               tegra_periph_clk_safe_rate_init(c);
 }
 
 static int tegra21_periph_clk_enable(struct clk *c)
@@ -4040,15 +4171,13 @@ static int tegra21_periph_clk_enable(struct clk *c)
                return 0;
        }
 
-       /* FIXME: WAR for HW bug 1438604 */
-       if (!(tegra_platform_is_linsim() &&
-               (!strcmp(c->name, "nvjpg") || !strcmp(c->name, "nvdec"))))
-               clk_writel_delay(PERIPH_CLK_TO_BIT(c), PERIPH_CLK_TO_ENB_SET_REG(c));
+       clk_writel_delay(PERIPH_CLK_TO_BIT(c), PERIPH_CLK_TO_ENB_SET_REG(c));
 
        if (!(c->flags & PERIPH_NO_RESET) && !(c->flags & PERIPH_MANUAL_RESET)) {
                if (clk_readl(PERIPH_CLK_TO_RST_REG(c)) & PERIPH_CLK_TO_BIT(c)) {
                        udelay(RESET_PROPAGATION_DELAY);
-                       clk_writel(PERIPH_CLK_TO_BIT(c), PERIPH_CLK_TO_RST_CLR_REG(c));
+                       clk_writel_delay(PERIPH_CLK_TO_BIT(c),
+                                        PERIPH_CLK_TO_RST_CLR_REG(c));
                }
        }
        spin_unlock_irqrestore(&periph_refcount_lock, flags);
@@ -4075,11 +4204,8 @@ static void tegra21_periph_clk_disable(struct clk *c)
                if (c->flags & PERIPH_ON_APB)
                        val = chipid_readl();
 
-               /* FIXME: WAR for HW bug 1438604 */
-               if (!(tegra_platform_is_linsim() &&
-                       (!strcmp(c->name, "nvjpg") || !strcmp(c->name, "nvdec"))))
-                       clk_writel_delay(
-                               PERIPH_CLK_TO_BIT(c), PERIPH_CLK_TO_ENB_CLR_REG(c));
+               clk_writel_delay(PERIPH_CLK_TO_BIT(c),
+                                PERIPH_CLK_TO_ENB_CLR_REG(c));
        }
        spin_unlock_irqrestore(&periph_refcount_lock, flags);
 }
@@ -4090,9 +4216,6 @@ static void tegra21_periph_clk_reset(struct clk *c, bool assert)
        pr_debug("%s %s on clock %s\n", __func__,
                 assert ? "assert" : "deassert", c->name);
 
-       if (c->flags & PERIPH_NO_ENB)
-               return;
-
        if (!(c->flags & PERIPH_NO_RESET)) {
                if (assert) {
                        /* If peripheral is in the APB bus then read the APB
@@ -4102,11 +4225,11 @@ static void tegra21_periph_clk_reset(struct clk *c, bool assert)
                        if (c->flags & PERIPH_ON_APB)
                                val = chipid_readl();
 
-                       clk_writel(PERIPH_CLK_TO_BIT(c),
-                                  PERIPH_CLK_TO_RST_SET_REG(c));
+                       clk_writel_delay(PERIPH_CLK_TO_BIT(c),
+                                        PERIPH_CLK_TO_RST_SET_REG(c));
                } else
-                       clk_writel(PERIPH_CLK_TO_BIT(c),
-                                  PERIPH_CLK_TO_RST_CLR_REG(c));
+                       clk_writel_delay(PERIPH_CLK_TO_BIT(c),
+                                        PERIPH_CLK_TO_RST_CLR_REG(c));
        }
 }
 
@@ -4126,12 +4249,12 @@ static int tegra21_periph_clk_set_parent(struct clk *c, struct clk *p)
                        val |= (sel->value << periph_clk_source_shift(c));
 
                        if (c->refcnt)
-                               clk_enable(p);
+                               tegra_clk_prepare_enable(p);
 
                        clk_writel_delay(val, c->reg);
 
                        if (c->refcnt && c->parent)
-                               clk_disable(c->parent);
+                               tegra_clk_disable_unprepare(c->parent);
 
                        clk_reparent(c, p);
                        return 0;
@@ -4239,8 +4362,6 @@ static struct clk_ops tegra_periph_clk_ops = {
 /* Supper skipper ops */
 static void tegra21_clk_super_skip_init(struct clk *c)
 {
-       u32 val = clk_readl(c->reg);
-
        if (!c->parent)
                c->parent = c - 1;
        c->parent->skipper = c;
@@ -4249,15 +4370,10 @@ static void tegra21_clk_super_skip_init(struct clk *c)
        c->state = ON;
        c->max_rate = c->parent->max_rate;
 
-       if (val & SUPER_SKIPPER_ENABLE) {
-               c->div = ((val & SUPER_SKIPPER_DIV_MASK) >>
-                         SUPER_SKIPPER_DIV_SHIFT) + 1;
-               c->mul = ((val & SUPER_SKIPPER_MUL_MASK) >>
-                         SUPER_SKIPPER_MUL_SHIFT) + 1;
-       } else {
-               c->div = 1;
-               c->mul = 1;
-       }
+       /* Always set initial 1:1 ratio */
+       clk_writel(0, c->reg);
+       c->div = 1;
+       c->mul = 1;
 }
 
 static int tegra21_clk_super_skip_enable(struct clk *c)
@@ -4301,8 +4417,13 @@ static int tegra21_clk_super_skip_set_rate(struct clk *c, unsigned long rate)
                c->mul = 1;
        }
 
-       /* FIXME: for SCLK c->reg, this write to be replaced with IPC to BPMP */
-       clk_writel(val, c->reg);
+#ifdef CONFIG_TEGRA_BPMP_SCLK_SKIP
+       /* For SCLK do not touch the register directly - send IPC to BPMP */
+       if (c->flags & DIV_BUS)
+               tegra_bpmp_sclk_skip_set_rate(input_rate, rate);
+       else
+#endif
+               clk_writel(val, c->reg);
 
        clk_unlock_restore(c->parent, &flags);
        return 0;
@@ -4546,8 +4667,8 @@ static int tegra21_sor_brick_set_parent(struct clk *c, struct clk *p)
        for (sel = c->inputs; sel->input != NULL; sel++) {
                if (sel->input == p) {
                        if (c->refcnt) {
-                               clk_enable(p);
-                               clk_disable(c->parent);
+                               tegra_clk_prepare_enable(p);
+                               tegra_clk_disable_unprepare(c->parent);
                        }
                        clk_reparent(c, p);
                        return 0;
@@ -4607,7 +4728,7 @@ static int tegra21_sor1_clk_set_parent(struct clk *c, struct clk *p)
        for (sel = c->inputs; sel->input != NULL; sel++) {
                if (sel->input == p) {
                        if (c->refcnt)
-                               clk_enable(p);
+                               tegra_clk_prepare_enable(p);
                        /*
                         * Since sor1 output mux control setting share the same
                         * register with source mux/divider switch, use switch
@@ -4621,7 +4742,7 @@ static int tegra21_sor1_clk_set_parent(struct clk *c, struct clk *p)
                        clk_unlock_restore(src, &flags);
 
                        if (c->refcnt)
-                               clk_disable(c->parent);
+                               tegra_clk_disable_unprepare(c->parent);
 
                        clk_reparent(c, p);
                        return 0;
@@ -4691,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)
 {
@@ -4737,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)
@@ -4771,6 +5125,7 @@ static int tegra21_clk_out_enable(struct clk *c)
        val = pmc_readl(c->reg);
        val |= (0x1 << c->u.periph.clk_num);
        pmc_writel(val, c->reg);
+       pmc_readl(c->reg);
        spin_unlock_irqrestore(&clk_out_lock, flags);
 
        return 0;
@@ -4787,6 +5142,7 @@ static void tegra21_clk_out_disable(struct clk *c)
        val = pmc_readl(c->reg);
        val &= ~(0x1 << c->u.periph.clk_num);
        pmc_writel(val, c->reg);
+       pmc_readl(c->reg);
        spin_unlock_irqrestore(&clk_out_lock, flags);
 }
 
@@ -4801,17 +5157,18 @@ static int tegra21_clk_out_set_parent(struct clk *c, struct clk *p)
        for (sel = c->inputs; sel->input != NULL; sel++) {
                if (sel->input == p) {
                        if (c->refcnt)
-                               clk_enable(p);
+                               tegra_clk_prepare_enable(p);
 
                        spin_lock_irqsave(&clk_out_lock, flags);
                        val = pmc_readl(c->reg);
                        val &= ~periph_clk_source_mask(c);
                        val |= (sel->value << periph_clk_source_shift(c));
                        pmc_writel(val, c->reg);
+                       pmc_readl(c->reg);
                        spin_unlock_irqrestore(&clk_out_lock, flags);
 
                        if (c->refcnt && c->parent)
-                               clk_disable(c->parent);
+                               tegra_clk_disable_unprepare(c->parent);
 
                        clk_reparent(c, p);
                        return 0;
@@ -4883,7 +5240,7 @@ static int tegra21_emc_clk_set_rate(struct clk *c, unsigned long rate)
                if (div_value == c->div)
                        return 0;
        } else if (c->refcnt)
-               clk_enable(p);
+               tegra_clk_prepare_enable(p);
 
        ret = tegra_emc_set_rate_on_parent(rate, p);
        if (ret < 0)
@@ -4891,7 +5248,7 @@ static int tegra21_emc_clk_set_rate(struct clk *c, unsigned long rate)
 
        if (p != c->parent) {
                if(c->refcnt && c->parent)
-                       clk_disable(c->parent);
+                       tegra_clk_disable_unprepare(c->parent);
                clk_reparent(c, p);
        }
        c->div = div_value;
@@ -4943,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);
@@ -5039,12 +5412,12 @@ static int tegra21_audio_sync_clk_set_parent(struct clk *c, struct clk *p)
                        val |= sel->value;
 
                        if (c->refcnt)
-                               clk_enable(p);
+                               tegra_clk_prepare_enable(p);
 
                        clk_writel(val, c->reg);
 
                        if (c->refcnt && c->parent)
-                               clk_disable(c->parent);
+                               tegra_clk_disable_unprepare(c->parent);
 
                        clk_reparent(c, p);
                        return 0;
@@ -5070,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 = {
@@ -5089,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
@@ -5114,7 +5499,6 @@ static long tegra21_clk_cbus_round_updown(struct clk *c, unsigned long rate,
                                          bool up)
 {
        int i;
-       const int *millivolts;
 
        if (!c->dvfs) {
                if (!c->min_rate)
@@ -5136,12 +5520,9 @@ static long tegra21_clk_cbus_round_updown(struct clk *c, unsigned long rate,
        }
        rate = max(rate, c->min_rate);
 
-       millivolts = tegra_dvfs_get_millivolts_pll(c->dvfs);
        for (i = 0; ; i++) {
                unsigned long f = c->dvfs->freqs[i];
-               int mv = millivolts[i];
-               if ((f >= rate) || (mv >= c->dvfs->max_millivolts) ||
-                   ((i + 1) >=  c->dvfs->num_freqs)) {
+               if ((f >= rate) || ((i + 1) >=  c->dvfs->num_freqs)) {
                        if (!up && i && (f > rate))
                                i--;
                        break;
@@ -5220,7 +5601,7 @@ static int cbus_dvfs_set_rate(struct clk *c, unsigned long rate)
                        u.shared_bus_user.node) {
                struct clk *client =  user->u.shared_bus_user.client;
                if (client && client->refcnt && (client->parent == c->parent)) {
-                       ret = tegra_dvfs_set_rate(c, rate);
+                       ret = tegra_dvfs_set_rate(client, rate);
                        if (ret)
                                return ret;
                }
@@ -5245,6 +5626,9 @@ static void cbus_skip(struct clk *c, unsigned long bus_rate)
        struct clk *user;
        unsigned long rate;
 
+       if (!(c->shared_bus_flags & SHARED_BUS_USE_SKIPPERS))
+               return;
+
        list_for_each_entry(user, &c->shared_bus_list,
                        u.shared_bus_user.node) {
                struct clk *client = user->u.shared_bus_user.client;
@@ -5283,14 +5667,14 @@ static int tegra21_clk_cbus_set_rate(struct clk *c, unsigned long rate)
        if (rate == 0)
                return 0;
 
-       ret = clk_enable(c->parent);
+       ret = tegra_clk_prepare_enable(c->parent);
        if (ret) {
                pr_err("%s: failed to enable %s clock: %d\n",
                       __func__, c->name, ret);
                return ret;
        }
 
-       dramp = tegra21_is_dyn_ramp(c->parent, rate * c->div, false);
+       dramp = tegra_pll_can_ramp_to_rate(c->parent, rate * c->div);
        if (!dramp) {
                c->shared_bus_backup.value = get_next_backup_div(c, rate);
                ret = cbus_backup(c);
@@ -5315,16 +5699,16 @@ static int tegra21_clk_cbus_set_rate(struct clk *c, unsigned long rate)
        cbus_skip(c, rate);
 
 out:
-       clk_disable(c->parent);
+       tegra_clk_disable_unprepare(c->parent);
        return ret;
 }
 
 static inline void cbus_move_enabled_user(
        struct clk *user, struct clk *dst, struct clk *src)
 {
-       clk_enable(dst);
+       tegra_clk_prepare_enable(dst);
        list_move_tail(&user->u.shared_bus_user.node, &dst->shared_bus_list);
-       clk_disable(src);
+       tegra_clk_disable_unprepare(src);
        clk_reparent(user, dst);
 }
 
@@ -5678,7 +6062,7 @@ static int tegra_clk_shared_bus_user_set_parent(struct clk *c, struct clk *p)
                return -EINVAL;
 
        if (c->refcnt)
-               clk_enable(p);
+               tegra_clk_prepare_enable(p);
 
        list_move_tail(&c->u.shared_bus_user.node, &p->shared_bus_list);
        ret = tegra_clk_shared_bus_update(p);
@@ -5686,14 +6070,14 @@ static int tegra_clk_shared_bus_user_set_parent(struct clk *c, struct clk *p)
                list_move_tail(&c->u.shared_bus_user.node,
                               &c->parent->shared_bus_list);
                tegra_clk_shared_bus_update(c->parent);
-               clk_disable(p);
+               tegra_clk_disable_unprepare(p);
                return ret;
        }
 
        tegra_clk_shared_bus_update(c->parent);
 
        if (c->refcnt)
-               clk_disable(c->parent);
+               tegra_clk_disable_unprepare(c->parent);
 
        clk_reparent(c, p);
 
@@ -5731,8 +6115,10 @@ static long tegra_clk_shared_bus_user_round_rate(
                        rate = c->parent->max_rate;
                } else {
                        /* Skippers allow to run below bus minimum */
+                       bool use_skip = c->parent->shared_bus_flags &
+                               SHARED_BUS_USE_SKIPPERS;
                        struct clk *client = c->u.shared_bus_user.client;
-                       int skip = (client && client->skipper) ?
+                       int skip = (use_skip && client && client->skipper) ?
                                SUPER_SKIPPER_TERM_SIZE : 0;
                        unsigned long min_rate = c->parent->min_rate >> skip;
 
@@ -5752,7 +6138,7 @@ static int tegra_clk_shared_bus_user_enable(struct clk *c)
        c->u.shared_bus_user.enabled = true;
        ret = tegra_clk_shared_bus_update_locked(c->parent);
        if (!ret && c->u.shared_bus_user.client)
-               ret = clk_enable(c->u.shared_bus_user.client);
+               ret = tegra_clk_prepare_enable(c->u.shared_bus_user.client);
        clk_unlock_restore(c->parent, &flags);
 
        if (!ret && c->cross_clk_mutex && clk_cansleep(c))
@@ -5767,7 +6153,7 @@ static void tegra_clk_shared_bus_user_disable(struct clk *c)
 
        clk_lock_save(c->parent, &flags);
        if (c->u.shared_bus_user.client)
-               clk_disable(c->u.shared_bus_user.client);
+               tegra_clk_disable_unprepare(c->u.shared_bus_user.client);
        c->u.shared_bus_user.enabled = false;
        tegra_clk_shared_bus_update_locked(c->parent);
        clk_unlock_restore(c->parent, &flags);
@@ -5843,13 +6229,13 @@ static int tegra21_clk_coupled_gate_enable(struct clk *c)
                if (sel->input == c->parent)
                        continue;
 
-               ret = clk_enable(sel->input);
+               ret = tegra_clk_prepare_enable(sel->input);
                if (ret) {
                        while (sel != c->inputs) {
                                sel--;
                                if (sel->input == c->parent)
                                        continue;
-                               clk_disable(sel->input);
+                               tegra_clk_disable_unprepare(sel->input);
                        }
                        return ret;
                }
@@ -5875,7 +6261,7 @@ static void tegra21_clk_coupled_gate_disable(struct clk *c)
                        continue;
 
                if (sel->input->set)    /* enforce coupling after boot only */
-                       clk_disable(sel->input);
+                       tegra_clk_disable_unprepare(sel->input);
        }
 }
 
@@ -6146,16 +6532,16 @@ static struct clk tegra_pll_a1 = {
 };
 
 static struct clk_pll_freq_table tegra_pll_a_freq_table[] = {
-       { 12000000, 282240000, 46, 1, 2, 1, 4424},      /* actual: 282240234 */
-       { 12000000, 368640000, 60, 1, 2, 1, 7701},      /* actual: 368640381 */
+       { 12000000, 282240000, 47, 1, 2, 1, 0xf148},    /* actual: 282240234 */
+       { 12000000, 368640000, 61, 1, 2, 1, 0xfe15},    /* actual: 368640381 */
        { 12000000, 240000000, 60, 1, 3, 1, },
 
-       { 13000000, 282240000, 42, 1, 2, 1, 7549},      /* actual: 282239807 */
-       { 13000000, 368640000, 55, 1, 2, 1, 9944},      /* actual: 368640137 */
+       { 13000000, 282240000, 43, 1, 2, 1, 0xfd7d},    /* actual: 282239807 */
+       { 13000000, 368640000, 56, 1, 2, 1, 0x06d8},    /* actual: 368640137 */
        { 13000000, 240000000, 55, 1, 3, 1, },          /* actual: 238.3 MHz */
 
-       { 38400000, 282240000, 43, 3, 2, 1, 4915},      /* actual: 282239844 */
-       { 38400000, 368640000, 56, 3, 2, 1, 9011},      /* actual: 368639844 */
+       { 38400000, 282240000, 44, 3, 2, 1, 0xf333},    /* actual: 282239844 */
+       { 38400000, 368640000, 57, 3, 2, 1, 0x0333},    /* actual: 368639844 */
        { 38400000, 240000000, 75, 3, 4, 1,},
        { 0, 0, 0, 0, 0, 0 },
 };
@@ -6219,13 +6605,13 @@ 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[] = {
        { 12000000, 594000000,  99, 1, 2},
-       { 13000000, 594000000,  90, 1, 2, 0, 7247},     /* actual: 594000183 */
-       { 38400000, 594000000,  91, 3, 2, 0, 10752},
+       { 13000000, 594000000,  91, 1, 2, 0, 0xfc4f},   /* actual: 594000183 */
+       { 38400000, 594000000,  92, 3, 2, 0, 0x0a00},
        { 0, 0, 0, 0, 0, 0 },
 };
 
@@ -6291,8 +6677,8 @@ static struct clk tegra_pll_d_out0 = {
 
 static struct clk_pll_freq_table tegra_pll_d2_freq_table[] = {
        { 12000000, 594000000,  99, 1, 2},
-       { 13000000, 594000000,  90, 1, 2, 0, 7247},     /* actual: 594000183 */
-       { 38400000, 594000000,  91, 3, 2, 0, 10752},
+       { 13000000, 594000000,  91, 1, 2, 0, 0xfc4f},   /* actual: 594000183 */
+       { 38400000, 594000000,  92, 3, 2, 0, 0x0a00},
        { 0, 0, 0, 0, 0, 0 },
 };
 
@@ -6353,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 },
 };
 
@@ -6614,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 },
 };
 
@@ -6737,6 +7133,11 @@ static struct clk tegra_pll_p = {
        },
 };
 
+static struct clk_mux_sel mux_clk_osc[] = {
+       { .input = &tegra_clk_osc, .value = 0},
+       { 0, 0},
+};
+
 static struct clk_mux_sel mux_pllp[] = {
        { .input = &tegra_pll_p, .value = 0},
        { 0, 0},
@@ -6853,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,
@@ -6967,12 +7368,21 @@ static struct clk_pll_freq_table tegra_pll_e_freq_table[] = {
        { 0, 0, 0, 0, 0, 0 },
 };
 
+static struct clk_mux_sel mux_pll_e_inputs[] = {
+       { .input = &tegra_pll_ref,      .value = 0},
+       { .input = &tegra_pll_p,        .value = 1},
+       { .input = &tegra_pll_re_vco,   .value = 2},
+       { .input = &tegra_pll_re_vco,   .value = 3},
+       { 0, 0},
+};
+
 static struct clk tegra_pll_e = {
        .name      = "pll_e",
        .flags     = PLL_FIXED,
        .ops       = &tegra_plle_ops,
        .reg       = 0xe8,
        .max_rate  = 100000000,
+       .inputs    = mux_pll_e_inputs,
        .u.pll = {
                .input_min = 12000000,
                .input_max = 800000000,
@@ -7020,16 +7430,6 @@ static struct clk tegra_pciex_clk = {
        },
 };
 
-static struct clk tegra_pex_uphy_clk = {
-       .name      = "pex_uphy",
-       .parent    = &tegra_pll_e,
-       .ops       = &tegra_pciex_clk_ops,
-       .max_rate  = 500000000,
-       .u.periph  = {
-               .clk_num   = 205,
-       },
-};
-
 /* Audio sync clocks */
 #define SYNC_SOURCE(_id, _dev)                         \
        {                                               \
@@ -7043,7 +7443,7 @@ static struct clk tegra_pex_uphy_clk = {
                .ops       = &tegra_sync_source_ops     \
        }
 static struct clk tegra_sync_source_list[] = {
-       SYNC_SOURCE(spdif_in, tegra30-spdif),
+       SYNC_SOURCE(spdif_in, tegra210-spdif),
        SYNC_SOURCE(i2s0, tegra210-i2s.0),
        SYNC_SOURCE(i2s1, tegra210-i2s.1),
        SYNC_SOURCE(i2s2, tegra210-i2s.2),
@@ -7098,7 +7498,7 @@ static struct clk tegra_clk_audio_list[] = {
        AUDIO_SYNC_CLK(audio2, tegra210-i2s.2, 2),
        AUDIO_SYNC_CLK(audio3, tegra210-i2s.3, 3),
        AUDIO_SYNC_CLK(audio4, tegra210-i2s.4, 4),
-       AUDIO_SYNC_CLK(audio, tegra30-spdif, 5),        /* SPDIF */
+       AUDIO_SYNC_CLK(audio, tegra210-spdif, 5),       /* SPDIF */
 };
 
 #define AUDIO_SYNC_2X_CLK(_id, _dev, _index)                           \
@@ -7119,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, tegra30-spdif, 5),     /* SPDIF */
+       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},                                                        \
@@ -7140,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)           \
@@ -7157,15 +7560,15 @@ MUX_I2S_SPDIF(audio, 5);                /* SPDIF */
        }
 
 static struct clk tegra_clk_audio_dmic_list[] = {
-       AUDIO_SYNC_DMIC_CLK(audio0, tegra30-i2s.0, 0x560),
-       AUDIO_SYNC_DMIC_CLK(audio1, tegra30-i2s.1, 0x564),
-       AUDIO_SYNC_DMIC_CLK(audio2, tegra30-i2s.2, 0x6b8),
+       AUDIO_SYNC_DMIC_CLK(audio0, tegra210-i2s.0, 0x560),
+       AUDIO_SYNC_DMIC_CLK(audio1, tegra210-i2s.1, 0x564),
+       AUDIO_SYNC_DMIC_CLK(audio2, tegra210-i2s.2, 0x6b8),
 };
 
 #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},                                                        \
@@ -7265,12 +7668,13 @@ static struct clk_mux_sel mux_sclk[] = {
        { 0, 0},
 };
 
+/* ADSP cluster clocks */
 static struct clk_mux_sel mux_aclk_adsp[] = {
-       { .input = &tegra_pll_a1,       .value = 0},
        { .input = &tegra_pll_p_out_adsp, .value = 2},
        { .input = &tegra_pll_a_out0,   .value = 3},
        { .input = &tegra_clk_m,        .value = 6},
        { .input = &tegra_pll_a,        .value = 7},
+       { .input = &tegra_pll_a1,       .value = 8},
        { 0, 0},
 };
 
@@ -7278,17 +7682,20 @@ 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(val, reg);
+
+       clk_writel_delay(ADSP_INTF, reg);
+       udelay(50);
+       clk_writel_delay(val, reg);
 }
 
 static int tegra21_adsp_clk_enable(struct clk *c)
 {
        u32 val = ADSP_NEON | ADSP_CORE;
 
-       clk_writel(val, CLK_OUT_ENB_SET_Y);
+       clk_writel_delay(val, CLK_OUT_ENB_SET_Y);
        return 0;
 }
 
@@ -7296,29 +7703,63 @@ static void tegra21_adsp_clk_disable(struct clk *c)
 {
        u32 val = ADSP_NEON | ADSP_CORE;
 
-       clk_writel(val, CLK_OUT_ENB_CLR_Y);
+       clk_writel_delay(val, CLK_OUT_ENB_CLR_Y);
+}
+
+static void tegra21_adsp_clk_init(struct clk *c)
+{
+       /*
+        * Check/enforce ADSP clock default configuration:
+        * - parent clk_m
+        * - disabled
+        */
+       tegra21_super_clk_set_parent(c, &tegra_clk_m);
+       tegra21_super_clk_init(c);
+
+       /*
+        * CPU and system super clocks cannot be disabled, and super clock init
+        * always marks clock sate ON, which is not true for ADSP. Need explicit
+        * check here.
+        */
+       c->state = clk_readl(CLK_OUT_ENB_Y)&(ADSP_NEON | ADSP_CORE) ? ON : OFF;
+       if (c->state == ON) {
+               WARN(1, "Tegra ADSP clock is running on boot: turning Off\n");
+               tegra21_adsp_clk_disable(c);
+               c->state = OFF;
+       }
 }
 
 static struct clk_ops tegra_adsp_ops = {
-       .init           = tegra21_super_clk_init,
+       .init           = tegra21_adsp_clk_init,
        .enable         = tegra21_adsp_clk_enable,
        .disable        = tegra21_adsp_clk_disable,
        .set_parent     = tegra21_super_clk_set_parent,
-       .set_rate       = tegra21_super_clk_set_rate,
        .reset          = tegra21_adsp_clk_reset,
 };
 
-static struct raw_notifier_head adsp_rate_change_nh;
 static struct clk tegra_clk_aclk_adsp = {
        .name   = "adsp",
-       .flags  = DIV_U71 | DIV_U71_INT | MUX,
+       .flags  = DIV_U71 | DIV_U71_INT,
        .inputs = mux_aclk_adsp,
        .reg    = 0x6e0,
        .ops    = &tegra_adsp_ops,
-       .max_rate = 600000000UL,
-       .rate_change_nh = &adsp_rate_change_nh,
+       .max_rate = 1200000000,
 };
 
+static struct raw_notifier_head adsp_cpu_rate_change_nh;
+static struct clk tegra_clk_virtual_adsp_cpu = {
+       .name      = "adsp_cpu",
+       .parent    = &tegra_clk_aclk_adsp,
+       .ops       = &tegra_adsp_cpu_ops,
+       .max_rate  = 1000000000,
+       .u.cpu = {
+               .main      = &tegra_pll_a1,
+               .backup    = &tegra_pll_p_out_adsp,
+       },
+       .rate_change_nh = &adsp_cpu_rate_change_nh,
+};
+
+/* CPU clusters clocks */
 static struct clk tegra_clk_cclk_g = {
        .name   = "cclk_g",
        .flags  = DIV_U71 | DIV_U71_INT,
@@ -7376,12 +7817,13 @@ static struct clk tegra_clk_cpu_cmplx = {
        .max_rate  = 3000000000UL,
 };
 
+/* System bus clocks */
 static struct clk tegra_clk_sclk_mux = {
        .name   = "sclk_mux",
        .inputs = mux_sclk,
        .reg    = 0x28,
        .ops    = &tegra_super_ops,
-       .max_rate = 600000000,
+       .max_rate = 1200000000,
        .min_rate = 12000000,
 };
 
@@ -7402,6 +7844,7 @@ static struct clk tegra_clk_sclk_div = {
 
 static struct clk tegra_clk_sclk = {
        .name = "sclk",
+       .flags  = DIV_BUS,
        .ops = &tegra_clk_super_skip_ops,
        .reg = 0x2c,
        .parent = &tegra_clk_sclk_div,
@@ -7473,6 +7916,42 @@ static struct clk tegra_clk_blink = {
        .max_rate       = 32768,
 };
 
+static struct clk_ops tegra_xusb_padctl_ops = {
+       .reset    = tegra21_periph_clk_reset,
+};
+
+static struct clk tegra_clk_xusb_padctl = {
+       .name      = "xusb_padctl",
+       .ops       = &tegra_xusb_padctl_ops,
+       .u.periph  = {
+               .clk_num = 142,
+       },
+};
+
+static struct clk tegra_clk_sata_uphy = {
+       .name      = "sata_uphy",
+       .ops       = &tegra_xusb_padctl_ops,
+       .u.periph  = {
+               .clk_num = 204,
+       },
+};
+
+static struct clk tegra_pex_uphy_clk = {
+       .name      = "pex_uphy",
+       .ops       = &tegra_xusb_padctl_ops,
+       .u.periph  = {
+               .clk_num   = 205,
+       },
+};
+
+static struct clk tegra_clk_usb2_hsic_trk = {
+       .name      = "usb2_hsic_trk",
+       .flags     = DIV_U71 | PERIPH_NO_ENB | PERIPH_NO_RESET,
+       .inputs    = mux_clk_osc,
+       .reg       = 0x6cc,
+       .ops       = &tegra_periph_clk_ops,
+       .max_rate  = 38400000,
+};
 
 /* Multimedia modules muxes */
 static struct clk_mux_sel mux_pllc2_c_c3_pllp_plla1_clkm[] = {
@@ -7503,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},
 };
 
@@ -7522,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},
@@ -7651,6 +8130,14 @@ static struct clk_mux_sel mux_pllp_pllc_clkm[] = {
        { 0, 0},
 };
 
+static struct clk_mux_sel mux_pllp_pllc_plla_clkm[] = {
+       {.input = &tegra_pll_p,     .value = 0},
+       {.input = &tegra_pll_c,     .value = 2},
+       {.input = &tegra_pll_a_out0,     .value = 4},
+       {.input = &tegra_clk_m,     .value = 6},
+       { 0, 0},
+};
+
 static struct clk_mux_sel mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2[] = {
        {.input = &tegra_pll_p,     .value = 0},
        {.input = &tegra_pll_c,     .value = 2},
@@ -7661,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},
@@ -7680,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},
@@ -7689,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},
 };
 
@@ -7701,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},
 };
 
@@ -7806,6 +8309,11 @@ static struct clk_mux_sel mux_clk_32k[] = {
        { 0, 0},
 };
 
+static struct clk_mux_sel mux_clk_usb2_hsic_trk[] = {
+       { .input = &tegra_clk_usb2_hsic_trk, .value = 0},
+       { 0, 0},
+};
+
 static struct clk tegra_clk_mc;
 static struct clk_mux_sel mux_clk_mc[] = {
        { .input = &tegra_clk_mc, .value = 0},
@@ -7819,11 +8327,37 @@ 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,
        .reg = 0x19c,
-       .max_rate = 1066000000,
+       .max_rate = 1800000000,
        .min_rate = 12750000,
        .inputs = mux_pllm_pllc_pllp_clkm,
        .flags = MUX | DIV_U71 | PERIPH_EMC_ENB,
@@ -7860,7 +8394,7 @@ static struct clk tegra_clk_host1x = {
        .u.periph = {
                .clk_num   = 28,
                .pll_low = &tegra_pll_p,
-               .pll_high = &tegra_pll_c,
+               .pll_high = &tegra_pll_p,
        },
        .rate_change_nh = &host1x_rate_change_nh,
 };
@@ -7901,6 +8435,9 @@ static struct clk tegra_clk_c2bus = {
        .shared_bus_backup = {
                .input = &tegra_pll_p,
        },
+#ifdef CONFIG_TEGRA_CBUS_CAN_USE_SKIPPERS
+       .shared_bus_flags = SHARED_BUS_USE_SKIPPERS,
+#endif
        .rate_change_nh = &c2bus_rate_change_nh,
 };
 static struct clk tegra_clk_c3bus = {
@@ -7914,6 +8451,9 @@ static struct clk tegra_clk_c3bus = {
        .shared_bus_backup = {
                .input = &tegra_pll_p,
        },
+#ifdef CONFIG_TEGRA_CBUS_CAN_USE_SKIPPERS
+       .shared_bus_flags = SHARED_BUS_USE_SKIPPERS,
+#endif
        .rate_change_nh = &c3bus_rate_change_nh,
 };
 
@@ -7956,19 +8496,40 @@ static struct clk_ops tegra_clk_gpu_ops = {
        .reset          = &tegra21_periph_clk_reset,
 };
 
-/* This is a dummy clock for gpu. The enable/disable/reset routine controls
-   input clock of the actual gpu clock. The input clock itself has a fixed
-   frequency. The actual gpu clock's frequency is controlled by gpu driver,
-   not here in clock framework. However, we assoicate this dummy clock with
-   dvfs to control voltage of gpu rail along with frequency change of actual
-   gpu clock. So frequency here and in dvfs are based on the acutal gpu clock. */
-static struct clk tegra_clk_gpu = {
+/*
+ * This clock provides a common gate control for branches of different clocks
+ * supplied to GPU: mselect, memory controller, pll_p_out5, jtag and la. The
+ * mselect and mc clocks are always running; pll_p_out5 is explicitly controlled
+ * by GPU driver; jtag and la clocks are set by debug interface configuration.
+ * Therefore we don't need to propagate refcount to those clocks, and just set
+ * GPU gate clock as OSC child.
+ */
+static struct clk tegra_clk_gpu_gate = {
+       .name      = "gpu_gate",
+       .parent    = &tegra_clk_osc,
+       .ops       = &tegra_clk_gpu_ops,
+       .u.periph  = {
+               .clk_num = 184,
+       },
+       .flags     = PERIPH_MANUAL_RESET,
+       .max_rate  = 48000000,
+       .min_rate  = 12000000,
+};
+
+/*
+ * This is a reference clock for GPU. The enable/disable routine control input
+ * clock of the GPCPLL. The reference clock itself has a fixed frequency. The
+ * actual GPU clock's frequency is controlled via gbus, which is a child of this
+ * clock.
+ */
+static struct clk tegra_clk_gpu_ref = {
        .name      = "gpu_ref",
        .ops       = &tegra_clk_gpu_ops,
        .parent    = &tegra_pll_ref,
        .u.periph  = {
-               .clk_num = 184,
+               .clk_num = 189,
        },
+       .flags     = PERIPH_NO_RESET,
        .max_rate  = 48000000,
        .min_rate  = 12000000,
 };
@@ -8070,12 +8631,15 @@ static struct clk_ops tegra_clk_gbus_ops = {
        .shared_bus_update = tegra21_clk_shared_connector_update, /* re-use */
 };
 
+static struct raw_notifier_head gbus_rate_change_nh;
+
 static struct clk tegra_clk_gbus = {
        .name      = "gbus",
        .ops       = &tegra_clk_gbus_ops,
-       .parent    = &tegra_clk_gpu,
+       .parent    = &tegra_clk_gpu_ref,
        .max_rate  = 1300000000,
        .shared_bus_flags = SHARED_BUS_RETENTION,
+       .rate_change_nh = &gbus_rate_change_nh,
 };
 
 static void tegra21_camera_mclk_init(struct clk *c)
@@ -8089,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;
        }
 }
 
@@ -8122,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,
@@ -8307,105 +8903,107 @@ static DEFINE_MUTEX(sbus_cross_mutex);
 struct clk tegra_list_clks[] = {
        PERIPH_CLK("apbdma",    "tegra-apbdma",         NULL,   34,     0,      38400000,  mux_clk_m,                   0),
        PERIPH_CLK("rtc",       "rtc-tegra",            NULL,   4,      0,      32768,     mux_clk_32k,                 PERIPH_NO_RESET | PERIPH_ON_APB),
-       PERIPH_CLK("kbc",       "tegra-kbc",            NULL,   36,     0,      32768,     mux_clk_32k,                 PERIPH_NO_RESET | PERIPH_ON_APB),
        PERIPH_CLK("timer",     "timer",                NULL,   5,      0,      38400000,  mux_clk_m,                   0),
        PERIPH_CLK("spare1",    "spare1",               NULL,   192,    0,      38400000,  mux_clk_m,                   0),
        PERIPH_CLK("axiap",     "axiap",                NULL,   196,    0,      38400000,  mux_clk_m,                   0),
-       PERIPH_CLK("iqc1",      "iqc1",                 NULL,   221,    0,      38400000,  mux_clk_m,                   PERIPH_NO_RESET | PERIPH_ON_APB),
-       PERIPH_CLK("iqc2",      "iqc2",                 NULL,   220,    0,      38400000,  mux_clk_m,                   PERIPH_NO_RESET | PERIPH_ON_APB),
+       PERIPH_CLK("iqc1",      "tegra210-iqc.0",       NULL,   221,    0,      38400000,  mux_clk_m,                   PERIPH_NO_RESET | PERIPH_ON_APB),
+       PERIPH_CLK("iqc2",      "tegra210-iqc.1",       NULL,   220,    0,      38400000,  mux_clk_m,                   PERIPH_NO_RESET | PERIPH_ON_APB),
        PERIPH_CLK("kfuse",     "kfuse-tegra",          NULL,   40,     0,      38400000,  mux_clk_m,                   PERIPH_ON_APB),
-       PERIPH_CLK("fuse",      "fuse-tegra",           "fuse", 39,     0,      38400000,  mux_clk_m,                   PERIPH_ON_APB),
-       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_ON_APB),
-       PERIPH_CLK("i2s1",      "tegra210-i2s.1",       NULL,   11,     0x100,  204000000,  mux_pllaout0_audio1_2x_pllp_clkm,   MUX | DIV_U71 | PERIPH_ON_APB),
-       PERIPH_CLK("i2s2",      "tegra210-i2s.2",       NULL,   18,     0x104,  204000000,  mux_pllaout0_audio2_2x_pllp_clkm,   MUX | DIV_U71 | PERIPH_ON_APB),
-       PERIPH_CLK("i2s3",      "tegra210-i2s.3",       NULL,   101,    0x3bc,  204000000,  mux_pllaout0_audio3_2x_pllp_clkm,   MUX | DIV_U71 | PERIPH_ON_APB),
-       PERIPH_CLK("i2s4",      "tegra210-i2s.4",       NULL,   102,    0x3c0,  204000000,  mux_pllaout0_audio4_2x_pllp_clkm,   MUX | DIV_U71 | PERIPH_ON_APB),
-       PERIPH_CLK("spdif_out", "tegra30-spdif",        "spdif_out",    10,     0x108,   24576000, mux_pllaout0_audio_2x_pllp_clkm,     MUX | DIV_U71 | PERIPH_ON_APB),
-       PERIPH_CLK("spdif_in",  "tegra30-spdif",        "spdif_in",     10,     0x10c,  408000000, mux_pllp_pllc,               MUX | DIV_U71 | PERIPH_ON_APB),
-       PERIPH_CLK("dmic1",     "tegra30-i2s.0",        NULL,   161,    0x64c,  24576000, mux_pllaout0_audio0_dmic_pllp_clkm,   MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
-       PERIPH_CLK("dmic2",     "tegra30-i2s.1",        NULL,   162,    0x650,  24576000, mux_pllaout0_audio1_dmic_pllp_clkm,   MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
-       PERIPH_CLK("dmic3",     "tegra30-i2s.2",        NULL,   197,    0x6bc,  24576000, mux_pllaout0_audio2_dmic_pllp_clkm,   MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
+       PERIPH_CLK("fuse",      "fuse-tegra",         "fuse",   39,     0,      38400000,  mux_clk_m,                   PERIPH_ON_APB),
+       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_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_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),
-       D_AUDIO_CLK("d_audio",  "tegra210-axbar",               "ahub", 106,    0x3d0,  48000000,  mux_d_audio_clk,     MUX | DIV_U71 | PERIPH_ON_APB),
-       PERIPH_CLK("hda",       "tegra30-hda",          "hda",   125,   0x428,  108000000, mux_pllp_pllc_clkm,  MUX | DIV_U71 | PERIPH_ON_APB),
-       PERIPH_CLK("hda2codec_2x",      "tegra30-hda",  "hda2codec",   111,     0x3e4,  910000000,  mux_pllp_pllc_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("sbc1",      "spi-tegra114.0",       NULL,   41,     0x134, 204000000, mux_pllp_pllc_clkm,   MUX | DIV_U71 | PERIPH_ON_APB),
-       PERIPH_CLK("sbc2",      "spi-tegra114.1",       NULL,   44,     0x118, 204000000, mux_pllp_pllc_clkm,   MUX | DIV_U71 | PERIPH_ON_APB),
-       PERIPH_CLK("sbc3",      "spi-tegra114.2",       NULL,   46,     0x11c, 204000000, mux_pllp_pllc_clkm,   MUX | DIV_U71 | PERIPH_ON_APB),
-       PERIPH_CLK("sbc4",      "spi-tegra114.3",       NULL,   68,     0x1b4, 48000000, mux_pllp_pllc_clkm,    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",       "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_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("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_ddr",        "sdhci-tegra.0",        "ddr",  14,     0x150,  208000000, 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,  208000000, 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("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("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("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_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),
        PERIPH_CLK("bsea",      "nvavp",                "bsea", 62,     0,      250000000, mux_clk_m,                   0),
        PERIPH_CLK("bsev",      "tegra-aes",            "bsev", 63,     0,      250000000, mux_clk_m,                   0),
        PERIPH_CLK("cec",       "tegra_cec",            NULL,   136,    0,      250000000, mux_clk_m,                   PERIPH_ON_APB),
-       PERIPH_CLK("csite",     "csite",                NULL,   73,     0x1d4,  144000000, mux_pllp_pllc_clkm,  MUX | DIV_U71 | PERIPH_ON_APB),
-       PERIPH_CLK("la",        "la",                   NULL,   76,     0x1f8,  38400000,  mux_pllp_pllc_clkm,  MUX | DIV_U71 | PERIPH_ON_APB),
-       PERIPH_CLK("owr",       "tegra_w1",             NULL,   71,     0x1cc,  38400000,  mux_pllp_pllc_clkm,  MUX | DIV_U71 | PERIPH_ON_APB),
-       PERIPH_CLK("i2c1",      "tegra21-i2c.0",        "div-clk",      12,     0x124,  136000000, mux_pllp_clkm,       MUX | DIV_U16 | PERIPH_ON_APB),
-       PERIPH_CLK("i2c2",      "tegra21-i2c.1",        "div-clk",      54,     0x198,  136000000, mux_pllp_clkm,       MUX | DIV_U16 | PERIPH_ON_APB),
-       PERIPH_CLK("i2c3",      "tegra21-i2c.2",        "div-clk",      67,     0x1b8,  136000000, mux_pllp_clkm,       MUX | DIV_U16 | PERIPH_ON_APB),
-       PERIPH_CLK("i2c4",      "tegra21-i2c.3",        "div-clk",      103,    0x3c4,  136000000, mux_pllp_clkm,       MUX | DIV_U16 | PERIPH_ON_APB),
-       PERIPH_CLK("i2c5",      "tegra21-i2c.4",        "div-clk",      47,     0x128,  58300000,  mux_pllp_clkm,       MUX | DIV_U16 | PERIPH_ON_APB),
-       PERIPH_CLK("i2c6",      "tegra21-i2c.5",        "div-clk",      166,    0x65c,  58300000,  mux_pllp_clkm,       MUX | DIV_U16 | PERIPH_ON_APB),
+       PERIPH_CLK("csite",     "csite",                NULL,   73,     0x1d4,  144000000, mux_pllp_pllc_clkm,          MUX | DIV_U71 | PERIPH_ON_APB),
+       PERIPH_CLK("la",        "la",                   NULL,   76,     0x1f8,  38400000,  mux_pllp_pllc_clkm,          MUX | DIV_U71 | PERIPH_ON_APB),
+
+       PERIPH_CLK("owr",       "tegra_w1",             NULL,   71,     0x1cc,  38400000,  mux_pllp_pllc_clkm,          MUX | DIV_U71 | PERIPH_ON_APB),
+       PERIPH_CLK("i2c1",      "tegra21-i2c.0",   "div-clk",   12,     0x124,  136000000, mux_pllp_clkm,       MUX | DIV_U16 | PERIPH_ON_APB),
+       PERIPH_CLK("i2c2",      "tegra21-i2c.1",   "div-clk",   54,     0x198,  136000000, mux_pllp_clkm,       MUX | DIV_U16 | PERIPH_ON_APB),
+       PERIPH_CLK("i2c3",      "tegra21-i2c.2",   "div-clk",   67,     0x1b8,  136000000, mux_pllp_clkm,       MUX | DIV_U16 | PERIPH_ON_APB),
+       PERIPH_CLK("i2c4",      "tegra21-i2c.3",   "div-clk",   103,    0x3c4,  136000000, mux_pllp_clkm,       MUX | DIV_U16 | PERIPH_ON_APB),
+       PERIPH_CLK("i2c5",      "tegra21-i2c.4",   "div-clk",   47,     0x128,  136000000, mux_pllp_clkm,       MUX | DIV_U16 | PERIPH_ON_APB),
+       PERIPH_CLK("i2c6",      "tegra21-i2c.5",   "div-clk",   166,    0x65c,  136000000, mux_pllp_clkm,       MUX | DIV_U16 | PERIPH_ON_APB),
        PERIPH_CLK("mipibif",   "mipibif",              NULL,   173,    0x660,  408000000,  mux_pllp_clkm,      MUX | DIV_U71 | PERIPH_ON_APB),
        PERIPH_CLK("mipi-cal",  "mipi-cal",             NULL,   56,     0,      60000000,  mux_clk_m, PERIPH_ON_APB),
-       PERIPH_CLK("uarta",     "serial-tegra.0",               NULL,   6,      0x178,  800000000, mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB),
-       PERIPH_CLK("uartb",     "serial-tegra.1",               NULL,   7,      0x17c,  800000000, mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB),
-       PERIPH_CLK("uartc",     "serial-tegra.2",               NULL,   55,     0x1a0,  800000000, mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB),
-       PERIPH_CLK("uartd",     "serial-tegra.3",               NULL,   65,     0x1c0,  800000000, mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB),
-       PERIPH_CLK("uartape",   "uartape",              NULL,   212,    0x710,  50000000, mux_pllp_pllc_clkm,   MUX | DIV_U151 | DIV_U151_UART | PERIPH_NO_RESET | 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("vi_sensor",  NULL,                  "vi_sensor",    164,    0x1a8,  408000000, mux_pllc_pllp_plla,  MUX | DIV_U71 | PERIPH_NO_RESET),
-       PERIPH_CLK("vi_sensor2", NULL,                  "vi_sensor2",   165,    0x658,  408000000, mux_pllc_pllp_plla,  MUX | DIV_U71 | PERIPH_NO_RESET),
+       PERIPH_CLK("uarta",     "serial-tegra.0",       NULL,   6,      0x178,  800000000, mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB),
+       PERIPH_CLK("uartb",     "serial-tegra.1",       NULL,   7,      0x17c,  800000000, mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB),
+       PERIPH_CLK("uartc",     "serial-tegra.2",       NULL,   55,     0x1a0,  800000000, mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB),
+       PERIPH_CLK("uartd",     "serial-tegra.3",       NULL,   65,     0x1c0,  800000000, mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB),
+       PERIPH_CLK("uartape",   "uartape",              NULL,   212,    0x710,  50000000, mux_pllp_pllc_clkm,                                   MUX | DIV_U151 | DIV_U151_UART | PERIPH_NO_RESET | PERIPH_ON_APB),
+
+       PERIPH_CLK("vi_sensor",  NULL,          "vi_sensor",    164,    0x1a8,  408000000, mux_pllc_pllp_plla,          MUX | DIV_U71 | PERIPH_NO_RESET),
+       PERIPH_CLK("vi_sensor2", NULL,          "vi_sensor2",   165,    0x658,  408000000, mux_pllc_pllp_plla,          MUX | DIV_U71 | PERIPH_NO_RESET),
        PERIPH_CLK_EX("dtv",    "dtv",                  NULL,   79,     0x1dc,  250000000, mux_clk_m,                   PERIPH_ON_APB,  &tegra_dtv_clk_ops),
        PERIPH_CLK("disp1",     "tegradc.0",            NULL,   27,     0x138,  800000000, mux_pllp_plld_plld2_clkm,    MUX),
        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("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_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),
-       PERIPH_CLK("usb3",      "tegra-ehci.2",         NULL,   59,     0,      480000000, mux_clk_m,                   0),
-       PERIPH_CLK("hsic_trk",  "hsic_trk",             NULL,   209,    0x6cc,  38400000, mux_clk_m,                    PERIPH_NO_RESET),
-       PERIPH_CLK("usb2_trk",  "usb2_trk",             NULL,   210,    0x6cc,  38400000, mux_clk_m,                    PERIPH_NO_RESET),
-       PERIPH_CLK_EX("dsia",   "tegradc.0",            "dsia", 48,     0xd0,   500000000, mux_plld_out0,               PLLD,   &tegra_dsi_clk_ops),
-       PERIPH_CLK_EX("dsib",   "tegradc.1",            "dsib", 82,     0x4b8,  500000000, mux_plld_out0,               PLLD,   &tegra_dsi_clk_ops),
-       PERIPH_CLK("dsi1-fixed", "tegradc.0",           "dsi-fixed",    0,      0,      108000000, mux_pllp_out3,       PERIPH_NO_ENB),
-       PERIPH_CLK("dsi2-fixed", "tegradc.1",           "dsi-fixed",    0,      0,      108000000, mux_pllp_out3,       PERIPH_NO_ENB),
-       PERIPH_CLK("csi",       "vi",                   "csi",  52,     0,      480000000, mux_plld,                    PLLD),
-       PERIPH_CLK("ispa",      "isp",                  "ispa", 23,     0,      700000000, mux_isp,                     PERIPH_ON_APB),
-       PERIPH_CLK("ispb",      "isp",                  "ispb", 3,      0,      700000000, mux_isp,                     PERIPH_ON_APB),
-       PERIPH_CLK("csus",      "vi",                   "csus", 92,     0,      150000000, mux_clk_m,                   PERIPH_NO_RESET),
-       PERIPH_CLK("vim2_clk",  "vi",                   "vim2_clk",     171,    0,      150000000, mux_clk_m,           PERIPH_NO_RESET),
-       PERIPH_CLK("cilab",     "vi",                   "cilab", 144,   0x614,  102000000, mux_pllp_pllc_clkm,          MUX | DIV_U71),
-       PERIPH_CLK("cilcd",     "vi",                   "cilcd", 145,   0x618,  102000000, mux_pllp_pllc_clkm,          MUX | DIV_U71),
-       PERIPH_CLK("cile",      "vi",                   "cile",  146,   0x61c,  102000000, mux_pllp_pllc_clkm,          MUX | DIV_U71),
-       PERIPH_CLK("dsialp",    "tegradc.0",            "dsialp", 147,  0x620,  156000000, mux_pllp_pllc_clkm,          MUX | DIV_U71),
-       PERIPH_CLK("dsiblp",    "tegradc.1",            "dsiblp", 148,  0x624,  156000000, mux_pllp_pllc_clkm,          MUX | DIV_U71),
-       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("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_ON_APB),
+       PERIPH_CLK("usb3",      "tegra-ehci.2",         NULL,   59,     0,      480000000, mux_clk_m,                   PERIPH_NO_ENB | PERIPH_NO_RESET),
+       PERIPH_CLK("hsic_trk",  NULL,             "hsic_trk",   209,    0,      38400000, mux_clk_usb2_hsic_trk,        PERIPH_NO_RESET),
+       PERIPH_CLK("usb2_trk",  NULL,             "usb2_trk",   210,    0,      38400000, mux_clk_usb2_hsic_trk,        PERIPH_NO_RESET),
+
+       PERIPH_CLK_EX("dsia",   "tegradc.0",          "dsia",   48,     0xd0,  1500000000, mux_plld_out0,               PLLD,   &tegra_dsi_clk_ops),
+       PERIPH_CLK_EX("dsib",   "tegradc.1",          "dsib",   82,     0x4b8, 1500000000, mux_plld_out0,               PLLD,   &tegra_dsi_clk_ops),
+       PERIPH_CLK("dsi1-fixed", "tegradc.0",    "dsi-fixed",   0,      0,      108000000, mux_pllp_out3,               PERIPH_NO_ENB | PERIPH_NO_RESET),
+       PERIPH_CLK("dsi2-fixed", "tegradc.1",    "dsi-fixed",   0,      0,      108000000, mux_pllp_out3,               PERIPH_NO_ENB | PERIPH_NO_RESET),
+       PERIPH_CLK("csi",       "vi",                  "csi",   52,     0,     1000000000, mux_plld,                    PLLD),
+       PERIPH_CLK("csus",      "vi",                 "csus",   92,     0,      150000000, mux_clk_m,                   PERIPH_NO_RESET),
+       PERIPH_CLK("vim2_clk",  "vi",             "vim2_clk",   171,    0,      150000000, mux_clk_m,                   PERIPH_NO_RESET),
+       PERIPH_CLK("cilab",     "vi",                "cilab",   144,    0x614,  204000000, mux_pllp_pllc_clkm,          MUX | DIV_U71 | PERIPH_NO_RESET),
+       PERIPH_CLK("cilcd",     "vi",                "cilcd",   145,    0x618,  204000000, mux_pllp_pllc_clkm,          MUX | DIV_U71 | PERIPH_NO_RESET),
+       PERIPH_CLK("cile",      "vi",                 "cile",   146,    0x61c,  204000000, mux_pllp_pllc_clkm,          MUX | DIV_U71 | PERIPH_NO_RESET),
+       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_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),
        PERIPH_CLK("extern1",   "extern1",              NULL,   120,    0x3ec,  216000000, mux_plla_clk32_pllp_clkm_plle,       MUX | DIV_U71),
        PERIPH_CLK("extern2",   "extern2",              NULL,   121,    0x3f0,  216000000, mux_plla_clk32_pllp_clkm_plle,       MUX | DIV_U71),
@@ -8415,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),
@@ -8425,17 +9023,21 @@ struct clk tegra_list_clks[] = {
        PERIPH_CLK("mc_ccpa",   "mc_ccpa",              NULL,   201,    0,      1066000000, mux_clk_mc,                 PERIPH_NO_RESET),
        PERIPH_CLK("mc_cdpa",   "mc_cdpa",              NULL,   200,    0,      1066000000, mux_clk_mc,                 PERIPH_NO_RESET),
 
-       PERIPH_CLK_SKIP("vic03", "vic03",       NULL,   178,    0x678,  0x6f0,  500000000, mux_pllc_pllp_plla1_pllc2_c3_clkm,   MUX | DIV_U71),
-       PERIPH_CLK_SKIP("msenc", "msenc",       NULL,   219,    0x6a0,  0x6e8,  768000000, mux_pllc2_c_c3_pllp_plla1_clkm,      MUX | DIV_U71 | DIV_U71_INT),
-       PERIPH_CLK_SKIP("nvdec", "nvdec",       NULL,   194,    0x698,  0x6f4,  768000000, mux_pllc2_c_c3_pllp_plla1_clkm, MUX | DIV_U71 | DIV_U71_INT),
-       PERIPH_CLK_SKIP("nvjpg", "nvjpg",       NULL,   195,    0x69c,  0x700,  768000000, mux_pllc2_c_c3_pllp_plla1_clkm, MUX | DIV_U71 | DIV_U71_INT),
+       PERIPH_CLK_SKIP("vic03", "vic03",       NULL,   178,    0x678,  0x6f0,  700000000, mux_pllc_pllp_plla1_pllc2_c3_clkm,   MUX | DIV_U71),
+       PERIPH_CLK_SKIP("msenc", "msenc",       NULL,   219,    0x6a0,  0x6e8,  700000000, mux_pllc2_c_c3_pllp_plla1_clkm,      MUX | DIV_U71 | DIV_U71_INT),
+       PERIPH_CLK_SKIP("nvdec", "nvdec",       NULL,   194,    0x698,  0x6f4,  700000000, mux_pllc2_c_c3_pllp_plla1_clkm,      MUX | DIV_U71 | DIV_U71_INT),
+       PERIPH_CLK_SKIP("nvjpg", "nvjpg",       NULL,   195,    0x69c,  0x700,  700000000, mux_pllc2_c_c3_pllp_plla1_clkm,      MUX | DIV_U71 | DIV_U71_INT),
 #ifdef CONFIG_TEGRA_SE_ON_CBUS
-       PERIPH_CLK_SKIP("se",   "se",           NULL,   127,    0x42c,  0x704,  600000000, mux_pllp_pllc2_c_c3_clkm,    MUX | DIV_U71 | DIV_U71_INT | PERIPH_ON_APB),
+       PERIPH_CLK_SKIP("se",   "se",           NULL,   127,    0x42c,  0x704,  700000000, mux_pllp_pllc2_c_c3_clkm,    MUX | DIV_U71 | DIV_U71_INT | PERIPH_ON_APB),
 #else
-       PERIPH_CLK_SKIP("se",   "tegra21-se",   NULL,   127,    0x42c,  0x704,  600000000, mux_pllp_pllc2_c_c3_clkm,    MUX | DIV_U71 | DIV_U71_INT | PERIPH_ON_APB),
+       PERIPH_CLK_SKIP("se",   "tegra21-se",   NULL,   127,    0x42c,  0x704,  700000000, mux_pllp_pllc2_c_c3_clkm,    MUX | DIV_U71 | DIV_U71_INT | PERIPH_ON_APB),
 #endif
-       PERIPH_CLK("tsec",      "tegra_tsec",   "tsec", 83,     0x1f4,          408000000, mux_pllp_pllc_clkm,          MUX | DIV_U71 | DIV_U71_INT),
-       PERIPH_CLK_SKIP("tsecb", "tsecb",       NULL,   206,    0x6d8,  0x70c,  768000000, mux_pllp_pllc2_c_c3_clkm,    MUX | DIV_U71 | DIV_U71_INT),
+       PERIPH_CLK_SKIP("tsec", "tegra_tsec",   "tsec", 83,     0x1f4,  0x708,  408000000, mux_pllp_pllc_clkm,          MUX | DIV_U71 | DIV_U71_INT),
+       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_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),
        SHARED_CLK("bsea.sclk", "tegra-aes",            "sclk", &tegra_clk_sbus_cmplx, NULL, 0, 0),
@@ -8457,6 +9059,7 @@ struct clk tegra_list_clks[] = {
        SHARED_SCLK("sbc2.sclk", "tegra12-spi.1",       "sclk", &tegra_clk_apb,        NULL, 0, 0),
        SHARED_SCLK("sbc3.sclk", "tegra12-spi.2",       "sclk", &tegra_clk_apb,        NULL, 0, 0),
        SHARED_SCLK("sbc4.sclk", "tegra12-spi.3",       "sclk", &tegra_clk_apb,        NULL, 0, 0),
+       SHARED_SCLK("boot.apb.sclk", "boot.apb.sclk",   NULL,   &tegra_clk_apb,        NULL, 0, 0),
 
        SHARED_EMC_CLK("avp.emc",       "nvavp",        "emc",  &tegra_clk_emc, NULL, 0, 0, 0),
        SHARED_EMC_CLK("cpu.emc",       "cpu",          "emc",  &tegra_clk_emc, NULL, 0, 0, 0),
@@ -8472,7 +9075,7 @@ struct clk tegra_list_clks[] = {
        SHARED_EMC_CLK("cap.emc",       "cap.emc",      NULL,   &tegra_clk_emc, NULL, 0, SHARED_CEILING, 0),
        SHARED_EMC_CLK("cap.vcore.emc", "cap.vcore.emc", NULL,  &tegra_clk_emc, NULL, 0, SHARED_CEILING, 0),
        SHARED_EMC_CLK("cap.throttle.emc", "cap_throttle", NULL, &tegra_clk_emc, NULL, 0, SHARED_CEILING_BUT_ISO, 0),
-       SHARED_EMC_CLK("3d.emc",        "tegra_gm20b.0",        "emc",  &tegra_clk_emc, NULL, 0, 0,             BIT(EMC_USER_3D)),
+       SHARED_EMC_CLK("3d.emc",        "tegra_gpu.0",  "emc",  &tegra_clk_emc, NULL, 0, 0,             BIT(EMC_USER_3D)),
        SHARED_EMC_CLK("msenc.emc",     "tegra_msenc",  "emc",  &tegra_clk_emc, NULL, 0, SHARED_BW,     BIT(EMC_USER_MSENC)),
        SHARED_EMC_CLK("nvjpg.emc",     "tegra_nvjpg",  "emc",  &tegra_clk_emc, NULL, 0, SHARED_BW,     BIT(EMC_USER_NVJPG)),
        SHARED_EMC_CLK("nvdec.emc",     "tegra_nvdec",  "emc",  &tegra_clk_emc, NULL, 0, 0, 0),
@@ -8483,39 +9086,42 @@ 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("vic03.cbus",     "tegra_vic03",          "vic03", &tegra_clk_c2bus, "vic03", 0, 0),
-       SHARED_LIMIT("cap.c2bus",               "cap.c2bus",            NULL,    &tegra_clk_c2bus, NULL,    0, SHARED_CEILING),
-       SHARED_LIMIT("cap.vcore.c2bus",         "cap.vcore.c2bus",              NULL,    &tegra_clk_c2bus, NULL,    0, SHARED_CEILING),
+       DUAL_CBUS_CLK("nvjpg.cbus",     "tegra_nvjpg",          "nvjpg", &tegra_clk_c2bus, "nvjpg", 0, 0),
+       DUAL_CBUS_CLK("se.cbus",        "tegra21-se",           NULL,    &tegra_clk_c2bus, "se",    0, 0),
+       SHARED_LIMIT("cap.c2bus",       "cap.c2bus",            NULL,    &tegra_clk_c2bus, NULL,    0, SHARED_CEILING),
+       SHARED_LIMIT("cap.vcore.c2bus", "cap.vcore.c2bus",      NULL,    &tegra_clk_c2bus, NULL,    0, SHARED_CEILING),
        SHARED_LIMIT("cap.throttle.c2bus", "cap_throttle",      NULL,    &tegra_clk_c2bus, NULL,    0, SHARED_CEILING),
        SHARED_LIMIT("floor.c2bus",     "floor.c2bus",          NULL,    &tegra_clk_c2bus, NULL,    0, 0),
-       SHARED_CLK("override.c2bus",    "override.c2bus",       NULL,    &tegra_clk_c2bus, NULL,  0, SHARED_OVERRIDE),
-       SHARED_LIMIT("edp.c2bus",         "edp.c2bus",            NULL,   &tegra_clk_c2bus, NULL,  0, SHARED_CEILING),
+       SHARED_CLK("override.c2bus",    "override.c2bus",       NULL,    &tegra_clk_c2bus, NULL,    0, SHARED_OVERRIDE),
+       SHARED_LIMIT("edp.c2bus",       "edp.c2bus",            NULL,    &tegra_clk_c2bus, NULL,    0, SHARED_CEILING),
 
+       DUAL_CBUS_CLK("vic03.cbus",     "tegra_vic03",          "vic03", &tegra_clk_c3bus, "vic03", 0, 0),
        DUAL_CBUS_CLK("msenc.cbus",     "tegra_msenc",          "msenc", &tegra_clk_c3bus, "msenc", 0, 0),
-       DUAL_CBUS_CLK("nvjpg.cbus",     "tegra_nvjpg",          "nvjpg", &tegra_clk_c3bus, "nvjpg", 0, 0),
        DUAL_CBUS_CLK("nvdec.cbus",     "tegra_nvdec",          "nvdec", &tegra_clk_c3bus, "nvdec", 0, 0),
-       DUAL_CBUS_CLK("se.cbus",        "tegra21-se",           NULL,    &tegra_clk_c3bus, "se",    0, 0),
-       DUAL_CBUS_CLK("tsecb.cbus",     "tegra_tsecb",          "tsecb",  &tegra_clk_c3bus,  "tsecb", 0, 0),
-       SHARED_LIMIT("cap.c3bus",               "cap.c3bus",            NULL,    &tegra_clk_c3bus, NULL,    0, SHARED_CEILING),
-       SHARED_LIMIT("cap.vcore.c3bus",         "cap.vcore.c3bus",              NULL,    &tegra_clk_c3bus, NULL,    0, SHARED_CEILING),
+       DUAL_CBUS_CLK("tsecb.cbus",     "tegra_tsecb",          "tsecb", &tegra_clk_c3bus, "tsecb", 0, 0),
+       SHARED_LIMIT("vic_floor.cbus",  "tegra_vic03",          "vic_floor",    &tegra_clk_c3bus, NULL, 0, 0),
+       SHARED_LIMIT("cap.c3bus",       "cap.c3bus",            NULL,    &tegra_clk_c3bus, NULL,    0, SHARED_CEILING),
+       SHARED_LIMIT("cap.vcore.c3bus", "cap.vcore.c3bus",      NULL,    &tegra_clk_c3bus, NULL,    0, SHARED_CEILING),
        SHARED_LIMIT("cap.throttle.c3bus", "cap_throttle",      NULL,    &tegra_clk_c3bus, NULL,    0, SHARED_CEILING),
        SHARED_LIMIT("floor.c3bus",     "floor.c3bus",          NULL,    &tegra_clk_c3bus, NULL,    0, 0),
-       SHARED_CLK("override.c3bus",    "override.c3bus",       NULL,    &tegra_clk_c3bus, NULL,  0, SHARED_OVERRIDE),
+       SHARED_CLK("override.c3bus",    "override.c3bus",       NULL,    &tegra_clk_c3bus, NULL,    0, SHARED_OVERRIDE),
 
-       SHARED_CLK("gm20b.gbus",        "tegra_gk20a",  "gpu",  &tegra_clk_gbus, NULL,  0, 0),
-       SHARED_LIMIT("cap.gbus",                "cap.gbus",     NULL,   &tegra_clk_gbus, NULL,  0, SHARED_CEILING),
-       SHARED_LIMIT("edp.gbus",                "edp.gbus",     NULL,   &tegra_clk_gbus, NULL,  0, SHARED_CEILING),
+       SHARED_CLK("gm20b.gbus",        "tegra_gpu.0",          "gpu",  &tegra_clk_gbus, NULL,  0, 0),
+       SHARED_LIMIT("cap.gbus",        "cap.gbus",             NULL,   &tegra_clk_gbus, NULL,  0, SHARED_CEILING),
+       SHARED_LIMIT("edp.gbus",        "edp.gbus",             NULL,   &tegra_clk_gbus, NULL,  0, SHARED_CEILING),
        SHARED_LIMIT("cap.throttle.gbus", "cap_throttle",       NULL,   &tegra_clk_gbus, NULL,  0, SHARED_CEILING),
        SHARED_LIMIT("cap.profile.gbus", "profile.gbus",        "cap",  &tegra_clk_gbus, NULL,  0, SHARED_CEILING),
-       SHARED_CLK("override.gbus",     "override.gbus", NULL,  &tegra_clk_gbus, NULL,  0, SHARED_OVERRIDE),
-       SHARED_LIMIT("floor.gbus",      "floor.gbus", NULL,     &tegra_clk_gbus, NULL,  0, 0),
-       SHARED_LIMIT("floor.profile.gbus", "profile.gbus", "floor", &tegra_clk_gbus, NULL,  0, 0),
+       SHARED_CLK("override.gbus",     "override.gbus",        NULL,   &tegra_clk_gbus, NULL,  0, SHARED_OVERRIDE),
+       SHARED_LIMIT("floor.gbus",      "floor.gbus",           NULL,   &tegra_clk_gbus, NULL,  0, 0),
+       SHARED_LIMIT("floor.profile.gbus", "profile.gbus",      "floor", &tegra_clk_gbus, NULL, 0, 0),
 
        SHARED_CLK("nv.host1x", "tegra_host1x",         "host1x", &tegra_clk_host1x, NULL,  0, 0),
        SHARED_CLK("vi.host1x", "tegra_vi",             "host1x", &tegra_clk_host1x, NULL,  0, 0),
        SHARED_LIMIT("cap.host1x", "cap.host1x",        NULL,     &tegra_clk_host1x, NULL,  0, SHARED_CEILING),
-       SHARED_LIMIT("cap.vcore.host1x", "cap.vcore.host1x",    NULL,     &tegra_clk_host1x, NULL,  0, SHARED_CEILING),
+       SHARED_LIMIT("cap.vcore.host1x", "cap.vcore.host1x", NULL, &tegra_clk_host1x, NULL, 0, SHARED_CEILING),
        SHARED_LIMIT("floor.host1x", "floor.host1x",    NULL,     &tegra_clk_host1x, NULL,  0, 0),
        SHARED_CLK("override.host1x", "override.host1x", NULL,    &tegra_clk_host1x, NULL,  0, SHARED_OVERRIDE),
 
@@ -8542,6 +9148,7 @@ static struct clk tegra_visp_clks[] = {
 
 /* XUSB clocks */
 #define XUSB_ID "tegra-xhci"
+#define XUDC_ID "tegra-xudc"
 /* xusb common clock gate - enabled on init and never disabled */
 static void tegra21_xusb_gate_clk_init(struct clk *c)
 {
@@ -8556,6 +9163,7 @@ static struct clk tegra_clk_xusb_gate = {
        .name      = "xusb_gate",
        .flags     = ENABLE_ON_INIT | PERIPH_NO_RESET,
        .ops       = &tegra_xusb_gate_clk_ops,
+       .parent    = &tegra_clk_osc,
        .rate      = 12000000,
        .max_rate  = 48000000,
        .u.periph = {
@@ -8566,12 +9174,35 @@ static struct clk tegra_clk_xusb_gate = {
 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",       XUSB_ID, "fs_src",      143,    0x608,   48000000, mux_clkm_48M_pllp_480M,      MUX | DIV_U71 | PERIPH_NO_RESET),
-       PERIPH_CLK("xusb_ss_src",       XUSB_ID, "ss_src",      143,    0x610,  120000000, mux_clkm_pllre_clk32_480M_pllc_ref,  MUX | DIV_U71 | PERIPH_NO_RESET),
-       PERIPH_CLK("xusb_dev_src",      XUSB_ID, "dev_src",     95,     0x60c,  120000000, mux_clkm_pllp_pllre,         MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
+       PERIPH_CLK("xusb_fs_src",       NULL, "fs_src", 143,    0x608,   48000000, mux_clkm_48M_pllp_480M,      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,
@@ -8585,22 +9216,24 @@ static struct clk tegra_xusb_ss_div2 = {
 static struct clk_mux_sel mux_ss_div2_pllu_60M[] = {
        { .input = &tegra_xusb_ss_div2, .value = 0},
        { .input = &tegra_pll_u_60M,    .value = 1},
+       { .input = &tegra_xusb_source_clks[3], .value = 2},
+       { .input = &tegra_xusb_source_clks[3], .value = 3},
        { 0, 0},
 };
 
 static struct clk tegra_xusb_hs_src = {
        .name      = "xusb_hs_src",
        .lookup    = {
-               .dev_id    = XUSB_ID,
+               .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,
-       .max_rate  = 61200000,
+       .flags     = MUX | PLLU | PERIPH_NO_ENB | PERIPH_NO_RESET,
+       .max_rate  = 120000000,
        .u.periph = {
-               .src_mask  = 0x1 << 25,
+               .src_mask  = 0x3 << 25,
                .src_shift = 25,
        },
 };
@@ -8614,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},
@@ -8623,14 +9256,54 @@ 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},
 };
 
 static struct clk tegra_xusb_coupled_clks[] = {
        PERIPH_CLK_EX("xusb_host", XUSB_ID, "host", 89, 0, 350000000, mux_xusb_host, 0, &tegra_clk_coupled_gate_ops),
-       PERIPH_CLK_EX("xusb_ss",   XUSB_ID, "ss",  156, 0, 350000000, mux_xusb_ss,   0, &tegra_clk_coupled_gate_ops),
-       PERIPH_CLK_EX("xusb_dev",  XUSB_ID, "dev",  95, 0, 120000000, mux_xusb_dev,  0, &tegra_clk_coupled_gate_ops),
+       PERIPH_CLK_EX("xusb_ss",   NULL, "ss",  156,    0, 350000000, mux_xusb_ss,   0, &tegra_clk_coupled_gate_ops),
+       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)               \
@@ -8638,7 +9311,7 @@ static struct clk tegra_xusb_coupled_clks[] = {
                .name   = _name,                        \
                .lookup = {                             \
                        .dev_id = _dev,                 \
-                       .con_id         = _con,         \
+                       .con_id = _con,                 \
                },                                      \
        }
 
@@ -8647,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),
@@ -8696,11 +9368,17 @@ struct clk_duplicate tegra_clk_duplicates[] = {
        CLK_DUPLICATE("i2c5", "tegra_cl_dvfs", "i2c"),
        CLK_DUPLICATE("cpu_g", "tegra_cl_dvfs", "safe_dvfs"),
        CLK_DUPLICATE("actmon", "tegra_host1x", "actmon"),
-       CLK_DUPLICATE("gpu_ref", "tegra_gm20b.0", "PLLG_ref"),
-       CLK_DUPLICATE("gbus", "tegra_gm20b.0", "PLLG_out"),
-       CLK_DUPLICATE("pll_p_out5", "tegra_gm20b.0", "pwr"),
-       CLK_DUPLICATE("ispa.isp.cbus", "tegra_isp", "isp"),
+       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.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"),
@@ -8725,13 +9403,37 @@ struct clk_duplicate tegra_clk_duplicates[] = {
        CLK_DUPLICATE("dmic2", "tegra-dmic.1", NULL),
        CLK_DUPLICATE("dmic3", "tegra-dmic.2", NULL),
        CLK_DUPLICATE("d_audio", "tegra210-adma", NULL),
+       CLK_DUPLICATE("d_audio", "tegra210-amx.0", NULL),
+       CLK_DUPLICATE("d_audio", "tegra210-amx.1", NULL),
+       CLK_DUPLICATE("d_audio", "tegra210-adx.0", NULL),
+       CLK_DUPLICATE("d_audio", "tegra210-adx.1", NULL),
+       CLK_DUPLICATE("d_audio", "tegra210-afc.0", NULL),
+       CLK_DUPLICATE("d_audio", "tegra210-afc.1", NULL),
+       CLK_DUPLICATE("d_audio", "tegra210-afc.2", NULL),
+       CLK_DUPLICATE("d_audio", "tegra210-afc.3", NULL),
+       CLK_DUPLICATE("d_audio", "tegra210-afc.4", NULL),
+       CLK_DUPLICATE("d_audio", "tegra210-afc.5", NULL),
+       CLK_DUPLICATE("d_audio", "tegra210-sfc.0", NULL),
+       CLK_DUPLICATE("d_audio", "tegra210-sfc.1", NULL),
+       CLK_DUPLICATE("d_audio", "tegra210-sfc.2", NULL),
+       CLK_DUPLICATE("d_audio", "tegra210-sfc.3", NULL),
+       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,
@@ -8789,6 +9491,7 @@ struct clk *tegra_ptr_clks[] = {
        &tegra_clk_hclk,
        &tegra_clk_pclk,
        &tegra_clk_aclk_adsp,
+       &tegra_clk_virtual_adsp_cpu,
        &tegra_clk_virtual_cpu_g,
        &tegra_clk_virtual_cpu_lp,
        &tegra_clk_cpu_cmplx,
@@ -8803,41 +9506,70 @@ struct clk *tegra_ptr_clks[] = {
        &tegra_clk_mselect,
        &tegra_clk_c2bus,
        &tegra_clk_c3bus,
-       &tegra_clk_gpu,
+       &tegra_clk_gpu_gate,
+       &tegra_clk_gpu_ref,
        &tegra_clk_gbus,
        &tegra_clk_isp,
        &tegra_clk_cbus,
        &tegra_clk_sor1_src,
        &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,
 };
 
 struct clk *tegra_ptr_camera_mclks[] = {
        &tegra_camera_mclk,
        &tegra_camera_mclk2,
+       &tegra_camera_mclk3,
+       &tegra_camera_mipical,
 };
 
-/* Return true from this function if the target rate can be locked without
-   switching pll clients to back-up source */
-static bool tegra21_is_dyn_ramp(
-       struct clk *c, unsigned long rate, bool from_vco_min)
-{
-#if PLLCX_USE_DYN_RAMP
-       /* PLLC2, PLLC3 support dynamic ramp only when output divider <= 8 */
-       if ((c == &tegra_pll_c) || (c == &tegra_pll_c2) ||
-           (c == &tegra_pll_c3) || (c == &tegra_pll_a1)) {
-               struct clk_pll_freq_table cfg, old_cfg;
-               unsigned long input_rate = clk_get_rate(c->parent);
+#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) },
 
-               pll_base_parse_cfg(c, &old_cfg);
+       { .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) },
 
-               if (!pll_clk_find_cfg(c, &cfg, rate, input_rate, NULL)) {
-                       if ((cfg.m == old_cfg.m) && (cfg.p == old_cfg.p))
-                               return c->u.pll.defaults_set;
-               }
-       }
+       { .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
-       return false;
+
+/*
+ * Handle special clocks to check if they can be set to safe rate
+ */
+static void check_isp_reset(void)
+{
+       struct clk *isp = &tegra_clk_isp;
+       struct clk *ispa = tegra_get_clock_by_name("ispa");
+       struct clk *ispb = tegra_get_clock_by_name("ispb");
+
+       if (periph_clk_can_force_safe_rate(ispa) &&
+           periph_clk_can_force_safe_rate(ispb))
+               tegra_periph_clk_safe_rate_init(isp);
+}
+
+static void tegra21_periph_check_special_reset(void)
+{
+       check_isp_reset();
 }
 
 /* DFLL late init called with CPU clock lock taken */
@@ -8877,12 +9609,10 @@ static void __init tegra21_dfll_cpu_late_init(struct clk *c)
  *
  * PLLC4 post-divider PLLC_OUT0 and secondary divider PLLC_OUT3 ratios specified
  * in the table are selected to provide max input frequency to downstream module
- * dividers (fort better granularity of possible rates) but not above 800 MHz -
- * maximum rate that can be divided at minimum voltage.
+ * dividers (fort better granularity of possible rates).
  *
  * Commonly PLLC_OUT3 is also used as second clock source (along with PLLP) for
- * the system bus. However, in default configuration PLLC4_OUT1 = VCO/3 is
- * selected for system us to provide important target rate in 300-350 MHz range.
+ * the system bus.
  */
 struct pllc4_sdmmc_map {
        unsigned long sdmmc_max_rate;
@@ -8893,9 +9623,8 @@ struct pllc4_sdmmc_map {
 };
 
 static struct pllc4_sdmmc_map  tegra21_pllc4_sdmmc_map[] = {
-       {         0, 1000000000, 2, 1, &tegra_pll_c4_out1 }, /* default cfg */
-       { 266500000,  799500000, 1, 1, &tegra_pll_c4_out3 },
-       { 400000000,  800000000, 1, 1, &tegra_pll_c4_out3 },
+       {         0, 1000000000, 1, 1, &tegra_pll_c4_out3 }, /* default cfg */
+       { 266000000,  798000000, 4, 1, &tegra_pll_c4_out1 },
 };
 
 static void pllc4_set_fixed_rates(unsigned long cf)
@@ -8907,6 +9636,9 @@ static void pllc4_set_fixed_rates(unsigned long cf)
        struct pllc4_sdmmc_map *pllc4_cfg = &tegra21_pllc4_sdmmc_map[0];
 
        for_each_compatible_node(dn, NULL, "nvidia,tegra210-sdhci") {
+               if (!of_device_is_available(dn))
+                       continue;
+
                if (!of_property_read_u32(dn, "max-clk-limit", &val)
                    && (sdmmc_max_rate < val))
                        sdmmc_max_rate = val;
@@ -8968,19 +9700,25 @@ 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;
        case 408000000:
                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;
        case 204000000:
                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;
        default:
                pr_err("tegra: PLLP rate: %lu is not supported\n", pllp_rate);
@@ -9057,13 +9795,13 @@ void __init tegra21x_clk_init_la(void)
        c = tegra_get_clock_by_name("la");
        if (WARN(!c, "%s: could not find la clk\n", __func__))
                return;
-       clk_enable(c);
+       tegra_clk_prepare_enable(c);
 
        if (reg & MISC_GP_TRANSACTOR_SCRATCH_DP2_ENABLE) {
                c = tegra_get_clock_by_name("dp2");
                if (WARN(!c, "%s: could not find dp2 clk\n", __func__))
                        return;
-               clk_enable(c);
+               tegra_clk_prepare_enable(c);
        }
 }
 
@@ -9233,18 +9971,22 @@ int tegra_update_mselect_rate(unsigned long cpu_rate)
 
 #ifdef CONFIG_PM_SLEEP
 static u32 clk_rst_suspend[RST_DEVICES_NUM + CLK_OUT_ENB_NUM +
-                          PERIPH_CLK_SOURCE_NUM + 28];
+                          PERIPH_CLK_SOURCE_NUM + 25];
 
 static int tegra21_clk_suspend(void)
 {
        unsigned long off;
        u32 *ctx = clk_rst_suspend;
 
-       *ctx++ = clk_readl(OSC_CTRL) & OSC_CTRL_MASK;
+       *ctx++ = clk_readl(OSC_CTRL) & OSC_CTRL_OSC_FREQ_MASK;
        *ctx++ = clk_readl(CPU_SOFTRST_CTRL);
        *ctx++ = clk_readl(CPU_SOFTRST_CTRL1);
        *ctx++ = clk_readl(CPU_SOFTRST_CTRL2);
 
+       *ctx++ = clk_readl(SPARE_REG);
+       *ctx++ = clk_readl(MISC_CLK_ENB);
+       *ctx++ = clk_readl(CLK_MASK_ARM);
+
        *ctx++ = clk_readl(tegra_pll_p_out3.reg);
        *ctx++ = clk_readl(tegra_pll_p_out5.reg);
        *ctx++ = clk_readl(tegra_pll_p_out_hsio.reg);
@@ -9257,10 +9999,10 @@ static int tegra21_clk_suspend(void)
        *ctx++ = clk_readl(tegra_pll_c4_out3.reg);
        *ctx++ = clk_readl(tegra_pll_re_out1.reg);
 
-       *ctx++ = clk_readl(tegra_clk_pclk.reg);
        *ctx++ = clk_readl(tegra_clk_sclk.reg);
        *ctx++ = clk_readl(tegra_clk_sclk_div.reg);
        *ctx++ = clk_readl(tegra_clk_sclk_mux.reg);
+       *ctx++ = clk_readl(tegra_clk_pclk.reg);
 
        for (off = PERIPH_CLK_SOURCE_I2S1; off <= PERIPH_CLK_SOURCE_LA;
                        off += 4) {
@@ -9275,9 +10017,24 @@ static int tegra21_clk_suspend(void)
        for (off = AUDIO_DLY_CLK; off <= AUDIO_SYNC_CLK_SPDIF; off+=4) {
                *ctx++ = clk_readl(off);
        }
+       for (off = AUDIO_SYNC_CLK_DMIC1;
+             off <= AUDIO_SYNC_CLK_DMIC2; off += 4) {
+               *ctx++ = clk_readl(off);
+       }
        for (off = PERIPH_CLK_SOURCE_XUSB_HOST;
-               off <= PERIPH_CLK_SOURCE_VIC; off += 4)
+               off <= PERIPH_CLK_SOURCE_VIC; off += 4) {
+               if (off == PERIPH_CLK_SOURCE_EMC_DLL)
+                       continue;
                *ctx++ = clk_readl(off);
+       }
+       for (off = PERIPH_CLK_SOURCE_SDMMC_LEGACY;
+             off <= PERIPH_CLK_SOURCE_NVENC; off += 4) {
+               *ctx++ = clk_readl(off);
+       }
+       for (off = AUDIO_SYNC_CLK_DMIC3;
+             off <= PERIPH_CLK_SOURCE_DBGAPB; off += 4) {
+               *ctx++ = clk_readl(off);
+       }
 
        *ctx++ = clk_readl(RST_DEVICES_L);
        *ctx++ = clk_readl(RST_DEVICES_H);
@@ -9301,16 +10058,18 @@ 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_readl(SPARE_REG);
-       *ctx++ = clk_readl(MISC_CLK_ENB);
-       *ctx++ = clk_readl(CLK_MASK_ARM);
+       *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));
+       BUG_ON((ctx - clk_rst_suspend) > ARRAY_SIZE(clk_rst_suspend));
        return 0;
 }
 
 static void tegra21_clk_resume(void)
 {
-       unsigned long off;
+       unsigned long off, rate;
        const u32 *ctx = clk_rst_suspend;
        u32 val, clk_y, pll_u_mask, pll_u_base, pll_u_out12;
        u32 pll_p_out_hsio, pll_p_out_mask, pll_p_out34;
@@ -9322,14 +10081,21 @@ static void tegra21_clk_resume(void)
                (1 << tegra_pll_u_60M.reg_shift) |
                (1 << tegra_pll_u_48M.reg_shift);
 
-       /* FIXME: OSC_CTRL already restored by warm boot code? */
-       val = clk_readl(OSC_CTRL) & ~OSC_CTRL_MASK;
+       /*
+        * OSC frequency selection should be already restored by warm boot
+        * code, but just in case make sure it does not change across suspend.
+        */
+       val = clk_readl(OSC_CTRL) & ~OSC_CTRL_OSC_FREQ_MASK;
        val |= *ctx++;
        clk_writel(val, OSC_CTRL);
        clk_writel(*ctx++, CPU_SOFTRST_CTRL);
        clk_writel(*ctx++, CPU_SOFTRST_CTRL1);
        clk_writel(*ctx++, CPU_SOFTRST_CTRL2);
 
+       clk_writel(*ctx++, SPARE_REG);
+       clk_writel(*ctx++, MISC_CLK_ENB);
+       clk_writel(*ctx++, CLK_MASK_ARM);
+
        /* Since we are going to reset devices and switch clock sources in this
         * function, plls and secondary dividers is required to be enabled. The
         * actual value will be restored back later. Note that boot plls: pllm,
@@ -9381,11 +10147,21 @@ static void tegra21_clk_resume(void)
        pll_re_out1 = *ctx++;
        clk_writel(pll_re_out1 | val, tegra_pll_re_out1.reg);
 
-       /* FIXME: the oder here to be checked against boot-rom exit state */
+       /*
+        * To make sure system bus is not over-clocked during restoration:
+        * - use fixed safe 1:1:2 SCLK:HCLK:PCLK ratio until SCLK source is set
+        * - defer SCLK divider restoration after SCLK source is restored if
+        *   divider set by boot-rom is above saved value.
+        */
+       clk_writel(0x01, tegra_clk_pclk.reg);
+       clk_writel_delay(*ctx++, tegra_clk_sclk.reg);
+       val = *ctx++;
+       if (val > clk_readl(tegra_clk_sclk_div.reg))
+               clk_writel_delay(val, tegra_clk_sclk_div.reg);
+       clk_writel_delay(*ctx++, tegra_clk_sclk_mux.reg);
+       if (val != clk_readl(tegra_clk_sclk_div.reg))
+               clk_writel_delay(val, tegra_clk_sclk_div.reg);
        clk_writel(*ctx++, tegra_clk_pclk.reg);
-       clk_writel(*ctx++, tegra_clk_sclk.reg);
-       clk_writel(*ctx++, tegra_clk_sclk_div.reg);
-       clk_writel(*ctx++, tegra_clk_sclk_mux.reg);
 
        /* enable all clocks before configuring clock sources */
        clk_writel(CLK_OUT_ENB_L_RESET_MASK, CLK_OUT_ENB_L);
@@ -9394,8 +10170,7 @@ static void tegra21_clk_resume(void)
        clk_writel(CLK_OUT_ENB_V_RESET_MASK, CLK_OUT_ENB_V);
        clk_writel(CLK_OUT_ENB_W_RESET_MASK, CLK_OUT_ENB_W);
        clk_writel(CLK_OUT_ENB_X_RESET_MASK, CLK_OUT_ENB_X);
-       clk_writel(CLK_OUT_ENB_Y_RESET_MASK, CLK_OUT_ENB_Y);
-       wmb();
+       clk_writel_delay(CLK_OUT_ENB_Y_RESET_MASK, CLK_OUT_ENB_Y);
 
        for (off = PERIPH_CLK_SOURCE_I2S1; off <= PERIPH_CLK_SOURCE_LA;
                        off += 4) {
@@ -9410,10 +10185,26 @@ static void tegra21_clk_resume(void)
        for (off = AUDIO_DLY_CLK; off <= AUDIO_SYNC_CLK_SPDIF; off+=4) {
                clk_writel(*ctx++, off);
        }
+       for (off = AUDIO_SYNC_CLK_DMIC1;
+             off <= AUDIO_SYNC_CLK_DMIC2; off += 4) {
+               clk_writel(*ctx++, off);
+       }
        for (off = PERIPH_CLK_SOURCE_XUSB_HOST;
-               off <= PERIPH_CLK_SOURCE_VIC; off += 4)
+               off <= PERIPH_CLK_SOURCE_VIC; off += 4) {
+               if (off == PERIPH_CLK_SOURCE_EMC_DLL)
+                       continue;
+               clk_writel(*ctx++, off);
+       }
+       for (off = PERIPH_CLK_SOURCE_SDMMC_LEGACY;
+             off <= PERIPH_CLK_SOURCE_NVENC; off += 4) {
                clk_writel(*ctx++, off);
+       }
+       for (off = AUDIO_SYNC_CLK_DMIC3;
+             off <= PERIPH_CLK_SOURCE_DBGAPB; off += 4) {
+               clk_writel(*ctx++, off);
+       }
 
+       clk_readl(off);
        udelay(RESET_PROPAGATION_DELAY);
 
        clk_writel(*ctx++, RST_DEVICES_L);
@@ -9422,8 +10213,7 @@ static void tegra21_clk_resume(void)
        clk_writel(*ctx++, RST_DEVICES_V);
        clk_writel(*ctx++, RST_DEVICES_W);
        clk_writel(*ctx++, RST_DEVICES_X);
-       clk_writel(*ctx++, RST_DEVICES_Y);
-       wmb();
+       clk_writel_delay(*ctx++, RST_DEVICES_Y);
 
        clk_writel(*ctx++, CLK_OUT_ENB_L);
        clk_writel(*ctx++, CLK_OUT_ENB_H);
@@ -9448,10 +10238,6 @@ static void tegra21_clk_resume(void)
        clk_writel(*ctx++, tegra_clk_cclk_lp.reg);
        clk_writel_delay(*ctx++, tegra_clk_cclk_lp.reg + SUPER_CLK_DIVIDER);
 
-       clk_writel(*ctx++, SPARE_REG);
-       clk_writel(*ctx++, MISC_CLK_ENB);
-       clk_writel(*ctx++, CLK_MASK_ARM);
-
        /* Restore back the actual pll and secondary divider values */
        clk_writel(pll_p_out34, tegra_pll_p_out3.reg);
        val = clk_readl(tegra_pll_p_out_hsio.reg) & (~pll_p_out_mask);
@@ -9520,25 +10306,29 @@ static void tegra21_clk_resume(void)
        if (tegra_pll_mb.state == OFF)
                tegra_pll_mb.ops->disable(&tegra_pll_mb);
 
-       /* FIXME: implement EMC resume */
        if (p != tegra_clk_emc.parent) {
                pr_debug("EMC parent(refcount) across suspend: %s(%d) : %s(%d)",
                        p->name, p->refcnt, tegra_clk_emc.parent->name,
                        tegra_clk_emc.parent->refcnt);
 
-               BUG_ON(!p->refcnt);
-               p->refcnt--;
+               /* emc switched to the new parent by low level code, but ref
+                  count and s/w state need to be updated */
+               clk_disable_locked(p);
+               clk_enable_locked(tegra_clk_emc.parent);
+       }
 
-               /* the new parent is enabled by low level code, but ref count
-                  need to be updated up to the root */
-               p = tegra_clk_emc.parent;
-               while (p && ((p->refcnt++) == 0))
-                       p = p->parent;
+       /* update DVFS voltage requirements */
+       rate = clk_get_rate_all_locked(&tegra_clk_emc);
+       if (*ctx != rate) {
+               tegra_dvfs_set_rate(&tegra_clk_emc, rate);
+               if (p == tegra_clk_emc.parent) {
+                       rate = clk_get_rate_all_locked(p);
+                       tegra_dvfs_set_rate(p, rate);
+               }
        }
        tegra_emc_timing_invalidate();
 
        tegra21_pllu_hw_ctrl_set(&tegra_pll_u_vco); /* PLLU, UTMIP h/w ctrl */
-       tegra21_plle_clk_resume(&tegra_pll_e); /* Restore plle parent as pll_re_vco */
 }
 
 static struct syscore_ops tegra_clk_syscore_ops = {
@@ -9558,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;
@@ -9571,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]);
 
@@ -9598,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) {
@@ -9610,6 +10461,9 @@ void __init tegra21x_init_clocks(void)
                clkdev_add(&tegra_clk_duplicates[i].lookup);
        }
 
+       /* Check/apply safe rate to clocks with reset dependency on others */
+       tegra21_periph_check_special_reset();
+
        /* Initialize to default */
        tegra_init_cpu_edp_limits(0);
 
@@ -9619,11 +10473,16 @@ 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)
 {
-       clk_disable(&tegra_pll_re_vco);
+       tegra_clk_disable_unprepare(&tegra_pll_re_vco);
+       tegra_clk_disable_unprepare(tegra_get_clock_by_name("boot.apb.sclk"));
        return 0;
 }
 late_initcall(tegra21x_clk_late_init);