]> Pileus Git - ~andy/linux/blobdiff - drivers/clk/tegra/clk-tegra114.c
Merge tag 'clk-for-linus-3.12' of git://git.linaro.org/people/mturquette/linux
[~andy/linux] / drivers / clk / tegra / clk-tegra114.c
index b6015cb4fc01af4f7f92f898b4373748ad73b008..9467da7dee4918a60762700442d9685fc658ab3c 100644 (file)
 /* Tegra CPU clock and reset control regs */
 #define CLK_RST_CONTROLLER_CPU_CMPLX_STATUS    0x470
 
+#ifdef CONFIG_PM_SLEEP
+static struct cpu_clk_suspend_context {
+       u32 clk_csite_src;
+       u32 cclkg_burst;
+       u32 cclkg_divider;
+} tegra114_cpu_clk_sctx;
+#endif
+
 static int periph_clk_enb_refcnt[CLK_OUT_ENB_NUM * 32];
 
 static void __iomem *clk_base;
@@ -1558,7 +1566,8 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base)
 
        /* audio0 */
        clk = clk_register_mux(NULL, "audio0_mux", mux_audio_sync_clk,
-                              ARRAY_SIZE(mux_audio_sync_clk), 0,
+                              ARRAY_SIZE(mux_audio_sync_clk),
+                              CLK_SET_RATE_NO_REPARENT,
                               clk_base + AUDIO_SYNC_CLK_I2S0, 0, 3, 0,
                               NULL);
        clks[audio0_mux] = clk;
@@ -1570,7 +1579,8 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base)
 
        /* audio1 */
        clk = clk_register_mux(NULL, "audio1_mux", mux_audio_sync_clk,
-                              ARRAY_SIZE(mux_audio_sync_clk), 0,
+                              ARRAY_SIZE(mux_audio_sync_clk),
+                              CLK_SET_RATE_NO_REPARENT,
                               clk_base + AUDIO_SYNC_CLK_I2S1, 0, 3, 0,
                               NULL);
        clks[audio1_mux] = clk;
@@ -1582,7 +1592,8 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base)
 
        /* audio2 */
        clk = clk_register_mux(NULL, "audio2_mux", mux_audio_sync_clk,
-                              ARRAY_SIZE(mux_audio_sync_clk), 0,
+                              ARRAY_SIZE(mux_audio_sync_clk),
+                              CLK_SET_RATE_NO_REPARENT,
                               clk_base + AUDIO_SYNC_CLK_I2S2, 0, 3, 0,
                               NULL);
        clks[audio2_mux] = clk;
@@ -1594,7 +1605,8 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base)
 
        /* audio3 */
        clk = clk_register_mux(NULL, "audio3_mux", mux_audio_sync_clk,
-                              ARRAY_SIZE(mux_audio_sync_clk), 0,
+                              ARRAY_SIZE(mux_audio_sync_clk),
+                              CLK_SET_RATE_NO_REPARENT,
                               clk_base + AUDIO_SYNC_CLK_I2S3, 0, 3, 0,
                               NULL);
        clks[audio3_mux] = clk;
@@ -1606,7 +1618,8 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base)
 
        /* audio4 */
        clk = clk_register_mux(NULL, "audio4_mux", mux_audio_sync_clk,
-                              ARRAY_SIZE(mux_audio_sync_clk), 0,
+                              ARRAY_SIZE(mux_audio_sync_clk),
+                              CLK_SET_RATE_NO_REPARENT,
                               clk_base + AUDIO_SYNC_CLK_I2S4, 0, 3, 0,
                               NULL);
        clks[audio4_mux] = clk;
@@ -1618,7 +1631,8 @@ static void __init tegra114_audio_clk_init(void __iomem *clk_base)
 
        /* spdif */
        clk = clk_register_mux(NULL, "spdif_mux", mux_audio_sync_clk,
-                              ARRAY_SIZE(mux_audio_sync_clk), 0,
+                              ARRAY_SIZE(mux_audio_sync_clk),
+                              CLK_SET_RATE_NO_REPARENT,
                               clk_base + AUDIO_SYNC_CLK_SPDIF, 0, 3, 0,
                               NULL);
        clks[spdif_mux] = clk;
@@ -1713,7 +1727,8 @@ static void __init tegra114_pmc_clk_init(void __iomem *pmc_base)
 
        /* clk_out_1 */
        clk = clk_register_mux(NULL, "clk_out_1_mux", clk_out1_parents,
-                              ARRAY_SIZE(clk_out1_parents), 0,
+                              ARRAY_SIZE(clk_out1_parents),
+                              CLK_SET_RATE_NO_REPARENT,
                               pmc_base + PMC_CLK_OUT_CNTRL, 6, 3, 0,
                               &clk_out_lock);
        clks[clk_out_1_mux] = clk;
@@ -1725,7 +1740,8 @@ static void __init tegra114_pmc_clk_init(void __iomem *pmc_base)
 
        /* clk_out_2 */
        clk = clk_register_mux(NULL, "clk_out_2_mux", clk_out2_parents,
-                              ARRAY_SIZE(clk_out2_parents), 0,
+                              ARRAY_SIZE(clk_out2_parents),
+                              CLK_SET_RATE_NO_REPARENT,
                               pmc_base + PMC_CLK_OUT_CNTRL, 14, 3, 0,
                               &clk_out_lock);
        clks[clk_out_2_mux] = clk;
@@ -1737,7 +1753,8 @@ static void __init tegra114_pmc_clk_init(void __iomem *pmc_base)
 
        /* clk_out_3 */
        clk = clk_register_mux(NULL, "clk_out_3_mux", clk_out3_parents,
-                              ARRAY_SIZE(clk_out3_parents), 0,
+                              ARRAY_SIZE(clk_out3_parents),
+                              CLK_SET_RATE_NO_REPARENT,
                               pmc_base + PMC_CLK_OUT_CNTRL, 22, 3, 0,
                               &clk_out_lock);
        clks[clk_out_3_mux] = clk;
@@ -2055,7 +2072,8 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base)
 
        /* dsia */
        clk = clk_register_mux(NULL, "dsia_mux", mux_plld_out0_plld2_out0,
-                              ARRAY_SIZE(mux_plld_out0_plld2_out0), 0,
+                              ARRAY_SIZE(mux_plld_out0_plld2_out0),
+                              CLK_SET_RATE_NO_REPARENT,
                               clk_base + PLLD_BASE, 25, 1, 0, &pll_d_lock);
        clks[dsia_mux] = clk;
        clk = tegra_clk_register_periph_gate("dsia", "dsia_mux", 0, clk_base,
@@ -2065,7 +2083,8 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base)
 
        /* dsib */
        clk = clk_register_mux(NULL, "dsib_mux", mux_plld_out0_plld2_out0,
-                              ARRAY_SIZE(mux_plld_out0_plld2_out0), 0,
+                              ARRAY_SIZE(mux_plld_out0_plld2_out0),
+                              CLK_SET_RATE_NO_REPARENT,
                               clk_base + PLLD2_BASE, 25, 1, 0, &pll_d2_lock);
        clks[dsib_mux] = clk;
        clk = tegra_clk_register_periph_gate("dsib", "dsib_mux", 0, clk_base,
@@ -2102,7 +2121,8 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base)
 
        /* emc */
        clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
-                              ARRAY_SIZE(mux_pllmcp_clkm), 0,
+                              ARRAY_SIZE(mux_pllmcp_clkm),
+                              CLK_SET_RATE_NO_REPARENT,
                               clk_base + CLK_SOURCE_EMC,
                               29, 3, 0, NULL);
        clk = tegra_clk_register_periph_gate("emc", "emc_mux", 0, clk_base,
@@ -2142,9 +2162,39 @@ static void tegra114_disable_cpu_clock(u32 cpu)
        /* flow controller would take care in the power sequence. */
 }
 
+#ifdef CONFIG_PM_SLEEP
+static void tegra114_cpu_clock_suspend(void)
+{
+       /* switch coresite to clk_m, save off original source */
+       tegra114_cpu_clk_sctx.clk_csite_src =
+                               readl(clk_base + CLK_SOURCE_CSITE);
+       writel(3 << 30, clk_base + CLK_SOURCE_CSITE);
+
+       tegra114_cpu_clk_sctx.cclkg_burst =
+                               readl(clk_base + CCLKG_BURST_POLICY);
+       tegra114_cpu_clk_sctx.cclkg_divider =
+                               readl(clk_base + CCLKG_BURST_POLICY + 4);
+}
+
+static void tegra114_cpu_clock_resume(void)
+{
+       writel(tegra114_cpu_clk_sctx.clk_csite_src,
+                                       clk_base + CLK_SOURCE_CSITE);
+
+       writel(tegra114_cpu_clk_sctx.cclkg_burst,
+                                       clk_base + CCLKG_BURST_POLICY);
+       writel(tegra114_cpu_clk_sctx.cclkg_divider,
+                                       clk_base + CCLKG_BURST_POLICY + 4);
+}
+#endif
+
 static struct tegra_cpu_car_ops tegra114_cpu_car_ops = {
        .wait_for_reset = tegra114_wait_cpu_in_reset,
        .disable_clock  = tegra114_disable_cpu_clock,
+#ifdef CONFIG_PM_SLEEP
+       .suspend        = tegra114_cpu_clock_suspend,
+       .resume         = tegra114_cpu_clock_resume,
+#endif
 };
 
 static const struct of_device_id pmc_match[] __initconst = {
@@ -2156,7 +2206,7 @@ static const struct of_device_id pmc_match[] __initconst = {
  * dfll_soc/dfll_ref apparently must be kept enabled, otherwise I2C5
  * breaks
  */
-static __initdata struct tegra_clk_init_table init_table[] = {
+static struct tegra_clk_init_table init_table[] __initdata = {
        {uarta, pll_p, 408000000, 0},
        {uartb, pll_p, 408000000, 0},
        {uartc, pll_p, 408000000, 0},