clk: sm1: add sm1 dsu clk notify for change dsu freq [1/1]
authorShunzhou Jiang <shunzhou.jiang@amlogic.com>
Tue, 14 May 2019 01:47:43 +0000 (09:47 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Mon, 3 Jun 2019 11:09:31 +0000 (04:09 -0700)
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 <shunzhou.jiang@amlogic.com>
Signed-off-by: Hong Guo <hong.guo@amlogic.com>
arch/arm/boot/dts/amlogic/mesonsm1.dtsi
arch/arm64/boot/dts/amlogic/mesonsm1.dtsi
drivers/amlogic/clk/g12a/g12a.c
drivers/amlogic/clk/sm1/sm1.c

index 26199d1..e53ca60 100644 (file)
                        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>;
                        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>;
                        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>;
                        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>;
                                compatible = "amlogic,sm1-clkc-2";
                                #clock-cells = <1>;
                                reg = <0x0 0x3dc>;
+                               own-dsu-clk;
                        };
                };/* end of hiubus*/
 
index 1548a4b..2e127a7 100644 (file)
                        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>;
                        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>;
                        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>;
                        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>;
                                compatible = "amlogic,sm1-clkc-2";
                                #clock-cells = <1>;
                                reg = <0x0 0x0 0x0 0x3dc>;
+                               own-dsu-clk;
                        };
                };/* end of hiubus*/
 
index db280c5..cb6ae48 100644 (file)
@@ -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,
index 2f8acf3..f63d515 100644 (file)
@@ -26,6 +26,7 @@
 #include "../clkc.h"
 #include "../g12a/g12a.h"
 #include "sm1.h"
+#include <linux/delay.h>
 
 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);
-
-