diff options
author | Ben Dooks <ben-linux@fluff.org> | 2010-01-12 00:13:58 -0500 |
---|---|---|
committer | Ben Dooks <ben-linux@fluff.org> | 2010-01-15 03:10:16 -0500 |
commit | be97162d47b2e067f9d21097650f2f0405dacc9f (patch) | |
tree | c0389eb759c96354faee38c9d0b607006c9760bb /arch/arm/plat-s5pc1xx | |
parent | 47101ec73901183520de724fb5f9062c014236bb (diff) |
ARM: S5PC1XX: Use common UART IRQ handling code
Use the common UART IRQ handling code for the S5PC100 system.
Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Diffstat (limited to 'arch/arm/plat-s5pc1xx')
-rw-r--r-- | arch/arm/plat-s5pc1xx/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm/plat-s5pc1xx/irq.c | 116 |
2 files changed, 4 insertions, 113 deletions
diff --git a/arch/arm/plat-s5pc1xx/Kconfig b/arch/arm/plat-s5pc1xx/Kconfig index 256f0f9f1ddf..c7ccdf22eefa 100644 --- a/arch/arm/plat-s5pc1xx/Kconfig +++ b/arch/arm/plat-s5pc1xx/Kconfig | |||
@@ -12,6 +12,7 @@ config PLAT_S5PC1XX | |||
12 | select NO_IOPORT | 12 | select NO_IOPORT |
13 | select ARCH_REQUIRE_GPIOLIB | 13 | select ARCH_REQUIRE_GPIOLIB |
14 | select SAMSUNG_CLKSRC | 14 | select SAMSUNG_CLKSRC |
15 | select SAMSUNG_IRQ_UART | ||
15 | select SAMSUNG_IRQ_VIC_TIMER | 16 | select SAMSUNG_IRQ_VIC_TIMER |
16 | select S3C_GPIO_TRACK | 17 | select S3C_GPIO_TRACK |
17 | select S3C_GPIO_PULL_UPDOWN | 18 | select S3C_GPIO_PULL_UPDOWN |
diff --git a/arch/arm/plat-s5pc1xx/irq.c b/arch/arm/plat-s5pc1xx/irq.c index ae233bdeb7e2..bfc524827819 100644 --- a/arch/arm/plat-s5pc1xx/irq.c +++ b/arch/arm/plat-s5pc1xx/irq.c | |||
@@ -21,18 +21,13 @@ | |||
21 | 21 | ||
22 | #include <mach/map.h> | 22 | #include <mach/map.h> |
23 | #include <plat/irq-vic-timer.h> | 23 | #include <plat/irq-vic-timer.h> |
24 | #include <plat/irq-uart.h> | ||
24 | #include <plat/cpu.h> | 25 | #include <plat/cpu.h> |
25 | 26 | ||
26 | struct uart_irq { | ||
27 | void __iomem *regs; | ||
28 | unsigned int base_irq; | ||
29 | unsigned int parent_irq; | ||
30 | }; | ||
31 | |||
32 | /* Note, we make use of the fact that the parent IRQs, IRQ_UART[0..3] | 27 | /* Note, we make use of the fact that the parent IRQs, IRQ_UART[0..3] |
33 | * are consecutive when looking up the interrupt in the demux routines. | 28 | * are consecutive when looking up the interrupt in the demux routines. |
34 | */ | 29 | */ |
35 | static struct uart_irq uart_irqs[] = { | 30 | static struct s3c_uart_irq uart_irqs[] = { |
36 | [0] = { | 31 | [0] = { |
37 | .regs = (void *)S3C_VA_UART0, | 32 | .regs = (void *)S3C_VA_UART0, |
38 | .base_irq = IRQ_S3CUART_BASE0, | 33 | .base_irq = IRQ_S3CUART_BASE0, |
@@ -55,113 +50,9 @@ static struct uart_irq uart_irqs[] = { | |||
55 | }, | 50 | }, |
56 | }; | 51 | }; |
57 | 52 | ||
58 | static inline void __iomem *s3c_irq_uart_base(unsigned int irq) | ||
59 | { | ||
60 | struct uart_irq *uirq = get_irq_chip_data(irq); | ||
61 | return uirq->regs; | ||
62 | } | ||
63 | |||
64 | static inline unsigned int s3c_irq_uart_bit(unsigned int irq) | ||
65 | { | ||
66 | return irq & 3; | ||
67 | } | ||
68 | |||
69 | /* UART interrupt registers, not worth adding to seperate include header */ | ||
70 | #define S3C64XX_UINTP 0x30 | ||
71 | #define S3C64XX_UINTSP 0x34 | ||
72 | #define S3C64XX_UINTM 0x38 | ||
73 | |||
74 | static void s3c_irq_uart_mask(unsigned int irq) | ||
75 | { | ||
76 | void __iomem *regs = s3c_irq_uart_base(irq); | ||
77 | unsigned int bit = s3c_irq_uart_bit(irq); | ||
78 | u32 reg; | ||
79 | |||
80 | reg = __raw_readl(regs + S3C64XX_UINTM); | ||
81 | reg |= (1 << bit); | ||
82 | __raw_writel(reg, regs + S3C64XX_UINTM); | ||
83 | } | ||
84 | |||
85 | static void s3c_irq_uart_maskack(unsigned int irq) | ||
86 | { | ||
87 | void __iomem *regs = s3c_irq_uart_base(irq); | ||
88 | unsigned int bit = s3c_irq_uart_bit(irq); | ||
89 | u32 reg; | ||
90 | |||
91 | reg = __raw_readl(regs + S3C64XX_UINTM); | ||
92 | reg |= (1 << bit); | ||
93 | __raw_writel(reg, regs + S3C64XX_UINTM); | ||
94 | __raw_writel(1 << bit, regs + S3C64XX_UINTP); | ||
95 | } | ||
96 | |||
97 | static void s3c_irq_uart_unmask(unsigned int irq) | ||
98 | { | ||
99 | void __iomem *regs = s3c_irq_uart_base(irq); | ||
100 | unsigned int bit = s3c_irq_uart_bit(irq); | ||
101 | u32 reg; | ||
102 | |||
103 | reg = __raw_readl(regs + S3C64XX_UINTM); | ||
104 | reg &= ~(1 << bit); | ||
105 | __raw_writel(reg, regs + S3C64XX_UINTM); | ||
106 | } | ||
107 | |||
108 | static void s3c_irq_uart_ack(unsigned int irq) | ||
109 | { | ||
110 | void __iomem *regs = s3c_irq_uart_base(irq); | ||
111 | unsigned int bit = s3c_irq_uart_bit(irq); | ||
112 | |||
113 | __raw_writel(1 << bit, regs + S3C64XX_UINTP); | ||
114 | } | ||
115 | |||
116 | static void s3c_irq_demux_uart(unsigned int irq, struct irq_desc *desc) | ||
117 | { | ||
118 | struct uart_irq *uirq = &uart_irqs[irq - IRQ_UART0]; | ||
119 | u32 pend = __raw_readl(uirq->regs + S3C64XX_UINTP); | ||
120 | int base = uirq->base_irq; | ||
121 | |||
122 | if (pend & (1 << 0)) | ||
123 | generic_handle_irq(base); | ||
124 | if (pend & (1 << 1)) | ||
125 | generic_handle_irq(base + 1); | ||
126 | if (pend & (1 << 2)) | ||
127 | generic_handle_irq(base + 2); | ||
128 | if (pend & (1 << 3)) | ||
129 | generic_handle_irq(base + 3); | ||
130 | } | ||
131 | |||
132 | static struct irq_chip s3c_irq_uart = { | ||
133 | .name = "s3c-uart", | ||
134 | .mask = s3c_irq_uart_mask, | ||
135 | .unmask = s3c_irq_uart_unmask, | ||
136 | .mask_ack = s3c_irq_uart_maskack, | ||
137 | .ack = s3c_irq_uart_ack, | ||
138 | }; | ||
139 | |||
140 | static void __init s5pc1xx_uart_irq(struct uart_irq *uirq) | ||
141 | { | ||
142 | void __iomem *reg_base = uirq->regs; | ||
143 | unsigned int irq; | ||
144 | int offs; | ||
145 | |||
146 | /* mask all interrupts at the start. */ | ||
147 | __raw_writel(0xf, reg_base + S3C64XX_UINTM); | ||
148 | |||
149 | for (offs = 0; offs < 3; offs++) { | ||
150 | irq = uirq->base_irq + offs; | ||
151 | |||
152 | set_irq_chip(irq, &s3c_irq_uart); | ||
153 | set_irq_chip_data(irq, uirq); | ||
154 | set_irq_handler(irq, handle_level_irq); | ||
155 | set_irq_flags(irq, IRQF_VALID); | ||
156 | } | ||
157 | |||
158 | set_irq_chained_handler(uirq->parent_irq, s3c_irq_demux_uart); | ||
159 | } | ||
160 | |||
161 | void __init s5pc1xx_init_irq(u32 *vic_valid, int num) | 53 | void __init s5pc1xx_init_irq(u32 *vic_valid, int num) |
162 | { | 54 | { |
163 | int i; | 55 | int i; |
164 | int uart; | ||
165 | 56 | ||
166 | printk(KERN_DEBUG "%s: initialising interrupts\n", __func__); | 57 | printk(KERN_DEBUG "%s: initialising interrupts\n", __func__); |
167 | 58 | ||
@@ -178,8 +69,7 @@ void __init s5pc1xx_init_irq(u32 *vic_valid, int num) | |||
178 | s3c_init_vic_timer_irq(IRQ_TIMER3_VIC, IRQ_TIMER3); | 69 | s3c_init_vic_timer_irq(IRQ_TIMER3_VIC, IRQ_TIMER3); |
179 | s3c_init_vic_timer_irq(IRQ_TIMER4_VIC, IRQ_TIMER4); | 70 | s3c_init_vic_timer_irq(IRQ_TIMER4_VIC, IRQ_TIMER4); |
180 | 71 | ||
181 | for (uart = 0; uart < ARRAY_SIZE(uart_irqs); uart++) | 72 | s3c_init_uart_irqs(uart_irqs, ARRAY_SIZE(uart_irqs)); |
182 | s5pc1xx_uart_irq(&uart_irqs[uart]); | ||
183 | } | 73 | } |
184 | 74 | ||
185 | 75 | ||