diff options
author | Anson Huang <b20788@freescale.com> | 2014-01-09 16:03:16 +0800 |
---|---|---|
committer | Shawn Guo <shawn.guo@linaro.org> | 2014-03-05 10:35:01 +0800 |
commit | 751f7e999afcef157527f5f6f06529c93f8a4022 (patch) | |
tree | 49dae752f037aa96d2a61ec88ee5179a75c0d86d /arch/arm/mach-imx/clk-imx6sl.c | |
parent | 848db4a0a17aaf97b8ba5b1f754d635ff622670a (diff) |
ARM: imx: add cpuidle support for i.mx6sl
Add cpuidle support for i.MX6SL, currently only support
two cpuidle levels(ARM wfi and WAIT mode), and add software
workaround for WAIT mode errata as below:
ERR005311 CCM: After exit from WAIT mode, unwanted interrupt(s) taken
during WAIT mode entry process could cause cache memory
corruption.
Software workaround:
To prevent this issue from occurring, software should ensure that
the ARM to IPG clock ratio is less than 12:5 (that is < 2.4x), before
entering WAIT mode.
Signed-off-by: Anson Huang <b20788@freescale.com>
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Diffstat (limited to 'arch/arm/mach-imx/clk-imx6sl.c')
-rw-r--r-- | arch/arm/mach-imx/clk-imx6sl.c | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/arch/arm/mach-imx/clk-imx6sl.c b/arch/arm/mach-imx/clk-imx6sl.c index c5f17c2d4951..6f21a1333fe4 100644 --- a/arch/arm/mach-imx/clk-imx6sl.c +++ b/arch/arm/mach-imx/clk-imx6sl.c @@ -66,6 +66,32 @@ static struct clk_div_table video_div_table[] = { static struct clk *clks[IMX6SL_CLK_END]; static struct clk_onecell_data clk_data; +/* + * ERR005311 CCM: After exit from WAIT mode, unwanted interrupt(s) taken + * during WAIT mode entry process could cause cache memory + * corruption. + * + * Software workaround: + * To prevent this issue from occurring, software should ensure that the + * ARM to IPG clock ratio is less than 12:5 (that is < 2.4x), before + * entering WAIT mode. + * + * This function will set the ARM clk to max value within the 12:5 limit. + */ +void imx6sl_set_wait_clk(bool enter) +{ + static unsigned long saved_arm_rate; + + if (enter) { + unsigned long ipg_rate = clk_get_rate(clks[IMX6SL_CLK_IPG]); + unsigned long max_arm_wait_rate = (12 * ipg_rate) / 5; + saved_arm_rate = clk_get_rate(clks[IMX6SL_CLK_ARM]); + clk_set_rate(clks[IMX6SL_CLK_ARM], max_arm_wait_rate); + } else { + clk_set_rate(clks[IMX6SL_CLK_ARM], saved_arm_rate); + } +} + static void __init imx6sl_clocks_init(struct device_node *ccm_node) { struct device_node *np; |