]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
MLK-9961-4 arm:imx6x: Change PLL1 clock management.
authorRanjani Vaidyanathan <Ranjani.Vaidyanathan@freescale.com>
Fri, 30 Jan 2015 19:40:30 +0000 (13:40 -0600)
committerBai Ping <b51503@freescale.com>
Wed, 11 Feb 2015 10:46:24 +0000 (18:46 +0800)
Add support to leave PLL1 enabled since its required whenever ARM-PODF is
changed. With this patch PLL1 is set to bypassed mode (and enabled) whenever
ARM is sourced from step_clk.

Signed-off-by: Ranjani Vaidyanathan <Ranjani.Vaidyanathan@freescale.com>
arch/arm/mach-imx/busfreq-imx6.c
arch/arm/mach-imx/clk-imx6q.c
arch/arm/mach-imx/clk-imx6sl.c
arch/arm/mach-imx/clk-imx6sx.c
arch/arm/mach-imx/clk-pllv3.c
arch/arm/mach-imx/imx6sl_lpm_wfi.S
arch/arm/mach-imx/imx6sx_low_power_idle.S

index 5f7649bc5a1a31d19348922579ca6e9545c98474..7d65d08a46538e30e1f052ec2f5b2104b53f7e92 100644 (file)
@@ -117,6 +117,9 @@ static struct clk *axi_alt_sel_clk;
 static struct clk *axi_sel_clk;
 static struct clk *pll3_pfd1_540m;
 static struct clk *m4_clk;
+static struct clk *pll1;
+static struct clk *pll1_bypass;
+static struct clk *pll1_bypass_src;
 
 static u32 pll2_org_rate;
 static struct delayed_work low_bus_freq_handler;
@@ -231,9 +234,10 @@ static void exit_lpm_imx6sx(void)
        else if (ddr_type == MMDC_MDMISC_DDR_TYPE_LPDDR2)
                update_lpddr2_freq(ddr_normal_rate);
        /* correct parent info after ddr freq change in asm code */
-       imx_clk_set_parent(periph2_clk2_sel, pll3);
        imx_clk_set_parent(periph2_pre_clk, pll2_400);
        imx_clk_set_parent(periph2_clk, periph2_pre_clk);
+       imx_clk_set_parent(periph2_clk2_sel, pll3);
+
        /*
         * As periph2_clk's parent is not changed from
         * audio mode to high mode, so clk framework
@@ -247,6 +251,7 @@ static void exit_lpm_imx6sx(void)
                imx_clk_set_rate(mmdc_clk, ddr_normal_rate);
 
        clk_disable_unprepare(pll2_400);
+
        if (audio_bus_freq_mode)
                clk_disable_unprepare(pll2_400);
 }
@@ -286,6 +291,12 @@ static void enter_lpm_imx6sl(void)
                         */
                        imx_clk_set_parent(step_clk, pll2_400);
                        imx_clk_set_parent(pll1_sw_clk, step_clk);
+                       /*
+                         * Need to ensure that PLL1 is bypassed and enabled
+                         * before ARM-PODF is set.
+                         */
+                       clk_set_parent(pll1_bypass, pll1_bypass_src);
+
                        /*
                         * Ensure that the clock will be
                         * at original speed.
@@ -326,12 +337,17 @@ static void enter_lpm_imx6sl(void)
                                 * the CPU freq does not change, so attempt to
                                 * get a freq as close to 396MHz as possible.
                                 */
-                               imx_clk_set_rate(pll1_sys,
-                                       clk_round_rate(pll1_sys, (org_arm_rate * 2)));
-                               pll1_rate = clk_get_rate(pll1_sys);
+                               imx_clk_set_rate(pll1,
+                                       clk_round_rate(pll1, (org_arm_rate * 2)));
+                               pll1_rate = clk_get_rate(pll1);
                                arm_div = pll1_rate / org_arm_rate;
                                if (pll1_rate / arm_div > org_arm_rate)
                                        arm_div++;
+                               /*
+                                 * Need to ensure that PLL1 is bypassed and enabled
+                                 * before ARM-PODF is set.
+                                 */
+                               clk_set_parent(pll1_bypass, pll1);
                                /*
                                 * Ensure ARM CLK is lower before
                                 * changing the parent.
@@ -402,6 +418,11 @@ static void exit_lpm_imx6sl(void)
                /* Move ARM from PLL1_SW_CLK to PLL2_400. */
                imx_clk_set_parent(step_clk, pll2_400);
                imx_clk_set_parent(pll1_sw_clk, step_clk);
+               /*
+                 * Need to ensure that PLL1 is bypassed and enabled
+                 * before ARM-PODF is set.
+                 */
+               clk_set_parent(pll1_bypass, pll1_bypass_src);
                imx_clk_set_rate(cpu_clk, org_arm_rate);
                ultra_low_bus_freq_mode = 0;
        }
@@ -958,13 +979,6 @@ static int busfreq_probe(struct platform_device *pdev)
        }
 
        if (cpu_is_imx6sl() || cpu_is_imx6sx()) {
-               pll1_sys = devm_clk_get(&pdev->dev, "pll1_sys");
-               if (IS_ERR(pll1_sys)) {
-                       dev_err(busfreq_dev, "%s: failed to get pll1_sys\n",
-                               __func__);
-                       return PTR_ERR(pll1_sys);
-               }
-
                ahb_clk = devm_clk_get(&pdev->dev, "ahb");
                if (IS_ERR(ahb_clk)) {
                        dev_err(busfreq_dev, "%s: failed to get ahb_clk\n",
@@ -979,13 +993,6 @@ static int busfreq_probe(struct platform_device *pdev)
                        return PTR_ERR(ocram_clk);
                }
 
-               pll1_sw_clk = devm_clk_get(&pdev->dev, "pll1_sw");
-               if (IS_ERR(pll1_sw_clk)) {
-                       dev_err(busfreq_dev, "%s: failed to get pll1_sw_clk\n",
-                               __func__);
-                       return PTR_ERR(pll1_sw_clk);
-               }
-
                periph2_clk = devm_clk_get(&pdev->dev, "periph2");
                if (IS_ERR(periph2_clk)) {
                        dev_err(busfreq_dev, "%s: failed to get periph2\n",
@@ -1026,6 +1033,41 @@ static int busfreq_probe(struct platform_device *pdev)
                }
        }
        if (cpu_is_imx6sl()) {
+               pll1 = devm_clk_get(&pdev->dev, "pll1");
+               if (IS_ERR(pll1)) {
+                       dev_err(busfreq_dev, "%s: failed to get pll1\n",
+                               __func__);
+                       return PTR_ERR(pll1);
+               }
+
+               pll1_bypass = devm_clk_get(&pdev->dev, "pll1_bypass");
+               if (IS_ERR(pll1_bypass)) {
+                       dev_err(busfreq_dev, "%s: failed to get pll1_bypass\n",
+                               __func__);
+                       return PTR_ERR(pll1_bypass);
+               }
+
+               pll1_bypass_src = devm_clk_get(&pdev->dev, "pll1_bypass_src");
+               if (IS_ERR(pll1_bypass_src)) {
+                       dev_err(busfreq_dev, "%s: failed to get pll1_bypass_src\n",
+                               __func__);
+                       return PTR_ERR(pll1_bypass_src);
+               }
+
+               pll1_sys = devm_clk_get(&pdev->dev, "pll1_sys");
+               if (IS_ERR(pll1_sys)) {
+                       dev_err(busfreq_dev, "%s: failed to get pll1_sys\n",
+                               __func__);
+                       return PTR_ERR(pll1_sys);
+               }
+
+               pll1_sw_clk = devm_clk_get(&pdev->dev, "pll1_sw");
+               if (IS_ERR(pll1_sw_clk)) {
+                       dev_err(busfreq_dev, "%s: failed to get pll1_sw_clk\n",
+                               __func__);
+                       return PTR_ERR(pll1_sw_clk);
+               }
+
                pll2_bypass_src = devm_clk_get(&pdev->dev, "pll2_bypass_src");
                if (IS_ERR(pll2_bypass_src)) {
                        dev_err(busfreq_dev, "%s: failed to get pll2_bypass_src\n",
index 213485756283a6928539b94a1ede867a06caaca3..c05df7346072fc614fdf19866f3ea847bcbf3165 100644 (file)
@@ -185,7 +185,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
        imx_clk_set_parent(clk[IMX6QDL_PLL6_BYPASS], clk[IMX6QDL_CLK_PLL6]);
        imx_clk_set_parent(clk[IMX6QDL_PLL7_BYPASS], clk[IMX6QDL_CLK_PLL7]);
 
-       clk[IMX6QDL_CLK_PLL1_SYS]      = imx_clk_gate("pll1_sys",      "pll1_bypass", base + 0x00, 13);
+       clk[IMX6QDL_CLK_PLL1_SYS]      = imx_clk_fixed_factor("pll1_sys",      "pll1_bypass", 1, 1);
        clk[IMX6QDL_CLK_PLL2_BUS]      = imx_clk_gate("pll2_bus",      "pll2_bypass", base + 0x30, 13);
        clk[IMX6QDL_CLK_PLL3_USB_OTG]  = imx_clk_gate("pll3_usb_otg",  "pll3_bypass", base + 0x10, 13);
        clk[IMX6QDL_CLK_PLL4_AUDIO]    = imx_clk_gate("pll4_audio",    "pll4_bypass", base + 0x70, 13);
index 17ebe1b748b5cbaba780894d8ad89610d1bcb9c8..1a6a2269a24698816bb3aa8f54dc2154e1f8ee14 100644 (file)
@@ -150,36 +150,12 @@ static int imx6sl_get_arm_divider_for_wait(void)
        }
 }
 
-static void imx6sl_enable_pll_arm(bool enable)
-{
-       static u32 saved_pll_arm;
-       u32 val;
-
-       if (enable) {
-               saved_pll_arm = val = readl_relaxed(anatop_base + PLL_ARM);
-               val |= BM_PLL_ARM_ENABLE;
-               val &= ~BM_PLL_ARM_POWERDOWN;
-               writel_relaxed(val, anatop_base + PLL_ARM);
-               while (!(__raw_readl(anatop_base + PLL_ARM) & BM_PLL_ARM_LOCK))
-                       ;
-       } else {
-                writel_relaxed(saved_pll_arm, anatop_base + PLL_ARM);
-       }
-}
-
 void imx6sl_set_wait_clk(bool enter)
 {
        static unsigned long saved_arm_div;
        u32 val;
        int arm_div_for_wait = imx6sl_get_arm_divider_for_wait();
 
-       /*
-        * According to hardware design, arm podf change need
-        * PLL1 clock enabled.
-        */
-       if (arm_div_for_wait == ARM_WAIT_DIV_396M)
-               imx6sl_enable_pll_arm(true);
-
        if (enter) {
                /*
                 * If in this mode, the IPG clock is at 12MHz, we can
@@ -206,9 +182,6 @@ void imx6sl_set_wait_clk(bool enter)
        }
        while (__raw_readl(ccm_base + CDHIPR) & BM_CDHIPR_ARM_PODF_BUSY)
                ;
-
-       if (arm_div_for_wait == ARM_WAIT_DIV_396M)
-               imx6sl_enable_pll_arm(false);
 }
 
 static int __init setup_uart_clk(char *uart_rate)
@@ -269,7 +242,7 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
        imx_clk_set_parent(clks[IMX6SL_PLL6_BYPASS], clks[IMX6SL_CLK_PLL6]);
        imx_clk_set_parent(clks[IMX6SL_PLL7_BYPASS], clks[IMX6SL_CLK_PLL7]);
 
-       clks[IMX6SL_CLK_PLL1_SYS]      = imx_clk_gate("pll1_sys",      "pll1_bypass", base + 0x00, 13);
+       clks[IMX6SL_CLK_PLL1_SYS]      = imx_clk_fixed_factor("pll1_sys",      "pll1_bypass", 1, 1);
        clks[IMX6SL_CLK_PLL2_BUS]      = imx_clk_gate("pll2_bus",      "pll2_bypass", base + 0x30, 13);
        clks[IMX6SL_CLK_PLL3_USB_OTG]  = imx_clk_gate("pll3_usb_otg",  "pll3_bypass", base + 0x10, 13);
        clks[IMX6SL_CLK_PLL4_AUDIO]    = imx_clk_gate("pll4_audio",    "pll4_bypass", base + 0x70, 13);
index f64bf9a7b7ecadab73f21f14b044d4a4b70bd293..f61237db3cda9607360ad151e8daa0c48bea81ad 100644 (file)
@@ -239,7 +239,7 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
        imx_clk_set_parent(clks[IMX6SX_PLL6_BYPASS], clks[IMX6SX_CLK_PLL6]);
        imx_clk_set_parent(clks[IMX6SX_PLL7_BYPASS], clks[IMX6SX_CLK_PLL7]);
 
-       clks[IMX6SX_CLK_PLL1_SYS]      = imx_clk_gate("pll1_sys",      "pll1_bypass", base + 0x00, 13);
+       clks[IMX6SX_CLK_PLL1_SYS]      = imx_clk_fixed_factor("pll1_sys",      "pll1_bypass", 1, 1);
        clks[IMX6SX_CLK_PLL2_BUS]      = imx_clk_gate("pll2_bus",      "pll2_bypass", base + 0x30, 13);
        clks[IMX6SX_CLK_PLL3_USB_OTG]  = imx_clk_gate("pll3_usb_otg",  "pll3_bypass", base + 0x10, 13);
        clks[IMX6SX_CLK_PLL4_AUDIO]    = imx_clk_gate("pll4_audio",    "pll4_bypass", base + 0x70, 13);
index 08451d6ff04f1bbe9dcd86975e790bc4cf49114c..728280ec7f928abe00ab251ad9fc3d53c8dbf684 100644 (file)
@@ -354,7 +354,7 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
 
        init.name = name;
        init.ops = ops;
-       init.flags = CLK_SET_RATE_GATE;
+       init.flags = CLK_SET_RATE_GATE | CLK_GET_RATE_NOCACHE;
        init.parent_names = &parent_name;
        init.num_parents = 1;
 
index 439556f7a24373cf5509171267e2f4883b201783..c8aa2dd93ca0572c8b460a9eafbeb50472b562eb 100644 (file)
@@ -125,14 +125,6 @@ audio_mode:
        str     r6, [r10, #0x14]
 
        ccm_do_wait
-       /*
-        * Bypass PLL1. the PLL1 output is disabled,
-        * need to enable its output.
-        */
-       ldr     r10, [r0, #PM_INFO_ANATOP_V_OFFSET]
-       ldr     r6, =(1 << 16)
-       orr     r6, r6, #0x2000
-       str     r6, [r10, #0x04]
 
        /*
         * ARM is sourced from pll2_pfd2_400M here.
@@ -205,13 +197,6 @@ audio_ccm_restore:
        orr     r6, r6, #0x4
        str     r6, [r10, #0xc]
 
-       ldr     r10, [r0, #PM_INFO_ANATOP_V_OFFSET]
-
-       ldr     r6, =(1 << 16)
-       str     r6, [r10, #0x08]
-       ldr     r6, =(1 << 13)
-       str     r6, [r10, #0x8]
-
        /* restore mmdc podf */
        ldr     r10, [r0, #PM_INFO_CCM_V_OFFSET]
        ldr     r6, [r10, #0x14]
index dd0a22086c5b72ce0b1658b9a0b9adbd80bb6827..796e9fd6d71ccab6b41275e1915c7a26a00221d2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2014-2015 Freescale Semiconductor, Inc. All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 
        ccm_do_wait
 
-       ldr     r10, [r0, #PM_INFO_MX6Q_ANATOP_V_OFFSET]
-
-       /* enable PLL1 bypass output */
-       ldr     r7, [r10]
-       orr     r7, r7, #0x12000
-       str     r7, [r10]
-
        ldr     r10, [r0, #PM_INFO_MX6Q_CCM_V_OFFSET]
 
        /* set pll1_sw to from pll1 main */
        ldreq   r10, [r0, #PM_INFO_MX6Q_ANATOP_V_OFFSET]
        ldrne   r10, [r0, #PM_INFO_MX6Q_ANATOP_P_OFFSET]
 
-       /* disable PLL1 bypass output */
-       ldr     r7, [r10]
-       bic     r7, r7, #0x12000
-       str     r7, [r10]
-
        .endm
 
        .macro  anatop_enter_idle