summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnson Huang <anson.huang@nxp.com>2018-12-07 05:03:34 -0500
committerStephen Boyd <sboyd@kernel.org>2018-12-14 17:03:12 -0500
commit7128d7f7bae11217cdd304b0620a4461102e599b (patch)
tree9c4204092d7464f354ee88c29ce8d9847a5d3a78
parent401371fb597e035c3e7de5b69a4fa0e8243cb6a4 (diff)
clk: imx: imx7ulp: add arm hsrun mode clocks support
i.MX7ULP has a Cortex-A7 CPU which can run in RUN mode or HSRUN mode, it is controlled in SMC1 module. The RUN mode and HSRUN mode will use different clock source for ARM, "divcore" for RUN mode and "hsrun_divcore" for HSRUN mode, so the control bits in SMC1 module can be abstracted as a HW clock mux, this patch adds HSRUN mode related clocks in SCG1 module and adds "arm" clock in SMC1 module to support RUN mode and HSRUN mode switch. Latest clock tree in RUN mode as below: firc 0 0 0 48000000 0 0 50000 firc_bus_clk 0 0 0 48000000 0 0 50000 hsrun_scs_sel 0 0 0 48000000 0 0 50000 hsrun_divcore 0 0 0 48000000 0 0 50000 sosc 3 3 3 24000000 0 0 50000 spll_pre_sel 1 1 1 24000000 0 0 50000 spll_pre_div 1 1 2 24000000 0 0 50000 spll 1 1 2 528000000 0 0 50000 spll_pfd0 1 1 1 500210526 0 0 50000 spll_pfd_sel 1 1 0 500210526 0 0 50000 spll_sel 1 1 0 500210526 0 0 50000 scs_sel 1 1 0 500210526 0 0 50000 divcore 1 1 0 500210526 0 0 50000 arm 1 1 0 500210526 0 0 50000 Signed-off-by: Anson Huang <Anson.Huang@nxp.com> Signed-off-by: Stephen Boyd <sboyd@kernel.org>
-rw-r--r--drivers/clk/imx/clk-imx7ulp.c31
1 files changed, 30 insertions, 1 deletions
diff --git a/drivers/clk/imx/clk-imx7ulp.c b/drivers/clk/imx/clk-imx7ulp.c
index 3b7507ff7869..4e18f629f823 100644
--- a/drivers/clk/imx/clk-imx7ulp.c
+++ b/drivers/clk/imx/clk-imx7ulp.c
@@ -29,6 +29,7 @@ static const char * const ddr_sels[] = { "apll_pfd_sel", "upll", };
29static const char * const nic_sels[] = { "firc", "ddr_clk", }; 29static const char * const nic_sels[] = { "firc", "ddr_clk", };
30static const char * const periph_plat_sels[] = { "dummy", "nic1_bus_clk", "nic1_clk", "ddr_clk", "apll_pfd2", "apll_pfd1", "apll_pfd0", "upll", }; 30static const char * const periph_plat_sels[] = { "dummy", "nic1_bus_clk", "nic1_clk", "ddr_clk", "apll_pfd2", "apll_pfd1", "apll_pfd0", "upll", };
31static const char * const periph_bus_sels[] = { "dummy", "sosc_bus_clk", "mpll", "firc_bus_clk", "rosc", "nic1_bus_clk", "nic1_clk", "spll_bus_clk", }; 31static const char * const periph_bus_sels[] = { "dummy", "sosc_bus_clk", "mpll", "firc_bus_clk", "rosc", "nic1_bus_clk", "nic1_clk", "spll_bus_clk", };
32static const char * const arm_sels[] = { "divcore", "dummy", "dummy", "hsrun_divcore", };
32 33
33/* used by sosc/sirc/firc/ddr/spll/apll dividers */ 34/* used by sosc/sirc/firc/ddr/spll/apll dividers */
34static const struct clk_div_table ulp_div_table[] = { 35static const struct clk_div_table ulp_div_table[] = {
@@ -102,10 +103,12 @@ static void __init imx7ulp_clk_scg1_init(struct device_node *np)
102 103
103 /* scs/ddr/nic select different clock source requires that clock to be enabled first */ 104 /* scs/ddr/nic select different clock source requires that clock to be enabled first */
104 clks[IMX7ULP_CLK_SYS_SEL] = imx_clk_hw_mux2("scs_sel", base + 0x14, 24, 4, scs_sels, ARRAY_SIZE(scs_sels)); 105 clks[IMX7ULP_CLK_SYS_SEL] = imx_clk_hw_mux2("scs_sel", base + 0x14, 24, 4, scs_sels, ARRAY_SIZE(scs_sels));
106 clks[IMX7ULP_CLK_HSRUN_SYS_SEL] = imx_clk_hw_mux2("hsrun_scs_sel", base + 0x1c, 24, 4, scs_sels, ARRAY_SIZE(scs_sels));
105 clks[IMX7ULP_CLK_NIC_SEL] = imx_clk_hw_mux2("nic_sel", base + 0x40, 28, 1, nic_sels, ARRAY_SIZE(nic_sels)); 107 clks[IMX7ULP_CLK_NIC_SEL] = imx_clk_hw_mux2("nic_sel", base + 0x40, 28, 1, nic_sels, ARRAY_SIZE(nic_sels));
106 clks[IMX7ULP_CLK_DDR_SEL] = imx_clk_hw_mux_flags("ddr_sel", base + 0x30, 24, 1, ddr_sels, ARRAY_SIZE(ddr_sels), CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE); 108 clks[IMX7ULP_CLK_DDR_SEL] = imx_clk_hw_mux_flags("ddr_sel", base + 0x30, 24, 1, ddr_sels, ARRAY_SIZE(ddr_sels), CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE);
107 109
108 clks[IMX7ULP_CLK_CORE_DIV] = imx_clk_hw_divider_flags("divcore", "scs_sel", base + 0x14, 16, 4, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL); 110 clks[IMX7ULP_CLK_CORE_DIV] = imx_clk_hw_divider_flags("divcore", "scs_sel", base + 0x14, 16, 4, CLK_SET_RATE_PARENT);
111 clks[IMX7ULP_CLK_HSRUN_CORE_DIV] = imx_clk_hw_divider_flags("hsrun_divcore", "hsrun_scs_sel", base + 0x1c, 16, 4, CLK_SET_RATE_PARENT);
109 112
110 clks[IMX7ULP_CLK_DDR_DIV] = imx_clk_divider_gate("ddr_clk", "ddr_sel", CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, base + 0x30, 0, 3, 113 clks[IMX7ULP_CLK_DDR_DIV] = imx_clk_divider_gate("ddr_clk", "ddr_sel", CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, base + 0x30, 0, 3,
111 0, ulp_div_table, &imx_ccm_lock); 114 0, ulp_div_table, &imx_ccm_lock);
@@ -218,3 +221,29 @@ static void __init imx7ulp_clk_pcc3_init(struct device_node *np)
218 of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data); 221 of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
219} 222}
220CLK_OF_DECLARE(imx7ulp_clk_pcc3, "fsl,imx7ulp-pcc3", imx7ulp_clk_pcc3_init); 223CLK_OF_DECLARE(imx7ulp_clk_pcc3, "fsl,imx7ulp-pcc3", imx7ulp_clk_pcc3_init);
224
225static void __init imx7ulp_clk_smc1_init(struct device_node *np)
226{
227 struct clk_hw_onecell_data *clk_data;
228 struct clk_hw **clks;
229 void __iomem *base;
230
231 clk_data = kzalloc(sizeof(*clk_data) + sizeof(*clk_data->hws) *
232 IMX7ULP_CLK_SMC1_END, GFP_KERNEL);
233 if (!clk_data)
234 return;
235
236 clk_data->num = IMX7ULP_CLK_SMC1_END;
237 clks = clk_data->hws;
238
239 /* SMC1 */
240 base = of_iomap(np, 0);
241 WARN_ON(!base);
242
243 clks[IMX7ULP_CLK_ARM] = imx_clk_hw_mux_flags("arm", base + 0x10, 8, 2, arm_sels, ARRAY_SIZE(arm_sels), CLK_IS_CRITICAL);
244
245 imx_check_clk_hws(clks, clk_data->num);
246
247 of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
248}
249CLK_OF_DECLARE(imx7ulp_clk_smc1, "fsl,imx7ulp-smc1", imx7ulp_clk_smc1_init);