aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-s5pc100
diff options
context:
space:
mode:
authorJoonyoung Shim <jy0922.shim@samsung.com>2010-09-30 22:18:05 -0400
committerKukjin Kim <kgene.kim@samsung.com>2010-10-20 18:54:57 -0400
commit7e47935bb7190cd4bbc6fa4023b64b4785a2bcdc (patch)
tree47a8137ef0a4eb06835b9a6a9d01e84adc3d4470 /arch/arm/mach-s5pc100
parent5fdc97b5d95aa8175c085545a4c37bccd45dd950 (diff)
ARM: S5PC100: Use generic S5P GPIO Interrupt interface
S5PC100 SoC can use common S5P GPIO interrupt code. This patch removes specific S5PC100 gpio interrupts code and adds required defines and code to make use of common S5P code. Signed-off-by: Joonyoung Shim <jy0922.shim@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
Diffstat (limited to 'arch/arm/mach-s5pc100')
-rw-r--r--arch/arm/mach-s5pc100/Makefile2
-rw-r--r--arch/arm/mach-s5pc100/gpiolib.c45
-rw-r--r--arch/arm/mach-s5pc100/include/mach/irqs.h9
-rw-r--r--arch/arm/mach-s5pc100/irq-gpio.c266
4 files changed, 17 insertions, 305 deletions
diff --git a/arch/arm/mach-s5pc100/Makefile b/arch/arm/mach-s5pc100/Makefile
index a021ed1fb4b6..eecab57d2e5d 100644
--- a/arch/arm/mach-s5pc100/Makefile
+++ b/arch/arm/mach-s5pc100/Makefile
@@ -11,7 +11,7 @@ obj- :=
11 11
12# Core support for S5PC100 system 12# Core support for S5PC100 system
13 13
14obj-$(CONFIG_CPU_S5PC100) += cpu.o init.o clock.o gpiolib.o irq-gpio.o 14obj-$(CONFIG_CPU_S5PC100) += cpu.o init.o clock.o gpiolib.o
15obj-$(CONFIG_CPU_S5PC100) += setup-i2c0.o 15obj-$(CONFIG_CPU_S5PC100) += setup-i2c0.o
16obj-$(CONFIG_CPU_S5PC100) += dma.o 16obj-$(CONFIG_CPU_S5PC100) += dma.o
17 17
diff --git a/arch/arm/mach-s5pc100/gpiolib.c b/arch/arm/mach-s5pc100/gpiolib.c
index 0fab7f2cd8bf..5811578ad4e4 100644
--- a/arch/arm/mach-s5pc100/gpiolib.c
+++ b/arch/arm/mach-s5pc100/gpiolib.c
@@ -61,11 +61,6 @@
61 * L3 8 4Bit None 61 * L3 8 4Bit None
62 */ 62 */
63 63
64static int s5pc100_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
65{
66 return S3C_IRQ_GPIO(chip->base + offset);
67}
68
69static int s5pc100_gpiolib_to_eint(struct gpio_chip *chip, unsigned int offset) 64static int s5pc100_gpiolib_to_eint(struct gpio_chip *chip, unsigned int offset)
70{ 65{
71 int base; 66 int base;
@@ -232,6 +227,7 @@ static struct s3c_gpio_chip s5pc100_gpio_chips[] = {
232 .base = S5PC100_GPH0(0), 227 .base = S5PC100_GPH0(0),
233 .ngpio = S5PC100_GPIO_H0_NR, 228 .ngpio = S5PC100_GPIO_H0_NR,
234 .label = "GPH0", 229 .label = "GPH0",
230 .to_irq = s5pc100_gpiolib_to_eint,
235 }, 231 },
236 }, { 232 }, {
237 .base = S5PC100_GPH1_BASE, 233 .base = S5PC100_GPH1_BASE,
@@ -240,6 +236,7 @@ static struct s3c_gpio_chip s5pc100_gpio_chips[] = {
240 .base = S5PC100_GPH1(0), 236 .base = S5PC100_GPH1(0),
241 .ngpio = S5PC100_GPIO_H1_NR, 237 .ngpio = S5PC100_GPIO_H1_NR,
242 .label = "GPH1", 238 .label = "GPH1",
239 .to_irq = s5pc100_gpiolib_to_eint,
243 }, 240 },
244 }, { 241 }, {
245 .base = S5PC100_GPH2_BASE, 242 .base = S5PC100_GPH2_BASE,
@@ -248,6 +245,7 @@ static struct s3c_gpio_chip s5pc100_gpio_chips[] = {
248 .base = S5PC100_GPH2(0), 245 .base = S5PC100_GPH2(0),
249 .ngpio = S5PC100_GPIO_H2_NR, 246 .ngpio = S5PC100_GPIO_H2_NR,
250 .label = "GPH2", 247 .label = "GPH2",
248 .to_irq = s5pc100_gpiolib_to_eint,
251 }, 249 },
252 }, { 250 }, {
253 .base = S5PC100_GPH3_BASE, 251 .base = S5PC100_GPH3_BASE,
@@ -256,6 +254,7 @@ static struct s3c_gpio_chip s5pc100_gpio_chips[] = {
256 .base = S5PC100_GPH3(0), 254 .base = S5PC100_GPH3(0),
257 .ngpio = S5PC100_GPIO_H3_NR, 255 .ngpio = S5PC100_GPIO_H3_NR,
258 .label = "GPH3", 256 .label = "GPH3",
257 .to_irq = s5pc100_gpiolib_to_eint,
259 }, 258 },
260 }, { 259 }, {
261 .base = S5PC100_GPI_BASE, 260 .base = S5PC100_GPI_BASE,
@@ -380,47 +379,25 @@ static struct s3c_gpio_chip s5pc100_gpio_chips[] = {
380 }, 379 },
381}; 380};
382 381
383/* FIXME move from irq-gpio.c */
384extern struct irq_chip s5pc100_gpioint;
385extern void s5pc100_irq_gpioint_handler(unsigned int irq, struct irq_desc *desc);
386
387static __init void s5pc100_gpiolib_link(struct s3c_gpio_chip *chip)
388{
389 /* Interrupt */
390 if (chip->config == &gpio_cfg) {
391 int i, irq;
392
393 chip->chip.to_irq = s5pc100_gpiolib_to_irq;
394
395 for (i = 0; i < chip->chip.ngpio; i++) {
396 irq = S3C_IRQ_GPIO_BASE + chip->chip.base + i;
397 set_irq_chip(irq, &s5pc100_gpioint);
398 set_irq_data(irq, &chip->chip);
399 set_irq_handler(irq, handle_level_irq);
400 set_irq_flags(irq, IRQF_VALID);
401 }
402 } else if (chip->config == &gpio_cfg_eint) {
403 chip->chip.to_irq = s5pc100_gpiolib_to_eint;
404 }
405}
406
407static __init int s5pc100_gpiolib_init(void) 382static __init int s5pc100_gpiolib_init(void)
408{ 383{
409 struct s3c_gpio_chip *chip; 384 struct s3c_gpio_chip *chip;
410 int nr_chips; 385 int nr_chips;
386 int gpioint_group = 0;
411 387
412 chip = s5pc100_gpio_chips; 388 chip = s5pc100_gpio_chips;
413 nr_chips = ARRAY_SIZE(s5pc100_gpio_chips); 389 nr_chips = ARRAY_SIZE(s5pc100_gpio_chips);
414 390
415 for (; nr_chips > 0; nr_chips--, chip++) 391 for (; nr_chips > 0; nr_chips--, chip++) {
416 s5pc100_gpiolib_link(chip); 392 if (chip->config == &gpio_cfg) {
393 /* gpio interrupts */
394 chip->group = gpioint_group++;
395 }
396 }
417 397
418 samsung_gpiolib_add_4bit_chips(s5pc100_gpio_chips, 398 samsung_gpiolib_add_4bit_chips(s5pc100_gpio_chips,
419 ARRAY_SIZE(s5pc100_gpio_chips)); 399 ARRAY_SIZE(s5pc100_gpio_chips));
420 400
421 /* Interrupt */
422 set_irq_chained_handler(IRQ_GPIOINT, s5pc100_irq_gpioint_handler);
423
424 return 0; 401 return 0;
425} 402}
426core_initcall(s5pc100_gpiolib_init); 403core_initcall(s5pc100_gpiolib_init);
diff --git a/arch/arm/mach-s5pc100/include/mach/irqs.h b/arch/arm/mach-s5pc100/include/mach/irqs.h
index 06513e647242..e782dd6bcf60 100644
--- a/arch/arm/mach-s5pc100/include/mach/irqs.h
+++ b/arch/arm/mach-s5pc100/include/mach/irqs.h
@@ -100,11 +100,12 @@
100#define S5P_EINT_BASE1 (S5P_IRQ_VIC0(0)) 100#define S5P_EINT_BASE1 (S5P_IRQ_VIC0(0))
101#define S5P_EINT_BASE2 (IRQ_VIC_END + 1) 101#define S5P_EINT_BASE2 (IRQ_VIC_END + 1)
102 102
103#define S3C_IRQ_GPIO_BASE (IRQ_EINT(31) + 1) 103/* GPIO interrupt */
104#define S3C_IRQ_GPIO(x) (S3C_IRQ_GPIO_BASE + (x)) 104#define S5P_GPIOINT_BASE (IRQ_EINT(31) + 1)
105#define S5P_GPIOINT_GROUP_MAXNR 21
105 106
106/* Until MP04 Groups -> 40 (exactly 39) Groups * 8 ~= 320 GPIOs */ 107/* Set the default NR_IRQS */
107#define NR_IRQS (S3C_IRQ_GPIO(320) + 1) 108#define NR_IRQS (IRQ_EINT(31) + S5P_GPIOINT_COUNT + 1)
108 109
109/* Compatibility */ 110/* Compatibility */
110#define IRQ_LCD_FIFO IRQ_LCD0 111#define IRQ_LCD_FIFO IRQ_LCD0
diff --git a/arch/arm/mach-s5pc100/irq-gpio.c b/arch/arm/mach-s5pc100/irq-gpio.c
deleted file mode 100644
index 2bf86c18bc73..000000000000
--- a/arch/arm/mach-s5pc100/irq-gpio.c
+++ /dev/null
@@ -1,266 +0,0 @@
1/*
2 * arch/arm/mach-s5pc100/irq-gpio.c
3 *
4 * Copyright (C) 2009 Samsung Electronics
5 *
6 * S5PC100 - Interrupt handling for IRQ_GPIO${group}(x)
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#include <linux/kernel.h>
14#include <linux/interrupt.h>
15#include <linux/irq.h>
16#include <linux/io.h>
17#include <linux/gpio.h>
18
19#include <mach/map.h>
20#include <plat/gpio-cfg.h>
21
22#define S5P_GPIOREG(x) (S5P_VA_GPIO + (x))
23
24#define CON_OFFSET 0x700
25#define MASK_OFFSET 0x900
26#define PEND_OFFSET 0xA00
27#define CON_OFFSET_2 0xE00
28#define MASK_OFFSET_2 0xF00
29#define PEND_OFFSET_2 0xF40
30
31#define GPIOINT_LEVEL_LOW 0x0
32#define GPIOINT_LEVEL_HIGH 0x1
33#define GPIOINT_EDGE_FALLING 0x2
34#define GPIOINT_EDGE_RISING 0x3
35#define GPIOINT_EDGE_BOTH 0x4
36
37static int group_to_con_offset(int group)
38{
39 return group << 2;
40}
41
42static int group_to_mask_offset(int group)
43{
44 return group << 2;
45}
46
47static int group_to_pend_offset(int group)
48{
49 return group << 2;
50}
51
52static int s5pc100_get_start(unsigned int group)
53{
54 switch (group) {
55 case 0: return S5PC100_GPIO_A0_START;
56 case 1: return S5PC100_GPIO_A1_START;
57 case 2: return S5PC100_GPIO_B_START;
58 case 3: return S5PC100_GPIO_C_START;
59 case 4: return S5PC100_GPIO_D_START;
60 case 5: return S5PC100_GPIO_E0_START;
61 case 6: return S5PC100_GPIO_E1_START;
62 case 7: return S5PC100_GPIO_F0_START;
63 case 8: return S5PC100_GPIO_F1_START;
64 case 9: return S5PC100_GPIO_F2_START;
65 case 10: return S5PC100_GPIO_F3_START;
66 case 11: return S5PC100_GPIO_G0_START;
67 case 12: return S5PC100_GPIO_G1_START;
68 case 13: return S5PC100_GPIO_G2_START;
69 case 14: return S5PC100_GPIO_G3_START;
70 case 15: return S5PC100_GPIO_I_START;
71 case 16: return S5PC100_GPIO_J0_START;
72 case 17: return S5PC100_GPIO_J1_START;
73 case 18: return S5PC100_GPIO_J2_START;
74 case 19: return S5PC100_GPIO_J3_START;
75 case 20: return S5PC100_GPIO_J4_START;
76 default:
77 BUG();
78 }
79
80 return -EINVAL;
81}
82
83static int s5pc100_get_group(unsigned int irq)
84{
85 irq -= S3C_IRQ_GPIO(0);
86
87 switch (irq) {
88 case S5PC100_GPIO_A0_START ... S5PC100_GPIO_A1_START - 1:
89 return 0;
90 case S5PC100_GPIO_A1_START ... S5PC100_GPIO_B_START - 1:
91 return 1;
92 case S5PC100_GPIO_B_START ... S5PC100_GPIO_C_START - 1:
93 return 2;
94 case S5PC100_GPIO_C_START ... S5PC100_GPIO_D_START - 1:
95 return 3;
96 case S5PC100_GPIO_D_START ... S5PC100_GPIO_E0_START - 1:
97 return 4;
98 case S5PC100_GPIO_E0_START ... S5PC100_GPIO_E1_START - 1:
99 return 5;
100 case S5PC100_GPIO_E1_START ... S5PC100_GPIO_F0_START - 1:
101 return 6;
102 case S5PC100_GPIO_F0_START ... S5PC100_GPIO_F1_START - 1:
103 return 7;
104 case S5PC100_GPIO_F1_START ... S5PC100_GPIO_F2_START - 1:
105 return 8;
106 case S5PC100_GPIO_F2_START ... S5PC100_GPIO_F3_START - 1:
107 return 9;
108 case S5PC100_GPIO_F3_START ... S5PC100_GPIO_G0_START - 1:
109 return 10;
110 case S5PC100_GPIO_G0_START ... S5PC100_GPIO_G1_START - 1:
111 return 11;
112 case S5PC100_GPIO_G1_START ... S5PC100_GPIO_G2_START - 1:
113 return 12;
114 case S5PC100_GPIO_G2_START ... S5PC100_GPIO_G3_START - 1:
115 return 13;
116 case S5PC100_GPIO_G3_START ... S5PC100_GPIO_H0_START - 1:
117 return 14;
118 case S5PC100_GPIO_I_START ... S5PC100_GPIO_J0_START - 1:
119 return 15;
120 case S5PC100_GPIO_J0_START ... S5PC100_GPIO_J1_START - 1:
121 return 16;
122 case S5PC100_GPIO_J1_START ... S5PC100_GPIO_J2_START - 1:
123 return 17;
124 case S5PC100_GPIO_J2_START ... S5PC100_GPIO_J3_START - 1:
125 return 18;
126 case S5PC100_GPIO_J3_START ... S5PC100_GPIO_J4_START - 1:
127 return 19;
128 case S5PC100_GPIO_J4_START ... S5PC100_GPIO_K0_START - 1:
129 return 20;
130 default:
131 BUG();
132 }
133
134 return -EINVAL;
135}
136
137static int s5pc100_get_offset(unsigned int irq)
138{
139 struct gpio_chip *chip = get_irq_data(irq);
140 return irq - S3C_IRQ_GPIO(chip->base);
141}
142
143static void s5pc100_gpioint_ack(unsigned int irq)
144{
145 int group, offset, pend_offset;
146 unsigned int value;
147
148 group = s5pc100_get_group(irq);
149 offset = s5pc100_get_offset(irq);
150 pend_offset = group_to_pend_offset(group);
151
152 value = __raw_readl(S5P_GPIOREG(PEND_OFFSET) + pend_offset);
153 value |= 1 << offset;
154 __raw_writel(value, S5P_GPIOREG(PEND_OFFSET) + pend_offset);
155}
156
157static void s5pc100_gpioint_mask(unsigned int irq)
158{
159 int group, offset, mask_offset;
160 unsigned int value;
161
162 group = s5pc100_get_group(irq);
163 offset = s5pc100_get_offset(irq);
164 mask_offset = group_to_mask_offset(group);
165
166 value = __raw_readl(S5P_GPIOREG(MASK_OFFSET) + mask_offset);
167 value |= 1 << offset;
168 __raw_writel(value, S5P_GPIOREG(MASK_OFFSET) + mask_offset);
169}
170
171static void s5pc100_gpioint_unmask(unsigned int irq)
172{
173 int group, offset, mask_offset;
174 unsigned int value;
175
176 group = s5pc100_get_group(irq);
177 offset = s5pc100_get_offset(irq);
178 mask_offset = group_to_mask_offset(group);
179
180 value = __raw_readl(S5P_GPIOREG(MASK_OFFSET) + mask_offset);
181 value &= ~(1 << offset);
182 __raw_writel(value, S5P_GPIOREG(MASK_OFFSET) + mask_offset);
183}
184
185static void s5pc100_gpioint_mask_ack(unsigned int irq)
186{
187 s5pc100_gpioint_mask(irq);
188 s5pc100_gpioint_ack(irq);
189}
190
191static int s5pc100_gpioint_set_type(unsigned int irq, unsigned int type)
192{
193 int group, offset, con_offset;
194 unsigned int value;
195
196 group = s5pc100_get_group(irq);
197 offset = s5pc100_get_offset(irq);
198 con_offset = group_to_con_offset(group);
199
200 switch (type) {
201 case IRQ_TYPE_NONE:
202 printk(KERN_WARNING "No irq type\n");
203 return -EINVAL;
204 case IRQ_TYPE_EDGE_RISING:
205 type = GPIOINT_EDGE_RISING;
206 break;
207 case IRQ_TYPE_EDGE_FALLING:
208 type = GPIOINT_EDGE_FALLING;
209 break;
210 case IRQ_TYPE_EDGE_BOTH:
211 type = GPIOINT_EDGE_BOTH;
212 break;
213 case IRQ_TYPE_LEVEL_HIGH:
214 type = GPIOINT_LEVEL_HIGH;
215 break;
216 case IRQ_TYPE_LEVEL_LOW:
217 type = GPIOINT_LEVEL_LOW;
218 break;
219 default:
220 BUG();
221 }
222
223
224 value = __raw_readl(S5P_GPIOREG(CON_OFFSET) + con_offset);
225 value &= ~(0xf << (offset * 0x4));
226 value |= (type << (offset * 0x4));
227 __raw_writel(value, S5P_GPIOREG(CON_OFFSET) + con_offset);
228
229 return 0;
230}
231
232struct irq_chip s5pc100_gpioint = {
233 .name = "GPIO",
234 .ack = s5pc100_gpioint_ack,
235 .mask = s5pc100_gpioint_mask,
236 .mask_ack = s5pc100_gpioint_mask_ack,
237 .unmask = s5pc100_gpioint_unmask,
238 .set_type = s5pc100_gpioint_set_type,
239};
240
241void s5pc100_irq_gpioint_handler(unsigned int irq, struct irq_desc *desc)
242{
243 int group, offset, pend_offset, mask_offset;
244 int real_irq, group_end;
245 unsigned int pend, mask;
246
247 group_end = 21;
248
249 for (group = 0; group < group_end; group++) {
250 pend_offset = group_to_pend_offset(group);
251 pend = __raw_readl(S5P_GPIOREG(PEND_OFFSET) + pend_offset);
252 if (!pend)
253 continue;
254
255 mask_offset = group_to_mask_offset(group);
256 mask = __raw_readl(S5P_GPIOREG(MASK_OFFSET) + mask_offset);
257 pend &= ~mask;
258
259 for (offset = 0; offset < 8; offset++) {
260 if (pend & (1 << offset)) {
261 real_irq = s5pc100_get_start(group) + offset;
262 generic_handle_irq(S3C_IRQ_GPIO(real_irq));
263 }
264 }
265 }
266}