These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / clk / tegra / clk-tegra124.c
index 11f857c..87975f7 100644 (file)
@@ -15,7 +15,6 @@
  */
 
 #include <linux/io.h>
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/of.h>
@@ -24,6 +23,7 @@
 #include <linux/export.h>
 #include <linux/clk/tegra.h>
 #include <dt-bindings/clock/tegra124-car.h>
+#include <dt-bindings/reset/tegra124-car.h>
 
 #include "clk.h"
 #include "clk-id.h"
@@ -39,6 +39,9 @@
 #define CLK_SOURCE_CSITE 0x1d4
 #define CLK_SOURCE_EMC 0x19c
 
+#define RST_DFLL_DVCO                  0x2f4
+#define DVFS_DFLL_RESET_SHIFT          0
+
 #define PLLC_BASE 0x80
 #define PLLC_OUT 0x84
 #define PLLC_MISC2 0x88
@@ -94,6 +97,8 @@
 #define PMC_PLLM_WB0_OVERRIDE 0x1dc
 #define PMC_PLLM_WB0_OVERRIDE_2 0x2b0
 
+#define CCLKG_BURST_POLICY 0x368
+
 #define UTMIP_PLL_CFG2 0x488
 #define UTMIP_PLL_CFG2_STABLE_COUNT(x) (((x) & 0xffff) << 6)
 #define UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(x) (((x) & 0x3f) << 18)
 #ifdef CONFIG_PM_SLEEP
 static struct cpu_clk_suspend_context {
        u32 clk_csite_src;
+       u32 cclkg_burst;
+       u32 cclkg_divider;
 } tegra124_cpu_clk_sctx;
 #endif
 
@@ -152,11 +159,6 @@ static unsigned long tegra124_input_freq[] = {
        [12] = 260000000,
 };
 
-static const char *mux_pllmcp_clkm[] = {
-       "pll_m", "pll_c", "pll_p", "clk_m", "pll_m_ud", "pll_c2", "pll_c3",
-};
-#define mux_pllmcp_clkm_idx NULL
-
 static struct div_nmp pllxc_nmp = {
        .divm_shift = 0,
        .divm_width = 8,
@@ -791,7 +793,6 @@ static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = {
        [tegra_clk_i2c2] = { .dt_id = TEGRA124_CLK_I2C2, .present = true },
        [tegra_clk_uartc] = { .dt_id = TEGRA124_CLK_UARTC, .present = true },
        [tegra_clk_mipi_cal] = { .dt_id = TEGRA124_CLK_MIPI_CAL, .present = true },
-       [tegra_clk_emc] = { .dt_id = TEGRA124_CLK_EMC, .present = true },
        [tegra_clk_usb2] = { .dt_id = TEGRA124_CLK_USB2, .present = true },
        [tegra_clk_usb3] = { .dt_id = TEGRA124_CLK_USB3, .present = true },
        [tegra_clk_vde_8] = { .dt_id = TEGRA124_CLK_VDE, .present = true },
@@ -1127,13 +1128,7 @@ static __init void tegra124_periph_clk_init(void __iomem *clk_base,
                                             periph_clk_enb_refcnt);
        clks[TEGRA124_CLK_DSIB] = clk;
 
-       /* emc mux */
-       clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
-                              ARRAY_SIZE(mux_pllmcp_clkm), 0,
-                              clk_base + CLK_SOURCE_EMC,
-                              29, 3, 0, &emc_lock);
-
-       clk = tegra_clk_register_mc("mc", "emc_mux", clk_base + CLK_SOURCE_EMC,
+       clk = tegra_clk_register_mc("mc", "emc", clk_base + CLK_SOURCE_EMC,
                                    &emc_lock);
        clks[TEGRA124_CLK_MC] = clk;
 
@@ -1331,12 +1326,22 @@ static void tegra124_cpu_clock_suspend(void)
        tegra124_cpu_clk_sctx.clk_csite_src =
                                readl(clk_base + CLK_SOURCE_CSITE);
        writel(3 << 30, clk_base + CLK_SOURCE_CSITE);
+
+       tegra124_cpu_clk_sctx.cclkg_burst =
+                               readl(clk_base + CCLKG_BURST_POLICY);
+       tegra124_cpu_clk_sctx.cclkg_divider =
+                               readl(clk_base + CCLKG_BURST_POLICY + 4);
 }
 
 static void tegra124_cpu_clock_resume(void)
 {
        writel(tegra124_cpu_clk_sctx.clk_csite_src,
                                clk_base + CLK_SOURCE_CSITE);
+
+       writel(tegra124_cpu_clk_sctx.cclkg_burst,
+                                       clk_base + CCLKG_BURST_POLICY);
+       writel(tegra124_cpu_clk_sctx.cclkg_divider,
+                                       clk_base + CCLKG_BURST_POLICY + 4);
 }
 #endif
 
@@ -1389,7 +1394,6 @@ static struct tegra_clk_init_table common_init_table[] __initdata = {
        {TEGRA124_CLK_XUSB_HOST_SRC, TEGRA124_CLK_PLL_RE_OUT, 112000000, 0},
        {TEGRA124_CLK_SATA, TEGRA124_CLK_PLL_P, 104000000, 0},
        {TEGRA124_CLK_SATA_OOB, TEGRA124_CLK_PLL_P, 204000000, 0},
-       {TEGRA124_CLK_EMC, TEGRA124_CLK_CLK_MAX, 0, 1},
        {TEGRA124_CLK_MSELECT, TEGRA124_CLK_CLK_MAX, 0, 1},
        {TEGRA124_CLK_CSITE, TEGRA124_CLK_CLK_MAX, 0, 1},
        {TEGRA124_CLK_TSENSOR, TEGRA124_CLK_CLK_M, 400000, 0},
@@ -1413,6 +1417,10 @@ static struct tegra_clk_init_table tegra132_init_table[] __initdata = {
        {TEGRA124_CLK_CLK_MAX, TEGRA124_CLK_CLK_MAX, 0, 0},
 };
 
+static struct tegra_audio_clk_info tegra124_audio_plls[] = {
+       { "pll_a", &pll_a_params, tegra_clk_pll_a, "pll_p_out1" },
+};
+
 /**
  * tegra124_clock_apply_init_table - initialize clocks on Tegra124 SoCs
  *
@@ -1427,6 +1435,68 @@ static void __init tegra124_clock_apply_init_table(void)
        tegra_init_from_table(tegra124_init_table, clks, TEGRA124_CLK_CLK_MAX);
 }
 
+/**
+ * tegra124_car_barrier - wait for pending writes to the CAR to complete
+ *
+ * Wait for any outstanding writes to the CAR MMIO space from this CPU
+ * to complete before continuing execution.  No return value.
+ */
+static void tegra124_car_barrier(void)
+{
+       readl_relaxed(clk_base + RST_DFLL_DVCO);
+}
+
+/**
+ * tegra124_clock_assert_dfll_dvco_reset - assert the DFLL's DVCO reset
+ *
+ * Assert the reset line of the DFLL's DVCO.  No return value.
+ */
+static void tegra124_clock_assert_dfll_dvco_reset(void)
+{
+       u32 v;
+
+       v = readl_relaxed(clk_base + RST_DFLL_DVCO);
+       v |= (1 << DVFS_DFLL_RESET_SHIFT);
+       writel_relaxed(v, clk_base + RST_DFLL_DVCO);
+       tegra124_car_barrier();
+}
+
+/**
+ * tegra124_clock_deassert_dfll_dvco_reset - deassert the DFLL's DVCO reset
+ *
+ * Deassert the reset line of the DFLL's DVCO, allowing the DVCO to
+ * operate.  No return value.
+ */
+static void tegra124_clock_deassert_dfll_dvco_reset(void)
+{
+       u32 v;
+
+       v = readl_relaxed(clk_base + RST_DFLL_DVCO);
+       v &= ~(1 << DVFS_DFLL_RESET_SHIFT);
+       writel_relaxed(v, clk_base + RST_DFLL_DVCO);
+       tegra124_car_barrier();
+}
+
+static int tegra124_reset_assert(unsigned long id)
+{
+       if (id == TEGRA124_RST_DFLL_DVCO)
+               tegra124_clock_assert_dfll_dvco_reset();
+       else
+               return -EINVAL;
+
+       return 0;
+}
+
+static int tegra124_reset_deassert(unsigned long id)
+{
+       if (id == TEGRA124_RST_DFLL_DVCO)
+               tegra124_clock_deassert_dfll_dvco_reset();
+       else
+               return -EINVAL;
+
+       return 0;
+}
+
 /**
  * tegra132_clock_apply_init_table - initialize clocks on Tegra132 SoCs
  *
@@ -1489,7 +1559,9 @@ static void __init tegra124_132_clock_init_pre(struct device_node *np)
        tegra_fixed_clk_init(tegra124_clks);
        tegra124_pll_init(clk_base, pmc_base);
        tegra124_periph_clk_init(clk_base, pmc_base);
-       tegra_audio_clk_init(clk_base, pmc_base, tegra124_clks, &pll_a_params);
+       tegra_audio_clk_init(clk_base, pmc_base, tegra124_clks,
+                            tegra124_audio_plls,
+                            ARRAY_SIZE(tegra124_audio_plls));
        tegra_pmc_clk_init(pmc_base, tegra124_clks);
 
        /* For Tegra124 & Tegra132, PLLD is the only source for DSIA & DSIB */
@@ -1512,7 +1584,13 @@ static void __init tegra124_132_clock_init_post(struct device_node *np)
 {
        tegra_super_clk_gen4_init(clk_base, pmc_base, tegra124_clks,
                                  &pll_x_params);
+       tegra_init_special_resets(1, tegra124_reset_assert,
+                                 tegra124_reset_deassert);
        tegra_add_of_provider(np);
+
+       clks[TEGRA124_CLK_EMC] = tegra_clk_register_emc(clk_base, np,
+                                                       &emc_lock);
+
        tegra_register_devclks(devclks, ARRAY_SIZE(devclks));
 
        tegra_cpu_car_ops = &tegra124_cpu_car_ops;