Merge branches 'clk-imx7ulp', 'clk-imx6-fixes', 'clk-imx-fixes', 'clk-imx8qxp' and 'clk-imx8mq' into clk-next
- NXP i.MX7ULP SoC clock support - Support for i.MX8QXP SoC clocks - Support for NXP i.MX8MQ clock controllers * clk-imx7ulp: clk: imx: add imx7ulp clk driver clk: imx: implement new clk_hw based APIs clk: imx: make mux parent strings const dt-bindings: clock: add imx7ulp clock binding doc clk: imx: add imx7ulp composite clk support clk: imx: add pfdv2 support clk: imx: add pllv4 support clk: fractional-divider: add CLK_FRAC_DIVIDER_ZERO_BASED flag support clk: imx: add gatable clock divider support * clk-imx6-fixes: clk: imx6q: handle ENET PLL bypass clk: imx6q: optionally get CCM inputs via standard clock handles clk: imx6q: reset exclusive gates on init * clk-imx-fixes: clk: imx6q: add DCICx clocks gate clk: imx6sl: ensure MMDC CH0 handshake is bypassed clk: imx7d: remove UART1 clock setting * clk-imx8qxp: clk: imx: add imx8qxp lpcg driver clk: imx: add lpcg clock support clk: imx: add imx8qxp clk driver clk: imx: add scu clock common part clk: imx: add configuration option for mmio clks dt-bindings: clock: add imx8qxp lpcg clock binding dt-bindings: clock: imx8qxp: add SCU clock IDs firmware: imx: add pm svc headfile dt-bindings: fsl: scu: update power domain binding firmware: imx: remove resource id enums dt-bindings: imx: add scu resource id headfile * clk-imx8mq: clk: imx: Make the i.MX8MQ CCM clock driver CLK_IMX8MQ dependant clk: imx: remove redundant initialization of ret to zero clk: imx: Add SCCG PLL type clk: imx: Add fractional PLL output clock clk: imx: Add clock driver for i.MX8MQ CCM clk: imx: Add imx composite clock dt-bindings: Add binding for i.MX8MQ CCM
这个提交包含在:

@@ -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);
|
||||
|
在新工单中引用
屏蔽一个用户