arm: tegra: Move driver files to drivers/platform
[linux-3.10.git] / drivers / platform / tegra / tegra21_clocks.c
index 94e495f..64dd550 100644 (file)
 
 #include <tegra/mc.h>
 
-#include "clock.h"
+#include <linux/platform/tegra/clock.h>
 #include "tegra_clocks_ops.h"
-#include "dvfs.h"
+#include <linux/platform/tegra/dvfs.h>
 #include "pm.h"
 #include "sleep.h"
 #include "devices.h"
-#include "tegra_cl_dvfs.h"
-#include "cpu-tegra.h"
+#include <linux/platform/tegra/tegra_cl_dvfs.h>
+#include <linux/platform/tegra/cpu-tegra.h>
 
 /* FIXME: Disable for initial Si bringup */
 #undef USE_PLLE_SS
 
 #define 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 PLLE_AUX_CML_SATA_ENABLE       (1<<1)
 #define PLLE_AUX_CML_PCIE_ENABLE       (1<<0)
 
+#define SOURCE_SATA                    0x424
+
 /* USB PLLs PD HW controls */
 #define XUSBIO_PLL_CFG0                                0x51c
 #define XUSBIO_PLL_CFG0_SEQ_START_STATE                (1<<25)
 #define PLLP_DEFAULT_FIXED_RATE                408000000
 
 /* Use PLL_RE as PLLE input (default - OSC via pll reference divider) */
-#define USE_PLLE_INPUT_PLLRE    1
+#define USE_PLLE_INPUT_PLLRE    0
 
 static void pllc4_set_fixed_rates(unsigned long cf);
 static void tegra21_dfll_cpu_late_init(struct clk *c);
@@ -627,7 +629,7 @@ static const struct utmi_clk_param utmi_parameters[] =
 
        {19200000,      0x03,           0x4B,           0x06,           0xBB},
        /* HACK!!! FIXME!!! following entry for 38.4MHz is a stub */
-       {38400000,      0x0,            0x0,            0x06,           0x3},
+       {38400000,      0x03,           0x4B,           0x06,           0x80}
 };
 
 static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
@@ -1525,7 +1527,13 @@ static int tegra21_cpu_cmplx_clk_set_parent(struct clk *c, struct clk *p)
         * in advanvce before the switch happens. If target p_source is DFLL it
         * is switched here to open loop mode.
         */
-       tegra_clk_prepare_enable(p);
+       ret = tegra_clk_prepare_enable(p);
+       if (ret) {
+               pr_err("%s: Failed to enable parent clock %s\n",
+                       __func__, p->name);
+               goto abort;
+       }
+
        if (c_source == dfll)
                tegra_dvfs_dfll_mode_clear(c->parent->dvfs, rate);
 
@@ -1734,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);
@@ -2227,6 +2239,10 @@ static void tegra21_utmi_param_configure(struct clk *c)
                return;
        }
 
+       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! */
@@ -2265,6 +2281,21 @@ static void tegra21_utmi_param_configure(struct clk *c)
        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;
+       clk_writel(reg, UTMIP_PLL_CFG1);
+
+       reg = clk_readl(UTMIPLL_HW_PWRDN_CFG0);
+       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 */
+       reg = clk_readl(UTMIPLL_HW_PWRDN_CFG0);
+       reg |= UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE;
+       pll_writel_delay(reg, UTMIPLL_HW_PWRDN_CFG0);
 }
 
 /*
@@ -4781,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)
 {
@@ -4929,6 +5030,68 @@ static struct clk_ops tegra_sdmmc24_clk_ops = {
        .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);
 
@@ -5137,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);
@@ -5264,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 = {
@@ -5283,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
@@ -6548,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 },
 };
 
@@ -7491,9 +7682,12 @@ static void tegra21_adsp_clk_reset(struct clk *c, bool assert)
 {
        unsigned long reg = assert ? RST_DEVICES_SET_Y : RST_DEVICES_CLR_Y;
        u32 val = ADSP_NEON | ADSP_SCU | ADSP_WDT | ADSP_DBG
-               | ADSP_PERIPH | ADSP_INTF | ADSP_CORE;
+               | ADSP_PERIPH | ADSP_CORE;
 
        pr_debug("%s %s\n", __func__, assert ? "assert" : "deassert");
+
+       clk_writel_delay(ADSP_INTF, reg);
+       udelay(50);
        clk_writel_delay(val, reg);
 }
 
@@ -7788,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},
 };
 
@@ -7807,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},
@@ -7954,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},
@@ -7994,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},
 };
 
@@ -8006,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},
 };
 
@@ -8129,6 +8327,32 @@ static struct clk_mux_sel mux_plld[] = {
 
 static struct raw_notifier_head emc_rate_change_nh;
 
+static struct clk tegra_clk_sata = {
+       .name      = "sata",
+       .lookup    = {
+               .dev_id = "tegra_sata",
+       },
+       .ops       = &tegra_periph_clk_ops,
+       .reg       = SOURCE_SATA,
+       .max_rate  = 216000000,
+       .u.periph  = {
+               .clk_num = 124,
+       },
+       .inputs    = mux_pllp_pllc_clkm,
+       .flags     = MUX | DIV_U71 | PERIPH_ON_APB,
+};
+
+static struct clk tegra_sata_aux_clk = {
+       .name      = "sata_aux",
+       .parent    = &tegra_clk_sata,
+       .ops       = &tegra_cml_clk_ops,
+       .reg       = SOURCE_SATA,
+       .max_rate  = 216000000,
+       .u.periph  = {
+               .clk_num = 24,
+       },
+};
+
 static struct clk tegra_clk_emc = {
        .name = "emc",
        .ops = &tegra_emc_clk_ops,
@@ -8429,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;
        }
 }
 
@@ -8462,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,
@@ -8663,7 +8919,7 @@ struct clk tegra_list_clks[] = {
        PERIPH_CLK("i2s3",      "tegra210-i2s.3",       NULL,   101,    0x3bc,  204000000,  mux_pllaout0_audio3_pllp_clkm,      MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
        PERIPH_CLK("i2s4",      "tegra210-i2s.4",       NULL,   102,    0x3c0,  204000000,  mux_pllaout0_audio4_pllp_clkm,      MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
        PERIPH_CLK("spdif_out", "tegra210-spdif", "spdif_out",  10,     0x108,   49152000, mux_pllaout0_audio_2x_pllp_clkm,     MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
-       PERIPH_CLK("spdif_in",  "tegra210-spdif",  "spdif_in",  10,     0x10c,  408000000, mux_pllp_pllc,                       MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
+       PERIPH_CLK("spdif_in",  "tegra210-spdif",  "spdif_in",  10,     0x10c,  408000000, mux_pllp_pllc_clkm_1,                MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
        PERIPH_CLK("dmic1",     "tegra210-dmic.0",      NULL,   161,    0x64c,  24576000, mux_pllaout0_audio0_dmic_pllp_clkm,   MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
        PERIPH_CLK("dmic2",     "tegra210-dmic.1",      NULL,   162,    0x650,  24576000, mux_pllaout0_audio1_dmic_pllp_clkm,   MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
        PERIPH_CLK("dmic3",     "tegra210-dmic.2",      NULL,   197,    0x6bc,  24576000, mux_pllaout0_audio2_dmic_pllp_clkm,   MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
@@ -8675,14 +8931,13 @@ struct clk tegra_list_clks[] = {
        PERIPH_CLK("hda2codec_2x", "tegra30-hda", "hda2codec",  111,    0x3e4,  102000000,  mux_pllp_pllc_plla_clkm,            MUX | DIV_U71 | PERIPH_ON_APB),
        PERIPH_CLK("hda2hdmi",  "tegra30-hda",     "hda2hdmi",  128,    0,      408000000,  mux_clk_m,                          PERIPH_ON_APB),
 
-       PERIPH_CLK("qspi",      "qspi",                 NULL,   211,    0x6c4, 166000000, mux_pllp_pllc_pllc4_out2_pllc4_out1_clkm_pllc4_out0, MUX | DIV_U71 | PERIPH_ON_APB),
-       PERIPH_CLK("vi_i2c",    "vi_i2c",               NULL,   208,    0x6c8, 136000000, mux_pllp_pllc_clkm,   MUX | DIV_U151 | PERIPH_ON_APB),
+       PERIPH_CLK("qspi",      "qspi",                 NULL,   211,    0x6c4, 166000000, mux_pllp_pllc_pllc_out1_pllc4_out2_pllc4_out1_clkm_pllc4_out0, MUX | DIV_U71 | PERIPH_ON_APB),
+       PERIPH_CLK("vii2c",     "vii2c",                NULL,   208,    0x6c8, 136000000, mux_pllp_pllc_clkm,   MUX | DIV_U16 | PERIPH_ON_APB),
        PERIPH_CLK("sbc1",      "spi-tegra114.0",       NULL,   41,     0x134,  51000000, mux_pllp_pllc_clkm,   MUX | DIV_U71 | PERIPH_ON_APB),
        PERIPH_CLK("sbc2",      "spi-tegra114.1",       NULL,   44,     0x118,  51000000, mux_pllp_pllc_clkm,   MUX | DIV_U71 | PERIPH_ON_APB),
        PERIPH_CLK("sbc3",      "spi-tegra114.2",       NULL,   46,     0x11c,  51000000, mux_pllp_pllc_clkm,   MUX | DIV_U71 | PERIPH_ON_APB),
        PERIPH_CLK("sbc4",      "spi-tegra114.3",       NULL,   68,     0x1b4,  51000000, mux_pllp_pllc_clkm,   MUX | DIV_U71 | PERIPH_ON_APB),
        PERIPH_CLK("sata_oob",  "tegra_sata_oob",       NULL,   123,    0x420,  216000000, mux_pllp_pllc_clkm,  MUX | DIV_U71 | PERIPH_ON_APB),
-       PERIPH_CLK("sata",      "tegra_sata",           NULL,   124,    0x424,  216000000, mux_pllp_pllc_clkm,  MUX | DIV_U71 | PERIPH_ON_APB),
        PERIPH_CLK("sata_cold", "tegra_sata_cold",      NULL,   129,    0,      48000000,  mux_clk_m,           PERIPH_ON_APB),
        PERIPH_CLK("sdmmc1",    "sdhci-tegra.0",        NULL,   14,     0x150,  208000000, mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0,      MUX | DIV_U71 | PERIPH_ON_APB),
        PERIPH_CLK("sdmmc3",    "sdhci-tegra.2",        NULL,   69,     0x1bc,  208000000, mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0,      MUX | DIV_U71 | PERIPH_ON_APB),
@@ -8723,8 +8978,8 @@ struct clk tegra_list_clks[] = {
        PERIPH_CLK("disp2",     "tegradc.1",            NULL,   26,     0x13c,  800000000, mux_pllp_plld_plld2_clkm,    MUX),
        PERIPH_CLK_EX("sor0",   "sor0",                 NULL,   182,    0x414,  600000000, mux_pllp_sor_sor0_brick,             MUX,    &tegra_sor0_clk_ops),
        PERIPH_CLK_EX("sor1",   "sor1",                 NULL,   183,    0x410,  600000000, mux_pllp_sor_sor1_brick_sor1_src,    MUX,    &tegra_sor1_clk_ops),
-       PERIPH_CLK("dpaux",     "dpaux",                NULL,   181,    0,      408000000, mux_pllp,                    0),
-       PERIPH_CLK("dpaux1",    "dpaux1",               NULL,   207,    0,      408000000, mux_pllp,                    0),
+       PERIPH_CLK_EX("dpaux",  "dpaux",                NULL,   181,    0,       24000000, mux_pllp,                    0, &tegra_dpaux_clk_ops),
+       PERIPH_CLK_EX("dpaux1", "dpaux1",               NULL,   207,    0,       24000000, mux_pllp,                    0, &tegra_dpaux_clk_ops),
 
        PERIPH_CLK("usbd",      "tegra-udc.0",          NULL,   22,     0,      480000000, mux_clk_m,                   0),
        PERIPH_CLK("usb2",      "tegra-ehci.1",         NULL,   58,     0,      480000000, mux_clk_m,                   0),
@@ -8745,8 +9000,8 @@ struct clk tegra_list_clks[] = {
        PERIPH_CLK("dsialp",    "tegradc.0",        "dsialp",   147,    0x620,  204000000, mux_pllp_pllc_clkm,          MUX | DIV_U71 | PERIPH_NO_RESET),
        PERIPH_CLK("dsiblp",    "tegradc.1",        "dsiblp",   148,    0x624,  204000000, mux_pllp_pllc_clkm,          MUX | DIV_U71 | PERIPH_NO_RESET),
 
-       PERIPH_CLK("entropy",   "entropy",              NULL,   149,    0x628,  102000000, mux_pllp_clkm_1,             MUX | DIV_U71),
-       PERIPH_CLK("uart_mipi_cal", "uart_mipi_cal",    NULL,   177,    0x66c,  102000000, mux_pllp_out3_pllp_pllc_clkm, MUX | DIV_U71 | PERIPH_NO_RESET),
+       PERIPH_CLK("entropy",   "entropy",              NULL,   149,    0x628,  102000000, mux_pllp_clkm_clk32_plle,            MUX | DIV_U71),
+       PERIPH_CLK("uart_mipi_cal", "uart_mipi_cal",    NULL,   177,    0x66c,  102000000, mux_pllp_out3_pllp_pllc_clkm,        MUX | DIV_U71 | PERIPH_NO_RESET),
        PERIPH_CLK("dbgapb",    "dbgapb",               NULL,   185,    0x718,  136000000, mux_pllp_clkm_2,             MUX | DIV_U71 | PERIPH_NO_RESET),
        PERIPH_CLK("tsensor",   "tegra-tsensor",        NULL,   100,    0x3b8,  216000000, mux_pllp_pllc_clkm_clk32,    MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
        PERIPH_CLK("actmon",    "actmon",               NULL,   119,    0x3e8,  216000000, mux_pllp_pllc_clk32_clkm,    MUX | DIV_U71),
@@ -8758,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),
@@ -8781,7 +9036,7 @@ struct clk tegra_list_clks[] = {
        PERIPH_CLK_SKIP("tsecb", "tsecb",       NULL,   206,    0x6d8,  0x70c,  700000000, mux_pllp_pllc2_c_c3_clkm,    MUX | DIV_U71 | DIV_U71_INT),
        PERIPH_CLK_SKIP("ispa", "isp",          "ispa", 23,     0,      0x6f8,  700000000, mux_isp,                             PERIPH_ON_APB),
        PERIPH_CLK_SKIP("ispb", "isp",          "ispb", 3,      0,      0x6fc,  700000000, mux_isp,                             PERIPH_ON_APB),
-       PERIPH_CLK_EX("vi",     "vi",           "vi",   20,     0x148,          700000000, mux_pllc2_c_c3_pllp_plla1_pllc4,     MUX | DIV_U71 | DIV_U71_INT, &tegra_vi_clk_ops),
+       PERIPH_CLK_EX("vi",     "vi",           "vi",   20,     0x148,          700000000, mux_pllc2_c_c3_pllp_clkm_plla1_pllc4,        MUX | DIV_U71 | DIV_U71_INT, &tegra_vi_clk_ops),
        SUPER_SKIP_CLK("vi_skip", "vi",         "skip",         0x6ec,             NULL, 0),
 
        SHARED_CLK("avp.sclk",  "nvavp",                "sclk", &tegra_clk_sbus_cmplx, NULL, 0, 0),
@@ -8831,6 +9086,7 @@ struct clk tegra_list_clks[] = {
        SHARED_EMC_CLK("floor.emc",     "floor.emc",    NULL,   &tegra_clk_emc, NULL, 0, 0, 0),
        SHARED_EMC_CLK("override.emc", "override.emc",  NULL,   &tegra_clk_emc, NULL, 0, SHARED_OVERRIDE, 0),
        SHARED_EMC_CLK("vic.emc",       "tegra_vic03",  "emc",  &tegra_clk_emc, NULL, 0, 0, 0),
+       SHARED_EMC_CLK("vic_shared.emc",        "tegra_vic03",  "emc_shared",  &tegra_clk_emc, NULL, 0, SHARED_BW, 0),
        SHARED_EMC_CLK("ape.emc", "ape", "emc",  &tegra_clk_emc, NULL, 0, 0, 0),
 
        DUAL_CBUS_CLK("nvjpg.cbus",     "tegra_nvjpg",          "nvjpg", &tegra_clk_c2bus, "nvjpg", 0, 0),
@@ -8919,11 +9175,34 @@ static struct clk tegra_xusb_source_clks[] = {
        PERIPH_CLK("xusb_host_src",     XUSB_ID, "host_src",    143,    0x600,  120000000, mux_clkm_pllp_pllre,         MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
        PERIPH_CLK("xusb_falcon_src",   XUSB_ID, "falcon_src",  143,    0x604,  350000000, mux_clkm_pllp_pllre,         MUX | DIV_U71 | PERIPH_NO_RESET),
        PERIPH_CLK("xusb_fs_src",       NULL, "fs_src", 143,    0x608,   48000000, mux_clkm_48M_pllp_480M,      MUX | DIV_U71 | PERIPH_NO_RESET),
-       PERIPH_CLK("xusb_ss_src",       NULL, "ss_src", 143,    0x610,  120000000, mux_clkm_pllre_clk32_480M_pllc_ref,  MUX | DIV_U71 | PERIPH_NO_RESET),
+       PERIPH_CLK_EX("xusb_ss_src",    NULL, "ss_src", 143,    0x610,  120000000, mux_clkm_pllre_clk32_480M_pllc_ref,  MUX | DIV_U71 | PERIPH_NO_RESET, &tegra_xusb_ss_ops),
        PERIPH_CLK("xusb_dev_src",      XUDC_ID, "dev_src",     95,     0x60c,  120000000, mux_clkm_pllp_pllre,         MUX | DIV_U71 | PERIPH_ON_APB),
        SHARED_EMC_CLK("xusb.emc",      XUSB_ID, "emc", &tegra_clk_emc, NULL,   0,      SHARED_BW, 0),
 };
 
+static struct clk_mux_sel mux_ss_clk_m[] = {
+       { .input = &tegra_xusb_source_clks[3], .value = 0},
+       { .input = &tegra_clk_m,               .value = 1},
+       { 0, 0},
+};
+
+static struct clk tegra_xusb_ssp_src = {
+       .name      = "xusb_ssp_src",
+       .lookup    = {
+               .dev_id    = NULL,
+               .con_id    = "ssp_src",
+       },
+       .ops       = &tegra_xusb_ss_ops,
+       .reg       = 0x610,
+       .inputs    = mux_ss_clk_m,
+       .flags     = MUX | PERIPH_NO_ENB | PERIPH_NO_RESET,
+       .max_rate  = 120000000,
+       .u.periph = {
+               .src_mask  = 0x1 << 24,
+               .src_shift = 24,
+       },
+};
+
 static struct clk tegra_xusb_ss_div2 = {
        .name      = "xusb_ss_div2",
        .ops       = &tegra_clk_m_div_ops,
@@ -8948,7 +9227,7 @@ static struct clk tegra_xusb_hs_src = {
                .dev_id    = NULL,
                .con_id    = "hs_src",
        },
-       .ops       = &tegra_periph_clk_ops,
+       .ops       = &tegra_xusb_ss_ops,
        .reg       = 0x610,
        .inputs    = mux_ss_div2_pllu_60M,
        .flags     = MUX | PLLU | PERIPH_NO_ENB | PERIPH_NO_RESET,
@@ -8968,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},
@@ -8977,7 +9256,8 @@ static struct clk_mux_sel mux_xusb_ss[] = {
 static struct clk_mux_sel mux_xusb_dev[] = {
        { .input = &tegra_xusb_source_clks[4], .value = 4},
        { .input = &tegra_xusb_source_clks[2], .value = 2},
-       { .input = &tegra_xusb_source_clks[3], .value = 3},
+       { .input = &tegra_xusb_ssp_src,        .value = 3},
+       { .input = &tegra_xusb_hs_src,         .value = 5},
        { 0, 0},
 };
 
@@ -8987,6 +9267,45 @@ static struct clk tegra_xusb_coupled_clks[] = {
        PERIPH_CLK_EX("xusb_dev",  XUDC_ID, "dev",  95, 0, 120000000, mux_xusb_dev,  0, &tegra_clk_coupled_gate_ops),
 };
 
+#define SLCG_CLK(_root_name, _name_ext, _dev, _con, _reg, _bit)                \
+       {                                                               \
+               .name      = _root_name "_slcg_ovr" _name_ext,          \
+               .lookup = {                                             \
+                       .dev_id = _dev,                                 \
+                       .con_id = _con,                                 \
+               },                                                      \
+               .ops       = &tegra_clk_slcg_ops,                       \
+               .reg       = _reg,                                      \
+               .max_rate  = 38400000, /* replaced by root max */       \
+               .u.periph = {                                           \
+                       .clk_num   = _bit,                              \
+               },                                                      \
+       }
+
+static struct clk tegra_slcg_clks[] = {
+       SLCG_CLK("disp2",       "",     "tegradc.1",    "slcg",         0xf8,   2),
+       SLCG_CLK("disp1",       "",     "tegradc.0",    "slcg",         0xf8,   1),
+
+       SLCG_CLK("vi",          "",     "tegra_vi",     "slcg",         0xf8,   15),
+       SLCG_CLK("ispa",        "",     "tegra_isp.0",  "slcg",         0x554,  3),
+       SLCG_CLK("ispb",        "",     "tegra_isp.1",  "slcg",         0x3a4,  22),
+
+       SLCG_CLK("nvdec",       "",     "tegra_nvdec",  "slcg",         0x554,  31),
+       SLCG_CLK("msenc",       "",     "tegra_msenc",  "slcg",         0x554,  29),
+       SLCG_CLK("nvjpg",       "",     "tegra_nvjpg",  "slcg",         0x554,  9),
+       SLCG_CLK("vic03",       "",     "tegra_vic03",  "slcg",         0x554,  5),
+
+       SLCG_CLK("xusb_dev",    "",     XUDC_ID,        "slcg",         0x3a0,  31),
+       SLCG_CLK("xusb_host",   "",     XUSB_ID,        "slcg",         0x3a0,  30),
+       SLCG_CLK("sata",        "_fpci", "tegra_sata",  "slcg_fpci",    0x3a0,  19),
+       SLCG_CLK("sata",        "_ipfs", "tegra_sata",  "slcg_ipfs",    0x3a0,  17),
+       SLCG_CLK("sata",        "",     "tegra_sata",   "slcg",         0x3a0,  0),
+
+       SLCG_CLK("d_audio",     "",   "tegra210-axbar", "slcg",         0x3a0,  1),
+       SLCG_CLK("adsp",        "",     NULL,           "slcg_adsp",    0x554,  11),
+       SLCG_CLK("ape",         "",     NULL,           "slcg_ape",     0x554,  10),
+};
+
 #define CLK_DUPLICATE(_name, _dev, _con)               \
        {                                               \
                .name   = _name,                        \
@@ -9053,6 +9372,13 @@ struct clk_duplicate tegra_clk_duplicates[] = {
        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"),
@@ -9189,6 +9515,8 @@ struct clk *tegra_ptr_clks[] = {
        &tegra_clk_sor0_brick,
        &tegra_clk_sor1_brick,
        &tegra_clk_xusb_padctl,
+       &tegra_clk_sata,
+       &tegra_sata_aux_clk,
        &tegra_clk_sata_uphy,
        &tegra_clk_usb2_hsic_trk,
 };
@@ -9196,7 +9524,34 @@ struct clk *tegra_ptr_clks[] = {
 struct clk *tegra_ptr_camera_mclks[] = {
        &tegra_camera_mclk,
        &tegra_camera_mclk2,
+       &tegra_camera_mclk3,
+       &tegra_camera_mipical,
+};
+
+#ifdef CONFIG_DEBUG_FS
+static struct tegra_pto_table ptodefs[] = {
+       { .name = "pll_c",  .divider = 2, .pto_id = 1,   .presel_reg = 0x088, .presel_value = BIT(3),  .presel_mask = BIT(3) },
+       { .name = "pll_a1", .divider = 2, .pto_id = 85,  .presel_reg = 0x6a8, .presel_value = BIT(3),  .presel_mask = BIT(3) },
+       { .name = "pll_c2", .divider = 2, .pto_id = 88,  .presel_reg = 0x4ec, .presel_value = BIT(3),  .presel_mask = BIT(3) },
+       { .name = "pll_c3", .divider = 2, .pto_id = 89,  .presel_reg = 0x500, .presel_value = BIT(3),  .presel_mask = BIT(3) },
+
+       { .name = "pll_a",  .divider = 2, .pto_id = 4,   .presel_reg = 0x0bc, .presel_value = BIT(29), .presel_mask = BIT(29) },
+       { .name = "pll_x",  .divider = 2, .pto_id = 5,   .presel_reg = 0x0e4, .presel_value = BIT(22), .presel_mask = BIT(22) },
+
+       { .name = "pll_d",  .divider = 2, .pto_id = 203, .presel_reg = 0x0dc, .presel_value = BIT(25), .presel_mask = BIT(25) },
+       { .name = "pll_d2", .divider = 2, .pto_id = 205, .presel_reg = 0x4b8, .presel_value = BIT(16), .presel_mask = BIT(16) },
+       { .name = "pll_dp", .divider = 2, .pto_id = 207, .presel_reg = 0x590, .presel_value = BIT(16), .presel_mask = BIT(16) },
+       { .name = "pll_c4", .divider = 2, .pto_id = 81,  .presel_reg = 0x5a4, .presel_value = BIT(16), .presel_mask = BIT(16) },
+
+       { .name = "pll_m",  .divider = 2, .pto_id = 2,   .presel_reg = 0x9c,  .presel_value = BIT(8),  .presel_mask = BIT(8) },
+       { .name = "pll_mb", .divider = 2, .pto_id = 37,  .presel_reg = 0x9c,  .presel_value = BIT(9),  .presel_mask = BIT(9) },
+
+       { .name = "pll_u", .divider = 2,  .pto_id = 269, .presel_reg = 0xcc,  .presel_value = BIT(27), .presel_mask = BIT(27) },
+       { .name = "pll_re_vco", .divider = 2, .pto_id = 271, .presel_reg = 0x4c8, .presel_value = BIT(26), .presel_mask = BIT(26) },
+
+       { .name = NULL, },
 };
+#endif
 
 /*
  * Handle special clocks to check if they can be set to safe rate
@@ -9345,6 +9700,7 @@ static void tegra21_pllp_init_dependencies(unsigned long pllp_rate)
                tegra_pll_p_out3.u.pll_div.default_rate = 72000000;
                tegra_pll_p_out4.u.pll_div.default_rate = 108000000;
                tegra_pll_p_out5.u.pll_div.default_rate = 108000000;
+               tegra_clk_sbus_cmplx.u.system.threshold = 108000000;
                tegra_clk_host1x.u.periph.threshold = 108000000;
                tegra_clk_aclk_adsp.u.cclk.div71 = 2; /* reg settings */
                break;
@@ -9352,6 +9708,7 @@ static void tegra21_pllp_init_dependencies(unsigned long pllp_rate)
                tegra_pll_p_out3.u.pll_div.default_rate = 102000000;
                tegra_pll_p_out4.u.pll_div.default_rate = 204000000;
                tegra_pll_p_out5.u.pll_div.default_rate = 204000000;
+               tegra_clk_sbus_cmplx.u.system.threshold = 204000000;
                tegra_clk_host1x.u.periph.threshold = 204000000;
                tegra_clk_aclk_adsp.u.cclk.div71 = 2; /* reg settings */
                break;
@@ -9359,6 +9716,7 @@ static void tegra21_pllp_init_dependencies(unsigned long pllp_rate)
                tegra_pll_p_out3.u.pll_div.default_rate = 102000000;
                tegra_pll_p_out4.u.pll_div.default_rate = 204000000;
                tegra_pll_p_out5.u.pll_div.default_rate = 204000000;
+               tegra_clk_sbus_cmplx.u.system.threshold = 204000000;
                tegra_clk_host1x.u.periph.threshold = 204000000;
                tegra_clk_aclk_adsp.u.cclk.div71 = 0; /* reg settings */
                break;
@@ -9700,7 +10058,8 @@ static int tegra21_clk_suspend(void)
        *ctx++ = clk_readl(tegra_clk_cclk_lp.reg);
        *ctx++ = clk_readl(tegra_clk_cclk_lp.reg + SUPER_CLK_DIVIDER);
 
-       *ctx++ = clk_get_rate_all_locked(&tegra_clk_emc);
+       *ctx = clk_get_rate_all_locked(&tegra_clk_emc);
+       tegra21_emc_clk_suspend(&tegra_clk_emc, *ctx++);
 
        pr_debug("%s: suspend entries: %d, suspend array: %u\n", __func__,
                (s32)(ctx - clk_rst_suspend), (u32)ARRAY_SIZE(clk_rst_suspend));
@@ -9989,6 +10348,7 @@ 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]);
@@ -10086,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) {
@@ -10110,6 +10473,10 @@ void __init tegra21x_init_clocks(void)
 #ifdef CONFIG_PM_SLEEP
        register_syscore_ops(&tegra_clk_syscore_ops);
 #endif
+
+#ifdef CONFIG_DEBUG_FS
+       tegra_clk_add_pto_entries(ptodefs);
+#endif
 }
 
 static int __init tegra21x_clk_late_init(void)