aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-tegra/legacy_irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-tegra/legacy_irq.c')
-rw-r--r--arch/arm/mach-tegra/legacy_irq.c109
1 files changed, 105 insertions, 4 deletions
diff --git a/arch/arm/mach-tegra/legacy_irq.c b/arch/arm/mach-tegra/legacy_irq.c
index 7cc8601c19ff..38eb719a4f53 100644
--- a/arch/arm/mach-tegra/legacy_irq.c
+++ b/arch/arm/mach-tegra/legacy_irq.c
@@ -18,17 +18,30 @@
18#include <linux/io.h> 18#include <linux/io.h>
19#include <linux/kernel.h> 19#include <linux/kernel.h>
20#include <mach/iomap.h> 20#include <mach/iomap.h>
21#include <mach/irqs.h>
21#include <mach/legacy_irq.h> 22#include <mach/legacy_irq.h>
22 23
23#define ICTLR_CPU_IER 0x20 24#define INT_SYS_NR (INT_GPIO_BASE - INT_PRI_BASE)
24#define ICTLR_CPU_IER_SET 0x24 25#define INT_SYS_SZ (INT_SEC_BASE - INT_PRI_BASE)
25#define ICTLR_CPU_IER_CLR 0x28 26#define PPI_NR ((INT_SYS_NR+INT_SYS_SZ-1)/INT_SYS_SZ)
26#define ICTLR_CPU_IEP_CLASS 0x2C 27
27#define ICTLR_CPU_IEP_VFIQ 0x08 28#define ICTLR_CPU_IEP_VFIQ 0x08
28#define ICTLR_CPU_IEP_FIR 0x14 29#define ICTLR_CPU_IEP_FIR 0x14
29#define ICTLR_CPU_IEP_FIR_SET 0x18 30#define ICTLR_CPU_IEP_FIR_SET 0x18
30#define ICTLR_CPU_IEP_FIR_CLR 0x1c 31#define ICTLR_CPU_IEP_FIR_CLR 0x1c
31 32
33#define ICTLR_CPU_IER 0x20
34#define ICTLR_CPU_IER_SET 0x24
35#define ICTLR_CPU_IER_CLR 0x28
36#define ICTLR_CPU_IEP_CLASS 0x2C
37
38#define ICTLR_COP_IER 0x30
39#define ICTLR_COP_IER_SET 0x34
40#define ICTLR_COP_IER_CLR 0x38
41#define ICTLR_COP_IEP_CLASS 0x3c
42
43#define NUM_ICTLRS 4
44
32static void __iomem *ictlr_reg_base[] = { 45static void __iomem *ictlr_reg_base[] = {
33 IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE), 46 IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE),
34 IO_ADDRESS(TEGRA_SECONDARY_ICTLR_BASE), 47 IO_ADDRESS(TEGRA_SECONDARY_ICTLR_BASE),
@@ -36,6 +49,9 @@ static void __iomem *ictlr_reg_base[] = {
36 IO_ADDRESS(TEGRA_QUATERNARY_ICTLR_BASE), 49 IO_ADDRESS(TEGRA_QUATERNARY_ICTLR_BASE),
37}; 50};
38 51
52static u32 tegra_legacy_wake_mask[4];
53static u32 tegra_legacy_saved_mask[4];
54
39/* When going into deep sleep, the CPU is powered down, taking the GIC with it 55/* When going into deep sleep, the CPU is powered down, taking the GIC with it
40 In order to wake, the wake interrupts need to be enabled in the legacy 56 In order to wake, the wake interrupts need to be enabled in the legacy
41 interrupt controller. */ 57 interrupt controller. */
@@ -112,3 +128,88 @@ unsigned long tegra_legacy_class(int nr)
112 base = ictlr_reg_base[nr]; 128 base = ictlr_reg_base[nr];
113 return readl(base + ICTLR_CPU_IEP_CLASS); 129 return readl(base + ICTLR_CPU_IEP_CLASS);
114} 130}
131
132int tegra_legacy_irq_set_wake(int irq, int enable)
133{
134 irq -= 32;
135 if (enable)
136 tegra_legacy_wake_mask[irq >> 5] |= 1 << (irq & 31);
137 else
138 tegra_legacy_wake_mask[irq >> 5] &= ~(1 << (irq & 31));
139
140 return 0;
141}
142
143void tegra_legacy_irq_set_lp1_wake_mask(void)
144{
145 void __iomem *base;
146 int i;
147
148 for (i = 0; i < NUM_ICTLRS; i++) {
149 base = ictlr_reg_base[i];
150 tegra_legacy_saved_mask[i] = readl(base + ICTLR_CPU_IER);
151 writel(tegra_legacy_wake_mask[i], base + ICTLR_CPU_IER);
152 }
153}
154
155void tegra_legacy_irq_restore_mask(void)
156{
157 void __iomem *base;
158 int i;
159
160 for (i = 0; i < NUM_ICTLRS; i++) {
161 base = ictlr_reg_base[i];
162 writel(tegra_legacy_saved_mask[i], base + ICTLR_CPU_IER);
163 }
164}
165
166void tegra_init_legacy_irq(void)
167{
168 int i;
169
170 for (i = 0; i < NUM_ICTLRS; i++) {
171 void __iomem *ictlr = ictlr_reg_base[i];
172 writel(~0, ictlr + ICTLR_CPU_IER_CLR);
173 writel(0, ictlr + ICTLR_CPU_IEP_CLASS);
174 }
175}
176
177#ifdef CONFIG_PM
178static u32 cop_ier[NUM_ICTLRS];
179static u32 cpu_ier[NUM_ICTLRS];
180static u32 cpu_iep[NUM_ICTLRS];
181
182void tegra_irq_suspend(void)
183{
184 unsigned long flags;
185 int i;
186
187 local_irq_save(flags);
188 for (i = 0; i < NUM_ICTLRS; i++) {
189 void __iomem *ictlr = ictlr_reg_base[i];
190 cpu_ier[i] = readl(ictlr + ICTLR_CPU_IER);
191 cpu_iep[i] = readl(ictlr + ICTLR_CPU_IEP_CLASS);
192 cop_ier[i] = readl(ictlr + ICTLR_COP_IER);
193 writel(~0, ictlr + ICTLR_COP_IER_CLR);
194 }
195 local_irq_restore(flags);
196}
197
198void tegra_irq_resume(void)
199{
200 unsigned long flags;
201 int i;
202
203 local_irq_save(flags);
204 for (i = 0; i < NUM_ICTLRS; i++) {
205 void __iomem *ictlr = ictlr_reg_base[i];
206 writel(cpu_iep[i], ictlr + ICTLR_CPU_IEP_CLASS);
207 writel(~0ul, ictlr + ICTLR_CPU_IER_CLR);
208 writel(cpu_ier[i], ictlr + ICTLR_CPU_IER_SET);
209 writel(0, ictlr + ICTLR_COP_IEP_CLASS);
210 writel(~0ul, ictlr + ICTLR_COP_IER_CLR);
211 writel(cop_ier[i], ictlr + ICTLR_COP_IER_SET);
212 }
213 local_irq_restore(flags);
214}
215#endif