diff options
Diffstat (limited to 'arch/arm/mach-s5pc100')
-rw-r--r-- | arch/arm/mach-s5pc100/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/mach-s5pc100/gpiolib.c | 45 | ||||
-rw-r--r-- | arch/arm/mach-s5pc100/include/mach/irqs.h | 9 | ||||
-rw-r--r-- | arch/arm/mach-s5pc100/irq-gpio.c | 266 |
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 | ||
14 | obj-$(CONFIG_CPU_S5PC100) += cpu.o init.o clock.o gpiolib.o irq-gpio.o | 14 | obj-$(CONFIG_CPU_S5PC100) += cpu.o init.o clock.o gpiolib.o |
15 | obj-$(CONFIG_CPU_S5PC100) += setup-i2c0.o | 15 | obj-$(CONFIG_CPU_S5PC100) += setup-i2c0.o |
16 | obj-$(CONFIG_CPU_S5PC100) += dma.o | 16 | obj-$(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 | ||
64 | static int s5pc100_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset) | ||
65 | { | ||
66 | return S3C_IRQ_GPIO(chip->base + offset); | ||
67 | } | ||
68 | |||
69 | static int s5pc100_gpiolib_to_eint(struct gpio_chip *chip, unsigned int offset) | 64 | static 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 */ | ||
384 | extern struct irq_chip s5pc100_gpioint; | ||
385 | extern void s5pc100_irq_gpioint_handler(unsigned int irq, struct irq_desc *desc); | ||
386 | |||
387 | static __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 | |||
407 | static __init int s5pc100_gpiolib_init(void) | 382 | static __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 | } |
426 | core_initcall(s5pc100_gpiolib_init); | 403 | core_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 | |||
37 | static int group_to_con_offset(int group) | ||
38 | { | ||
39 | return group << 2; | ||
40 | } | ||
41 | |||
42 | static int group_to_mask_offset(int group) | ||
43 | { | ||
44 | return group << 2; | ||
45 | } | ||
46 | |||
47 | static int group_to_pend_offset(int group) | ||
48 | { | ||
49 | return group << 2; | ||
50 | } | ||
51 | |||
52 | static 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 | |||
83 | static 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 | |||
137 | static 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 | |||
143 | static 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 | |||
157 | static 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 | |||
171 | static 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 | |||
185 | static void s5pc100_gpioint_mask_ack(unsigned int irq) | ||
186 | { | ||
187 | s5pc100_gpioint_mask(irq); | ||
188 | s5pc100_gpioint_ack(irq); | ||
189 | } | ||
190 | |||
191 | static 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 | |||
232 | struct 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 | |||
241 | void 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 | } | ||