aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpio-samsung.c
diff options
context:
space:
mode:
authorKukjin Kim <kgene.kim@samsung.com>2011-08-30 07:39:08 -0400
committerKukjin Kim <kgene.kim@samsung.com>2011-09-21 02:06:05 -0400
commit1b39d5f2cc5c28085bbf48db80bf704ab4dedda9 (patch)
treec75a0e8468865c3657bb2ec750a118cb4a81948b /drivers/gpio/gpio-samsung.c
parentc4b3fd38dfb677d7a3997527c9cbdc21b81424a3 (diff)
gpio/samsung: gpio-samsung.c to support Samsung GPIOs
This patch adds support for Samsung GPIOs with one gpio driver and removes old GPIO drivers which are drivers/gpio-s3c24xx.c, gpio-s3c64xx.c, gpio-s5p64x0.c, gpio-s5pc100.c, gpio-s5pv210.c, gpio-exynos4.c, gpio-plat-samsung.c, plat-samsung/gpio-config.c and gpio.c to support each Samsung SoCs before. Because the gpio-samsung.c can replace old Samsung GPIO drivers. Basically, the gpio-samsung.c has been made by their merging and removing duplicated definitions. Note: gpio-samsung.c includes some SoC dependent codes and it will be replaced next time. Cc: Ben Dooks <ben-linux@fluff.org> Acked-by: Grant Likely <grant.likely@secretlab.ca> [kgene.kim@samsung.com: squash the removing and adding patches] [kgene.kim@samsung.com: fixes bug during to register of gpio_chips] Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
Diffstat (limited to 'drivers/gpio/gpio-samsung.c')
-rw-r--r--drivers/gpio/gpio-samsung.c2686
1 files changed, 2686 insertions, 0 deletions
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c
new file mode 100644
index 000000000000..36f3675e7de8
--- /dev/null
+++ b/drivers/gpio/gpio-samsung.c
@@ -0,0 +1,2686 @@
1/*
2 * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
3 * http://www.samsung.com/
4 *
5 * Copyright 2008 Openmoko, Inc.
6 * Copyright 2008 Simtec Electronics
7 * Ben Dooks <ben@simtec.co.uk>
8 * http://armlinux.simtec.co.uk/
9 *
10 * SAMSUNG - GPIOlib support
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 */
16
17#include <linux/kernel.h>
18#include <linux/irq.h>
19#include <linux/io.h>
20#include <linux/gpio.h>
21#include <linux/init.h>
22#include <linux/spinlock.h>
23#include <linux/module.h>
24#include <linux/interrupt.h>
25#include <linux/sysdev.h>
26#include <linux/ioport.h>
27
28#include <asm/irq.h>
29
30#include <mach/hardware.h>
31#include <mach/map.h>
32#include <mach/regs-clock.h>
33#include <mach/regs-gpio.h>
34
35#include <plat/cpu.h>
36#include <plat/gpio-core.h>
37#include <plat/gpio-cfg.h>
38#include <plat/gpio-cfg-helpers.h>
39#include <plat/gpio-fns.h>
40#include <plat/pm.h>
41
42#ifndef DEBUG_GPIO
43#define gpio_dbg(x...) do { } while (0)
44#else
45#define gpio_dbg(x...) printk(KERN_DEBUG x)
46#endif
47
48int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip,
49 unsigned int off, samsung_gpio_pull_t pull)
50{
51 void __iomem *reg = chip->base + 0x08;
52 int shift = off * 2;
53 u32 pup;
54
55 pup = __raw_readl(reg);
56 pup &= ~(3 << shift);
57 pup |= pull << shift;
58 __raw_writel(pup, reg);
59
60 return 0;
61}
62
63samsung_gpio_pull_t samsung_gpio_getpull_updown(struct samsung_gpio_chip *chip,
64 unsigned int off)
65{
66 void __iomem *reg = chip->base + 0x08;
67 int shift = off * 2;
68 u32 pup = __raw_readl(reg);
69
70 pup >>= shift;
71 pup &= 0x3;
72
73 return (__force samsung_gpio_pull_t)pup;
74}
75
76int s3c2443_gpio_setpull(struct samsung_gpio_chip *chip,
77 unsigned int off, samsung_gpio_pull_t pull)
78{
79 switch (pull) {
80 case S3C_GPIO_PULL_NONE:
81 pull = 0x01;
82 break;
83 case S3C_GPIO_PULL_UP:
84 pull = 0x00;
85 break;
86 case S3C_GPIO_PULL_DOWN:
87 pull = 0x02;
88 break;
89 }
90 return samsung_gpio_setpull_updown(chip, off, pull);
91}
92
93samsung_gpio_pull_t s3c2443_gpio_getpull(struct samsung_gpio_chip *chip,
94 unsigned int off)
95{
96 samsung_gpio_pull_t pull;
97
98 pull = samsung_gpio_getpull_updown(chip, off);
99
100 switch (pull) {
101 case 0x00:
102 pull = S3C_GPIO_PULL_UP;
103 break;
104 case 0x01:
105 case 0x03:
106 pull = S3C_GPIO_PULL_NONE;
107 break;
108 case 0x02:
109 pull = S3C_GPIO_PULL_DOWN;
110 break;
111 }
112
113 return pull;
114}
115
116static int s3c24xx_gpio_setpull_1(struct samsung_gpio_chip *chip,
117 unsigned int off, samsung_gpio_pull_t pull,
118 samsung_gpio_pull_t updown)
119{
120 void __iomem *reg = chip->base + 0x08;
121 u32 pup = __raw_readl(reg);
122
123 if (pull == updown)
124 pup &= ~(1 << off);
125 else if (pull == S3C_GPIO_PULL_NONE)
126 pup |= (1 << off);
127 else
128 return -EINVAL;
129
130 __raw_writel(pup, reg);
131 return 0;
132}
133
134static samsung_gpio_pull_t s3c24xx_gpio_getpull_1(struct samsung_gpio_chip *chip,
135 unsigned int off,
136 samsung_gpio_pull_t updown)
137{
138 void __iomem *reg = chip->base + 0x08;
139 u32 pup = __raw_readl(reg);
140
141 pup &= (1 << off);
142 return pup ? S3C_GPIO_PULL_NONE : updown;
143}
144
145samsung_gpio_pull_t s3c24xx_gpio_getpull_1up(struct samsung_gpio_chip *chip,
146 unsigned int off)
147{
148 return s3c24xx_gpio_getpull_1(chip, off, S3C_GPIO_PULL_UP);
149}
150
151int s3c24xx_gpio_setpull_1up(struct samsung_gpio_chip *chip,
152 unsigned int off, samsung_gpio_pull_t pull)
153{
154 return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_UP);
155}
156
157samsung_gpio_pull_t s3c24xx_gpio_getpull_1down(struct samsung_gpio_chip *chip,
158 unsigned int off)
159{
160 return s3c24xx_gpio_getpull_1(chip, off, S3C_GPIO_PULL_DOWN);
161}
162
163int s3c24xx_gpio_setpull_1down(struct samsung_gpio_chip *chip,
164 unsigned int off, samsung_gpio_pull_t pull)
165{
166 return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_DOWN);
167}
168
169static int exynos4_gpio_setpull(struct samsung_gpio_chip *chip,
170 unsigned int off, samsung_gpio_pull_t pull)
171{
172 if (pull == S3C_GPIO_PULL_UP)
173 pull = 3;
174
175 return samsung_gpio_setpull_updown(chip, off, pull);
176}
177
178static samsung_gpio_pull_t exynos4_gpio_getpull(struct samsung_gpio_chip *chip,
179 unsigned int off)
180{
181 samsung_gpio_pull_t pull;
182
183 pull = samsung_gpio_getpull_updown(chip, off);
184
185 if (pull == 3)
186 pull = S3C_GPIO_PULL_UP;
187
188 return pull;
189}
190
191/*
192 * samsung_gpio_setcfg_2bit - Samsung 2bit style GPIO configuration.
193 * @chip: The gpio chip that is being configured.
194 * @off: The offset for the GPIO being configured.
195 * @cfg: The configuration value to set.
196 *
197 * This helper deal with the GPIO cases where the control register
198 * has two bits of configuration per gpio, which have the following
199 * functions:
200 * 00 = input
201 * 01 = output
202 * 1x = special function
203 */
204
205static int samsung_gpio_setcfg_2bit(struct samsung_gpio_chip *chip,
206 unsigned int off, unsigned int cfg)
207{
208 void __iomem *reg = chip->base;
209 unsigned int shift = off * 2;
210 u32 con;
211
212 if (samsung_gpio_is_cfg_special(cfg)) {
213 cfg &= 0xf;
214 if (cfg > 3)
215 return -EINVAL;
216
217 cfg <<= shift;
218 }
219
220 con = __raw_readl(reg);
221 con &= ~(0x3 << shift);
222 con |= cfg;
223 __raw_writel(con, reg);
224
225 return 0;
226}
227
228/*
229 * samsung_gpio_getcfg_2bit - Samsung 2bit style GPIO configuration read.
230 * @chip: The gpio chip that is being configured.
231 * @off: The offset for the GPIO being configured.
232 *
233 * The reverse of samsung_gpio_setcfg_2bit(). Will return a value whicg
234 * could be directly passed back to samsung_gpio_setcfg_2bit(), from the
235 * S3C_GPIO_SPECIAL() macro.
236 */
237
238static unsigned int samsung_gpio_getcfg_2bit(struct samsung_gpio_chip *chip,
239 unsigned int off)
240{
241 u32 con;
242
243 con = __raw_readl(chip->base);
244 con >>= off * 2;
245 con &= 3;
246
247 /* this conversion works for IN and OUT as well as special mode */
248 return S3C_GPIO_SPECIAL(con);
249}
250
251/*
252 * samsung_gpio_setcfg_4bit - Samsung 4bit single register GPIO config.
253 * @chip: The gpio chip that is being configured.
254 * @off: The offset for the GPIO being configured.
255 * @cfg: The configuration value to set.
256 *
257 * This helper deal with the GPIO cases where the control register has 4 bits
258 * of control per GPIO, generally in the form of:
259 * 0000 = Input
260 * 0001 = Output
261 * others = Special functions (dependent on bank)
262 *
263 * Note, since the code to deal with the case where there are two control
264 * registers instead of one, we do not have a separate set of functions for
265 * each case.
266 */
267
268static int samsung_gpio_setcfg_4bit(struct samsung_gpio_chip *chip,
269 unsigned int off, unsigned int cfg)
270{
271 void __iomem *reg = chip->base;
272 unsigned int shift = (off & 7) * 4;
273 u32 con;
274
275 if (off < 8 && chip->chip.ngpio > 8)
276 reg -= 4;
277
278 if (samsung_gpio_is_cfg_special(cfg)) {
279 cfg &= 0xf;
280 cfg <<= shift;
281 }
282
283 con = __raw_readl(reg);
284 con &= ~(0xf << shift);
285 con |= cfg;
286 __raw_writel(con, reg);
287
288 return 0;
289}
290
291/*
292 * samsung_gpio_getcfg_4bit - Samsung 4bit single register GPIO config read.
293 * @chip: The gpio chip that is being configured.
294 * @off: The offset for the GPIO being configured.
295 *
296 * The reverse of samsung_gpio_setcfg_4bit(), turning a gpio configuration
297 * register setting into a value the software can use, such as could be passed
298 * to samsung_gpio_setcfg_4bit().
299 *
300 * @sa samsung_gpio_getcfg_2bit
301 */
302
303static unsigned samsung_gpio_getcfg_4bit(struct samsung_gpio_chip *chip,
304 unsigned int off)
305{
306 void __iomem *reg = chip->base;
307 unsigned int shift = (off & 7) * 4;
308 u32 con;
309
310 if (off < 8 && chip->chip.ngpio > 8)
311 reg -= 4;
312
313 con = __raw_readl(reg);
314 con >>= shift;
315 con &= 0xf;
316
317 /* this conversion works for IN and OUT as well as special mode */
318 return S3C_GPIO_SPECIAL(con);
319}
320
321/*
322 * s3c24xx_gpio_setcfg_abank - S3C24XX style GPIO configuration (Bank A)
323 * @chip: The gpio chip that is being configured.
324 * @off: The offset for the GPIO being configured.
325 * @cfg: The configuration value to set.
326 *
327 * This helper deal with the GPIO cases where the control register
328 * has one bit of configuration for the gpio, where setting the bit
329 * means the pin is in special function mode and unset means output.
330 */
331
332static int s3c24xx_gpio_setcfg_abank(struct samsung_gpio_chip *chip,
333 unsigned int off, unsigned int cfg)
334{
335 void __iomem *reg = chip->base;
336 unsigned int shift = off;
337 u32 con;
338
339 if (samsung_gpio_is_cfg_special(cfg)) {
340 cfg &= 0xf;
341
342 /* Map output to 0, and SFN2 to 1 */
343 cfg -= 1;
344 if (cfg > 1)
345 return -EINVAL;
346
347 cfg <<= shift;
348 }
349
350 con = __raw_readl(reg);
351 con &= ~(0x1 << shift);
352 con |= cfg;
353 __raw_writel(con, reg);
354
355 return 0;
356}
357
358/*
359 * s3c24xx_gpio_getcfg_abank - S3C24XX style GPIO configuration read (Bank A)
360 * @chip: The gpio chip that is being configured.
361 * @off: The offset for the GPIO being configured.
362 *
363 * The reverse of s3c24xx_gpio_setcfg_abank() turning an GPIO into a usable
364 * GPIO configuration value.
365 *
366 * @sa samsung_gpio_getcfg_2bit
367 * @sa samsung_gpio_getcfg_4bit
368 */
369
370static unsigned s3c24xx_gpio_getcfg_abank(struct samsung_gpio_chip *chip,
371 unsigned int off)
372{
373 u32 con;
374
375 con = __raw_readl(chip->base);
376 con >>= off;
377 con &= 1;
378 con++;
379
380 return S3C_GPIO_SFN(con);
381}
382
383static int s5p64x0_gpio_setcfg_rbank(struct samsung_gpio_chip *chip,
384 unsigned int off, unsigned int cfg)
385{
386 void __iomem *reg = chip->base;
387 unsigned int shift;
388 u32 con;
389
390 switch (off) {
391 case 0:
392 case 1:
393 case 2:
394 case 3:
395 case 4:
396 case 5:
397 shift = (off & 7) * 4;
398 reg -= 4;
399 break;
400 case 6:
401 shift = ((off + 1) & 7) * 4;
402 reg -= 4;
403 default:
404 shift = ((off + 1) & 7) * 4;
405 break;
406 }
407
408 if (samsung_gpio_is_cfg_special(cfg)) {
409 cfg &= 0xf;
410 cfg <<= shift;
411 }
412
413 con = __raw_readl(reg);
414 con &= ~(0xf << shift);
415 con |= cfg;
416 __raw_writel(con, reg);
417
418 return 0;
419}
420
421static void __init samsung_gpiolib_set_cfg(struct samsung_gpio_cfg *chipcfg,
422 int nr_chips)
423{
424 for (; nr_chips > 0; nr_chips--, chipcfg++) {
425 if (!chipcfg->set_config)
426 chipcfg->set_config = samsung_gpio_setcfg_4bit;
427 if (!chipcfg->get_config)
428 chipcfg->get_config = samsung_gpio_getcfg_4bit;
429 if (!chipcfg->set_pull)
430 chipcfg->set_pull = samsung_gpio_setpull_updown;
431 if (!chipcfg->get_pull)
432 chipcfg->get_pull = samsung_gpio_getpull_updown;
433 }
434}
435
436struct samsung_gpio_cfg s3c24xx_gpiocfg_default = {
437 .set_config = samsung_gpio_setcfg_2bit,
438 .get_config = samsung_gpio_getcfg_2bit,
439};
440
441static struct samsung_gpio_cfg s3c24xx_gpiocfg_banka = {
442 .set_config = s3c24xx_gpio_setcfg_abank,
443 .get_config = s3c24xx_gpio_getcfg_abank,
444};
445
446static struct samsung_gpio_cfg exynos4_gpio_cfg = {
447 .set_pull = exynos4_gpio_setpull,
448 .get_pull = exynos4_gpio_getpull,
449};
450
451static struct samsung_gpio_cfg s5p64x0_gpio_cfg_rbank = {
452 .cfg_eint = 0x3,
453 .set_config = s5p64x0_gpio_setcfg_rbank,
454 .get_config = samsung_gpio_getcfg_4bit,
455 .set_pull = samsung_gpio_setpull_updown,
456 .get_pull = samsung_gpio_getpull_updown,
457};
458
459static struct samsung_gpio_cfg samsung_gpio_cfgs[] = {
460 {
461 .cfg_eint = 0x0,
462 }, {
463 .cfg_eint = 0x3,
464 }, {
465 .cfg_eint = 0x7,
466 }, {
467 .cfg_eint = 0xF,
468 }, {
469 .cfg_eint = 0x0,
470 .set_config = samsung_gpio_setcfg_2bit,
471 .get_config = samsung_gpio_getcfg_2bit,
472 }, {
473 .cfg_eint = 0x2,
474 .set_config = samsung_gpio_setcfg_2bit,
475 .get_config = samsung_gpio_getcfg_2bit,
476 }, {
477 .cfg_eint = 0x3,
478 .set_config = samsung_gpio_setcfg_2bit,
479 .get_config = samsung_gpio_getcfg_2bit,
480 }, {
481 .set_config = samsung_gpio_setcfg_2bit,
482 .get_config = samsung_gpio_getcfg_2bit,
483 },
484};
485
486/*
487 * Default routines for controlling GPIO, based on the original S3C24XX
488 * GPIO functions which deal with the case where each gpio bank of the
489 * chip is as following:
490 *
491 * base + 0x00: Control register, 2 bits per gpio
492 * gpio n: 2 bits starting at (2*n)
493 * 00 = input, 01 = output, others mean special-function
494 * base + 0x04: Data register, 1 bit per gpio
495 * bit n: data bit n
496*/
497
498static int samsung_gpiolib_2bit_input(struct gpio_chip *chip, unsigned offset)
499{
500 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
501 void __iomem *base = ourchip->base;
502 unsigned long flags;
503 unsigned long con;
504
505 samsung_gpio_lock(ourchip, flags);
506
507 con = __raw_readl(base + 0x00);
508 con &= ~(3 << (offset * 2));
509
510 __raw_writel(con, base + 0x00);
511
512 samsung_gpio_unlock(ourchip, flags);
513 return 0;
514}
515
516static int samsung_gpiolib_2bit_output(struct gpio_chip *chip,
517 unsigned offset, int value)
518{
519 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
520 void __iomem *base = ourchip->base;
521 unsigned long flags;
522 unsigned long dat;
523 unsigned long con;
524
525 samsung_gpio_lock(ourchip, flags);
526
527 dat = __raw_readl(base + 0x04);
528 dat &= ~(1 << offset);
529 if (value)
530 dat |= 1 << offset;
531 __raw_writel(dat, base + 0x04);
532
533 con = __raw_readl(base + 0x00);
534 con &= ~(3 << (offset * 2));
535 con |= 1 << (offset * 2);
536
537 __raw_writel(con, base + 0x00);
538 __raw_writel(dat, base + 0x04);
539
540 samsung_gpio_unlock(ourchip, flags);
541 return 0;
542}
543
544/*
545 * The samsung_gpiolib_4bit routines are to control the gpio banks where
546 * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
547 * following example:
548 *
549 * base + 0x00: Control register, 4 bits per gpio
550 * gpio n: 4 bits starting at (4*n)
551 * 0000 = input, 0001 = output, others mean special-function
552 * base + 0x04: Data register, 1 bit per gpio
553 * bit n: data bit n
554 *
555 * Note, since the data register is one bit per gpio and is at base + 0x4
556 * we can use samsung_gpiolib_get and samsung_gpiolib_set to change the
557 * state of the output.
558 */
559
560static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
561 unsigned int offset)
562{
563 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
564 void __iomem *base = ourchip->base;
565 unsigned long con;
566
567 con = __raw_readl(base + GPIOCON_OFF);
568 con &= ~(0xf << con_4bit_shift(offset));
569 __raw_writel(con, base + GPIOCON_OFF);
570
571 gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con);
572
573 return 0;
574}
575
576static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
577 unsigned int offset, int value)
578{
579 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
580 void __iomem *base = ourchip->base;
581 unsigned long con;
582 unsigned long dat;
583
584 con = __raw_readl(base + GPIOCON_OFF);
585 con &= ~(0xf << con_4bit_shift(offset));
586 con |= 0x1 << con_4bit_shift(offset);
587
588 dat = __raw_readl(base + GPIODAT_OFF);
589
590 if (value)
591 dat |= 1 << offset;
592 else
593 dat &= ~(1 << offset);
594
595 __raw_writel(dat, base + GPIODAT_OFF);
596 __raw_writel(con, base + GPIOCON_OFF);
597 __raw_writel(dat, base + GPIODAT_OFF);
598
599 gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
600
601 return 0;
602}
603
604/*
605 * The next set of routines are for the case where the GPIO configuration
606 * registers are 4 bits per GPIO but there is more than one register (the
607 * bank has more than 8 GPIOs.
608 *
609 * This case is the similar to the 4 bit case, but the registers are as
610 * follows:
611 *
612 * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
613 * gpio n: 4 bits starting at (4*n)
614 * 0000 = input, 0001 = output, others mean special-function
615 * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
616 * gpio n: 4 bits starting at (4*n)
617 * 0000 = input, 0001 = output, others mean special-function
618 * base + 0x08: Data register, 1 bit per gpio
619 * bit n: data bit n
620 *
621 * To allow us to use the samsung_gpiolib_get and samsung_gpiolib_set
622 * routines we store the 'base + 0x4' address so that these routines see
623 * the data register at ourchip->base + 0x04.
624 */
625
626static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
627 unsigned int offset)
628{
629 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
630 void __iomem *base = ourchip->base;
631 void __iomem *regcon = base;
632 unsigned long con;
633
634 if (offset > 7)
635 offset -= 8;
636 else
637 regcon -= 4;
638
639 con = __raw_readl(regcon);
640 con &= ~(0xf << con_4bit_shift(offset));
641 __raw_writel(con, regcon);
642
643 gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con);
644
645 return 0;
646}
647
648static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
649 unsigned int offset, int value)
650{
651 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
652 void __iomem *base = ourchip->base;
653 void __iomem *regcon = base;
654 unsigned long con;
655 unsigned long dat;
656 unsigned con_offset = offset;
657
658 if (con_offset > 7)
659 con_offset -= 8;
660 else
661 regcon -= 4;
662
663 con = __raw_readl(regcon);
664 con &= ~(0xf << con_4bit_shift(con_offset));
665 con |= 0x1 << con_4bit_shift(con_offset);
666
667 dat = __raw_readl(base + GPIODAT_OFF);
668
669 if (value)
670 dat |= 1 << offset;
671 else
672 dat &= ~(1 << offset);
673
674 __raw_writel(dat, base + GPIODAT_OFF);
675 __raw_writel(con, regcon);
676 __raw_writel(dat, base + GPIODAT_OFF);
677
678 gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
679
680 return 0;
681}
682
683/* The next set of routines are for the case of s3c24xx bank a */
684
685static int s3c24xx_gpiolib_banka_input(struct gpio_chip *chip, unsigned offset)
686{
687 return -EINVAL;
688}
689
690static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip,
691 unsigned offset, int value)
692{
693 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
694 void __iomem *base = ourchip->base;
695 unsigned long flags;
696 unsigned long dat;
697 unsigned long con;
698
699 local_irq_save(flags);
700
701 con = __raw_readl(base + 0x00);
702 dat = __raw_readl(base + 0x04);
703
704 dat &= ~(1 << offset);
705 if (value)
706 dat |= 1 << offset;
707
708 __raw_writel(dat, base + 0x04);
709
710 con &= ~(1 << offset);
711
712 __raw_writel(con, base + 0x00);
713 __raw_writel(dat, base + 0x04);
714
715 local_irq_restore(flags);
716 return 0;
717}
718
719/* The next set of routines are for the case of s5p64x0 bank r */
720
721static int s5p64x0_gpiolib_rbank_input(struct gpio_chip *chip,
722 unsigned int offset)
723{
724 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
725 void __iomem *base = ourchip->base;
726 void __iomem *regcon = base;
727 unsigned long con;
728 unsigned long flags;
729
730 switch (offset) {
731 case 6:
732 offset += 1;
733 case 0:
734 case 1:
735 case 2:
736 case 3:
737 case 4:
738 case 5:
739 regcon -= 4;
740 break;
741 default:
742 offset -= 7;
743 break;
744 }
745
746 samsung_gpio_lock(ourchip, flags);
747
748 con = __raw_readl(regcon);
749 con &= ~(0xf << con_4bit_shift(offset));
750 __raw_writel(con, regcon);
751
752 samsung_gpio_unlock(ourchip, flags);
753
754 return 0;
755}
756
757static int s5p64x0_gpiolib_rbank_output(struct gpio_chip *chip,
758 unsigned int offset, int value)
759{
760 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
761 void __iomem *base = ourchip->base;
762 void __iomem *regcon = base;
763 unsigned long con;
764 unsigned long dat;
765 unsigned long flags;
766 unsigned con_offset = offset;
767
768 switch (con_offset) {
769 case 6:
770 con_offset += 1;
771 case 0:
772 case 1:
773 case 2:
774 case 3:
775 case 4:
776 case 5:
777 regcon -= 4;
778 break;
779 default:
780 con_offset -= 7;
781 break;
782 }
783
784 samsung_gpio_lock(ourchip, flags);
785
786 con = __raw_readl(regcon);
787 con &= ~(0xf << con_4bit_shift(con_offset));
788 con |= 0x1 << con_4bit_shift(con_offset);
789
790 dat = __raw_readl(base + GPIODAT_OFF);
791 if (value)
792 dat |= 1 << offset;
793 else
794 dat &= ~(1 << offset);
795
796 __raw_writel(con, regcon);
797 __raw_writel(dat, base + GPIODAT_OFF);
798
799 samsung_gpio_unlock(ourchip, flags);
800
801 return 0;
802}
803
804static void samsung_gpiolib_set(struct gpio_chip *chip,
805 unsigned offset, int value)
806{
807 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
808 void __iomem *base = ourchip->base;
809 unsigned long flags;
810 unsigned long dat;
811
812 samsung_gpio_lock(ourchip, flags);
813
814 dat = __raw_readl(base + 0x04);
815 dat &= ~(1 << offset);
816 if (value)
817 dat |= 1 << offset;
818 __raw_writel(dat, base + 0x04);
819
820 samsung_gpio_unlock(ourchip, flags);
821}
822
823static int samsung_gpiolib_get(struct gpio_chip *chip, unsigned offset)
824{
825 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
826 unsigned long val;
827
828 val = __raw_readl(ourchip->base + 0x04);
829 val >>= offset;
830 val &= 1;
831
832 return val;
833}
834
835/*
836 * CONFIG_S3C_GPIO_TRACK enables the tracking of the s3c specific gpios
837 * for use with the configuration calls, and other parts of the s3c gpiolib
838 * support code.
839 *
840 * Not all s3c support code will need this, as some configurations of cpu
841 * may only support one or two different configuration options and have an
842 * easy gpio to samsung_gpio_chip mapping function. If this is the case, then
843 * the machine support file should provide its own samsung_gpiolib_getchip()
844 * and any other necessary functions.
845 */
846
847#ifdef CONFIG_S3C_GPIO_TRACK
848struct samsung_gpio_chip *s3c_gpios[S3C_GPIO_END];
849
850static __init void s3c_gpiolib_track(struct samsung_gpio_chip *chip)
851{
852 unsigned int gpn;
853 int i;
854
855 gpn = chip->chip.base;
856 for (i = 0; i < chip->chip.ngpio; i++, gpn++) {
857 BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios));
858 s3c_gpios[gpn] = chip;
859 }
860}
861#endif /* CONFIG_S3C_GPIO_TRACK */
862
863/*
864 * samsung_gpiolib_add() - add the Samsung gpio_chip.
865 * @chip: The chip to register
866 *
867 * This is a wrapper to gpiochip_add() that takes our specific gpio chip
868 * information and makes the necessary alterations for the platform and
869 * notes the information for use with the configuration systems and any
870 * other parts of the system.
871 */
872
873static void __init samsung_gpiolib_add(struct samsung_gpio_chip *chip)
874{
875 struct gpio_chip *gc = &chip->chip;
876 int ret;
877
878 BUG_ON(!chip->base);
879 BUG_ON(!gc->label);
880 BUG_ON(!gc->ngpio);
881
882 spin_lock_init(&chip->lock);
883
884 if (!gc->direction_input)
885 gc->direction_input = samsung_gpiolib_2bit_input;
886 if (!gc->direction_output)
887 gc->direction_output = samsung_gpiolib_2bit_output;
888 if (!gc->set)
889 gc->set = samsung_gpiolib_set;
890 if (!gc->get)
891 gc->get = samsung_gpiolib_get;
892
893#ifdef CONFIG_PM
894 if (chip->pm != NULL) {
895 if (!chip->pm->save || !chip->pm->resume)
896 printk(KERN_ERR "gpio: %s has missing PM functions\n",
897 gc->label);
898 } else
899 printk(KERN_ERR "gpio: %s has no PM function\n", gc->label);
900#endif
901
902 /* gpiochip_add() prints own failure message on error. */
903 ret = gpiochip_add(gc);
904 if (ret >= 0)
905 s3c_gpiolib_track(chip);
906}
907
908static void __init s3c24xx_gpiolib_add_chips(struct samsung_gpio_chip *chip,
909 int nr_chips, void __iomem *base)
910{
911 int i;
912 struct gpio_chip *gc = &chip->chip;
913
914 for (i = 0 ; i < nr_chips; i++, chip++) {
915 if (!chip->config)
916 chip->config = &s3c24xx_gpiocfg_default;
917 if (!chip->pm)
918 chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
919 if ((base != NULL) && (chip->base == NULL))
920 chip->base = base + ((i) * 0x10);
921
922 if (!gc->direction_input)
923 gc->direction_input = samsung_gpiolib_2bit_input;
924 if (!gc->direction_output)
925 gc->direction_output = samsung_gpiolib_2bit_output;
926
927 samsung_gpiolib_add(chip);
928 }
929}
930
931static void __init samsung_gpiolib_add_2bit_chips(struct samsung_gpio_chip *chip,
932 int nr_chips, void __iomem *base,
933 unsigned int offset)
934{
935 int i;
936
937 for (i = 0 ; i < nr_chips; i++, chip++) {
938 chip->chip.direction_input = samsung_gpiolib_2bit_input;
939 chip->chip.direction_output = samsung_gpiolib_2bit_output;
940
941 if (!chip->config)
942 chip->config = &samsung_gpio_cfgs[7];
943 if (!chip->pm)
944 chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
945 if ((base != NULL) && (chip->base == NULL))
946 chip->base = base + ((i) * offset);
947
948 samsung_gpiolib_add(chip);
949 }
950}
951
952/*
953 * samsung_gpiolib_add_4bit_chips - 4bit single register GPIO config.
954 * @chip: The gpio chip that is being configured.
955 * @nr_chips: The no of chips (gpio ports) for the GPIO being configured.
956 *
957 * This helper deal with the GPIO cases where the control register has 4 bits
958 * of control per GPIO, generally in the form of:
959 * 0000 = Input
960 * 0001 = Output
961 * others = Special functions (dependent on bank)
962 *
963 * Note, since the code to deal with the case where there are two control
964 * registers instead of one, we do not have a separate set of function
965 * (samsung_gpiolib_add_4bit2_chips)for each case.
966 */
967
968static void __init samsung_gpiolib_add_4bit_chips(struct samsung_gpio_chip *chip,
969 int nr_chips, void __iomem *base)
970{
971 int i;
972
973 for (i = 0 ; i < nr_chips; i++, chip++) {
974 chip->chip.direction_input = samsung_gpiolib_4bit_input;
975 chip->chip.direction_output = samsung_gpiolib_4bit_output;
976
977 if (!chip->config)
978 chip->config = &samsung_gpio_cfgs[2];
979 if (!chip->pm)
980 chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
981 if ((base != NULL) && (chip->base == NULL))
982 chip->base = base + ((i) * 0x20);
983
984 samsung_gpiolib_add(chip);
985 }
986}
987
988static void __init samsung_gpiolib_add_4bit2_chips(struct samsung_gpio_chip *chip,
989 int nr_chips)
990{
991 for (; nr_chips > 0; nr_chips--, chip++) {
992 chip->chip.direction_input = samsung_gpiolib_4bit2_input;
993 chip->chip.direction_output = samsung_gpiolib_4bit2_output;
994
995 if (!chip->config)
996 chip->config = &samsung_gpio_cfgs[2];
997 if (!chip->pm)
998 chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
999
1000 samsung_gpiolib_add(chip);
1001 }
1002}
1003
1004static void __init s5p64x0_gpiolib_add_rbank(struct samsung_gpio_chip *chip,
1005 int nr_chips)
1006{
1007 for (; nr_chips > 0; nr_chips--, chip++) {
1008 chip->chip.direction_input = s5p64x0_gpiolib_rbank_input;
1009 chip->chip.direction_output = s5p64x0_gpiolib_rbank_output;
1010
1011 if (!chip->pm)
1012 chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
1013
1014 samsung_gpiolib_add(chip);
1015 }
1016}
1017
1018int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
1019{
1020 struct samsung_gpio_chip *samsung_chip = container_of(chip, struct samsung_gpio_chip, chip);
1021
1022 return samsung_chip->irq_base + offset;
1023}
1024
1025#ifdef CONFIG_PLAT_S3C24XX
1026static int s3c24xx_gpiolib_fbank_to_irq(struct gpio_chip *chip, unsigned offset)
1027{
1028 if (offset < 4)
1029 return IRQ_EINT0 + offset;
1030
1031 if (offset < 8)
1032 return IRQ_EINT4 + offset - 4;
1033
1034 return -EINVAL;
1035}
1036#endif
1037
1038#ifdef CONFIG_PLAT_S3C64XX
1039static int s3c64xx_gpiolib_mbank_to_irq(struct gpio_chip *chip, unsigned pin)
1040{
1041 return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO;
1042}
1043
1044static int s3c64xx_gpiolib_lbank_to_irq(struct gpio_chip *chip, unsigned pin)
1045{
1046 return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO;
1047}
1048#endif
1049
1050struct samsung_gpio_chip s3c24xx_gpios[] = {
1051#ifdef CONFIG_PLAT_S3C24XX
1052 {
1053 .config = &s3c24xx_gpiocfg_banka,
1054 .chip = {
1055 .base = S3C2410_GPA(0),
1056 .owner = THIS_MODULE,
1057 .label = "GPIOA",
1058 .ngpio = 24,
1059 .direction_input = s3c24xx_gpiolib_banka_input,
1060 .direction_output = s3c24xx_gpiolib_banka_output,
1061 },
1062 }, {
1063 .chip = {
1064 .base = S3C2410_GPB(0),
1065 .owner = THIS_MODULE,
1066 .label = "GPIOB",
1067 .ngpio = 16,
1068 },
1069 }, {
1070 .chip = {
1071 .base = S3C2410_GPC(0),
1072 .owner = THIS_MODULE,
1073 .label = "GPIOC",
1074 .ngpio = 16,
1075 },
1076 }, {
1077 .chip = {
1078 .base = S3C2410_GPD(0),
1079 .owner = THIS_MODULE,
1080 .label = "GPIOD",
1081 .ngpio = 16,
1082 },
1083 }, {
1084 .chip = {
1085 .base = S3C2410_GPE(0),
1086 .label = "GPIOE",
1087 .owner = THIS_MODULE,
1088 .ngpio = 16,
1089 },
1090 }, {
1091 .chip = {
1092 .base = S3C2410_GPF(0),
1093 .owner = THIS_MODULE,
1094 .label = "GPIOF",
1095 .ngpio = 8,
1096 .to_irq = s3c24xx_gpiolib_fbank_to_irq,
1097 },
1098 }, {
1099 .irq_base = IRQ_EINT8,
1100 .chip = {
1101 .base = S3C2410_GPG(0),
1102 .owner = THIS_MODULE,
1103 .label = "GPIOG",
1104 .ngpio = 16,
1105 .to_irq = samsung_gpiolib_to_irq,
1106 },
1107 }, {
1108 .chip = {
1109 .base = S3C2410_GPH(0),
1110 .owner = THIS_MODULE,
1111 .label = "GPIOH",
1112 .ngpio = 11,
1113 },
1114 },
1115 /* GPIOS for the S3C2443 and later devices. */
1116 {
1117 .base = S3C2440_GPJCON,
1118 .chip = {
1119 .base = S3C2410_GPJ(0),
1120 .owner = THIS_MODULE,
1121 .label = "GPIOJ",
1122 .ngpio = 16,
1123 },
1124 }, {
1125 .base = S3C2443_GPKCON,
1126 .chip = {
1127 .base = S3C2410_GPK(0),
1128 .owner = THIS_MODULE,
1129 .label = "GPIOK",
1130 .ngpio = 16,
1131 },
1132 }, {
1133 .base = S3C2443_GPLCON,
1134 .chip = {
1135 .base = S3C2410_GPL(0),
1136 .owner = THIS_MODULE,
1137 .label = "GPIOL",
1138 .ngpio = 15,
1139 },
1140 }, {
1141 .base = S3C2443_GPMCON,
1142 .chip = {
1143 .base = S3C2410_GPM(0),
1144 .owner = THIS_MODULE,
1145 .label = "GPIOM",
1146 .ngpio = 2,
1147 },
1148 },
1149#endif
1150};
1151
1152/*
1153 * GPIO bank summary:
1154 *
1155 * Bank GPIOs Style SlpCon ExtInt Group
1156 * A 8 4Bit Yes 1
1157 * B 7 4Bit Yes 1
1158 * C 8 4Bit Yes 2
1159 * D 5 4Bit Yes 3
1160 * E 5 4Bit Yes None
1161 * F 16 2Bit Yes 4 [1]
1162 * G 7 4Bit Yes 5
1163 * H 10 4Bit[2] Yes 6
1164 * I 16 2Bit Yes None
1165 * J 12 2Bit Yes None
1166 * K 16 4Bit[2] No None
1167 * L 15 4Bit[2] No None
1168 * M 6 4Bit No IRQ_EINT
1169 * N 16 2Bit No IRQ_EINT
1170 * O 16 2Bit Yes 7
1171 * P 15 2Bit Yes 8
1172 * Q 9 2Bit Yes 9
1173 *
1174 * [1] BANKF pins 14,15 do not form part of the external interrupt sources
1175 * [2] BANK has two control registers, GPxCON0 and GPxCON1
1176 */
1177
1178static struct samsung_gpio_chip s3c64xx_gpios_4bit[] = {
1179#ifdef CONFIG_PLAT_S3C64XX
1180 {
1181 .chip = {
1182 .base = S3C64XX_GPA(0),
1183 .ngpio = S3C64XX_GPIO_A_NR,
1184 .label = "GPA",
1185 },
1186 }, {
1187 .chip = {
1188 .base = S3C64XX_GPB(0),
1189 .ngpio = S3C64XX_GPIO_B_NR,
1190 .label = "GPB",
1191 },
1192 }, {
1193 .chip = {
1194 .base = S3C64XX_GPC(0),
1195 .ngpio = S3C64XX_GPIO_C_NR,
1196 .label = "GPC",
1197 },
1198 }, {
1199 .chip = {
1200 .base = S3C64XX_GPD(0),
1201 .ngpio = S3C64XX_GPIO_D_NR,
1202 .label = "GPD",
1203 },
1204 }, {
1205 .config = &samsung_gpio_cfgs[0],
1206 .chip = {
1207 .base = S3C64XX_GPE(0),
1208 .ngpio = S3C64XX_GPIO_E_NR,
1209 .label = "GPE",
1210 },
1211 }, {
1212 .base = S3C64XX_GPG_BASE,
1213 .chip = {
1214 .base = S3C64XX_GPG(0),
1215 .ngpio = S3C64XX_GPIO_G_NR,
1216 .label = "GPG",
1217 },
1218 }, {
1219 .base = S3C64XX_GPM_BASE,
1220 .config = &samsung_gpio_cfgs[1],
1221 .chip = {
1222 .base = S3C64XX_GPM(0),
1223 .ngpio = S3C64XX_GPIO_M_NR,
1224 .label = "GPM",
1225 .to_irq = s3c64xx_gpiolib_mbank_to_irq,
1226 },
1227 },
1228#endif
1229};
1230
1231static struct samsung_gpio_chip s3c64xx_gpios_4bit2[] = {
1232#ifdef CONFIG_PLAT_S3C64XX
1233 {
1234 .base = S3C64XX_GPH_BASE + 0x4,
1235 .chip = {
1236 .base = S3C64XX_GPH(0),
1237 .ngpio = S3C64XX_GPIO_H_NR,
1238 .label = "GPH",
1239 },
1240 }, {
1241 .base = S3C64XX_GPK_BASE + 0x4,
1242 .config = &samsung_gpio_cfgs[0],
1243 .chip = {
1244 .base = S3C64XX_GPK(0),
1245 .ngpio = S3C64XX_GPIO_K_NR,
1246 .label = "GPK",
1247 },
1248 }, {
1249 .base = S3C64XX_GPL_BASE + 0x4,
1250 .config = &samsung_gpio_cfgs[1],
1251 .chip = {
1252 .base = S3C64XX_GPL(0),
1253 .ngpio = S3C64XX_GPIO_L_NR,
1254 .label = "GPL",
1255 .to_irq = s3c64xx_gpiolib_lbank_to_irq,
1256 },
1257 },
1258#endif
1259};
1260
1261static struct samsung_gpio_chip s3c64xx_gpios_2bit[] = {
1262#ifdef CONFIG_PLAT_S3C64XX
1263 {
1264 .base = S3C64XX_GPF_BASE,
1265 .config = &samsung_gpio_cfgs[6],
1266 .chip = {
1267 .base = S3C64XX_GPF(0),
1268 .ngpio = S3C64XX_GPIO_F_NR,
1269 .label = "GPF",
1270 },
1271 }, {
1272 .config = &samsung_gpio_cfgs[7],
1273 .chip = {
1274 .base = S3C64XX_GPI(0),
1275 .ngpio = S3C64XX_GPIO_I_NR,
1276 .label = "GPI",
1277 },
1278 }, {
1279 .config = &samsung_gpio_cfgs[7],
1280 .chip = {
1281 .base = S3C64XX_GPJ(0),
1282 .ngpio = S3C64XX_GPIO_J_NR,
1283 .label = "GPJ",
1284 },
1285 }, {
1286 .config = &samsung_gpio_cfgs[6],
1287 .chip = {
1288 .base = S3C64XX_GPO(0),
1289 .ngpio = S3C64XX_GPIO_O_NR,
1290 .label = "GPO",
1291 },
1292 }, {
1293 .config = &samsung_gpio_cfgs[6],
1294 .chip = {
1295 .base = S3C64XX_GPP(0),
1296 .ngpio = S3C64XX_GPIO_P_NR,
1297 .label = "GPP",
1298 },
1299 }, {
1300 .config = &samsung_gpio_cfgs[6],
1301 .chip = {
1302 .base = S3C64XX_GPQ(0),
1303 .ngpio = S3C64XX_GPIO_Q_NR,
1304 .label = "GPQ",
1305 },
1306 }, {
1307 .base = S3C64XX_GPN_BASE,
1308 .irq_base = IRQ_EINT(0),
1309 .config = &samsung_gpio_cfgs[5],
1310 .chip = {
1311 .base = S3C64XX_GPN(0),
1312 .ngpio = S3C64XX_GPIO_N_NR,
1313 .label = "GPN",
1314 .to_irq = samsung_gpiolib_to_irq,
1315 },
1316 },
1317#endif
1318};
1319
1320/*
1321 * S5P6440 GPIO bank summary:
1322 *
1323 * Bank GPIOs Style SlpCon ExtInt Group
1324 * A 6 4Bit Yes 1
1325 * B 7 4Bit Yes 1
1326 * C 8 4Bit Yes 2
1327 * F 2 2Bit Yes 4 [1]
1328 * G 7 4Bit Yes 5
1329 * H 10 4Bit[2] Yes 6
1330 * I 16 2Bit Yes None
1331 * J 12 2Bit Yes None
1332 * N 16 2Bit No IRQ_EINT
1333 * P 8 2Bit Yes 8
1334 * R 15 4Bit[2] Yes 8
1335 */
1336
1337static struct samsung_gpio_chip s5p6440_gpios_4bit[] = {
1338#ifdef CONFIG_CPU_S5P6440
1339 {
1340 .chip = {
1341 .base = S5P6440_GPA(0),
1342 .ngpio = S5P6440_GPIO_A_NR,
1343 .label = "GPA",
1344 },
1345 }, {
1346 .chip = {
1347 .base = S5P6440_GPB(0),
1348 .ngpio = S5P6440_GPIO_B_NR,
1349 .label = "GPB",
1350 },
1351 }, {
1352 .chip = {
1353 .base = S5P6440_GPC(0),
1354 .ngpio = S5P6440_GPIO_C_NR,
1355 .label = "GPC",
1356 },
1357 }, {
1358 .base = S5P64X0_GPG_BASE,
1359 .chip = {
1360 .base = S5P6440_GPG(0),
1361 .ngpio = S5P6440_GPIO_G_NR,
1362 .label = "GPG",
1363 },
1364 },
1365#endif
1366};
1367
1368static struct samsung_gpio_chip s5p6440_gpios_4bit2[] = {
1369#ifdef CONFIG_CPU_S5P6440
1370 {
1371 .base = S5P64X0_GPH_BASE + 0x4,
1372 .chip = {
1373 .base = S5P6440_GPH(0),
1374 .ngpio = S5P6440_GPIO_H_NR,
1375 .label = "GPH",
1376 },
1377 },
1378#endif
1379};
1380
1381static struct samsung_gpio_chip s5p6440_gpios_rbank[] = {
1382#ifdef CONFIG_CPU_S5P6440
1383 {
1384 .base = S5P64X0_GPR_BASE + 0x4,
1385 .config = &s5p64x0_gpio_cfg_rbank,
1386 .chip = {
1387 .base = S5P6440_GPR(0),
1388 .ngpio = S5P6440_GPIO_R_NR,
1389 .label = "GPR",
1390 },
1391 },
1392#endif
1393};
1394
1395static struct samsung_gpio_chip s5p6440_gpios_2bit[] = {
1396#ifdef CONFIG_CPU_S5P6440
1397 {
1398 .base = S5P64X0_GPF_BASE,
1399 .config = &samsung_gpio_cfgs[6],
1400 .chip = {
1401 .base = S5P6440_GPF(0),
1402 .ngpio = S5P6440_GPIO_F_NR,
1403 .label = "GPF",
1404 },
1405 }, {
1406 .base = S5P64X0_GPI_BASE,
1407 .config = &samsung_gpio_cfgs[4],
1408 .chip = {
1409 .base = S5P6440_GPI(0),
1410 .ngpio = S5P6440_GPIO_I_NR,
1411 .label = "GPI",
1412 },
1413 }, {
1414 .base = S5P64X0_GPJ_BASE,
1415 .config = &samsung_gpio_cfgs[4],
1416 .chip = {
1417 .base = S5P6440_GPJ(0),
1418 .ngpio = S5P6440_GPIO_J_NR,
1419 .label = "GPJ",
1420 },
1421 }, {
1422 .base = S5P64X0_GPN_BASE,
1423 .config = &samsung_gpio_cfgs[5],
1424 .chip = {
1425 .base = S5P6440_GPN(0),
1426 .ngpio = S5P6440_GPIO_N_NR,
1427 .label = "GPN",
1428 },
1429 }, {
1430 .base = S5P64X0_GPP_BASE,
1431 .config = &samsung_gpio_cfgs[6],
1432 .chip = {
1433 .base = S5P6440_GPP(0),
1434 .ngpio = S5P6440_GPIO_P_NR,
1435 .label = "GPP",
1436 },
1437 },
1438#endif
1439};
1440
1441/*
1442 * S5P6450 GPIO bank summary:
1443 *
1444 * Bank GPIOs Style SlpCon ExtInt Group
1445 * A 6 4Bit Yes 1
1446 * B 7 4Bit Yes 1
1447 * C 8 4Bit Yes 2
1448 * D 8 4Bit Yes None
1449 * F 2 2Bit Yes None
1450 * G 14 4Bit[2] Yes 5
1451 * H 10 4Bit[2] Yes 6
1452 * I 16 2Bit Yes None
1453 * J 12 2Bit Yes None
1454 * K 5 4Bit Yes None
1455 * N 16 2Bit No IRQ_EINT
1456 * P 11 2Bit Yes 8
1457 * Q 14 2Bit Yes None
1458 * R 15 4Bit[2] Yes None
1459 * S 8 2Bit Yes None
1460 *
1461 * [1] BANKF pins 14,15 do not form part of the external interrupt sources
1462 * [2] BANK has two control registers, GPxCON0 and GPxCON1
1463 */
1464
1465static struct samsung_gpio_chip s5p6450_gpios_4bit[] = {
1466#ifdef CONFIG_CPU_S5P6450
1467 {
1468 .chip = {
1469 .base = S5P6450_GPA(0),
1470 .ngpio = S5P6450_GPIO_A_NR,
1471 .label = "GPA",
1472 },
1473 }, {
1474 .chip = {
1475 .base = S5P6450_GPB(0),
1476 .ngpio = S5P6450_GPIO_B_NR,
1477 .label = "GPB",
1478 },
1479 }, {
1480 .chip = {
1481 .base = S5P6450_GPC(0),
1482 .ngpio = S5P6450_GPIO_C_NR,
1483 .label = "GPC",
1484 },
1485 }, {
1486 .chip = {
1487 .base = S5P6450_GPD(0),
1488 .ngpio = S5P6450_GPIO_D_NR,
1489 .label = "GPD",
1490 },
1491 }, {
1492 .base = S5P6450_GPK_BASE,
1493 .chip = {
1494 .base = S5P6450_GPK(0),
1495 .ngpio = S5P6450_GPIO_K_NR,
1496 .label = "GPK",
1497 },
1498 },
1499#endif
1500};
1501
1502static struct samsung_gpio_chip s5p6450_gpios_4bit2[] = {
1503#ifdef CONFIG_CPU_S5P6450
1504 {
1505 .base = S5P64X0_GPG_BASE + 0x4,
1506 .chip = {
1507 .base = S5P6450_GPG(0),
1508 .ngpio = S5P6450_GPIO_G_NR,
1509 .label = "GPG",
1510 },
1511 }, {
1512 .base = S5P64X0_GPH_BASE + 0x4,
1513 .chip = {
1514 .base = S5P6450_GPH(0),
1515 .ngpio = S5P6450_GPIO_H_NR,
1516 .label = "GPH",
1517 },
1518 },
1519#endif
1520};
1521
1522static struct samsung_gpio_chip s5p6450_gpios_rbank[] = {
1523#ifdef CONFIG_CPU_S5P6450
1524 {
1525 .base = S5P64X0_GPR_BASE + 0x4,
1526 .config = &s5p64x0_gpio_cfg_rbank,
1527 .chip = {
1528 .base = S5P6450_GPR(0),
1529 .ngpio = S5P6450_GPIO_R_NR,
1530 .label = "GPR",
1531 },
1532 },
1533#endif
1534};
1535
1536static struct samsung_gpio_chip s5p6450_gpios_2bit[] = {
1537#ifdef CONFIG_CPU_S5P6450
1538 {
1539 .base = S5P64X0_GPF_BASE,
1540 .config = &samsung_gpio_cfgs[6],
1541 .chip = {
1542 .base = S5P6450_GPF(0),
1543 .ngpio = S5P6450_GPIO_F_NR,
1544 .label = "GPF",
1545 },
1546 }, {
1547 .base = S5P64X0_GPI_BASE,
1548 .config = &samsung_gpio_cfgs[4],
1549 .chip = {
1550 .base = S5P6450_GPI(0),
1551 .ngpio = S5P6450_GPIO_I_NR,
1552 .label = "GPI",
1553 },
1554 }, {
1555 .base = S5P64X0_GPJ_BASE,
1556 .config = &samsung_gpio_cfgs[4],
1557 .chip = {
1558 .base = S5P6450_GPJ(0),
1559 .ngpio = S5P6450_GPIO_J_NR,
1560 .label = "GPJ",
1561 },
1562 }, {
1563 .base = S5P64X0_GPN_BASE,
1564 .config = &samsung_gpio_cfgs[5],
1565 .chip = {
1566 .base = S5P6450_GPN(0),
1567 .ngpio = S5P6450_GPIO_N_NR,
1568 .label = "GPN",
1569 },
1570 }, {
1571 .base = S5P64X0_GPP_BASE,
1572 .config = &samsung_gpio_cfgs[6],
1573 .chip = {
1574 .base = S5P6450_GPP(0),
1575 .ngpio = S5P6450_GPIO_P_NR,
1576 .label = "GPP",
1577 },
1578 }, {
1579 .base = S5P6450_GPQ_BASE,
1580 .config = &samsung_gpio_cfgs[5],
1581 .chip = {
1582 .base = S5P6450_GPQ(0),
1583 .ngpio = S5P6450_GPIO_Q_NR,
1584 .label = "GPQ",
1585 },
1586 }, {
1587 .base = S5P6450_GPS_BASE,
1588 .config = &samsung_gpio_cfgs[6],
1589 .chip = {
1590 .base = S5P6450_GPS(0),
1591 .ngpio = S5P6450_GPIO_S_NR,
1592 .label = "GPS",
1593 },
1594 },
1595#endif
1596};
1597
1598/*
1599 * S5PC100 GPIO bank summary:
1600 *
1601 * Bank GPIOs Style INT Type
1602 * A0 8 4Bit GPIO_INT0
1603 * A1 5 4Bit GPIO_INT1
1604 * B 8 4Bit GPIO_INT2
1605 * C 5 4Bit GPIO_INT3
1606 * D 7 4Bit GPIO_INT4
1607 * E0 8 4Bit GPIO_INT5
1608 * E1 6 4Bit GPIO_INT6
1609 * F0 8 4Bit GPIO_INT7
1610 * F1 8 4Bit GPIO_INT8
1611 * F2 8 4Bit GPIO_INT9
1612 * F3 4 4Bit GPIO_INT10
1613 * G0 8 4Bit GPIO_INT11
1614 * G1 3 4Bit GPIO_INT12
1615 * G2 7 4Bit GPIO_INT13
1616 * G3 7 4Bit GPIO_INT14
1617 * H0 8 4Bit WKUP_INT
1618 * H1 8 4Bit WKUP_INT
1619 * H2 8 4Bit WKUP_INT
1620 * H3 8 4Bit WKUP_INT
1621 * I 8 4Bit GPIO_INT15
1622 * J0 8 4Bit GPIO_INT16
1623 * J1 5 4Bit GPIO_INT17
1624 * J2 8 4Bit GPIO_INT18
1625 * J3 8 4Bit GPIO_INT19
1626 * J4 4 4Bit GPIO_INT20
1627 * K0 8 4Bit None
1628 * K1 6 4Bit None
1629 * K2 8 4Bit None
1630 * K3 8 4Bit None
1631 * L0 8 4Bit None
1632 * L1 8 4Bit None
1633 * L2 8 4Bit None
1634 * L3 8 4Bit None
1635 */
1636
1637static struct samsung_gpio_chip s5pc100_gpios_4bit[] = {
1638#ifdef CONFIG_CPU_S5PC100
1639 {
1640 .chip = {
1641 .base = S5PC100_GPA0(0),
1642 .ngpio = S5PC100_GPIO_A0_NR,
1643 .label = "GPA0",
1644 },
1645 }, {
1646 .chip = {
1647 .base = S5PC100_GPA1(0),
1648 .ngpio = S5PC100_GPIO_A1_NR,
1649 .label = "GPA1",
1650 },
1651 }, {
1652 .chip = {
1653 .base = S5PC100_GPB(0),
1654 .ngpio = S5PC100_GPIO_B_NR,
1655 .label = "GPB",
1656 },
1657 }, {
1658 .chip = {
1659 .base = S5PC100_GPC(0),
1660 .ngpio = S5PC100_GPIO_C_NR,
1661 .label = "GPC",
1662 },
1663 }, {
1664 .chip = {
1665 .base = S5PC100_GPD(0),
1666 .ngpio = S5PC100_GPIO_D_NR,
1667 .label = "GPD",
1668 },
1669 }, {
1670 .chip = {
1671 .base = S5PC100_GPE0(0),
1672 .ngpio = S5PC100_GPIO_E0_NR,
1673 .label = "GPE0",
1674 },
1675 }, {
1676 .chip = {
1677 .base = S5PC100_GPE1(0),
1678 .ngpio = S5PC100_GPIO_E1_NR,
1679 .label = "GPE1",
1680 },
1681 }, {
1682 .chip = {
1683 .base = S5PC100_GPF0(0),
1684 .ngpio = S5PC100_GPIO_F0_NR,
1685 .label = "GPF0",
1686 },
1687 }, {
1688 .chip = {
1689 .base = S5PC100_GPF1(0),
1690 .ngpio = S5PC100_GPIO_F1_NR,
1691 .label = "GPF1",
1692 },
1693 }, {
1694 .chip = {
1695 .base = S5PC100_GPF2(0),
1696 .ngpio = S5PC100_GPIO_F2_NR,
1697 .label = "GPF2",
1698 },
1699 }, {
1700 .chip = {
1701 .base = S5PC100_GPF3(0),
1702 .ngpio = S5PC100_GPIO_F3_NR,
1703 .label = "GPF3",
1704 },
1705 }, {
1706 .chip = {
1707 .base = S5PC100_GPG0(0),
1708 .ngpio = S5PC100_GPIO_G0_NR,
1709 .label = "GPG0",
1710 },
1711 }, {
1712 .chip = {
1713 .base = S5PC100_GPG1(0),
1714 .ngpio = S5PC100_GPIO_G1_NR,
1715 .label = "GPG1",
1716 },
1717 }, {
1718 .chip = {
1719 .base = S5PC100_GPG2(0),
1720 .ngpio = S5PC100_GPIO_G2_NR,
1721 .label = "GPG2",
1722 },
1723 }, {
1724 .chip = {
1725 .base = S5PC100_GPG3(0),
1726 .ngpio = S5PC100_GPIO_G3_NR,
1727 .label = "GPG3",
1728 },
1729 }, {
1730 .chip = {
1731 .base = S5PC100_GPI(0),
1732 .ngpio = S5PC100_GPIO_I_NR,
1733 .label = "GPI",
1734 },
1735 }, {
1736 .chip = {
1737 .base = S5PC100_GPJ0(0),
1738 .ngpio = S5PC100_GPIO_J0_NR,
1739 .label = "GPJ0",
1740 },
1741 }, {
1742 .chip = {
1743 .base = S5PC100_GPJ1(0),
1744 .ngpio = S5PC100_GPIO_J1_NR,
1745 .label = "GPJ1",
1746 },
1747 }, {
1748 .chip = {
1749 .base = S5PC100_GPJ2(0),
1750 .ngpio = S5PC100_GPIO_J2_NR,
1751 .label = "GPJ2",
1752 },
1753 }, {
1754 .chip = {
1755 .base = S5PC100_GPJ3(0),
1756 .ngpio = S5PC100_GPIO_J3_NR,
1757 .label = "GPJ3",
1758 },
1759 }, {
1760 .chip = {
1761 .base = S5PC100_GPJ4(0),
1762 .ngpio = S5PC100_GPIO_J4_NR,
1763 .label = "GPJ4",
1764 },
1765 }, {
1766 .chip = {
1767 .base = S5PC100_GPK0(0),
1768 .ngpio = S5PC100_GPIO_K0_NR,
1769 .label = "GPK0",
1770 },
1771 }, {
1772 .chip = {
1773 .base = S5PC100_GPK1(0),
1774 .ngpio = S5PC100_GPIO_K1_NR,
1775 .label = "GPK1",
1776 },
1777 }, {
1778 .chip = {
1779 .base = S5PC100_GPK2(0),
1780 .ngpio = S5PC100_GPIO_K2_NR,
1781 .label = "GPK2",
1782 },
1783 }, {
1784 .chip = {
1785 .base = S5PC100_GPK3(0),
1786 .ngpio = S5PC100_GPIO_K3_NR,
1787 .label = "GPK3",
1788 },
1789 }, {
1790 .chip = {
1791 .base = S5PC100_GPL0(0),
1792 .ngpio = S5PC100_GPIO_L0_NR,
1793 .label = "GPL0",
1794 },
1795 }, {
1796 .chip = {
1797 .base = S5PC100_GPL1(0),
1798 .ngpio = S5PC100_GPIO_L1_NR,
1799 .label = "GPL1",
1800 },
1801 }, {
1802 .chip = {
1803 .base = S5PC100_GPL2(0),
1804 .ngpio = S5PC100_GPIO_L2_NR,
1805 .label = "GPL2",
1806 },
1807 }, {
1808 .chip = {
1809 .base = S5PC100_GPL3(0),
1810 .ngpio = S5PC100_GPIO_L3_NR,
1811 .label = "GPL3",
1812 },
1813 }, {
1814 .chip = {
1815 .base = S5PC100_GPL4(0),
1816 .ngpio = S5PC100_GPIO_L4_NR,
1817 .label = "GPL4",
1818 },
1819 }, {
1820 .base = (S5P_VA_GPIO + 0xC00),
1821 .irq_base = IRQ_EINT(0),
1822 .chip = {
1823 .base = S5PC100_GPH0(0),
1824 .ngpio = S5PC100_GPIO_H0_NR,
1825 .label = "GPH0",
1826 .to_irq = samsung_gpiolib_to_irq,
1827 },
1828 }, {
1829 .base = (S5P_VA_GPIO + 0xC20),
1830 .irq_base = IRQ_EINT(8),
1831 .chip = {
1832 .base = S5PC100_GPH1(0),
1833 .ngpio = S5PC100_GPIO_H1_NR,
1834 .label = "GPH1",
1835 .to_irq = samsung_gpiolib_to_irq,
1836 },
1837 }, {
1838 .base = (S5P_VA_GPIO + 0xC40),
1839 .irq_base = IRQ_EINT(16),
1840 .chip = {
1841 .base = S5PC100_GPH2(0),
1842 .ngpio = S5PC100_GPIO_H2_NR,
1843 .label = "GPH2",
1844 .to_irq = samsung_gpiolib_to_irq,
1845 },
1846 }, {
1847 .base = (S5P_VA_GPIO + 0xC60),
1848 .irq_base = IRQ_EINT(24),
1849 .chip = {
1850 .base = S5PC100_GPH3(0),
1851 .ngpio = S5PC100_GPIO_H3_NR,
1852 .label = "GPH3",
1853 .to_irq = samsung_gpiolib_to_irq,
1854 },
1855 },
1856#endif
1857};
1858
1859/*
1860 * Followings are the gpio banks in S5PV210/S5PC110
1861 *
1862 * The 'config' member when left to NULL, is initialized to the default
1863 * structure samsung_gpio_cfgs[4] in the init function below.
1864 *
1865 * The 'base' member is also initialized in the init function below.
1866 * Note: The initialization of 'base' member of samsung_gpio_chip structure
1867 * uses the above macro and depends on the banks being listed in order here.
1868 */
1869
1870static struct samsung_gpio_chip s5pv210_gpios_4bit[] = {
1871#ifdef CONFIG_CPU_S5PV210
1872 {
1873 .chip = {
1874 .base = S5PV210_GPA0(0),
1875 .ngpio = S5PV210_GPIO_A0_NR,
1876 .label = "GPA0",
1877 },
1878 }, {
1879 .chip = {
1880 .base = S5PV210_GPA1(0),
1881 .ngpio = S5PV210_GPIO_A1_NR,
1882 .label = "GPA1",
1883 },
1884 }, {
1885 .chip = {
1886 .base = S5PV210_GPB(0),
1887 .ngpio = S5PV210_GPIO_B_NR,
1888 .label = "GPB",
1889 },
1890 }, {
1891 .chip = {
1892 .base = S5PV210_GPC0(0),
1893 .ngpio = S5PV210_GPIO_C0_NR,
1894 .label = "GPC0",
1895 },
1896 }, {
1897 .chip = {
1898 .base = S5PV210_GPC1(0),
1899 .ngpio = S5PV210_GPIO_C1_NR,
1900 .label = "GPC1",
1901 },
1902 }, {
1903 .chip = {
1904 .base = S5PV210_GPD0(0),
1905 .ngpio = S5PV210_GPIO_D0_NR,
1906 .label = "GPD0",
1907 },
1908 }, {
1909 .chip = {
1910 .base = S5PV210_GPD1(0),
1911 .ngpio = S5PV210_GPIO_D1_NR,
1912 .label = "GPD1",
1913 },
1914 }, {
1915 .chip = {
1916 .base = S5PV210_GPE0(0),
1917 .ngpio = S5PV210_GPIO_E0_NR,
1918 .label = "GPE0",
1919 },
1920 }, {
1921 .chip = {
1922 .base = S5PV210_GPE1(0),
1923 .ngpio = S5PV210_GPIO_E1_NR,
1924 .label = "GPE1",
1925 },
1926 }, {
1927 .chip = {
1928 .base = S5PV210_GPF0(0),
1929 .ngpio = S5PV210_GPIO_F0_NR,
1930 .label = "GPF0",
1931 },
1932 }, {
1933 .chip = {
1934 .base = S5PV210_GPF1(0),
1935 .ngpio = S5PV210_GPIO_F1_NR,
1936 .label = "GPF1",
1937 },
1938 }, {
1939 .chip = {
1940 .base = S5PV210_GPF2(0),
1941 .ngpio = S5PV210_GPIO_F2_NR,
1942 .label = "GPF2",
1943 },
1944 }, {
1945 .chip = {
1946 .base = S5PV210_GPF3(0),
1947 .ngpio = S5PV210_GPIO_F3_NR,
1948 .label = "GPF3",
1949 },
1950 }, {
1951 .chip = {
1952 .base = S5PV210_GPG0(0),
1953 .ngpio = S5PV210_GPIO_G0_NR,
1954 .label = "GPG0",
1955 },
1956 }, {
1957 .chip = {
1958 .base = S5PV210_GPG1(0),
1959 .ngpio = S5PV210_GPIO_G1_NR,
1960 .label = "GPG1",
1961 },
1962 }, {
1963 .chip = {
1964 .base = S5PV210_GPG2(0),
1965 .ngpio = S5PV210_GPIO_G2_NR,
1966 .label = "GPG2",
1967 },
1968 }, {
1969 .chip = {
1970 .base = S5PV210_GPG3(0),
1971 .ngpio = S5PV210_GPIO_G3_NR,
1972 .label = "GPG3",
1973 },
1974 }, {
1975 .chip = {
1976 .base = S5PV210_GPI(0),
1977 .ngpio = S5PV210_GPIO_I_NR,
1978 .label = "GPI",
1979 },
1980 }, {
1981 .chip = {
1982 .base = S5PV210_GPJ0(0),
1983 .ngpio = S5PV210_GPIO_J0_NR,
1984 .label = "GPJ0",
1985 },
1986 }, {
1987 .chip = {
1988 .base = S5PV210_GPJ1(0),
1989 .ngpio = S5PV210_GPIO_J1_NR,
1990 .label = "GPJ1",
1991 },
1992 }, {
1993 .chip = {
1994 .base = S5PV210_GPJ2(0),
1995 .ngpio = S5PV210_GPIO_J2_NR,
1996 .label = "GPJ2",
1997 },
1998 }, {
1999 .chip = {
2000 .base = S5PV210_GPJ3(0),
2001 .ngpio = S5PV210_GPIO_J3_NR,
2002 .label = "GPJ3",
2003 },
2004 }, {
2005 .chip = {
2006 .base = S5PV210_GPJ4(0),
2007 .ngpio = S5PV210_GPIO_J4_NR,
2008 .label = "GPJ4",
2009 },
2010 }, {
2011 .chip = {
2012 .base = S5PV210_MP01(0),
2013 .ngpio = S5PV210_GPIO_MP01_NR,
2014 .label = "MP01",
2015 },
2016 }, {
2017 .chip = {
2018 .base = S5PV210_MP02(0),
2019 .ngpio = S5PV210_GPIO_MP02_NR,
2020 .label = "MP02",
2021 },
2022 }, {
2023 .chip = {
2024 .base = S5PV210_MP03(0),
2025 .ngpio = S5PV210_GPIO_MP03_NR,
2026 .label = "MP03",
2027 },
2028 }, {
2029 .chip = {
2030 .base = S5PV210_MP04(0),
2031 .ngpio = S5PV210_GPIO_MP04_NR,
2032 .label = "MP04",
2033 },
2034 }, {
2035 .chip = {
2036 .base = S5PV210_MP05(0),
2037 .ngpio = S5PV210_GPIO_MP05_NR,
2038 .label = "MP05",
2039 },
2040 }, {
2041 .base = (S5P_VA_GPIO + 0xC00),
2042 .irq_base = IRQ_EINT(0),
2043 .chip = {
2044 .base = S5PV210_GPH0(0),
2045 .ngpio = S5PV210_GPIO_H0_NR,
2046 .label = "GPH0",
2047 .to_irq = samsung_gpiolib_to_irq,
2048 },
2049 }, {
2050 .base = (S5P_VA_GPIO + 0xC20),
2051 .irq_base = IRQ_EINT(8),
2052 .chip = {
2053 .base = S5PV210_GPH1(0),
2054 .ngpio = S5PV210_GPIO_H1_NR,
2055 .label = "GPH1",
2056 .to_irq = samsung_gpiolib_to_irq,
2057 },
2058 }, {
2059 .base = (S5P_VA_GPIO + 0xC40),
2060 .irq_base = IRQ_EINT(16),
2061 .chip = {
2062 .base = S5PV210_GPH2(0),
2063 .ngpio = S5PV210_GPIO_H2_NR,
2064 .label = "GPH2",
2065 .to_irq = samsung_gpiolib_to_irq,
2066 },
2067 }, {
2068 .base = (S5P_VA_GPIO + 0xC60),
2069 .irq_base = IRQ_EINT(24),
2070 .chip = {
2071 .base = S5PV210_GPH3(0),
2072 .ngpio = S5PV210_GPIO_H3_NR,
2073 .label = "GPH3",
2074 .to_irq = samsung_gpiolib_to_irq,
2075 },
2076 },
2077#endif
2078};
2079
2080/*
2081 * Followings are the gpio banks in EXYNOS4210
2082 *
2083 * The 'config' member when left to NULL, is initialized to the default
2084 * structure samsung_gpio_cfgs[4] in the init function below.
2085 *
2086 * The 'base' member is also initialized in the init function below.
2087 * Note: The initialization of 'base' member of samsung_gpio_chip structure
2088 * uses the above macro and depends on the banks being listed in order here.
2089 */
2090
2091static struct samsung_gpio_chip exynos4_gpios_1[] = {
2092#ifdef CONFIG_ARCH_EXYNOS4
2093 {
2094 .chip = {
2095 .base = EXYNOS4_GPA0(0),
2096 .ngpio = EXYNOS4_GPIO_A0_NR,
2097 .label = "GPA0",
2098 },
2099 }, {
2100 .chip = {
2101 .base = EXYNOS4_GPA1(0),
2102 .ngpio = EXYNOS4_GPIO_A1_NR,
2103 .label = "GPA1",
2104 },
2105 }, {
2106 .chip = {
2107 .base = EXYNOS4_GPB(0),
2108 .ngpio = EXYNOS4_GPIO_B_NR,
2109 .label = "GPB",
2110 },
2111 }, {
2112 .chip = {
2113 .base = EXYNOS4_GPC0(0),
2114 .ngpio = EXYNOS4_GPIO_C0_NR,
2115 .label = "GPC0",
2116 },
2117 }, {
2118 .chip = {
2119 .base = EXYNOS4_GPC1(0),
2120 .ngpio = EXYNOS4_GPIO_C1_NR,
2121 .label = "GPC1",
2122 },
2123 }, {
2124 .chip = {
2125 .base = EXYNOS4_GPD0(0),
2126 .ngpio = EXYNOS4_GPIO_D0_NR,
2127 .label = "GPD0",
2128 },
2129 }, {
2130 .chip = {
2131 .base = EXYNOS4_GPD1(0),
2132 .ngpio = EXYNOS4_GPIO_D1_NR,
2133 .label = "GPD1",
2134 },
2135 }, {
2136 .chip = {
2137 .base = EXYNOS4_GPE0(0),
2138 .ngpio = EXYNOS4_GPIO_E0_NR,
2139 .label = "GPE0",
2140 },
2141 }, {
2142 .chip = {
2143 .base = EXYNOS4_GPE1(0),
2144 .ngpio = EXYNOS4_GPIO_E1_NR,
2145 .label = "GPE1",
2146 },
2147 }, {
2148 .chip = {
2149 .base = EXYNOS4_GPE2(0),
2150 .ngpio = EXYNOS4_GPIO_E2_NR,
2151 .label = "GPE2",
2152 },
2153 }, {
2154 .chip = {
2155 .base = EXYNOS4_GPE3(0),
2156 .ngpio = EXYNOS4_GPIO_E3_NR,
2157 .label = "GPE3",
2158 },
2159 }, {
2160 .chip = {
2161 .base = EXYNOS4_GPE4(0),
2162 .ngpio = EXYNOS4_GPIO_E4_NR,
2163 .label = "GPE4",
2164 },
2165 }, {
2166 .chip = {
2167 .base = EXYNOS4_GPF0(0),
2168 .ngpio = EXYNOS4_GPIO_F0_NR,
2169 .label = "GPF0",
2170 },
2171 }, {
2172 .chip = {
2173 .base = EXYNOS4_GPF1(0),
2174 .ngpio = EXYNOS4_GPIO_F1_NR,
2175 .label = "GPF1",
2176 },
2177 }, {
2178 .chip = {
2179 .base = EXYNOS4_GPF2(0),
2180 .ngpio = EXYNOS4_GPIO_F2_NR,
2181 .label = "GPF2",
2182 },
2183 }, {
2184 .chip = {
2185 .base = EXYNOS4_GPF3(0),
2186 .ngpio = EXYNOS4_GPIO_F3_NR,
2187 .label = "GPF3",
2188 },
2189 },
2190#endif
2191};
2192
2193static struct samsung_gpio_chip exynos4_gpios_2[] = {
2194#ifdef CONFIG_ARCH_EXYNOS4
2195 {
2196 .chip = {
2197 .base = EXYNOS4_GPJ0(0),
2198 .ngpio = EXYNOS4_GPIO_J0_NR,
2199 .label = "GPJ0",
2200 },
2201 }, {
2202 .chip = {
2203 .base = EXYNOS4_GPJ1(0),
2204 .ngpio = EXYNOS4_GPIO_J1_NR,
2205 .label = "GPJ1",
2206 },
2207 }, {
2208 .chip = {
2209 .base = EXYNOS4_GPK0(0),
2210 .ngpio = EXYNOS4_GPIO_K0_NR,
2211 .label = "GPK0",
2212 },
2213 }, {
2214 .chip = {
2215 .base = EXYNOS4_GPK1(0),
2216 .ngpio = EXYNOS4_GPIO_K1_NR,
2217 .label = "GPK1",
2218 },
2219 }, {
2220 .chip = {
2221 .base = EXYNOS4_GPK2(0),
2222 .ngpio = EXYNOS4_GPIO_K2_NR,
2223 .label = "GPK2",
2224 },
2225 }, {
2226 .chip = {
2227 .base = EXYNOS4_GPK3(0),
2228 .ngpio = EXYNOS4_GPIO_K3_NR,
2229 .label = "GPK3",
2230 },
2231 }, {
2232 .chip = {
2233 .base = EXYNOS4_GPL0(0),
2234 .ngpio = EXYNOS4_GPIO_L0_NR,
2235 .label = "GPL0",
2236 },
2237 }, {
2238 .chip = {
2239 .base = EXYNOS4_GPL1(0),
2240 .ngpio = EXYNOS4_GPIO_L1_NR,
2241 .label = "GPL1",
2242 },
2243 }, {
2244 .chip = {
2245 .base = EXYNOS4_GPL2(0),
2246 .ngpio = EXYNOS4_GPIO_L2_NR,
2247 .label = "GPL2",
2248 },
2249 }, {
2250 .config = &samsung_gpio_cfgs[4],
2251 .chip = {
2252 .base = EXYNOS4_GPY0(0),
2253 .ngpio = EXYNOS4_GPIO_Y0_NR,
2254 .label = "GPY0",
2255 },
2256 }, {
2257 .config = &samsung_gpio_cfgs[4],
2258 .chip = {
2259 .base = EXYNOS4_GPY1(0),
2260 .ngpio = EXYNOS4_GPIO_Y1_NR,
2261 .label = "GPY1",
2262 },
2263 }, {
2264 .config = &samsung_gpio_cfgs[4],
2265 .chip = {
2266 .base = EXYNOS4_GPY2(0),
2267 .ngpio = EXYNOS4_GPIO_Y2_NR,
2268 .label = "GPY2",
2269 },
2270 }, {
2271 .config = &samsung_gpio_cfgs[4],
2272 .chip = {
2273 .base = EXYNOS4_GPY3(0),
2274 .ngpio = EXYNOS4_GPIO_Y3_NR,
2275 .label = "GPY3",
2276 },
2277 }, {
2278 .config = &samsung_gpio_cfgs[4],
2279 .chip = {
2280 .base = EXYNOS4_GPY4(0),
2281 .ngpio = EXYNOS4_GPIO_Y4_NR,
2282 .label = "GPY4",
2283 },
2284 }, {
2285 .config = &samsung_gpio_cfgs[4],
2286 .chip = {
2287 .base = EXYNOS4_GPY5(0),
2288 .ngpio = EXYNOS4_GPIO_Y5_NR,
2289 .label = "GPY5",
2290 },
2291 }, {
2292 .config = &samsung_gpio_cfgs[4],
2293 .chip = {
2294 .base = EXYNOS4_GPY6(0),
2295 .ngpio = EXYNOS4_GPIO_Y6_NR,
2296 .label = "GPY6",
2297 },
2298 }, {
2299 .base = (S5P_VA_GPIO2 + 0xC00),
2300 .config = &samsung_gpio_cfgs[4],
2301 .irq_base = IRQ_EINT(0),
2302 .chip = {
2303 .base = EXYNOS4_GPX0(0),
2304 .ngpio = EXYNOS4_GPIO_X0_NR,
2305 .label = "GPX0",
2306 .to_irq = samsung_gpiolib_to_irq,
2307 },
2308 }, {
2309 .base = (S5P_VA_GPIO2 + 0xC20),
2310 .config = &samsung_gpio_cfgs[4],
2311 .irq_base = IRQ_EINT(8),
2312 .chip = {
2313 .base = EXYNOS4_GPX1(0),
2314 .ngpio = EXYNOS4_GPIO_X1_NR,
2315 .label = "GPX1",
2316 .to_irq = samsung_gpiolib_to_irq,
2317 },
2318 }, {
2319 .base = (S5P_VA_GPIO2 + 0xC40),
2320 .config = &samsung_gpio_cfgs[4],
2321 .irq_base = IRQ_EINT(16),
2322 .chip = {
2323 .base = EXYNOS4_GPX2(0),
2324 .ngpio = EXYNOS4_GPIO_X2_NR,
2325 .label = "GPX2",
2326 .to_irq = samsung_gpiolib_to_irq,
2327 },
2328 }, {
2329 .base = (S5P_VA_GPIO2 + 0xC60),
2330 .config = &samsung_gpio_cfgs[4],
2331 .irq_base = IRQ_EINT(24),
2332 .chip = {
2333 .base = EXYNOS4_GPX3(0),
2334 .ngpio = EXYNOS4_GPIO_X3_NR,
2335 .label = "GPX3",
2336 .to_irq = samsung_gpiolib_to_irq,
2337 },
2338 },
2339#endif
2340};
2341
2342static struct samsung_gpio_chip exynos4_gpios_3[] = {
2343#ifdef CONFIG_ARCH_EXYNOS4
2344 {
2345 .chip = {
2346 .base = EXYNOS4_GPZ(0),
2347 .ngpio = EXYNOS4_GPIO_Z_NR,
2348 .label = "GPZ",
2349 },
2350 },
2351#endif
2352};
2353
2354/* TODO: cleanup soc_is_* */
2355static __init int samsung_gpiolib_init(void)
2356{
2357 struct samsung_gpio_chip *chip;
2358 int i, nr_chips;
2359 int group = 0;
2360
2361 samsung_gpiolib_set_cfg(samsung_gpio_cfgs, ARRAY_SIZE(samsung_gpio_cfgs));
2362
2363 if (soc_is_s3c24xx()) {
2364 s3c24xx_gpiolib_add_chips(s3c24xx_gpios,
2365 ARRAY_SIZE(s3c24xx_gpios), S3C24XX_VA_GPIO);
2366 } else if (soc_is_s3c64xx()) {
2367 samsung_gpiolib_add_2bit_chips(s3c64xx_gpios_2bit,
2368 ARRAY_SIZE(s3c64xx_gpios_2bit),
2369 S3C64XX_VA_GPIO + 0xE0, 0x20);
2370 samsung_gpiolib_add_4bit_chips(s3c64xx_gpios_4bit,
2371 ARRAY_SIZE(s3c64xx_gpios_4bit),
2372 S3C64XX_VA_GPIO);
2373 samsung_gpiolib_add_4bit2_chips(s3c64xx_gpios_4bit2,
2374 ARRAY_SIZE(s3c64xx_gpios_4bit2));
2375 } else if (soc_is_s5p6440()) {
2376 samsung_gpiolib_add_2bit_chips(s5p6440_gpios_2bit,
2377 ARRAY_SIZE(s5p6440_gpios_2bit), NULL, 0x0);
2378 samsung_gpiolib_add_4bit_chips(s5p6440_gpios_4bit,
2379 ARRAY_SIZE(s5p6440_gpios_4bit), S5P_VA_GPIO);
2380 samsung_gpiolib_add_4bit2_chips(s5p6440_gpios_4bit2,
2381 ARRAY_SIZE(s5p6440_gpios_4bit2));
2382 s5p64x0_gpiolib_add_rbank(s5p6440_gpios_rbank,
2383 ARRAY_SIZE(s5p6440_gpios_rbank));
2384 } else if (soc_is_s5p6450()) {
2385 samsung_gpiolib_add_2bit_chips(s5p6450_gpios_2bit,
2386 ARRAY_SIZE(s5p6450_gpios_2bit), NULL, 0x0);
2387 samsung_gpiolib_add_4bit_chips(s5p6450_gpios_4bit,
2388 ARRAY_SIZE(s5p6450_gpios_4bit), S5P_VA_GPIO);
2389 samsung_gpiolib_add_4bit2_chips(s5p6450_gpios_4bit2,
2390 ARRAY_SIZE(s5p6450_gpios_4bit2));
2391 s5p64x0_gpiolib_add_rbank(s5p6450_gpios_rbank,
2392 ARRAY_SIZE(s5p6450_gpios_rbank));
2393 } else if (soc_is_s5pc100()) {
2394 group = 0;
2395 chip = s5pc100_gpios_4bit;
2396 nr_chips = ARRAY_SIZE(s5pc100_gpios_4bit);
2397
2398 for (i = 0; i < nr_chips; i++, chip++) {
2399 if (!chip->config) {
2400 chip->config = &samsung_gpio_cfgs[4];
2401 chip->group = group++;
2402 }
2403 }
2404 samsung_gpiolib_add_4bit_chips(s5pc100_gpios_4bit, nr_chips, S5P_VA_GPIO);
2405#if defined(CONFIG_CPU_S5PC100) && defined(CONFIG_S5P_GPIO_INT)
2406 s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
2407#endif
2408 } else if (soc_is_s5pv210()) {
2409 group = 0;
2410 chip = s5pv210_gpios_4bit;
2411 nr_chips = ARRAY_SIZE(s5pv210_gpios_4bit);
2412
2413 for (i = 0; i < nr_chips; i++, chip++) {
2414 if (!chip->config) {
2415 chip->config = &samsung_gpio_cfgs[4];
2416 chip->group = group++;
2417 }
2418 }
2419 samsung_gpiolib_add_4bit_chips(s5pv210_gpios_4bit, nr_chips, S5P_VA_GPIO);
2420#if defined(CONFIG_CPU_S5PV210) && defined(CONFIG_S5P_GPIO_INT)
2421 s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
2422#endif
2423 } else if (soc_is_exynos4210()) {
2424 group = 0;
2425
2426 /* gpio part1 */
2427 chip = exynos4_gpios_1;
2428 nr_chips = ARRAY_SIZE(exynos4_gpios_1);
2429
2430 for (i = 0; i < nr_chips; i++, chip++) {
2431 if (!chip->config) {
2432 chip->config = &exynos4_gpio_cfg;
2433 chip->group = group++;
2434 }
2435 }
2436 samsung_gpiolib_add_4bit_chips(exynos4_gpios_1, nr_chips, S5P_VA_GPIO1);
2437
2438 /* gpio part2 */
2439 chip = exynos4_gpios_2;
2440 nr_chips = ARRAY_SIZE(exynos4_gpios_2);
2441
2442 for (i = 0; i < nr_chips; i++, chip++) {
2443 if (!chip->config) {
2444 chip->config = &exynos4_gpio_cfg;
2445 chip->group = group++;
2446 }
2447 }
2448 samsung_gpiolib_add_4bit_chips(exynos4_gpios_2, nr_chips, S5P_VA_GPIO2);
2449
2450 /* gpio part3 */
2451 chip = exynos4_gpios_3;
2452 nr_chips = ARRAY_SIZE(exynos4_gpios_3);
2453
2454 for (i = 0; i < nr_chips; i++, chip++) {
2455 if (!chip->config) {
2456 chip->config = &exynos4_gpio_cfg;
2457 chip->group = group++;
2458 }
2459 }
2460 samsung_gpiolib_add_4bit_chips(exynos4_gpios_3, nr_chips, S5P_VA_GPIO3);
2461
2462#if defined(CONFIG_SOC_EXYNOS4210) && defined(CONFIG_S5P_GPIO_INT)
2463 s5p_register_gpioint_bank(IRQ_GPIO_XA, 0, IRQ_GPIO1_NR_GROUPS);
2464 s5p_register_gpioint_bank(IRQ_GPIO_XB, IRQ_GPIO1_NR_GROUPS, IRQ_GPIO2_NR_GROUPS);
2465#endif
2466 }
2467
2468 return 0;
2469}
2470core_initcall(samsung_gpiolib_init);
2471
2472int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
2473{
2474 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2475 unsigned long flags;
2476 int offset;
2477 int ret;
2478
2479 if (!chip)
2480 return -EINVAL;
2481
2482 offset = pin - chip->chip.base;
2483
2484 samsung_gpio_lock(chip, flags);
2485 ret = samsung_gpio_do_setcfg(chip, offset, config);
2486 samsung_gpio_unlock(chip, flags);
2487
2488 return ret;
2489}
2490EXPORT_SYMBOL(s3c_gpio_cfgpin);
2491
2492int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
2493 unsigned int cfg)
2494{
2495 int ret;
2496
2497 for (; nr > 0; nr--, start++) {
2498 ret = s3c_gpio_cfgpin(start, cfg);
2499 if (ret != 0)
2500 return ret;
2501 }
2502
2503 return 0;
2504}
2505EXPORT_SYMBOL_GPL(s3c_gpio_cfgpin_range);
2506
2507int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
2508 unsigned int cfg, samsung_gpio_pull_t pull)
2509{
2510 int ret;
2511
2512 for (; nr > 0; nr--, start++) {
2513 s3c_gpio_setpull(start, pull);
2514 ret = s3c_gpio_cfgpin(start, cfg);
2515 if (ret != 0)
2516 return ret;
2517 }
2518
2519 return 0;
2520}
2521EXPORT_SYMBOL_GPL(s3c_gpio_cfgall_range);
2522
2523unsigned s3c_gpio_getcfg(unsigned int pin)
2524{
2525 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2526 unsigned long flags;
2527 unsigned ret = 0;
2528 int offset;
2529
2530 if (chip) {
2531 offset = pin - chip->chip.base;
2532
2533 samsung_gpio_lock(chip, flags);
2534 ret = samsung_gpio_do_getcfg(chip, offset);
2535 samsung_gpio_unlock(chip, flags);
2536 }
2537
2538 return ret;
2539}
2540EXPORT_SYMBOL(s3c_gpio_getcfg);
2541
2542int s3c_gpio_setpull(unsigned int pin, samsung_gpio_pull_t pull)
2543{
2544 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2545 unsigned long flags;
2546 int offset, ret;
2547
2548 if (!chip)
2549 return -EINVAL;
2550
2551 offset = pin - chip->chip.base;
2552
2553 samsung_gpio_lock(chip, flags);
2554 ret = samsung_gpio_do_setpull(chip, offset, pull);
2555 samsung_gpio_unlock(chip, flags);
2556
2557 return ret;
2558}
2559EXPORT_SYMBOL(s3c_gpio_setpull);
2560
2561samsung_gpio_pull_t s3c_gpio_getpull(unsigned int pin)
2562{
2563 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2564 unsigned long flags;
2565 int offset;
2566 u32 pup = 0;
2567
2568 if (chip) {
2569 offset = pin - chip->chip.base;
2570
2571 samsung_gpio_lock(chip, flags);
2572 pup = samsung_gpio_do_getpull(chip, offset);
2573 samsung_gpio_unlock(chip, flags);
2574 }
2575
2576 return (__force samsung_gpio_pull_t)pup;
2577}
2578EXPORT_SYMBOL(s3c_gpio_getpull);
2579
2580/* gpiolib wrappers until these are totally eliminated */
2581
2582void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
2583{
2584 int ret;
2585
2586 WARN_ON(to); /* should be none of these left */
2587
2588 if (!to) {
2589 /* if pull is enabled, try first with up, and if that
2590 * fails, try using down */
2591
2592 ret = s3c_gpio_setpull(pin, S3C_GPIO_PULL_UP);
2593 if (ret)
2594 s3c_gpio_setpull(pin, S3C_GPIO_PULL_DOWN);
2595 } else {
2596 s3c_gpio_setpull(pin, S3C_GPIO_PULL_NONE);
2597 }
2598}
2599EXPORT_SYMBOL(s3c2410_gpio_pullup);
2600
2601void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
2602{
2603 /* do this via gpiolib until all users removed */
2604
2605 gpio_request(pin, "temporary");
2606 gpio_set_value(pin, to);
2607 gpio_free(pin);
2608}
2609EXPORT_SYMBOL(s3c2410_gpio_setpin);
2610
2611unsigned int s3c2410_gpio_getpin(unsigned int pin)
2612{
2613 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2614 unsigned long offs = pin - chip->chip.base;
2615
2616 return __raw_readl(chip->base + 0x04) & (1 << offs);
2617}
2618EXPORT_SYMBOL(s3c2410_gpio_getpin);
2619
2620#ifdef CONFIG_S5P_GPIO_DRVSTR
2621s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin)
2622{
2623 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2624 unsigned int off;
2625 void __iomem *reg;
2626 int shift;
2627 u32 drvstr;
2628
2629 if (!chip)
2630 return -EINVAL;
2631
2632 off = pin - chip->chip.base;
2633 shift = off * 2;
2634 reg = chip->base + 0x0C;
2635
2636 drvstr = __raw_readl(reg);
2637 drvstr = drvstr >> shift;
2638 drvstr &= 0x3;
2639
2640 return (__force s5p_gpio_drvstr_t)drvstr;
2641}
2642EXPORT_SYMBOL(s5p_gpio_get_drvstr);
2643
2644int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr)
2645{
2646 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2647 unsigned int off;
2648 void __iomem *reg;
2649 int shift;
2650 u32 tmp;
2651
2652 if (!chip)
2653 return -EINVAL;
2654
2655 off = pin - chip->chip.base;
2656 shift = off * 2;
2657 reg = chip->base + 0x0C;
2658
2659 tmp = __raw_readl(reg);
2660 tmp &= ~(0x3 << shift);
2661 tmp |= drvstr << shift;
2662
2663 __raw_writel(tmp, reg);
2664
2665 return 0;
2666}
2667EXPORT_SYMBOL(s5p_gpio_set_drvstr);
2668#endif /* CONFIG_S5P_GPIO_DRVSTR */
2669
2670#ifdef CONFIG_PLAT_S3C24XX
2671unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
2672{
2673 unsigned long flags;
2674 unsigned long misccr;
2675
2676 local_irq_save(flags);
2677 misccr = __raw_readl(S3C24XX_MISCCR);
2678 misccr &= ~clear;
2679 misccr ^= change;
2680 __raw_writel(misccr, S3C24XX_MISCCR);
2681 local_irq_restore(flags);
2682
2683 return misccr;
2684}
2685EXPORT_SYMBOL(s3c2410_modify_misccr);
2686#endif