aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorHeiko Stuebner <heiko@sntech.de>2012-05-19 12:01:35 -0400
committerKukjin Kim <kgene.kim@samsung.com>2012-05-19 14:05:04 -0400
commit0e944e276c7ebcb880d20f6e9255f596c85fc767 (patch)
tree90aff0c2e5fe44fda194d4a26ed678dc38c48e5c /arch
parent2de05a57467c43f58802cdeaa547aee73396b6f3 (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.h15
-rw-r--r--arch/arm/mach-s3c24xx/irq-s3c2416.c98
-rw-r--r--arch/arm/mach-s3c24xx/s3c2416.c1
-rw-r--r--arch/arm/plat-samsung/include/plat/s3c2416.h3
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
198static 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
206static 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
216static 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
226struct 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
197static int __init s3c2416_add_sub(unsigned int base, 235static 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
254static 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
216static int __init s3c2416_irq_add(struct device *dev, 290static 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
249arch_initcall(s3c2416_irq_init); 325arch_initcall(s3c2416_irq_init);
250 326
327#ifdef CONFIG_PM
328static struct sleep_save irq_save[] = {
329 SAVE_ITEM(S3C2416_INTMSK2),
330};
331
332int s3c2416_irq_suspend(void)
333{
334 s3c_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
335
336 return 0;
337}
338
339void s3c2416_irq_resume(void)
340{
341 s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
342}
343
344struct 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);
24extern int s3c2416_baseclk_add(void); 24extern int s3c2416_baseclk_add(void);
25 25
26extern void s3c2416_restart(char mode, const char *cmd); 26extern void s3c2416_restart(char mode, const char *cmd);
27
28extern 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