diff options
-rw-r--r-- | arch/arm/plat-s3c64xx/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm/plat-s3c64xx/irq.c | 90 | ||||
-rw-r--r-- | arch/arm/plat-samsung/Kconfig | 7 | ||||
-rw-r--r-- | arch/arm/plat-samsung/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/plat-samsung/include/plat/irq-vic-timer.h | 13 | ||||
-rw-r--r-- | arch/arm/plat-samsung/irq-vic-timer.c | 86 |
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 | |||
30 | static void s3c_irq_demux_timer(unsigned int base_irq, unsigned int sub_irq) | ||
31 | { | ||
32 | generic_handle_irq(sub_irq); | ||
33 | } | ||
34 | |||
35 | static void s3c_irq_demux_timer0(unsigned int irq, struct irq_desc *desc) | ||
36 | { | ||
37 | s3c_irq_demux_timer(irq, IRQ_TIMER0); | ||
38 | } | ||
39 | |||
40 | static void s3c_irq_demux_timer1(unsigned int irq, struct irq_desc *desc) | ||
41 | { | ||
42 | s3c_irq_demux_timer(irq, IRQ_TIMER1); | ||
43 | } | ||
44 | |||
45 | static void s3c_irq_demux_timer2(unsigned int irq, struct irq_desc *desc) | ||
46 | { | ||
47 | s3c_irq_demux_timer(irq, IRQ_TIMER2); | ||
48 | } | ||
49 | |||
50 | static void s3c_irq_demux_timer3(unsigned int irq, struct irq_desc *desc) | ||
51 | { | ||
52 | s3c_irq_demux_timer(irq, IRQ_TIMER3); | ||
53 | } | ||
54 | |||
55 | static 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 | |||
62 | static 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 | |||
71 | static 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 | |||
80 | static 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 | |||
89 | static 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 | |||
96 | struct uart_irq { | 28 | struct 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 | ||
228 | void __init s3c64xx_init_irq(u32 vic0_valid, u32 vic1_valid) | 160 | void __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 | |||
24 | config 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 | ||
24 | config S3C_GPIO_CFG_S3C24XX | 31 | config 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 | ||
18 | obj-$(CONFIG_SAMSUNG_CLKSRC) += clock-clksrc.o | 18 | obj-$(CONFIG_SAMSUNG_CLKSRC) += clock-clksrc.o |
19 | 19 | ||
20 | obj-$(CONFIG_SAMSUNG_IRQ_VIC_TIMER) += irq-vic-timer.o | ||
21 | |||
20 | # devices | 22 | # devices |
21 | 23 | ||
22 | obj-$(CONFIG_S3C_DEV_HSMMC) += dev-hsmmc.o | 24 | obj-$(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 | |||
13 | extern 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 | |||
25 | static 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 | |||
32 | static 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 | |||
41 | static 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 | |||
50 | static 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 | |||
59 | static 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 | */ | ||
74 | void __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 | } | ||