diff options
author | David Woodhouse <David.Woodhouse@intel.com> | 2008-07-25 10:40:14 -0400 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2008-07-25 10:40:14 -0400 |
commit | ff877ea80efa2015b6263766f78ee42c2a1b32f9 (patch) | |
tree | 85205005c611ab774702148558321c6fb92f1ccd /arch/avr32/mach-at32ap/intc.c | |
parent | 30821fee4f0cb3e6d241d9f7ddc37742212e3eb7 (diff) | |
parent | d37e6bf68fc1eb34a4ad21d9ae8890ed37ea80e7 (diff) |
Merge branch 'linux-next' of git://git.infradead.org/~dedekind/ubi-2.6
Diffstat (limited to 'arch/avr32/mach-at32ap/intc.c')
-rw-r--r-- | arch/avr32/mach-at32ap/intc.c | 80 |
1 files changed, 77 insertions, 3 deletions
diff --git a/arch/avr32/mach-at32ap/intc.c b/arch/avr32/mach-at32ap/intc.c index 097cf4e84052..994c4545e2b7 100644 --- a/arch/avr32/mach-at32ap/intc.c +++ b/arch/avr32/mach-at32ap/intc.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2006 Atmel Corporation | 2 | * Copyright (C) 2006, 2008 Atmel Corporation |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
5 | * it under the terms of the GNU General Public License version 2 as | 5 | * it under the terms of the GNU General Public License version 2 as |
@@ -12,14 +12,20 @@ | |||
12 | #include <linux/interrupt.h> | 12 | #include <linux/interrupt.h> |
13 | #include <linux/irq.h> | 13 | #include <linux/irq.h> |
14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
15 | #include <linux/sysdev.h> | ||
15 | 16 | ||
16 | #include <asm/io.h> | 17 | #include <asm/io.h> |
17 | 18 | ||
18 | #include "intc.h" | 19 | #include "intc.h" |
19 | 20 | ||
20 | struct intc { | 21 | struct intc { |
21 | void __iomem *regs; | 22 | void __iomem *regs; |
22 | struct irq_chip chip; | 23 | struct irq_chip chip; |
24 | struct sys_device sysdev; | ||
25 | #ifdef CONFIG_PM | ||
26 | unsigned long suspend_ipr; | ||
27 | unsigned long saved_ipr[64]; | ||
28 | #endif | ||
23 | }; | 29 | }; |
24 | 30 | ||
25 | extern struct platform_device at32_intc0_device; | 31 | extern struct platform_device at32_intc0_device; |
@@ -136,6 +142,74 @@ fail: | |||
136 | panic("Interrupt controller initialization failed!\n"); | 142 | panic("Interrupt controller initialization failed!\n"); |
137 | } | 143 | } |
138 | 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 | |||
191 | static struct sysdev_class intc_class = { | ||
192 | .name = "intc", | ||
193 | .suspend = intc_suspend, | ||
194 | .resume = intc_resume, | ||
195 | }; | ||
196 | |||
197 | static int __init intc_init_sysdev(void) | ||
198 | { | ||
199 | int ret; | ||
200 | |||
201 | ret = sysdev_class_register(&intc_class); | ||
202 | if (ret) | ||
203 | return ret; | ||
204 | |||
205 | intc0.sysdev.id = 0; | ||
206 | intc0.sysdev.cls = &intc_class; | ||
207 | ret = sysdev_register(&intc0.sysdev); | ||
208 | |||
209 | return ret; | ||
210 | } | ||
211 | device_initcall(intc_init_sysdev); | ||
212 | |||
139 | unsigned long intc_get_pending(unsigned int group) | 213 | unsigned long intc_get_pending(unsigned int group) |
140 | { | 214 | { |
141 | return intc_readl(&intc0, INTREQ0 + 4 * group); | 215 | return intc_readl(&intc0, INTREQ0 + 4 * group); |