From efc28c832fe17f94464ad5c331b3b6454e131fbd Mon Sep 17 00:00:00 2001 From: Shunzhou Jiang Date: Tue, 14 May 2019 09:47:43 +0800 Subject: [PATCH] clk: sm1: add sm1 dsu clk notify for change dsu freq [1/1] PD#SWPL-8145 Problem: dsu clk can't change freq Solution: add sm1 dsu clk notify Verify: sm1_skt Change-Id: If3ecf1066b49c07e6af69ce342956cb0469a5f87 Signed-off-by: Shunzhou Jiang Signed-off-by: Hong Guo --- arch/arm/boot/dts/amlogic/mesonsm1.dtsi | 33 ++++++++++---- arch/arm64/boot/dts/amlogic/mesonsm1.dtsi | 33 ++++++++++---- drivers/amlogic/clk/g12a/g12a.c | 13 ------ drivers/amlogic/clk/sm1/sm1.c | 71 +++++++++++++++++++++++++------ 4 files changed, 107 insertions(+), 43 deletions(-) diff --git a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi index 26199d1..e53ca60 100644 --- a/arch/arm/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm/boot/dts/amlogic/mesonsm1.dtsi @@ -58,10 +58,14 @@ cpu-idle-states = <&CPU_SLEEP_0>; clocks = <&clkc CLKID_CPU_CLK>, <&clkc CLKID_CPU_FCLK_P>, - <&clkc CLKID_SYS_PLL>; + <&clkc CLKID_SYS_PLL>, + <&clkc CLKID_DSU_CLK>, + <&clkc CLKID_DSU_PRE_CLK>; clock-names = "core_clk", "low_freq_clk_parent", - "high_freq_clk_parent"; + "high_freq_clk_parent", + "dsu_clk", + "dsu_pre_parent"; operating-points-v2 = <&cpu_opp_table0>; cpu-supply = <&vddcpu0>; voltage-tolerance = <0>; @@ -76,10 +80,14 @@ cpu-idle-states = <&CPU_SLEEP_0>; clocks = <&clkc CLKID_CPU_CLK>, <&clkc CLKID_CPU_FCLK_P>, - <&clkc CLKID_SYS_PLL>; + <&clkc CLKID_SYS_PLL>, + <&clkc CLKID_DSU_CLK>, + <&clkc CLKID_DSU_PRE_CLK>; clock-names = "core_clk", "low_freq_clk_parent", - "high_freq_clk_parent"; + "high_freq_clk_parent", + "dsu_clk", + "dsu_pre_parent"; operating-points-v2 = <&cpu_opp_table0>; cpu-supply = <&vddcpu0>; voltage-tolerance = <0>; @@ -94,10 +102,14 @@ cpu-idle-states = <&CPU_SLEEP_0>; clocks = <&clkc CLKID_CPU_CLK>, <&clkc CLKID_CPU_FCLK_P>, - <&clkc CLKID_SYS_PLL>; + <&clkc CLKID_SYS_PLL>, + <&clkc CLKID_DSU_CLK>, + <&clkc CLKID_DSU_PRE_CLK>; clock-names = "core_clk", "low_freq_clk_parent", - "high_freq_clk_parent"; + "high_freq_clk_parent", + "dsu_clk", + "dsu_pre_parent"; operating-points-v2 = <&cpu_opp_table0>; cpu-supply = <&vddcpu0>; voltage-tolerance = <0>; @@ -112,10 +124,14 @@ cpu-idle-states = <&CPU_SLEEP_0>; clocks = <&clkc CLKID_CPU_CLK>, <&clkc CLKID_CPU_FCLK_P>, - <&clkc CLKID_SYS_PLL>; + <&clkc CLKID_SYS_PLL>, + <&clkc CLKID_DSU_CLK>, + <&clkc CLKID_DSU_PRE_CLK>; clock-names = "core_clk", "low_freq_clk_parent", - "high_freq_clk_parent"; + "high_freq_clk_parent", + "dsu_clk", + "dsu_pre_parent"; operating-points-v2 = <&cpu_opp_table0>; cpu-supply = <&vddcpu0>; voltage-tolerance = <0>; @@ -757,6 +773,7 @@ compatible = "amlogic,sm1-clkc-2"; #clock-cells = <1>; reg = <0x0 0x3dc>; + own-dsu-clk; }; };/* end of hiubus*/ diff --git a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi index 1548a4b..2e127a7 100644 --- a/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonsm1.dtsi @@ -58,10 +58,14 @@ cpu-idle-states = <&CPU_SLEEP_0>; clocks = <&clkc CLKID_CPU_CLK>, <&clkc CLKID_CPU_FCLK_P>, - <&clkc CLKID_SYS_PLL>; + <&clkc CLKID_SYS_PLL>, + <&clkc CLKID_DSU_CLK>, + <&clkc CLKID_DSU_PRE_CLK>; clock-names = "core_clk", "low_freq_clk_parent", - "high_freq_clk_parent"; + "high_freq_clk_parent", + "dsu_clk", + "dsu_pre_parent"; operating-points-v2 = <&cpu_opp_table0>; cpu-supply = <&vddcpu0>; voltage-tolerance = <0>; @@ -76,10 +80,14 @@ cpu-idle-states = <&CPU_SLEEP_0>; clocks = <&clkc CLKID_CPU_CLK>, <&clkc CLKID_CPU_FCLK_P>, - <&clkc CLKID_SYS_PLL>; + <&clkc CLKID_SYS_PLL>, + <&clkc CLKID_DSU_CLK>, + <&clkc CLKID_DSU_PRE_CLK>; clock-names = "core_clk", "low_freq_clk_parent", - "high_freq_clk_parent"; + "high_freq_clk_parent", + "dsu_clk", + "dsu_pre_parent"; operating-points-v2 = <&cpu_opp_table0>; cpu-supply = <&vddcpu0>; voltage-tolerance = <0>; @@ -94,10 +102,14 @@ cpu-idle-states = <&CPU_SLEEP_0>; clocks = <&clkc CLKID_CPU_CLK>, <&clkc CLKID_CPU_FCLK_P>, - <&clkc CLKID_SYS_PLL>; + <&clkc CLKID_SYS_PLL>, + <&clkc CLKID_DSU_CLK>, + <&clkc CLKID_DSU_PRE_CLK>; clock-names = "core_clk", "low_freq_clk_parent", - "high_freq_clk_parent"; + "high_freq_clk_parent", + "dsu_clk", + "dsu_pre_parent"; operating-points-v2 = <&cpu_opp_table0>; cpu-supply = <&vddcpu0>; voltage-tolerance = <0>; @@ -112,10 +124,14 @@ cpu-idle-states = <&CPU_SLEEP_0>; clocks = <&clkc CLKID_CPU_CLK>, <&clkc CLKID_CPU_FCLK_P>, - <&clkc CLKID_SYS_PLL>; + <&clkc CLKID_SYS_PLL>, + <&clkc CLKID_DSU_CLK>, + <&clkc CLKID_DSU_PRE_CLK>; clock-names = "core_clk", "low_freq_clk_parent", - "high_freq_clk_parent"; + "high_freq_clk_parent", + "dsu_clk", + "dsu_pre_parent"; operating-points-v2 = <&cpu_opp_table0>; cpu-supply = <&vddcpu0>; voltage-tolerance = <0>; @@ -757,6 +773,7 @@ compatible = "amlogic,sm1-clkc-2"; #clock-cells = <1>; reg = <0x0 0x0 0x0 0x3dc>; + own-dsu-clk; }; };/* end of hiubus*/ diff --git a/drivers/amlogic/clk/g12a/g12a.c b/drivers/amlogic/clk/g12a/g12a.c index db280c5..cb6ae48 100644 --- a/drivers/amlogic/clk/g12a/g12a.c +++ b/drivers/amlogic/clk/g12a/g12a.c @@ -1028,19 +1028,6 @@ static void __init g12a_clkc_init(struct device_node *np) goto iounmap; } - if (of_property_read_bool(np, "own-dsu-clk")) { - if (clks[CLKID_DSU_CLK]) { - clk_set_parent(clks[CLKID_DSU_CLK], - clks[CLKID_CPU_CLK]); - /* set sm1_dsu_pre_clk to 1.5G, gp1 pll is 1.5G */ - clk_set_rate(clks[CLKID_DSU_PRE_CLK], 1500000000); - clk_prepare_enable(clks[CLKID_DSU_PRE_CLK]); - /* set sm1_dsu_pre_clk as dsu_pre's parent */ - clk_set_parent(clks[CLKID_DSU_CLK], - clks[CLKID_DSU_PRE_CLK]); - } - } - pr_debug("%s: cpu clk register notifier ok!", __func__); ret = of_clk_add_provider(np, of_clk_src_onecell_get, diff --git a/drivers/amlogic/clk/sm1/sm1.c b/drivers/amlogic/clk/sm1/sm1.c index 2f8acf3..f63d515 100644 --- a/drivers/amlogic/clk/sm1/sm1.c +++ b/drivers/amlogic/clk/sm1/sm1.c @@ -26,6 +26,7 @@ #include "../clkc.h" #include "../g12a/g12a.h" #include "sm1.h" +#include static struct meson_clk_pll sm1_gp1_pll = { .m = { @@ -244,7 +245,7 @@ static struct clk_mux sm1_dsu_pre_src_clk_mux0 = { .parent_names = (const char *[]){ "xtal", "fclk_div2", "fclk_div3", "gp1_pll" }, .num_parents = 4, - .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + .flags = CLK_SET_RATE_PARENT, }, }; @@ -259,7 +260,7 @@ static struct clk_mux sm1_dsu_pre_src_clk_mux1 = { .parent_names = (const char *[]){ "xtal", "fclk_div2", "fclk_div3", "gp1_pll" }, .num_parents = 4, - .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + .flags = CLK_SET_RATE_PARENT, }, }; @@ -423,12 +424,53 @@ static struct clk_hw *sm1_clk_hws[] = { &sm1_csi_phy.hw, }; +struct sm1_nb_data { + struct notifier_block nb; +}; + +static int sm1_dsu_mux_clk_notifier_cb(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct clk *dsu_pre_clk, *parent_clk; + int ret; + + switch (event) { + case PRE_RATE_CHANGE: + /* switch to sm1_dsu_fixed_sel1, set it to 1G (default 24M) */ + ret = clk_set_rate(sm1_dsu_pre_clk_mux1.hw.clk, 1000000000); + if (ret < 0) + return ret; + parent_clk = sm1_dsu_pre_clk_mux1.hw.clk; + break; + case POST_RATE_CHANGE: + parent_clk = sm1_dsu_pre_clk_mux0.hw.clk; + break; + default: + return NOTIFY_DONE; + } + + dsu_pre_clk = sm1_dsu_pre_post_clk_mux.hw.clk; + + ret = clk_set_parent(dsu_pre_clk, parent_clk); + if (ret) + return notifier_from_errno(ret); + + usleep_range(80, 120); + + return NOTIFY_OK; +} + +static struct sm1_nb_data sm1_dsu_nb_data = { + .nb.notifier_call = sm1_dsu_mux_clk_notifier_cb, +}; + static void __init sm1_clkc_init(struct device_node *np) { int ret = 0, clkid, i; if (!clk_base) clk_base = of_iomap(np, 0); + if (!clk_base) { pr_err("%s: Unable to map clk base\n", __func__); return; @@ -560,17 +602,20 @@ static void __init sm1_clkc_init(struct device_node *np) panic("%s: %d register cts_csi_adapt_clk_composite error\n", __func__, __LINE__); - if (clks[CLKID_CPU_CLK]) { - if (!of_property_read_bool(np, "own-dsu-clk")) - return; - /* set cpu clk as dsu_clk's parent*/ - clk_set_parent(sm1_dsu_clk.hw.clk, clks[CLKID_CPU_CLK]); - /* set sm1_dsu_pre_clk to 1.5G, gp1 pll is 1.5G */ - clk_set_rate(sm1_dsu_pre_clk.hw.clk, 1500000000); - clk_prepare_enable(sm1_dsu_pre_clk.hw.clk); - /* set sm1_dsu_pre_clk as dsu_clk's parent */ - clk_set_parent(sm1_dsu_clk.hw.clk, sm1_dsu_pre_clk.hw.clk); + if (of_property_read_bool(np, "own-dsu-clk")) { + /* + * when change sm1_dsu_pre_clk_mux0, switch to + * sm1_dsu_pre_clk_mux1 to avoid crash + */ + ret = clk_notifier_register(sm1_dsu_pre_clk_mux0.hw.clk, + &sm1_dsu_nb_data.nb); + if (ret) { + pr_err("%s: failed to register clock notifier for cpu_clk\n", + __func__); + goto iounmap; + } } + pr_err("sm1 clk probe ok\n"); return; iounmap: @@ -579,5 +624,3 @@ iounmap: } CLK_OF_DECLARE(sm1, "amlogic,sm1-clkc-2", sm1_clkc_init); - - -- 2.7.4