aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-imx
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2012-06-30 19:13:15 -0400
committerOlof Johansson <olof@lixom.net>2012-06-30 19:13:15 -0400
commit839ab0c18fe4cf83dd99ca814f2b4cf822cd99be (patch)
tree868e835a3cee2d3bb5071a0f00eb98bcce8ebdea /arch/arm/mach-imx
parent6b16351acbd415e66ba16bf7d473ece1574cf0bc (diff)
parentb9d18dc3a05d59894d60d5e173ebfb89a4b91bdf (diff)
Merge branch 'imx/cpuidle' into next/pm
* imx/cpuidle: ARM: imx: Add imx6q cpuidle driver ARM: imx: Add imx5 cpuidle ARM: imx: Add common imx cpuidle init functionality. ARM: imx: Enable imx53 low power idle ARM: imx: clean and consolidate imx5 suspend and idle code ARM: imx: Add comments to tzic_enable_waker() ARM: imx: Modify IMX_IO_P2V macro Resolved trivial context conflict in arch/arm/plat-mxc/include/mach/common.h Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'arch/arm/mach-imx')
-rw-r--r--arch/arm/mach-imx/clk-imx51-imx53.c2
-rw-r--r--arch/arm/mach-imx/imx53-dt.c1
-rw-r--r--arch/arm/mach-imx/mach-imx6q.c19
-rw-r--r--arch/arm/mach-imx/mach-mx53_ard.c1
-rw-r--r--arch/arm/mach-imx/mach-mx53_evk.c1
-rw-r--r--arch/arm/mach-imx/mach-mx53_loco.c1
-rw-r--r--arch/arm/mach-imx/mach-mx53_smd.c1
-rw-r--r--arch/arm/mach-imx/mm-imx5.c26
-rw-r--r--arch/arm/mach-imx/pm-imx5.c111
9 files changed, 116 insertions, 47 deletions
diff --git a/arch/arm/mach-imx/clk-imx51-imx53.c b/arch/arm/mach-imx/clk-imx51-imx53.c
index a2200c77bf70..4b89fae14a5a 100644
--- a/arch/arm/mach-imx/clk-imx51-imx53.c
+++ b/arch/arm/mach-imx/clk-imx51-imx53.c
@@ -279,6 +279,7 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil,
279 clk_register_clkdev(clk[dummy], NULL, "imx-keypad"); 279 clk_register_clkdev(clk[dummy], NULL, "imx-keypad");
280 clk_register_clkdev(clk[tve_gate], NULL, "imx-tve.0"); 280 clk_register_clkdev(clk[tve_gate], NULL, "imx-tve.0");
281 clk_register_clkdev(clk[ipu_di1_gate], "di1", "imx-tve.0"); 281 clk_register_clkdev(clk[ipu_di1_gate], "di1", "imx-tve.0");
282 clk_register_clkdev(clk[gpc_dvfs], "gpc_dvfs", NULL);
282 283
283 /* Set SDHC parents to be PLL2 */ 284 /* Set SDHC parents to be PLL2 */
284 clk_set_parent(clk[esdhc_a_sel], clk[pll2_sw]); 285 clk_set_parent(clk[esdhc_a_sel], clk[pll2_sw]);
@@ -336,7 +337,6 @@ int __init mx51_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
336 clk_register_clkdev(clk[mx51_mipi], "mipi_hsp", NULL); 337 clk_register_clkdev(clk[mx51_mipi], "mipi_hsp", NULL);
337 clk_register_clkdev(clk[vpu_gate], NULL, "imx51-vpu.0"); 338 clk_register_clkdev(clk[vpu_gate], NULL, "imx51-vpu.0");
338 clk_register_clkdev(clk[fec_gate], NULL, "imx27-fec.0"); 339 clk_register_clkdev(clk[fec_gate], NULL, "imx27-fec.0");
339 clk_register_clkdev(clk[gpc_dvfs], "gpc_dvfs", NULL);
340 clk_register_clkdev(clk[ipu_gate], "bus", "imx51-ipu"); 340 clk_register_clkdev(clk[ipu_gate], "bus", "imx51-ipu");
341 clk_register_clkdev(clk[ipu_di0_gate], "di0", "imx51-ipu"); 341 clk_register_clkdev(clk[ipu_di0_gate], "di0", "imx51-ipu");
342 clk_register_clkdev(clk[ipu_di1_gate], "di1", "imx51-ipu"); 342 clk_register_clkdev(clk[ipu_di1_gate], "di1", "imx51-ipu");
diff --git a/arch/arm/mach-imx/imx53-dt.c b/arch/arm/mach-imx/imx53-dt.c
index eb04b6248e48..481c3e96ad7f 100644
--- a/arch/arm/mach-imx/imx53-dt.c
+++ b/arch/arm/mach-imx/imx53-dt.c
@@ -147,6 +147,7 @@ DT_MACHINE_START(IMX53_DT, "Freescale i.MX53 (Device Tree Support)")
147 .handle_irq = imx53_handle_irq, 147 .handle_irq = imx53_handle_irq,
148 .timer = &imx53_timer, 148 .timer = &imx53_timer,
149 .init_machine = imx53_dt_init, 149 .init_machine = imx53_dt_init,
150 .init_late = imx53_init_late,
150 .dt_compat = imx53_dt_board_compat, 151 .dt_compat = imx53_dt_board_compat,
151 .restart = mxc_restart, 152 .restart = mxc_restart,
152MACHINE_END 153MACHINE_END
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index b47e98b7d539..d4ca2c470142 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -12,7 +12,9 @@
12 12
13#include <linux/clk.h> 13#include <linux/clk.h>
14#include <linux/clkdev.h> 14#include <linux/clkdev.h>
15#include <linux/cpuidle.h>
15#include <linux/delay.h> 16#include <linux/delay.h>
17#include <linux/export.h>
16#include <linux/init.h> 18#include <linux/init.h>
17#include <linux/io.h> 19#include <linux/io.h>
18#include <linux/irq.h> 20#include <linux/irq.h>
@@ -24,6 +26,7 @@
24#include <linux/pinctrl/machine.h> 26#include <linux/pinctrl/machine.h>
25#include <linux/phy.h> 27#include <linux/phy.h>
26#include <linux/micrel_phy.h> 28#include <linux/micrel_phy.h>
29#include <asm/cpuidle.h>
27#include <asm/smp_twd.h> 30#include <asm/smp_twd.h>
28#include <asm/hardware/cache-l2x0.h> 31#include <asm/hardware/cache-l2x0.h>
29#include <asm/hardware/gic.h> 32#include <asm/hardware/gic.h>
@@ -31,8 +34,10 @@
31#include <asm/mach/time.h> 34#include <asm/mach/time.h>
32#include <asm/system_misc.h> 35#include <asm/system_misc.h>
33#include <mach/common.h> 36#include <mach/common.h>
37#include <mach/cpuidle.h>
34#include <mach/hardware.h> 38#include <mach/hardware.h>
35 39
40
36void imx6q_restart(char mode, const char *cmd) 41void imx6q_restart(char mode, const char *cmd)
37{ 42{
38 struct device_node *np; 43 struct device_node *np;
@@ -129,6 +134,19 @@ static void __init imx6q_init_machine(void)
129 imx6q_pm_init(); 134 imx6q_pm_init();
130} 135}
131 136
137static struct cpuidle_driver imx6q_cpuidle_driver = {
138 .name = "imx6q_cpuidle",
139 .owner = THIS_MODULE,
140 .en_core_tk_irqen = 1,
141 .states[0] = ARM_CPUIDLE_WFI_STATE,
142 .state_count = 1,
143};
144
145static void __init imx6q_init_late(void)
146{
147 imx_cpuidle_init(&imx6q_cpuidle_driver);
148}
149
132static void __init imx6q_map_io(void) 150static void __init imx6q_map_io(void)
133{ 151{
134 imx_lluart_map_io(); 152 imx_lluart_map_io();
@@ -186,6 +204,7 @@ DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad (Device Tree)")
186 .handle_irq = imx6q_handle_irq, 204 .handle_irq = imx6q_handle_irq,
187 .timer = &imx6q_timer, 205 .timer = &imx6q_timer,
188 .init_machine = imx6q_init_machine, 206 .init_machine = imx6q_init_machine,
207 .init_late = imx6q_init_late,
189 .dt_compat = imx6q_dt_compat, 208 .dt_compat = imx6q_dt_compat,
190 .restart = imx6q_restart, 209 .restart = imx6q_restart,
191MACHINE_END 210MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx53_ard.c b/arch/arm/mach-imx/mach-mx53_ard.c
index 05641980dc5e..f1e83d6d2dfc 100644
--- a/arch/arm/mach-imx/mach-mx53_ard.c
+++ b/arch/arm/mach-imx/mach-mx53_ard.c
@@ -266,5 +266,6 @@ MACHINE_START(MX53_ARD, "Freescale MX53 ARD Board")
266 .handle_irq = imx53_handle_irq, 266 .handle_irq = imx53_handle_irq,
267 .timer = &mx53_ard_timer, 267 .timer = &mx53_ard_timer,
268 .init_machine = mx53_ard_board_init, 268 .init_machine = mx53_ard_board_init,
269 .init_late = imx53_init_late,
269 .restart = mxc_restart, 270 .restart = mxc_restart,
270MACHINE_END 271MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx53_evk.c b/arch/arm/mach-imx/mach-mx53_evk.c
index 5a72188b9cdb..8387496ef5ec 100644
--- a/arch/arm/mach-imx/mach-mx53_evk.c
+++ b/arch/arm/mach-imx/mach-mx53_evk.c
@@ -174,5 +174,6 @@ MACHINE_START(MX53_EVK, "Freescale MX53 EVK Board")
174 .handle_irq = imx53_handle_irq, 174 .handle_irq = imx53_handle_irq,
175 .timer = &mx53_evk_timer, 175 .timer = &mx53_evk_timer,
176 .init_machine = mx53_evk_board_init, 176 .init_machine = mx53_evk_board_init,
177 .init_late = imx53_init_late,
177 .restart = mxc_restart, 178 .restart = mxc_restart,
178MACHINE_END 179MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx53_loco.c b/arch/arm/mach-imx/mach-mx53_loco.c
index 37f67cac15a4..e266f3f0f080 100644
--- a/arch/arm/mach-imx/mach-mx53_loco.c
+++ b/arch/arm/mach-imx/mach-mx53_loco.c
@@ -316,5 +316,6 @@ MACHINE_START(MX53_LOCO, "Freescale MX53 LOCO Board")
316 .handle_irq = imx53_handle_irq, 316 .handle_irq = imx53_handle_irq,
317 .timer = &mx53_loco_timer, 317 .timer = &mx53_loco_timer,
318 .init_machine = mx53_loco_board_init, 318 .init_machine = mx53_loco_board_init,
319 .init_late = imx53_init_late,
319 .restart = mxc_restart, 320 .restart = mxc_restart,
320MACHINE_END 321MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx53_smd.c b/arch/arm/mach-imx/mach-mx53_smd.c
index 8e972c5c3e13..4f4c1b93ea66 100644
--- a/arch/arm/mach-imx/mach-mx53_smd.c
+++ b/arch/arm/mach-imx/mach-mx53_smd.c
@@ -163,5 +163,6 @@ MACHINE_START(MX53_SMD, "Freescale MX53 SMD Board")
163 .handle_irq = imx53_handle_irq, 163 .handle_irq = imx53_handle_irq,
164 .timer = &mx53_smd_timer, 164 .timer = &mx53_smd_timer,
165 .init_machine = mx53_smd_board_init, 165 .init_machine = mx53_smd_board_init,
166 .init_late = imx53_init_late,
166 .restart = mxc_restart, 167 .restart = mxc_restart,
167MACHINE_END 168MACHINE_END
diff --git a/arch/arm/mach-imx/mm-imx5.c b/arch/arm/mach-imx/mm-imx5.c
index 1d003053d562..f19d604e1b2a 100644
--- a/arch/arm/mach-imx/mm-imx5.c
+++ b/arch/arm/mach-imx/mm-imx5.c
@@ -16,7 +16,6 @@
16#include <linux/clk.h> 16#include <linux/clk.h>
17#include <linux/pinctrl/machine.h> 17#include <linux/pinctrl/machine.h>
18 18
19#include <asm/system_misc.h>
20#include <asm/mach/map.h> 19#include <asm/mach/map.h>
21 20
22#include <mach/hardware.h> 21#include <mach/hardware.h>
@@ -24,24 +23,6 @@
24#include <mach/devices-common.h> 23#include <mach/devices-common.h>
25#include <mach/iomux-v3.h> 24#include <mach/iomux-v3.h>
26 25
27static struct clk *gpc_dvfs_clk;
28
29static void imx5_idle(void)
30{
31 /* gpc clock is needed for SRPG */
32 if (gpc_dvfs_clk == NULL) {
33 gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs");
34 if (IS_ERR(gpc_dvfs_clk))
35 return;
36 clk_prepare(gpc_dvfs_clk);
37 }
38 clk_enable(gpc_dvfs_clk);
39 mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
40 if (!tzic_enable_wake())
41 cpu_do_idle();
42 clk_disable(gpc_dvfs_clk);
43}
44
45/* 26/*
46 * Define the MX50 memory map. 27 * Define the MX50 memory map.
47 */ 28 */
@@ -105,7 +86,6 @@ void __init imx51_init_early(void)
105 mxc_set_cpu_type(MXC_CPU_MX51); 86 mxc_set_cpu_type(MXC_CPU_MX51);
106 mxc_iomux_v3_init(MX51_IO_ADDRESS(MX51_IOMUXC_BASE_ADDR)); 87 mxc_iomux_v3_init(MX51_IO_ADDRESS(MX51_IOMUXC_BASE_ADDR));
107 mxc_arch_reset_init(MX51_IO_ADDRESS(MX51_WDOG1_BASE_ADDR)); 88 mxc_arch_reset_init(MX51_IO_ADDRESS(MX51_WDOG1_BASE_ADDR));
108 arm_pm_idle = imx5_idle;
109} 89}
110 90
111void __init imx53_init_early(void) 91void __init imx53_init_early(void)
@@ -243,4 +223,10 @@ void __init imx53_soc_init(void)
243void __init imx51_init_late(void) 223void __init imx51_init_late(void)
244{ 224{
245 mx51_neon_fixup(); 225 mx51_neon_fixup();
226 imx51_pm_init();
227}
228
229void __init imx53_init_late(void)
230{
231 imx53_pm_init();
246} 232}
diff --git a/arch/arm/mach-imx/pm-imx5.c b/arch/arm/mach-imx/pm-imx5.c
index e26a9cb05ed8..19621ed1ffa5 100644
--- a/arch/arm/mach-imx/pm-imx5.c
+++ b/arch/arm/mach-imx/pm-imx5.c
@@ -12,19 +12,30 @@
12#include <linux/clk.h> 12#include <linux/clk.h>
13#include <linux/io.h> 13#include <linux/io.h>
14#include <linux/err.h> 14#include <linux/err.h>
15#include <linux/export.h>
15#include <asm/cacheflush.h> 16#include <asm/cacheflush.h>
17#include <asm/system_misc.h>
16#include <asm/tlbflush.h> 18#include <asm/tlbflush.h>
17#include <mach/common.h> 19#include <mach/common.h>
20#include <mach/cpuidle.h>
18#include <mach/hardware.h> 21#include <mach/hardware.h>
19#include "crm-regs-imx5.h" 22#include "crm-regs-imx5.h"
20 23
21static struct clk *gpc_dvfs_clk; 24/*
25 * The WAIT_UNCLOCKED_POWER_OFF state only requires <= 500ns to exit.
26 * This is also the lowest power state possible without affecting
27 * non-cpu parts of the system. For these reasons, imx5 should default
28 * to always using this state for cpu idling. The PM_SUSPEND_STANDBY also
29 * uses this state and needs to take no action when registers remain confgiured
30 * for this state.
31 */
32#define IMX5_DEFAULT_CPU_IDLE_STATE WAIT_UNCLOCKED_POWER_OFF
22 33
23/* 34/*
24 * set cpu low power mode before WFI instruction. This function is called 35 * set cpu low power mode before WFI instruction. This function is called
25 * mx5 because it can be used for mx50, mx51, and mx53. 36 * mx5 because it can be used for mx50, mx51, and mx53.
26 */ 37 */
27void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode) 38static void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
28{ 39{
29 u32 plat_lpc, arm_srpgcr, ccm_clpcr; 40 u32 plat_lpc, arm_srpgcr, ccm_clpcr;
30 u32 empgc0, empgc1; 41 u32 empgc0, empgc1;
@@ -87,11 +98,6 @@ void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
87 } 98 }
88} 99}
89 100
90static int mx5_suspend_prepare(void)
91{
92 return clk_prepare_enable(gpc_dvfs_clk);
93}
94
95static int mx5_suspend_enter(suspend_state_t state) 101static int mx5_suspend_enter(suspend_state_t state)
96{ 102{
97 switch (state) { 103 switch (state) {
@@ -99,7 +105,7 @@ static int mx5_suspend_enter(suspend_state_t state)
99 mx5_cpu_lp_set(STOP_POWER_OFF); 105 mx5_cpu_lp_set(STOP_POWER_OFF);
100 break; 106 break;
101 case PM_SUSPEND_STANDBY: 107 case PM_SUSPEND_STANDBY:
102 mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF); 108 /* DEFAULT_IDLE_STATE already configured */
103 break; 109 break;
104 default: 110 default:
105 return -EINVAL; 111 return -EINVAL;
@@ -114,12 +120,10 @@ static int mx5_suspend_enter(suspend_state_t state)
114 __raw_writel(0, MXC_SRPG_EMPGC1_SRPGCR); 120 __raw_writel(0, MXC_SRPG_EMPGC1_SRPGCR);
115 } 121 }
116 cpu_do_idle(); 122 cpu_do_idle();
117 return 0;
118}
119 123
120static void mx5_suspend_finish(void) 124 /* return registers to default idle state */
121{ 125 mx5_cpu_lp_set(IMX5_DEFAULT_CPU_IDLE_STATE);
122 clk_disable_unprepare(gpc_dvfs_clk); 126 return 0;
123} 127}
124 128
125static int mx5_pm_valid(suspend_state_t state) 129static int mx5_pm_valid(suspend_state_t state)
@@ -129,25 +133,80 @@ static int mx5_pm_valid(suspend_state_t state)
129 133
130static const struct platform_suspend_ops mx5_suspend_ops = { 134static const struct platform_suspend_ops mx5_suspend_ops = {
131 .valid = mx5_pm_valid, 135 .valid = mx5_pm_valid,
132 .prepare = mx5_suspend_prepare,
133 .enter = mx5_suspend_enter, 136 .enter = mx5_suspend_enter,
134 .finish = mx5_suspend_finish,
135}; 137};
136 138
137static int __init mx5_pm_init(void) 139static inline int imx5_cpu_do_idle(void)
140{
141 int ret = tzic_enable_wake();
142
143 if (likely(!ret))
144 cpu_do_idle();
145
146 return ret;
147}
148
149static void imx5_pm_idle(void)
150{
151 imx5_cpu_do_idle();
152}
153
154static int imx5_cpuidle_enter(struct cpuidle_device *dev,
155 struct cpuidle_driver *drv, int idx)
156{
157 int ret;
158
159 ret = imx5_cpu_do_idle();
160 if (ret < 0)
161 return ret;
162
163 return idx;
164}
165
166static struct cpuidle_driver imx5_cpuidle_driver = {
167 .name = "imx5_cpuidle",
168 .owner = THIS_MODULE,
169 .en_core_tk_irqen = 1,
170 .states[0] = {
171 .enter = imx5_cpuidle_enter,
172 .exit_latency = 2,
173 .target_residency = 1,
174 .flags = CPUIDLE_FLAG_TIME_VALID,
175 .name = "IMX5 SRPG",
176 .desc = "CPU state retained,powered off",
177 },
178 .state_count = 1,
179};
180
181static int __init imx5_pm_common_init(void)
138{ 182{
139 if (!cpu_is_mx51() && !cpu_is_mx53()) 183 int ret;
140 return 0; 184 struct clk *gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs");
141 185
142 if (gpc_dvfs_clk == NULL) 186 if (IS_ERR(gpc_dvfs_clk))
143 gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs"); 187 return PTR_ERR(gpc_dvfs_clk);
144 188
145 if (!IS_ERR(gpc_dvfs_clk)) { 189 ret = clk_prepare_enable(gpc_dvfs_clk);
146 if (cpu_is_mx51()) 190 if (ret)
147 suspend_set_ops(&mx5_suspend_ops); 191 return ret;
148 } else
149 return -EPERM;
150 192
193 arm_pm_idle = imx5_pm_idle;
194
195 /* Set the registers to the default cpu idle state. */
196 mx5_cpu_lp_set(IMX5_DEFAULT_CPU_IDLE_STATE);
197
198 imx_cpuidle_init(&imx5_cpuidle_driver);
151 return 0; 199 return 0;
152} 200}
153device_initcall(mx5_pm_init); 201
202void __init imx51_pm_init(void)
203{
204 int ret = imx5_pm_common_init();
205 if (!ret)
206 suspend_set_ops(&mx5_suspend_ops);
207}
208
209void __init imx53_pm_init(void)
210{
211 imx5_pm_common_init();
212}