diff options
author | Olof Johansson <olof@lixom.net> | 2013-02-05 19:31:33 -0500 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2013-02-05 19:31:51 -0500 |
commit | 5060c8881a4b177e27d5bcf351212f2bee125955 (patch) | |
tree | 17020202fd68bcdeba1e10a0a26c7e4e7fa83507 | |
parent | 7dcbeef7926fefa53b0466a27c90238744fb11d8 (diff) | |
parent | f44ddba3635e35317057e976888d4a12dcb0f842 (diff) |
Merge branch 'next/irq-s3c24xx' of git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung into next/cleanup
From Kukjin Kim:
This is redoing the s3c24xx irqs in a generic way by using a declarative
approach.
* 'next/irq-s3c24xx' of git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung:
ARM: S3C24XX: transform s3c2443 subirqs into new structure
ARM: S3C24XX: modify s3c2443 irq init to initialize all irqs
ARM: S3C24XX: move s3c2443 irq code to irq.c
ARM: S3C24XX: transform s3c2416 irqs into new structure
ARM: S3C24XX: modify s3c2416 irq init to initialize all irqs
ARM: S3C24XX: move s3c2416 irq init to common irq code
ARM: S3C24XX: Modify s3c_irq_wake to use the hwirq property
ARM: S3C24XX: Move irq syscore-ops to irq-pm
ARM: S3C24XX: transform irq handling into a declarative form
Signed-off-by: Olof Johansson <olof@lixom.net>
-rw-r--r-- | arch/arm/mach-s3c24xx/Makefile | 4 | ||||
-rw-r--r-- | arch/arm/mach-s3c24xx/common.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-s3c24xx/irq-pm.c | 41 | ||||
-rw-r--r-- | arch/arm/mach-s3c24xx/irq-s3c2416.c | 348 | ||||
-rw-r--r-- | arch/arm/mach-s3c24xx/irq-s3c2443.c | 281 | ||||
-rw-r--r-- | arch/arm/mach-s3c24xx/mach-smdk2416.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-s3c24xx/mach-smdk2443.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-s3c24xx/s3c2410.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-s3c24xx/s3c2412.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-s3c24xx/s3c2416.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-s3c24xx/s3c2440.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-s3c24xx/s3c2442.c | 4 | ||||
-rw-r--r-- | arch/arm/plat-s3c24xx/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm/plat-s3c24xx/irq.c | 1110 | ||||
-rw-r--r-- | arch/arm/plat-samsung/include/plat/pm.h | 6 | ||||
-rw-r--r-- | arch/arm/plat-samsung/include/plat/s3c2416.h | 1 | ||||
-rw-r--r-- | arch/arm/plat-samsung/include/plat/s3c2443.h | 2 |
17 files changed, 687 insertions, 1132 deletions
diff --git a/arch/arm/mach-s3c24xx/Makefile b/arch/arm/mach-s3c24xx/Makefile index 08b87cdb98b7..1d67582da41a 100644 --- a/arch/arm/mach-s3c24xx/Makefile +++ b/arch/arm/mach-s3c24xx/Makefile | |||
@@ -28,7 +28,7 @@ obj-$(CONFIG_S3C2412_DMA) += dma-s3c2412.o | |||
28 | obj-$(CONFIG_S3C2412_PM) += pm-s3c2412.o | 28 | obj-$(CONFIG_S3C2412_PM) += pm-s3c2412.o |
29 | obj-$(CONFIG_S3C2412_PM_SLEEP) += sleep-s3c2412.o | 29 | obj-$(CONFIG_S3C2412_PM_SLEEP) += sleep-s3c2412.o |
30 | 30 | ||
31 | obj-$(CONFIG_CPU_S3C2416) += s3c2416.o irq-s3c2416.o clock-s3c2416.o | 31 | obj-$(CONFIG_CPU_S3C2416) += s3c2416.o clock-s3c2416.o |
32 | obj-$(CONFIG_S3C2416_PM) += pm-s3c2416.o | 32 | obj-$(CONFIG_S3C2416_PM) += pm-s3c2416.o |
33 | 33 | ||
34 | obj-$(CONFIG_CPU_S3C2440) += s3c2440.o irq-s3c2440.o clock-s3c2440.o | 34 | obj-$(CONFIG_CPU_S3C2440) += s3c2440.o irq-s3c2440.o clock-s3c2440.o |
@@ -39,7 +39,7 @@ obj-$(CONFIG_S3C2440_DMA) += dma-s3c2440.o | |||
39 | obj-$(CONFIG_S3C2440_PLL_12000000) += pll-s3c2440-12000000.o | 39 | obj-$(CONFIG_S3C2440_PLL_12000000) += pll-s3c2440-12000000.o |
40 | obj-$(CONFIG_S3C2440_PLL_16934400) += pll-s3c2440-16934400.o | 40 | obj-$(CONFIG_S3C2440_PLL_16934400) += pll-s3c2440-16934400.o |
41 | 41 | ||
42 | obj-$(CONFIG_CPU_S3C2443) += s3c2443.o irq-s3c2443.o clock-s3c2443.o | 42 | obj-$(CONFIG_CPU_S3C2443) += s3c2443.o clock-s3c2443.o |
43 | 43 | ||
44 | # PM | 44 | # PM |
45 | 45 | ||
diff --git a/arch/arm/mach-s3c24xx/common.h b/arch/arm/mach-s3c24xx/common.h index c2f596e7bc2d..ed6276fcaa3b 100644 --- a/arch/arm/mach-s3c24xx/common.h +++ b/arch/arm/mach-s3c24xx/common.h | |||
@@ -15,4 +15,6 @@ | |||
15 | void s3c2410_restart(char mode, const char *cmd); | 15 | void s3c2410_restart(char mode, const char *cmd); |
16 | void s3c244x_restart(char mode, const char *cmd); | 16 | void s3c244x_restart(char mode, const char *cmd); |
17 | 17 | ||
18 | extern struct syscore_ops s3c24xx_irq_syscore_ops; | ||
19 | |||
18 | #endif /* __ARCH_ARM_MACH_S3C24XX_COMMON_H */ | 20 | #endif /* __ARCH_ARM_MACH_S3C24XX_COMMON_H */ |
diff --git a/arch/arm/mach-s3c24xx/irq-pm.c b/arch/arm/mach-s3c24xx/irq-pm.c index 0efb2e2848c8..e1199599873e 100644 --- a/arch/arm/mach-s3c24xx/irq-pm.c +++ b/arch/arm/mach-s3c24xx/irq-pm.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
17 | #include <linux/irq.h> | 17 | #include <linux/irq.h> |
18 | #include <linux/syscore_ops.h> | ||
18 | 19 | ||
19 | #include <plat/cpu.h> | 20 | #include <plat/cpu.h> |
20 | #include <plat/pm.h> | 21 | #include <plat/pm.h> |
@@ -29,18 +30,18 @@ | |||
29 | * set bit to 1 in allow bitfield to enable the wakeup settings on it | 30 | * set bit to 1 in allow bitfield to enable the wakeup settings on it |
30 | */ | 31 | */ |
31 | 32 | ||
32 | unsigned long s3c_irqwake_intallow = 1L << (IRQ_RTC - IRQ_EINT0) | 0xfL; | 33 | unsigned long s3c_irqwake_intallow = 1L << 30 | 0xfL; |
33 | unsigned long s3c_irqwake_eintallow = 0x0000fff0L; | 34 | unsigned long s3c_irqwake_eintallow = 0x0000fff0L; |
34 | 35 | ||
35 | int s3c_irq_wake(struct irq_data *data, unsigned int state) | 36 | int s3c_irq_wake(struct irq_data *data, unsigned int state) |
36 | { | 37 | { |
37 | unsigned long irqbit = 1 << (data->irq - IRQ_EINT0); | 38 | unsigned long irqbit = 1 << data->hwirq; |
38 | 39 | ||
39 | if (!(s3c_irqwake_intallow & irqbit)) | 40 | if (!(s3c_irqwake_intallow & irqbit)) |
40 | return -ENOENT; | 41 | return -ENOENT; |
41 | 42 | ||
42 | printk(KERN_INFO "wake %s for irq %d\n", | 43 | pr_info("wake %s for hwirq %lu\n", |
43 | state ? "enabled" : "disabled", data->irq); | 44 | state ? "enabled" : "disabled", data->hwirq); |
44 | 45 | ||
45 | if (!state) | 46 | if (!state) |
46 | s3c_irqwake_intmask |= irqbit; | 47 | s3c_irqwake_intmask |= irqbit; |
@@ -64,7 +65,7 @@ static unsigned long save_extint[3]; | |||
64 | static unsigned long save_eintflt[4]; | 65 | static unsigned long save_eintflt[4]; |
65 | static unsigned long save_eintmask; | 66 | static unsigned long save_eintmask; |
66 | 67 | ||
67 | int s3c24xx_irq_suspend(void) | 68 | static int s3c24xx_irq_suspend(void) |
68 | { | 69 | { |
69 | unsigned int i; | 70 | unsigned int i; |
70 | 71 | ||
@@ -80,7 +81,7 @@ int s3c24xx_irq_suspend(void) | |||
80 | return 0; | 81 | return 0; |
81 | } | 82 | } |
82 | 83 | ||
83 | void s3c24xx_irq_resume(void) | 84 | static void s3c24xx_irq_resume(void) |
84 | { | 85 | { |
85 | unsigned int i; | 86 | unsigned int i; |
86 | 87 | ||
@@ -93,3 +94,31 @@ void s3c24xx_irq_resume(void) | |||
93 | s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save)); | 94 | s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save)); |
94 | __raw_writel(save_eintmask, S3C24XX_EINTMASK); | 95 | __raw_writel(save_eintmask, S3C24XX_EINTMASK); |
95 | } | 96 | } |
97 | |||
98 | struct syscore_ops s3c24xx_irq_syscore_ops = { | ||
99 | .suspend = s3c24xx_irq_suspend, | ||
100 | .resume = s3c24xx_irq_resume, | ||
101 | }; | ||
102 | |||
103 | #ifdef CONFIG_CPU_S3C2416 | ||
104 | static struct sleep_save s3c2416_irq_save[] = { | ||
105 | SAVE_ITEM(S3C2416_INTMSK2), | ||
106 | }; | ||
107 | |||
108 | static int s3c2416_irq_suspend(void) | ||
109 | { | ||
110 | s3c_pm_do_save(s3c2416_irq_save, ARRAY_SIZE(s3c2416_irq_save)); | ||
111 | |||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static void s3c2416_irq_resume(void) | ||
116 | { | ||
117 | s3c_pm_do_restore(s3c2416_irq_save, ARRAY_SIZE(s3c2416_irq_save)); | ||
118 | } | ||
119 | |||
120 | struct syscore_ops s3c2416_irq_syscore_ops = { | ||
121 | .suspend = s3c2416_irq_suspend, | ||
122 | .resume = s3c2416_irq_resume, | ||
123 | }; | ||
124 | #endif | ||
diff --git a/arch/arm/mach-s3c24xx/irq-s3c2416.c b/arch/arm/mach-s3c24xx/irq-s3c2416.c deleted file mode 100644 index ff141b0af26b..000000000000 --- a/arch/arm/mach-s3c24xx/irq-s3c2416.c +++ /dev/null | |||
@@ -1,348 +0,0 @@ | |||
1 | /* linux/arch/arm/mach-s3c2416/irq.c | ||
2 | * | ||
3 | * Copyright (c) 2009 Yauhen Kharuzhy <jekhor@gmail.com>, | ||
4 | * as part of OpenInkpot project | ||
5 | * Copyright (c) 2009 Promwad Innovation Company | ||
6 | * Yauhen Kharuzhy <yauhen.kharuzhy@promwad.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #include <linux/init.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/ioport.h> | ||
28 | #include <linux/device.h> | ||
29 | #include <linux/io.h> | ||
30 | #include <linux/syscore_ops.h> | ||
31 | |||
32 | #include <mach/hardware.h> | ||
33 | #include <asm/irq.h> | ||
34 | |||
35 | #include <asm/mach/irq.h> | ||
36 | |||
37 | #include <mach/regs-irq.h> | ||
38 | #include <mach/regs-gpio.h> | ||
39 | |||
40 | #include <plat/cpu.h> | ||
41 | #include <plat/pm.h> | ||
42 | #include <plat/irq.h> | ||
43 | |||
44 | #define INTMSK(start, end) ((1 << ((end) + 1 - (start))) - 1) | ||
45 | |||
46 | static inline void s3c2416_irq_demux(unsigned int irq, unsigned int len) | ||
47 | { | ||
48 | unsigned int subsrc, submsk; | ||
49 | unsigned int end; | ||
50 | |||
51 | /* read the current pending interrupts, and the mask | ||
52 | * for what it is available */ | ||
53 | |||
54 | subsrc = __raw_readl(S3C2410_SUBSRCPND); | ||
55 | submsk = __raw_readl(S3C2410_INTSUBMSK); | ||
56 | |||
57 | subsrc &= ~submsk; | ||
58 | subsrc >>= (irq - S3C2410_IRQSUB(0)); | ||
59 | subsrc &= (1 << len)-1; | ||
60 | |||
61 | end = len + irq; | ||
62 | |||
63 | for (; irq < end && subsrc; irq++) { | ||
64 | if (subsrc & 1) | ||
65 | generic_handle_irq(irq); | ||
66 | |||
67 | subsrc >>= 1; | ||
68 | } | ||
69 | } | ||
70 | |||
71 | /* WDT/AC97 sub interrupts */ | ||
72 | |||
73 | static void s3c2416_irq_demux_wdtac97(unsigned int irq, struct irq_desc *desc) | ||
74 | { | ||
75 | s3c2416_irq_demux(IRQ_S3C2443_WDT, 4); | ||
76 | } | ||
77 | |||
78 | #define INTMSK_WDTAC97 (1UL << (IRQ_WDT - IRQ_EINT0)) | ||
79 | #define SUBMSK_WDTAC97 INTMSK(IRQ_S3C2443_WDT, IRQ_S3C2443_AC97) | ||
80 | |||
81 | static void s3c2416_irq_wdtac97_mask(struct irq_data *data) | ||
82 | { | ||
83 | s3c_irqsub_mask(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97); | ||
84 | } | ||
85 | |||
86 | static void s3c2416_irq_wdtac97_unmask(struct irq_data *data) | ||
87 | { | ||
88 | s3c_irqsub_unmask(data->irq, INTMSK_WDTAC97); | ||
89 | } | ||
90 | |||
91 | static void s3c2416_irq_wdtac97_ack(struct irq_data *data) | ||
92 | { | ||
93 | s3c_irqsub_maskack(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97); | ||
94 | } | ||
95 | |||
96 | static struct irq_chip s3c2416_irq_wdtac97 = { | ||
97 | .irq_mask = s3c2416_irq_wdtac97_mask, | ||
98 | .irq_unmask = s3c2416_irq_wdtac97_unmask, | ||
99 | .irq_ack = s3c2416_irq_wdtac97_ack, | ||
100 | }; | ||
101 | |||
102 | /* LCD sub interrupts */ | ||
103 | |||
104 | static void s3c2416_irq_demux_lcd(unsigned int irq, struct irq_desc *desc) | ||
105 | { | ||
106 | s3c2416_irq_demux(IRQ_S3C2443_LCD1, 4); | ||
107 | } | ||
108 | |||
109 | #define INTMSK_LCD (1UL << (IRQ_LCD - IRQ_EINT0)) | ||
110 | #define SUBMSK_LCD INTMSK(IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4) | ||
111 | |||
112 | static void s3c2416_irq_lcd_mask(struct irq_data *data) | ||
113 | { | ||
114 | s3c_irqsub_mask(data->irq, INTMSK_LCD, SUBMSK_LCD); | ||
115 | } | ||
116 | |||
117 | static void s3c2416_irq_lcd_unmask(struct irq_data *data) | ||
118 | { | ||
119 | s3c_irqsub_unmask(data->irq, INTMSK_LCD); | ||
120 | } | ||
121 | |||
122 | static void s3c2416_irq_lcd_ack(struct irq_data *data) | ||
123 | { | ||
124 | s3c_irqsub_maskack(data->irq, INTMSK_LCD, SUBMSK_LCD); | ||
125 | } | ||
126 | |||
127 | static struct irq_chip s3c2416_irq_lcd = { | ||
128 | .irq_mask = s3c2416_irq_lcd_mask, | ||
129 | .irq_unmask = s3c2416_irq_lcd_unmask, | ||
130 | .irq_ack = s3c2416_irq_lcd_ack, | ||
131 | }; | ||
132 | |||
133 | /* DMA sub interrupts */ | ||
134 | |||
135 | static void s3c2416_irq_demux_dma(unsigned int irq, struct irq_desc *desc) | ||
136 | { | ||
137 | s3c2416_irq_demux(IRQ_S3C2443_DMA0, 6); | ||
138 | } | ||
139 | |||
140 | #define INTMSK_DMA (1UL << (IRQ_S3C2443_DMA - IRQ_EINT0)) | ||
141 | #define SUBMSK_DMA INTMSK(IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5) | ||
142 | |||
143 | |||
144 | static void s3c2416_irq_dma_mask(struct irq_data *data) | ||
145 | { | ||
146 | s3c_irqsub_mask(data->irq, INTMSK_DMA, SUBMSK_DMA); | ||
147 | } | ||
148 | |||
149 | static void s3c2416_irq_dma_unmask(struct irq_data *data) | ||
150 | { | ||
151 | s3c_irqsub_unmask(data->irq, INTMSK_DMA); | ||
152 | } | ||
153 | |||
154 | static void s3c2416_irq_dma_ack(struct irq_data *data) | ||
155 | { | ||
156 | s3c_irqsub_maskack(data->irq, INTMSK_DMA, SUBMSK_DMA); | ||
157 | } | ||
158 | |||
159 | static struct irq_chip s3c2416_irq_dma = { | ||
160 | .irq_mask = s3c2416_irq_dma_mask, | ||
161 | .irq_unmask = s3c2416_irq_dma_unmask, | ||
162 | .irq_ack = s3c2416_irq_dma_ack, | ||
163 | }; | ||
164 | |||
165 | /* UART3 sub interrupts */ | ||
166 | |||
167 | static void s3c2416_irq_demux_uart3(unsigned int irq, struct irq_desc *desc) | ||
168 | { | ||
169 | s3c2416_irq_demux(IRQ_S3C2443_RX3, 3); | ||
170 | } | ||
171 | |||
172 | #define INTMSK_UART3 (1UL << (IRQ_S3C2443_UART3 - IRQ_EINT0)) | ||
173 | #define SUBMSK_UART3 (0x7 << (IRQ_S3C2443_RX3 - S3C2410_IRQSUB(0))) | ||
174 | |||
175 | static void s3c2416_irq_uart3_mask(struct irq_data *data) | ||
176 | { | ||
177 | s3c_irqsub_mask(data->irq, INTMSK_UART3, SUBMSK_UART3); | ||
178 | } | ||
179 | |||
180 | static void s3c2416_irq_uart3_unmask(struct irq_data *data) | ||
181 | { | ||
182 | s3c_irqsub_unmask(data->irq, INTMSK_UART3); | ||
183 | } | ||
184 | |||
185 | static void s3c2416_irq_uart3_ack(struct irq_data *data) | ||
186 | { | ||
187 | s3c_irqsub_maskack(data->irq, INTMSK_UART3, SUBMSK_UART3); | ||
188 | } | ||
189 | |||
190 | static struct irq_chip s3c2416_irq_uart3 = { | ||
191 | .irq_mask = s3c2416_irq_uart3_mask, | ||
192 | .irq_unmask = s3c2416_irq_uart3_unmask, | ||
193 | .irq_ack = s3c2416_irq_uart3_ack, | ||
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 | |||
233 | /* IRQ initialisation code */ | ||
234 | |||
235 | static int s3c2416_add_sub(unsigned int base, | ||
236 | void (*demux)(unsigned int, | ||
237 | struct irq_desc *), | ||
238 | struct irq_chip *chip, | ||
239 | unsigned int start, unsigned int end) | ||
240 | { | ||
241 | unsigned int irqno; | ||
242 | |||
243 | irq_set_chip_and_handler(base, &s3c_irq_level_chip, handle_level_irq); | ||
244 | irq_set_chained_handler(base, demux); | ||
245 | |||
246 | for (irqno = start; irqno <= end; irqno++) { | ||
247 | irq_set_chip_and_handler(irqno, chip, handle_level_irq); | ||
248 | set_irq_flags(irqno, IRQF_VALID); | ||
249 | } | ||
250 | |||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | static void 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 | |||
290 | static int s3c2416_irq_add(struct device *dev, | ||
291 | struct subsys_interface *sif) | ||
292 | { | ||
293 | printk(KERN_INFO "S3C2416: IRQ Support\n"); | ||
294 | |||
295 | s3c2416_add_sub(IRQ_LCD, s3c2416_irq_demux_lcd, &s3c2416_irq_lcd, | ||
296 | IRQ_S3C2443_LCD2, IRQ_S3C2443_LCD4); | ||
297 | |||
298 | s3c2416_add_sub(IRQ_S3C2443_DMA, s3c2416_irq_demux_dma, | ||
299 | &s3c2416_irq_dma, IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5); | ||
300 | |||
301 | s3c2416_add_sub(IRQ_S3C2443_UART3, s3c2416_irq_demux_uart3, | ||
302 | &s3c2416_irq_uart3, | ||
303 | IRQ_S3C2443_RX3, IRQ_S3C2443_ERR3); | ||
304 | |||
305 | s3c2416_add_sub(IRQ_WDT, s3c2416_irq_demux_wdtac97, | ||
306 | &s3c2416_irq_wdtac97, | ||
307 | IRQ_S3C2443_WDT, IRQ_S3C2443_AC97); | ||
308 | |||
309 | s3c2416_irq_add_second(); | ||
310 | |||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | static struct subsys_interface s3c2416_irq_interface = { | ||
315 | .name = "s3c2416_irq", | ||
316 | .subsys = &s3c2416_subsys, | ||
317 | .add_dev = s3c2416_irq_add, | ||
318 | }; | ||
319 | |||
320 | static int __init s3c2416_irq_init(void) | ||
321 | { | ||
322 | return subsys_interface_register(&s3c2416_irq_interface); | ||
323 | } | ||
324 | |||
325 | arch_initcall(s3c2416_irq_init); | ||
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/irq-s3c2443.c b/arch/arm/mach-s3c24xx/irq-s3c2443.c deleted file mode 100644 index 5e69109c0928..000000000000 --- a/arch/arm/mach-s3c24xx/irq-s3c2443.c +++ /dev/null | |||
@@ -1,281 +0,0 @@ | |||
1 | /* linux/arch/arm/mach-s3c2443/irq.c | ||
2 | * | ||
3 | * Copyright (c) 2007 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include <linux/init.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/ioport.h> | ||
26 | #include <linux/device.h> | ||
27 | #include <linux/io.h> | ||
28 | |||
29 | #include <mach/hardware.h> | ||
30 | #include <asm/irq.h> | ||
31 | |||
32 | #include <asm/mach/irq.h> | ||
33 | |||
34 | #include <mach/regs-irq.h> | ||
35 | #include <mach/regs-gpio.h> | ||
36 | |||
37 | #include <plat/cpu.h> | ||
38 | #include <plat/pm.h> | ||
39 | #include <plat/irq.h> | ||
40 | |||
41 | #define INTMSK(start, end) ((1 << ((end) + 1 - (start))) - 1) | ||
42 | |||
43 | static inline void s3c2443_irq_demux(unsigned int irq, unsigned int len) | ||
44 | { | ||
45 | unsigned int subsrc, submsk; | ||
46 | unsigned int end; | ||
47 | |||
48 | /* read the current pending interrupts, and the mask | ||
49 | * for what it is available */ | ||
50 | |||
51 | subsrc = __raw_readl(S3C2410_SUBSRCPND); | ||
52 | submsk = __raw_readl(S3C2410_INTSUBMSK); | ||
53 | |||
54 | subsrc &= ~submsk; | ||
55 | subsrc >>= (irq - S3C2410_IRQSUB(0)); | ||
56 | subsrc &= (1 << len)-1; | ||
57 | |||
58 | end = len + irq; | ||
59 | |||
60 | for (; irq < end && subsrc; irq++) { | ||
61 | if (subsrc & 1) | ||
62 | generic_handle_irq(irq); | ||
63 | |||
64 | subsrc >>= 1; | ||
65 | } | ||
66 | } | ||
67 | |||
68 | /* WDT/AC97 sub interrupts */ | ||
69 | |||
70 | static void s3c2443_irq_demux_wdtac97(unsigned int irq, struct irq_desc *desc) | ||
71 | { | ||
72 | s3c2443_irq_demux(IRQ_S3C2443_WDT, 4); | ||
73 | } | ||
74 | |||
75 | #define INTMSK_WDTAC97 (1UL << (IRQ_WDT - IRQ_EINT0)) | ||
76 | #define SUBMSK_WDTAC97 INTMSK(IRQ_S3C2443_WDT, IRQ_S3C2443_AC97) | ||
77 | |||
78 | static void s3c2443_irq_wdtac97_mask(struct irq_data *data) | ||
79 | { | ||
80 | s3c_irqsub_mask(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97); | ||
81 | } | ||
82 | |||
83 | static void s3c2443_irq_wdtac97_unmask(struct irq_data *data) | ||
84 | { | ||
85 | s3c_irqsub_unmask(data->irq, INTMSK_WDTAC97); | ||
86 | } | ||
87 | |||
88 | static void s3c2443_irq_wdtac97_ack(struct irq_data *data) | ||
89 | { | ||
90 | s3c_irqsub_maskack(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97); | ||
91 | } | ||
92 | |||
93 | static struct irq_chip s3c2443_irq_wdtac97 = { | ||
94 | .irq_mask = s3c2443_irq_wdtac97_mask, | ||
95 | .irq_unmask = s3c2443_irq_wdtac97_unmask, | ||
96 | .irq_ack = s3c2443_irq_wdtac97_ack, | ||
97 | }; | ||
98 | |||
99 | /* LCD sub interrupts */ | ||
100 | |||
101 | static void s3c2443_irq_demux_lcd(unsigned int irq, struct irq_desc *desc) | ||
102 | { | ||
103 | s3c2443_irq_demux(IRQ_S3C2443_LCD1, 4); | ||
104 | } | ||
105 | |||
106 | #define INTMSK_LCD (1UL << (IRQ_LCD - IRQ_EINT0)) | ||
107 | #define SUBMSK_LCD INTMSK(IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4) | ||
108 | |||
109 | static void s3c2443_irq_lcd_mask(struct irq_data *data) | ||
110 | { | ||
111 | s3c_irqsub_mask(data->irq, INTMSK_LCD, SUBMSK_LCD); | ||
112 | } | ||
113 | |||
114 | static void s3c2443_irq_lcd_unmask(struct irq_data *data) | ||
115 | { | ||
116 | s3c_irqsub_unmask(data->irq, INTMSK_LCD); | ||
117 | } | ||
118 | |||
119 | static void s3c2443_irq_lcd_ack(struct irq_data *data) | ||
120 | { | ||
121 | s3c_irqsub_maskack(data->irq, INTMSK_LCD, SUBMSK_LCD); | ||
122 | } | ||
123 | |||
124 | static struct irq_chip s3c2443_irq_lcd = { | ||
125 | .irq_mask = s3c2443_irq_lcd_mask, | ||
126 | .irq_unmask = s3c2443_irq_lcd_unmask, | ||
127 | .irq_ack = s3c2443_irq_lcd_ack, | ||
128 | }; | ||
129 | |||
130 | /* DMA sub interrupts */ | ||
131 | |||
132 | static void s3c2443_irq_demux_dma(unsigned int irq, struct irq_desc *desc) | ||
133 | { | ||
134 | s3c2443_irq_demux(IRQ_S3C2443_DMA0, 6); | ||
135 | } | ||
136 | |||
137 | #define INTMSK_DMA (1UL << (IRQ_S3C2443_DMA - IRQ_EINT0)) | ||
138 | #define SUBMSK_DMA INTMSK(IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5) | ||
139 | |||
140 | static void s3c2443_irq_dma_mask(struct irq_data *data) | ||
141 | { | ||
142 | s3c_irqsub_mask(data->irq, INTMSK_DMA, SUBMSK_DMA); | ||
143 | } | ||
144 | |||
145 | static void s3c2443_irq_dma_unmask(struct irq_data *data) | ||
146 | { | ||
147 | s3c_irqsub_unmask(data->irq, INTMSK_DMA); | ||
148 | } | ||
149 | |||
150 | static void s3c2443_irq_dma_ack(struct irq_data *data) | ||
151 | { | ||
152 | s3c_irqsub_maskack(data->irq, INTMSK_DMA, SUBMSK_DMA); | ||
153 | } | ||
154 | |||
155 | static struct irq_chip s3c2443_irq_dma = { | ||
156 | .irq_mask = s3c2443_irq_dma_mask, | ||
157 | .irq_unmask = s3c2443_irq_dma_unmask, | ||
158 | .irq_ack = s3c2443_irq_dma_ack, | ||
159 | }; | ||
160 | |||
161 | /* UART3 sub interrupts */ | ||
162 | |||
163 | static void s3c2443_irq_demux_uart3(unsigned int irq, struct irq_desc *desc) | ||
164 | { | ||
165 | s3c2443_irq_demux(IRQ_S3C2443_RX3, 3); | ||
166 | } | ||
167 | |||
168 | #define INTMSK_UART3 (1UL << (IRQ_S3C2443_UART3 - IRQ_EINT0)) | ||
169 | #define SUBMSK_UART3 (0x7 << (IRQ_S3C2443_RX3 - S3C2410_IRQSUB(0))) | ||
170 | |||
171 | static void s3c2443_irq_uart3_mask(struct irq_data *data) | ||
172 | { | ||
173 | s3c_irqsub_mask(data->irq, INTMSK_UART3, SUBMSK_UART3); | ||
174 | } | ||
175 | |||
176 | static void s3c2443_irq_uart3_unmask(struct irq_data *data) | ||
177 | { | ||
178 | s3c_irqsub_unmask(data->irq, INTMSK_UART3); | ||
179 | } | ||
180 | |||
181 | static void s3c2443_irq_uart3_ack(struct irq_data *data) | ||
182 | { | ||
183 | s3c_irqsub_maskack(data->irq, INTMSK_UART3, SUBMSK_UART3); | ||
184 | } | ||
185 | |||
186 | static struct irq_chip s3c2443_irq_uart3 = { | ||
187 | .irq_mask = s3c2443_irq_uart3_mask, | ||
188 | .irq_unmask = s3c2443_irq_uart3_unmask, | ||
189 | .irq_ack = s3c2443_irq_uart3_ack, | ||
190 | }; | ||
191 | |||
192 | /* CAM sub interrupts */ | ||
193 | |||
194 | static void s3c2443_irq_demux_cam(unsigned int irq, struct irq_desc *desc) | ||
195 | { | ||
196 | s3c2443_irq_demux(IRQ_S3C2440_CAM_C, 4); | ||
197 | } | ||
198 | |||
199 | #define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0)) | ||
200 | #define SUBMSK_CAM INTMSK(IRQ_S3C2440_CAM_C, IRQ_S3C2440_CAM_P) | ||
201 | |||
202 | static void s3c2443_irq_cam_mask(struct irq_data *data) | ||
203 | { | ||
204 | s3c_irqsub_mask(data->irq, INTMSK_CAM, SUBMSK_CAM); | ||
205 | } | ||
206 | |||
207 | static void s3c2443_irq_cam_unmask(struct irq_data *data) | ||
208 | { | ||
209 | s3c_irqsub_unmask(data->irq, INTMSK_CAM); | ||
210 | } | ||
211 | |||
212 | static void s3c2443_irq_cam_ack(struct irq_data *data) | ||
213 | { | ||
214 | s3c_irqsub_maskack(data->irq, INTMSK_CAM, SUBMSK_CAM); | ||
215 | } | ||
216 | |||
217 | static struct irq_chip s3c2443_irq_cam = { | ||
218 | .irq_mask = s3c2443_irq_cam_mask, | ||
219 | .irq_unmask = s3c2443_irq_cam_unmask, | ||
220 | .irq_ack = s3c2443_irq_cam_ack, | ||
221 | }; | ||
222 | |||
223 | /* IRQ initialisation code */ | ||
224 | |||
225 | static int s3c2443_add_sub(unsigned int base, | ||
226 | void (*demux)(unsigned int, | ||
227 | struct irq_desc *), | ||
228 | struct irq_chip *chip, | ||
229 | unsigned int start, unsigned int end) | ||
230 | { | ||
231 | unsigned int irqno; | ||
232 | |||
233 | irq_set_chip_and_handler(base, &s3c_irq_level_chip, handle_level_irq); | ||
234 | irq_set_chained_handler(base, demux); | ||
235 | |||
236 | for (irqno = start; irqno <= end; irqno++) { | ||
237 | irq_set_chip_and_handler(irqno, chip, handle_level_irq); | ||
238 | set_irq_flags(irqno, IRQF_VALID); | ||
239 | } | ||
240 | |||
241 | return 0; | ||
242 | } | ||
243 | |||
244 | static int s3c2443_irq_add(struct device *dev, | ||
245 | struct subsys_interface *sif) | ||
246 | { | ||
247 | printk("S3C2443: IRQ Support\n"); | ||
248 | |||
249 | s3c2443_add_sub(IRQ_CAM, s3c2443_irq_demux_cam, &s3c2443_irq_cam, | ||
250 | IRQ_S3C2440_CAM_C, IRQ_S3C2440_CAM_P); | ||
251 | |||
252 | s3c2443_add_sub(IRQ_LCD, s3c2443_irq_demux_lcd, &s3c2443_irq_lcd, | ||
253 | IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4); | ||
254 | |||
255 | s3c2443_add_sub(IRQ_S3C2443_DMA, s3c2443_irq_demux_dma, | ||
256 | &s3c2443_irq_dma, IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5); | ||
257 | |||
258 | s3c2443_add_sub(IRQ_S3C2443_UART3, s3c2443_irq_demux_uart3, | ||
259 | &s3c2443_irq_uart3, | ||
260 | IRQ_S3C2443_RX3, IRQ_S3C2443_ERR3); | ||
261 | |||
262 | s3c2443_add_sub(IRQ_WDT, s3c2443_irq_demux_wdtac97, | ||
263 | &s3c2443_irq_wdtac97, | ||
264 | IRQ_S3C2443_WDT, IRQ_S3C2443_AC97); | ||
265 | |||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | static struct subsys_interface s3c2443_irq_interface = { | ||
270 | .name = "s3c2443_irq", | ||
271 | .subsys = &s3c2443_subsys, | ||
272 | .add_dev = s3c2443_irq_add, | ||
273 | }; | ||
274 | |||
275 | static int __init s3c2443_irq_init(void) | ||
276 | { | ||
277 | return subsys_interface_register(&s3c2443_irq_interface); | ||
278 | } | ||
279 | |||
280 | arch_initcall(s3c2443_irq_init); | ||
281 | |||
diff --git a/arch/arm/mach-s3c24xx/mach-smdk2416.c b/arch/arm/mach-s3c24xx/mach-smdk2416.c index 72dfec689322..ebb2e61f3d07 100644 --- a/arch/arm/mach-s3c24xx/mach-smdk2416.c +++ b/arch/arm/mach-s3c24xx/mach-smdk2416.c | |||
@@ -250,7 +250,7 @@ MACHINE_START(SMDK2416, "SMDK2416") | |||
250 | /* Maintainer: Yauhen Kharuzhy <jekhor@gmail.com> */ | 250 | /* Maintainer: Yauhen Kharuzhy <jekhor@gmail.com> */ |
251 | .atag_offset = 0x100, | 251 | .atag_offset = 0x100, |
252 | 252 | ||
253 | .init_irq = s3c24xx_init_irq, | 253 | .init_irq = s3c2416_init_irq, |
254 | .map_io = smdk2416_map_io, | 254 | .map_io = smdk2416_map_io, |
255 | .init_machine = smdk2416_machine_init, | 255 | .init_machine = smdk2416_machine_init, |
256 | .init_time = s3c24xx_timer_init, | 256 | .init_time = s3c24xx_timer_init, |
diff --git a/arch/arm/mach-s3c24xx/mach-smdk2443.c b/arch/arm/mach-s3c24xx/mach-smdk2443.c index 406c8137620e..fc65d74d3c73 100644 --- a/arch/arm/mach-s3c24xx/mach-smdk2443.c +++ b/arch/arm/mach-s3c24xx/mach-smdk2443.c | |||
@@ -140,7 +140,7 @@ MACHINE_START(SMDK2443, "SMDK2443") | |||
140 | /* Maintainer: Ben Dooks <ben-linux@fluff.org> */ | 140 | /* Maintainer: Ben Dooks <ben-linux@fluff.org> */ |
141 | .atag_offset = 0x100, | 141 | .atag_offset = 0x100, |
142 | 142 | ||
143 | .init_irq = s3c24xx_init_irq, | 143 | .init_irq = s3c2443_init_irq, |
144 | .map_io = smdk2443_map_io, | 144 | .map_io = smdk2443_map_io, |
145 | .init_machine = smdk2443_machine_init, | 145 | .init_machine = smdk2443_machine_init, |
146 | .init_time = s3c24xx_timer_init, | 146 | .init_time = s3c24xx_timer_init, |
diff --git a/arch/arm/mach-s3c24xx/s3c2410.c b/arch/arm/mach-s3c24xx/s3c2410.c index a3c5cb086ee2..9ebef95da721 100644 --- a/arch/arm/mach-s3c24xx/s3c2410.c +++ b/arch/arm/mach-s3c24xx/s3c2410.c | |||
@@ -49,6 +49,8 @@ | |||
49 | #include <plat/gpio-cfg.h> | 49 | #include <plat/gpio-cfg.h> |
50 | #include <plat/gpio-cfg-helpers.h> | 50 | #include <plat/gpio-cfg-helpers.h> |
51 | 51 | ||
52 | #include "common.h" | ||
53 | |||
52 | /* Initial IO mappings */ | 54 | /* Initial IO mappings */ |
53 | 55 | ||
54 | static struct map_desc s3c2410_iodesc[] __initdata = { | 56 | static struct map_desc s3c2410_iodesc[] __initdata = { |
@@ -182,8 +184,8 @@ int __init s3c2410_init(void) | |||
182 | 184 | ||
183 | #ifdef CONFIG_PM | 185 | #ifdef CONFIG_PM |
184 | register_syscore_ops(&s3c2410_pm_syscore_ops); | 186 | register_syscore_ops(&s3c2410_pm_syscore_ops); |
185 | #endif | ||
186 | register_syscore_ops(&s3c24xx_irq_syscore_ops); | 187 | register_syscore_ops(&s3c24xx_irq_syscore_ops); |
188 | #endif | ||
187 | 189 | ||
188 | return device_register(&s3c2410_dev); | 190 | return device_register(&s3c2410_dev); |
189 | } | 191 | } |
diff --git a/arch/arm/mach-s3c24xx/s3c2412.c b/arch/arm/mach-s3c24xx/s3c2412.c index c511a225f07a..ec0b31818c51 100644 --- a/arch/arm/mach-s3c24xx/s3c2412.c +++ b/arch/arm/mach-s3c24xx/s3c2412.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <plat/regs-spi.h> | 47 | #include <plat/regs-spi.h> |
48 | #include <plat/s3c2412.h> | 48 | #include <plat/s3c2412.h> |
49 | 49 | ||
50 | #include "common.h" | ||
50 | #include "regs-dsc.h" | 51 | #include "regs-dsc.h" |
51 | 52 | ||
52 | #define S3C2412_SWRST (S3C24XX_VA_CLKPWR + 0x30) | 53 | #define S3C2412_SWRST (S3C24XX_VA_CLKPWR + 0x30) |
@@ -245,8 +246,8 @@ int __init s3c2412_init(void) | |||
245 | 246 | ||
246 | #ifdef CONFIG_PM | 247 | #ifdef CONFIG_PM |
247 | register_syscore_ops(&s3c2412_pm_syscore_ops); | 248 | register_syscore_ops(&s3c2412_pm_syscore_ops); |
248 | #endif | ||
249 | register_syscore_ops(&s3c24xx_irq_syscore_ops); | 249 | register_syscore_ops(&s3c24xx_irq_syscore_ops); |
250 | #endif | ||
250 | 251 | ||
251 | return device_register(&s3c2412_dev); | 252 | return device_register(&s3c2412_dev); |
252 | } | 253 | } |
diff --git a/arch/arm/mach-s3c24xx/s3c2416.c b/arch/arm/mach-s3c24xx/s3c2416.c index 77ee0b732237..e30476db0295 100644 --- a/arch/arm/mach-s3c24xx/s3c2416.c +++ b/arch/arm/mach-s3c24xx/s3c2416.c | |||
@@ -63,6 +63,8 @@ | |||
63 | #include <plat/rtc-core.h> | 63 | #include <plat/rtc-core.h> |
64 | #include <plat/spi-core.h> | 64 | #include <plat/spi-core.h> |
65 | 65 | ||
66 | #include "common.h" | ||
67 | |||
66 | static struct map_desc s3c2416_iodesc[] __initdata = { | 68 | static struct map_desc s3c2416_iodesc[] __initdata = { |
67 | IODESC_ENT(WATCHDOG), | 69 | IODESC_ENT(WATCHDOG), |
68 | IODESC_ENT(CLKPWR), | 70 | IODESC_ENT(CLKPWR), |
@@ -105,9 +107,9 @@ int __init s3c2416_init(void) | |||
105 | 107 | ||
106 | #ifdef CONFIG_PM | 108 | #ifdef CONFIG_PM |
107 | register_syscore_ops(&s3c2416_pm_syscore_ops); | 109 | register_syscore_ops(&s3c2416_pm_syscore_ops); |
108 | #endif | ||
109 | register_syscore_ops(&s3c24xx_irq_syscore_ops); | 110 | register_syscore_ops(&s3c24xx_irq_syscore_ops); |
110 | register_syscore_ops(&s3c2416_irq_syscore_ops); | 111 | register_syscore_ops(&s3c2416_irq_syscore_ops); |
112 | #endif | ||
111 | 113 | ||
112 | return device_register(&s3c2416_dev); | 114 | return device_register(&s3c2416_dev); |
113 | } | 115 | } |
diff --git a/arch/arm/mach-s3c24xx/s3c2440.c b/arch/arm/mach-s3c24xx/s3c2440.c index 2b3dddb49af7..559e394e8989 100644 --- a/arch/arm/mach-s3c24xx/s3c2440.c +++ b/arch/arm/mach-s3c24xx/s3c2440.c | |||
@@ -40,6 +40,8 @@ | |||
40 | #include <plat/gpio-cfg.h> | 40 | #include <plat/gpio-cfg.h> |
41 | #include <plat/gpio-cfg-helpers.h> | 41 | #include <plat/gpio-cfg-helpers.h> |
42 | 42 | ||
43 | #include "common.h" | ||
44 | |||
43 | static struct device s3c2440_dev = { | 45 | static struct device s3c2440_dev = { |
44 | .bus = &s3c2440_subsys, | 46 | .bus = &s3c2440_subsys, |
45 | }; | 47 | }; |
@@ -57,9 +59,9 @@ int __init s3c2440_init(void) | |||
57 | 59 | ||
58 | #ifdef CONFIG_PM | 60 | #ifdef CONFIG_PM |
59 | register_syscore_ops(&s3c2410_pm_syscore_ops); | 61 | register_syscore_ops(&s3c2410_pm_syscore_ops); |
62 | register_syscore_ops(&s3c24xx_irq_syscore_ops); | ||
60 | #endif | 63 | #endif |
61 | register_syscore_ops(&s3c244x_pm_syscore_ops); | 64 | register_syscore_ops(&s3c244x_pm_syscore_ops); |
62 | register_syscore_ops(&s3c24xx_irq_syscore_ops); | ||
63 | 65 | ||
64 | /* register our system device for everything else */ | 66 | /* register our system device for everything else */ |
65 | 67 | ||
diff --git a/arch/arm/mach-s3c24xx/s3c2442.c b/arch/arm/mach-s3c24xx/s3c2442.c index 22cb7c94a8c8..f732826c2359 100644 --- a/arch/arm/mach-s3c24xx/s3c2442.c +++ b/arch/arm/mach-s3c24xx/s3c2442.c | |||
@@ -51,6 +51,8 @@ | |||
51 | #include <plat/gpio-cfg.h> | 51 | #include <plat/gpio-cfg.h> |
52 | #include <plat/gpio-cfg-helpers.h> | 52 | #include <plat/gpio-cfg-helpers.h> |
53 | 53 | ||
54 | #include "common.h" | ||
55 | |||
54 | /* S3C2442 extended clock support */ | 56 | /* S3C2442 extended clock support */ |
55 | 57 | ||
56 | static unsigned long s3c2442_camif_upll_round(struct clk *clk, | 58 | static unsigned long s3c2442_camif_upll_round(struct clk *clk, |
@@ -172,9 +174,9 @@ int __init s3c2442_init(void) | |||
172 | 174 | ||
173 | #ifdef CONFIG_PM | 175 | #ifdef CONFIG_PM |
174 | register_syscore_ops(&s3c2410_pm_syscore_ops); | 176 | register_syscore_ops(&s3c2410_pm_syscore_ops); |
177 | register_syscore_ops(&s3c24xx_irq_syscore_ops); | ||
175 | #endif | 178 | #endif |
176 | register_syscore_ops(&s3c244x_pm_syscore_ops); | 179 | register_syscore_ops(&s3c244x_pm_syscore_ops); |
177 | register_syscore_ops(&s3c24xx_irq_syscore_ops); | ||
178 | 180 | ||
179 | return device_register(&s3c2442_dev); | 181 | return device_register(&s3c2442_dev); |
180 | } | 182 | } |
diff --git a/arch/arm/plat-s3c24xx/Kconfig b/arch/arm/plat-s3c24xx/Kconfig index eef3b6a2f8a8..3bb5c8fd34a1 100644 --- a/arch/arm/plat-s3c24xx/Kconfig +++ b/arch/arm/plat-s3c24xx/Kconfig | |||
@@ -9,6 +9,7 @@ config PLAT_S3C24XX | |||
9 | select ARCH_REQUIRE_GPIOLIB | 9 | select ARCH_REQUIRE_GPIOLIB |
10 | select NO_IOPORT | 10 | select NO_IOPORT |
11 | select S3C_DEV_NAND | 11 | select S3C_DEV_NAND |
12 | select IRQ_DOMAIN | ||
12 | help | 13 | help |
13 | Base platform code for any Samsung S3C24XX device | 14 | Base platform code for any Samsung S3C24XX device |
14 | 15 | ||
diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c index fe57bbbf166b..cb9f5e011e73 100644 --- a/arch/arm/plat-s3c24xx/irq.c +++ b/arch/arm/plat-s3c24xx/irq.c | |||
@@ -1,7 +1,9 @@ | |||
1 | /* linux/arch/arm/plat-s3c24xx/irq.c | 1 | /* |
2 | * S3C24XX IRQ handling | ||
2 | * | 3 | * |
3 | * Copyright (c) 2003-2004 Simtec Electronics | 4 | * Copyright (c) 2003-2004 Simtec Electronics |
4 | * Ben Dooks <ben@simtec.co.uk> | 5 | * Ben Dooks <ben@simtec.co.uk> |
6 | * Copyright (c) 2012 Heiko Stuebner <heiko@sntech.de> | ||
5 | * | 7 | * |
6 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
@@ -12,175 +14,123 @@ | |||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | * GNU General Public License for more details. | 16 | * GNU General Public License for more details. |
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | 17 | */ |
20 | 18 | ||
21 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/slab.h> | ||
22 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/io.h> | ||
23 | #include <linux/err.h> | ||
23 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
24 | #include <linux/ioport.h> | 25 | #include <linux/ioport.h> |
25 | #include <linux/device.h> | 26 | #include <linux/device.h> |
26 | #include <linux/syscore_ops.h> | 27 | #include <linux/irqdomain.h> |
27 | 28 | ||
28 | #include <asm/irq.h> | ||
29 | #include <asm/mach/irq.h> | 29 | #include <asm/mach/irq.h> |
30 | 30 | ||
31 | #include <plat/regs-irqtype.h> | 31 | #include <mach/regs-irq.h> |
32 | #include <mach/regs-gpio.h> | ||
32 | 33 | ||
33 | #include <plat/cpu.h> | 34 | #include <plat/cpu.h> |
35 | #include <plat/regs-irqtype.h> | ||
34 | #include <plat/pm.h> | 36 | #include <plat/pm.h> |
35 | #include <plat/irq.h> | 37 | #include <plat/irq.h> |
36 | 38 | ||
37 | static void | 39 | #define S3C_IRQTYPE_NONE 0 |
38 | s3c_irq_mask(struct irq_data *data) | 40 | #define S3C_IRQTYPE_EINT 1 |
39 | { | 41 | #define S3C_IRQTYPE_EDGE 2 |
40 | unsigned int irqno = data->irq - IRQ_EINT0; | 42 | #define S3C_IRQTYPE_LEVEL 3 |
41 | unsigned long mask; | ||
42 | |||
43 | mask = __raw_readl(S3C2410_INTMSK); | ||
44 | mask |= 1UL << irqno; | ||
45 | __raw_writel(mask, S3C2410_INTMSK); | ||
46 | } | ||
47 | |||
48 | static inline void | ||
49 | s3c_irq_ack(struct irq_data *data) | ||
50 | { | ||
51 | unsigned long bitval = 1UL << (data->irq - IRQ_EINT0); | ||
52 | |||
53 | __raw_writel(bitval, S3C2410_SRCPND); | ||
54 | __raw_writel(bitval, S3C2410_INTPND); | ||
55 | } | ||
56 | |||
57 | static inline void | ||
58 | s3c_irq_maskack(struct irq_data *data) | ||
59 | { | ||
60 | unsigned long bitval = 1UL << (data->irq - IRQ_EINT0); | ||
61 | unsigned long mask; | ||
62 | |||
63 | mask = __raw_readl(S3C2410_INTMSK); | ||
64 | __raw_writel(mask|bitval, S3C2410_INTMSK); | ||
65 | |||
66 | __raw_writel(bitval, S3C2410_SRCPND); | ||
67 | __raw_writel(bitval, S3C2410_INTPND); | ||
68 | } | ||
69 | |||
70 | |||
71 | static void | ||
72 | s3c_irq_unmask(struct irq_data *data) | ||
73 | { | ||
74 | unsigned int irqno = data->irq; | ||
75 | unsigned long mask; | ||
76 | |||
77 | if (irqno != IRQ_TIMER4 && irqno != IRQ_EINT8t23) | ||
78 | irqdbf2("s3c_irq_unmask %d\n", irqno); | ||
79 | 43 | ||
80 | irqno -= IRQ_EINT0; | 44 | struct s3c_irq_data { |
81 | 45 | unsigned int type; | |
82 | mask = __raw_readl(S3C2410_INTMSK); | 46 | unsigned long parent_irq; |
83 | mask &= ~(1UL << irqno); | ||
84 | __raw_writel(mask, S3C2410_INTMSK); | ||
85 | } | ||
86 | 47 | ||
87 | struct irq_chip s3c_irq_level_chip = { | 48 | /* data gets filled during init */ |
88 | .name = "s3c-level", | 49 | struct s3c_irq_intc *intc; |
89 | .irq_ack = s3c_irq_maskack, | 50 | unsigned long sub_bits; |
90 | .irq_mask = s3c_irq_mask, | 51 | struct s3c_irq_intc *sub_intc; |
91 | .irq_unmask = s3c_irq_unmask, | ||
92 | .irq_set_wake = s3c_irq_wake | ||
93 | }; | 52 | }; |
94 | 53 | ||
95 | struct irq_chip s3c_irq_chip = { | 54 | /* |
96 | .name = "s3c", | 55 | * Sructure holding the controller data |
97 | .irq_ack = s3c_irq_ack, | 56 | * @reg_pending register holding pending irqs |
98 | .irq_mask = s3c_irq_mask, | 57 | * @reg_intpnd special register intpnd in main intc |
99 | .irq_unmask = s3c_irq_unmask, | 58 | * @reg_mask mask register |
100 | .irq_set_wake = s3c_irq_wake | 59 | * @domain irq_domain of the controller |
60 | * @parent parent controller for ext and sub irqs | ||
61 | * @irqs irq-data, always s3c_irq_data[32] | ||
62 | */ | ||
63 | struct s3c_irq_intc { | ||
64 | void __iomem *reg_pending; | ||
65 | void __iomem *reg_intpnd; | ||
66 | void __iomem *reg_mask; | ||
67 | struct irq_domain *domain; | ||
68 | struct s3c_irq_intc *parent; | ||
69 | struct s3c_irq_data *irqs; | ||
101 | }; | 70 | }; |
102 | 71 | ||
103 | static void | 72 | static void s3c_irq_mask(struct irq_data *data) |
104 | s3c_irqext_mask(struct irq_data *data) | ||
105 | { | 73 | { |
106 | unsigned int irqno = data->irq - EXTINT_OFF; | 74 | struct s3c_irq_intc *intc = data->domain->host_data; |
75 | struct s3c_irq_intc *parent_intc = intc->parent; | ||
76 | struct s3c_irq_data *irq_data = &intc->irqs[data->hwirq]; | ||
77 | struct s3c_irq_data *parent_data; | ||
107 | unsigned long mask; | 78 | unsigned long mask; |
79 | unsigned int irqno; | ||
80 | |||
81 | mask = __raw_readl(intc->reg_mask); | ||
82 | mask |= (1UL << data->hwirq); | ||
83 | __raw_writel(mask, intc->reg_mask); | ||
84 | |||
85 | if (parent_intc && irq_data->parent_irq) { | ||
86 | parent_data = &parent_intc->irqs[irq_data->parent_irq]; | ||
108 | 87 | ||
109 | mask = __raw_readl(S3C24XX_EINTMASK); | 88 | /* check to see if we need to mask the parent IRQ */ |
110 | mask |= ( 1UL << irqno); | 89 | if ((mask & parent_data->sub_bits) == parent_data->sub_bits) { |
111 | __raw_writel(mask, S3C24XX_EINTMASK); | 90 | irqno = irq_find_mapping(parent_intc->domain, |
91 | irq_data->parent_irq); | ||
92 | s3c_irq_mask(irq_get_irq_data(irqno)); | ||
93 | } | ||
94 | } | ||
112 | } | 95 | } |
113 | 96 | ||
114 | static void | 97 | static void s3c_irq_unmask(struct irq_data *data) |
115 | s3c_irqext_ack(struct irq_data *data) | ||
116 | { | 98 | { |
117 | unsigned long req; | 99 | struct s3c_irq_intc *intc = data->domain->host_data; |
118 | unsigned long bit; | 100 | struct s3c_irq_intc *parent_intc = intc->parent; |
101 | struct s3c_irq_data *irq_data = &intc->irqs[data->hwirq]; | ||
119 | unsigned long mask; | 102 | unsigned long mask; |
103 | unsigned int irqno; | ||
120 | 104 | ||
121 | bit = 1UL << (data->irq - EXTINT_OFF); | 105 | mask = __raw_readl(intc->reg_mask); |
122 | 106 | mask &= ~(1UL << data->hwirq); | |
123 | mask = __raw_readl(S3C24XX_EINTMASK); | 107 | __raw_writel(mask, intc->reg_mask); |
124 | |||
125 | __raw_writel(bit, S3C24XX_EINTPEND); | ||
126 | |||
127 | req = __raw_readl(S3C24XX_EINTPEND); | ||
128 | req &= ~mask; | ||
129 | 108 | ||
130 | /* not sure if we should be acking the parent irq... */ | 109 | if (parent_intc && irq_data->parent_irq) { |
131 | 110 | irqno = irq_find_mapping(parent_intc->domain, | |
132 | if (data->irq <= IRQ_EINT7) { | 111 | irq_data->parent_irq); |
133 | if ((req & 0xf0) == 0) | 112 | s3c_irq_unmask(irq_get_irq_data(irqno)); |
134 | s3c_irq_ack(irq_get_irq_data(IRQ_EINT4t7)); | ||
135 | } else { | ||
136 | if ((req >> 8) == 0) | ||
137 | s3c_irq_ack(irq_get_irq_data(IRQ_EINT8t23)); | ||
138 | } | 113 | } |
139 | } | 114 | } |
140 | 115 | ||
141 | static void | 116 | static inline void s3c_irq_ack(struct irq_data *data) |
142 | s3c_irqext_unmask(struct irq_data *data) | ||
143 | { | 117 | { |
144 | unsigned int irqno = data->irq - EXTINT_OFF; | 118 | struct s3c_irq_intc *intc = data->domain->host_data; |
145 | unsigned long mask; | 119 | unsigned long bitval = 1UL << data->hwirq; |
146 | 120 | ||
147 | mask = __raw_readl(S3C24XX_EINTMASK); | 121 | __raw_writel(bitval, intc->reg_pending); |
148 | mask &= ~(1UL << irqno); | 122 | if (intc->reg_intpnd) |
149 | __raw_writel(mask, S3C24XX_EINTMASK); | 123 | __raw_writel(bitval, intc->reg_intpnd); |
150 | } | 124 | } |
151 | 125 | ||
152 | int | 126 | static int s3c_irqext_type_set(void __iomem *gpcon_reg, |
153 | s3c_irqext_type(struct irq_data *data, unsigned int type) | 127 | void __iomem *extint_reg, |
128 | unsigned long gpcon_offset, | ||
129 | unsigned long extint_offset, | ||
130 | unsigned int type) | ||
154 | { | 131 | { |
155 | void __iomem *extint_reg; | ||
156 | void __iomem *gpcon_reg; | ||
157 | unsigned long gpcon_offset, extint_offset; | ||
158 | unsigned long newvalue = 0, value; | 132 | unsigned long newvalue = 0, value; |
159 | 133 | ||
160 | if ((data->irq >= IRQ_EINT0) && (data->irq <= IRQ_EINT3)) { | ||
161 | gpcon_reg = S3C2410_GPFCON; | ||
162 | extint_reg = S3C24XX_EXTINT0; | ||
163 | gpcon_offset = (data->irq - IRQ_EINT0) * 2; | ||
164 | extint_offset = (data->irq - IRQ_EINT0) * 4; | ||
165 | } else if ((data->irq >= IRQ_EINT4) && (data->irq <= IRQ_EINT7)) { | ||
166 | gpcon_reg = S3C2410_GPFCON; | ||
167 | extint_reg = S3C24XX_EXTINT0; | ||
168 | gpcon_offset = (data->irq - (EXTINT_OFF)) * 2; | ||
169 | extint_offset = (data->irq - (EXTINT_OFF)) * 4; | ||
170 | } else if ((data->irq >= IRQ_EINT8) && (data->irq <= IRQ_EINT15)) { | ||
171 | gpcon_reg = S3C2410_GPGCON; | ||
172 | extint_reg = S3C24XX_EXTINT1; | ||
173 | gpcon_offset = (data->irq - IRQ_EINT8) * 2; | ||
174 | extint_offset = (data->irq - IRQ_EINT8) * 4; | ||
175 | } else if ((data->irq >= IRQ_EINT16) && (data->irq <= IRQ_EINT23)) { | ||
176 | gpcon_reg = S3C2410_GPGCON; | ||
177 | extint_reg = S3C24XX_EXTINT2; | ||
178 | gpcon_offset = (data->irq - IRQ_EINT8) * 2; | ||
179 | extint_offset = (data->irq - IRQ_EINT16) * 4; | ||
180 | } else { | ||
181 | return -1; | ||
182 | } | ||
183 | |||
184 | /* Set the GPIO to external interrupt mode */ | 134 | /* Set the GPIO to external interrupt mode */ |
185 | value = __raw_readl(gpcon_reg); | 135 | value = __raw_readl(gpcon_reg); |
186 | value = (value & ~(3 << gpcon_offset)) | (0x02 << gpcon_offset); | 136 | value = (value & ~(3 << gpcon_offset)) | (0x02 << gpcon_offset); |
@@ -190,7 +140,7 @@ s3c_irqext_type(struct irq_data *data, unsigned int type) | |||
190 | switch (type) | 140 | switch (type) |
191 | { | 141 | { |
192 | case IRQ_TYPE_NONE: | 142 | case IRQ_TYPE_NONE: |
193 | printk(KERN_WARNING "No edge setting!\n"); | 143 | pr_warn("No edge setting!\n"); |
194 | break; | 144 | break; |
195 | 145 | ||
196 | case IRQ_TYPE_EDGE_RISING: | 146 | case IRQ_TYPE_EDGE_RISING: |
@@ -214,8 +164,8 @@ s3c_irqext_type(struct irq_data *data, unsigned int type) | |||
214 | break; | 164 | break; |
215 | 165 | ||
216 | default: | 166 | default: |
217 | printk(KERN_ERR "No such irq type %d", type); | 167 | pr_err("No such irq type %d", type); |
218 | return -1; | 168 | return -EINVAL; |
219 | } | 169 | } |
220 | 170 | ||
221 | value = __raw_readl(extint_reg); | 171 | value = __raw_readl(extint_reg); |
@@ -225,265 +175,113 @@ s3c_irqext_type(struct irq_data *data, unsigned int type) | |||
225 | return 0; | 175 | return 0; |
226 | } | 176 | } |
227 | 177 | ||
228 | static struct irq_chip s3c_irqext_chip = { | 178 | /* FIXME: make static when it's out of plat-samsung/irq.h */ |
229 | .name = "s3c-ext", | 179 | int s3c_irqext_type(struct irq_data *data, unsigned int type) |
230 | .irq_mask = s3c_irqext_mask, | ||
231 | .irq_unmask = s3c_irqext_unmask, | ||
232 | .irq_ack = s3c_irqext_ack, | ||
233 | .irq_set_type = s3c_irqext_type, | ||
234 | .irq_set_wake = s3c_irqext_wake | ||
235 | }; | ||
236 | |||
237 | static struct irq_chip s3c_irq_eint0t4 = { | ||
238 | .name = "s3c-ext0", | ||
239 | .irq_ack = s3c_irq_ack, | ||
240 | .irq_mask = s3c_irq_mask, | ||
241 | .irq_unmask = s3c_irq_unmask, | ||
242 | .irq_set_wake = s3c_irq_wake, | ||
243 | .irq_set_type = s3c_irqext_type, | ||
244 | }; | ||
245 | |||
246 | /* mask values for the parent registers for each of the interrupt types */ | ||
247 | |||
248 | #define INTMSK_UART0 (1UL << (IRQ_UART0 - IRQ_EINT0)) | ||
249 | #define INTMSK_UART1 (1UL << (IRQ_UART1 - IRQ_EINT0)) | ||
250 | #define INTMSK_UART2 (1UL << (IRQ_UART2 - IRQ_EINT0)) | ||
251 | #define INTMSK_ADCPARENT (1UL << (IRQ_ADCPARENT - IRQ_EINT0)) | ||
252 | |||
253 | |||
254 | /* UART0 */ | ||
255 | |||
256 | static void | ||
257 | s3c_irq_uart0_mask(struct irq_data *data) | ||
258 | { | 180 | { |
259 | s3c_irqsub_mask(data->irq, INTMSK_UART0, 7); | 181 | void __iomem *extint_reg; |
260 | } | 182 | void __iomem *gpcon_reg; |
183 | unsigned long gpcon_offset, extint_offset; | ||
261 | 184 | ||
262 | static void | 185 | if ((data->hwirq >= 4) && (data->hwirq <= 7)) { |
263 | s3c_irq_uart0_unmask(struct irq_data *data) | 186 | gpcon_reg = S3C2410_GPFCON; |
264 | { | 187 | extint_reg = S3C24XX_EXTINT0; |
265 | s3c_irqsub_unmask(data->irq, INTMSK_UART0); | 188 | gpcon_offset = (data->hwirq) * 2; |
266 | } | 189 | extint_offset = (data->hwirq) * 4; |
190 | } else if ((data->hwirq >= 8) && (data->hwirq <= 15)) { | ||
191 | gpcon_reg = S3C2410_GPGCON; | ||
192 | extint_reg = S3C24XX_EXTINT1; | ||
193 | gpcon_offset = (data->hwirq - 8) * 2; | ||
194 | extint_offset = (data->hwirq - 8) * 4; | ||
195 | } else if ((data->hwirq >= 16) && (data->hwirq <= 23)) { | ||
196 | gpcon_reg = S3C2410_GPGCON; | ||
197 | extint_reg = S3C24XX_EXTINT2; | ||
198 | gpcon_offset = (data->hwirq - 8) * 2; | ||
199 | extint_offset = (data->hwirq - 16) * 4; | ||
200 | } else { | ||
201 | return -EINVAL; | ||
202 | } | ||
267 | 203 | ||
268 | static void | 204 | return s3c_irqext_type_set(gpcon_reg, extint_reg, gpcon_offset, |
269 | s3c_irq_uart0_ack(struct irq_data *data) | 205 | extint_offset, type); |
270 | { | ||
271 | s3c_irqsub_maskack(data->irq, INTMSK_UART0, 7); | ||
272 | } | 206 | } |
273 | 207 | ||
274 | static struct irq_chip s3c_irq_uart0 = { | 208 | static int s3c_irqext0_type(struct irq_data *data, unsigned int type) |
275 | .name = "s3c-uart0", | ||
276 | .irq_mask = s3c_irq_uart0_mask, | ||
277 | .irq_unmask = s3c_irq_uart0_unmask, | ||
278 | .irq_ack = s3c_irq_uart0_ack, | ||
279 | }; | ||
280 | |||
281 | /* UART1 */ | ||
282 | |||
283 | static void | ||
284 | s3c_irq_uart1_mask(struct irq_data *data) | ||
285 | { | 209 | { |
286 | s3c_irqsub_mask(data->irq, INTMSK_UART1, 7 << 3); | 210 | void __iomem *extint_reg; |
287 | } | 211 | void __iomem *gpcon_reg; |
212 | unsigned long gpcon_offset, extint_offset; | ||
288 | 213 | ||
289 | static void | 214 | if ((data->hwirq >= 0) && (data->hwirq <= 3)) { |
290 | s3c_irq_uart1_unmask(struct irq_data *data) | 215 | gpcon_reg = S3C2410_GPFCON; |
291 | { | 216 | extint_reg = S3C24XX_EXTINT0; |
292 | s3c_irqsub_unmask(data->irq, INTMSK_UART1); | 217 | gpcon_offset = (data->hwirq) * 2; |
293 | } | 218 | extint_offset = (data->hwirq) * 4; |
219 | } else { | ||
220 | return -EINVAL; | ||
221 | } | ||
294 | 222 | ||
295 | static void | 223 | return s3c_irqext_type_set(gpcon_reg, extint_reg, gpcon_offset, |
296 | s3c_irq_uart1_ack(struct irq_data *data) | 224 | extint_offset, type); |
297 | { | ||
298 | s3c_irqsub_maskack(data->irq, INTMSK_UART1, 7 << 3); | ||
299 | } | 225 | } |
300 | 226 | ||
301 | static struct irq_chip s3c_irq_uart1 = { | 227 | struct irq_chip s3c_irq_chip = { |
302 | .name = "s3c-uart1", | 228 | .name = "s3c", |
303 | .irq_mask = s3c_irq_uart1_mask, | 229 | .irq_ack = s3c_irq_ack, |
304 | .irq_unmask = s3c_irq_uart1_unmask, | 230 | .irq_mask = s3c_irq_mask, |
305 | .irq_ack = s3c_irq_uart1_ack, | 231 | .irq_unmask = s3c_irq_unmask, |
232 | .irq_set_wake = s3c_irq_wake | ||
306 | }; | 233 | }; |
307 | 234 | ||
308 | /* UART2 */ | 235 | struct irq_chip s3c_irq_level_chip = { |
309 | 236 | .name = "s3c-level", | |
310 | static void | 237 | .irq_mask = s3c_irq_mask, |
311 | s3c_irq_uart2_mask(struct irq_data *data) | 238 | .irq_unmask = s3c_irq_unmask, |
312 | { | 239 | .irq_ack = s3c_irq_ack, |
313 | s3c_irqsub_mask(data->irq, INTMSK_UART2, 7 << 6); | ||
314 | } | ||
315 | |||
316 | static void | ||
317 | s3c_irq_uart2_unmask(struct irq_data *data) | ||
318 | { | ||
319 | s3c_irqsub_unmask(data->irq, INTMSK_UART2); | ||
320 | } | ||
321 | |||
322 | static void | ||
323 | s3c_irq_uart2_ack(struct irq_data *data) | ||
324 | { | ||
325 | s3c_irqsub_maskack(data->irq, INTMSK_UART2, 7 << 6); | ||
326 | } | ||
327 | |||
328 | static struct irq_chip s3c_irq_uart2 = { | ||
329 | .name = "s3c-uart2", | ||
330 | .irq_mask = s3c_irq_uart2_mask, | ||
331 | .irq_unmask = s3c_irq_uart2_unmask, | ||
332 | .irq_ack = s3c_irq_uart2_ack, | ||
333 | }; | 240 | }; |
334 | 241 | ||
335 | /* ADC and Touchscreen */ | 242 | static struct irq_chip s3c_irqext_chip = { |
336 | 243 | .name = "s3c-ext", | |
337 | static void | 244 | .irq_mask = s3c_irq_mask, |
338 | s3c_irq_adc_mask(struct irq_data *d) | 245 | .irq_unmask = s3c_irq_unmask, |
339 | { | 246 | .irq_ack = s3c_irq_ack, |
340 | s3c_irqsub_mask(d->irq, INTMSK_ADCPARENT, 3 << 9); | 247 | .irq_set_type = s3c_irqext_type, |
341 | } | 248 | .irq_set_wake = s3c_irqext_wake |
342 | |||
343 | static void | ||
344 | s3c_irq_adc_unmask(struct irq_data *d) | ||
345 | { | ||
346 | s3c_irqsub_unmask(d->irq, INTMSK_ADCPARENT); | ||
347 | } | ||
348 | |||
349 | static void | ||
350 | s3c_irq_adc_ack(struct irq_data *d) | ||
351 | { | ||
352 | s3c_irqsub_ack(d->irq, INTMSK_ADCPARENT, 3 << 9); | ||
353 | } | ||
354 | |||
355 | static struct irq_chip s3c_irq_adc = { | ||
356 | .name = "s3c-adc", | ||
357 | .irq_mask = s3c_irq_adc_mask, | ||
358 | .irq_unmask = s3c_irq_adc_unmask, | ||
359 | .irq_ack = s3c_irq_adc_ack, | ||
360 | }; | 249 | }; |
361 | 250 | ||
362 | /* irq demux for adc */ | 251 | static struct irq_chip s3c_irq_eint0t4 = { |
363 | static void s3c_irq_demux_adc(unsigned int irq, | 252 | .name = "s3c-ext0", |
364 | struct irq_desc *desc) | 253 | .irq_ack = s3c_irq_ack, |
365 | { | 254 | .irq_mask = s3c_irq_mask, |
366 | unsigned int subsrc, submsk; | 255 | .irq_unmask = s3c_irq_unmask, |
367 | unsigned int offset = 9; | 256 | .irq_set_wake = s3c_irq_wake, |
368 | 257 | .irq_set_type = s3c_irqext0_type, | |
369 | /* read the current pending interrupts, and the mask | 258 | }; |
370 | * for what it is available */ | ||
371 | |||
372 | subsrc = __raw_readl(S3C2410_SUBSRCPND); | ||
373 | submsk = __raw_readl(S3C2410_INTSUBMSK); | ||
374 | |||
375 | subsrc &= ~submsk; | ||
376 | subsrc >>= offset; | ||
377 | subsrc &= 3; | ||
378 | |||
379 | if (subsrc != 0) { | ||
380 | if (subsrc & 1) { | ||
381 | generic_handle_irq(IRQ_TC); | ||
382 | } | ||
383 | if (subsrc & 2) { | ||
384 | generic_handle_irq(IRQ_ADC); | ||
385 | } | ||
386 | } | ||
387 | } | ||
388 | 259 | ||
389 | static void s3c_irq_demux_uart(unsigned int start) | 260 | static void s3c_irq_demux(unsigned int irq, struct irq_desc *desc) |
390 | { | 261 | { |
391 | unsigned int subsrc, submsk; | 262 | struct irq_chip *chip = irq_desc_get_chip(desc); |
392 | unsigned int offset = start - IRQ_S3CUART_RX0; | 263 | struct s3c_irq_intc *intc = desc->irq_data.domain->host_data; |
393 | 264 | struct s3c_irq_data *irq_data = &intc->irqs[desc->irq_data.hwirq]; | |
394 | /* read the current pending interrupts, and the mask | 265 | struct s3c_irq_intc *sub_intc = irq_data->sub_intc; |
395 | * for what it is available */ | 266 | unsigned long src; |
396 | 267 | unsigned long msk; | |
397 | subsrc = __raw_readl(S3C2410_SUBSRCPND); | 268 | unsigned int n; |
398 | submsk = __raw_readl(S3C2410_INTSUBMSK); | 269 | |
399 | 270 | chained_irq_enter(chip, desc); | |
400 | irqdbf2("s3c_irq_demux_uart: start=%d (%d), subsrc=0x%08x,0x%08x\n", | 271 | |
401 | start, offset, subsrc, submsk); | 272 | src = __raw_readl(sub_intc->reg_pending); |
402 | 273 | msk = __raw_readl(sub_intc->reg_mask); | |
403 | subsrc &= ~submsk; | 274 | |
404 | subsrc >>= offset; | 275 | src &= ~msk; |
405 | subsrc &= 7; | 276 | src &= irq_data->sub_bits; |
406 | 277 | ||
407 | if (subsrc != 0) { | 278 | while (src) { |
408 | if (subsrc & 1) | 279 | n = __ffs(src); |
409 | generic_handle_irq(start); | 280 | src &= ~(1 << n); |
410 | 281 | generic_handle_irq(irq_find_mapping(sub_intc->domain, n)); | |
411 | if (subsrc & 2) | ||
412 | generic_handle_irq(start+1); | ||
413 | |||
414 | if (subsrc & 4) | ||
415 | generic_handle_irq(start+2); | ||
416 | } | 282 | } |
417 | } | ||
418 | |||
419 | /* uart demux entry points */ | ||
420 | |||
421 | static void | ||
422 | s3c_irq_demux_uart0(unsigned int irq, | ||
423 | struct irq_desc *desc) | ||
424 | { | ||
425 | irq = irq; | ||
426 | s3c_irq_demux_uart(IRQ_S3CUART_RX0); | ||
427 | } | ||
428 | 283 | ||
429 | static void | 284 | chained_irq_exit(chip, desc); |
430 | s3c_irq_demux_uart1(unsigned int irq, | ||
431 | struct irq_desc *desc) | ||
432 | { | ||
433 | irq = irq; | ||
434 | s3c_irq_demux_uart(IRQ_S3CUART_RX1); | ||
435 | } | ||
436 | |||
437 | static void | ||
438 | s3c_irq_demux_uart2(unsigned int irq, | ||
439 | struct irq_desc *desc) | ||
440 | { | ||
441 | irq = irq; | ||
442 | s3c_irq_demux_uart(IRQ_S3CUART_RX2); | ||
443 | } | ||
444 | |||
445 | static void | ||
446 | s3c_irq_demux_extint8(unsigned int irq, | ||
447 | struct irq_desc *desc) | ||
448 | { | ||
449 | unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND); | ||
450 | unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK); | ||
451 | |||
452 | eintpnd &= ~eintmsk; | ||
453 | eintpnd &= ~0xff; /* ignore lower irqs */ | ||
454 | |||
455 | /* we may as well handle all the pending IRQs here */ | ||
456 | |||
457 | while (eintpnd) { | ||
458 | irq = __ffs(eintpnd); | ||
459 | eintpnd &= ~(1<<irq); | ||
460 | |||
461 | irq += (IRQ_EINT4 - 4); | ||
462 | generic_handle_irq(irq); | ||
463 | } | ||
464 | |||
465 | } | ||
466 | |||
467 | static void | ||
468 | s3c_irq_demux_extint4t7(unsigned int irq, | ||
469 | struct irq_desc *desc) | ||
470 | { | ||
471 | unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND); | ||
472 | unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK); | ||
473 | |||
474 | eintpnd &= ~eintmsk; | ||
475 | eintpnd &= 0xff; /* only lower irqs */ | ||
476 | |||
477 | /* we may as well handle all the pending IRQs here */ | ||
478 | |||
479 | while (eintpnd) { | ||
480 | irq = __ffs(eintpnd); | ||
481 | eintpnd &= ~(1<<irq); | ||
482 | |||
483 | irq += (IRQ_EINT4 - 4); | ||
484 | |||
485 | generic_handle_irq(irq); | ||
486 | } | ||
487 | } | 285 | } |
488 | 286 | ||
489 | #ifdef CONFIG_FIQ | 287 | #ifdef CONFIG_FIQ |
@@ -519,158 +317,506 @@ int s3c24xx_set_fiq(unsigned int irq, bool on) | |||
519 | EXPORT_SYMBOL_GPL(s3c24xx_set_fiq); | 317 | EXPORT_SYMBOL_GPL(s3c24xx_set_fiq); |
520 | #endif | 318 | #endif |
521 | 319 | ||
320 | static int s3c24xx_irq_map(struct irq_domain *h, unsigned int virq, | ||
321 | irq_hw_number_t hw) | ||
322 | { | ||
323 | struct s3c_irq_intc *intc = h->host_data; | ||
324 | struct s3c_irq_data *irq_data = &intc->irqs[hw]; | ||
325 | struct s3c_irq_intc *parent_intc; | ||
326 | struct s3c_irq_data *parent_irq_data; | ||
327 | unsigned int irqno; | ||
328 | |||
329 | if (!intc) { | ||
330 | pr_err("irq-s3c24xx: no controller found for hwirq %lu\n", hw); | ||
331 | return -EINVAL; | ||
332 | } | ||
522 | 333 | ||
523 | /* s3c24xx_init_irq | 334 | if (!irq_data) { |
524 | * | 335 | pr_err("irq-s3c24xx: no irq data found for hwirq %lu\n", hw); |
525 | * Initialise S3C2410 IRQ system | 336 | return -EINVAL; |
526 | */ | 337 | } |
527 | 338 | ||
528 | void __init s3c24xx_init_irq(void) | 339 | /* attach controller pointer to irq_data */ |
340 | irq_data->intc = intc; | ||
341 | |||
342 | /* set handler and flags */ | ||
343 | switch (irq_data->type) { | ||
344 | case S3C_IRQTYPE_NONE: | ||
345 | return 0; | ||
346 | case S3C_IRQTYPE_EINT: | ||
347 | if (irq_data->parent_irq) | ||
348 | irq_set_chip_and_handler(virq, &s3c_irqext_chip, | ||
349 | handle_edge_irq); | ||
350 | else | ||
351 | irq_set_chip_and_handler(virq, &s3c_irq_eint0t4, | ||
352 | handle_edge_irq); | ||
353 | break; | ||
354 | case S3C_IRQTYPE_EDGE: | ||
355 | if (irq_data->parent_irq || | ||
356 | intc->reg_pending == S3C2416_SRCPND2) | ||
357 | irq_set_chip_and_handler(virq, &s3c_irq_level_chip, | ||
358 | handle_edge_irq); | ||
359 | else | ||
360 | irq_set_chip_and_handler(virq, &s3c_irq_chip, | ||
361 | handle_edge_irq); | ||
362 | break; | ||
363 | case S3C_IRQTYPE_LEVEL: | ||
364 | if (irq_data->parent_irq) | ||
365 | irq_set_chip_and_handler(virq, &s3c_irq_level_chip, | ||
366 | handle_level_irq); | ||
367 | else | ||
368 | irq_set_chip_and_handler(virq, &s3c_irq_chip, | ||
369 | handle_level_irq); | ||
370 | break; | ||
371 | default: | ||
372 | pr_err("irq-s3c24xx: unsupported irqtype %d\n", irq_data->type); | ||
373 | return -EINVAL; | ||
374 | } | ||
375 | set_irq_flags(virq, IRQF_VALID); | ||
376 | |||
377 | if (irq_data->parent_irq) { | ||
378 | parent_intc = intc->parent; | ||
379 | if (!parent_intc) { | ||
380 | pr_err("irq-s3c24xx: no parent controller found for hwirq %lu\n", | ||
381 | hw); | ||
382 | goto err; | ||
383 | } | ||
384 | |||
385 | parent_irq_data = &parent_intc->irqs[irq_data->parent_irq]; | ||
386 | if (!irq_data) { | ||
387 | pr_err("irq-s3c24xx: no irq data found for hwirq %lu\n", | ||
388 | hw); | ||
389 | goto err; | ||
390 | } | ||
391 | |||
392 | parent_irq_data->sub_intc = intc; | ||
393 | parent_irq_data->sub_bits |= (1UL << hw); | ||
394 | |||
395 | /* attach the demuxer to the parent irq */ | ||
396 | irqno = irq_find_mapping(parent_intc->domain, | ||
397 | irq_data->parent_irq); | ||
398 | if (!irqno) { | ||
399 | pr_err("irq-s3c24xx: could not find mapping for parent irq %lu\n", | ||
400 | irq_data->parent_irq); | ||
401 | goto err; | ||
402 | } | ||
403 | irq_set_chained_handler(irqno, s3c_irq_demux); | ||
404 | } | ||
405 | |||
406 | return 0; | ||
407 | |||
408 | err: | ||
409 | set_irq_flags(virq, 0); | ||
410 | |||
411 | /* the only error can result from bad mapping data*/ | ||
412 | return -EINVAL; | ||
413 | } | ||
414 | |||
415 | static struct irq_domain_ops s3c24xx_irq_ops = { | ||
416 | .map = s3c24xx_irq_map, | ||
417 | .xlate = irq_domain_xlate_twocell, | ||
418 | }; | ||
419 | |||
420 | static void s3c24xx_clear_intc(struct s3c_irq_intc *intc) | ||
529 | { | 421 | { |
422 | void __iomem *reg_source; | ||
530 | unsigned long pend; | 423 | unsigned long pend; |
531 | unsigned long last; | 424 | unsigned long last; |
532 | int irqno; | ||
533 | int i; | 425 | int i; |
534 | 426 | ||
535 | #ifdef CONFIG_FIQ | 427 | /* if intpnd is set, read the next pending irq from there */ |
536 | init_FIQ(FIQ_START); | 428 | reg_source = intc->reg_intpnd ? intc->reg_intpnd : intc->reg_pending; |
537 | #endif | ||
538 | |||
539 | irqdbf("s3c2410_init_irq: clearing interrupt status flags\n"); | ||
540 | |||
541 | /* first, clear all interrupts pending... */ | ||
542 | 429 | ||
543 | last = 0; | 430 | last = 0; |
544 | for (i = 0; i < 4; i++) { | 431 | for (i = 0; i < 4; i++) { |
545 | pend = __raw_readl(S3C24XX_EINTPEND); | 432 | pend = __raw_readl(reg_source); |
546 | 433 | ||
547 | if (pend == 0 || pend == last) | 434 | if (pend == 0 || pend == last) |
548 | break; | 435 | break; |
549 | 436 | ||
550 | __raw_writel(pend, S3C24XX_EINTPEND); | 437 | __raw_writel(pend, intc->reg_pending); |
551 | printk("irq: clearing pending ext status %08x\n", (int)pend); | 438 | if (intc->reg_intpnd) |
439 | __raw_writel(pend, intc->reg_intpnd); | ||
440 | |||
441 | pr_info("irq: clearing pending status %08x\n", (int)pend); | ||
552 | last = pend; | 442 | last = pend; |
553 | } | 443 | } |
444 | } | ||
554 | 445 | ||
555 | last = 0; | 446 | struct s3c_irq_intc *s3c24xx_init_intc(struct device_node *np, |
556 | for (i = 0; i < 4; i++) { | 447 | struct s3c_irq_data *irq_data, |
557 | pend = __raw_readl(S3C2410_INTPND); | 448 | struct s3c_irq_intc *parent, |
558 | 449 | unsigned long address) | |
559 | if (pend == 0 || pend == last) | 450 | { |
560 | break; | 451 | struct s3c_irq_intc *intc; |
561 | 452 | void __iomem *base = (void *)0xf6000000; /* static mapping */ | |
562 | __raw_writel(pend, S3C2410_SRCPND); | 453 | int irq_num; |
563 | __raw_writel(pend, S3C2410_INTPND); | 454 | int irq_start; |
564 | printk("irq: clearing pending status %08x\n", (int)pend); | 455 | int irq_offset; |
565 | last = pend; | 456 | int ret; |
457 | |||
458 | intc = kzalloc(sizeof(struct s3c_irq_intc), GFP_KERNEL); | ||
459 | if (!intc) | ||
460 | return ERR_PTR(-ENOMEM); | ||
461 | |||
462 | intc->irqs = irq_data; | ||
463 | |||
464 | if (parent) | ||
465 | intc->parent = parent; | ||
466 | |||
467 | /* select the correct data for the controller. | ||
468 | * Need to hard code the irq num start and offset | ||
469 | * to preserve the static mapping for now | ||
470 | */ | ||
471 | switch (address) { | ||
472 | case 0x4a000000: | ||
473 | pr_debug("irq: found main intc\n"); | ||
474 | intc->reg_pending = base; | ||
475 | intc->reg_mask = base + 0x08; | ||
476 | intc->reg_intpnd = base + 0x10; | ||
477 | irq_num = 32; | ||
478 | irq_start = S3C2410_IRQ(0); | ||
479 | irq_offset = 0; | ||
480 | break; | ||
481 | case 0x4a000018: | ||
482 | pr_debug("irq: found subintc\n"); | ||
483 | intc->reg_pending = base + 0x18; | ||
484 | intc->reg_mask = base + 0x1c; | ||
485 | irq_num = 29; | ||
486 | irq_start = S3C2410_IRQSUB(0); | ||
487 | irq_offset = 0; | ||
488 | break; | ||
489 | case 0x4a000040: | ||
490 | pr_debug("irq: found intc2\n"); | ||
491 | intc->reg_pending = base + 0x40; | ||
492 | intc->reg_mask = base + 0x48; | ||
493 | intc->reg_intpnd = base + 0x50; | ||
494 | irq_num = 8; | ||
495 | irq_start = S3C2416_IRQ(0); | ||
496 | irq_offset = 0; | ||
497 | break; | ||
498 | case 0x560000a4: | ||
499 | pr_debug("irq: found eintc\n"); | ||
500 | base = (void *)0xfd000000; | ||
501 | |||
502 | intc->reg_mask = base + 0xa4; | ||
503 | intc->reg_pending = base + 0x08; | ||
504 | irq_num = 20; | ||
505 | irq_start = S3C2410_IRQ(32); | ||
506 | irq_offset = 4; | ||
507 | break; | ||
508 | default: | ||
509 | pr_err("irq: unsupported controller address\n"); | ||
510 | ret = -EINVAL; | ||
511 | goto err; | ||
566 | } | 512 | } |
567 | 513 | ||
568 | last = 0; | 514 | /* now that all the data is complete, init the irq-domain */ |
569 | for (i = 0; i < 4; i++) { | 515 | s3c24xx_clear_intc(intc); |
570 | pend = __raw_readl(S3C2410_SUBSRCPND); | 516 | intc->domain = irq_domain_add_legacy(np, irq_num, irq_start, |
517 | irq_offset, &s3c24xx_irq_ops, | ||
518 | intc); | ||
519 | if (!intc->domain) { | ||
520 | pr_err("irq: could not create irq-domain\n"); | ||
521 | ret = -EINVAL; | ||
522 | goto err; | ||
523 | } | ||
571 | 524 | ||
572 | if (pend == 0 || pend == last) | 525 | return intc; |
573 | break; | ||
574 | 526 | ||
575 | printk("irq: clearing subpending status %08x\n", (int)pend); | 527 | err: |
576 | __raw_writel(pend, S3C2410_SUBSRCPND); | 528 | kfree(intc); |
577 | last = pend; | 529 | return ERR_PTR(ret); |
578 | } | 530 | } |
579 | 531 | ||
580 | /* register the main interrupts */ | 532 | /* s3c24xx_init_irq |
533 | * | ||
534 | * Initialise S3C2410 IRQ system | ||
535 | */ | ||
581 | 536 | ||
582 | irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n"); | 537 | static struct s3c_irq_data init_base[32] = { |
538 | { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */ | ||
539 | { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */ | ||
540 | { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */ | ||
541 | { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */ | ||
542 | { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */ | ||
543 | { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */ | ||
544 | { .type = S3C_IRQTYPE_NONE, }, /* reserved */ | ||
545 | { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */ | ||
546 | { .type = S3C_IRQTYPE_EDGE, }, /* TICK */ | ||
547 | { .type = S3C_IRQTYPE_EDGE, }, /* WDT */ | ||
548 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */ | ||
549 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */ | ||
550 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */ | ||
551 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */ | ||
552 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */ | ||
553 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */ | ||
554 | { .type = S3C_IRQTYPE_EDGE, }, /* LCD */ | ||
555 | { .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */ | ||
556 | { .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */ | ||
557 | { .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */ | ||
558 | { .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */ | ||
559 | { .type = S3C_IRQTYPE_EDGE, }, /* SDI */ | ||
560 | { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */ | ||
561 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */ | ||
562 | { .type = S3C_IRQTYPE_NONE, }, /* reserved */ | ||
563 | { .type = S3C_IRQTYPE_EDGE, }, /* USBD */ | ||
564 | { .type = S3C_IRQTYPE_EDGE, }, /* USBH */ | ||
565 | { .type = S3C_IRQTYPE_EDGE, }, /* IIC */ | ||
566 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */ | ||
567 | { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */ | ||
568 | { .type = S3C_IRQTYPE_EDGE, }, /* RTC */ | ||
569 | { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */ | ||
570 | }; | ||
583 | 571 | ||
584 | for (irqno = IRQ_EINT4t7; irqno <= IRQ_ADCPARENT; irqno++) { | 572 | static struct s3c_irq_data init_eint[32] = { |
585 | /* set all the s3c2410 internal irqs */ | 573 | { .type = S3C_IRQTYPE_NONE, }, /* reserved */ |
574 | { .type = S3C_IRQTYPE_NONE, }, /* reserved */ | ||
575 | { .type = S3C_IRQTYPE_NONE, }, /* reserved */ | ||
576 | { .type = S3C_IRQTYPE_NONE, }, /* reserved */ | ||
577 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT4 */ | ||
578 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT5 */ | ||
579 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT6 */ | ||
580 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT7 */ | ||
581 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT8 */ | ||
582 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT9 */ | ||
583 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT10 */ | ||
584 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT11 */ | ||
585 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT12 */ | ||
586 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT13 */ | ||
587 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT14 */ | ||
588 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT15 */ | ||
589 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT16 */ | ||
590 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT17 */ | ||
591 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT18 */ | ||
592 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT19 */ | ||
593 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT20 */ | ||
594 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT21 */ | ||
595 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT22 */ | ||
596 | { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT23 */ | ||
597 | }; | ||
586 | 598 | ||
587 | switch (irqno) { | 599 | static struct s3c_irq_data init_subint[32] = { |
588 | /* deal with the special IRQs (cascaded) */ | 600 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */ |
601 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */ | ||
602 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */ | ||
603 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */ | ||
604 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */ | ||
605 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */ | ||
606 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */ | ||
607 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */ | ||
608 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */ | ||
609 | { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */ | ||
610 | { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */ | ||
611 | }; | ||
589 | 612 | ||
590 | case IRQ_EINT4t7: | 613 | void __init s3c24xx_init_irq(void) |
591 | case IRQ_EINT8t23: | 614 | { |
592 | case IRQ_UART0: | 615 | struct s3c_irq_intc *main_intc; |
593 | case IRQ_UART1: | ||
594 | case IRQ_UART2: | ||
595 | case IRQ_ADCPARENT: | ||
596 | irq_set_chip_and_handler(irqno, &s3c_irq_level_chip, | ||
597 | handle_level_irq); | ||
598 | break; | ||
599 | 616 | ||
600 | case IRQ_RESERVED6: | 617 | #ifdef CONFIG_FIQ |
601 | case IRQ_RESERVED24: | 618 | init_FIQ(FIQ_START); |
602 | /* no IRQ here */ | 619 | #endif |
603 | break; | ||
604 | 620 | ||
605 | default: | 621 | main_intc = s3c24xx_init_intc(NULL, &init_base[0], NULL, 0x4a000000); |
606 | //irqdbf("registering irq %d (s3c irq)\n", irqno); | 622 | if (IS_ERR(main_intc)) { |
607 | irq_set_chip_and_handler(irqno, &s3c_irq_chip, | 623 | pr_err("irq: could not create main interrupt controller\n"); |
608 | handle_edge_irq); | 624 | return; |
609 | set_irq_flags(irqno, IRQF_VALID); | ||
610 | } | ||
611 | } | 625 | } |
612 | 626 | ||
613 | /* setup the cascade irq handlers */ | 627 | s3c24xx_init_intc(NULL, &init_subint[0], main_intc, 0x4a000018); |
628 | s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4); | ||
629 | } | ||
614 | 630 | ||
615 | irq_set_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint4t7); | 631 | #ifdef CONFIG_CPU_S3C2416 |
616 | irq_set_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint8); | 632 | static struct s3c_irq_data init_s3c2416base[32] = { |
633 | { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */ | ||
634 | { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */ | ||
635 | { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */ | ||
636 | { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */ | ||
637 | { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */ | ||
638 | { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */ | ||
639 | { .type = S3C_IRQTYPE_NONE, }, /* reserved */ | ||
640 | { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */ | ||
641 | { .type = S3C_IRQTYPE_EDGE, }, /* TICK */ | ||
642 | { .type = S3C_IRQTYPE_LEVEL, }, /* WDT/AC97 */ | ||
643 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */ | ||
644 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */ | ||
645 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */ | ||
646 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */ | ||
647 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */ | ||
648 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */ | ||
649 | { .type = S3C_IRQTYPE_LEVEL, }, /* LCD */ | ||
650 | { .type = S3C_IRQTYPE_LEVEL, }, /* DMA */ | ||
651 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART3 */ | ||
652 | { .type = S3C_IRQTYPE_NONE, }, /* reserved */ | ||
653 | { .type = S3C_IRQTYPE_EDGE, }, /* SDI1 */ | ||
654 | { .type = S3C_IRQTYPE_EDGE, }, /* SDI0 */ | ||
655 | { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */ | ||
656 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */ | ||
657 | { .type = S3C_IRQTYPE_EDGE, }, /* NAND */ | ||
658 | { .type = S3C_IRQTYPE_EDGE, }, /* USBD */ | ||
659 | { .type = S3C_IRQTYPE_EDGE, }, /* USBH */ | ||
660 | { .type = S3C_IRQTYPE_EDGE, }, /* IIC */ | ||
661 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */ | ||
662 | { .type = S3C_IRQTYPE_NONE, }, | ||
663 | { .type = S3C_IRQTYPE_EDGE, }, /* RTC */ | ||
664 | { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */ | ||
665 | }; | ||
617 | 666 | ||
618 | irq_set_chained_handler(IRQ_UART0, s3c_irq_demux_uart0); | 667 | static struct s3c_irq_data init_s3c2416subint[32] = { |
619 | irq_set_chained_handler(IRQ_UART1, s3c_irq_demux_uart1); | 668 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */ |
620 | irq_set_chained_handler(IRQ_UART2, s3c_irq_demux_uart2); | 669 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */ |
621 | irq_set_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc); | 670 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */ |
671 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */ | ||
672 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */ | ||
673 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */ | ||
674 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */ | ||
675 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */ | ||
676 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */ | ||
677 | { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */ | ||
678 | { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */ | ||
679 | { .type = S3C_IRQTYPE_NONE }, /* reserved */ | ||
680 | { .type = S3C_IRQTYPE_NONE }, /* reserved */ | ||
681 | { .type = S3C_IRQTYPE_NONE }, /* reserved */ | ||
682 | { .type = S3C_IRQTYPE_NONE }, /* reserved */ | ||
683 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD2 */ | ||
684 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD3 */ | ||
685 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD4 */ | ||
686 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA0 */ | ||
687 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA1 */ | ||
688 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA2 */ | ||
689 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA3 */ | ||
690 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA4 */ | ||
691 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA5 */ | ||
692 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-RX */ | ||
693 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-TX */ | ||
694 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-ERR */ | ||
695 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* WDT */ | ||
696 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* AC97 */ | ||
697 | }; | ||
622 | 698 | ||
623 | /* external interrupts */ | 699 | static struct s3c_irq_data init_s3c2416_second[32] = { |
700 | { .type = S3C_IRQTYPE_EDGE }, /* 2D */ | ||
701 | { .type = S3C_IRQTYPE_EDGE }, /* IIC1 */ | ||
702 | { .type = S3C_IRQTYPE_NONE }, /* reserved */ | ||
703 | { .type = S3C_IRQTYPE_NONE }, /* reserved */ | ||
704 | { .type = S3C_IRQTYPE_EDGE }, /* PCM0 */ | ||
705 | { .type = S3C_IRQTYPE_EDGE }, /* PCM1 */ | ||
706 | { .type = S3C_IRQTYPE_EDGE }, /* I2S0 */ | ||
707 | { .type = S3C_IRQTYPE_EDGE }, /* I2S1 */ | ||
708 | }; | ||
624 | 709 | ||
625 | for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) { | 710 | void __init s3c2416_init_irq(void) |
626 | irqdbf("registering irq %d (ext int)\n", irqno); | 711 | { |
627 | irq_set_chip_and_handler(irqno, &s3c_irq_eint0t4, | 712 | struct s3c_irq_intc *main_intc; |
628 | handle_edge_irq); | 713 | |
629 | set_irq_flags(irqno, IRQF_VALID); | 714 | pr_info("S3C2416: IRQ Support\n"); |
630 | } | 715 | |
716 | #ifdef CONFIG_FIQ | ||
717 | init_FIQ(FIQ_START); | ||
718 | #endif | ||
631 | 719 | ||
632 | for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) { | 720 | main_intc = s3c24xx_init_intc(NULL, &init_s3c2416base[0], NULL, 0x4a000000); |
633 | irqdbf("registering irq %d (extended s3c irq)\n", irqno); | 721 | if (IS_ERR(main_intc)) { |
634 | irq_set_chip_and_handler(irqno, &s3c_irqext_chip, | 722 | pr_err("irq: could not create main interrupt controller\n"); |
635 | handle_edge_irq); | 723 | return; |
636 | set_irq_flags(irqno, IRQF_VALID); | ||
637 | } | 724 | } |
638 | 725 | ||
639 | /* register the uart interrupts */ | 726 | s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4); |
727 | s3c24xx_init_intc(NULL, &init_s3c2416subint[0], main_intc, 0x4a000018); | ||
640 | 728 | ||
641 | irqdbf("s3c2410: registering external interrupts\n"); | 729 | s3c24xx_init_intc(NULL, &init_s3c2416_second[0], NULL, 0x4a000040); |
730 | } | ||
642 | 731 | ||
643 | for (irqno = IRQ_S3CUART_RX0; irqno <= IRQ_S3CUART_ERR0; irqno++) { | 732 | #endif |
644 | irqdbf("registering irq %d (s3c uart0 irq)\n", irqno); | ||
645 | irq_set_chip_and_handler(irqno, &s3c_irq_uart0, | ||
646 | handle_level_irq); | ||
647 | set_irq_flags(irqno, IRQF_VALID); | ||
648 | } | ||
649 | 733 | ||
650 | for (irqno = IRQ_S3CUART_RX1; irqno <= IRQ_S3CUART_ERR1; irqno++) { | 734 | #ifdef CONFIG_CPU_S3C2443 |
651 | irqdbf("registering irq %d (s3c uart1 irq)\n", irqno); | 735 | static struct s3c_irq_data init_s3c2443base[32] = { |
652 | irq_set_chip_and_handler(irqno, &s3c_irq_uart1, | 736 | { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */ |
653 | handle_level_irq); | 737 | { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */ |
654 | set_irq_flags(irqno, IRQF_VALID); | 738 | { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */ |
655 | } | 739 | { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */ |
740 | { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */ | ||
741 | { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */ | ||
742 | { .type = S3C_IRQTYPE_LEVEL, }, /* CAM */ | ||
743 | { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */ | ||
744 | { .type = S3C_IRQTYPE_EDGE, }, /* TICK */ | ||
745 | { .type = S3C_IRQTYPE_LEVEL, }, /* WDT/AC97 */ | ||
746 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */ | ||
747 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */ | ||
748 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */ | ||
749 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */ | ||
750 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */ | ||
751 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */ | ||
752 | { .type = S3C_IRQTYPE_LEVEL, }, /* LCD */ | ||
753 | { .type = S3C_IRQTYPE_LEVEL, }, /* DMA */ | ||
754 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART3 */ | ||
755 | { .type = S3C_IRQTYPE_EDGE, }, /* CFON */ | ||
756 | { .type = S3C_IRQTYPE_EDGE, }, /* SDI1 */ | ||
757 | { .type = S3C_IRQTYPE_EDGE, }, /* SDI0 */ | ||
758 | { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */ | ||
759 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */ | ||
760 | { .type = S3C_IRQTYPE_EDGE, }, /* NAND */ | ||
761 | { .type = S3C_IRQTYPE_EDGE, }, /* USBD */ | ||
762 | { .type = S3C_IRQTYPE_EDGE, }, /* USBH */ | ||
763 | { .type = S3C_IRQTYPE_EDGE, }, /* IIC */ | ||
764 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */ | ||
765 | { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */ | ||
766 | { .type = S3C_IRQTYPE_EDGE, }, /* RTC */ | ||
767 | { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */ | ||
768 | }; | ||
656 | 769 | ||
657 | for (irqno = IRQ_S3CUART_RX2; irqno <= IRQ_S3CUART_ERR2; irqno++) { | ||
658 | irqdbf("registering irq %d (s3c uart2 irq)\n", irqno); | ||
659 | irq_set_chip_and_handler(irqno, &s3c_irq_uart2, | ||
660 | handle_level_irq); | ||
661 | set_irq_flags(irqno, IRQF_VALID); | ||
662 | } | ||
663 | 770 | ||
664 | for (irqno = IRQ_TC; irqno <= IRQ_ADC; irqno++) { | 771 | static struct s3c_irq_data init_s3c2443subint[32] = { |
665 | irqdbf("registering irq %d (s3c adc irq)\n", irqno); | 772 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */ |
666 | irq_set_chip_and_handler(irqno, &s3c_irq_adc, handle_edge_irq); | 773 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */ |
667 | set_irq_flags(irqno, IRQF_VALID); | 774 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */ |
775 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */ | ||
776 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */ | ||
777 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */ | ||
778 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */ | ||
779 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */ | ||
780 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */ | ||
781 | { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */ | ||
782 | { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */ | ||
783 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_C */ | ||
784 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_P */ | ||
785 | { .type = S3C_IRQTYPE_NONE }, /* reserved */ | ||
786 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD1 */ | ||
787 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD2 */ | ||
788 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD3 */ | ||
789 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD4 */ | ||
790 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA0 */ | ||
791 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA1 */ | ||
792 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA2 */ | ||
793 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA3 */ | ||
794 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA4 */ | ||
795 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA5 */ | ||
796 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-RX */ | ||
797 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-TX */ | ||
798 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-ERR */ | ||
799 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* WDT */ | ||
800 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* AC97 */ | ||
801 | }; | ||
802 | |||
803 | void __init s3c2443_init_irq(void) | ||
804 | { | ||
805 | struct s3c_irq_intc *main_intc; | ||
806 | |||
807 | pr_info("S3C2443: IRQ Support\n"); | ||
808 | |||
809 | #ifdef CONFIG_FIQ | ||
810 | init_FIQ(FIQ_START); | ||
811 | #endif | ||
812 | |||
813 | main_intc = s3c24xx_init_intc(NULL, &init_s3c2443base[0], NULL, 0x4a000000); | ||
814 | if (IS_ERR(main_intc)) { | ||
815 | pr_err("irq: could not create main interrupt controller\n"); | ||
816 | return; | ||
668 | } | 817 | } |
669 | 818 | ||
670 | irqdbf("s3c2410: registered interrupt handlers\n"); | 819 | s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4); |
820 | s3c24xx_init_intc(NULL, &init_s3c2443subint[0], main_intc, 0x4a000018); | ||
671 | } | 821 | } |
672 | 822 | #endif | |
673 | struct syscore_ops s3c24xx_irq_syscore_ops = { | ||
674 | .suspend = s3c24xx_irq_suspend, | ||
675 | .resume = s3c24xx_irq_resume, | ||
676 | }; | ||
diff --git a/arch/arm/plat-samsung/include/plat/pm.h b/arch/arm/plat-samsung/include/plat/pm.h index 887a0c954379..f6fcadeee969 100644 --- a/arch/arm/plat-samsung/include/plat/pm.h +++ b/arch/arm/plat-samsung/include/plat/pm.h | |||
@@ -109,17 +109,11 @@ extern void s3c_pm_do_restore_core(struct sleep_save *ptr, int count); | |||
109 | #ifdef CONFIG_PM | 109 | #ifdef CONFIG_PM |
110 | extern int s3c_irq_wake(struct irq_data *data, unsigned int state); | 110 | extern int s3c_irq_wake(struct irq_data *data, unsigned int state); |
111 | extern int s3c_irqext_wake(struct irq_data *data, unsigned int state); | 111 | extern int s3c_irqext_wake(struct irq_data *data, unsigned int state); |
112 | extern int s3c24xx_irq_suspend(void); | ||
113 | extern void s3c24xx_irq_resume(void); | ||
114 | #else | 112 | #else |
115 | #define s3c_irq_wake NULL | 113 | #define s3c_irq_wake NULL |
116 | #define s3c_irqext_wake NULL | 114 | #define s3c_irqext_wake NULL |
117 | #define s3c24xx_irq_suspend NULL | ||
118 | #define s3c24xx_irq_resume NULL | ||
119 | #endif | 115 | #endif |
120 | 116 | ||
121 | extern struct syscore_ops s3c24xx_irq_syscore_ops; | ||
122 | |||
123 | /* PM debug functions */ | 117 | /* PM debug functions */ |
124 | 118 | ||
125 | #ifdef CONFIG_SAMSUNG_PM_DEBUG | 119 | #ifdef CONFIG_SAMSUNG_PM_DEBUG |
diff --git a/arch/arm/plat-samsung/include/plat/s3c2416.h b/arch/arm/plat-samsung/include/plat/s3c2416.h index 7178e338e25e..f27399a3c68d 100644 --- a/arch/arm/plat-samsung/include/plat/s3c2416.h +++ b/arch/arm/plat-samsung/include/plat/s3c2416.h | |||
@@ -25,6 +25,7 @@ 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 | 27 | ||
28 | extern void s3c2416_init_irq(void); | ||
28 | extern struct syscore_ops s3c2416_irq_syscore_ops; | 29 | extern struct syscore_ops s3c2416_irq_syscore_ops; |
29 | 30 | ||
30 | #else | 31 | #else |
diff --git a/arch/arm/plat-samsung/include/plat/s3c2443.h b/arch/arm/plat-samsung/include/plat/s3c2443.h index a5b794ff838b..71b88ec48956 100644 --- a/arch/arm/plat-samsung/include/plat/s3c2443.h +++ b/arch/arm/plat-samsung/include/plat/s3c2443.h | |||
@@ -25,6 +25,8 @@ extern void s3c2443_init_clocks(int xtal); | |||
25 | extern int s3c2443_baseclk_add(void); | 25 | extern int s3c2443_baseclk_add(void); |
26 | 26 | ||
27 | extern void s3c2443_restart(char mode, const char *cmd); | 27 | extern void s3c2443_restart(char mode, const char *cmd); |
28 | |||
29 | extern void s3c2443_init_irq(void); | ||
28 | #else | 30 | #else |
29 | #define s3c2443_init_clocks NULL | 31 | #define s3c2443_init_clocks NULL |
30 | #define s3c2443_init_uarts NULL | 32 | #define s3c2443_init_uarts NULL |