summaryrefslogtreecommitdiff
path: root/arch/arm/mach-imx
diff options
context:
space:
mode:
authorRanjani Vaidyanathan <Ranjani.Vaidyanathan@freescale.com>2015-01-30 13:40:30 -0600
committerBai Ping <b51503@freescale.com>2015-02-11 18:46:24 +0800
commiteb98c3e690ea59da9b5c278fdfb9b96cade4a80c (patch)
tree39b3ea660f6df9da4c10a8de168bba4b18dd2aa9 /arch/arm/mach-imx
parent0806c8dfd8adc7eb4291c1fbfc45e1e029b4b523 (diff)
MLK-9961-4 arm:imx6x: Change PLL1 clock management.
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>
Diffstat (limited to 'arch/arm/mach-imx')
-rw-r--r--arch/arm/mach-imx/busfreq-imx6.c78
-rw-r--r--arch/arm/mach-imx/clk-imx6q.c2
-rw-r--r--arch/arm/mach-imx/clk-imx6sl.c29
-rw-r--r--arch/arm/mach-imx/clk-imx6sx.c2
-rw-r--r--arch/arm/mach-imx/clk-pllv3.c2
-rw-r--r--arch/arm/mach-imx/imx6sl_lpm_wfi.S15
-rw-r--r--arch/arm/mach-imx/imx6sx_low_power_idle.S14
7 files changed, 65 insertions, 77 deletions
diff --git a/arch/arm/mach-imx/busfreq-imx6.c b/arch/arm/mach-imx/busfreq-imx6.c
index 5f7649bc5a1a..7d65d08a4653 100644
--- a/arch/arm/mach-imx/busfreq-imx6.c
+++ b/arch/arm/mach-imx/busfreq-imx6.c
@@ -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);
}
@@ -287,6 +292,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,13 +337,18 @@ 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",
diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c
index 213485756283..c05df7346072 100644
--- a/arch/arm/mach-imx/clk-imx6q.c
+++ b/arch/arm/mach-imx/clk-imx6q.c
@@ -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);
diff --git a/arch/arm/mach-imx/clk-imx6sl.c b/arch/arm/mach-imx/clk-imx6sl.c
index 17ebe1b748b5..1a6a2269a246 100644
--- a/arch/arm/mach-imx/clk-imx6sl.c
+++ b/arch/arm/mach-imx/clk-imx6sl.c
@@ -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);
diff --git a/arch/arm/mach-imx/clk-imx6sx.c b/arch/arm/mach-imx/clk-imx6sx.c
index f64bf9a7b7ec..f61237db3cda 100644
--- a/arch/arm/mach-imx/clk-imx6sx.c
+++ b/arch/arm/mach-imx/clk-imx6sx.c
@@ -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);
diff --git a/arch/arm/mach-imx/clk-pllv3.c b/arch/arm/mach-imx/clk-pllv3.c
index 08451d6ff04f..728280ec7f92 100644
--- a/arch/arm/mach-imx/clk-pllv3.c
+++ b/arch/arm/mach-imx/clk-pllv3.c
@@ -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;
diff --git a/arch/arm/mach-imx/imx6sl_lpm_wfi.S b/arch/arm/mach-imx/imx6sl_lpm_wfi.S
index 439556f7a243..c8aa2dd93ca0 100644
--- a/arch/arm/mach-imx/imx6sl_lpm_wfi.S
+++ b/arch/arm/mach-imx/imx6sl_lpm_wfi.S
@@ -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]
diff --git a/arch/arm/mach-imx/imx6sx_low_power_idle.S b/arch/arm/mach-imx/imx6sx_low_power_idle.S
index dd0a22086c5b..796e9fd6d71c 100644
--- a/arch/arm/mach-imx/imx6sx_low_power_idle.S
+++ b/arch/arm/mach-imx/imx6sx_low_power_idle.S
@@ -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
@@ -90,13 +90,6 @@
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 */
@@ -203,11 +196,6 @@
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