diff options
Diffstat (limited to 'arch/arm/mach-tegra/legacy_irq.c')
-rw-r--r-- | arch/arm/mach-tegra/legacy_irq.c | 109 |
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 | |||
32 | static void __iomem *ictlr_reg_base[] = { | 45 | static 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 | ||
52 | static u32 tegra_legacy_wake_mask[4]; | ||
53 | static 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 | |||
132 | int 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 | |||
143 | void 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 | |||
155 | void 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 | |||
166 | void 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 | ||
178 | static u32 cop_ier[NUM_ICTLRS]; | ||
179 | static u32 cpu_ier[NUM_ICTLRS]; | ||
180 | static u32 cpu_iep[NUM_ICTLRS]; | ||
181 | |||
182 | void 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 | |||
198 | void 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 | ||