aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/plat-s3c64xx/Kconfig1
-rw-r--r--arch/arm/plat-s3c64xx/irq.c90
-rw-r--r--arch/arm/plat-samsung/Kconfig7
-rw-r--r--arch/arm/plat-samsung/Makefile2
-rw-r--r--arch/arm/plat-samsung/include/plat/irq-vic-timer.h13
-rw-r--r--arch/arm/plat-samsung/irq-vic-timer.c86
6 files changed, 116 insertions, 83 deletions
diff --git a/arch/arm/plat-s3c64xx/Kconfig b/arch/arm/plat-s3c64xx/Kconfig
index bec12242706b..02d716fb157a 100644
--- a/arch/arm/plat-s3c64xx/Kconfig
+++ b/arch/arm/plat-s3c64xx/Kconfig
@@ -14,6 +14,7 @@ config PLAT_S3C64XX
14 select NO_IOPORT 14 select NO_IOPORT
15 select ARCH_REQUIRE_GPIOLIB 15 select ARCH_REQUIRE_GPIOLIB
16 select SAMSUNG_CLKSRC 16 select SAMSUNG_CLKSRC
17 select SAMSUNG_IRQ_VIC_TIMER
17 select S3C_GPIO_TRACK 18 select S3C_GPIO_TRACK
18 select S3C_GPIO_PULL_UPDOWN 19 select S3C_GPIO_PULL_UPDOWN
19 select S3C_GPIO_CFG_S3C24XX 20 select S3C_GPIO_CFG_S3C24XX
diff --git a/arch/arm/plat-s3c64xx/irq.c b/arch/arm/plat-s3c64xx/irq.c
index 8dc5b6da9789..8b69bca05876 100644
--- a/arch/arm/plat-s3c64xx/irq.c
+++ b/arch/arm/plat-s3c64xx/irq.c
@@ -21,78 +21,10 @@
21#include <asm/hardware/vic.h> 21#include <asm/hardware/vic.h>
22 22
23#include <mach/map.h> 23#include <mach/map.h>
24#include <plat/irq-vic-timer.h>
24#include <plat/regs-serial.h> 25#include <plat/regs-serial.h>
25#include <plat/regs-timer.h>
26#include <plat/cpu.h> 26#include <plat/cpu.h>
27 27
28/* Timer interrupt handling */
29
30static void s3c_irq_demux_timer(unsigned int base_irq, unsigned int sub_irq)
31{
32 generic_handle_irq(sub_irq);
33}
34
35static void s3c_irq_demux_timer0(unsigned int irq, struct irq_desc *desc)
36{
37 s3c_irq_demux_timer(irq, IRQ_TIMER0);
38}
39
40static void s3c_irq_demux_timer1(unsigned int irq, struct irq_desc *desc)
41{
42 s3c_irq_demux_timer(irq, IRQ_TIMER1);
43}
44
45static void s3c_irq_demux_timer2(unsigned int irq, struct irq_desc *desc)
46{
47 s3c_irq_demux_timer(irq, IRQ_TIMER2);
48}
49
50static void s3c_irq_demux_timer3(unsigned int irq, struct irq_desc *desc)
51{
52 s3c_irq_demux_timer(irq, IRQ_TIMER3);
53}
54
55static void s3c_irq_demux_timer4(unsigned int irq, struct irq_desc *desc)
56{
57 s3c_irq_demux_timer(irq, IRQ_TIMER4);
58}
59
60/* We assume the IRQ_TIMER0..IRQ_TIMER4 range is continuous. */
61
62static void s3c_irq_timer_mask(unsigned int irq)
63{
64 u32 reg = __raw_readl(S3C64XX_TINT_CSTAT);
65
66 reg &= 0x1f; /* mask out pending interrupts */
67 reg &= ~(1 << (irq - IRQ_TIMER0));
68 __raw_writel(reg, S3C64XX_TINT_CSTAT);
69}
70
71static void s3c_irq_timer_unmask(unsigned int irq)
72{
73 u32 reg = __raw_readl(S3C64XX_TINT_CSTAT);
74
75 reg &= 0x1f; /* mask out pending interrupts */
76 reg |= 1 << (irq - IRQ_TIMER0);
77 __raw_writel(reg, S3C64XX_TINT_CSTAT);
78}
79
80static void s3c_irq_timer_ack(unsigned int irq)
81{
82 u32 reg = __raw_readl(S3C64XX_TINT_CSTAT);
83
84 reg &= 0x1f;
85 reg |= (1 << 5) << (irq - IRQ_TIMER0);
86 __raw_writel(reg, S3C64XX_TINT_CSTAT);
87}
88
89static struct irq_chip s3c_irq_timer = {
90 .name = "s3c-timer",
91 .mask = s3c_irq_timer_mask,
92 .unmask = s3c_irq_timer_unmask,
93 .ack = s3c_irq_timer_ack,
94};
95
96struct uart_irq { 28struct uart_irq {
97 void __iomem *regs; 29 void __iomem *regs;
98 unsigned int base_irq; 30 unsigned int base_irq;
@@ -227,7 +159,7 @@ static void __init s3c64xx_uart_irq(struct uart_irq *uirq)
227 159
228void __init s3c64xx_init_irq(u32 vic0_valid, u32 vic1_valid) 160void __init s3c64xx_init_irq(u32 vic0_valid, u32 vic1_valid)
229{ 161{
230 int uart, irq; 162 int uart;
231 163
232 printk(KERN_DEBUG "%s: initialising interrupts\n", __func__); 164 printk(KERN_DEBUG "%s: initialising interrupts\n", __func__);
233 165
@@ -237,20 +169,12 @@ void __init s3c64xx_init_irq(u32 vic0_valid, u32 vic1_valid)
237 169
238 /* add the timer sub-irqs */ 170 /* add the timer sub-irqs */
239 171
240 set_irq_chained_handler(IRQ_TIMER0_VIC, s3c_irq_demux_timer0); 172 s3c_init_vic_timer_irq(IRQ_TIMER0_VIC, IRQ_TIMER0);
241 set_irq_chained_handler(IRQ_TIMER1_VIC, s3c_irq_demux_timer1); 173 s3c_init_vic_timer_irq(IRQ_TIMER1_VIC, IRQ_TIMER1);
242 set_irq_chained_handler(IRQ_TIMER2_VIC, s3c_irq_demux_timer2); 174 s3c_init_vic_timer_irq(IRQ_TIMER2_VIC, IRQ_TIMER2);
243 set_irq_chained_handler(IRQ_TIMER3_VIC, s3c_irq_demux_timer3); 175 s3c_init_vic_timer_irq(IRQ_TIMER3_VIC, IRQ_TIMER3);
244 set_irq_chained_handler(IRQ_TIMER4_VIC, s3c_irq_demux_timer4); 176 s3c_init_vic_timer_irq(IRQ_TIMER4_VIC, IRQ_TIMER4);
245
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);
250 }
251 177
252 for (uart = 0; uart < ARRAY_SIZE(uart_irqs); uart++) 178 for (uart = 0; uart < ARRAY_SIZE(uart_irqs); uart++)
253 s3c64xx_uart_irq(&uart_irqs[uart]); 179 s3c64xx_uart_irq(&uart_irqs[uart]);
254} 180}
255
256
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index 9e7daf29b86a..cedecd87d899 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -19,6 +19,13 @@ config SAMSUNG_CLKSRC
19 Select the clock code for the clksrc implementation 19 Select the clock code for the clksrc implementation
20 used by newer systems such as the S3C64XX. 20 used by newer systems such as the S3C64XX.
21 21
22# options for IRQ support
23
24config SAMSUNG_IRQ_VIC_TIMER
25 bool
26 help
27 Internal configuration to build the VIC timer interrupt code.
28
22# options for gpio configuration support 29# options for gpio configuration support
23 30
24config S3C_GPIO_CFG_S3C24XX 31config S3C_GPIO_CFG_S3C24XX
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index 2c0143713ea9..aa048c7337dd 100644
--- a/arch/arm/plat-samsung/Makefile
+++ b/arch/arm/plat-samsung/Makefile
@@ -17,6 +17,8 @@ obj-y += gpio-config.o
17 17
18obj-$(CONFIG_SAMSUNG_CLKSRC) += clock-clksrc.o 18obj-$(CONFIG_SAMSUNG_CLKSRC) += clock-clksrc.o
19 19
20obj-$(CONFIG_SAMSUNG_IRQ_VIC_TIMER) += irq-vic-timer.o
21
20# devices 22# devices
21 23
22obj-$(CONFIG_S3C_DEV_HSMMC) += dev-hsmmc.o 24obj-$(CONFIG_S3C_DEV_HSMMC) += dev-hsmmc.o
diff --git a/arch/arm/plat-samsung/include/plat/irq-vic-timer.h b/arch/arm/plat-samsung/include/plat/irq-vic-timer.h
new file mode 100644
index 000000000000..a90b53431b5b
--- /dev/null
+++ b/arch/arm/plat-samsung/include/plat/irq-vic-timer.h
@@ -0,0 +1,13 @@
1/* arch/arm/plat-samsung/include/plat/irq-vic-timer.h
2 *
3 * Copyright (c) 2010 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * Header file for Samsung SoC IRQ VIC timer
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 version 2 as
10 * published by the Free Software Foundation.
11*/
12
13extern void s3c_init_vic_timer_irq(unsigned int vic, unsigned int timer);
diff --git a/arch/arm/plat-samsung/irq-vic-timer.c b/arch/arm/plat-samsung/irq-vic-timer.c
new file mode 100644
index 000000000000..0270519fcabc
--- /dev/null
+++ b/arch/arm/plat-samsung/irq-vic-timer.c
@@ -0,0 +1,86 @@
1/* arch/arm/plat-samsung/irq-vic-timer.c
2 * originally part of arch/arm/plat-s3c64xx/irq.c
3 *
4 * Copyright 2008 Openmoko, Inc.
5 * Copyright 2008 Simtec Electronics
6 * Ben Dooks <ben@simtec.co.uk>
7 * http://armlinux.simtec.co.uk/
8 *
9 * S3C64XX - Interrupt handling
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 */
15
16#include <linux/kernel.h>
17#include <linux/interrupt.h>
18#include <linux/irq.h>
19#include <linux/io.h>
20
21#include <mach/map.h>
22#include <plat/irq-vic-timer.h>
23#include <plat/regs-timer.h>
24
25static void s3c_irq_demux_vic_timer(unsigned int irq, struct irq_desc *desc)
26{
27 generic_handle_irq((int)desc->handler_data);
28}
29
30/* We assume the IRQ_TIMER0..IRQ_TIMER4 range is continuous. */
31
32static void s3c_irq_timer_mask(unsigned int irq)
33{
34 u32 reg = __raw_readl(S3C64XX_TINT_CSTAT);
35
36 reg &= 0x1f; /* mask out pending interrupts */
37 reg &= ~(1 << (irq - IRQ_TIMER0));
38 __raw_writel(reg, S3C64XX_TINT_CSTAT);
39}
40
41static void s3c_irq_timer_unmask(unsigned int irq)
42{
43 u32 reg = __raw_readl(S3C64XX_TINT_CSTAT);
44
45 reg &= 0x1f; /* mask out pending interrupts */
46 reg |= 1 << (irq - IRQ_TIMER0);
47 __raw_writel(reg, S3C64XX_TINT_CSTAT);
48}
49
50static void s3c_irq_timer_ack(unsigned int irq)
51{
52 u32 reg = __raw_readl(S3C64XX_TINT_CSTAT);
53
54 reg &= 0x1f;
55 reg |= (1 << 5) << (irq - IRQ_TIMER0);
56 __raw_writel(reg, S3C64XX_TINT_CSTAT);
57}
58
59static struct irq_chip s3c_irq_timer = {
60 .name = "s3c-timer",
61 .mask = s3c_irq_timer_mask,
62 .unmask = s3c_irq_timer_unmask,
63 .ack = s3c_irq_timer_ack,
64};
65
66/**
67 * s3c_init_vic_timer_irq() - initialise timer irq chanined off VIC.\
68 * @parent_irq: The parent IRQ on the VIC for the timer.
69 * @timer_irq: The IRQ to be used for the timer.
70 *
71 * Register the necessary IRQ chaining and support for the timer IRQs
72 * chained of the VIC.
73 */
74void __init s3c_init_vic_timer_irq(unsigned int parent_irq,
75 unsigned int timer_irq)
76{
77 struct irq_desc *desc = irq_to_desc(parent_irq);
78
79 set_irq_chained_handler(parent_irq, s3c_irq_demux_vic_timer);
80
81 set_irq_chip(timer_irq, &s3c_irq_timer);
82 set_irq_handler(timer_irq, handle_level_irq);
83 set_irq_flags(timer_irq, IRQF_VALID);
84
85 desc->handler_data = (void *)timer_irq;
86}