blob: 5811578ad4e439bf9e74ecc50c63dc9e8ef2dbe3 [file] [log] [blame]
Kyungmin Parkb0d52172009-11-17 08:41:16 +01001/*
Marek Szyprowskiacc84702010-05-20 07:51:08 +02002 * arch/arm/plat-s5pc100/gpiolib.c
Kyungmin Parkb0d52172009-11-17 08:41:16 +01003 *
4 * Copyright 2009 Samsung Electronics Co
5 * Kyungmin Park <kyungmin.park@samsung.com>
6 *
Marek Szyprowskiacc84702010-05-20 07:51:08 +02007 * S5PC100 - GPIOlib support
Kyungmin Parkb0d52172009-11-17 08:41:16 +01008 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/kernel.h>
15#include <linux/irq.h>
16#include <linux/io.h>
17#include <linux/gpio.h>
18
19#include <mach/map.h>
Marek Szyprowski79044492010-05-18 12:38:41 +020020#include <mach/regs-gpio.h>
Kyungmin Parkb0d52172009-11-17 08:41:16 +010021
Ben Dookse856bb12010-01-19 17:14:46 +090022#include <plat/gpio-core.h>
Kyungmin Parkb0d52172009-11-17 08:41:16 +010023#include <plat/gpio-cfg.h>
24#include <plat/gpio-cfg-helpers.h>
Kyungmin Parkb0d52172009-11-17 08:41:16 +010025
26/* S5PC100 GPIO bank summary:
27 *
28 * Bank GPIOs Style INT Type
29 * A0 8 4Bit GPIO_INT0
30 * A1 5 4Bit GPIO_INT1
31 * B 8 4Bit GPIO_INT2
32 * C 5 4Bit GPIO_INT3
33 * D 7 4Bit GPIO_INT4
34 * E0 8 4Bit GPIO_INT5
35 * E1 6 4Bit GPIO_INT6
36 * F0 8 4Bit GPIO_INT7
37 * F1 8 4Bit GPIO_INT8
38 * F2 8 4Bit GPIO_INT9
39 * F3 4 4Bit GPIO_INT10
40 * G0 8 4Bit GPIO_INT11
41 * G1 3 4Bit GPIO_INT12
42 * G2 7 4Bit GPIO_INT13
43 * G3 7 4Bit GPIO_INT14
44 * H0 8 4Bit WKUP_INT
45 * H1 8 4Bit WKUP_INT
46 * H2 8 4Bit WKUP_INT
47 * H3 8 4Bit WKUP_INT
48 * I 8 4Bit GPIO_INT15
49 * J0 8 4Bit GPIO_INT16
50 * J1 5 4Bit GPIO_INT17
51 * J2 8 4Bit GPIO_INT18
52 * J3 8 4Bit GPIO_INT19
53 * J4 4 4Bit GPIO_INT20
54 * K0 8 4Bit None
55 * K1 6 4Bit None
56 * K2 8 4Bit None
57 * K3 8 4Bit None
58 * L0 8 4Bit None
59 * L1 8 4Bit None
60 * L2 8 4Bit None
61 * L3 8 4Bit None
62 */
63
Marek Szyprowskiacc84702010-05-20 07:51:08 +020064static int s5pc100_gpiolib_to_eint(struct gpio_chip *chip, unsigned int offset)
Kyungmin Parkb0d52172009-11-17 08:41:16 +010065{
66 int base;
67
68 base = chip->base - S5PC100_GPH0(0);
69 if (base == 0)
70 return IRQ_EINT(offset);
71 base = chip->base - S5PC100_GPH1(0);
72 if (base == 0)
73 return IRQ_EINT(8 + offset);
74 base = chip->base - S5PC100_GPH2(0);
75 if (base == 0)
76 return IRQ_EINT(16 + offset);
77 base = chip->base - S5PC100_GPH3(0);
78 if (base == 0)
79 return IRQ_EINT(24 + offset);
80 return -EINVAL;
81}
Marek Szyprowski80dfd952010-05-20 07:51:10 +020082
Kyungmin Parkb0d52172009-11-17 08:41:16 +010083static struct s3c_gpio_cfg gpio_cfg = {
84 .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
85 .set_pull = s3c_gpio_setpull_updown,
86 .get_pull = s3c_gpio_getpull_updown,
87};
88
89static struct s3c_gpio_cfg gpio_cfg_eint = {
90 .cfg_eint = 0xf,
91 .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
92 .set_pull = s3c_gpio_setpull_updown,
93 .get_pull = s3c_gpio_getpull_updown,
94};
95
96static struct s3c_gpio_cfg gpio_cfg_noint = {
97 .set_config = s3c_gpio_setcfg_s3c64xx_4bit,
98 .set_pull = s3c_gpio_setpull_updown,
99 .get_pull = s3c_gpio_getpull_updown,
100};
101
102static struct s3c_gpio_chip s5pc100_gpio_chips[] = {
103 {
104 .base = S5PC100_GPA0_BASE,
105 .config = &gpio_cfg,
106 .chip = {
107 .base = S5PC100_GPA0(0),
108 .ngpio = S5PC100_GPIO_A0_NR,
109 .label = "GPA0",
110 },
111 }, {
112 .base = S5PC100_GPA1_BASE,
113 .config = &gpio_cfg,
114 .chip = {
115 .base = S5PC100_GPA1(0),
116 .ngpio = S5PC100_GPIO_A1_NR,
117 .label = "GPA1",
118 },
119 }, {
120 .base = S5PC100_GPB_BASE,
121 .config = &gpio_cfg,
122 .chip = {
123 .base = S5PC100_GPB(0),
124 .ngpio = S5PC100_GPIO_B_NR,
125 .label = "GPB",
126 },
127 }, {
128 .base = S5PC100_GPC_BASE,
129 .config = &gpio_cfg,
130 .chip = {
131 .base = S5PC100_GPC(0),
132 .ngpio = S5PC100_GPIO_C_NR,
133 .label = "GPC",
134 },
135 }, {
136 .base = S5PC100_GPD_BASE,
137 .config = &gpio_cfg,
138 .chip = {
139 .base = S5PC100_GPD(0),
140 .ngpio = S5PC100_GPIO_D_NR,
141 .label = "GPD",
142 },
143 }, {
144 .base = S5PC100_GPE0_BASE,
145 .config = &gpio_cfg,
146 .chip = {
147 .base = S5PC100_GPE0(0),
148 .ngpio = S5PC100_GPIO_E0_NR,
149 .label = "GPE0",
150 },
151 }, {
152 .base = S5PC100_GPE1_BASE,
153 .config = &gpio_cfg,
154 .chip = {
155 .base = S5PC100_GPE1(0),
156 .ngpio = S5PC100_GPIO_E1_NR,
157 .label = "GPE1",
158 },
159 }, {
160 .base = S5PC100_GPF0_BASE,
161 .config = &gpio_cfg,
162 .chip = {
163 .base = S5PC100_GPF0(0),
164 .ngpio = S5PC100_GPIO_F0_NR,
165 .label = "GPF0",
166 },
167 }, {
168 .base = S5PC100_GPF1_BASE,
169 .config = &gpio_cfg,
170 .chip = {
171 .base = S5PC100_GPF1(0),
172 .ngpio = S5PC100_GPIO_F1_NR,
173 .label = "GPF1",
174 },
175 }, {
176 .base = S5PC100_GPF2_BASE,
177 .config = &gpio_cfg,
178 .chip = {
179 .base = S5PC100_GPF2(0),
180 .ngpio = S5PC100_GPIO_F2_NR,
181 .label = "GPF2",
182 },
183 }, {
184 .base = S5PC100_GPF3_BASE,
185 .config = &gpio_cfg,
186 .chip = {
187 .base = S5PC100_GPF3(0),
188 .ngpio = S5PC100_GPIO_F3_NR,
189 .label = "GPF3",
190 },
191 }, {
192 .base = S5PC100_GPG0_BASE,
193 .config = &gpio_cfg,
194 .chip = {
195 .base = S5PC100_GPG0(0),
196 .ngpio = S5PC100_GPIO_G0_NR,
197 .label = "GPG0",
198 },
199 }, {
200 .base = S5PC100_GPG1_BASE,
201 .config = &gpio_cfg,
202 .chip = {
203 .base = S5PC100_GPG1(0),
204 .ngpio = S5PC100_GPIO_G1_NR,
205 .label = "GPG1",
206 },
207 }, {
208 .base = S5PC100_GPG2_BASE,
209 .config = &gpio_cfg,
210 .chip = {
211 .base = S5PC100_GPG2(0),
212 .ngpio = S5PC100_GPIO_G2_NR,
213 .label = "GPG2",
214 },
215 }, {
216 .base = S5PC100_GPG3_BASE,
217 .config = &gpio_cfg,
218 .chip = {
219 .base = S5PC100_GPG3(0),
220 .ngpio = S5PC100_GPIO_G3_NR,
221 .label = "GPG3",
222 },
223 }, {
224 .base = S5PC100_GPH0_BASE,
225 .config = &gpio_cfg_eint,
226 .chip = {
227 .base = S5PC100_GPH0(0),
228 .ngpio = S5PC100_GPIO_H0_NR,
229 .label = "GPH0",
Joonyoung Shim7e479352010-10-01 11:18:05 +0900230 .to_irq = s5pc100_gpiolib_to_eint,
Kyungmin Parkb0d52172009-11-17 08:41:16 +0100231 },
232 }, {
233 .base = S5PC100_GPH1_BASE,
234 .config = &gpio_cfg_eint,
235 .chip = {
236 .base = S5PC100_GPH1(0),
237 .ngpio = S5PC100_GPIO_H1_NR,
238 .label = "GPH1",
Joonyoung Shim7e479352010-10-01 11:18:05 +0900239 .to_irq = s5pc100_gpiolib_to_eint,
Kyungmin Parkb0d52172009-11-17 08:41:16 +0100240 },
241 }, {
242 .base = S5PC100_GPH2_BASE,
243 .config = &gpio_cfg_eint,
244 .chip = {
245 .base = S5PC100_GPH2(0),
246 .ngpio = S5PC100_GPIO_H2_NR,
247 .label = "GPH2",
Joonyoung Shim7e479352010-10-01 11:18:05 +0900248 .to_irq = s5pc100_gpiolib_to_eint,
Kyungmin Parkb0d52172009-11-17 08:41:16 +0100249 },
250 }, {
251 .base = S5PC100_GPH3_BASE,
252 .config = &gpio_cfg_eint,
253 .chip = {
254 .base = S5PC100_GPH3(0),
255 .ngpio = S5PC100_GPIO_H3_NR,
256 .label = "GPH3",
Joonyoung Shim7e479352010-10-01 11:18:05 +0900257 .to_irq = s5pc100_gpiolib_to_eint,
Kyungmin Parkb0d52172009-11-17 08:41:16 +0100258 },
259 }, {
260 .base = S5PC100_GPI_BASE,
261 .config = &gpio_cfg,
262 .chip = {
263 .base = S5PC100_GPI(0),
264 .ngpio = S5PC100_GPIO_I_NR,
265 .label = "GPI",
266 },
267 }, {
268 .base = S5PC100_GPJ0_BASE,
269 .config = &gpio_cfg,
270 .chip = {
271 .base = S5PC100_GPJ0(0),
272 .ngpio = S5PC100_GPIO_J0_NR,
273 .label = "GPJ0",
274 },
275 }, {
276 .base = S5PC100_GPJ1_BASE,
277 .config = &gpio_cfg,
278 .chip = {
279 .base = S5PC100_GPJ1(0),
280 .ngpio = S5PC100_GPIO_J1_NR,
281 .label = "GPJ1",
282 },
283 }, {
284 .base = S5PC100_GPJ2_BASE,
285 .config = &gpio_cfg,
286 .chip = {
287 .base = S5PC100_GPJ2(0),
288 .ngpio = S5PC100_GPIO_J2_NR,
289 .label = "GPJ2",
290 },
291 }, {
292 .base = S5PC100_GPJ3_BASE,
293 .config = &gpio_cfg,
294 .chip = {
295 .base = S5PC100_GPJ3(0),
296 .ngpio = S5PC100_GPIO_J3_NR,
297 .label = "GPJ3",
298 },
299 }, {
300 .base = S5PC100_GPJ4_BASE,
301 .config = &gpio_cfg,
302 .chip = {
303 .base = S5PC100_GPJ4(0),
304 .ngpio = S5PC100_GPIO_J4_NR,
305 .label = "GPJ4",
306 },
307 }, {
308 .base = S5PC100_GPK0_BASE,
309 .config = &gpio_cfg_noint,
310 .chip = {
311 .base = S5PC100_GPK0(0),
312 .ngpio = S5PC100_GPIO_K0_NR,
313 .label = "GPK0",
314 },
315 }, {
316 .base = S5PC100_GPK1_BASE,
317 .config = &gpio_cfg_noint,
318 .chip = {
319 .base = S5PC100_GPK1(0),
320 .ngpio = S5PC100_GPIO_K1_NR,
321 .label = "GPK1",
322 },
323 }, {
324 .base = S5PC100_GPK2_BASE,
325 .config = &gpio_cfg_noint,
326 .chip = {
327 .base = S5PC100_GPK2(0),
328 .ngpio = S5PC100_GPIO_K2_NR,
329 .label = "GPK2",
330 },
331 }, {
332 .base = S5PC100_GPK3_BASE,
333 .config = &gpio_cfg_noint,
334 .chip = {
335 .base = S5PC100_GPK3(0),
336 .ngpio = S5PC100_GPIO_K3_NR,
337 .label = "GPK3",
338 },
339 }, {
340 .base = S5PC100_GPL0_BASE,
341 .config = &gpio_cfg_noint,
342 .chip = {
343 .base = S5PC100_GPL0(0),
344 .ngpio = S5PC100_GPIO_L0_NR,
345 .label = "GPL0",
346 },
347 }, {
348 .base = S5PC100_GPL1_BASE,
349 .config = &gpio_cfg_noint,
350 .chip = {
351 .base = S5PC100_GPL1(0),
352 .ngpio = S5PC100_GPIO_L1_NR,
353 .label = "GPL1",
354 },
355 }, {
356 .base = S5PC100_GPL2_BASE,
357 .config = &gpio_cfg_noint,
358 .chip = {
359 .base = S5PC100_GPL2(0),
360 .ngpio = S5PC100_GPIO_L2_NR,
361 .label = "GPL2",
362 },
363 }, {
364 .base = S5PC100_GPL3_BASE,
365 .config = &gpio_cfg_noint,
366 .chip = {
367 .base = S5PC100_GPL3(0),
368 .ngpio = S5PC100_GPIO_L3_NR,
369 .label = "GPL3",
370 },
371 }, {
372 .base = S5PC100_GPL4_BASE,
373 .config = &gpio_cfg_noint,
374 .chip = {
375 .base = S5PC100_GPL4(0),
376 .ngpio = S5PC100_GPIO_L4_NR,
377 .label = "GPL4",
378 },
379 },
380};
381
Marek Szyprowskiacc84702010-05-20 07:51:08 +0200382static __init int s5pc100_gpiolib_init(void)
Kyungmin Parkb0d52172009-11-17 08:41:16 +0100383{
Marek Szyprowski252b8ef2010-05-18 12:38:40 +0200384 struct s3c_gpio_chip *chip;
Kyungmin Parkb0d52172009-11-17 08:41:16 +0100385 int nr_chips;
Joonyoung Shim7e479352010-10-01 11:18:05 +0900386 int gpioint_group = 0;
Kyungmin Parkb0d52172009-11-17 08:41:16 +0100387
Marek Szyprowski252b8ef2010-05-18 12:38:40 +0200388 chip = s5pc100_gpio_chips;
389 nr_chips = ARRAY_SIZE(s5pc100_gpio_chips);
Kyungmin Parkb0d52172009-11-17 08:41:16 +0100390
Joonyoung Shim7e479352010-10-01 11:18:05 +0900391 for (; nr_chips > 0; nr_chips--, chip++) {
392 if (chip->config == &gpio_cfg) {
393 /* gpio interrupts */
394 chip->group = gpioint_group++;
395 }
396 }
Marek Szyprowski252b8ef2010-05-18 12:38:40 +0200397
398 samsung_gpiolib_add_4bit_chips(s5pc100_gpio_chips,
399 ARRAY_SIZE(s5pc100_gpio_chips));
Marek Szyprowski23686a02010-05-20 07:51:09 +0200400
Kyungmin Parkb0d52172009-11-17 08:41:16 +0100401 return 0;
402}
Marek Szyprowskiacc84702010-05-20 07:51:08 +0200403core_initcall(s5pc100_gpiolib_init);