diff options
author | Bai Ping <b51503@freescale.com> | 2015-07-07 20:47:27 +0800 |
---|---|---|
committer | Bai Ping <b51503@freescale.com> | 2015-07-22 18:23:25 +0800 |
commit | 579724343b31c5f0b664ca39a5cbb66f2ded9ff9 (patch) | |
tree | 9dcb92314ace8933baa904158347fca446e83cdc | |
parent | 1b058645ab95717db8df7de389e1c725dc0c49cc (diff) |
MLK-11234 ARM: imx: add RC-OSC freq initialization on imx6ul
If in low power idle, we use the RC-OSC to reduce the power consumption,
the RC-OSC freq need to be adjusted, otherwise, the RC-OSC freq is not
very accurate. It may lead to system instability issue.
Signed-off-by: Bai Ping <b51503@freescale.com>
(cherry picked from commit d46bf0b55942e20813382be58862aa67bfb8751b)
-rw-r--r-- | arch/arm/mach-imx/cpuidle-imx6ul.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/arch/arm/mach-imx/cpuidle-imx6ul.c b/arch/arm/mach-imx/cpuidle-imx6ul.c index d9d445c4222d..13a2755d27cc 100644 --- a/arch/arm/mach-imx/cpuidle-imx6ul.c +++ b/arch/arm/mach-imx/cpuidle-imx6ul.c @@ -9,6 +9,7 @@ #include <linux/busfreq-imx.h> #include <linux/cpuidle.h> #include <linux/cpu_pm.h> +#include <linux/delay.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/regulator/consumer.h> @@ -25,6 +26,23 @@ #define MAX_MMDC_IO_NUM 14 +#define PMU_LOW_PWR_CTRL 0x270 +#define XTALOSC24M_OSC_CONFIG0 0x2a0 +#define XTALOSC24M_OSC_CONFIG1 0x2b0 +#define XTALOSC24M_OSC_CONFIG2 0x2c0 +#define XTALOSC24M_OSC_CONFIG0_RC_OSC_PROG_CUR_SHIFT 24 +#define XTALOSC24M_OSC_CONFIG0_HYST_MINUS_MASK 0xf +#define XTALOSC24M_OSC_CONFIG0_HYST_MINUS_SHIFT 16 +#define XTALOSC24M_OSC_CONFIG0_HYST_PLUS_MASK 0xf +#define XTALOSC24M_OSC_CONFIG0_HYST_PLUS_SHIFT 12 +#define XTALOSC24M_OSC_CONFIG0_RC_OSC_PROG_SHIFT 4 +#define XTALOSC24M_OSC_CONFIG0_ENABLE_SHIFT 1 +#define XTALOSC24M_OSC_CONFIG0_START_SHIFT 0 +#define XTALOSC24M_OSC_CONFIG1_COUNT_RC_CUR_SHIFT 20 +#define XTALOSC24M_OSC_CONFIG1_COUNT_RC_TRG_SHIFT 0 +#define XTALOSC24M_OSC_CONFIG2_COUNT_1M_TRG_MASK 0xfff +#define XTALOSC24M_OSC_CONFIG2_COUNT_1M_TRG_SHIFT 0 + extern unsigned long iram_tlb_phys_addr; static void __iomem *wfi_iram_base; @@ -131,6 +149,8 @@ static struct cpuidle_driver imx6ul_cpuidle_driver = { int __init imx6ul_cpuidle_init(void) { + void __iomem *anatop_base = (void __iomem *)IMX_IO_P2V(MX6Q_ANATOP_BASE_ADDR); + u32 val; #ifdef CONFIG_CPU_FREQ struct imx6_cpuidle_pm_info *cpuidle_pm_info; int i; @@ -183,5 +203,56 @@ int __init imx6ul_cpuidle_init(void) imx6q_set_int_mem_clk_lpm(true); + /* + * enable RC-OSC here, as it needs at least 4ms for RC-OSC to + * be stable, low power idle flow can NOT endure this big + * latency, so we make RC-OSC self-tuning enabled here. + */ + val = readl_relaxed(anatop_base + PMU_LOW_PWR_CTRL); + val |= 0x1; + writel_relaxed(val, anatop_base + PMU_LOW_PWR_CTRL); + /* + * config RC-OSC freq + * tune_enable = 1;tune_start = 1;hyst_plus = 0;hyst_minus = 0; + * osc_prog = 0xa7; + */ + writel_relaxed( + 0x4 << XTALOSC24M_OSC_CONFIG0_RC_OSC_PROG_CUR_SHIFT | + 0xa7 << XTALOSC24M_OSC_CONFIG0_RC_OSC_PROG_SHIFT | + 0x1 << XTALOSC24M_OSC_CONFIG0_ENABLE_SHIFT | + 0x1 << XTALOSC24M_OSC_CONFIG0_START_SHIFT, + anatop_base + XTALOSC24M_OSC_CONFIG0); + /* set count_trg = 0x2dc */ + writel_relaxed( + 0x40 << XTALOSC24M_OSC_CONFIG1_COUNT_RC_CUR_SHIFT | + 0x2dc << XTALOSC24M_OSC_CONFIG1_COUNT_RC_TRG_SHIFT, + anatop_base + XTALOSC24M_OSC_CONFIG1); + /* wait 4ms according to hardware design */ + msleep(4); + /* + * now add some hysteresis, hyst_plus=3, hyst_minus=3 + * (the minimum hysteresis that looks good is 2) + */ + val = readl_relaxed(anatop_base + XTALOSC24M_OSC_CONFIG0); + val &= ~((XTALOSC24M_OSC_CONFIG0_HYST_MINUS_MASK << + XTALOSC24M_OSC_CONFIG0_HYST_MINUS_SHIFT) | + (XTALOSC24M_OSC_CONFIG0_HYST_PLUS_MASK << + XTALOSC24M_OSC_CONFIG0_HYST_PLUS_SHIFT)); + val |= (0x3 << XTALOSC24M_OSC_CONFIG0_HYST_MINUS_SHIFT) | + (0x3 << XTALOSC24M_OSC_CONFIG0_HYST_PLUS_SHIFT); + writel_relaxed(val, anatop_base + XTALOSC24M_OSC_CONFIG0); + /* set the count_1m_trg = 0x2d7 */ + val = readl_relaxed(anatop_base + XTALOSC24M_OSC_CONFIG2); + val &= ~(XTALOSC24M_OSC_CONFIG2_COUNT_1M_TRG_MASK << + XTALOSC24M_OSC_CONFIG2_COUNT_1M_TRG_SHIFT); + val |= 0x2d7 << XTALOSC24M_OSC_CONFIG2_COUNT_1M_TRG_SHIFT; + writel_relaxed(val, anatop_base + XTALOSC24M_OSC_CONFIG2); + /* + * hardware design require to write XTALOSC24M_OSC_CONFIG0 or + * XTALOSC24M_OSC_CONFIG1 to + * make XTALOSC24M_OSC_CONFIG2 write work + */ + val = readl_relaxed(anatop_base + XTALOSC24M_OSC_CONFIG1); + return cpuidle_register(&imx6ul_cpuidle_driver, NULL); } |