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