MLK-20136-03 driver: soc: imx: add 100mts support for imx8mq low bus mode
authorBai Ping <ping.bai@nxp.com>
Wed, 31 Oct 2018 01:59:37 +0000 (09:59 +0800)
committerLeonard Crestez <leonard.crestez@nxp.com>
Wed, 17 Apr 2019 23:51:34 +0000 (02:51 +0300)
The 100MTS low bus mode can be only supported by i.MX8MQ Rev2.1 and
future TO. So necessary check is added to identify the chip revision
when doing busfreq mode switch.

Signed-off-by: Bai Ping <ping.bai@nxp.com>
Reviewed-by: Anson Huang <Anson.Huang@nxp.com>
(cherry picked from commit a906afb17d445b40f6c70fa2a2c3b6707ada0e47)

drivers/soc/imx/busfreq-imx8mq.c

index a8c3488..7624764 100644 (file)
@@ -33,6 +33,8 @@
 #include <linux/smp.h>
 #include <linux/suspend.h>
 #include <soc/imx/fsl_sip.h>
+#include <soc/imx/revision.h>
+#include <soc/imx8/soc.h>
 
 #define HIGH_FREQ_3200MTS      0x0
 #define AUDIO_FREQ_400MTS      0x1
@@ -113,15 +115,32 @@ static void reduce_bus_freq(void)
                if (cur_bus_freq_mode == BUS_FREQ_HIGH) {
 
                        if (of_machine_is_compatible("fsl,imx8mq")) {
-                               update_bus_freq(LOW_BUS_FREQ_667MTS);
-
-                               /*
-                                * the dram_apb and dram_core clk rate is changed
-                                * in ATF side, below two lines of code is just used
-                                * to upate the clock tree info in kernel side.
-                                */
-                               clk_set_rate(dram_apb_pre_div, 160000000);
-                               clk_get_rate(dram_pll_clk);
+                               if (imx8_get_soc_revision() < IMX_CHIP_REVISION_2_1) {
+                                       update_bus_freq(LOW_BUS_FREQ_667MTS);
+
+                                       /*
+                                        * the dram_apb and dram_core clk rate is changed
+                                        * in ATF side, below two lines of code is just used
+                                        * to upate the clock tree info in kernel side.
+                                        */
+                                       clk_set_rate(dram_apb_pre_div, 160000000);
+                                       clk_get_rate(dram_pll_clk);
+                               } else {
+                                       /* prepare the necessary clk before frequency change */
+                                       clk_prepare_enable(sys1_pll_40m);
+                                       clk_prepare_enable(dram_alt_root);
+                                       clk_prepare_enable(sys1_pll_100m);
+
+                                       update_bus_freq(LOW_BUS_FREQ_100MTS);
+
+                                       clk_set_parent(dram_alt_src, sys1_pll_100m);
+                                       clk_set_parent(dram_core_clk, dram_alt_root);
+                                       clk_set_parent(dram_apb_src, sys1_pll_40m);
+                                       clk_set_rate(dram_apb_pre_div, 20000000);
+                                       clk_disable_unprepare(sys1_pll_100m);
+                                       clk_disable_unprepare(sys1_pll_40m);
+                                       clk_disable_unprepare(dram_alt_root);
+                               }
                                /* reduce the NOC & bus clock */
                                clk_set_rate(noc_div, clk_get_rate(noc_div) / 8);
                        } else {
@@ -154,12 +173,33 @@ static void reduce_bus_freq(void)
                cur_bus_freq_mode = BUS_FREQ_AUDIO;
        } else {
                if (cur_bus_freq_mode == BUS_FREQ_HIGH) {
-
                        if (of_machine_is_compatible("fsl,imx8mq")) {
-                               update_bus_freq(LOW_BUS_FREQ_667MTS);
-
-                               clk_set_rate(dram_apb_pre_div, 160000000);
-                               clk_get_rate(dram_pll_clk);
+                               if (imx8_get_soc_revision() < IMX_CHIP_REVISION_2_1) {
+                                       update_bus_freq(LOW_BUS_FREQ_667MTS);
+
+                                       /*
+                                        * the dram_apb and dram_core clk rate is changed
+                                        * in ATF side, below two lines of code is just used
+                                        * to upate the clock tree info in kernel side.
+                                        */
+                                       clk_set_rate(dram_apb_pre_div, 160000000);
+                                       clk_get_rate(dram_pll_clk);
+                               } else {
+                                       /* prepare the necessary clk before frequency change */
+                                       clk_prepare_enable(sys1_pll_40m);
+                                       clk_prepare_enable(dram_alt_root);
+                                       clk_prepare_enable(sys1_pll_100m);
+
+                                       update_bus_freq(LOW_BUS_FREQ_100MTS);
+
+                                       clk_set_parent(dram_alt_src, sys1_pll_100m);
+                                       clk_set_parent(dram_core_clk, dram_alt_root);
+                                       clk_set_parent(dram_apb_src, sys1_pll_40m);
+                                       clk_set_rate(dram_apb_pre_div, 20000000);
+                                       clk_disable_unprepare(sys1_pll_100m);
+                                       clk_disable_unprepare(sys1_pll_40m);
+                                       clk_disable_unprepare(dram_alt_root);
+                               }
                                /* reduce the NOC & bus clock */
                                clk_set_rate(noc_div, clk_get_rate(noc_div) / 8);
                        } else {
@@ -253,11 +293,27 @@ static int set_high_bus_freq(int high_bus_freq)
                return 0;
 
        if (of_machine_is_compatible("fsl,imx8mq")) {
-               /* switch the DDR freqeuncy */
-               update_bus_freq(HIGH_FREQ_3200MTS);
-
-               clk_set_rate(dram_apb_pre_div, 200000000);
-               clk_get_rate(dram_pll_clk);
+               if (imx8_get_soc_revision() < IMX_CHIP_REVISION_2_1) {
+                       /* switch the DDR freqeuncy */
+                       update_bus_freq(HIGH_FREQ_3200MTS);
+
+                       clk_set_rate(dram_apb_pre_div, 200000000);
+                       clk_get_rate(dram_pll_clk);
+               } else {
+                       /*  enable the clks needed in frequency */
+                       clk_prepare_enable(sys1_pll_800m);
+                       clk_prepare_enable(dram_pll_clk);
+
+                       /* switch the DDR freqeuncy */
+                       update_bus_freq(HIGH_FREQ_3200MTS);
+
+                       /* correct the clock tree info */
+                       clk_set_parent(dram_apb_src, sys1_pll_800m);
+                       clk_set_rate(dram_apb_pre_div, 160000000);
+                       clk_set_parent(dram_core_clk, dram_pll_clk);
+                       clk_disable_unprepare(sys1_pll_800m);
+                       clk_disable_unprepare(dram_pll_clk);
+               }
                clk_set_rate(noc_div, 800000000);
        } else {
                /*  enable the clks needed in frequency */