aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorRanjani Vaidyanathan <ra5478@freescale.com>2013-08-26 14:50:03 -0400
committerNitin Garg <nitin.garg@freescale.com>2014-04-16 09:05:33 -0400
commit2503fa545b9c6441080ae1903a87882ecd40e2a5 (patch)
treed03b4fa0fd70f537781c8b13846e189482283fbd /arch
parentf7acad14c0eea241c5a5ed0378c8f45bb002d14b (diff)
ENGR00277382-2 [MX6SL] Add WaIT mode support for MX6SL.
Enable WAIT mode support for MX6SL. Need to ensure that the ARM:IPG clock ratio is maintained at 12:5 when WFI is executed. This is the fix for the WAIT mode issue on MX6SL. Set AHB to 132Mhz at boot, which is the recommended freq for AHB. Signed-off-by: Ranjani Vaidyanathan <ra5478@freescale.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-imx/Makefile1
-rw-r--r--arch/arm/mach-imx/clk-imx6sl.c29
-rw-r--r--arch/arm/mach-imx/common.h1
-rw-r--r--arch/arm/mach-imx/cpuidle-imx6sl.c54
-rw-r--r--arch/arm/mach-imx/cpuidle.h7
-rw-r--r--arch/arm/mach-imx/mach-imx6sl.c4
6 files changed, 95 insertions, 1 deletions
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index e53fb59eaf95..9b80b2328785 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o
31ifeq ($(CONFIG_CPU_IDLE),y) 31ifeq ($(CONFIG_CPU_IDLE),y)
32obj-$(CONFIG_SOC_IMX5) += cpuidle-imx5.o 32obj-$(CONFIG_SOC_IMX5) += cpuidle-imx5.o
33obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o 33obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o
34obj-$(CONFIG_SOC_IMX6SL) += cpuidle-imx6sl.o
34endif 35endif
35 36
36ifdef CONFIG_SND_IMX_SOC 37ifdef CONFIG_SND_IMX_SOC
diff --git a/arch/arm/mach-imx/clk-imx6sl.c b/arch/arm/mach-imx/clk-imx6sl.c
index cc054d122830..5a7e76af7698 100644
--- a/arch/arm/mach-imx/clk-imx6sl.c
+++ b/arch/arm/mach-imx/clk-imx6sl.c
@@ -67,6 +67,30 @@ static struct clk_div_table video_div_table[] = {
67 67
68static struct clk *clks[IMX6SL_CLK_CLK_END]; 68static struct clk *clks[IMX6SL_CLK_CLK_END];
69static struct clk_onecell_data clk_data; 69static struct clk_onecell_data clk_data;
70static u32 cur_arm_podf;
71
72/*
73 * On MX6SL, need to ensure that the ARM:IPG clock ratio is maintained
74 * within 12:5 when the clocks to ARM are gated when the SOC enters
75 * WAIT mode. This is necessary to avoid WAIT mode issue (an early
76 * interrupt waking up the ARM).
77 * This function will set the ARM clk to max value within the 12:5 limit.
78 */
79void imx6sl_set_wait_clk(bool enter)
80{
81 u32 parent_rate = clk_get_rate(clk_get_parent(clks[IMX6SL_CLK_ARM]));
82
83 if (enter) {
84 u32 ipg_rate = clk_get_rate(clks[IMX6SL_CLK_IPG]);
85 u32 max_arm_wait_clk = (12 * ipg_rate) / 5;
86 u32 wait_podf = (parent_rate + max_arm_wait_clk - 1) /
87 max_arm_wait_clk;
88
89 cur_arm_podf = parent_rate / clk_get_rate(clks[IMX6SL_CLK_ARM]);
90 clk_set_rate(clks[IMX6SL_CLK_ARM], parent_rate / wait_podf);
91 } else
92 clk_set_rate(clks[IMX6SL_CLK_ARM], parent_rate / cur_arm_podf);
93}
70 94
71static void __init imx6sl_clocks_init(struct device_node *ccm_node) 95static void __init imx6sl_clocks_init(struct device_node *ccm_node)
72{ 96{
@@ -258,6 +282,11 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
258 clk_register_clkdev(clks[IMX6SL_CLK_GPT], "ipg", "imx-gpt.0"); 282 clk_register_clkdev(clks[IMX6SL_CLK_GPT], "ipg", "imx-gpt.0");
259 clk_register_clkdev(clks[IMX6SL_CLK_GPT_SERIAL], "per", "imx-gpt.0"); 283 clk_register_clkdev(clks[IMX6SL_CLK_GPT_SERIAL], "per", "imx-gpt.0");
260 284
285 /* Ensure the AHB clk is at 132MHz. */
286 ret = clk_set_rate(clks[IMX6SL_CLK_AHB], 132000000);
287 if (ret)
288 pr_warn("%s: failed to set AHB clock rate %d\n", __func__, ret);
289
261 /* 290 /*
262 * To prevent the bus clock from being disabled accidently when 291 * To prevent the bus clock from being disabled accidently when
263 * clk_disable() gets called on child clock, let's increment the use 292 * clk_disable() gets called on child clock, let's increment the use
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index 790ca9678843..36647133e3e6 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -146,6 +146,7 @@ extern void imx_anatop_post_resume(void);
146extern void imx_anatop_pu_enable(bool enable); 146extern void imx_anatop_pu_enable(bool enable);
147extern int imx6_set_lpm(enum mxc_cpu_pwr_mode mode); 147extern int imx6_set_lpm(enum mxc_cpu_pwr_mode mode);
148extern void imx6_set_cache_lpm_in_wait(bool enable); 148extern void imx6_set_cache_lpm_in_wait(bool enable);
149extern void imx6sl_set_wait_clk(bool enter);
149 150
150extern void imx_cpu_die(unsigned int cpu); 151extern void imx_cpu_die(unsigned int cpu);
151extern int imx_cpu_kill(unsigned int cpu); 152extern int imx_cpu_kill(unsigned int cpu);
diff --git a/arch/arm/mach-imx/cpuidle-imx6sl.c b/arch/arm/mach-imx/cpuidle-imx6sl.c
new file mode 100644
index 000000000000..7d8ed7c90043
--- /dev/null
+++ b/arch/arm/mach-imx/cpuidle-imx6sl.c
@@ -0,0 +1,54 @@
1/*
2 * Copyright (C) 2012-2013 Freescale Semiconductor, Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/cpuidle.h>
10#include <linux/module.h>
11#include <linux/of.h>
12#include <asm/cpuidle.h>
13#include <asm/proc-fns.h>
14
15#include "common.h"
16#include "cpuidle.h"
17
18static int imx6sl_enter_wait(struct cpuidle_device *dev,
19 struct cpuidle_driver *drv, int index)
20{
21 imx6_set_lpm(WAIT_UNCLOCKED);
22 imx6sl_set_wait_clk(true);
23 cpu_do_idle();
24 imx6sl_set_wait_clk(false);
25 imx6_set_lpm(WAIT_CLOCKED);
26
27 return index;
28}
29
30static struct cpuidle_driver imx6sl_cpuidle_driver = {
31 .name = "imx6sl_cpuidle",
32 .owner = THIS_MODULE,
33 .states = {
34 /* WFI */
35 ARM_CPUIDLE_WFI_STATE,
36 /* WAIT */
37 {
38 .exit_latency = 50,
39 .target_residency = 75,
40 .flags = CPUIDLE_FLAG_TIME_VALID |
41 CPUIDLE_FLAG_TIMER_STOP,
42 .enter = imx6sl_enter_wait,
43 .name = "WAIT",
44 .desc = "Clock off",
45 },
46 },
47 .state_count = 2,
48 .safe_state_index = 0,
49};
50
51int __init imx6sl_cpuidle_init(void)
52{
53 return cpuidle_register(&imx6sl_cpuidle_driver, NULL);
54}
diff --git a/arch/arm/mach-imx/cpuidle.h b/arch/arm/mach-imx/cpuidle.h
index 786f98ecc145..0cdeeaff08f7 100644
--- a/arch/arm/mach-imx/cpuidle.h
+++ b/arch/arm/mach-imx/cpuidle.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright 2012 Freescale Semiconductor, Inc. 2 * Copyright 2012-2013 Freescale Semiconductor, Inc.
3 * Copyright 2012 Linaro Ltd. 3 * Copyright 2012 Linaro Ltd.
4 * 4 *
5 * The code contained herein is licensed under the GNU General Public 5 * The code contained herein is licensed under the GNU General Public
@@ -13,6 +13,7 @@
13#ifdef CONFIG_CPU_IDLE 13#ifdef CONFIG_CPU_IDLE
14extern int imx5_cpuidle_init(void); 14extern int imx5_cpuidle_init(void);
15extern int imx6q_cpuidle_init(void); 15extern int imx6q_cpuidle_init(void);
16extern int imx6sl_cpuidle_init(void);
16#else 17#else
17static inline int imx5_cpuidle_init(void) 18static inline int imx5_cpuidle_init(void)
18{ 19{
@@ -22,4 +23,8 @@ static inline int imx6q_cpuidle_init(void)
22{ 23{
23 return 0; 24 return 0;
24} 25}
26static inline int imx6sl_cpuidle_init(void)
27{
28 return 0;
29}
25#endif 30#endif
diff --git a/arch/arm/mach-imx/mach-imx6sl.c b/arch/arm/mach-imx/mach-imx6sl.c
index 0578373c9bfe..e1c83798bc3d 100644
--- a/arch/arm/mach-imx/mach-imx6sl.c
+++ b/arch/arm/mach-imx/mach-imx6sl.c
@@ -19,6 +19,7 @@
19#include <asm/mach/map.h> 19#include <asm/mach/map.h>
20 20
21#include "common.h" 21#include "common.h"
22#include "cpuidle.h"
22#include "hardware.h" 23#include "hardware.h"
23 24
24static struct platform_device imx6sl_cpufreq_pdev = { 25static struct platform_device imx6sl_cpufreq_pdev = {
@@ -94,6 +95,9 @@ static void __init imx6sl_init_late(void)
94 else 95 else
95 pr_err("failed to find fsl,imx6sl-iomux-gpr regmap\n"); 96 pr_err("failed to find fsl,imx6sl-iomux-gpr regmap\n");
96 97
98 /* Init CPUIDLE */
99 imx6sl_cpuidle_init();
100
97 if (IS_ENABLED(CONFIG_ARM_IMX6_CPUFREQ)) { 101 if (IS_ENABLED(CONFIG_ARM_IMX6_CPUFREQ)) {
98 imx6sl_opp_init(&imx6sl_cpufreq_pdev.dev); 102 imx6sl_opp_init(&imx6sl_cpufreq_pdev.dev);
99 platform_device_register(&imx6sl_cpufreq_pdev); 103 platform_device_register(&imx6sl_cpufreq_pdev);