aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2012-01-03 15:27:56 -0500
committerArnd Bergmann <arnd@arndb.de>2012-01-03 15:27:56 -0500
commit038485ea9b66858c17f82e5393004532825106a7 (patch)
treee411be1686e4ed73c4f74f0388410231d26e5c76 /arch/arm
parent5d3cb0ffdd0c8987dc17a2ef4529b246198ceb72 (diff)
parent8b69791215857e3e885d27b3945759ace820794a (diff)
Merge branch 'imx6/pm' into next/pm
* imx6/pm: ARM: imx6q: resume PL310 only when CACHE_L2X0 defined ARM: imx6q: build pm code only when CONFIG_PM selected ARM: mx5: use generic irq chip pm interface for pm functions on
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/mach-imx/Kconfig1
-rw-r--r--arch/arm/mach-imx/Makefile6
-rw-r--r--arch/arm/mach-imx/head-v7.S15
-rw-r--r--arch/arm/mach-imx/pm-imx6q.c2
-rw-r--r--arch/arm/mach-mx5/mm.c19
-rw-r--r--arch/arm/mach-mx5/system.c3
-rw-r--r--arch/arm/plat-mxc/include/mach/common.h8
-rw-r--r--arch/arm/plat-mxc/include/mach/mxc.h2
-rw-r--r--arch/arm/plat-mxc/tzic.c40
9 files changed, 74 insertions, 22 deletions
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index c44aa974e79c..0929768573ba 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -595,6 +595,7 @@ comment "i.MX6 family:"
595 595
596config SOC_IMX6Q 596config SOC_IMX6Q
597 bool "i.MX6 Quad support" 597 bool "i.MX6 Quad support"
598 select ARM_CPU_SUSPEND if PM
598 select ARM_GIC 599 select ARM_GIC
599 select CACHE_L2X0 600 select CACHE_L2X0
600 select CPU_V7 601 select CPU_V7
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index aba73214c2a8..7a739bb5915e 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -70,4 +70,8 @@ AFLAGS_head-v7.o :=-Wa,-march=armv7-a
70obj-$(CONFIG_SMP) += platsmp.o 70obj-$(CONFIG_SMP) += platsmp.o
71obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o 71obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
72obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o 72obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
73obj-$(CONFIG_SOC_IMX6Q) += clock-imx6q.o mach-imx6q.o pm-imx6q.o 73obj-$(CONFIG_SOC_IMX6Q) += clock-imx6q.o mach-imx6q.o
74
75ifeq ($(CONFIG_PM),y)
76obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o
77endif
diff --git a/arch/arm/mach-imx/head-v7.S b/arch/arm/mach-imx/head-v7.S
index 6229efbc70cb..cec23a857c7e 100644
--- a/arch/arm/mach-imx/head-v7.S
+++ b/arch/arm/mach-imx/head-v7.S
@@ -71,6 +71,7 @@ ENTRY(v7_secondary_startup)
71ENDPROC(v7_secondary_startup) 71ENDPROC(v7_secondary_startup)
72#endif 72#endif
73 73
74#ifdef CONFIG_PM
74/* 75/*
75 * The following code is located into the .data section. This is to 76 * The following code is located into the .data section. This is to
76 * allow phys_l2x0_saved_regs to be accessed with a relative load 77 * allow phys_l2x0_saved_regs to be accessed with a relative load
@@ -79,6 +80,7 @@ ENDPROC(v7_secondary_startup)
79 .data 80 .data
80 .align 81 .align
81 82
83#ifdef CONFIG_CACHE_L2X0
82 .macro pl310_resume 84 .macro pl310_resume
83 ldr r2, phys_l2x0_saved_regs 85 ldr r2, phys_l2x0_saved_regs
84 ldr r0, [r2, #L2X0_R_PHY_BASE] @ get physical base of l2x0 86 ldr r0, [r2, #L2X0_R_PHY_BASE] @ get physical base of l2x0
@@ -88,12 +90,17 @@ ENDPROC(v7_secondary_startup)
88 str r1, [r0, #L2X0_CTRL] @ re-enable L2 90 str r1, [r0, #L2X0_CTRL] @ re-enable L2
89 .endm 91 .endm
90 92
93 .globl phys_l2x0_saved_regs
94phys_l2x0_saved_regs:
95 .long 0
96#else
97 .macro pl310_resume
98 .endm
99#endif
100
91ENTRY(v7_cpu_resume) 101ENTRY(v7_cpu_resume)
92 bl v7_invalidate_l1 102 bl v7_invalidate_l1
93 pl310_resume 103 pl310_resume
94 b cpu_resume 104 b cpu_resume
95ENDPROC(v7_cpu_resume) 105ENDPROC(v7_cpu_resume)
96 106#endif
97 .globl phys_l2x0_saved_regs
98phys_l2x0_saved_regs:
99 .long 0
diff --git a/arch/arm/mach-imx/pm-imx6q.c b/arch/arm/mach-imx/pm-imx6q.c
index f20f191d7cca..f7b0c2b1b905 100644
--- a/arch/arm/mach-imx/pm-imx6q.c
+++ b/arch/arm/mach-imx/pm-imx6q.c
@@ -64,7 +64,9 @@ void __init imx6q_pm_init(void)
64 * address of the data structure used by l2x0 core to save registers, 64 * address of the data structure used by l2x0 core to save registers,
65 * and later restore the necessary ones in imx6q resume entry. 65 * and later restore the necessary ones in imx6q resume entry.
66 */ 66 */
67#ifdef CONFIG_CACHE_L2X0
67 phys_l2x0_saved_regs = __pa(&l2x0_saved_regs); 68 phys_l2x0_saved_regs = __pa(&l2x0_saved_regs);
69#endif
68 70
69 suspend_set_ops(&imx6q_pm_ops); 71 suspend_set_ops(&imx6q_pm_ops);
70} 72}
diff --git a/arch/arm/mach-mx5/mm.c b/arch/arm/mach-mx5/mm.c
index df4a508f240a..bc17dfea3817 100644
--- a/arch/arm/mach-mx5/mm.c
+++ b/arch/arm/mach-mx5/mm.c
@@ -13,6 +13,7 @@
13 13
14#include <linux/mm.h> 14#include <linux/mm.h>
15#include <linux/init.h> 15#include <linux/init.h>
16#include <linux/clk.h>
16 17
17#include <asm/mach/map.h> 18#include <asm/mach/map.h>
18 19
@@ -21,10 +22,26 @@
21#include <mach/devices-common.h> 22#include <mach/devices-common.h>
22#include <mach/iomux-v3.h> 23#include <mach/iomux-v3.h>
23 24
25static struct clk *gpc_dvfs_clk;
26
24static void imx5_idle(void) 27static void imx5_idle(void)
25{ 28{
26 if (!need_resched()) 29 if (!need_resched()) {
30 /* gpc clock is needed for SRPG */
31 if (gpc_dvfs_clk == NULL) {
32 gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs");
33 if (IS_ERR(gpc_dvfs_clk))
34 goto err0;
35 }
36 clk_enable(gpc_dvfs_clk);
27 mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF); 37 mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
38 if (tzic_enable_wake())
39 goto err1;
40 cpu_do_idle();
41err1:
42 clk_disable(gpc_dvfs_clk);
43 }
44err0:
28 local_irq_enable(); 45 local_irq_enable();
29} 46}
30 47
diff --git a/arch/arm/mach-mx5/system.c b/arch/arm/mach-mx5/system.c
index 144ebebc4a61..5eebfaad1226 100644
--- a/arch/arm/mach-mx5/system.c
+++ b/arch/arm/mach-mx5/system.c
@@ -55,9 +55,6 @@ void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
55 stop_mode = 1; 55 stop_mode = 1;
56 } 56 }
57 arm_srpgcr |= MXC_SRPGCR_PCR; 57 arm_srpgcr |= MXC_SRPGCR_PCR;
58
59 if (tzic_enable_wake(1) != 0)
60 return;
61 break; 58 break;
62 case STOP_POWER_ON: 59 case STOP_POWER_ON:
63 ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET; 60 ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET;
diff --git a/arch/arm/plat-mxc/include/mach/common.h b/arch/arm/plat-mxc/include/mach/common.h
index 6698cae942f7..3846c53f5b5d 100644
--- a/arch/arm/plat-mxc/include/mach/common.h
+++ b/arch/arm/plat-mxc/include/mach/common.h
@@ -130,6 +130,12 @@ extern void imx53_evk_common_init(void);
130extern void imx53_qsb_common_init(void); 130extern void imx53_qsb_common_init(void);
131extern void imx53_smd_common_init(void); 131extern void imx53_smd_common_init(void);
132extern int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode); 132extern int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode);
133extern void imx6q_pm_init(void);
134extern void imx6q_clock_map_io(void); 133extern void imx6q_clock_map_io(void);
134
135#ifdef CONFIG_PM
136extern void imx6q_pm_init(void);
137#else
138static inline void imx6q_pm_init(void) {}
139#endif
140
135#endif 141#endif
diff --git a/arch/arm/plat-mxc/include/mach/mxc.h b/arch/arm/plat-mxc/include/mach/mxc.h
index a4d36d601d55..d78298366a91 100644
--- a/arch/arm/plat-mxc/include/mach/mxc.h
+++ b/arch/arm/plat-mxc/include/mach/mxc.h
@@ -168,7 +168,7 @@ struct cpu_op {
168 u32 cpu_rate; 168 u32 cpu_rate;
169}; 169};
170 170
171int tzic_enable_wake(int is_idle); 171int tzic_enable_wake(void);
172 172
173extern struct cpu_op *(*get_cpu_op)(int *op); 173extern struct cpu_op *(*get_cpu_op)(int *op);
174#endif 174#endif
diff --git a/arch/arm/plat-mxc/tzic.c b/arch/arm/plat-mxc/tzic.c
index a3c164c7ba82..98308ec1f321 100644
--- a/arch/arm/plat-mxc/tzic.c
+++ b/arch/arm/plat-mxc/tzic.c
@@ -73,7 +73,28 @@ static int tzic_set_irq_fiq(unsigned int irq, unsigned int type)
73#define tzic_set_irq_fiq NULL 73#define tzic_set_irq_fiq NULL
74#endif 74#endif
75 75
76static unsigned int *wakeup_intr[4]; 76#ifdef CONFIG_PM
77static void tzic_irq_suspend(struct irq_data *d)
78{
79 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
80 int idx = gc->irq_base >> 5;
81
82 __raw_writel(gc->wake_active, tzic_base + TZIC_WAKEUP0(idx));
83}
84
85static void tzic_irq_resume(struct irq_data *d)
86{
87 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
88 int idx = gc->irq_base >> 5;
89
90 __raw_writel(__raw_readl(tzic_base + TZIC_ENSET0(idx)),
91 tzic_base + TZIC_WAKEUP0(idx));
92}
93
94#else
95#define tzic_irq_suspend NULL
96#define tzic_irq_resume NULL
97#endif
77 98
78static struct mxc_extra_irq tzic_extra_irq = { 99static struct mxc_extra_irq tzic_extra_irq = {
79#ifdef CONFIG_FIQ 100#ifdef CONFIG_FIQ
@@ -91,12 +112,13 @@ static __init void tzic_init_gc(unsigned int irq_start)
91 handle_level_irq); 112 handle_level_irq);
92 gc->private = &tzic_extra_irq; 113 gc->private = &tzic_extra_irq;
93 gc->wake_enabled = IRQ_MSK(32); 114 gc->wake_enabled = IRQ_MSK(32);
94 wakeup_intr[idx] = &gc->wake_active;
95 115
96 ct = gc->chip_types; 116 ct = gc->chip_types;
97 ct->chip.irq_mask = irq_gc_mask_disable_reg; 117 ct->chip.irq_mask = irq_gc_mask_disable_reg;
98 ct->chip.irq_unmask = irq_gc_unmask_enable_reg; 118 ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
99 ct->chip.irq_set_wake = irq_gc_set_wake; 119 ct->chip.irq_set_wake = irq_gc_set_wake;
120 ct->chip.irq_suspend = tzic_irq_suspend;
121 ct->chip.irq_resume = tzic_irq_resume;
100 ct->regs.disable = TZIC_ENCLEAR0(idx); 122 ct->regs.disable = TZIC_ENCLEAR0(idx);
101 ct->regs.enable = TZIC_ENSET0(idx); 123 ct->regs.enable = TZIC_ENSET0(idx);
102 124
@@ -167,23 +189,19 @@ void __init tzic_init_irq(void __iomem *irqbase)
167/** 189/**
168 * tzic_enable_wake() - enable wakeup interrupt 190 * tzic_enable_wake() - enable wakeup interrupt
169 * 191 *
170 * @param is_idle 1 if called in idle loop (ENSET0 register);
171 * 0 to be used when called from low power entry
172 * @return 0 if successful; non-zero otherwise 192 * @return 0 if successful; non-zero otherwise
173 */ 193 */
174int tzic_enable_wake(int is_idle) 194int tzic_enable_wake(void)
175{ 195{
176 unsigned int i, v; 196 unsigned int i;
177 197
178 __raw_writel(1, tzic_base + TZIC_DSMINT); 198 __raw_writel(1, tzic_base + TZIC_DSMINT);
179 if (unlikely(__raw_readl(tzic_base + TZIC_DSMINT) == 0)) 199 if (unlikely(__raw_readl(tzic_base + TZIC_DSMINT) == 0))
180 return -EAGAIN; 200 return -EAGAIN;
181 201
182 for (i = 0; i < 4; i++) { 202 for (i = 0; i < 4; i++)
183 v = is_idle ? __raw_readl(tzic_base + TZIC_ENSET0(i)) : 203 __raw_writel(__raw_readl(tzic_base + TZIC_ENSET0(i)),
184 *wakeup_intr[i]; 204 tzic_base + TZIC_WAKEUP0(i));
185 __raw_writel(v, tzic_base + TZIC_WAKEUP0(i));
186 }
187 205
188 return 0; 206 return 0;
189} 207}