MLK-12868-03 ARM: imx: add busfreq support on imx6ull
authorBai Ping <ping.bai@nxp.com>
Thu, 7 Apr 2016 09:20:03 +0000 (17:20 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 19:51:52 +0000 (14:51 -0500)
Add busfreq support on i.MX6ULL. per to the design
team, there is a 24MHz low power run mode on i.MX6ULL.
the define for this mode is as below:
----------------------------
|cpu    DRAM    AXI    AHB |
 24MHz  24MHz   24MHz  24MHz

The mode can be implemented as 'low_bus_mode' in busfreq,
compared to i.MX6UL, the additional code we need to add is
clk change for cpu core. so in low_bus_mode, the cpu will run
at 24MHz.

Signed-off-by: Bai Ping <ping.bai@nxp.com>
arch/arm/mach-imx/busfreq-imx.c
arch/arm/mach-imx/busfreq_ddr3.c

index 49e3429..0a99bdb 100644 (file)
@@ -155,6 +155,34 @@ int unregister_busfreq_notifier(struct notifier_block *nb)
 }
 EXPORT_SYMBOL(unregister_busfreq_notifier);
 
+static struct clk *origin_step_parent;
+
+/*
+ * on i.MX6ULL, when entering low bus mode, the ARM core
+ * can run at 24MHz to support the low power run mode per
+ * to design team.
+ */
+static void imx6ull_lower_cpu_rate(bool enter)
+{
+       if (enter)
+               org_arm_rate = clk_get_rate(arm_clk);
+
+       clk_set_parent(pll1_bypass_clk, pll1_bypass_src_clk);
+       clk_set_parent(pll1_sw_clk, pll1_sys_clk);
+
+       if (enter) {
+               origin_step_parent = clk_get_parent(step_clk);
+               clk_set_parent(step_clk, osc_clk);
+               clk_set_parent(pll1_sw_clk, step_clk);
+               clk_set_rate(arm_clk, LPAPM_CLK);
+       } else {
+               clk_set_parent(step_clk, origin_step_parent);
+               clk_set_parent(pll1_sw_clk, step_clk);
+               clk_set_rate(arm_clk, org_arm_rate);
+               clk_set_parent(pll1_bypass_clk, pll1_clk);
+       }
+}
+
 /*
  * enter_lpm_imx6_up and exit_lpm_imx6_up is used by
  * i.MX6SX/i.MX6UL for entering and exiting lpm mode.
@@ -197,6 +225,10 @@ static void enter_lpm_imx6_up(void)
                        else if (ddr_type == IMX_DDR_TYPE_LPDDR2)
                                clk_set_rate(mmdc_clk, HIGH_AUDIO_CLK);
                }
+
+               if (cpu_is_imx6ull() && low_bus_freq_mode)
+                       imx6ull_lower_cpu_rate(false);
+
                audio_bus_freq_mode = 1;
                low_bus_freq_mode = 0;
                cur_bus_freq_mode = BUS_FREQ_AUDIO;
@@ -210,6 +242,10 @@ static void enter_lpm_imx6_up(void)
 
                if (audio_bus_freq_mode)
                        clk_disable_unprepare(pll2_400_clk);
+
+               if (cpu_is_imx6ull())
+                       imx6ull_lower_cpu_rate(true);
+
                low_bus_freq_mode = 1;
                audio_bus_freq_mode = 0;
                cur_bus_freq_mode = BUS_FREQ_LOW;
@@ -255,20 +291,23 @@ static void enter_lpm_imx6_smp(void)
 
 static void exit_lpm_imx6_up(void)
 {
+       if (cpu_is_imx6ull() && low_bus_freq_mode)
+               imx6ull_lower_cpu_rate(false);
+
        clk_prepare_enable(pll2_400_clk);
 
        /*
         * lower ahb/ocram's freq first to avoid too high
         * freq during parent switch from OSC to pll3.
         */
-       if (cpu_is_imx6ul())
+       if (cpu_is_imx6ul() || cpu_is_imx6ull())
                clk_set_rate(ahb_clk, LPAPM_CLK / 4);
        else
                clk_set_rate(ahb_clk, LPAPM_CLK / 3);
 
        clk_set_rate(ocram_clk, LPAPM_CLK / 2);
        /* set periph clk to from pll2_bus on i.MX6UL */
-       if (cpu_is_imx6ul())
+       if (cpu_is_imx6ul() || cpu_is_imx6ull())
                clk_set_parent(periph_pre_clk, pll2_bus_clk);
        /* set periph clk to from pll2_400 */
        else
@@ -563,7 +602,7 @@ static void reduce_bus_freq(void)
 
        if (cpu_is_imx7d())
                enter_lpm_imx7d();
-       else if (cpu_is_imx6sx() || cpu_is_imx6ul())
+       else if (cpu_is_imx6sx() || cpu_is_imx6ul() || cpu_is_imx6ull())
                enter_lpm_imx6_up();
        else if (cpu_is_imx6q() || cpu_is_imx6dl())
                enter_lpm_imx6_smp();
@@ -656,7 +695,7 @@ static int set_high_bus_freq(int high_bus_freq)
 
        if (cpu_is_imx7d())
                exit_lpm_imx7d();
-       else if (cpu_is_imx6sx() || cpu_is_imx6ul())
+       else if (cpu_is_imx6sx() || cpu_is_imx6ul() || cpu_is_imx6ull())
                exit_lpm_imx6_up();
        else if (cpu_is_imx6q() || cpu_is_imx6dl())
                exit_lpm_imx6_smp();
@@ -1015,7 +1054,7 @@ static int busfreq_probe(struct platform_device *pdev)
                }
        }
 
-       if (cpu_is_imx6sx() || cpu_is_imx6ul() || cpu_is_imx6sl()) {
+       if (cpu_is_imx6sx() || cpu_is_imx6ul() || cpu_is_imx6sl() || cpu_is_imx6ull()) {
                ahb_clk = devm_clk_get(&pdev->dev, "ahb");
                ocram_clk = devm_clk_get(&pdev->dev, "ocram");
                periph2_clk = devm_clk_get(&pdev->dev, "periph2");
@@ -1033,7 +1072,7 @@ static int busfreq_probe(struct platform_device *pdev)
                }
        }
 
-       if (cpu_is_imx6sx() || cpu_is_imx6ul()) {
+       if (cpu_is_imx6sx() || cpu_is_imx6ul() || cpu_is_imx6ull()) {
                mmdc_clk = devm_clk_get(&pdev->dev, "mmdc");
                if (IS_ERR(mmdc_clk)) {
                        dev_err(busfreq_dev,
@@ -1051,6 +1090,18 @@ static int busfreq_probe(struct platform_device *pdev)
        }
 
        if (cpu_is_imx6sl()) {
+               pll2_bypass_src_clk = devm_clk_get(&pdev->dev, "pll2_bypass_src");
+               pll2_bypass_clk = devm_clk_get(&pdev->dev, "pll2_bypass");
+               pll2_clk = devm_clk_get(&pdev->dev, "pll2");
+               if (IS_ERR(pll2_bypass_src_clk) || IS_ERR(pll2_bypass_clk)
+                       || IS_ERR(pll2_clk)) {
+                       dev_err(busfreq_dev,
+                               "%s failed to get busfreq clk for imx6sl.\n", __func__);
+                       return -EINVAL;
+               }
+       }
+
+       if (cpu_is_imx6ull() || cpu_is_imx6sl()) {
                arm_clk = devm_clk_get(&pdev->dev, "arm");
                step_clk = devm_clk_get(&pdev->dev, "step");
                pll1_clk = devm_clk_get(&pdev->dev, "pll1");
@@ -1058,16 +1109,10 @@ static int busfreq_probe(struct platform_device *pdev)
                pll1_bypass_clk = devm_clk_get(&pdev->dev, "pll1_bypass");
                pll1_sys_clk = devm_clk_get(&pdev->dev, "pll1_sys");
                pll1_sw_clk = devm_clk_get(&pdev->dev, "pll1_sw");
-               pll2_bypass_src_clk = devm_clk_get(&pdev->dev, "pll2_bypass_src");
-               pll2_bypass_clk = devm_clk_get(&pdev->dev, "pll2_bypass");
-               pll2_clk = devm_clk_get(&pdev->dev, "pll2");
                if (IS_ERR(arm_clk) || IS_ERR(step_clk) || IS_ERR(pll1_clk)
                        || IS_ERR(pll1_bypass_src_clk) || IS_ERR(pll1_bypass_clk)
-                       || IS_ERR(pll1_sys_clk) || IS_ERR(pll1_sw_clk)
-                       || IS_ERR(pll2_bypass_src_clk) || IS_ERR(pll2_bypass_clk)
-                       || IS_ERR(pll2_clk)) {
-                       dev_err(busfreq_dev,
-                               "%s failed to get busfreq clk for imx6sl.\n", __func__);
+                       || IS_ERR(pll1_sys_clk) || IS_ERR(pll1_sw_clk)) {
+                       dev_err(busfreq_dev, "%s failed to get busfreq clk for imx6ull/sl.\n", __func__);
                        return -EINVAL;
                }
        }
@@ -1160,7 +1205,7 @@ static int busfreq_probe(struct platform_device *pdev)
                        pr_info("ddr3 normal rate changed to 400MHz for TO1.1.\n");
                }
                err = init_ddrc_ddr_settings(pdev);
-       } else if (cpu_is_imx6sx() || cpu_is_imx6ul()) {
+       } else if (cpu_is_imx6sx() || cpu_is_imx6ul() || cpu_is_imx6ull()) {
                ddr_type = imx_mmdc_get_ddr_type();
                if (ddr_type == IMX_DDR_TYPE_DDR3)
                        err = init_mmdc_ddr3_settings_imx6_up(pdev);
index d98bb26..3a016f1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2015 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2011-2016 Freescale Semiconductor, Inc. All Rights Reserved.
  */
 
 /*
@@ -540,7 +540,7 @@ int init_mmdc_ddr3_settings_imx6_up(struct platform_device *busfreq_pdev)
                                + normal_mmdc_settings[i][0]);
        }
 
-       if (cpu_is_imx6ul())
+       if (cpu_is_imx6ul() || cpu_is_imx6ull())
                iomux_settings_size = ARRAY_SIZE(iomux_offsets_mx6ul);
        else
                iomux_settings_size = ARRAY_SIZE(iomux_offsets_mx6sx);
@@ -567,7 +567,7 @@ int init_mmdc_ddr3_settings_imx6_up(struct platform_device *busfreq_pdev)
        }
 
        for (i = 0; i < iomux_settings_size; i++) {
-               if (cpu_is_imx6ul()) {
+               if (cpu_is_imx6ul() || cpu_is_imx6ull()) {
                        iomux_offsets_mx6ul[i][1] =
                        readl_relaxed(iomux_base +
                                iomux_offsets_mx6ul[i][0]);