clk: imx7ulp: make it easy to change ARM core clk
authorPeng Fan <peng.fan@nxp.com>
Mon, 16 Mar 2020 08:32:33 +0000 (16:32 +0800)
committerShawn Guo <shawnguo@kernel.org>
Tue, 14 Apr 2020 13:35:58 +0000 (21:35 +0800)
ARM clk could only source from divcore or hsrun_divcore.

Follow what we already used on i.MX7D and i.MX8M SoCs, use
imx_clk_hw_cpu API. When ARM core is running normaly,
whether divcore or hwrun_divcore will finally source
from SPLL_PFD0. However SPLL_PFD0 is marked with CLK_SET_GATE,
so we need to disable SPLL_PFD0, when configure the rate.
So add CORE and HSRUN_CORE virtual clk to make it easy to
configure the clk using imx_clk_hw_cpu API.

Since CORE and HSRUN_CORE already marked with CLK_IS_CRITICAL, no
need to set ARM as CLK_IS_CRITICAL. And when set the rate of ARM clk,
prograting it the parent with CLK_SET_RATE_PARENT will finally set
the SPLL_PFD0 clk.

Signed-off-by: Peng Fan <peng.fan@nxp.com>
Reviewed-by: Abel Vesa <abel.vesa@nxp.com>
Signed-off-by: Shawn Guo <shawnguo@kernel.org>
drivers/clk/imx/clk-imx7ulp.c
include/dt-bindings/clock/imx7ulp-clock.h

index 3710aa0dee9bf4d28de242ca38a68a935f6cf4d3..634c0b6636b0e47f40c350e4e4763a6c3e4f30d3 100644 (file)
@@ -29,7 +29,7 @@ static const char * const ddr_sels[]          = { "apll_pfd_sel", "dummy", "dummy", "dum
 static const char * const nic_sels[]           = { "firc", "ddr_clk", };
 static const char * const periph_plat_sels[]   = { "dummy", "nic1_bus_clk", "nic1_clk", "ddr_clk", "apll_pfd2", "apll_pfd1", "apll_pfd0", "upll", };
 static const char * const periph_bus_sels[]    = { "dummy", "sosc_bus_clk", "dummy", "firc_bus_clk", "rosc", "nic1_bus_clk", "nic1_clk", "spll_bus_clk", };
-static const char * const arm_sels[]           = { "divcore", "dummy", "dummy", "hsrun_divcore", };
+static const char * const arm_sels[]           = { "core", "dummy", "dummy", "hsrun_core", };
 
 /* used by sosc/sirc/firc/ddr/spll/apll dividers */
 static const struct clk_div_table ulp_div_table[] = {
@@ -121,7 +121,9 @@ static void __init imx7ulp_clk_scg1_init(struct device_node *np)
        hws[IMX7ULP_CLK_DDR_SEL]        = imx_clk_hw_mux_flags("ddr_sel", base + 0x30, 24, 2, ddr_sels, ARRAY_SIZE(ddr_sels), CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE);
 
        hws[IMX7ULP_CLK_CORE_DIV]       = imx_clk_hw_divider_flags("divcore",   "scs_sel",  base + 0x14, 16, 4, CLK_SET_RATE_PARENT);
+       hws[IMX7ULP_CLK_CORE]           = imx_clk_hw_cpu("core", "divcore", hws[IMX7ULP_CLK_CORE_DIV]->clk, hws[IMX7ULP_CLK_SYS_SEL]->clk, hws[IMX7ULP_CLK_SPLL_SEL]->clk, hws[IMX7ULP_CLK_FIRC]->clk);
        hws[IMX7ULP_CLK_HSRUN_CORE_DIV] = imx_clk_hw_divider_flags("hsrun_divcore", "hsrun_scs_sel", base + 0x1c, 16, 4, CLK_SET_RATE_PARENT);
+       hws[IMX7ULP_CLK_HSRUN_CORE] = imx_clk_hw_cpu("hsrun_core", "hsrun_divcore", hws[IMX7ULP_CLK_HSRUN_CORE_DIV]->clk, hws[IMX7ULP_CLK_HSRUN_SYS_SEL]->clk, hws[IMX7ULP_CLK_SPLL_SEL]->clk, hws[IMX7ULP_CLK_FIRC]->clk);
 
        hws[IMX7ULP_CLK_DDR_DIV]        = imx_clk_hw_divider_gate("ddr_clk", "ddr_sel", CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, base + 0x30, 0, 3,
                                                               0, ulp_div_table, &imx_ccm_lock);
@@ -270,7 +272,7 @@ static void __init imx7ulp_clk_smc1_init(struct device_node *np)
        base = of_iomap(np, 0);
        WARN_ON(!base);
 
-       hws[IMX7ULP_CLK_ARM] = imx_clk_hw_mux_flags("arm", base + 0x10, 8, 2, arm_sels, ARRAY_SIZE(arm_sels), CLK_IS_CRITICAL);
+       hws[IMX7ULP_CLK_ARM] = imx_clk_hw_mux_flags("arm", base + 0x10, 8, 2, arm_sels, ARRAY_SIZE(arm_sels), CLK_SET_RATE_PARENT);
 
        imx_check_clk_hws(hws, clk_data->num);
 
index 38145bdcd975228253d3e347cdf5ca8f2ddb3325..b58370d146e2ec81dce40ca168fac8fcb7acb2ff 100644 (file)
 #define IMX7ULP_CLK_HSRUN_SYS_SEL      44
 #define IMX7ULP_CLK_HSRUN_CORE_DIV     45
 
-#define IMX7ULP_CLK_SCG1_END           46
+#define IMX7ULP_CLK_CORE               46
+#define IMX7ULP_CLK_HSRUN_CORE         47
+
+#define IMX7ULP_CLK_SCG1_END           48
 
 /* PCC2 */
 #define IMX7ULP_CLK_DMA1               0