diff options
-rw-r--r-- | drivers/soc/imx/busfreq-imx8mq.c | 94 |
1 files changed, 75 insertions, 19 deletions
diff --git a/drivers/soc/imx/busfreq-imx8mq.c b/drivers/soc/imx/busfreq-imx8mq.c index a8c3488d0b4c..7624764dbaa1 100644 --- a/drivers/soc/imx/busfreq-imx8mq.c +++ b/drivers/soc/imx/busfreq-imx8mq.c @@ -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 */ |