1 /* arch/arm/plat-s3c64xx/irq.c
3 * Copyright 2008 Openmoko, Inc.
4 * Copyright 2008 Simtec Electronics
5 * Ben Dooks <ben@simtec.co.uk>
6 * http://armlinux.simtec.co.uk/
8 * S3C64XX - Interrupt handling
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
15 #include <linux/kernel.h>
16 #include <linux/interrupt.h>
17 #include <linux/serial_core.h>
18 #include <linux/irq.h>
21 #include <asm/hardware/vic.h>
24 #include <plat/regs-serial.h>
25 #include <plat/regs-timer.h>
28 /* Timer interrupt handling */
30 static void s3c_irq_demux_timer(unsigned int base_irq
, unsigned int sub_irq
)
32 generic_handle_irq(sub_irq
);
35 static void s3c_irq_demux_timer0(unsigned int irq
, struct irq_desc
*desc
)
37 s3c_irq_demux_timer(irq
, IRQ_TIMER0
);
40 static void s3c_irq_demux_timer1(unsigned int irq
, struct irq_desc
*desc
)
42 s3c_irq_demux_timer(irq
, IRQ_TIMER1
);
45 static void s3c_irq_demux_timer2(unsigned int irq
, struct irq_desc
*desc
)
47 s3c_irq_demux_timer(irq
, IRQ_TIMER2
);
50 static void s3c_irq_demux_timer3(unsigned int irq
, struct irq_desc
*desc
)
52 s3c_irq_demux_timer(irq
, IRQ_TIMER3
);
55 static void s3c_irq_demux_timer4(unsigned int irq
, struct irq_desc
*desc
)
57 s3c_irq_demux_timer(irq
, IRQ_TIMER4
);
60 /* We assume the IRQ_TIMER0..IRQ_TIMER4 range is continuous. */
62 static void s3c_irq_timer_mask(unsigned int irq
)
64 u32 reg
= __raw_readl(S3C64XX_TINT_CSTAT
);
66 reg
&= 0x1f; /* mask out pending interrupts */
67 reg
&= ~(1 << (irq
- IRQ_TIMER0
));
68 __raw_writel(reg
, S3C64XX_TINT_CSTAT
);
71 static void s3c_irq_timer_unmask(unsigned int irq
)
73 u32 reg
= __raw_readl(S3C64XX_TINT_CSTAT
);
75 reg
&= 0x1f; /* mask out pending interrupts */
76 reg
|= 1 << (irq
- IRQ_TIMER0
);
77 __raw_writel(reg
, S3C64XX_TINT_CSTAT
);
80 static void s3c_irq_timer_ack(unsigned int irq
)
82 u32 reg
= __raw_readl(S3C64XX_TINT_CSTAT
);
85 reg
|= (1 << 5) << (irq
- IRQ_TIMER0
);
86 __raw_writel(reg
, S3C64XX_TINT_CSTAT
);
89 static struct irq_chip s3c_irq_timer
= {
91 .mask
= s3c_irq_timer_mask
,
92 .unmask
= s3c_irq_timer_unmask
,
93 .ack
= s3c_irq_timer_ack
,
98 unsigned int base_irq
;
99 unsigned int parent_irq
;
102 /* Note, we make use of the fact that the parent IRQs, IRQ_UART[0..3]
103 * are consecutive when looking up the interrupt in the demux routines.
105 static struct uart_irq uart_irqs
[] = {
107 .regs
= S3C_VA_UART0
,
108 .base_irq
= IRQ_S3CUART_BASE0
,
109 .parent_irq
= IRQ_UART0
,
112 .regs
= S3C_VA_UART1
,
113 .base_irq
= IRQ_S3CUART_BASE1
,
114 .parent_irq
= IRQ_UART1
,
117 .regs
= S3C_VA_UART2
,
118 .base_irq
= IRQ_S3CUART_BASE2
,
119 .parent_irq
= IRQ_UART2
,
122 .regs
= S3C_VA_UART3
,
123 .base_irq
= IRQ_S3CUART_BASE3
,
124 .parent_irq
= IRQ_UART3
,
128 static inline void __iomem
*s3c_irq_uart_base(unsigned int irq
)
130 struct uart_irq
*uirq
= get_irq_chip_data(irq
);
134 static inline unsigned int s3c_irq_uart_bit(unsigned int irq
)
139 /* UART interrupt registers, not worth adding to seperate include header */
141 static void s3c_irq_uart_mask(unsigned int irq
)
143 void __iomem
*regs
= s3c_irq_uart_base(irq
);
144 unsigned int bit
= s3c_irq_uart_bit(irq
);
147 reg
= __raw_readl(regs
+ S3C64XX_UINTM
);
149 __raw_writel(reg
, regs
+ S3C64XX_UINTM
);
152 static void s3c_irq_uart_maskack(unsigned int irq
)
154 void __iomem
*regs
= s3c_irq_uart_base(irq
);
155 unsigned int bit
= s3c_irq_uart_bit(irq
);
158 reg
= __raw_readl(regs
+ S3C64XX_UINTM
);
160 __raw_writel(reg
, regs
+ S3C64XX_UINTM
);
161 __raw_writel(1 << bit
, regs
+ S3C64XX_UINTP
);
164 static void s3c_irq_uart_unmask(unsigned int irq
)
166 void __iomem
*regs
= s3c_irq_uart_base(irq
);
167 unsigned int bit
= s3c_irq_uart_bit(irq
);
170 reg
= __raw_readl(regs
+ S3C64XX_UINTM
);
172 __raw_writel(reg
, regs
+ S3C64XX_UINTM
);
175 static void s3c_irq_uart_ack(unsigned int irq
)
177 void __iomem
*regs
= s3c_irq_uart_base(irq
);
178 unsigned int bit
= s3c_irq_uart_bit(irq
);
180 __raw_writel(1 << bit
, regs
+ S3C64XX_UINTP
);
183 static void s3c_irq_demux_uart(unsigned int irq
, struct irq_desc
*desc
)
185 struct uart_irq
*uirq
= &uart_irqs
[irq
- IRQ_UART0
];
186 u32 pend
= __raw_readl(uirq
->regs
+ S3C64XX_UINTP
);
187 int base
= uirq
->base_irq
;
190 generic_handle_irq(base
);
192 generic_handle_irq(base
+ 1);
194 generic_handle_irq(base
+ 2);
196 generic_handle_irq(base
+ 3);
199 static struct irq_chip s3c_irq_uart
= {
201 .mask
= s3c_irq_uart_mask
,
202 .unmask
= s3c_irq_uart_unmask
,
203 .mask_ack
= s3c_irq_uart_maskack
,
204 .ack
= s3c_irq_uart_ack
,
207 static void __init
s3c64xx_uart_irq(struct uart_irq
*uirq
)
209 void __iomem
*reg_base
= uirq
->regs
;
213 /* mask all interrupts at the start. */
214 __raw_writel(0xf, reg_base
+ S3C64XX_UINTM
);
216 for (offs
= 0; offs
< 3; offs
++) {
217 irq
= uirq
->base_irq
+ offs
;
219 set_irq_chip(irq
, &s3c_irq_uart
);
220 set_irq_chip_data(irq
, uirq
);
221 set_irq_handler(irq
, handle_level_irq
);
222 set_irq_flags(irq
, IRQF_VALID
);
225 set_irq_chained_handler(uirq
->parent_irq
, s3c_irq_demux_uart
);
228 void __init
s3c64xx_init_irq(u32 vic0_valid
, u32 vic1_valid
)
232 printk(KERN_DEBUG
"%s: initialising interrupts\n", __func__
);
234 /* initialise the pair of VICs */
235 vic_init(S3C_VA_VIC0
, S3C_VIC0_BASE
, vic0_valid
, 0);
236 vic_init(S3C_VA_VIC1
, S3C_VIC1_BASE
, vic1_valid
, 0);
238 /* add the timer sub-irqs */
240 set_irq_chained_handler(IRQ_TIMER0_VIC
, s3c_irq_demux_timer0
);
241 set_irq_chained_handler(IRQ_TIMER1_VIC
, s3c_irq_demux_timer1
);
242 set_irq_chained_handler(IRQ_TIMER2_VIC
, s3c_irq_demux_timer2
);
243 set_irq_chained_handler(IRQ_TIMER3_VIC
, s3c_irq_demux_timer3
);
244 set_irq_chained_handler(IRQ_TIMER4_VIC
, s3c_irq_demux_timer4
);
246 for (irq
= IRQ_TIMER0
; irq
<= IRQ_TIMER4
; irq
++) {
247 set_irq_chip(irq
, &s3c_irq_timer
);
248 set_irq_handler(irq
, handle_level_irq
);
249 set_irq_flags(irq
, IRQF_VALID
);
252 for (uart
= 0; uart
< ARRAY_SIZE(uart_irqs
); uart
++)
253 s3c64xx_uart_irq(&uart_irqs
[uart
]);