]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - arch/arm/mach-imx/clk-imx6sl.c
MLK-9961-4 arm:imx6x: Change PLL1 clock management.
[karo-tx-linux.git] / arch / arm / mach-imx / clk-imx6sl.c
index 51760c55c2841b1d06266c96eff84a18aa5de344..1a6a2269a24698816bb3aa8f54dc2154e1f8ee14 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2013-2014 Freescale Semiconductor, Inc.
+ * Copyright 2013-2015 Freescale Semiconductor, Inc.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -23,6 +23,7 @@
 #define CCDR                   0x04
 #define CCDR_CH0_HS_BYP                17
 #define BM_CCSR_PLL1_SW_CLK_SEL        (1 << 2)
+#define BM_CCSR_STEP_CLK_SEL   (1 << 8)
 #define CACRR                  0x10
 #define CDHIPR                 0x48
 #define BM_CDHIPR_ARM_PODF_BUSY        (1 << 16)
@@ -102,6 +103,7 @@ static struct clk_div_table video_div_table[] = {
 static unsigned int share_count_ssi1;
 static unsigned int share_count_ssi2;
 static unsigned int share_count_ssi3;
+static unsigned int share_count_spdif;
 
 static struct clk *clks[IMX6SL_CLK_END];
 static struct clk_onecell_data clk_data;
@@ -112,6 +114,7 @@ static const u32 clks_init_on[] __initconst = {
        IMX6SL_CLK_IPG, IMX6SL_CLK_ARM, IMX6SL_CLK_MMDC_ROOT,
 };
 
+extern int low_bus_freq_mode;
 /*
  * ERR005311 CCM: After exit from WAIT mode, unwanted interrupt(s) taken
  *           during WAIT mode entry process could cause cache memory
@@ -147,46 +150,38 @@ 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) {
-               saved_arm_div = readl_relaxed(ccm_base + CACRR);
-               writel_relaxed(arm_div_for_wait, ccm_base + CACRR);
+               /*
+                * If in this mode, the IPG clock is at 12MHz, we can
+                * only run ARM at a max 28.8MHz, so we need to run
+                * from the 24MHz OSC, as there is no way to get
+                * 28.8MHz, when ARM is sourced from PLl1.
+                */
+               if (low_bus_freq_mode) {
+                       val = readl_relaxed(ccm_base + CCSR);
+                       val |= BM_CCSR_PLL1_SW_CLK_SEL;
+                       writel_relaxed(val, ccm_base + CCSR);
+               } else {
+                       saved_arm_div = readl_relaxed(ccm_base + CACRR);
+                       writel_relaxed(arm_div_for_wait, ccm_base + CACRR);
+               }
        } else {
-               writel_relaxed(saved_arm_div, ccm_base + CACRR);
+               if (low_bus_freq_mode) {
+                       val = readl_relaxed(ccm_base + CCSR);
+                       val &= ~BM_CCSR_PLL1_SW_CLK_SEL;
+                       writel_relaxed(val, ccm_base + CCSR);
+               } else {
+                       writel_relaxed(saved_arm_div, ccm_base + CACRR);
+               }
        }
        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)
@@ -247,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);
@@ -405,7 +400,8 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
        clks[IMX6SL_CLK_PWM4]         = imx_clk_gate2("pwm4",         "perclk",            base + 0x78, 22);
        clks[IMX6SL_CLK_SDMA]         = imx_clk_gate2("sdma",         "ipg",               base + 0x7c, 6);
        clks[IMX6SL_CLK_SPBA]         = imx_clk_gate2("spba",         "ipg",               base + 0x7c, 12);
-       clks[IMX6SL_CLK_SPDIF]        = imx_clk_gate2("spdif",        "spdif0_podf",       base + 0x7c, 14);
+       clks[IMX6SL_CLK_SPDIF]        = imx_clk_gate2_shared("spdif",     "spdif0_podf",   base + 0x7c, 14, &share_count_spdif);
+       clks[IMX6SL_CLK_SPDIF_GCLK]   = imx_clk_gate2_shared("spdif_gclk",  "ipg",         base + 0x7c, 14, &share_count_spdif);
        clks[IMX6SL_CLK_SSI1_IPG]     = imx_clk_gate2_shared("ssi1_ipg",     "ipg",        base + 0x7c, 18, &share_count_ssi1);
        clks[IMX6SL_CLK_SSI2_IPG]     = imx_clk_gate2_shared("ssi2_ipg",     "ipg",        base + 0x7c, 20, &share_count_ssi2);
        clks[IMX6SL_CLK_SSI3_IPG]     = imx_clk_gate2_shared("ssi3_ipg",     "ipg",        base + 0x7c, 22, &share_count_ssi3);