diff options
author | Bai Ping <ping.bai@nxp.com> | 2018-07-17 13:27:17 +0800 |
---|---|---|
committer | Jason Liu <jason.hui.liu@nxp.com> | 2019-02-12 10:32:44 +0800 |
commit | 4984e653a6e86f7b6e2e6c195be53da8dcb5f8fd (patch) | |
tree | 8015172172872cbec4d1c6fd2f68d3281c9de687 /drivers/soc | |
parent | a1247a1af9a77434393f35822be3f87699d64587 (diff) |
MLK-18427-03 driver: soc: add busfreq driver support for imx8mm
add busfreq support on i.MX8MM. when system is running at low bus or
audio bus mode, the dram & bus clock will be reduced to a lower rate:
NOC: 150MHZ, AXI: 24MHz, AXI 20MHZ, DRAM core clock: 25MHz.
when system is running at high bus mode, all the bus clock and dram
clock will be restore to the highest one.
Signed-off-by: Bai Ping <ping.bai@nxp.com>
Reviewed-by: Anson Huang <Anson.Huang@nxp.com>
Diffstat (limited to 'drivers/soc')
-rw-r--r-- | drivers/soc/imx/busfreq-imx8mq.c | 147 |
1 files changed, 121 insertions, 26 deletions
diff --git a/drivers/soc/imx/busfreq-imx8mq.c b/drivers/soc/imx/busfreq-imx8mq.c index 12ee3d6f807d..a8c3488d0b4c 100644 --- a/drivers/soc/imx/busfreq-imx8mq.c +++ b/drivers/soc/imx/busfreq-imx8mq.c @@ -112,17 +112,39 @@ static void reduce_bus_freq(void) if (audio_bus_count) { if (cur_bus_freq_mode == BUS_FREQ_HIGH) { - 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); - /* reduce the NOC & bus clock */ - clk_set_rate(noc_div, clk_get_rate(noc_div) / 8); + 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); + /* reduce the NOC & bus clock */ + clk_set_rate(noc_div, clk_get_rate(noc_div) / 8); + } 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); + + /* correct the clock tree info */ + 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); + + /* change the NOC rate */ + clk_set_rate(noc_div, clk_get_rate(noc_div) / 5); + } + clk_set_rate(ahb_div, clk_get_rate(ahb_div) / 6); clk_set_parent(main_axi_src, osc_25m); } @@ -133,12 +155,34 @@ static void reduce_bus_freq(void) } else { if (cur_bus_freq_mode == BUS_FREQ_HIGH) { - update_bus_freq(LOW_BUS_FREQ_667MTS); + 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); + /* reduce the NOC & bus clock */ + clk_set_rate(noc_div, clk_get_rate(noc_div) / 8); + } 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); + + /* correct the clock tree info */ + 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); + + /* change the NOC clock rate */ + clk_set_rate(noc_div, clk_get_rate(noc_div) / 5); + } - clk_set_rate(dram_apb_pre_div, 160000000); - clk_get_rate(dram_pll_clk); - /* reduce the NOC & bus clock */ - clk_set_rate(noc_div, clk_get_rate(noc_div) / 8); clk_set_rate(ahb_div, clk_get_rate(ahb_div) / 6); clk_set_parent(main_axi_src, osc_25m); } @@ -149,9 +193,9 @@ static void reduce_bus_freq(void) } if (audio_bus_freq_mode) - printk(KERN_DEBUG "ddrc freq set to audio mode: 167MHz\n"); + printk(KERN_DEBUG "ddrc freq set to audio bus mode\n"); if (low_bus_freq_mode) - printk(KERN_DEBUG "ddrc freq set to low bus mode: 167MHz\n"); + printk(KERN_DEBUG "ddrc freq set to low bus mode\n"); } static void reduce_bus_freq_handler(struct work_struct *work) @@ -208,12 +252,30 @@ static int set_high_bus_freq(int high_bus_freq) if (high_bus_freq_mode) return 0; - /* switch the DDR freqeuncy */ - update_bus_freq(HIGH_FREQ_3200MTS); + 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); + clk_set_rate(noc_div, 800000000); + } 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, 750000000); + } - clk_set_rate(dram_apb_pre_div, 200000000); - clk_get_rate(dram_pll_clk); - clk_set_rate(noc_div, 800000000); clk_set_rate(ahb_div, 133333333); clk_set_parent(main_axi_src, sys2_pll_333m); @@ -223,7 +285,7 @@ static int set_high_bus_freq(int high_bus_freq) cur_bus_freq_mode = BUS_FREQ_HIGH; if (high_bus_freq_mode) - printk(KERN_DEBUG "ddrc freq set to high mode: 800MHz\n"); + printk(KERN_DEBUG "ddrc freq set to high bus mode\n"); return 0; } @@ -435,7 +497,7 @@ static int init_busfreq_irq(struct platform_device *busfreq_pdev) return 0; } -static int init_busfreq_clk(struct platform_device *pdev) +static int imx8mq_init_busfreq_clk(struct platform_device *pdev) { dram_pll_clk = devm_clk_get(&pdev->dev, "dram_pll"); sys1_pll_800m = devm_clk_get(&pdev->dev, "sys1_pll_800m"); @@ -465,6 +527,35 @@ static int init_busfreq_clk(struct platform_device *pdev) return 0; } +static int imx8mm_init_busfreq_clk(struct platform_device *pdev) +{ + dram_pll_clk = devm_clk_get(&pdev->dev, "dram_pll"); + dram_alt_src = devm_clk_get(&pdev->dev, "dram_alt_src"); + dram_alt_root = devm_clk_get(&pdev->dev, "dram_alt_root"); + dram_core_clk = devm_clk_get(&pdev->dev, "dram_core"); + dram_apb_src = devm_clk_get(&pdev->dev, "dram_apb_src"); + dram_apb_pre_div = devm_clk_get(&pdev->dev, "dram_apb_pre_div"); + sys1_pll_800m = devm_clk_get(&pdev->dev, "sys_pll1_800m"); + sys1_pll_100m = devm_clk_get(&pdev->dev, "sys_pll1_100m"); + sys1_pll_40m = devm_clk_get(&pdev->dev, "sys_pll1_40m"); + noc_div = devm_clk_get(&pdev->dev, "noc_div"); + ahb_div = devm_clk_get(&pdev->dev, "ahb_div"); + main_axi_src = devm_clk_get(&pdev->dev, "main_axi_src"); + osc_25m = devm_clk_get(&pdev->dev, "osc_24m"); + sys2_pll_333m = devm_clk_get(&pdev->dev, "sys_pll2_333m"); + + if (IS_ERR(dram_pll_clk) || IS_ERR(dram_alt_src) || IS_ERR(dram_alt_root) || + IS_ERR(dram_core_clk) || IS_ERR(dram_apb_src) || IS_ERR(dram_apb_pre_div) || + IS_ERR(sys1_pll_800m) || IS_ERR(sys1_pll_100m) || IS_ERR(sys1_pll_40m) || + IS_ERR(osc_25m) || IS_ERR(noc_div) || IS_ERR(main_axi_src) || IS_ERR(ahb_div) || + IS_ERR(sys2_pll_333m)) { + dev_err(&pdev->dev, "failed to get busfreq clk\n"); + return -EINVAL; + } + + return 0; +} + /*! * This is the probe routine for the bus frequency driver. * @@ -480,7 +571,11 @@ static int busfreq_probe(struct platform_device *pdev) busfreq_dev = &pdev->dev; /* get the clock for DDRC */ - err = init_busfreq_clk(pdev); + if (of_machine_is_compatible("fsl,imx8mq")) + err = imx8mq_init_busfreq_clk(pdev); + else + err = imx8mm_init_busfreq_clk(pdev); + if (err) { dev_err(busfreq_dev, "init clk failed\n"); return err; |