blob: be7b0bd4eed467b00cf73b2f4584f28967f84679 [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>
Kay Sieversedbaa602011-12-21 16:26:03 -080025#include <linux/device.h>
Kukjin Kim1b39d5f2011-08-30 20:39:08 +090026#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>
Linus Walleijc67d0f22013-12-06 10:05:49 +010030#ifdef CONFIG_ARCH_S3C24XX
31#include <linux/platform_data/gpio-samsung-s3c24xx.h>
32#endif
Linus Walleij41c35482013-12-06 12:46:27 +010033#ifdef CONFIG_ARCH_S3C64XX
34#include <linux/platform_data/gpio-samsung-s3c64xx.h>
35#endif
Kukjin Kim1b39d5f2011-08-30 20:39:08 +090036
37#include <asm/irq.h>
38
39#include <mach/hardware.h>
40#include <mach/map.h>
Kukjin Kim1b39d5f2011-08-30 20:39:08 +090041#include <mach/regs-gpio.h>
42
43#include <plat/cpu.h>
44#include <plat/gpio-core.h>
45#include <plat/gpio-cfg.h>
46#include <plat/gpio-cfg-helpers.h>
Kukjin Kim1b39d5f2011-08-30 20:39:08 +090047#include <plat/pm.h>
48
Kukjin Kim1b39d5f2011-08-30 20:39:08 +090049int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip,
50 unsigned int off, samsung_gpio_pull_t pull)
51{
52 void __iomem *reg = chip->base + 0x08;
53 int shift = off * 2;
54 u32 pup;
55
56 pup = __raw_readl(reg);
57 pup &= ~(3 << shift);
58 pup |= pull << shift;
59 __raw_writel(pup, reg);
60
61 return 0;
62}
63
64samsung_gpio_pull_t samsung_gpio_getpull_updown(struct samsung_gpio_chip *chip,
65 unsigned int off)
66{
67 void __iomem *reg = chip->base + 0x08;
68 int shift = off * 2;
69 u32 pup = __raw_readl(reg);
70
71 pup >>= shift;
72 pup &= 0x3;
73
74 return (__force samsung_gpio_pull_t)pup;
75}
76
77int s3c2443_gpio_setpull(struct samsung_gpio_chip *chip,
78 unsigned int off, samsung_gpio_pull_t pull)
79{
80 switch (pull) {
81 case S3C_GPIO_PULL_NONE:
82 pull = 0x01;
83 break;
84 case S3C_GPIO_PULL_UP:
85 pull = 0x00;
86 break;
87 case S3C_GPIO_PULL_DOWN:
88 pull = 0x02;
89 break;
90 }
91 return samsung_gpio_setpull_updown(chip, off, pull);
92}
93
94samsung_gpio_pull_t s3c2443_gpio_getpull(struct samsung_gpio_chip *chip,
95 unsigned int off)
96{
97 samsung_gpio_pull_t pull;
98
99 pull = samsung_gpio_getpull_updown(chip, off);
100
101 switch (pull) {
102 case 0x00:
103 pull = S3C_GPIO_PULL_UP;
104 break;
105 case 0x01:
106 case 0x03:
107 pull = S3C_GPIO_PULL_NONE;
108 break;
109 case 0x02:
110 pull = S3C_GPIO_PULL_DOWN;
111 break;
112 }
113
114 return pull;
115}
116
117static int s3c24xx_gpio_setpull_1(struct samsung_gpio_chip *chip,
118 unsigned int off, samsung_gpio_pull_t pull,
119 samsung_gpio_pull_t updown)
120{
121 void __iomem *reg = chip->base + 0x08;
122 u32 pup = __raw_readl(reg);
123
124 if (pull == updown)
125 pup &= ~(1 << off);
126 else if (pull == S3C_GPIO_PULL_NONE)
127 pup |= (1 << off);
128 else
129 return -EINVAL;
130
131 __raw_writel(pup, reg);
132 return 0;
133}
134
135static samsung_gpio_pull_t s3c24xx_gpio_getpull_1(struct samsung_gpio_chip *chip,
136 unsigned int off,
137 samsung_gpio_pull_t updown)
138{
139 void __iomem *reg = chip->base + 0x08;
140 u32 pup = __raw_readl(reg);
141
142 pup &= (1 << off);
143 return pup ? S3C_GPIO_PULL_NONE : updown;
144}
145
146samsung_gpio_pull_t s3c24xx_gpio_getpull_1up(struct samsung_gpio_chip *chip,
147 unsigned int off)
148{
149 return s3c24xx_gpio_getpull_1(chip, off, S3C_GPIO_PULL_UP);
150}
151
152int s3c24xx_gpio_setpull_1up(struct samsung_gpio_chip *chip,
153 unsigned int off, samsung_gpio_pull_t pull)
154{
155 return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_UP);
156}
157
158samsung_gpio_pull_t s3c24xx_gpio_getpull_1down(struct samsung_gpio_chip *chip,
159 unsigned int off)
160{
161 return s3c24xx_gpio_getpull_1(chip, off, S3C_GPIO_PULL_DOWN);
162}
163
164int s3c24xx_gpio_setpull_1down(struct samsung_gpio_chip *chip,
165 unsigned int off, samsung_gpio_pull_t pull)
166{
167 return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_DOWN);
168}
169
Kukjin Kim1b39d5f2011-08-30 20:39:08 +0900170/*
171 * samsung_gpio_setcfg_2bit - Samsung 2bit style GPIO configuration.
172 * @chip: The gpio chip that is being configured.
173 * @off: The offset for the GPIO being configured.
174 * @cfg: The configuration value to set.
175 *
176 * This helper deal with the GPIO cases where the control register
177 * has two bits of configuration per gpio, which have the following
178 * functions:
179 * 00 = input
180 * 01 = output
181 * 1x = special function
182 */
183
184static int samsung_gpio_setcfg_2bit(struct samsung_gpio_chip *chip,
185 unsigned int off, unsigned int cfg)
186{
187 void __iomem *reg = chip->base;
188 unsigned int shift = off * 2;
189 u32 con;
190
191 if (samsung_gpio_is_cfg_special(cfg)) {
192 cfg &= 0xf;
193 if (cfg > 3)
194 return -EINVAL;
195
196 cfg <<= shift;
197 }
198
199 con = __raw_readl(reg);
200 con &= ~(0x3 << shift);
201 con |= cfg;
202 __raw_writel(con, reg);
203
204 return 0;
205}
206
207/*
208 * samsung_gpio_getcfg_2bit - Samsung 2bit style GPIO configuration read.
209 * @chip: The gpio chip that is being configured.
210 * @off: The offset for the GPIO being configured.
211 *
Mark Brownf1347592011-12-08 00:23:59 +0800212 * The reverse of samsung_gpio_setcfg_2bit(). Will return a value which
Kukjin Kim1b39d5f2011-08-30 20:39:08 +0900213 * could be directly passed back to samsung_gpio_setcfg_2bit(), from the
214 * S3C_GPIO_SPECIAL() macro.
215 */
216
217static unsigned int samsung_gpio_getcfg_2bit(struct samsung_gpio_chip *chip,
218 unsigned int off)
219{
220 u32 con;
221
222 con = __raw_readl(chip->base);
223 con >>= off * 2;
224 con &= 3;
225
226 /* this conversion works for IN and OUT as well as special mode */
227 return S3C_GPIO_SPECIAL(con);
228}
229
230/*
231 * samsung_gpio_setcfg_4bit - Samsung 4bit single register GPIO config.
232 * @chip: The gpio chip that is being configured.
233 * @off: The offset for the GPIO being configured.
234 * @cfg: The configuration value to set.
235 *
236 * This helper deal with the GPIO cases where the control register has 4 bits
237 * of control per GPIO, generally in the form of:
238 * 0000 = Input
239 * 0001 = Output
240 * others = Special functions (dependent on bank)
241 *
242 * Note, since the code to deal with the case where there are two control
243 * registers instead of one, we do not have a separate set of functions for
244 * each case.
245 */
246
247static int samsung_gpio_setcfg_4bit(struct samsung_gpio_chip *chip,
248 unsigned int off, unsigned int cfg)
249{
250 void __iomem *reg = chip->base;
251 unsigned int shift = (off & 7) * 4;
252 u32 con;
253
254 if (off < 8 && chip->chip.ngpio > 8)
255 reg -= 4;
256
257 if (samsung_gpio_is_cfg_special(cfg)) {
258 cfg &= 0xf;
259 cfg <<= shift;
260 }
261
262 con = __raw_readl(reg);
263 con &= ~(0xf << shift);
264 con |= cfg;
265 __raw_writel(con, reg);
266
267 return 0;
268}
269
270/*
271 * samsung_gpio_getcfg_4bit - Samsung 4bit single register GPIO config read.
272 * @chip: The gpio chip that is being configured.
273 * @off: The offset for the GPIO being configured.
274 *
275 * The reverse of samsung_gpio_setcfg_4bit(), turning a gpio configuration
276 * register setting into a value the software can use, such as could be passed
277 * to samsung_gpio_setcfg_4bit().
278 *
279 * @sa samsung_gpio_getcfg_2bit
280 */
281
282static unsigned samsung_gpio_getcfg_4bit(struct samsung_gpio_chip *chip,
283 unsigned int off)
284{
285 void __iomem *reg = chip->base;
286 unsigned int shift = (off & 7) * 4;
287 u32 con;
288
289 if (off < 8 && chip->chip.ngpio > 8)
290 reg -= 4;
291
292 con = __raw_readl(reg);
293 con >>= shift;
294 con &= 0xf;
295
296 /* this conversion works for IN and OUT as well as special mode */
297 return S3C_GPIO_SPECIAL(con);
298}
299
Tushar Beherac034b182011-10-05 08:55:49 +0900300#ifdef CONFIG_PLAT_S3C24XX
Kukjin Kim1b39d5f2011-08-30 20:39:08 +0900301/*
302 * s3c24xx_gpio_setcfg_abank - S3C24XX style GPIO configuration (Bank A)
303 * @chip: The gpio chip that is being configured.
304 * @off: The offset for the GPIO being configured.
305 * @cfg: The configuration value to set.
306 *
307 * This helper deal with the GPIO cases where the control register
308 * has one bit of configuration for the gpio, where setting the bit
309 * means the pin is in special function mode and unset means output.
310 */
311
312static int s3c24xx_gpio_setcfg_abank(struct samsung_gpio_chip *chip,
313 unsigned int off, unsigned int cfg)
314{
315 void __iomem *reg = chip->base;
316 unsigned int shift = off;
317 u32 con;
318
319 if (samsung_gpio_is_cfg_special(cfg)) {
320 cfg &= 0xf;
321
322 /* Map output to 0, and SFN2 to 1 */
323 cfg -= 1;
324 if (cfg > 1)
325 return -EINVAL;
326
327 cfg <<= shift;
328 }
329
330 con = __raw_readl(reg);
331 con &= ~(0x1 << shift);
332 con |= cfg;
333 __raw_writel(con, reg);
334
335 return 0;
336}
337
338/*
339 * s3c24xx_gpio_getcfg_abank - S3C24XX style GPIO configuration read (Bank A)
340 * @chip: The gpio chip that is being configured.
341 * @off: The offset for the GPIO being configured.
342 *
343 * The reverse of s3c24xx_gpio_setcfg_abank() turning an GPIO into a usable
344 * GPIO configuration value.
345 *
346 * @sa samsung_gpio_getcfg_2bit
347 * @sa samsung_gpio_getcfg_4bit
348 */
349
350static unsigned s3c24xx_gpio_getcfg_abank(struct samsung_gpio_chip *chip,
351 unsigned int off)
352{
353 u32 con;
354
355 con = __raw_readl(chip->base);
356 con >>= off;
357 con &= 1;
358 con++;
359
360 return S3C_GPIO_SFN(con);
361}
Tushar Beherac034b182011-10-05 08:55:49 +0900362#endif
Kukjin Kim1b39d5f2011-08-30 20:39:08 +0900363
Tushar Beherac034b182011-10-05 08:55:49 +0900364#if defined(CONFIG_CPU_S5P6440) || defined(CONFIG_CPU_S5P6450)
Kukjin Kim1b39d5f2011-08-30 20:39:08 +0900365static int s5p64x0_gpio_setcfg_rbank(struct samsung_gpio_chip *chip,
366 unsigned int off, unsigned int cfg)
367{
368 void __iomem *reg = chip->base;
369 unsigned int shift;
370 u32 con;
371
372 switch (off) {
373 case 0:
374 case 1:
375 case 2:
376 case 3:
377 case 4:
378 case 5:
379 shift = (off & 7) * 4;
380 reg -= 4;
381 break;
382 case 6:
383 shift = ((off + 1) & 7) * 4;
384 reg -= 4;
385 default:
386 shift = ((off + 1) & 7) * 4;
387 break;
388 }
389
390 if (samsung_gpio_is_cfg_special(cfg)) {
391 cfg &= 0xf;
392 cfg <<= shift;
393 }
394
395 con = __raw_readl(reg);
396 con &= ~(0xf << shift);
397 con |= cfg;
398 __raw_writel(con, reg);
399
400 return 0;
401}
Tushar Beherac034b182011-10-05 08:55:49 +0900402#endif
Kukjin Kim1b39d5f2011-08-30 20:39:08 +0900403
404static void __init samsung_gpiolib_set_cfg(struct samsung_gpio_cfg *chipcfg,
405 int nr_chips)
406{
407 for (; nr_chips > 0; nr_chips--, chipcfg++) {
408 if (!chipcfg->set_config)
409 chipcfg->set_config = samsung_gpio_setcfg_4bit;
410 if (!chipcfg->get_config)
411 chipcfg->get_config = samsung_gpio_getcfg_4bit;
412 if (!chipcfg->set_pull)
413 chipcfg->set_pull = samsung_gpio_setpull_updown;
414 if (!chipcfg->get_pull)
415 chipcfg->get_pull = samsung_gpio_getpull_updown;
416 }
417}
418
419struct samsung_gpio_cfg s3c24xx_gpiocfg_default = {
420 .set_config = samsung_gpio_setcfg_2bit,
421 .get_config = samsung_gpio_getcfg_2bit,
422};
423
Tushar Beherac034b182011-10-05 08:55:49 +0900424#ifdef CONFIG_PLAT_S3C24XX
Kukjin Kim1b39d5f2011-08-30 20:39:08 +0900425static struct samsung_gpio_cfg s3c24xx_gpiocfg_banka = {
426 .set_config = s3c24xx_gpio_setcfg_abank,
427 .get_config = s3c24xx_gpio_getcfg_abank,
428};
Tushar Beherac034b182011-10-05 08:55:49 +0900429#endif
Kukjin Kim1b39d5f2011-08-30 20:39:08 +0900430
Tushar Beherac034b182011-10-05 08:55:49 +0900431#if defined(CONFIG_CPU_S5P6440) || defined(CONFIG_CPU_S5P6450)
Kukjin Kim1b39d5f2011-08-30 20:39:08 +0900432static struct samsung_gpio_cfg s5p64x0_gpio_cfg_rbank = {
433 .cfg_eint = 0x3,
434 .set_config = s5p64x0_gpio_setcfg_rbank,
435 .get_config = samsung_gpio_getcfg_4bit,
436 .set_pull = samsung_gpio_setpull_updown,
437 .get_pull = samsung_gpio_getpull_updown,
438};
Tushar Beherac034b182011-10-05 08:55:49 +0900439#endif
Kukjin Kim1b39d5f2011-08-30 20:39:08 +0900440
441static struct samsung_gpio_cfg samsung_gpio_cfgs[] = {
Mark Brown29854792011-12-08 00:23:58 +0800442 [0] = {
Kukjin Kim1b39d5f2011-08-30 20:39:08 +0900443 .cfg_eint = 0x0,
Mark Brown29854792011-12-08 00:23:58 +0800444 },
445 [1] = {
Kukjin Kim1b39d5f2011-08-30 20:39:08 +0900446 .cfg_eint = 0x3,
Mark Brown29854792011-12-08 00:23:58 +0800447 },
448 [2] = {
Kukjin Kim1b39d5f2011-08-30 20:39:08 +0900449 .cfg_eint = 0x7,
Mark Brown29854792011-12-08 00:23:58 +0800450 },
451 [3] = {
Kukjin Kim1b39d5f2011-08-30 20:39:08 +0900452 .cfg_eint = 0xF,
Mark Brown29854792011-12-08 00:23:58 +0800453 },
454 [4] = {
Kukjin Kim1b39d5f2011-08-30 20:39:08 +0900455 .cfg_eint = 0x0,
456 .set_config = samsung_gpio_setcfg_2bit,
457 .get_config = samsung_gpio_getcfg_2bit,
Mark Brown29854792011-12-08 00:23:58 +0800458 },
459 [5] = {
Kukjin Kim1b39d5f2011-08-30 20:39:08 +0900460 .cfg_eint = 0x2,
461 .set_config = samsung_gpio_setcfg_2bit,
462 .get_config = samsung_gpio_getcfg_2bit,
Mark Brown29854792011-12-08 00:23:58 +0800463 },
464 [6] = {
Kukjin Kim1b39d5f2011-08-30 20:39:08 +0900465 .cfg_eint = 0x3,
466 .set_config = samsung_gpio_setcfg_2bit,
467 .get_config = samsung_gpio_getcfg_2bit,
Mark Brown29854792011-12-08 00:23:58 +0800468 },
469 [7] = {
Kukjin Kim1b39d5f2011-08-30 20:39:08 +0900470 .set_config = samsung_gpio_setcfg_2bit,
471 .get_config = samsung_gpio_getcfg_2bit,
Mark Brown29854792011-12-08 00:23:58 +0800472 },
Kukjin Kim1b39d5f2011-08-30 20:39:08 +0900473};
474
475/*
476 * Default routines for controlling GPIO, based on the original S3C24XX
477 * GPIO functions which deal with the case where each gpio bank of the
478 * chip is as following:
479 *
480 * base + 0x00: Control register, 2 bits per gpio
481 * gpio n: 2 bits starting at (2*n)
482 * 00 = input, 01 = output, others mean special-function
483 * base + 0x04: Data register, 1 bit per gpio
484 * bit n: data bit n
485*/
486
487static int samsung_gpiolib_2bit_input(struct gpio_chip *chip, unsigned offset)
488{
489 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
490 void __iomem *base = ourchip->base;
491 unsigned long flags;
492 unsigned long con;
493
494 samsung_gpio_lock(ourchip, flags);
495
496 con = __raw_readl(base + 0x00);
497 con &= ~(3 << (offset * 2));
498
499 __raw_writel(con, base + 0x00);
500
501 samsung_gpio_unlock(ourchip, flags);
502 return 0;
503}
504
505static int samsung_gpiolib_2bit_output(struct gpio_chip *chip,
506 unsigned offset, int value)
507{
508 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
509 void __iomem *base = ourchip->base;
510 unsigned long flags;
511 unsigned long dat;
512 unsigned long con;
513
514 samsung_gpio_lock(ourchip, flags);
515
516 dat = __raw_readl(base + 0x04);
517 dat &= ~(1 << offset);
518 if (value)
519 dat |= 1 << offset;
520 __raw_writel(dat, base + 0x04);
521
522 con = __raw_readl(base + 0x00);
523 con &= ~(3 << (offset * 2));
524 con |= 1 << (offset * 2);
525
526 __raw_writel(con, base + 0x00);
527 __raw_writel(dat, base + 0x04);
528
529 samsung_gpio_unlock(ourchip, flags);
530 return 0;
531}
532
533/*
534 * The samsung_gpiolib_4bit routines are to control the gpio banks where
535 * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
536 * following example:
537 *
538 * base + 0x00: Control register, 4 bits per gpio
539 * gpio n: 4 bits starting at (4*n)
540 * 0000 = input, 0001 = output, others mean special-function
541 * base + 0x04: Data register, 1 bit per gpio
542 * bit n: data bit n
543 *
544 * Note, since the data register is one bit per gpio and is at base + 0x4
545 * we can use samsung_gpiolib_get and samsung_gpiolib_set to change the
546 * state of the output.
547 */
548
549static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
550 unsigned int offset)
551{
552 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
553 void __iomem *base = ourchip->base;
554 unsigned long con;
555
556 con = __raw_readl(base + GPIOCON_OFF);
Eunki Kim2b88ff42012-10-23 22:39:38 +0900557 if (ourchip->bitmap_gpio_int & BIT(offset))
558 con |= 0xf << con_4bit_shift(offset);
559 else
560 con &= ~(0xf << con_4bit_shift(offset));
Kukjin Kim1b39d5f2011-08-30 20:39:08 +0900561 __raw_writel(con, base + GPIOCON_OFF);
562
Jingoo Han343db4b2012-10-23 23:12:23 +0900563 pr_debug("%s: %p: CON now %08lx\n", __func__, base, con);
Kukjin Kim1b39d5f2011-08-30 20:39:08 +0900564
565 return 0;
566}
567
568static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
569 unsigned int offset, int value)
570{
571 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
572 void __iomem *base = ourchip->base;
573 unsigned long con;
574 unsigned long dat;
575
576 con = __raw_readl(base + GPIOCON_OFF);
577 con &= ~(0xf << con_4bit_shift(offset));
578 con |= 0x1 << con_4bit_shift(offset);
579
580 dat = __raw_readl(base + GPIODAT_OFF);
581
582 if (value)
583 dat |= 1 << offset;
584 else
585 dat &= ~(1 << offset);
586
587 __raw_writel(dat, base + GPIODAT_OFF);
588 __raw_writel(con, base + GPIOCON_OFF);
589 __raw_writel(dat, base + GPIODAT_OFF);
590
Jingoo Han343db4b2012-10-23 23:12:23 +0900591 pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
Kukjin Kim1b39d5f2011-08-30 20:39:08 +0900592
593 return 0;
594}
595
596/*
597 * The next set of routines are for the case where the GPIO configuration
598 * registers are 4 bits per GPIO but there is more than one register (the
599 * bank has more than 8 GPIOs.
600 *
601 * This case is the similar to the 4 bit case, but the registers are as
602 * follows:
603 *
604 * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
605 * gpio n: 4 bits starting at (4*n)
606 * 0000 = input, 0001 = output, others mean special-function
607 * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
608 * gpio n: 4 bits starting at (4*n)
609 * 0000 = input, 0001 = output, others mean special-function
610 * base + 0x08: Data register, 1 bit per gpio
611 * bit n: data bit n
612 *
613 * To allow us to use the samsung_gpiolib_get and samsung_gpiolib_set
614 * routines we store the 'base + 0x4' address so that these routines see
615 * the data register at ourchip->base + 0x04.
616 */
617
618static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
619 unsigned int offset)
620{
621 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
622 void __iomem *base = ourchip->base;
623 void __iomem *regcon = base;
624 unsigned long con;
625
626 if (offset > 7)
627 offset -= 8;
628 else
629 regcon -= 4;
630
631 con = __raw_readl(regcon);
632 con &= ~(0xf << con_4bit_shift(offset));
633 __raw_writel(con, regcon);
634
Jingoo Han343db4b2012-10-23 23:12:23 +0900635 pr_debug("%s: %p: CON %08lx\n", __func__, base, con);
Kukjin Kim1b39d5f2011-08-30 20:39:08 +0900636
637 return 0;
638}
639
640static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
641 unsigned int offset, int value)
642{
643 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
644 void __iomem *base = ourchip->base;
645 void __iomem *regcon = base;
646 unsigned long con;
647 unsigned long dat;
648 unsigned con_offset = offset;
649
650 if (con_offset > 7)
651 con_offset -= 8;
652 else
653 regcon -= 4;
654
655 con = __raw_readl(regcon);
656 con &= ~(0xf << con_4bit_shift(con_offset));
657 con |= 0x1 << con_4bit_shift(con_offset);
658
659 dat = __raw_readl(base + GPIODAT_OFF);
660
661 if (value)
662 dat |= 1 << offset;
663 else
664 dat &= ~(1 << offset);
665
666 __raw_writel(dat, base + GPIODAT_OFF);
667 __raw_writel(con, regcon);
668 __raw_writel(dat, base + GPIODAT_OFF);
669
Jingoo Han343db4b2012-10-23 23:12:23 +0900670 pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
Kukjin Kim1b39d5f2011-08-30 20:39:08 +0900671
672 return 0;
673}
674
Tushar Beherac034b182011-10-05 08:55:49 +0900675#ifdef CONFIG_PLAT_S3C24XX
Kukjin Kim1b39d5f2011-08-30 20:39:08 +0900676/* The next set of routines are for the case of s3c24xx bank a */
677
678static int s3c24xx_gpiolib_banka_input(struct gpio_chip *chip, unsigned offset)
679{
680 return -EINVAL;
681}
682
683static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip,
684 unsigned offset, int value)
685{
686 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
687 void __iomem *base = ourchip->base;
688 unsigned long flags;
689 unsigned long dat;
690 unsigned long con;
691
692 local_irq_save(flags);
693
694 con = __raw_readl(base + 0x00);
695 dat = __raw_readl(base + 0x04);
696
697 dat &= ~(1 << offset);
698 if (value)
699 dat |= 1 << offset;
700
701 __raw_writel(dat, base + 0x04);
702
703 con &= ~(1 << offset);
704
705 __raw_writel(con, base + 0x00);
706 __raw_writel(dat, base + 0x04);
707
708 local_irq_restore(flags);
709 return 0;
710}
Tushar Beherac034b182011-10-05 08:55:49 +0900711#endif
Kukjin Kim1b39d5f2011-08-30 20:39:08 +0900712
713/* The next set of routines are for the case of s5p64x0 bank r */
714
715static int s5p64x0_gpiolib_rbank_input(struct gpio_chip *chip,
716 unsigned int offset)
717{
718 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
719 void __iomem *base = ourchip->base;
720 void __iomem *regcon = base;
721 unsigned long con;
722 unsigned long flags;
723
724 switch (offset) {
725 case 6:
726 offset += 1;
727 case 0:
728 case 1:
729 case 2:
730 case 3:
731 case 4:
732 case 5:
733 regcon -= 4;
734 break;
735 default:
736 offset -= 7;
737 break;
738 }
739
740 samsung_gpio_lock(ourchip, flags);
741
742 con = __raw_readl(regcon);
743 con &= ~(0xf << con_4bit_shift(offset));
744 __raw_writel(con, regcon);
745
746 samsung_gpio_unlock(ourchip, flags);
747
748 return 0;
749}
750
751static int s5p64x0_gpiolib_rbank_output(struct gpio_chip *chip,
752 unsigned int offset, int value)
753{
754 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
755 void __iomem *base = ourchip->base;
756 void __iomem *regcon = base;
757 unsigned long con;
758 unsigned long dat;
759 unsigned long flags;
760 unsigned con_offset = offset;
761
762 switch (con_offset) {
763 case 6:
764 con_offset += 1;
765 case 0:
766 case 1:
767 case 2:
768 case 3:
769 case 4:
770 case 5:
771 regcon -= 4;
772 break;
773 default:
774 con_offset -= 7;
775 break;
776 }
777
778 samsung_gpio_lock(ourchip, flags);
779
780 con = __raw_readl(regcon);
781 con &= ~(0xf << con_4bit_shift(con_offset));
782 con |= 0x1 << con_4bit_shift(con_offset);
783
784 dat = __raw_readl(base + GPIODAT_OFF);
785 if (value)
786 dat |= 1 << offset;
787 else
788 dat &= ~(1 << offset);
789
790 __raw_writel(con, regcon);
791 __raw_writel(dat, base + GPIODAT_OFF);
792
793 samsung_gpio_unlock(ourchip, flags);
794
795 return 0;
796}
797
798static void samsung_gpiolib_set(struct gpio_chip *chip,
799 unsigned offset, int value)
800{
801 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
802 void __iomem *base = ourchip->base;
803 unsigned long flags;
804 unsigned long dat;
805
806 samsung_gpio_lock(ourchip, flags);
807
808 dat = __raw_readl(base + 0x04);
809 dat &= ~(1 << offset);
810 if (value)
811 dat |= 1 << offset;
812 __raw_writel(dat, base + 0x04);
813
814 samsung_gpio_unlock(ourchip, flags);
815}
816
817static int samsung_gpiolib_get(struct gpio_chip *chip, unsigned offset)
818{
819 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
820 unsigned long val;
821
822 val = __raw_readl(ourchip->base + 0x04);
823 val >>= offset;
824 val &= 1;
825
826 return val;
827}
828
829/*
830 * CONFIG_S3C_GPIO_TRACK enables the tracking of the s3c specific gpios
831 * for use with the configuration calls, and other parts of the s3c gpiolib
832 * support code.
833 *
834 * Not all s3c support code will need this, as some configurations of cpu
835 * may only support one or two different configuration options and have an
836 * easy gpio to samsung_gpio_chip mapping function. If this is the case, then
837 * the machine support file should provide its own samsung_gpiolib_getchip()
838 * and any other necessary functions.
839 */
840
841#ifdef CONFIG_S3C_GPIO_TRACK
842struct samsung_gpio_chip *s3c_gpios[S3C_GPIO_END];
843
844static __init void s3c_gpiolib_track(struct samsung_gpio_chip *chip)
845{
846 unsigned int gpn;
847 int i;
848
849 gpn = chip->chip.base;
850 for (i = 0; i < chip->chip.ngpio; i++, gpn++) {
851 BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios));
852 s3c_gpios[gpn] = chip;
853 }
854}
855#endif /* CONFIG_S3C_GPIO_TRACK */
856
857/*
858 * samsung_gpiolib_add() - add the Samsung gpio_chip.
859 * @chip: The chip to register
860 *
861 * This is a wrapper to gpiochip_add() that takes our specific gpio chip
862 * information and makes the necessary alterations for the platform and
863 * notes the information for use with the configuration systems and any
864 * other parts of the system.
865 */
866
867static void __init samsung_gpiolib_add(struct samsung_gpio_chip *chip)
868{
869 struct gpio_chip *gc = &chip->chip;
870 int ret;
871
872 BUG_ON(!chip->base);
873 BUG_ON(!gc->label);
874 BUG_ON(!gc->ngpio);
875
876 spin_lock_init(&chip->lock);
877
878 if (!gc->direction_input)
879 gc->direction_input = samsung_gpiolib_2bit_input;
880 if (!gc->direction_output)
881 gc->direction_output = samsung_gpiolib_2bit_output;
882 if (!gc->set)
883 gc->set = samsung_gpiolib_set;
884 if (!gc->get)
885 gc->get = samsung_gpiolib_get;
886
887#ifdef CONFIG_PM
888 if (chip->pm != NULL) {
889 if (!chip->pm->save || !chip->pm->resume)
Jingoo Han343db4b2012-10-23 23:12:23 +0900890 pr_err("gpio: %s has missing PM functions\n",
Kukjin Kim1b39d5f2011-08-30 20:39:08 +0900891 gc->label);
892 } else
Jingoo Han343db4b2012-10-23 23:12:23 +0900893 pr_err("gpio: %s has no PM function\n", gc->label);
Kukjin Kim1b39d5f2011-08-30 20:39:08 +0900894#endif
895
896 /* gpiochip_add() prints own failure message on error. */
897 ret = gpiochip_add(gc);
898 if (ret >= 0)
899 s3c_gpiolib_track(chip);
900}
901
902static void __init s3c24xx_gpiolib_add_chips(struct samsung_gpio_chip *chip,
903 int nr_chips, void __iomem *base)
904{
905 int i;
906 struct gpio_chip *gc = &chip->chip;
907
908 for (i = 0 ; i < nr_chips; i++, chip++) {
Peter Korsgaard8a8ab2e2011-10-10 19:55:58 +0900909 /* skip banks not present on SoC */
910 if (chip->chip.base >= S3C_GPIO_END)
911 continue;
912
Kukjin Kim1b39d5f2011-08-30 20:39:08 +0900913 if (!chip->config)
914 chip->config = &s3c24xx_gpiocfg_default;
915 if (!chip->pm)
916 chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
917 if ((base != NULL) && (chip->base == NULL))
918 chip->base = base + ((i) * 0x10);
919
920 if (!gc->direction_input)
921 gc->direction_input = samsung_gpiolib_2bit_input;
922 if (!gc->direction_output)
923 gc->direction_output = samsung_gpiolib_2bit_output;
924
925 samsung_gpiolib_add(chip);
926 }
927}
928
929static void __init samsung_gpiolib_add_2bit_chips(struct samsung_gpio_chip *chip,
930 int nr_chips, void __iomem *base,
931 unsigned int offset)
932{
933 int i;
934
935 for (i = 0 ; i < nr_chips; i++, chip++) {
936 chip->chip.direction_input = samsung_gpiolib_2bit_input;
937 chip->chip.direction_output = samsung_gpiolib_2bit_output;
938
939 if (!chip->config)
940 chip->config = &samsung_gpio_cfgs[7];
941 if (!chip->pm)
942 chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
943 if ((base != NULL) && (chip->base == NULL))
944 chip->base = base + ((i) * offset);
945
946 samsung_gpiolib_add(chip);
947 }
948}
949
950/*
951 * samsung_gpiolib_add_4bit_chips - 4bit single register GPIO config.
952 * @chip: The gpio chip that is being configured.
953 * @nr_chips: The no of chips (gpio ports) for the GPIO being configured.
954 *
955 * This helper deal with the GPIO cases where the control register has 4 bits
956 * of control per GPIO, generally in the form of:
957 * 0000 = Input
958 * 0001 = Output
959 * others = Special functions (dependent on bank)
960 *
961 * Note, since the code to deal with the case where there are two control
962 * registers instead of one, we do not have a separate set of function
963 * (samsung_gpiolib_add_4bit2_chips)for each case.
964 */
965
966static void __init samsung_gpiolib_add_4bit_chips(struct samsung_gpio_chip *chip,
967 int nr_chips, void __iomem *base)
968{
969 int i;
970
971 for (i = 0 ; i < nr_chips; i++, chip++) {
972 chip->chip.direction_input = samsung_gpiolib_4bit_input;
973 chip->chip.direction_output = samsung_gpiolib_4bit_output;
974
975 if (!chip->config)
976 chip->config = &samsung_gpio_cfgs[2];
977 if (!chip->pm)
978 chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
979 if ((base != NULL) && (chip->base == NULL))
980 chip->base = base + ((i) * 0x20);
981
Eunki Kim2b88ff42012-10-23 22:39:38 +0900982 chip->bitmap_gpio_int = 0;
983
Kukjin Kim1b39d5f2011-08-30 20:39:08 +0900984 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{
Kukjin Kimd97fede2013-02-12 21:01:38 -08001028 if (offset < 4) {
Heiko Stuebner1c8408e2013-02-12 10:12:09 -08001029 if (soc_is_s3c2412())
1030 return IRQ_EINT0_2412 + offset;
1031 else
1032 return IRQ_EINT0 + offset;
Kukjin Kimd97fede2013-02-12 21:01:38 -08001033 }
Kukjin Kim1b39d5f2011-08-30 20:39:08 +09001034
1035 if (offset < 8)
1036 return IRQ_EINT4 + offset - 4;
1037
1038 return -EINVAL;
1039}
1040#endif
1041
Tomasz Figa54362e12013-10-06 08:59:30 +09001042#ifdef CONFIG_ARCH_S3C64XX
Kukjin Kim1b39d5f2011-08-30 20:39:08 +09001043static int s3c64xx_gpiolib_mbank_to_irq(struct gpio_chip *chip, unsigned pin)
1044{
1045 return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO;
1046}
1047
1048static int s3c64xx_gpiolib_lbank_to_irq(struct gpio_chip *chip, unsigned pin)
1049{
1050 return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO;
1051}
1052#endif
1053
1054struct samsung_gpio_chip s3c24xx_gpios[] = {
1055#ifdef CONFIG_PLAT_S3C24XX
1056 {
1057 .config = &s3c24xx_gpiocfg_banka,
1058 .chip = {
1059 .base = S3C2410_GPA(0),
1060 .owner = THIS_MODULE,
1061 .label = "GPIOA",
1062 .ngpio = 24,
1063 .direction_input = s3c24xx_gpiolib_banka_input,
1064 .direction_output = s3c24xx_gpiolib_banka_output,
1065 },
1066 }, {
1067 .chip = {
1068 .base = S3C2410_GPB(0),
1069 .owner = THIS_MODULE,
1070 .label = "GPIOB",
1071 .ngpio = 16,
1072 },
1073 }, {
1074 .chip = {
1075 .base = S3C2410_GPC(0),
1076 .owner = THIS_MODULE,
1077 .label = "GPIOC",
1078 .ngpio = 16,
1079 },
1080 }, {
1081 .chip = {
1082 .base = S3C2410_GPD(0),
1083 .owner = THIS_MODULE,
1084 .label = "GPIOD",
1085 .ngpio = 16,
1086 },
1087 }, {
1088 .chip = {
1089 .base = S3C2410_GPE(0),
1090 .label = "GPIOE",
1091 .owner = THIS_MODULE,
1092 .ngpio = 16,
1093 },
1094 }, {
1095 .chip = {
1096 .base = S3C2410_GPF(0),
1097 .owner = THIS_MODULE,
1098 .label = "GPIOF",
1099 .ngpio = 8,
1100 .to_irq = s3c24xx_gpiolib_fbank_to_irq,
1101 },
1102 }, {
1103 .irq_base = IRQ_EINT8,
1104 .chip = {
1105 .base = S3C2410_GPG(0),
1106 .owner = THIS_MODULE,
1107 .label = "GPIOG",
1108 .ngpio = 16,
1109 .to_irq = samsung_gpiolib_to_irq,
1110 },
1111 }, {
1112 .chip = {
1113 .base = S3C2410_GPH(0),
1114 .owner = THIS_MODULE,
1115 .label = "GPIOH",
1116 .ngpio = 11,
1117 },
1118 },
1119 /* GPIOS for the S3C2443 and later devices. */
1120 {
1121 .base = S3C2440_GPJCON,
1122 .chip = {
1123 .base = S3C2410_GPJ(0),
1124 .owner = THIS_MODULE,
1125 .label = "GPIOJ",
1126 .ngpio = 16,
1127 },
1128 }, {
1129 .base = S3C2443_GPKCON,
1130 .chip = {
1131 .base = S3C2410_GPK(0),
1132 .owner = THIS_MODULE,
1133 .label = "GPIOK",
1134 .ngpio = 16,
1135 },
1136 }, {
1137 .base = S3C2443_GPLCON,
1138 .chip = {
1139 .base = S3C2410_GPL(0),
1140 .owner = THIS_MODULE,
1141 .label = "GPIOL",
1142 .ngpio = 15,
1143 },
1144 }, {
1145 .base = S3C2443_GPMCON,
1146 .chip = {
1147 .base = S3C2410_GPM(0),
1148 .owner = THIS_MODULE,
1149 .label = "GPIOM",
1150 .ngpio = 2,
1151 },
1152 },
1153#endif
1154};
1155
1156/*
1157 * GPIO bank summary:
1158 *
1159 * Bank GPIOs Style SlpCon ExtInt Group
1160 * A 8 4Bit Yes 1
1161 * B 7 4Bit Yes 1
1162 * C 8 4Bit Yes 2
1163 * D 5 4Bit Yes 3
1164 * E 5 4Bit Yes None
1165 * F 16 2Bit Yes 4 [1]
1166 * G 7 4Bit Yes 5
1167 * H 10 4Bit[2] Yes 6
1168 * I 16 2Bit Yes None
1169 * J 12 2Bit Yes None
1170 * K 16 4Bit[2] No None
1171 * L 15 4Bit[2] No None
1172 * M 6 4Bit No IRQ_EINT
1173 * N 16 2Bit No IRQ_EINT
1174 * O 16 2Bit Yes 7
1175 * P 15 2Bit Yes 8
1176 * Q 9 2Bit Yes 9
1177 *
1178 * [1] BANKF pins 14,15 do not form part of the external interrupt sources
1179 * [2] BANK has two control registers, GPxCON0 and GPxCON1
1180 */
1181
1182static struct samsung_gpio_chip s3c64xx_gpios_4bit[] = {
Tomasz Figa54362e12013-10-06 08:59:30 +09001183#ifdef CONFIG_ARCH_S3C64XX
Kukjin Kim1b39d5f2011-08-30 20:39:08 +09001184 {
1185 .chip = {
1186 .base = S3C64XX_GPA(0),
1187 .ngpio = S3C64XX_GPIO_A_NR,
1188 .label = "GPA",
1189 },
1190 }, {
1191 .chip = {
1192 .base = S3C64XX_GPB(0),
1193 .ngpio = S3C64XX_GPIO_B_NR,
1194 .label = "GPB",
1195 },
1196 }, {
1197 .chip = {
1198 .base = S3C64XX_GPC(0),
1199 .ngpio = S3C64XX_GPIO_C_NR,
1200 .label = "GPC",
1201 },
1202 }, {
1203 .chip = {
1204 .base = S3C64XX_GPD(0),
1205 .ngpio = S3C64XX_GPIO_D_NR,
1206 .label = "GPD",
1207 },
1208 }, {
1209 .config = &samsung_gpio_cfgs[0],
1210 .chip = {
1211 .base = S3C64XX_GPE(0),
1212 .ngpio = S3C64XX_GPIO_E_NR,
1213 .label = "GPE",
1214 },
1215 }, {
1216 .base = S3C64XX_GPG_BASE,
1217 .chip = {
1218 .base = S3C64XX_GPG(0),
1219 .ngpio = S3C64XX_GPIO_G_NR,
1220 .label = "GPG",
1221 },
1222 }, {
1223 .base = S3C64XX_GPM_BASE,
1224 .config = &samsung_gpio_cfgs[1],
1225 .chip = {
1226 .base = S3C64XX_GPM(0),
1227 .ngpio = S3C64XX_GPIO_M_NR,
1228 .label = "GPM",
1229 .to_irq = s3c64xx_gpiolib_mbank_to_irq,
1230 },
1231 },
1232#endif
1233};
1234
1235static struct samsung_gpio_chip s3c64xx_gpios_4bit2[] = {
Tomasz Figa54362e12013-10-06 08:59:30 +09001236#ifdef CONFIG_ARCH_S3C64XX
Kukjin Kim1b39d5f2011-08-30 20:39:08 +09001237 {
1238 .base = S3C64XX_GPH_BASE + 0x4,
1239 .chip = {
1240 .base = S3C64XX_GPH(0),
1241 .ngpio = S3C64XX_GPIO_H_NR,
1242 .label = "GPH",
1243 },
1244 }, {
1245 .base = S3C64XX_GPK_BASE + 0x4,
1246 .config = &samsung_gpio_cfgs[0],
1247 .chip = {
1248 .base = S3C64XX_GPK(0),
1249 .ngpio = S3C64XX_GPIO_K_NR,
1250 .label = "GPK",
1251 },
1252 }, {
1253 .base = S3C64XX_GPL_BASE + 0x4,
1254 .config = &samsung_gpio_cfgs[1],
1255 .chip = {
1256 .base = S3C64XX_GPL(0),
1257 .ngpio = S3C64XX_GPIO_L_NR,
1258 .label = "GPL",
1259 .to_irq = s3c64xx_gpiolib_lbank_to_irq,
1260 },
1261 },
1262#endif
1263};
1264
1265static struct samsung_gpio_chip s3c64xx_gpios_2bit[] = {
Tomasz Figa54362e12013-10-06 08:59:30 +09001266#ifdef CONFIG_ARCH_S3C64XX
Kukjin Kim1b39d5f2011-08-30 20:39:08 +09001267 {
1268 .base = S3C64XX_GPF_BASE,
1269 .config = &samsung_gpio_cfgs[6],
1270 .chip = {
1271 .base = S3C64XX_GPF(0),
1272 .ngpio = S3C64XX_GPIO_F_NR,
1273 .label = "GPF",
1274 },
1275 }, {
1276 .config = &samsung_gpio_cfgs[7],
1277 .chip = {
1278 .base = S3C64XX_GPI(0),
1279 .ngpio = S3C64XX_GPIO_I_NR,
1280 .label = "GPI",
1281 },
1282 }, {
1283 .config = &samsung_gpio_cfgs[7],
1284 .chip = {
1285 .base = S3C64XX_GPJ(0),
1286 .ngpio = S3C64XX_GPIO_J_NR,
1287 .label = "GPJ",
1288 },
1289 }, {
1290 .config = &samsung_gpio_cfgs[6],
1291 .chip = {
1292 .base = S3C64XX_GPO(0),
1293 .ngpio = S3C64XX_GPIO_O_NR,
1294 .label = "GPO",
1295 },
1296 }, {
1297 .config = &samsung_gpio_cfgs[6],
1298 .chip = {
1299 .base = S3C64XX_GPP(0),
1300 .ngpio = S3C64XX_GPIO_P_NR,
1301 .label = "GPP",
1302 },
1303 }, {
1304 .config = &samsung_gpio_cfgs[6],
1305 .chip = {
1306 .base = S3C64XX_GPQ(0),
1307 .ngpio = S3C64XX_GPIO_Q_NR,
1308 .label = "GPQ",
1309 },
1310 }, {
1311 .base = S3C64XX_GPN_BASE,
1312 .irq_base = IRQ_EINT(0),
1313 .config = &samsung_gpio_cfgs[5],
1314 .chip = {
1315 .base = S3C64XX_GPN(0),
1316 .ngpio = S3C64XX_GPIO_N_NR,
1317 .label = "GPN",
1318 .to_irq = samsung_gpiolib_to_irq,
1319 },
1320 },
1321#endif
1322};
1323
1324/*
1325 * S5P6440 GPIO bank summary:
1326 *
1327 * Bank GPIOs Style SlpCon ExtInt Group
1328 * A 6 4Bit Yes 1
1329 * B 7 4Bit Yes 1
1330 * C 8 4Bit Yes 2
1331 * F 2 2Bit Yes 4 [1]
1332 * G 7 4Bit Yes 5
1333 * H 10 4Bit[2] Yes 6
1334 * I 16 2Bit Yes None
1335 * J 12 2Bit Yes None
1336 * N 16 2Bit No IRQ_EINT
1337 * P 8 2Bit Yes 8
1338 * R 15 4Bit[2] Yes 8
1339 */
1340
1341static struct samsung_gpio_chip s5p6440_gpios_4bit[] = {
1342#ifdef CONFIG_CPU_S5P6440
1343 {
1344 .chip = {
1345 .base = S5P6440_GPA(0),
1346 .ngpio = S5P6440_GPIO_A_NR,
1347 .label = "GPA",
1348 },
1349 }, {
1350 .chip = {
1351 .base = S5P6440_GPB(0),
1352 .ngpio = S5P6440_GPIO_B_NR,
1353 .label = "GPB",
1354 },
1355 }, {
1356 .chip = {
1357 .base = S5P6440_GPC(0),
1358 .ngpio = S5P6440_GPIO_C_NR,
1359 .label = "GPC",
1360 },
1361 }, {
1362 .base = S5P64X0_GPG_BASE,
1363 .chip = {
1364 .base = S5P6440_GPG(0),
1365 .ngpio = S5P6440_GPIO_G_NR,
1366 .label = "GPG",
1367 },
1368 },
1369#endif
1370};
1371
1372static struct samsung_gpio_chip s5p6440_gpios_4bit2[] = {
1373#ifdef CONFIG_CPU_S5P6440
1374 {
1375 .base = S5P64X0_GPH_BASE + 0x4,
1376 .chip = {
1377 .base = S5P6440_GPH(0),
1378 .ngpio = S5P6440_GPIO_H_NR,
1379 .label = "GPH",
1380 },
1381 },
1382#endif
1383};
1384
1385static struct samsung_gpio_chip s5p6440_gpios_rbank[] = {
1386#ifdef CONFIG_CPU_S5P6440
1387 {
1388 .base = S5P64X0_GPR_BASE + 0x4,
1389 .config = &s5p64x0_gpio_cfg_rbank,
1390 .chip = {
1391 .base = S5P6440_GPR(0),
1392 .ngpio = S5P6440_GPIO_R_NR,
1393 .label = "GPR",
1394 },
1395 },
1396#endif
1397};
1398
1399static struct samsung_gpio_chip s5p6440_gpios_2bit[] = {
1400#ifdef CONFIG_CPU_S5P6440
1401 {
1402 .base = S5P64X0_GPF_BASE,
1403 .config = &samsung_gpio_cfgs[6],
1404 .chip = {
1405 .base = S5P6440_GPF(0),
1406 .ngpio = S5P6440_GPIO_F_NR,
1407 .label = "GPF",
1408 },
1409 }, {
1410 .base = S5P64X0_GPI_BASE,
1411 .config = &samsung_gpio_cfgs[4],
1412 .chip = {
1413 .base = S5P6440_GPI(0),
1414 .ngpio = S5P6440_GPIO_I_NR,
1415 .label = "GPI",
1416 },
1417 }, {
1418 .base = S5P64X0_GPJ_BASE,
1419 .config = &samsung_gpio_cfgs[4],
1420 .chip = {
1421 .base = S5P6440_GPJ(0),
1422 .ngpio = S5P6440_GPIO_J_NR,
1423 .label = "GPJ",
1424 },
1425 }, {
1426 .base = S5P64X0_GPN_BASE,
1427 .config = &samsung_gpio_cfgs[5],
1428 .chip = {
1429 .base = S5P6440_GPN(0),
1430 .ngpio = S5P6440_GPIO_N_NR,
1431 .label = "GPN",
1432 },
1433 }, {
1434 .base = S5P64X0_GPP_BASE,
1435 .config = &samsung_gpio_cfgs[6],
1436 .chip = {
1437 .base = S5P6440_GPP(0),
1438 .ngpio = S5P6440_GPIO_P_NR,
1439 .label = "GPP",
1440 },
1441 },
1442#endif
1443};
1444
1445/*
1446 * S5P6450 GPIO bank summary:
1447 *
1448 * Bank GPIOs Style SlpCon ExtInt Group
1449 * A 6 4Bit Yes 1
1450 * B 7 4Bit Yes 1
1451 * C 8 4Bit Yes 2
1452 * D 8 4Bit Yes None
1453 * F 2 2Bit Yes None
1454 * G 14 4Bit[2] Yes 5
1455 * H 10 4Bit[2] Yes 6
1456 * I 16 2Bit Yes None
1457 * J 12 2Bit Yes None
1458 * K 5 4Bit Yes None
1459 * N 16 2Bit No IRQ_EINT
1460 * P 11 2Bit Yes 8
1461 * Q 14 2Bit Yes None
1462 * R 15 4Bit[2] Yes None
1463 * S 8 2Bit Yes None
1464 *
1465 * [1] BANKF pins 14,15 do not form part of the external interrupt sources
1466 * [2] BANK has two control registers, GPxCON0 and GPxCON1
1467 */
1468
1469static struct samsung_gpio_chip s5p6450_gpios_4bit[] = {
1470#ifdef CONFIG_CPU_S5P6450
1471 {
1472 .chip = {
1473 .base = S5P6450_GPA(0),
1474 .ngpio = S5P6450_GPIO_A_NR,
1475 .label = "GPA",
1476 },
1477 }, {
1478 .chip = {
1479 .base = S5P6450_GPB(0),
1480 .ngpio = S5P6450_GPIO_B_NR,
1481 .label = "GPB",
1482 },
1483 }, {
1484 .chip = {
1485 .base = S5P6450_GPC(0),
1486 .ngpio = S5P6450_GPIO_C_NR,
1487 .label = "GPC",
1488 },
1489 }, {
1490 .chip = {
1491 .base = S5P6450_GPD(0),
1492 .ngpio = S5P6450_GPIO_D_NR,
1493 .label = "GPD",
1494 },
1495 }, {
1496 .base = S5P6450_GPK_BASE,
1497 .chip = {
1498 .base = S5P6450_GPK(0),
1499 .ngpio = S5P6450_GPIO_K_NR,
1500 .label = "GPK",
1501 },
1502 },
1503#endif
1504};
1505
1506static struct samsung_gpio_chip s5p6450_gpios_4bit2[] = {
1507#ifdef CONFIG_CPU_S5P6450
1508 {
1509 .base = S5P64X0_GPG_BASE + 0x4,
1510 .chip = {
1511 .base = S5P6450_GPG(0),
1512 .ngpio = S5P6450_GPIO_G_NR,
1513 .label = "GPG",
1514 },
1515 }, {
1516 .base = S5P64X0_GPH_BASE + 0x4,
1517 .chip = {
1518 .base = S5P6450_GPH(0),
1519 .ngpio = S5P6450_GPIO_H_NR,
1520 .label = "GPH",
1521 },
1522 },
1523#endif
1524};
1525
1526static struct samsung_gpio_chip s5p6450_gpios_rbank[] = {
1527#ifdef CONFIG_CPU_S5P6450
1528 {
1529 .base = S5P64X0_GPR_BASE + 0x4,
1530 .config = &s5p64x0_gpio_cfg_rbank,
1531 .chip = {
1532 .base = S5P6450_GPR(0),
1533 .ngpio = S5P6450_GPIO_R_NR,
1534 .label = "GPR",
1535 },
1536 },
1537#endif
1538};
1539
1540static struct samsung_gpio_chip s5p6450_gpios_2bit[] = {
1541#ifdef CONFIG_CPU_S5P6450
1542 {
1543 .base = S5P64X0_GPF_BASE,
1544 .config = &samsung_gpio_cfgs[6],
1545 .chip = {
1546 .base = S5P6450_GPF(0),
1547 .ngpio = S5P6450_GPIO_F_NR,
1548 .label = "GPF",
1549 },
1550 }, {
1551 .base = S5P64X0_GPI_BASE,
1552 .config = &samsung_gpio_cfgs[4],
1553 .chip = {
1554 .base = S5P6450_GPI(0),
1555 .ngpio = S5P6450_GPIO_I_NR,
1556 .label = "GPI",
1557 },
1558 }, {
1559 .base = S5P64X0_GPJ_BASE,
1560 .config = &samsung_gpio_cfgs[4],
1561 .chip = {
1562 .base = S5P6450_GPJ(0),
1563 .ngpio = S5P6450_GPIO_J_NR,
1564 .label = "GPJ",
1565 },
1566 }, {
1567 .base = S5P64X0_GPN_BASE,
1568 .config = &samsung_gpio_cfgs[5],
1569 .chip = {
1570 .base = S5P6450_GPN(0),
1571 .ngpio = S5P6450_GPIO_N_NR,
1572 .label = "GPN",
1573 },
1574 }, {
1575 .base = S5P64X0_GPP_BASE,
1576 .config = &samsung_gpio_cfgs[6],
1577 .chip = {
1578 .base = S5P6450_GPP(0),
1579 .ngpio = S5P6450_GPIO_P_NR,
1580 .label = "GPP",
1581 },
1582 }, {
1583 .base = S5P6450_GPQ_BASE,
1584 .config = &samsung_gpio_cfgs[5],
1585 .chip = {
1586 .base = S5P6450_GPQ(0),
1587 .ngpio = S5P6450_GPIO_Q_NR,
1588 .label = "GPQ",
1589 },
1590 }, {
1591 .base = S5P6450_GPS_BASE,
1592 .config = &samsung_gpio_cfgs[6],
1593 .chip = {
1594 .base = S5P6450_GPS(0),
1595 .ngpio = S5P6450_GPIO_S_NR,
1596 .label = "GPS",
1597 },
1598 },
1599#endif
1600};
1601
1602/*
1603 * S5PC100 GPIO bank summary:
1604 *
1605 * Bank GPIOs Style INT Type
1606 * A0 8 4Bit GPIO_INT0
1607 * A1 5 4Bit GPIO_INT1
1608 * B 8 4Bit GPIO_INT2
1609 * C 5 4Bit GPIO_INT3
1610 * D 7 4Bit GPIO_INT4
1611 * E0 8 4Bit GPIO_INT5
1612 * E1 6 4Bit GPIO_INT6
1613 * F0 8 4Bit GPIO_INT7
1614 * F1 8 4Bit GPIO_INT8
1615 * F2 8 4Bit GPIO_INT9
1616 * F3 4 4Bit GPIO_INT10
1617 * G0 8 4Bit GPIO_INT11
1618 * G1 3 4Bit GPIO_INT12
1619 * G2 7 4Bit GPIO_INT13
1620 * G3 7 4Bit GPIO_INT14
1621 * H0 8 4Bit WKUP_INT
1622 * H1 8 4Bit WKUP_INT
1623 * H2 8 4Bit WKUP_INT
1624 * H3 8 4Bit WKUP_INT
1625 * I 8 4Bit GPIO_INT15
1626 * J0 8 4Bit GPIO_INT16
1627 * J1 5 4Bit GPIO_INT17
1628 * J2 8 4Bit GPIO_INT18
1629 * J3 8 4Bit GPIO_INT19
1630 * J4 4 4Bit GPIO_INT20
1631 * K0 8 4Bit None
1632 * K1 6 4Bit None
1633 * K2 8 4Bit None
1634 * K3 8 4Bit None
1635 * L0 8 4Bit None
1636 * L1 8 4Bit None
1637 * L2 8 4Bit None
1638 * L3 8 4Bit None
1639 */
1640
1641static struct samsung_gpio_chip s5pc100_gpios_4bit[] = {
1642#ifdef CONFIG_CPU_S5PC100
1643 {
1644 .chip = {
1645 .base = S5PC100_GPA0(0),
1646 .ngpio = S5PC100_GPIO_A0_NR,
1647 .label = "GPA0",
1648 },
1649 }, {
1650 .chip = {
1651 .base = S5PC100_GPA1(0),
1652 .ngpio = S5PC100_GPIO_A1_NR,
1653 .label = "GPA1",
1654 },
1655 }, {
1656 .chip = {
1657 .base = S5PC100_GPB(0),
1658 .ngpio = S5PC100_GPIO_B_NR,
1659 .label = "GPB",
1660 },
1661 }, {
1662 .chip = {
1663 .base = S5PC100_GPC(0),
1664 .ngpio = S5PC100_GPIO_C_NR,
1665 .label = "GPC",
1666 },
1667 }, {
1668 .chip = {
1669 .base = S5PC100_GPD(0),
1670 .ngpio = S5PC100_GPIO_D_NR,
1671 .label = "GPD",
1672 },
1673 }, {
1674 .chip = {
1675 .base = S5PC100_GPE0(0),
1676 .ngpio = S5PC100_GPIO_E0_NR,
1677 .label = "GPE0",
1678 },
1679 }, {
1680 .chip = {
1681 .base = S5PC100_GPE1(0),
1682 .ngpio = S5PC100_GPIO_E1_NR,
1683 .label = "GPE1",
1684 },
1685 }, {
1686 .chip = {
1687 .base = S5PC100_GPF0(0),
1688 .ngpio = S5PC100_GPIO_F0_NR,
1689 .label = "GPF0",
1690 },
1691 }, {
1692 .chip = {
1693 .base = S5PC100_GPF1(0),
1694 .ngpio = S5PC100_GPIO_F1_NR,
1695 .label = "GPF1",
1696 },
1697 }, {
1698 .chip = {
1699 .base = S5PC100_GPF2(0),
1700 .ngpio = S5PC100_GPIO_F2_NR,
1701 .label = "GPF2",
1702 },
1703 }, {
1704 .chip = {
1705 .base = S5PC100_GPF3(0),
1706 .ngpio = S5PC100_GPIO_F3_NR,
1707 .label = "GPF3",
1708 },
1709 }, {
1710 .chip = {
1711 .base = S5PC100_GPG0(0),
1712 .ngpio = S5PC100_GPIO_G0_NR,
1713 .label = "GPG0",
1714 },
1715 }, {
1716 .chip = {
1717 .base = S5PC100_GPG1(0),
1718 .ngpio = S5PC100_GPIO_G1_NR,
1719 .label = "GPG1",
1720 },
1721 }, {
1722 .chip = {
1723 .base = S5PC100_GPG2(0),
1724 .ngpio = S5PC100_GPIO_G2_NR,
1725 .label = "GPG2",
1726 },
1727 }, {
1728 .chip = {
1729 .base = S5PC100_GPG3(0),
1730 .ngpio = S5PC100_GPIO_G3_NR,
1731 .label = "GPG3",
1732 },
1733 }, {
1734 .chip = {
1735 .base = S5PC100_GPI(0),
1736 .ngpio = S5PC100_GPIO_I_NR,
1737 .label = "GPI",
1738 },
1739 }, {
1740 .chip = {
1741 .base = S5PC100_GPJ0(0),
1742 .ngpio = S5PC100_GPIO_J0_NR,
1743 .label = "GPJ0",
1744 },
1745 }, {
1746 .chip = {
1747 .base = S5PC100_GPJ1(0),
1748 .ngpio = S5PC100_GPIO_J1_NR,
1749 .label = "GPJ1",
1750 },
1751 }, {
1752 .chip = {
1753 .base = S5PC100_GPJ2(0),
1754 .ngpio = S5PC100_GPIO_J2_NR,
1755 .label = "GPJ2",
1756 },
1757 }, {
1758 .chip = {
1759 .base = S5PC100_GPJ3(0),
1760 .ngpio = S5PC100_GPIO_J3_NR,
1761 .label = "GPJ3",
1762 },
1763 }, {
1764 .chip = {
1765 .base = S5PC100_GPJ4(0),
1766 .ngpio = S5PC100_GPIO_J4_NR,
1767 .label = "GPJ4",
1768 },
1769 }, {
1770 .chip = {
1771 .base = S5PC100_GPK0(0),
1772 .ngpio = S5PC100_GPIO_K0_NR,
1773 .label = "GPK0",
1774 },
1775 }, {
1776 .chip = {
1777 .base = S5PC100_GPK1(0),
1778 .ngpio = S5PC100_GPIO_K1_NR,
1779 .label = "GPK1",
1780 },
1781 }, {
1782 .chip = {
1783 .base = S5PC100_GPK2(0),
1784 .ngpio = S5PC100_GPIO_K2_NR,
1785 .label = "GPK2",
1786 },
1787 }, {
1788 .chip = {
1789 .base = S5PC100_GPK3(0),
1790 .ngpio = S5PC100_GPIO_K3_NR,
1791 .label = "GPK3",
1792 },
1793 }, {
1794 .chip = {
1795 .base = S5PC100_GPL0(0),
1796 .ngpio = S5PC100_GPIO_L0_NR,
1797 .label = "GPL0",
1798 },
1799 }, {
1800 .chip = {
1801 .base = S5PC100_GPL1(0),
1802 .ngpio = S5PC100_GPIO_L1_NR,
1803 .label = "GPL1",
1804 },
1805 }, {
1806 .chip = {
1807 .base = S5PC100_GPL2(0),
1808 .ngpio = S5PC100_GPIO_L2_NR,
1809 .label = "GPL2",
1810 },
1811 }, {
1812 .chip = {
1813 .base = S5PC100_GPL3(0),
1814 .ngpio = S5PC100_GPIO_L3_NR,
1815 .label = "GPL3",
1816 },
1817 }, {
1818 .chip = {
1819 .base = S5PC100_GPL4(0),
1820 .ngpio = S5PC100_GPIO_L4_NR,
1821 .label = "GPL4",
1822 },
1823 }, {
1824 .base = (S5P_VA_GPIO + 0xC00),
1825 .irq_base = IRQ_EINT(0),
1826 .chip = {
1827 .base = S5PC100_GPH0(0),
1828 .ngpio = S5PC100_GPIO_H0_NR,
1829 .label = "GPH0",
1830 .to_irq = samsung_gpiolib_to_irq,
1831 },
1832 }, {
1833 .base = (S5P_VA_GPIO + 0xC20),
1834 .irq_base = IRQ_EINT(8),
1835 .chip = {
1836 .base = S5PC100_GPH1(0),
1837 .ngpio = S5PC100_GPIO_H1_NR,
1838 .label = "GPH1",
1839 .to_irq = samsung_gpiolib_to_irq,
1840 },
1841 }, {
1842 .base = (S5P_VA_GPIO + 0xC40),
1843 .irq_base = IRQ_EINT(16),
1844 .chip = {
1845 .base = S5PC100_GPH2(0),
1846 .ngpio = S5PC100_GPIO_H2_NR,
1847 .label = "GPH2",
1848 .to_irq = samsung_gpiolib_to_irq,
1849 },
1850 }, {
1851 .base = (S5P_VA_GPIO + 0xC60),
1852 .irq_base = IRQ_EINT(24),
1853 .chip = {
1854 .base = S5PC100_GPH3(0),
1855 .ngpio = S5PC100_GPIO_H3_NR,
1856 .label = "GPH3",
1857 .to_irq = samsung_gpiolib_to_irq,
1858 },
1859 },
1860#endif
1861};
1862
1863/*
1864 * Followings are the gpio banks in S5PV210/S5PC110
1865 *
1866 * The 'config' member when left to NULL, is initialized to the default
Marek Szyprowskib391f8c2011-09-26 13:10:32 +09001867 * structure samsung_gpio_cfgs[3] in the init function below.
Kukjin Kim1b39d5f2011-08-30 20:39:08 +09001868 *
1869 * The 'base' member is also initialized in the init function below.
1870 * Note: The initialization of 'base' member of samsung_gpio_chip structure
1871 * uses the above macro and depends on the banks being listed in order here.
1872 */
1873
1874static struct samsung_gpio_chip s5pv210_gpios_4bit[] = {
1875#ifdef CONFIG_CPU_S5PV210
1876 {
1877 .chip = {
1878 .base = S5PV210_GPA0(0),
1879 .ngpio = S5PV210_GPIO_A0_NR,
1880 .label = "GPA0",
1881 },
1882 }, {
1883 .chip = {
1884 .base = S5PV210_GPA1(0),
1885 .ngpio = S5PV210_GPIO_A1_NR,
1886 .label = "GPA1",
1887 },
1888 }, {
1889 .chip = {
1890 .base = S5PV210_GPB(0),
1891 .ngpio = S5PV210_GPIO_B_NR,
1892 .label = "GPB",
1893 },
1894 }, {
1895 .chip = {
1896 .base = S5PV210_GPC0(0),
1897 .ngpio = S5PV210_GPIO_C0_NR,
1898 .label = "GPC0",
1899 },
1900 }, {
1901 .chip = {
1902 .base = S5PV210_GPC1(0),
1903 .ngpio = S5PV210_GPIO_C1_NR,
1904 .label = "GPC1",
1905 },
1906 }, {
1907 .chip = {
1908 .base = S5PV210_GPD0(0),
1909 .ngpio = S5PV210_GPIO_D0_NR,
1910 .label = "GPD0",
1911 },
1912 }, {
1913 .chip = {
1914 .base = S5PV210_GPD1(0),
1915 .ngpio = S5PV210_GPIO_D1_NR,
1916 .label = "GPD1",
1917 },
1918 }, {
1919 .chip = {
1920 .base = S5PV210_GPE0(0),
1921 .ngpio = S5PV210_GPIO_E0_NR,
1922 .label = "GPE0",
1923 },
1924 }, {
1925 .chip = {
1926 .base = S5PV210_GPE1(0),
1927 .ngpio = S5PV210_GPIO_E1_NR,
1928 .label = "GPE1",
1929 },
1930 }, {
1931 .chip = {
1932 .base = S5PV210_GPF0(0),
1933 .ngpio = S5PV210_GPIO_F0_NR,
1934 .label = "GPF0",
1935 },
1936 }, {
1937 .chip = {
1938 .base = S5PV210_GPF1(0),
1939 .ngpio = S5PV210_GPIO_F1_NR,
1940 .label = "GPF1",
1941 },
1942 }, {
1943 .chip = {
1944 .base = S5PV210_GPF2(0),
1945 .ngpio = S5PV210_GPIO_F2_NR,
1946 .label = "GPF2",
1947 },
1948 }, {
1949 .chip = {
1950 .base = S5PV210_GPF3(0),
1951 .ngpio = S5PV210_GPIO_F3_NR,
1952 .label = "GPF3",
1953 },
1954 }, {
1955 .chip = {
1956 .base = S5PV210_GPG0(0),
1957 .ngpio = S5PV210_GPIO_G0_NR,
1958 .label = "GPG0",
1959 },
1960 }, {
1961 .chip = {
1962 .base = S5PV210_GPG1(0),
1963 .ngpio = S5PV210_GPIO_G1_NR,
1964 .label = "GPG1",
1965 },
1966 }, {
1967 .chip = {
1968 .base = S5PV210_GPG2(0),
1969 .ngpio = S5PV210_GPIO_G2_NR,
1970 .label = "GPG2",
1971 },
1972 }, {
1973 .chip = {
1974 .base = S5PV210_GPG3(0),
1975 .ngpio = S5PV210_GPIO_G3_NR,
1976 .label = "GPG3",
1977 },
1978 }, {
1979 .chip = {
1980 .base = S5PV210_GPI(0),
1981 .ngpio = S5PV210_GPIO_I_NR,
1982 .label = "GPI",
1983 },
1984 }, {
1985 .chip = {
1986 .base = S5PV210_GPJ0(0),
1987 .ngpio = S5PV210_GPIO_J0_NR,
1988 .label = "GPJ0",
1989 },
1990 }, {
1991 .chip = {
1992 .base = S5PV210_GPJ1(0),
1993 .ngpio = S5PV210_GPIO_J1_NR,
1994 .label = "GPJ1",
1995 },
1996 }, {
1997 .chip = {
1998 .base = S5PV210_GPJ2(0),
1999 .ngpio = S5PV210_GPIO_J2_NR,
2000 .label = "GPJ2",
2001 },
2002 }, {
2003 .chip = {
2004 .base = S5PV210_GPJ3(0),
2005 .ngpio = S5PV210_GPIO_J3_NR,
2006 .label = "GPJ3",
2007 },
2008 }, {
2009 .chip = {
2010 .base = S5PV210_GPJ4(0),
2011 .ngpio = S5PV210_GPIO_J4_NR,
2012 .label = "GPJ4",
2013 },
2014 }, {
2015 .chip = {
2016 .base = S5PV210_MP01(0),
2017 .ngpio = S5PV210_GPIO_MP01_NR,
2018 .label = "MP01",
2019 },
2020 }, {
2021 .chip = {
2022 .base = S5PV210_MP02(0),
2023 .ngpio = S5PV210_GPIO_MP02_NR,
2024 .label = "MP02",
2025 },
2026 }, {
2027 .chip = {
2028 .base = S5PV210_MP03(0),
2029 .ngpio = S5PV210_GPIO_MP03_NR,
2030 .label = "MP03",
2031 },
2032 }, {
2033 .chip = {
2034 .base = S5PV210_MP04(0),
2035 .ngpio = S5PV210_GPIO_MP04_NR,
2036 .label = "MP04",
2037 },
2038 }, {
2039 .chip = {
2040 .base = S5PV210_MP05(0),
2041 .ngpio = S5PV210_GPIO_MP05_NR,
2042 .label = "MP05",
2043 },
2044 }, {
2045 .base = (S5P_VA_GPIO + 0xC00),
2046 .irq_base = IRQ_EINT(0),
2047 .chip = {
2048 .base = S5PV210_GPH0(0),
2049 .ngpio = S5PV210_GPIO_H0_NR,
2050 .label = "GPH0",
2051 .to_irq = samsung_gpiolib_to_irq,
2052 },
2053 }, {
2054 .base = (S5P_VA_GPIO + 0xC20),
2055 .irq_base = IRQ_EINT(8),
2056 .chip = {
2057 .base = S5PV210_GPH1(0),
2058 .ngpio = S5PV210_GPIO_H1_NR,
2059 .label = "GPH1",
2060 .to_irq = samsung_gpiolib_to_irq,
2061 },
2062 }, {
2063 .base = (S5P_VA_GPIO + 0xC40),
2064 .irq_base = IRQ_EINT(16),
2065 .chip = {
2066 .base = S5PV210_GPH2(0),
2067 .ngpio = S5PV210_GPIO_H2_NR,
2068 .label = "GPH2",
2069 .to_irq = samsung_gpiolib_to_irq,
2070 },
2071 }, {
2072 .base = (S5P_VA_GPIO + 0xC60),
2073 .irq_base = IRQ_EINT(24),
2074 .chip = {
2075 .base = S5PV210_GPH3(0),
2076 .ngpio = S5PV210_GPIO_H3_NR,
2077 .label = "GPH3",
2078 .to_irq = samsung_gpiolib_to_irq,
2079 },
2080 },
2081#endif
2082};
2083
Kukjin Kim1b39d5f2011-08-30 20:39:08 +09002084/* TODO: cleanup soc_is_* */
2085static __init int samsung_gpiolib_init(void)
2086{
2087 struct samsung_gpio_chip *chip;
2088 int i, nr_chips;
2089 int group = 0;
2090
Tomasz Figaba51bdd2012-11-07 08:44:55 +09002091 /*
Tomasz Figa608f9732013-08-26 02:37:41 +09002092 * Currently there are two drivers that can provide GPIO support for
2093 * Samsung SoCs. For device tree enabled platforms, the new
2094 * pinctrl-samsung driver is used, providing both GPIO and pin control
2095 * interfaces. For legacy (non-DT) platforms this driver is used.
2096 */
2097 if (of_have_populated_dt())
2098 return -ENODEV;
Tomasz Figaba51bdd2012-11-07 08:44:55 +09002099
Kukjin Kim1b39d5f2011-08-30 20:39:08 +09002100 samsung_gpiolib_set_cfg(samsung_gpio_cfgs, ARRAY_SIZE(samsung_gpio_cfgs));
2101
2102 if (soc_is_s3c24xx()) {
2103 s3c24xx_gpiolib_add_chips(s3c24xx_gpios,
2104 ARRAY_SIZE(s3c24xx_gpios), S3C24XX_VA_GPIO);
2105 } else if (soc_is_s3c64xx()) {
2106 samsung_gpiolib_add_2bit_chips(s3c64xx_gpios_2bit,
2107 ARRAY_SIZE(s3c64xx_gpios_2bit),
2108 S3C64XX_VA_GPIO + 0xE0, 0x20);
2109 samsung_gpiolib_add_4bit_chips(s3c64xx_gpios_4bit,
2110 ARRAY_SIZE(s3c64xx_gpios_4bit),
2111 S3C64XX_VA_GPIO);
2112 samsung_gpiolib_add_4bit2_chips(s3c64xx_gpios_4bit2,
2113 ARRAY_SIZE(s3c64xx_gpios_4bit2));
2114 } else if (soc_is_s5p6440()) {
2115 samsung_gpiolib_add_2bit_chips(s5p6440_gpios_2bit,
2116 ARRAY_SIZE(s5p6440_gpios_2bit), NULL, 0x0);
2117 samsung_gpiolib_add_4bit_chips(s5p6440_gpios_4bit,
2118 ARRAY_SIZE(s5p6440_gpios_4bit), S5P_VA_GPIO);
2119 samsung_gpiolib_add_4bit2_chips(s5p6440_gpios_4bit2,
2120 ARRAY_SIZE(s5p6440_gpios_4bit2));
2121 s5p64x0_gpiolib_add_rbank(s5p6440_gpios_rbank,
2122 ARRAY_SIZE(s5p6440_gpios_rbank));
2123 } else if (soc_is_s5p6450()) {
2124 samsung_gpiolib_add_2bit_chips(s5p6450_gpios_2bit,
2125 ARRAY_SIZE(s5p6450_gpios_2bit), NULL, 0x0);
2126 samsung_gpiolib_add_4bit_chips(s5p6450_gpios_4bit,
2127 ARRAY_SIZE(s5p6450_gpios_4bit), S5P_VA_GPIO);
2128 samsung_gpiolib_add_4bit2_chips(s5p6450_gpios_4bit2,
2129 ARRAY_SIZE(s5p6450_gpios_4bit2));
2130 s5p64x0_gpiolib_add_rbank(s5p6450_gpios_rbank,
2131 ARRAY_SIZE(s5p6450_gpios_rbank));
2132 } else if (soc_is_s5pc100()) {
2133 group = 0;
2134 chip = s5pc100_gpios_4bit;
2135 nr_chips = ARRAY_SIZE(s5pc100_gpios_4bit);
2136
2137 for (i = 0; i < nr_chips; i++, chip++) {
2138 if (!chip->config) {
Marek Szyprowskib391f8c2011-09-26 13:10:32 +09002139 chip->config = &samsung_gpio_cfgs[3];
Kukjin Kim1b39d5f2011-08-30 20:39:08 +09002140 chip->group = group++;
2141 }
2142 }
2143 samsung_gpiolib_add_4bit_chips(s5pc100_gpios_4bit, nr_chips, S5P_VA_GPIO);
2144#if defined(CONFIG_CPU_S5PC100) && defined(CONFIG_S5P_GPIO_INT)
2145 s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
2146#endif
2147 } else if (soc_is_s5pv210()) {
2148 group = 0;
2149 chip = s5pv210_gpios_4bit;
2150 nr_chips = ARRAY_SIZE(s5pv210_gpios_4bit);
2151
2152 for (i = 0; i < nr_chips; i++, chip++) {
2153 if (!chip->config) {
Marek Szyprowskib391f8c2011-09-26 13:10:32 +09002154 chip->config = &samsung_gpio_cfgs[3];
Kukjin Kim1b39d5f2011-08-30 20:39:08 +09002155 chip->group = group++;
2156 }
2157 }
2158 samsung_gpiolib_add_4bit_chips(s5pv210_gpios_4bit, nr_chips, S5P_VA_GPIO);
2159#if defined(CONFIG_CPU_S5PV210) && defined(CONFIG_S5P_GPIO_INT)
2160 s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
2161#endif
Mark Brownfbe92fc2011-10-18 08:46:50 +09002162 } else {
2163 WARN(1, "Unknown SoC in gpio-samsung, no GPIOs added\n");
2164 return -ENODEV;
Kukjin Kim1b39d5f2011-08-30 20:39:08 +09002165 }
2166
2167 return 0;
Kukjin Kim1b39d5f2011-08-30 20:39:08 +09002168}
2169core_initcall(samsung_gpiolib_init);
2170
2171int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
2172{
2173 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2174 unsigned long flags;
2175 int offset;
2176 int ret;
2177
2178 if (!chip)
2179 return -EINVAL;
2180
2181 offset = pin - chip->chip.base;
2182
2183 samsung_gpio_lock(chip, flags);
2184 ret = samsung_gpio_do_setcfg(chip, offset, config);
2185 samsung_gpio_unlock(chip, flags);
2186
2187 return ret;
2188}
2189EXPORT_SYMBOL(s3c_gpio_cfgpin);
2190
2191int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
2192 unsigned int cfg)
2193{
2194 int ret;
2195
2196 for (; nr > 0; nr--, start++) {
2197 ret = s3c_gpio_cfgpin(start, cfg);
2198 if (ret != 0)
2199 return ret;
2200 }
2201
2202 return 0;
2203}
2204EXPORT_SYMBOL_GPL(s3c_gpio_cfgpin_range);
2205
2206int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
2207 unsigned int cfg, samsung_gpio_pull_t pull)
2208{
2209 int ret;
2210
2211 for (; nr > 0; nr--, start++) {
2212 s3c_gpio_setpull(start, pull);
2213 ret = s3c_gpio_cfgpin(start, cfg);
2214 if (ret != 0)
2215 return ret;
2216 }
2217
2218 return 0;
2219}
2220EXPORT_SYMBOL_GPL(s3c_gpio_cfgall_range);
2221
2222unsigned s3c_gpio_getcfg(unsigned int pin)
2223{
2224 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2225 unsigned long flags;
2226 unsigned ret = 0;
2227 int offset;
2228
2229 if (chip) {
2230 offset = pin - chip->chip.base;
2231
2232 samsung_gpio_lock(chip, flags);
2233 ret = samsung_gpio_do_getcfg(chip, offset);
2234 samsung_gpio_unlock(chip, flags);
2235 }
2236
2237 return ret;
2238}
2239EXPORT_SYMBOL(s3c_gpio_getcfg);
2240
2241int s3c_gpio_setpull(unsigned int pin, samsung_gpio_pull_t pull)
2242{
2243 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2244 unsigned long flags;
2245 int offset, ret;
2246
2247 if (!chip)
2248 return -EINVAL;
2249
2250 offset = pin - chip->chip.base;
2251
2252 samsung_gpio_lock(chip, flags);
2253 ret = samsung_gpio_do_setpull(chip, offset, pull);
2254 samsung_gpio_unlock(chip, flags);
2255
2256 return ret;
2257}
2258EXPORT_SYMBOL(s3c_gpio_setpull);
2259
2260samsung_gpio_pull_t s3c_gpio_getpull(unsigned int pin)
2261{
2262 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2263 unsigned long flags;
2264 int offset;
2265 u32 pup = 0;
2266
2267 if (chip) {
2268 offset = pin - chip->chip.base;
2269
2270 samsung_gpio_lock(chip, flags);
2271 pup = samsung_gpio_do_getpull(chip, offset);
2272 samsung_gpio_unlock(chip, flags);
2273 }
2274
2275 return (__force samsung_gpio_pull_t)pup;
2276}
2277EXPORT_SYMBOL(s3c_gpio_getpull);
2278
Kukjin Kim1b39d5f2011-08-30 20:39:08 +09002279#ifdef CONFIG_S5P_GPIO_DRVSTR
2280s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin)
2281{
2282 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2283 unsigned int off;
2284 void __iomem *reg;
2285 int shift;
2286 u32 drvstr;
2287
2288 if (!chip)
2289 return -EINVAL;
2290
2291 off = pin - chip->chip.base;
2292 shift = off * 2;
2293 reg = chip->base + 0x0C;
2294
2295 drvstr = __raw_readl(reg);
2296 drvstr = drvstr >> shift;
2297 drvstr &= 0x3;
2298
2299 return (__force s5p_gpio_drvstr_t)drvstr;
2300}
2301EXPORT_SYMBOL(s5p_gpio_get_drvstr);
2302
2303int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr)
2304{
2305 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2306 unsigned int off;
2307 void __iomem *reg;
2308 int shift;
2309 u32 tmp;
2310
2311 if (!chip)
2312 return -EINVAL;
2313
2314 off = pin - chip->chip.base;
2315 shift = off * 2;
2316 reg = chip->base + 0x0C;
2317
2318 tmp = __raw_readl(reg);
2319 tmp &= ~(0x3 << shift);
2320 tmp |= drvstr << shift;
2321
2322 __raw_writel(tmp, reg);
2323
2324 return 0;
2325}
2326EXPORT_SYMBOL(s5p_gpio_set_drvstr);
2327#endif /* CONFIG_S5P_GPIO_DRVSTR */
2328
2329#ifdef CONFIG_PLAT_S3C24XX
2330unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
2331{
2332 unsigned long flags;
2333 unsigned long misccr;
2334
2335 local_irq_save(flags);
2336 misccr = __raw_readl(S3C24XX_MISCCR);
2337 misccr &= ~clear;
2338 misccr ^= change;
2339 __raw_writel(misccr, S3C24XX_MISCCR);
2340 local_irq_restore(flags);
2341
2342 return misccr;
2343}
2344EXPORT_SYMBOL(s3c2410_modify_misccr);
2345#endif