From eb98c3e690ea59da9b5c278fdfb9b96cade4a80c Mon Sep 17 00:00:00 2001 From: Ranjani Vaidyanathan Date: Fri, 30 Jan 2015 13:40:30 -0600 Subject: [PATCH] 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 --- arch/arm/mach-imx/busfreq-imx6.c | 78 +++++++++++++++++------ arch/arm/mach-imx/clk-imx6q.c | 2 +- arch/arm/mach-imx/clk-imx6sl.c | 29 +-------- arch/arm/mach-imx/clk-imx6sx.c | 2 +- arch/arm/mach-imx/clk-pllv3.c | 2 +- arch/arm/mach-imx/imx6sl_lpm_wfi.S | 15 ----- arch/arm/mach-imx/imx6sx_low_power_idle.S | 14 +--- 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); } @@ -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", 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 -- 2.39.2