Merge branches 'clk-imx7ulp', 'clk-imx6-fixes', 'clk-imx-fixes', 'clk-imx8qxp' and...
[sfrench/cifs-2.6.git] / drivers / clk / imx / clk-imx6q.c
index bbe0c60f4d09f868a0a5c7d5cca22d72e66e0013..716eac3136b4d712f5865476db52188bf11b6a85 100644 (file)
@@ -225,6 +225,41 @@ static void of_assigned_ldb_sels(struct device_node *node,
        }
 }
 
+static bool pll6_bypassed(struct device_node *node)
+{
+       int index, ret, num_clocks;
+       struct of_phandle_args clkspec;
+
+       num_clocks = of_count_phandle_with_args(node, "assigned-clocks",
+                                               "#clock-cells");
+       if (num_clocks < 0)
+               return false;
+
+       for (index = 0; index < num_clocks; index++) {
+               ret = of_parse_phandle_with_args(node, "assigned-clocks",
+                                                "#clock-cells", index,
+                                                &clkspec);
+               if (ret < 0)
+                       return false;
+
+               if (clkspec.np == node &&
+                   clkspec.args[0] == IMX6QDL_PLL6_BYPASS)
+                       break;
+       }
+
+       /* PLL6 bypass is not part of the assigned clock list */
+       if (index == num_clocks)
+               return false;
+
+       ret = of_parse_phandle_with_args(node, "assigned-clock-parents",
+                                        "#clock-cells", index, &clkspec);
+
+       if (clkspec.args[0] != IMX6QDL_CLK_PLL6)
+               return true;
+
+       return false;
+}
+
 #define CCM_CCDR               0x04
 #define CCM_CCSR               0x0c
 #define CCM_CS2CDR             0x2c
@@ -414,12 +449,24 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
        int ret;
 
        clk[IMX6QDL_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
-       clk[IMX6QDL_CLK_CKIL] = imx_obtain_fixed_clock("ckil", 0);
-       clk[IMX6QDL_CLK_CKIH] = imx_obtain_fixed_clock("ckih1", 0);
-       clk[IMX6QDL_CLK_OSC] = imx_obtain_fixed_clock("osc", 0);
+       clk[IMX6QDL_CLK_CKIL] = of_clk_get_by_name(ccm_node, "ckil");
+       if (IS_ERR(clk[IMX6QDL_CLK_CKIL]))
+               clk[IMX6QDL_CLK_CKIL] = imx_obtain_fixed_clock("ckil", 0);
+       clk[IMX6QDL_CLK_CKIH] = of_clk_get_by_name(ccm_node, "ckih1");
+       if (IS_ERR(clk[IMX6QDL_CLK_CKIH]))
+               clk[IMX6QDL_CLK_CKIH] = imx_obtain_fixed_clock("ckih1", 0);
+       clk[IMX6QDL_CLK_OSC] = of_clk_get_by_name(ccm_node, "osc");
+       if (IS_ERR(clk[IMX6QDL_CLK_OSC]))
+               clk[IMX6QDL_CLK_OSC] = imx_obtain_fixed_clock("osc", 0);
+
        /* Clock source from external clock via CLK1/2 PADs */
-       clk[IMX6QDL_CLK_ANACLK1] = imx_obtain_fixed_clock("anaclk1", 0);
-       clk[IMX6QDL_CLK_ANACLK2] = imx_obtain_fixed_clock("anaclk2", 0);
+       clk[IMX6QDL_CLK_ANACLK1] = of_clk_get_by_name(ccm_node, "anaclk1");
+       if (IS_ERR(clk[IMX6QDL_CLK_ANACLK1]))
+               clk[IMX6QDL_CLK_ANACLK1] = imx_obtain_fixed_clock("anaclk1", 0);
+
+       clk[IMX6QDL_CLK_ANACLK2] = of_clk_get_by_name(ccm_node, "anaclk2");
+       if (IS_ERR(clk[IMX6QDL_CLK_ANACLK2]))
+               clk[IMX6QDL_CLK_ANACLK2] = imx_obtain_fixed_clock("anaclk2", 0);
 
        np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");
        anatop_base = base = of_iomap(np, 0);
@@ -491,16 +538,32 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
        clk[IMX6QDL_CLK_USBPHY1_GATE] = imx_clk_gate("usbphy1_gate", "dummy", base + 0x10, 6);
        clk[IMX6QDL_CLK_USBPHY2_GATE] = imx_clk_gate("usbphy2_gate", "dummy", base + 0x20, 6);
 
-       clk[IMX6QDL_CLK_SATA_REF] = imx_clk_fixed_factor("sata_ref", "pll6_enet", 1, 5);
-       clk[IMX6QDL_CLK_PCIE_REF] = imx_clk_fixed_factor("pcie_ref", "pll6_enet", 1, 4);
+       /*
+        * The ENET PLL is special in that is has multiple outputs with
+        * different post-dividers that are all affected by the single bypass
+        * bit, so a single mux bit affects 3 independent branches of the clock
+        * tree. There is no good way to model this in the clock framework and
+        * dynamically changing the bypass bit, will yield unexpected results.
+        * So we treat any configuration that bypasses the ENET PLL as
+        * essentially static with the divider ratios reflecting the bypass
+        * status.
+        *
+        */
+       if (!pll6_bypassed(ccm_node)) {
+               clk[IMX6QDL_CLK_SATA_REF] = imx_clk_fixed_factor("sata_ref", "pll6_enet", 1, 5);
+               clk[IMX6QDL_CLK_PCIE_REF] = imx_clk_fixed_factor("pcie_ref", "pll6_enet", 1, 4);
+               clk[IMX6QDL_CLK_ENET_REF] = clk_register_divider_table(NULL, "enet_ref", "pll6_enet", 0,
+                                               base + 0xe0, 0, 2, 0, clk_enet_ref_table,
+                                               &imx_ccm_lock);
+       } else {
+               clk[IMX6QDL_CLK_SATA_REF] = imx_clk_fixed_factor("sata_ref", "pll6_enet", 1, 1);
+               clk[IMX6QDL_CLK_PCIE_REF] = imx_clk_fixed_factor("pcie_ref", "pll6_enet", 1, 1);
+               clk[IMX6QDL_CLK_ENET_REF] = imx_clk_fixed_factor("enet_ref", "pll6_enet", 1, 1);
+       }
 
        clk[IMX6QDL_CLK_SATA_REF_100M] = imx_clk_gate("sata_ref_100m", "sata_ref", base + 0xe0, 20);
        clk[IMX6QDL_CLK_PCIE_REF_125M] = imx_clk_gate("pcie_ref_125m", "pcie_ref", base + 0xe0, 19);
 
-       clk[IMX6QDL_CLK_ENET_REF] = clk_register_divider_table(NULL, "enet_ref", "pll6_enet", 0,
-                       base + 0xe0, 0, 2, 0, clk_enet_ref_table,
-                       &imx_ccm_lock);
-
        clk[IMX6QDL_CLK_LVDS1_SEL] = imx_clk_mux("lvds1_sel", base + 0x160, 0, 5, lvds_sels, ARRAY_SIZE(lvds_sels));
        clk[IMX6QDL_CLK_LVDS2_SEL] = imx_clk_mux("lvds2_sel", base + 0x160, 5, 5, lvds_sels, ARRAY_SIZE(lvds_sels));
 
@@ -508,8 +571,12 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
         * lvds1_gate and lvds2_gate are pseudo-gates.  Both can be
         * independently configured as clock inputs or outputs.  We treat
         * the "output_enable" bit as a gate, even though it's really just
-        * enabling clock output.
+        * enabling clock output. Initially the gate bits are cleared, as
+        * otherwise the exclusive configuration gets locked in the setup done
+        * by software running before the clock driver, with no way to change
+        * it.
         */
+       writel(readl(base + 0x160) & ~0x3c00, base + 0x160);
        clk[IMX6QDL_CLK_LVDS1_GATE] = imx_clk_gate_exclusive("lvds1_gate", "lvds1_sel", base + 0x160, 10, BIT(12));
        clk[IMX6QDL_CLK_LVDS2_GATE] = imx_clk_gate_exclusive("lvds2_gate", "lvds2_sel", base + 0x160, 11, BIT(13));
 
@@ -737,6 +804,8 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
        clk[IMX6QDL_CLK_CAN1_SERIAL]  = imx_clk_gate2("can1_serial",   "can_root",          base + 0x68, 16);
        clk[IMX6QDL_CLK_CAN2_IPG]     = imx_clk_gate2("can2_ipg",      "ipg",               base + 0x68, 18);
        clk[IMX6QDL_CLK_CAN2_SERIAL]  = imx_clk_gate2("can2_serial",   "can_root",          base + 0x68, 20);
+       clk[IMX6QDL_CLK_DCIC1]        = imx_clk_gate2("dcic1",         "ipu1_podf",         base + 0x68, 24);
+       clk[IMX6QDL_CLK_DCIC2]        = imx_clk_gate2("dcic2",         "ipu2_podf",         base + 0x68, 26);
        clk[IMX6QDL_CLK_ECSPI1]       = imx_clk_gate2("ecspi1",        "ecspi_root",        base + 0x6c, 0);
        clk[IMX6QDL_CLK_ECSPI2]       = imx_clk_gate2("ecspi2",        "ecspi_root",        base + 0x6c, 2);
        clk[IMX6QDL_CLK_ECSPI3]       = imx_clk_gate2("ecspi3",        "ecspi_root",        base + 0x6c, 4);