diff options
Diffstat (limited to 'arch/avr32/mach-at32ap/intc.c')
-rw-r--r-- | arch/avr32/mach-at32ap/intc.c | 54 |
1 files changed, 53 insertions, 1 deletions
diff --git a/arch/avr32/mach-at32ap/intc.c b/arch/avr32/mach-at32ap/intc.c index 644a3fb8c164..994c4545e2b7 100644 --- a/arch/avr32/mach-at32ap/intc.c +++ b/arch/avr32/mach-at32ap/intc.c | |||
@@ -22,6 +22,10 @@ struct intc { | |||
22 | void __iomem *regs; | 22 | void __iomem *regs; |
23 | struct irq_chip chip; | 23 | struct irq_chip chip; |
24 | struct sys_device sysdev; | 24 | struct sys_device sysdev; |
25 | #ifdef CONFIG_PM | ||
26 | unsigned long suspend_ipr; | ||
27 | unsigned long saved_ipr[64]; | ||
28 | #endif | ||
25 | }; | 29 | }; |
26 | 30 | ||
27 | extern struct platform_device at32_intc0_device; | 31 | extern struct platform_device at32_intc0_device; |
@@ -138,8 +142,56 @@ fail: | |||
138 | panic("Interrupt controller initialization failed!\n"); | 142 | panic("Interrupt controller initialization failed!\n"); |
139 | } | 143 | } |
140 | 144 | ||
145 | #ifdef CONFIG_PM | ||
146 | void intc_set_suspend_handler(unsigned long offset) | ||
147 | { | ||
148 | intc0.suspend_ipr = offset; | ||
149 | } | ||
150 | |||
151 | static int intc_suspend(struct sys_device *sdev, pm_message_t state) | ||
152 | { | ||
153 | struct intc *intc = container_of(sdev, struct intc, sysdev); | ||
154 | int i; | ||
155 | |||
156 | if (unlikely(!irqs_disabled())) { | ||
157 | pr_err("intc_suspend: called with interrupts enabled\n"); | ||
158 | return -EINVAL; | ||
159 | } | ||
160 | |||
161 | if (unlikely(!intc->suspend_ipr)) { | ||
162 | pr_err("intc_suspend: suspend_ipr not initialized\n"); | ||
163 | return -EINVAL; | ||
164 | } | ||
165 | |||
166 | for (i = 0; i < 64; i++) { | ||
167 | intc->saved_ipr[i] = intc_readl(intc, INTPR0 + 4 * i); | ||
168 | intc_writel(intc, INTPR0 + 4 * i, intc->suspend_ipr); | ||
169 | } | ||
170 | |||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static int intc_resume(struct sys_device *sdev) | ||
175 | { | ||
176 | struct intc *intc = container_of(sdev, struct intc, sysdev); | ||
177 | int i; | ||
178 | |||
179 | WARN_ON(!irqs_disabled()); | ||
180 | |||
181 | for (i = 0; i < 64; i++) | ||
182 | intc_writel(intc, INTPR0 + 4 * i, intc->saved_ipr[i]); | ||
183 | |||
184 | return 0; | ||
185 | } | ||
186 | #else | ||
187 | #define intc_suspend NULL | ||
188 | #define intc_resume NULL | ||
189 | #endif | ||
190 | |||
141 | static struct sysdev_class intc_class = { | 191 | static struct sysdev_class intc_class = { |
142 | .name = "intc", | 192 | .name = "intc", |
193 | .suspend = intc_suspend, | ||
194 | .resume = intc_resume, | ||
143 | }; | 195 | }; |
144 | 196 | ||
145 | static int __init intc_init_sysdev(void) | 197 | static int __init intc_init_sysdev(void) |