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