diff options
author | Heiko Stuebner <heiko@sntech.de> | 2012-05-19 12:01:35 -0400 |
---|---|---|
committer | Kukjin Kim <kgene.kim@samsung.com> | 2012-05-19 14:05:04 -0400 |
commit | 0e944e276c7ebcb880d20f6e9255f596c85fc767 (patch) | |
tree | 90aff0c2e5fe44fda194d4a26ed678dc38c48e5c /arch | |
parent | 2de05a57467c43f58802cdeaa547aee73396b6f3 (diff) |
ARM: S3C24XX: add support for second irq set of S3C2416
The S3C2416 has a separate second interrupt register-set to support
additional irqs. This patch adds the necessary constants and registers
the irq handlers for it.
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-s3c24xx/include/mach/irqs.h | 15 | ||||
-rw-r--r-- | arch/arm/mach-s3c24xx/irq-s3c2416.c | 98 | ||||
-rw-r--r-- | arch/arm/mach-s3c24xx/s3c2416.c | 1 | ||||
-rw-r--r-- | arch/arm/plat-samsung/include/plat/s3c2416.h | 3 |
4 files changed, 116 insertions, 1 deletions
diff --git a/arch/arm/mach-s3c24xx/include/mach/irqs.h b/arch/arm/mach-s3c24xx/include/mach/irqs.h index e53b2177319e..b7a9f4d469e8 100644 --- a/arch/arm/mach-s3c24xx/include/mach/irqs.h +++ b/arch/arm/mach-s3c24xx/include/mach/irqs.h | |||
@@ -134,6 +134,17 @@ | |||
134 | #define IRQ_S32416_WDT S3C2410_IRQSUB(27) | 134 | #define IRQ_S32416_WDT S3C2410_IRQSUB(27) |
135 | #define IRQ_S32416_AC97 S3C2410_IRQSUB(28) | 135 | #define IRQ_S32416_AC97 S3C2410_IRQSUB(28) |
136 | 136 | ||
137 | /* second interrupt-register of s3c2416/s3c2450 */ | ||
138 | |||
139 | #define S3C2416_IRQ(x) S3C2410_IRQ((x) + 54 + 29) | ||
140 | #define IRQ_S3C2416_2D S3C2416_IRQ(0) | ||
141 | #define IRQ_S3C2416_IIC1 S3C2416_IRQ(1) | ||
142 | #define IRQ_S3C2416_RESERVED2 S3C2416_IRQ(2) | ||
143 | #define IRQ_S3C2416_RESERVED3 S3C2416_IRQ(3) | ||
144 | #define IRQ_S3C2416_PCM0 S3C2416_IRQ(4) | ||
145 | #define IRQ_S3C2416_PCM1 S3C2416_IRQ(5) | ||
146 | #define IRQ_S3C2416_I2S0 S3C2416_IRQ(6) | ||
147 | #define IRQ_S3C2416_I2S1 S3C2416_IRQ(7) | ||
137 | 148 | ||
138 | /* extra irqs for s3c2440 */ | 149 | /* extra irqs for s3c2440 */ |
139 | 150 | ||
@@ -175,7 +186,9 @@ | |||
175 | #define IRQ_S3C2443_WDT S3C2410_IRQSUB(27) | 186 | #define IRQ_S3C2443_WDT S3C2410_IRQSUB(27) |
176 | #define IRQ_S3C2443_AC97 S3C2410_IRQSUB(28) | 187 | #define IRQ_S3C2443_AC97 S3C2410_IRQSUB(28) |
177 | 188 | ||
178 | #if defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2416) | 189 | #if defined(CONFIG_CPU_S3C2416) |
190 | #define NR_IRQS (IRQ_S3C2416_I2S1 + 1) | ||
191 | #elif defined(CONFIG_CPU_S3C2443) | ||
179 | #define NR_IRQS (IRQ_S3C2443_AC97+1) | 192 | #define NR_IRQS (IRQ_S3C2443_AC97+1) |
180 | #else | 193 | #else |
181 | #define NR_IRQS (IRQ_S3C2440_AC97+1) | 194 | #define NR_IRQS (IRQ_S3C2440_AC97+1) |
diff --git a/arch/arm/mach-s3c24xx/irq-s3c2416.c b/arch/arm/mach-s3c24xx/irq-s3c2416.c index fd49f35e448e..23ec97370f32 100644 --- a/arch/arm/mach-s3c24xx/irq-s3c2416.c +++ b/arch/arm/mach-s3c24xx/irq-s3c2416.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/ioport.h> | 27 | #include <linux/ioport.h> |
28 | #include <linux/device.h> | 28 | #include <linux/device.h> |
29 | #include <linux/io.h> | 29 | #include <linux/io.h> |
30 | #include <linux/syscore_ops.h> | ||
30 | 31 | ||
31 | #include <mach/hardware.h> | 32 | #include <mach/hardware.h> |
32 | #include <asm/irq.h> | 33 | #include <asm/irq.h> |
@@ -192,6 +193,43 @@ static struct irq_chip s3c2416_irq_uart3 = { | |||
192 | .irq_ack = s3c2416_irq_uart3_ack, | 193 | .irq_ack = s3c2416_irq_uart3_ack, |
193 | }; | 194 | }; |
194 | 195 | ||
196 | /* second interrupt register */ | ||
197 | |||
198 | static inline void s3c2416_irq_ack_second(struct irq_data *data) | ||
199 | { | ||
200 | unsigned long bitval = 1UL << (data->irq - IRQ_S3C2416_2D); | ||
201 | |||
202 | __raw_writel(bitval, S3C2416_SRCPND2); | ||
203 | __raw_writel(bitval, S3C2416_INTPND2); | ||
204 | } | ||
205 | |||
206 | static void s3c2416_irq_mask_second(struct irq_data *data) | ||
207 | { | ||
208 | unsigned long bitval = 1UL << (data->irq - IRQ_S3C2416_2D); | ||
209 | unsigned long mask; | ||
210 | |||
211 | mask = __raw_readl(S3C2416_INTMSK2); | ||
212 | mask |= bitval; | ||
213 | __raw_writel(mask, S3C2416_INTMSK2); | ||
214 | } | ||
215 | |||
216 | static void s3c2416_irq_unmask_second(struct irq_data *data) | ||
217 | { | ||
218 | unsigned long bitval = 1UL << (data->irq - IRQ_S3C2416_2D); | ||
219 | unsigned long mask; | ||
220 | |||
221 | mask = __raw_readl(S3C2416_INTMSK2); | ||
222 | mask &= ~bitval; | ||
223 | __raw_writel(mask, S3C2416_INTMSK2); | ||
224 | } | ||
225 | |||
226 | struct irq_chip s3c2416_irq_second = { | ||
227 | .irq_ack = s3c2416_irq_ack_second, | ||
228 | .irq_mask = s3c2416_irq_mask_second, | ||
229 | .irq_unmask = s3c2416_irq_unmask_second, | ||
230 | }; | ||
231 | |||
232 | |||
195 | /* IRQ initialisation code */ | 233 | /* IRQ initialisation code */ |
196 | 234 | ||
197 | static int __init s3c2416_add_sub(unsigned int base, | 235 | static int __init s3c2416_add_sub(unsigned int base, |
@@ -213,6 +251,42 @@ static int __init s3c2416_add_sub(unsigned int base, | |||
213 | return 0; | 251 | return 0; |
214 | } | 252 | } |
215 | 253 | ||
254 | static void __init s3c2416_irq_add_second(void) | ||
255 | { | ||
256 | unsigned long pend; | ||
257 | unsigned long last; | ||
258 | int irqno; | ||
259 | int i; | ||
260 | |||
261 | /* first, clear all interrupts pending... */ | ||
262 | last = 0; | ||
263 | for (i = 0; i < 4; i++) { | ||
264 | pend = __raw_readl(S3C2416_INTPND2); | ||
265 | |||
266 | if (pend == 0 || pend == last) | ||
267 | break; | ||
268 | |||
269 | __raw_writel(pend, S3C2416_SRCPND2); | ||
270 | __raw_writel(pend, S3C2416_INTPND2); | ||
271 | printk(KERN_INFO "irq: clearing pending status %08x\n", | ||
272 | (int)pend); | ||
273 | last = pend; | ||
274 | } | ||
275 | |||
276 | for (irqno = IRQ_S3C2416_2D; irqno <= IRQ_S3C2416_I2S1; irqno++) { | ||
277 | switch (irqno) { | ||
278 | case IRQ_S3C2416_RESERVED2: | ||
279 | case IRQ_S3C2416_RESERVED3: | ||
280 | /* no IRQ here */ | ||
281 | break; | ||
282 | default: | ||
283 | irq_set_chip_and_handler(irqno, &s3c2416_irq_second, | ||
284 | handle_edge_irq); | ||
285 | set_irq_flags(irqno, IRQF_VALID); | ||
286 | } | ||
287 | } | ||
288 | } | ||
289 | |||
216 | static int __init s3c2416_irq_add(struct device *dev, | 290 | static int __init s3c2416_irq_add(struct device *dev, |
217 | struct subsys_interface *sif) | 291 | struct subsys_interface *sif) |
218 | { | 292 | { |
@@ -232,6 +306,8 @@ static int __init s3c2416_irq_add(struct device *dev, | |||
232 | &s3c2416_irq_wdtac97, | 306 | &s3c2416_irq_wdtac97, |
233 | IRQ_S3C2443_WDT, IRQ_S3C2443_AC97); | 307 | IRQ_S3C2443_WDT, IRQ_S3C2443_AC97); |
234 | 308 | ||
309 | s3c2416_irq_add_second(); | ||
310 | |||
235 | return 0; | 311 | return 0; |
236 | } | 312 | } |
237 | 313 | ||
@@ -248,3 +324,25 @@ static int __init s3c2416_irq_init(void) | |||
248 | 324 | ||
249 | arch_initcall(s3c2416_irq_init); | 325 | arch_initcall(s3c2416_irq_init); |
250 | 326 | ||
327 | #ifdef CONFIG_PM | ||
328 | static struct sleep_save irq_save[] = { | ||
329 | SAVE_ITEM(S3C2416_INTMSK2), | ||
330 | }; | ||
331 | |||
332 | int s3c2416_irq_suspend(void) | ||
333 | { | ||
334 | s3c_pm_do_save(irq_save, ARRAY_SIZE(irq_save)); | ||
335 | |||
336 | return 0; | ||
337 | } | ||
338 | |||
339 | void s3c2416_irq_resume(void) | ||
340 | { | ||
341 | s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save)); | ||
342 | } | ||
343 | |||
344 | struct syscore_ops s3c2416_irq_syscore_ops = { | ||
345 | .suspend = s3c2416_irq_suspend, | ||
346 | .resume = s3c2416_irq_resume, | ||
347 | }; | ||
348 | #endif | ||
diff --git a/arch/arm/mach-s3c24xx/s3c2416.c b/arch/arm/mach-s3c24xx/s3c2416.c index 7743fade50df..ed5a95ece9eb 100644 --- a/arch/arm/mach-s3c24xx/s3c2416.c +++ b/arch/arm/mach-s3c24xx/s3c2416.c | |||
@@ -106,6 +106,7 @@ int __init s3c2416_init(void) | |||
106 | register_syscore_ops(&s3c2416_pm_syscore_ops); | 106 | register_syscore_ops(&s3c2416_pm_syscore_ops); |
107 | #endif | 107 | #endif |
108 | register_syscore_ops(&s3c24xx_irq_syscore_ops); | 108 | register_syscore_ops(&s3c24xx_irq_syscore_ops); |
109 | register_syscore_ops(&s3c2416_irq_syscore_ops); | ||
109 | 110 | ||
110 | return device_register(&s3c2416_dev); | 111 | return device_register(&s3c2416_dev); |
111 | } | 112 | } |
diff --git a/arch/arm/plat-samsung/include/plat/s3c2416.h b/arch/arm/plat-samsung/include/plat/s3c2416.h index de2b5bdc5ebd..7178e338e25e 100644 --- a/arch/arm/plat-samsung/include/plat/s3c2416.h +++ b/arch/arm/plat-samsung/include/plat/s3c2416.h | |||
@@ -24,6 +24,9 @@ extern void s3c2416_init_clocks(int xtal); | |||
24 | extern int s3c2416_baseclk_add(void); | 24 | extern int s3c2416_baseclk_add(void); |
25 | 25 | ||
26 | extern void s3c2416_restart(char mode, const char *cmd); | 26 | extern void s3c2416_restart(char mode, const char *cmd); |
27 | |||
28 | extern struct syscore_ops s3c2416_irq_syscore_ops; | ||
29 | |||
27 | #else | 30 | #else |
28 | #define s3c2416_init_clocks NULL | 31 | #define s3c2416_init_clocks NULL |
29 | #define s3c2416_init_uarts NULL | 32 | #define s3c2416_init_uarts NULL |