Merge branch 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[pandora-kernel.git] / arch / arm / mach-tegra / tegra2_clocks.c
index f6f685c..6d7c4ee 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "clock.h"
 #include "fuse.h"
+#include "tegra2_emc.h"
 
 #define RST_DEVICES                    0x004
 #define RST_DEVICES_SET                        0x300
 #define PERIPH_CLK_SOURCE_DIVU16_MASK  0xFFFF
 #define PERIPH_CLK_SOURCE_DIV_SHIFT    0
 
+#define SDMMC_CLK_INT_FB_SEL           (1 << 23)
+#define SDMMC_CLK_INT_FB_DLY_SHIFT     16
+#define SDMMC_CLK_INT_FB_DLY_MASK      (0xF << SDMMC_CLK_INT_FB_DLY_SHIFT)
+
 #define PLL_BASE                       0x0
 #define PLL_BASE_BYPASS                        (1<<31)
 #define PLL_BASE_ENABLE                        (1<<30)
@@ -154,6 +159,12 @@ static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
  */
 static DEFINE_SPINLOCK(clock_register_lock);
 
+/*
+ * Some peripheral clocks share an enable bit, so refcount the enable bits
+ * in registers CLK_ENABLE_L, CLK_ENABLE_H, and CLK_ENABLE_U
+ */
+static int tegra_periph_clk_enable_refcount[3 * 32];
+
 #define clk_writel(value, reg) \
        __raw_writel(value, (u32)reg_clk_base + (reg))
 #define clk_readl(reg) \
@@ -351,11 +362,24 @@ static int tegra2_super_clk_set_parent(struct clk *c, struct clk *p)
        return -EINVAL;
 }
 
+/*
+ * Super clocks have "clock skippers" instead of dividers.  Dividing using
+ * a clock skipper does not allow the voltage to be scaled down, so instead
+ * adjust the rate of the parent clock.  This requires that the parent of a
+ * super clock have no other children, otherwise the rate will change
+ * underneath the other children.
+ */
+static int tegra2_super_clk_set_rate(struct clk *c, unsigned long rate)
+{
+       return clk_set_rate(c->parent, rate);
+}
+
 static struct clk_ops tegra_super_ops = {
        .init                   = tegra2_super_clk_init,
        .enable                 = tegra2_super_clk_enable,
        .disable                = tegra2_super_clk_disable,
        .set_parent             = tegra2_super_clk_set_parent,
+       .set_rate               = tegra2_super_clk_set_rate,
 };
 
 /* virtual cpu clock functions */
@@ -424,6 +448,20 @@ static struct clk_ops tegra_cpu_ops = {
        .set_rate = tegra2_cpu_clk_set_rate,
 };
 
+/* virtual cop clock functions. Used to acquire the fake 'cop' clock to
+ * reset the COP block (i.e. AVP) */
+static void tegra2_cop_clk_reset(struct clk *c, bool assert)
+{
+       unsigned long reg = assert ? RST_DEVICES_SET : RST_DEVICES_CLR;
+
+       pr_debug("%s %s\n", __func__, assert ? "assert" : "deassert");
+       clk_writel(1 << 1, reg);
+}
+
+static struct clk_ops tegra_cop_ops = {
+       .reset    = tegra2_cop_clk_reset,
+};
+
 /* bus clock functions */
 static void tegra2_bus_clk_init(struct clk *c)
 {
@@ -860,9 +898,9 @@ static long tegra2_pll_div_clk_round_rate(struct clk *c, unsigned long rate)
                divider = clk_div71_get_divider(parent_rate, rate);
                if (divider < 0)
                        return divider;
-               return parent_rate * 2 / (divider + 2);
+               return DIV_ROUND_UP(parent_rate * 2, divider + 2);
        } else if (c->flags & DIV_2) {
-               return parent_rate / 2;
+               return DIV_ROUND_UP(parent_rate, 2);
        }
        return -EINVAL;
 }
@@ -908,9 +946,14 @@ static void tegra2_periph_clk_init(struct clk *c)
        }
 
        c->state = ON;
+
+       if (!c->u.periph.clk_num)
+               return;
+
        if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) &
                        PERIPH_CLK_TO_ENB_BIT(c)))
                c->state = OFF;
+
        if (!(c->flags & PERIPH_NO_RESET))
                if (clk_readl(RST_DEVICES + PERIPH_CLK_TO_ENB_REG(c)) &
                                PERIPH_CLK_TO_ENB_BIT(c))
@@ -920,8 +963,20 @@ static void tegra2_periph_clk_init(struct clk *c)
 static int tegra2_periph_clk_enable(struct clk *c)
 {
        u32 val;
+       unsigned long flags;
+       int refcount;
        pr_debug("%s on clock %s\n", __func__, c->name);
 
+       if (!c->u.periph.clk_num)
+               return 0;
+
+       spin_lock_irqsave(&clock_register_lock, flags);
+
+       refcount = tegra_periph_clk_enable_refcount[c->u.periph.clk_num]++;
+
+       if (refcount > 1)
+               goto out;
+
        clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
                CLK_OUT_ENB_SET + PERIPH_CLK_TO_ENB_SET_REG(c));
        if (!(c->flags & PERIPH_NO_RESET) && !(c->flags & PERIPH_MANUAL_RESET))
@@ -934,15 +989,32 @@ static int tegra2_periph_clk_enable(struct clk *c)
                val |= 0x3 << 24;
                clk_writel(val, c->reg);
        }
+
+out:
+       spin_unlock_irqrestore(&clock_register_lock, flags);
+
        return 0;
 }
 
 static void tegra2_periph_clk_disable(struct clk *c)
 {
+       unsigned long flags;
+
        pr_debug("%s on clock %s\n", __func__, c->name);
 
-       clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
-               CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
+       if (!c->u.periph.clk_num)
+               return;
+
+       spin_lock_irqsave(&clock_register_lock, flags);
+
+       if (c->refcnt)
+               tegra_periph_clk_enable_refcount[c->u.periph.clk_num]--;
+
+       if (tegra_periph_clk_enable_refcount[c->u.periph.clk_num] == 0)
+               clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
+                       CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
+
+       spin_unlock_irqrestore(&clock_register_lock, flags);
 }
 
 static void tegra2_periph_clk_reset(struct clk *c, bool assert)
@@ -951,6 +1023,9 @@ static void tegra2_periph_clk_reset(struct clk *c, bool assert)
 
        pr_debug("%s %s on clock %s\n", __func__,
                 assert ? "assert" : "deassert", c->name);
+
+       BUG_ON(!c->u.periph.clk_num);
+
        if (!(c->flags & PERIPH_NO_RESET))
                clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
                           base + PERIPH_CLK_TO_ENB_SET_REG(c));
@@ -1031,12 +1106,12 @@ static long tegra2_periph_clk_round_rate(struct clk *c,
                if (divider < 0)
                        return divider;
 
-               return parent_rate * 2 / (divider + 2);
+               return DIV_ROUND_UP(parent_rate * 2, divider + 2);
        } else if (c->flags & DIV_U16) {
                divider = clk_div16_get_divider(parent_rate, rate);
                if (divider < 0)
                        return divider;
-               return parent_rate / (divider + 1);
+               return DIV_ROUND_UP(parent_rate, divider + 1);
        }
        return -EINVAL;
 }
@@ -1051,12 +1126,80 @@ static struct clk_ops tegra_periph_clk_ops = {
        .reset                  = &tegra2_periph_clk_reset,
 };
 
+/* The SDMMC controllers have extra bits in the clock source register that
+ * adjust the delay between the clock and data to compenstate for delays
+ * on the PCB. */
+void tegra2_sdmmc_tap_delay(struct clk *c, int delay)
+{
+       u32 reg;
+
+       delay = clamp(delay, 0, 15);
+       reg = clk_readl(c->reg);
+       reg &= ~SDMMC_CLK_INT_FB_DLY_MASK;
+       reg |= SDMMC_CLK_INT_FB_SEL;
+       reg |= delay << SDMMC_CLK_INT_FB_DLY_SHIFT;
+       clk_writel(reg, c->reg);
+}
+
+/* External memory controller clock ops */
+static void tegra2_emc_clk_init(struct clk *c)
+{
+       tegra2_periph_clk_init(c);
+       c->max_rate = clk_get_rate_locked(c);
+}
+
+static long tegra2_emc_clk_round_rate(struct clk *c, unsigned long rate)
+{
+       long new_rate = rate;
+
+       new_rate = tegra_emc_round_rate(new_rate);
+       if (new_rate < 0)
+               return c->max_rate;
+
+       BUG_ON(new_rate != tegra2_periph_clk_round_rate(c, new_rate));
+
+       return new_rate;
+}
+
+static int tegra2_emc_clk_set_rate(struct clk *c, unsigned long rate)
+{
+       int ret;
+       /*
+        * The Tegra2 memory controller has an interlock with the clock
+        * block that allows memory shadowed registers to be updated,
+        * and then transfer them to the main registers at the same
+        * time as the clock update without glitches.
+        */
+       ret = tegra_emc_set_rate(rate);
+       if (ret < 0)
+               return ret;
+
+       ret = tegra2_periph_clk_set_rate(c, rate);
+       udelay(1);
+
+       return ret;
+}
+
+static struct clk_ops tegra_emc_clk_ops = {
+       .init                   = &tegra2_emc_clk_init,
+       .enable                 = &tegra2_periph_clk_enable,
+       .disable                = &tegra2_periph_clk_disable,
+       .set_parent             = &tegra2_periph_clk_set_parent,
+       .set_rate               = &tegra2_emc_clk_set_rate,
+       .round_rate             = &tegra2_emc_clk_round_rate,
+       .reset                  = &tegra2_periph_clk_reset,
+};
+
 /* Clock doubler ops */
 static void tegra2_clk_double_init(struct clk *c)
 {
        c->mul = 2;
        c->div = 1;
        c->state = ON;
+
+       if (!c->u.periph.clk_num)
+               return;
+
        if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) &
                        PERIPH_CLK_TO_ENB_BIT(c)))
                c->state = OFF;
@@ -1130,30 +1273,10 @@ static int tegra2_audio_sync_clk_set_parent(struct clk *c, struct clk *p)
        return -EINVAL;
 }
 
-static int tegra2_audio_sync_clk_set_rate(struct clk *c, unsigned long rate)
-{
-       unsigned long parent_rate;
-       if (!c->parent) {
-               pr_err("%s: clock has no parent\n", __func__);
-               return -EINVAL;
-       }
-       parent_rate = c->parent->rate;
-       if (rate != parent_rate) {
-               pr_err("%s: %s/%ld differs from parent %s/%ld\n",
-                       __func__,
-                       c->name, rate,
-                       c->parent->name, parent_rate);
-               return -EINVAL;
-       }
-       c->rate = parent_rate;
-       return 0;
-}
-
 static struct clk_ops tegra_audio_sync_clk_ops = {
        .init       = tegra2_audio_sync_clk_init,
        .enable     = tegra2_audio_sync_clk_enable,
        .disable    = tegra2_audio_sync_clk_disable,
-       .set_rate   = tegra2_audio_sync_clk_set_rate,
        .set_parent = tegra2_audio_sync_clk_set_parent,
 };
 
@@ -1164,6 +1287,9 @@ static void tegra2_cdev_clk_init(struct clk *c)
        /* We could un-tristate the cdev1 or cdev2 pingroup here; this is
         * currently done in the pinmux code. */
        c->state = ON;
+
+       BUG_ON(!c->u.periph.clk_num);
+
        if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) &
                        PERIPH_CLK_TO_ENB_BIT(c)))
                c->state = OFF;
@@ -1171,6 +1297,8 @@ static void tegra2_cdev_clk_init(struct clk *c)
 
 static int tegra2_cdev_clk_enable(struct clk *c)
 {
+       BUG_ON(!c->u.periph.clk_num);
+
        clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
                CLK_OUT_ENB_SET + PERIPH_CLK_TO_ENB_SET_REG(c));
        return 0;
@@ -1178,6 +1306,8 @@ static int tegra2_cdev_clk_enable(struct clk *c)
 
 static void tegra2_cdev_clk_disable(struct clk *c)
 {
+       BUG_ON(!c->u.periph.clk_num);
+
        clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
                CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
 }
@@ -1489,8 +1619,6 @@ static struct clk tegra_pll_p_out4 = {
 static struct clk_pll_freq_table tegra_pll_a_freq_table[] = {
        { 28800000, 56448000, 49, 25, 1, 1},
        { 28800000, 73728000, 64, 25, 1, 1},
-       { 28800000, 11289600, 49, 25, 1, 1},
-       { 28800000, 12288000, 64, 25, 1, 1},
        { 28800000, 24000000,  5,  6, 1, 1},
        { 0, 0, 0, 0, 0, 0 },
 };
@@ -1501,7 +1629,7 @@ static struct clk tegra_pll_a = {
        .ops       = &tegra_pll_ops,
        .reg       = 0xb0,
        .parent    = &tegra_pll_p_out1,
-       .max_rate  = 56448000,
+       .max_rate  = 73728000,
        .u.pll = {
                .input_min = 2000000,
                .input_max = 31000000,
@@ -1521,7 +1649,7 @@ static struct clk tegra_pll_a_out0 = {
        .parent    = &tegra_pll_a,
        .reg       = 0xb4,
        .reg_shift = 0,
-       .max_rate  = 56448000,
+       .max_rate  = 73728000,
 };
 
 static struct clk_pll_freq_table tegra_pll_d_freq_table[] = {
@@ -1623,10 +1751,10 @@ static struct clk_pll_freq_table tegra_pll_x_freq_table[] = {
        { 26000000, 760000000,  760,  26, 1, 12},
 
        /* 608 MHz */
-       { 12000000, 608000000,  760,  12, 1, 12},
-       { 13000000, 608000000,  760,  13, 1, 12},
+       { 12000000, 608000000,  608,  12, 1, 12},
+       { 13000000, 608000000,  608,  13, 1, 12},
        { 19200000, 608000000,  380,  12, 1, 8},
-       { 26000000, 608000000,  760,  26, 1, 12},
+       { 26000000, 608000000,  608,  26, 1, 12},
 
        /* 456 MHz */
        { 12000000, 456000000,  456,  12, 1, 12},
@@ -1695,8 +1823,8 @@ static struct clk tegra_clk_d = {
 };
 
 /* dap_mclk1, belongs to the cdev1 pingroup. */
-static struct clk tegra_dev1_clk = {
-       .name      = "clk_dev1",
+static struct clk tegra_clk_cdev1 = {
+       .name      = "cdev1",
        .ops       = &tegra_cdev_clk_ops,
        .rate      = 26000000,
        .max_rate  = 26000000,
@@ -1706,8 +1834,8 @@ static struct clk tegra_dev1_clk = {
 };
 
 /* dap_mclk2, belongs to the cdev2 pingroup. */
-static struct clk tegra_dev2_clk = {
-       .name      = "clk_dev2",
+static struct clk tegra_clk_cdev2 = {
+       .name      = "cdev2",
        .ops       = &tegra_cdev_clk_ops,
        .rate      = 26000000,
        .max_rate  = 26000000,
@@ -1739,7 +1867,7 @@ static struct clk tegra_clk_audio = {
        .name      = "audio",
        .inputs    = mux_audio_sync_clk,
        .reg       = 0x38,
-       .max_rate  = 24000000,
+       .max_rate  = 73728000,
        .ops       = &tegra_audio_sync_clk_ops
 };
 
@@ -1825,7 +1953,8 @@ static struct clk tegra_clk_sclk = {
        .inputs = mux_sclk,
        .reg    = 0x28,
        .ops    = &tegra_super_ops,
-       .max_rate = 600000000,
+       .max_rate = 240000000,
+       .min_rate = 120000000,
 };
 
 static struct clk tegra_clk_virtual_cpu = {
@@ -1839,6 +1968,13 @@ static struct clk tegra_clk_virtual_cpu = {
        },
 };
 
+static struct clk tegra_clk_cop = {
+       .name      = "cop",
+       .parent    = &tegra_clk_sclk,
+       .ops       = &tegra_cop_ops,
+       .max_rate  = 240000000,
+};
+
 static struct clk tegra_clk_hclk = {
        .name           = "hclk",
        .flags          = DIV_BUS,
@@ -1856,7 +1992,7 @@ static struct clk tegra_clk_pclk = {
        .reg            = 0x30,
        .reg_shift      = 0,
        .ops            = &tegra_bus_ops,
-       .max_rate       = 108000000,
+       .max_rate       = 120000000,
 };
 
 static struct clk tegra_clk_blink = {
@@ -1948,6 +2084,18 @@ static struct clk_mux_sel mux_pclk[] = {
        { 0, 0},
 };
 
+static struct clk tegra_clk_emc = {
+       .name = "emc",
+       .ops = &tegra_emc_clk_ops,
+       .reg = 0x19c,
+       .max_rate = 800000000,
+       .inputs = mux_pllm_pllc_pllp_clkm,
+       .flags = MUX | DIV_U71 | PERIPH_EMC_ENB,
+       .u.periph = {
+               .clk_num = 57,
+       },
+};
+
 #define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg, _max, _inputs, _flags) \
        {                                               \
                .name      = _name,                     \
@@ -1980,9 +2128,8 @@ struct clk tegra_list_clks[] = {
        PERIPH_CLK("apbdma",    "tegra-dma",            NULL,   34,     0,      108000000, mux_pclk,                    0),
        PERIPH_CLK("rtc",       "rtc-tegra",            NULL,   4,      0,      32768,     mux_clk_32k,                 PERIPH_NO_RESET),
        PERIPH_CLK("timer",     "timer",                NULL,   5,      0,      26000000,  mux_clk_m,                   0),
-       PERIPH_CLK("i2s1",      "i2s.0",                NULL,   11,     0x100,  26000000,  mux_pllaout0_audio2x_pllp_clkm,      MUX | DIV_U71),
-       PERIPH_CLK("i2s2",      "i2s.1",                NULL,   18,     0x104,  26000000,  mux_pllaout0_audio2x_pllp_clkm,      MUX | DIV_U71),
-       /* FIXME: spdif has 2 clocks but 1 enable */
+       PERIPH_CLK("i2s1",      "tegra-i2s.0",          NULL,   11,     0x100,  26000000,  mux_pllaout0_audio2x_pllp_clkm,      MUX | DIV_U71),
+       PERIPH_CLK("i2s2",      "tegra-i2s.1",          NULL,   18,     0x104,  26000000,  mux_pllaout0_audio2x_pllp_clkm,      MUX | DIV_U71),
        PERIPH_CLK("spdif_out", "spdif_out",            NULL,   10,     0x108,  100000000, mux_pllaout0_audio2x_pllp_clkm,      MUX | DIV_U71),
        PERIPH_CLK("spdif_in",  "spdif_in",             NULL,   10,     0x10c,  100000000, mux_pllp_pllc_pllm,          MUX | DIV_U71),
        PERIPH_CLK("pwm",       "pwm",                  NULL,   17,     0x110,  432000000, mux_pllp_pllc_audio_clkm_clk32,      MUX | DIV_U71),
@@ -1995,13 +2142,15 @@ struct clk tegra_list_clks[] = {
        PERIPH_CLK("sbc4",      "spi_tegra.3",          NULL,   68,     0x1b4,  160000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
        PERIPH_CLK("ide",       "ide",                  NULL,   25,     0x144,  100000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* requires min voltage */
        PERIPH_CLK("ndflash",   "tegra_nand",           NULL,   13,     0x160,  164000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* scales with voltage */
-       /* FIXME: vfir shares an enable with uartb */
        PERIPH_CLK("vfir",      "vfir",                 NULL,   7,      0x168,  72000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
        PERIPH_CLK("sdmmc1",    "sdhci-tegra.0",        NULL,   14,     0x150,  52000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* scales with voltage */
        PERIPH_CLK("sdmmc2",    "sdhci-tegra.1",        NULL,   9,      0x154,  52000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* scales with voltage */
        PERIPH_CLK("sdmmc3",    "sdhci-tegra.2",        NULL,   69,     0x1bc,  52000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* scales with voltage */
        PERIPH_CLK("sdmmc4",    "sdhci-tegra.3",        NULL,   15,     0x164,  52000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* scales with voltage */
-       PERIPH_CLK("vde",       "vde",                  NULL,   61,     0x1c8,  250000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* scales with voltage and process_id */
+       PERIPH_CLK("vcp",       "tegra-avp",            "vcp",  29,     0,      250000000, mux_clk_m,                   0),
+       PERIPH_CLK("bsea",      "tegra-avp",            "bsea", 62,     0,      250000000, mux_clk_m,                   0),
+       PERIPH_CLK("bsev",      "tegra-aes",            "bsev", 63,     0,      250000000, mux_clk_m,                   0),
+       PERIPH_CLK("vde",       "tegra-avp",            "vde",  61,     0x1c8,  250000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* scales with voltage and process_id */
        PERIPH_CLK("csite",     "csite",                NULL,   73,     0x1d4,  144000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* max rate ??? */
        /* FIXME: what is la? */
        PERIPH_CLK("la",        "la",                   NULL,   76,     0x1f8,  26000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
@@ -2023,13 +2172,11 @@ struct clk tegra_list_clks[] = {
        PERIPH_CLK("uarte",     "uart.4",               NULL,   66,     0x1c4,  600000000, mux_pllp_pllc_pllm_clkm,     MUX),
        PERIPH_CLK("3d",        "3d",                   NULL,   24,     0x158,  300000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71 | PERIPH_MANUAL_RESET), /* scales with voltage and process_id */
        PERIPH_CLK("2d",        "2d",                   NULL,   21,     0x15c,  300000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71), /* scales with voltage and process_id */
-       /* FIXME: vi and vi_sensor share an enable */
        PERIPH_CLK("vi",        "tegra_camera",         "vi",   20,     0x148,  150000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71), /* scales with voltage and process_id */
        PERIPH_CLK("vi_sensor", "tegra_camera",         "vi_sensor",    20,     0x1a8,  150000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71 | PERIPH_NO_RESET), /* scales with voltage and process_id */
        PERIPH_CLK("epp",       "epp",                  NULL,   19,     0x16c,  300000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71), /* scales with voltage and process_id */
        PERIPH_CLK("mpe",       "mpe",                  NULL,   60,     0x170,  250000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71), /* scales with voltage and process_id */
        PERIPH_CLK("host1x",    "host1x",               NULL,   28,     0x180,  166000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71), /* scales with voltage and process_id */
-       /* FIXME: cve and tvo share an enable   */
        PERIPH_CLK("cve",       "cve",                  NULL,   49,     0x140,  250000000, mux_pllp_plld_pllc_clkm,     MUX | DIV_U71), /* requires min voltage */
        PERIPH_CLK("tvo",       "tvo",                  NULL,   49,     0x188,  250000000, mux_pllp_plld_pllc_clkm,     MUX | DIV_U71), /* requires min voltage */
        PERIPH_CLK("hdmi",      "hdmi",                 NULL,   51,     0x18c,  600000000, mux_pllp_plld_pllc_clkm,     MUX | DIV_U71), /* requires min voltage */
@@ -2039,7 +2186,6 @@ struct clk tegra_list_clks[] = {
        PERIPH_CLK("usbd",      "fsl-tegra-udc",        NULL,   22,     0,      480000000, mux_clk_m,                   0), /* requires min voltage */
        PERIPH_CLK("usb2",      "tegra-ehci.1",         NULL,   58,     0,      480000000, mux_clk_m,                   0), /* requires min voltage */
        PERIPH_CLK("usb3",      "tegra-ehci.2",         NULL,   59,     0,      480000000, mux_clk_m,                   0), /* requires min voltage */
-       PERIPH_CLK("emc",       "emc",                  NULL,   57,     0x19c,  800000000, mux_pllm_pllc_pllp_clkm,     MUX | DIV_U71 | PERIPH_EMC_ENB),
        PERIPH_CLK("dsi",       "dsi",                  NULL,   48,     0,      500000000, mux_plld,                    0), /* scales with voltage */
        PERIPH_CLK("csi",       "tegra_camera",         "csi",  52,     0,      72000000,  mux_pllp_out3,               0),
        PERIPH_CLK("isp",       "tegra_camera",         "isp",  23,     0,      150000000, mux_clk_m,                   0), /* same frequency as VI */
@@ -2047,6 +2193,18 @@ struct clk tegra_list_clks[] = {
        PERIPH_CLK("pex",       NULL,                   "pex",  70,     0,      26000000,  mux_clk_m,                   PERIPH_MANUAL_RESET),
        PERIPH_CLK("afi",       NULL,                   "afi",  72,     0,      26000000,  mux_clk_m,                   PERIPH_MANUAL_RESET),
        PERIPH_CLK("pcie_xclk", NULL,             "pcie_xclk",  74,     0,      26000000,  mux_clk_m,                   PERIPH_MANUAL_RESET),
+
+       SHARED_CLK("avp.sclk",  "tegra-avp",            "sclk", &tegra_clk_sclk),
+       SHARED_CLK("avp.emc",   "tegra-avp",            "emc",  &tegra_clk_emc),
+       SHARED_CLK("cpu.emc",   "cpu",                  "emc",  &tegra_clk_emc),
+       SHARED_CLK("disp1.emc", "tegradc.0",            "emc",  &tegra_clk_emc),
+       SHARED_CLK("disp2.emc", "tegradc.1",            "emc",  &tegra_clk_emc),
+       SHARED_CLK("hdmi.emc",  "hdmi",                 "emc",  &tegra_clk_emc),
+       SHARED_CLK("host.emc",  "tegra_grhost",         "emc",  &tegra_clk_emc),
+       SHARED_CLK("usbd.emc",  "fsl-tegra-udc",        "emc",  &tegra_clk_emc),
+       SHARED_CLK("usb1.emc",  "tegra-ehci.0",         "emc",  &tegra_clk_emc),
+       SHARED_CLK("usb2.emc",  "tegra-ehci.1",         "emc",  &tegra_clk_emc),
+       SHARED_CLK("usb3.emc",  "tegra-ehci.2",         "emc",  &tegra_clk_emc),
 };
 
 #define CLK_DUPLICATE(_name, _dev, _con)               \
@@ -2077,6 +2235,13 @@ struct clk_duplicate tegra_clk_duplicates[] = {
        CLK_DUPLICATE("pwm", "tegra_pwm.1", NULL),
        CLK_DUPLICATE("pwm", "tegra_pwm.2", NULL),
        CLK_DUPLICATE("pwm", "tegra_pwm.3", NULL),
+       CLK_DUPLICATE("host1x", "tegra_grhost", "host1x"),
+       CLK_DUPLICATE("2d", "tegra_grhost", "gr2d"),
+       CLK_DUPLICATE("3d", "tegra_grhost", "gr3d"),
+       CLK_DUPLICATE("epp", "tegra_grhost", "epp"),
+       CLK_DUPLICATE("mpe", "tegra_grhost", "mpe"),
+       CLK_DUPLICATE("cop", "tegra-avp", "cop"),
+       CLK_DUPLICATE("vde", "tegra-aes", "vde"),
 };
 
 #define CLK(dev, con, ck)      \
@@ -2111,10 +2276,12 @@ struct clk *tegra_ptr_clks[] = {
        &tegra_clk_hclk,
        &tegra_clk_pclk,
        &tegra_clk_d,
-       &tegra_dev1_clk,
-       &tegra_dev2_clk,
+       &tegra_clk_cdev1,
+       &tegra_clk_cdev2,
        &tegra_clk_virtual_cpu,
        &tegra_clk_blink,
+       &tegra_clk_cop,
+       &tegra_clk_emc,
 };
 
 static void tegra2_init_one_clock(struct clk *c)
@@ -2155,7 +2322,7 @@ void __init tegra2_init_clocks(void)
 
 #ifdef CONFIG_PM
 static u32 clk_rst_suspend[RST_DEVICES_NUM + CLK_OUT_ENB_NUM +
-                          PERIPH_CLK_SOURCE_NUM + 19];
+                          PERIPH_CLK_SOURCE_NUM + 22];
 
 void tegra_clk_suspend(void)
 {
@@ -2163,16 +2330,18 @@ void tegra_clk_suspend(void)
        u32 *ctx = clk_rst_suspend;
 
        *ctx++ = clk_readl(OSC_CTRL) & OSC_CTRL_MASK;
-       *ctx++ = clk_readl(tegra_pll_p.reg + PLL_BASE);
-       *ctx++ = clk_readl(tegra_pll_p.reg + PLL_MISC(&tegra_pll_p));
        *ctx++ = clk_readl(tegra_pll_c.reg + PLL_BASE);
        *ctx++ = clk_readl(tegra_pll_c.reg + PLL_MISC(&tegra_pll_c));
        *ctx++ = clk_readl(tegra_pll_a.reg + PLL_BASE);
        *ctx++ = clk_readl(tegra_pll_a.reg + PLL_MISC(&tegra_pll_a));
+       *ctx++ = clk_readl(tegra_pll_s.reg + PLL_BASE);
+       *ctx++ = clk_readl(tegra_pll_s.reg + PLL_MISC(&tegra_pll_s));
+       *ctx++ = clk_readl(tegra_pll_d.reg + PLL_BASE);
+       *ctx++ = clk_readl(tegra_pll_d.reg + PLL_MISC(&tegra_pll_d));
+       *ctx++ = clk_readl(tegra_pll_u.reg + PLL_BASE);
+       *ctx++ = clk_readl(tegra_pll_u.reg + PLL_MISC(&tegra_pll_u));
 
        *ctx++ = clk_readl(tegra_pll_m_out1.reg);
-       *ctx++ = clk_readl(tegra_pll_p_out1.reg);
-       *ctx++ = clk_readl(tegra_pll_p_out3.reg);
        *ctx++ = clk_readl(tegra_pll_a_out0.reg);
        *ctx++ = clk_readl(tegra_pll_c_out1.reg);
 
@@ -2183,6 +2352,8 @@ void tegra_clk_suspend(void)
        *ctx++ = clk_readl(tegra_clk_sclk.reg + SUPER_CLK_DIVIDER);
        *ctx++ = clk_readl(tegra_clk_pclk.reg);
 
+       *ctx++ = clk_readl(tegra_clk_audio.reg);
+
        for (off = PERIPH_CLK_SOURCE_I2S1; off <= PERIPH_CLK_SOURCE_OSC;
                        off += 4) {
                if (off == PERIPH_CLK_SOURCE_EMC)
@@ -2200,6 +2371,8 @@ void tegra_clk_suspend(void)
 
        *ctx++ = clk_readl(MISC_CLK_ENB);
        *ctx++ = clk_readl(CLK_MASK_ARM);
+
+       BUG_ON(ctx - clk_rst_suspend != ARRAY_SIZE(clk_rst_suspend));
 }
 
 void tegra_clk_resume(void)
@@ -2212,17 +2385,19 @@ void tegra_clk_resume(void)
        val |= *ctx++;
        clk_writel(val, OSC_CTRL);
 
-       clk_writel(*ctx++, tegra_pll_p.reg + PLL_BASE);
-       clk_writel(*ctx++, tegra_pll_p.reg + PLL_MISC(&tegra_pll_p));
        clk_writel(*ctx++, tegra_pll_c.reg + PLL_BASE);
        clk_writel(*ctx++, tegra_pll_c.reg + PLL_MISC(&tegra_pll_c));
        clk_writel(*ctx++, tegra_pll_a.reg + PLL_BASE);
        clk_writel(*ctx++, tegra_pll_a.reg + PLL_MISC(&tegra_pll_a));
-       udelay(300);
+       clk_writel(*ctx++, tegra_pll_s.reg + PLL_BASE);
+       clk_writel(*ctx++, tegra_pll_s.reg + PLL_MISC(&tegra_pll_s));
+       clk_writel(*ctx++, tegra_pll_d.reg + PLL_BASE);
+       clk_writel(*ctx++, tegra_pll_d.reg + PLL_MISC(&tegra_pll_d));
+       clk_writel(*ctx++, tegra_pll_u.reg + PLL_BASE);
+       clk_writel(*ctx++, tegra_pll_u.reg + PLL_MISC(&tegra_pll_u));
+       udelay(1000);
 
        clk_writel(*ctx++, tegra_pll_m_out1.reg);
-       clk_writel(*ctx++, tegra_pll_p_out1.reg);
-       clk_writel(*ctx++, tegra_pll_p_out3.reg);
        clk_writel(*ctx++, tegra_pll_a_out0.reg);
        clk_writel(*ctx++, tegra_pll_c_out1.reg);
 
@@ -2233,6 +2408,8 @@ void tegra_clk_resume(void)
        clk_writel(*ctx++, tegra_clk_sclk.reg + SUPER_CLK_DIVIDER);
        clk_writel(*ctx++, tegra_clk_pclk.reg);
 
+       clk_writel(*ctx++, tegra_clk_audio.reg);
+
        /* enable all clocks before configuring clock sources */
        clk_writel(0xbffffff9ul, CLK_OUT_ENB);
        clk_writel(0xfefffff7ul, CLK_OUT_ENB + 4);