This source file includes following definitions.
- samsung_gpio_setpull_updown
- samsung_gpio_getpull_updown
- s3c2443_gpio_setpull
- s3c2443_gpio_getpull
- s3c24xx_gpio_setpull_1
- s3c24xx_gpio_getpull_1
- s3c24xx_gpio_getpull_1up
- s3c24xx_gpio_setpull_1up
- s3c24xx_gpio_getpull_1down
- s3c24xx_gpio_setpull_1down
- samsung_gpio_setcfg_2bit
- samsung_gpio_getcfg_2bit
- samsung_gpio_setcfg_4bit
- samsung_gpio_getcfg_4bit
- s3c24xx_gpio_setcfg_abank
- s3c24xx_gpio_getcfg_abank
- samsung_gpiolib_set_cfg
- samsung_gpiolib_2bit_input
- samsung_gpiolib_2bit_output
- samsung_gpiolib_4bit_input
- samsung_gpiolib_4bit_output
- samsung_gpiolib_4bit2_input
- samsung_gpiolib_4bit2_output
- s3c24xx_gpiolib_banka_input
- s3c24xx_gpiolib_banka_output
- samsung_gpiolib_set
- samsung_gpiolib_get
- s3c_gpiolib_track
- samsung_gpiolib_add
- s3c24xx_gpiolib_add_chips
- samsung_gpiolib_add_2bit_chips
- samsung_gpiolib_add_4bit_chips
- samsung_gpiolib_add_4bit2_chips
- samsung_gpiolib_to_irq
- s3c24xx_gpiolib_fbank_to_irq
- s3c64xx_gpiolib_mbank_to_irq
- s3c64xx_gpiolib_lbank_to_irq
- samsung_gpiolib_init
- s3c_gpio_cfgpin
- s3c_gpio_cfgpin_range
- s3c_gpio_cfgall_range
- s3c_gpio_getcfg
- s3c_gpio_setpull
- s3c_gpio_getpull
- s3c2410_modify_misccr
1
2
3
4
5
6
7
8
9
10
11
12
13 #include <linux/kernel.h>
14 #include <linux/irq.h>
15 #include <linux/io.h>
16 #include <linux/gpio.h>
17 #include <linux/init.h>
18 #include <linux/spinlock.h>
19 #include <linux/module.h>
20 #include <linux/interrupt.h>
21 #include <linux/device.h>
22 #include <linux/ioport.h>
23 #include <linux/of.h>
24 #include <linux/slab.h>
25 #include <linux/of_address.h>
26
27 #include <asm/irq.h>
28
29 #include <mach/irqs.h>
30 #include <mach/map.h>
31 #include <mach/regs-gpio.h>
32 #include <mach/gpio-samsung.h>
33
34 #include <plat/cpu.h>
35 #include <plat/gpio-core.h>
36 #include <plat/gpio-cfg.h>
37 #include <plat/gpio-cfg-helpers.h>
38 #include <plat/pm.h>
39
40 int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip,
41 unsigned int off, samsung_gpio_pull_t pull)
42 {
43 void __iomem *reg = chip->base + 0x08;
44 int shift = off * 2;
45 u32 pup;
46
47 pup = __raw_readl(reg);
48 pup &= ~(3 << shift);
49 pup |= pull << shift;
50 __raw_writel(pup, reg);
51
52 return 0;
53 }
54
55 samsung_gpio_pull_t samsung_gpio_getpull_updown(struct samsung_gpio_chip *chip,
56 unsigned int off)
57 {
58 void __iomem *reg = chip->base + 0x08;
59 int shift = off * 2;
60 u32 pup = __raw_readl(reg);
61
62 pup >>= shift;
63 pup &= 0x3;
64
65 return (__force samsung_gpio_pull_t)pup;
66 }
67
68 int s3c2443_gpio_setpull(struct samsung_gpio_chip *chip,
69 unsigned int off, samsung_gpio_pull_t pull)
70 {
71 switch (pull) {
72 case S3C_GPIO_PULL_NONE:
73 pull = 0x01;
74 break;
75 case S3C_GPIO_PULL_UP:
76 pull = 0x00;
77 break;
78 case S3C_GPIO_PULL_DOWN:
79 pull = 0x02;
80 break;
81 }
82 return samsung_gpio_setpull_updown(chip, off, pull);
83 }
84
85 samsung_gpio_pull_t s3c2443_gpio_getpull(struct samsung_gpio_chip *chip,
86 unsigned int off)
87 {
88 samsung_gpio_pull_t pull;
89
90 pull = samsung_gpio_getpull_updown(chip, off);
91
92 switch (pull) {
93 case 0x00:
94 pull = S3C_GPIO_PULL_UP;
95 break;
96 case 0x01:
97 case 0x03:
98 pull = S3C_GPIO_PULL_NONE;
99 break;
100 case 0x02:
101 pull = S3C_GPIO_PULL_DOWN;
102 break;
103 }
104
105 return pull;
106 }
107
108 static int s3c24xx_gpio_setpull_1(struct samsung_gpio_chip *chip,
109 unsigned int off, samsung_gpio_pull_t pull,
110 samsung_gpio_pull_t updown)
111 {
112 void __iomem *reg = chip->base + 0x08;
113 u32 pup = __raw_readl(reg);
114
115 if (pull == updown)
116 pup &= ~(1 << off);
117 else if (pull == S3C_GPIO_PULL_NONE)
118 pup |= (1 << off);
119 else
120 return -EINVAL;
121
122 __raw_writel(pup, reg);
123 return 0;
124 }
125
126 static samsung_gpio_pull_t s3c24xx_gpio_getpull_1(struct samsung_gpio_chip *chip,
127 unsigned int off,
128 samsung_gpio_pull_t updown)
129 {
130 void __iomem *reg = chip->base + 0x08;
131 u32 pup = __raw_readl(reg);
132
133 pup &= (1 << off);
134 return pup ? S3C_GPIO_PULL_NONE : updown;
135 }
136
137 samsung_gpio_pull_t s3c24xx_gpio_getpull_1up(struct samsung_gpio_chip *chip,
138 unsigned int off)
139 {
140 return s3c24xx_gpio_getpull_1(chip, off, S3C_GPIO_PULL_UP);
141 }
142
143 int s3c24xx_gpio_setpull_1up(struct samsung_gpio_chip *chip,
144 unsigned int off, samsung_gpio_pull_t pull)
145 {
146 return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_UP);
147 }
148
149 samsung_gpio_pull_t s3c24xx_gpio_getpull_1down(struct samsung_gpio_chip *chip,
150 unsigned int off)
151 {
152 return s3c24xx_gpio_getpull_1(chip, off, S3C_GPIO_PULL_DOWN);
153 }
154
155 int s3c24xx_gpio_setpull_1down(struct samsung_gpio_chip *chip,
156 unsigned int off, samsung_gpio_pull_t pull)
157 {
158 return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_DOWN);
159 }
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175 static int samsung_gpio_setcfg_2bit(struct samsung_gpio_chip *chip,
176 unsigned int off, unsigned int cfg)
177 {
178 void __iomem *reg = chip->base;
179 unsigned int shift = off * 2;
180 u32 con;
181
182 if (samsung_gpio_is_cfg_special(cfg)) {
183 cfg &= 0xf;
184 if (cfg > 3)
185 return -EINVAL;
186
187 cfg <<= shift;
188 }
189
190 con = __raw_readl(reg);
191 con &= ~(0x3 << shift);
192 con |= cfg;
193 __raw_writel(con, reg);
194
195 return 0;
196 }
197
198
199
200
201
202
203
204
205
206
207
208 static unsigned int samsung_gpio_getcfg_2bit(struct samsung_gpio_chip *chip,
209 unsigned int off)
210 {
211 u32 con;
212
213 con = __raw_readl(chip->base);
214 con >>= off * 2;
215 con &= 3;
216
217
218 return S3C_GPIO_SPECIAL(con);
219 }
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238 static int samsung_gpio_setcfg_4bit(struct samsung_gpio_chip *chip,
239 unsigned int off, unsigned int cfg)
240 {
241 void __iomem *reg = chip->base;
242 unsigned int shift = (off & 7) * 4;
243 u32 con;
244
245 if (off < 8 && chip->chip.ngpio > 8)
246 reg -= 4;
247
248 if (samsung_gpio_is_cfg_special(cfg)) {
249 cfg &= 0xf;
250 cfg <<= shift;
251 }
252
253 con = __raw_readl(reg);
254 con &= ~(0xf << shift);
255 con |= cfg;
256 __raw_writel(con, reg);
257
258 return 0;
259 }
260
261
262
263
264
265
266
267
268
269
270
271
272
273 static unsigned samsung_gpio_getcfg_4bit(struct samsung_gpio_chip *chip,
274 unsigned int off)
275 {
276 void __iomem *reg = chip->base;
277 unsigned int shift = (off & 7) * 4;
278 u32 con;
279
280 if (off < 8 && chip->chip.ngpio > 8)
281 reg -= 4;
282
283 con = __raw_readl(reg);
284 con >>= shift;
285 con &= 0xf;
286
287
288 return S3C_GPIO_SPECIAL(con);
289 }
290
291 #ifdef CONFIG_PLAT_S3C24XX
292
293
294
295
296
297
298
299
300
301
302
303 static int s3c24xx_gpio_setcfg_abank(struct samsung_gpio_chip *chip,
304 unsigned int off, unsigned int cfg)
305 {
306 void __iomem *reg = chip->base;
307 unsigned int shift = off;
308 u32 con;
309
310 if (samsung_gpio_is_cfg_special(cfg)) {
311 cfg &= 0xf;
312
313
314 cfg -= 1;
315 if (cfg > 1)
316 return -EINVAL;
317
318 cfg <<= shift;
319 }
320
321 con = __raw_readl(reg);
322 con &= ~(0x1 << shift);
323 con |= cfg;
324 __raw_writel(con, reg);
325
326 return 0;
327 }
328
329
330
331
332
333
334
335
336
337
338
339
340
341 static unsigned s3c24xx_gpio_getcfg_abank(struct samsung_gpio_chip *chip,
342 unsigned int off)
343 {
344 u32 con;
345
346 con = __raw_readl(chip->base);
347 con >>= off;
348 con &= 1;
349 con++;
350
351 return S3C_GPIO_SFN(con);
352 }
353 #endif
354
355 static void __init samsung_gpiolib_set_cfg(struct samsung_gpio_cfg *chipcfg,
356 int nr_chips)
357 {
358 for (; nr_chips > 0; nr_chips--, chipcfg++) {
359 if (!chipcfg->set_config)
360 chipcfg->set_config = samsung_gpio_setcfg_4bit;
361 if (!chipcfg->get_config)
362 chipcfg->get_config = samsung_gpio_getcfg_4bit;
363 if (!chipcfg->set_pull)
364 chipcfg->set_pull = samsung_gpio_setpull_updown;
365 if (!chipcfg->get_pull)
366 chipcfg->get_pull = samsung_gpio_getpull_updown;
367 }
368 }
369
370 struct samsung_gpio_cfg s3c24xx_gpiocfg_default = {
371 .set_config = samsung_gpio_setcfg_2bit,
372 .get_config = samsung_gpio_getcfg_2bit,
373 };
374
375 #ifdef CONFIG_PLAT_S3C24XX
376 static struct samsung_gpio_cfg s3c24xx_gpiocfg_banka = {
377 .set_config = s3c24xx_gpio_setcfg_abank,
378 .get_config = s3c24xx_gpio_getcfg_abank,
379 };
380 #endif
381
382 static struct samsung_gpio_cfg samsung_gpio_cfgs[] = {
383 [0] = {
384 .cfg_eint = 0x0,
385 },
386 [1] = {
387 .cfg_eint = 0x3,
388 },
389 [2] = {
390 .cfg_eint = 0x7,
391 },
392 [3] = {
393 .cfg_eint = 0xF,
394 },
395 [4] = {
396 .cfg_eint = 0x0,
397 .set_config = samsung_gpio_setcfg_2bit,
398 .get_config = samsung_gpio_getcfg_2bit,
399 },
400 [5] = {
401 .cfg_eint = 0x2,
402 .set_config = samsung_gpio_setcfg_2bit,
403 .get_config = samsung_gpio_getcfg_2bit,
404 },
405 [6] = {
406 .cfg_eint = 0x3,
407 .set_config = samsung_gpio_setcfg_2bit,
408 .get_config = samsung_gpio_getcfg_2bit,
409 },
410 [7] = {
411 .set_config = samsung_gpio_setcfg_2bit,
412 .get_config = samsung_gpio_getcfg_2bit,
413 },
414 };
415
416
417
418
419
420
421
422
423
424
425
426
427
428 static int samsung_gpiolib_2bit_input(struct gpio_chip *chip, unsigned offset)
429 {
430 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
431 void __iomem *base = ourchip->base;
432 unsigned long flags;
433 unsigned long con;
434
435 samsung_gpio_lock(ourchip, flags);
436
437 con = __raw_readl(base + 0x00);
438 con &= ~(3 << (offset * 2));
439
440 __raw_writel(con, base + 0x00);
441
442 samsung_gpio_unlock(ourchip, flags);
443 return 0;
444 }
445
446 static int samsung_gpiolib_2bit_output(struct gpio_chip *chip,
447 unsigned offset, int value)
448 {
449 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
450 void __iomem *base = ourchip->base;
451 unsigned long flags;
452 unsigned long dat;
453 unsigned long con;
454
455 samsung_gpio_lock(ourchip, flags);
456
457 dat = __raw_readl(base + 0x04);
458 dat &= ~(1 << offset);
459 if (value)
460 dat |= 1 << offset;
461 __raw_writel(dat, base + 0x04);
462
463 con = __raw_readl(base + 0x00);
464 con &= ~(3 << (offset * 2));
465 con |= 1 << (offset * 2);
466
467 __raw_writel(con, base + 0x00);
468 __raw_writel(dat, base + 0x04);
469
470 samsung_gpio_unlock(ourchip, flags);
471 return 0;
472 }
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490 static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
491 unsigned int offset)
492 {
493 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
494 void __iomem *base = ourchip->base;
495 unsigned long con;
496
497 con = __raw_readl(base + GPIOCON_OFF);
498 if (ourchip->bitmap_gpio_int & BIT(offset))
499 con |= 0xf << con_4bit_shift(offset);
500 else
501 con &= ~(0xf << con_4bit_shift(offset));
502 __raw_writel(con, base + GPIOCON_OFF);
503
504 pr_debug("%s: %p: CON now %08lx\n", __func__, base, con);
505
506 return 0;
507 }
508
509 static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
510 unsigned int offset, int value)
511 {
512 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
513 void __iomem *base = ourchip->base;
514 unsigned long con;
515 unsigned long dat;
516
517 con = __raw_readl(base + GPIOCON_OFF);
518 con &= ~(0xf << con_4bit_shift(offset));
519 con |= 0x1 << con_4bit_shift(offset);
520
521 dat = __raw_readl(base + GPIODAT_OFF);
522
523 if (value)
524 dat |= 1 << offset;
525 else
526 dat &= ~(1 << offset);
527
528 __raw_writel(dat, base + GPIODAT_OFF);
529 __raw_writel(con, base + GPIOCON_OFF);
530 __raw_writel(dat, base + GPIODAT_OFF);
531
532 pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
533
534 return 0;
535 }
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559 static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
560 unsigned int offset)
561 {
562 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
563 void __iomem *base = ourchip->base;
564 void __iomem *regcon = base;
565 unsigned long con;
566
567 if (offset > 7)
568 offset -= 8;
569 else
570 regcon -= 4;
571
572 con = __raw_readl(regcon);
573 con &= ~(0xf << con_4bit_shift(offset));
574 __raw_writel(con, regcon);
575
576 pr_debug("%s: %p: CON %08lx\n", __func__, base, con);
577
578 return 0;
579 }
580
581 static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
582 unsigned int offset, int value)
583 {
584 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
585 void __iomem *base = ourchip->base;
586 void __iomem *regcon = base;
587 unsigned long con;
588 unsigned long dat;
589 unsigned con_offset = offset;
590
591 if (con_offset > 7)
592 con_offset -= 8;
593 else
594 regcon -= 4;
595
596 con = __raw_readl(regcon);
597 con &= ~(0xf << con_4bit_shift(con_offset));
598 con |= 0x1 << con_4bit_shift(con_offset);
599
600 dat = __raw_readl(base + GPIODAT_OFF);
601
602 if (value)
603 dat |= 1 << offset;
604 else
605 dat &= ~(1 << offset);
606
607 __raw_writel(dat, base + GPIODAT_OFF);
608 __raw_writel(con, regcon);
609 __raw_writel(dat, base + GPIODAT_OFF);
610
611 pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
612
613 return 0;
614 }
615
616 #ifdef CONFIG_PLAT_S3C24XX
617
618
619 static int s3c24xx_gpiolib_banka_input(struct gpio_chip *chip, unsigned offset)
620 {
621 return -EINVAL;
622 }
623
624 static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip,
625 unsigned offset, int value)
626 {
627 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
628 void __iomem *base = ourchip->base;
629 unsigned long flags;
630 unsigned long dat;
631 unsigned long con;
632
633 local_irq_save(flags);
634
635 con = __raw_readl(base + 0x00);
636 dat = __raw_readl(base + 0x04);
637
638 dat &= ~(1 << offset);
639 if (value)
640 dat |= 1 << offset;
641
642 __raw_writel(dat, base + 0x04);
643
644 con &= ~(1 << offset);
645
646 __raw_writel(con, base + 0x00);
647 __raw_writel(dat, base + 0x04);
648
649 local_irq_restore(flags);
650 return 0;
651 }
652 #endif
653
654 static void samsung_gpiolib_set(struct gpio_chip *chip,
655 unsigned offset, int value)
656 {
657 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
658 void __iomem *base = ourchip->base;
659 unsigned long flags;
660 unsigned long dat;
661
662 samsung_gpio_lock(ourchip, flags);
663
664 dat = __raw_readl(base + 0x04);
665 dat &= ~(1 << offset);
666 if (value)
667 dat |= 1 << offset;
668 __raw_writel(dat, base + 0x04);
669
670 samsung_gpio_unlock(ourchip, flags);
671 }
672
673 static int samsung_gpiolib_get(struct gpio_chip *chip, unsigned offset)
674 {
675 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
676 unsigned long val;
677
678 val = __raw_readl(ourchip->base + 0x04);
679 val >>= offset;
680 val &= 1;
681
682 return val;
683 }
684
685
686
687
688
689
690
691
692
693
694
695
696
697 #ifdef CONFIG_S3C_GPIO_TRACK
698 struct samsung_gpio_chip *s3c_gpios[S3C_GPIO_END];
699
700 static __init void s3c_gpiolib_track(struct samsung_gpio_chip *chip)
701 {
702 unsigned int gpn;
703 int i;
704
705 gpn = chip->chip.base;
706 for (i = 0; i < chip->chip.ngpio; i++, gpn++) {
707 BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios));
708 s3c_gpios[gpn] = chip;
709 }
710 }
711 #endif
712
713
714
715
716
717
718
719
720
721
722
723 static void __init samsung_gpiolib_add(struct samsung_gpio_chip *chip)
724 {
725 struct gpio_chip *gc = &chip->chip;
726 int ret;
727
728 BUG_ON(!chip->base);
729 BUG_ON(!gc->label);
730 BUG_ON(!gc->ngpio);
731
732 spin_lock_init(&chip->lock);
733
734 if (!gc->direction_input)
735 gc->direction_input = samsung_gpiolib_2bit_input;
736 if (!gc->direction_output)
737 gc->direction_output = samsung_gpiolib_2bit_output;
738 if (!gc->set)
739 gc->set = samsung_gpiolib_set;
740 if (!gc->get)
741 gc->get = samsung_gpiolib_get;
742
743 #ifdef CONFIG_PM
744 if (chip->pm != NULL) {
745 if (!chip->pm->save || !chip->pm->resume)
746 pr_err("gpio: %s has missing PM functions\n",
747 gc->label);
748 } else
749 pr_err("gpio: %s has no PM function\n", gc->label);
750 #endif
751
752
753 ret = gpiochip_add_data(gc, chip);
754 if (ret >= 0)
755 s3c_gpiolib_track(chip);
756 }
757
758 static void __init s3c24xx_gpiolib_add_chips(struct samsung_gpio_chip *chip,
759 int nr_chips, void __iomem *base)
760 {
761 int i;
762 struct gpio_chip *gc = &chip->chip;
763
764 for (i = 0 ; i < nr_chips; i++, chip++) {
765
766 if (chip->chip.base >= S3C_GPIO_END)
767 continue;
768
769 if (!chip->config)
770 chip->config = &s3c24xx_gpiocfg_default;
771 if (!chip->pm)
772 chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
773 if ((base != NULL) && (chip->base == NULL))
774 chip->base = base + ((i) * 0x10);
775
776 if (!gc->direction_input)
777 gc->direction_input = samsung_gpiolib_2bit_input;
778 if (!gc->direction_output)
779 gc->direction_output = samsung_gpiolib_2bit_output;
780
781 samsung_gpiolib_add(chip);
782 }
783 }
784
785 static void __init samsung_gpiolib_add_2bit_chips(struct samsung_gpio_chip *chip,
786 int nr_chips, void __iomem *base,
787 unsigned int offset)
788 {
789 int i;
790
791 for (i = 0 ; i < nr_chips; i++, chip++) {
792 chip->chip.direction_input = samsung_gpiolib_2bit_input;
793 chip->chip.direction_output = samsung_gpiolib_2bit_output;
794
795 if (!chip->config)
796 chip->config = &samsung_gpio_cfgs[7];
797 if (!chip->pm)
798 chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
799 if ((base != NULL) && (chip->base == NULL))
800 chip->base = base + ((i) * offset);
801
802 samsung_gpiolib_add(chip);
803 }
804 }
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822 static void __init samsung_gpiolib_add_4bit_chips(struct samsung_gpio_chip *chip,
823 int nr_chips, void __iomem *base)
824 {
825 int i;
826
827 for (i = 0 ; i < nr_chips; i++, chip++) {
828 chip->chip.direction_input = samsung_gpiolib_4bit_input;
829 chip->chip.direction_output = samsung_gpiolib_4bit_output;
830
831 if (!chip->config)
832 chip->config = &samsung_gpio_cfgs[2];
833 if (!chip->pm)
834 chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
835 if ((base != NULL) && (chip->base == NULL))
836 chip->base = base + ((i) * 0x20);
837
838 chip->bitmap_gpio_int = 0;
839
840 samsung_gpiolib_add(chip);
841 }
842 }
843
844 static void __init samsung_gpiolib_add_4bit2_chips(struct samsung_gpio_chip *chip,
845 int nr_chips)
846 {
847 for (; nr_chips > 0; nr_chips--, chip++) {
848 chip->chip.direction_input = samsung_gpiolib_4bit2_input;
849 chip->chip.direction_output = samsung_gpiolib_4bit2_output;
850
851 if (!chip->config)
852 chip->config = &samsung_gpio_cfgs[2];
853 if (!chip->pm)
854 chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
855
856 samsung_gpiolib_add(chip);
857 }
858 }
859
860 int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
861 {
862 struct samsung_gpio_chip *samsung_chip = gpiochip_get_data(chip);
863
864 return samsung_chip->irq_base + offset;
865 }
866
867 #ifdef CONFIG_PLAT_S3C24XX
868 static int s3c24xx_gpiolib_fbank_to_irq(struct gpio_chip *chip, unsigned offset)
869 {
870 if (offset < 4) {
871 if (soc_is_s3c2412())
872 return IRQ_EINT0_2412 + offset;
873 else
874 return IRQ_EINT0 + offset;
875 }
876
877 if (offset < 8)
878 return IRQ_EINT4 + offset - 4;
879
880 return -EINVAL;
881 }
882 #endif
883
884 #ifdef CONFIG_ARCH_S3C64XX
885 static int s3c64xx_gpiolib_mbank_to_irq(struct gpio_chip *chip, unsigned pin)
886 {
887 return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO;
888 }
889
890 static int s3c64xx_gpiolib_lbank_to_irq(struct gpio_chip *chip, unsigned pin)
891 {
892 return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO;
893 }
894 #endif
895
896 struct samsung_gpio_chip s3c24xx_gpios[] = {
897 #ifdef CONFIG_PLAT_S3C24XX
898 {
899 .config = &s3c24xx_gpiocfg_banka,
900 .chip = {
901 .base = S3C2410_GPA(0),
902 .owner = THIS_MODULE,
903 .label = "GPIOA",
904 .ngpio = 27,
905 .direction_input = s3c24xx_gpiolib_banka_input,
906 .direction_output = s3c24xx_gpiolib_banka_output,
907 },
908 }, {
909 .chip = {
910 .base = S3C2410_GPB(0),
911 .owner = THIS_MODULE,
912 .label = "GPIOB",
913 .ngpio = 11,
914 },
915 }, {
916 .chip = {
917 .base = S3C2410_GPC(0),
918 .owner = THIS_MODULE,
919 .label = "GPIOC",
920 .ngpio = 16,
921 },
922 }, {
923 .chip = {
924 .base = S3C2410_GPD(0),
925 .owner = THIS_MODULE,
926 .label = "GPIOD",
927 .ngpio = 16,
928 },
929 }, {
930 .chip = {
931 .base = S3C2410_GPE(0),
932 .label = "GPIOE",
933 .owner = THIS_MODULE,
934 .ngpio = 16,
935 },
936 }, {
937 .chip = {
938 .base = S3C2410_GPF(0),
939 .owner = THIS_MODULE,
940 .label = "GPIOF",
941 .ngpio = 8,
942 .to_irq = s3c24xx_gpiolib_fbank_to_irq,
943 },
944 }, {
945 .irq_base = IRQ_EINT8,
946 .chip = {
947 .base = S3C2410_GPG(0),
948 .owner = THIS_MODULE,
949 .label = "GPIOG",
950 .ngpio = 16,
951 .to_irq = samsung_gpiolib_to_irq,
952 },
953 }, {
954 .chip = {
955 .base = S3C2410_GPH(0),
956 .owner = THIS_MODULE,
957 .label = "GPIOH",
958 .ngpio = 15,
959 },
960 },
961
962 {
963 .base = S3C2440_GPJCON,
964 .chip = {
965 .base = S3C2410_GPJ(0),
966 .owner = THIS_MODULE,
967 .label = "GPIOJ",
968 .ngpio = 16,
969 },
970 }, {
971 .base = S3C2443_GPKCON,
972 .chip = {
973 .base = S3C2410_GPK(0),
974 .owner = THIS_MODULE,
975 .label = "GPIOK",
976 .ngpio = 16,
977 },
978 }, {
979 .base = S3C2443_GPLCON,
980 .chip = {
981 .base = S3C2410_GPL(0),
982 .owner = THIS_MODULE,
983 .label = "GPIOL",
984 .ngpio = 15,
985 },
986 }, {
987 .base = S3C2443_GPMCON,
988 .chip = {
989 .base = S3C2410_GPM(0),
990 .owner = THIS_MODULE,
991 .label = "GPIOM",
992 .ngpio = 2,
993 },
994 },
995 #endif
996 };
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024 static struct samsung_gpio_chip s3c64xx_gpios_4bit[] = {
1025 #ifdef CONFIG_ARCH_S3C64XX
1026 {
1027 .chip = {
1028 .base = S3C64XX_GPA(0),
1029 .ngpio = S3C64XX_GPIO_A_NR,
1030 .label = "GPA",
1031 },
1032 }, {
1033 .chip = {
1034 .base = S3C64XX_GPB(0),
1035 .ngpio = S3C64XX_GPIO_B_NR,
1036 .label = "GPB",
1037 },
1038 }, {
1039 .chip = {
1040 .base = S3C64XX_GPC(0),
1041 .ngpio = S3C64XX_GPIO_C_NR,
1042 .label = "GPC",
1043 },
1044 }, {
1045 .chip = {
1046 .base = S3C64XX_GPD(0),
1047 .ngpio = S3C64XX_GPIO_D_NR,
1048 .label = "GPD",
1049 },
1050 }, {
1051 .config = &samsung_gpio_cfgs[0],
1052 .chip = {
1053 .base = S3C64XX_GPE(0),
1054 .ngpio = S3C64XX_GPIO_E_NR,
1055 .label = "GPE",
1056 },
1057 }, {
1058 .base = S3C64XX_GPG_BASE,
1059 .chip = {
1060 .base = S3C64XX_GPG(0),
1061 .ngpio = S3C64XX_GPIO_G_NR,
1062 .label = "GPG",
1063 },
1064 }, {
1065 .base = S3C64XX_GPM_BASE,
1066 .config = &samsung_gpio_cfgs[1],
1067 .chip = {
1068 .base = S3C64XX_GPM(0),
1069 .ngpio = S3C64XX_GPIO_M_NR,
1070 .label = "GPM",
1071 .to_irq = s3c64xx_gpiolib_mbank_to_irq,
1072 },
1073 },
1074 #endif
1075 };
1076
1077 static struct samsung_gpio_chip s3c64xx_gpios_4bit2[] = {
1078 #ifdef CONFIG_ARCH_S3C64XX
1079 {
1080 .base = S3C64XX_GPH_BASE + 0x4,
1081 .chip = {
1082 .base = S3C64XX_GPH(0),
1083 .ngpio = S3C64XX_GPIO_H_NR,
1084 .label = "GPH",
1085 },
1086 }, {
1087 .base = S3C64XX_GPK_BASE + 0x4,
1088 .config = &samsung_gpio_cfgs[0],
1089 .chip = {
1090 .base = S3C64XX_GPK(0),
1091 .ngpio = S3C64XX_GPIO_K_NR,
1092 .label = "GPK",
1093 },
1094 }, {
1095 .base = S3C64XX_GPL_BASE + 0x4,
1096 .config = &samsung_gpio_cfgs[1],
1097 .chip = {
1098 .base = S3C64XX_GPL(0),
1099 .ngpio = S3C64XX_GPIO_L_NR,
1100 .label = "GPL",
1101 .to_irq = s3c64xx_gpiolib_lbank_to_irq,
1102 },
1103 },
1104 #endif
1105 };
1106
1107 static struct samsung_gpio_chip s3c64xx_gpios_2bit[] = {
1108 #ifdef CONFIG_ARCH_S3C64XX
1109 {
1110 .base = S3C64XX_GPF_BASE,
1111 .config = &samsung_gpio_cfgs[6],
1112 .chip = {
1113 .base = S3C64XX_GPF(0),
1114 .ngpio = S3C64XX_GPIO_F_NR,
1115 .label = "GPF",
1116 },
1117 }, {
1118 .config = &samsung_gpio_cfgs[7],
1119 .chip = {
1120 .base = S3C64XX_GPI(0),
1121 .ngpio = S3C64XX_GPIO_I_NR,
1122 .label = "GPI",
1123 },
1124 }, {
1125 .config = &samsung_gpio_cfgs[7],
1126 .chip = {
1127 .base = S3C64XX_GPJ(0),
1128 .ngpio = S3C64XX_GPIO_J_NR,
1129 .label = "GPJ",
1130 },
1131 }, {
1132 .config = &samsung_gpio_cfgs[6],
1133 .chip = {
1134 .base = S3C64XX_GPO(0),
1135 .ngpio = S3C64XX_GPIO_O_NR,
1136 .label = "GPO",
1137 },
1138 }, {
1139 .config = &samsung_gpio_cfgs[6],
1140 .chip = {
1141 .base = S3C64XX_GPP(0),
1142 .ngpio = S3C64XX_GPIO_P_NR,
1143 .label = "GPP",
1144 },
1145 }, {
1146 .config = &samsung_gpio_cfgs[6],
1147 .chip = {
1148 .base = S3C64XX_GPQ(0),
1149 .ngpio = S3C64XX_GPIO_Q_NR,
1150 .label = "GPQ",
1151 },
1152 }, {
1153 .base = S3C64XX_GPN_BASE,
1154 .irq_base = IRQ_EINT(0),
1155 .config = &samsung_gpio_cfgs[5],
1156 .chip = {
1157 .base = S3C64XX_GPN(0),
1158 .ngpio = S3C64XX_GPIO_N_NR,
1159 .label = "GPN",
1160 .to_irq = samsung_gpiolib_to_irq,
1161 },
1162 },
1163 #endif
1164 };
1165
1166
1167 static __init int samsung_gpiolib_init(void)
1168 {
1169
1170
1171
1172
1173
1174
1175 if (of_have_populated_dt())
1176 return 0;
1177
1178 if (soc_is_s3c24xx()) {
1179 samsung_gpiolib_set_cfg(samsung_gpio_cfgs,
1180 ARRAY_SIZE(samsung_gpio_cfgs));
1181 s3c24xx_gpiolib_add_chips(s3c24xx_gpios,
1182 ARRAY_SIZE(s3c24xx_gpios), S3C24XX_VA_GPIO);
1183 } else if (soc_is_s3c64xx()) {
1184 samsung_gpiolib_set_cfg(samsung_gpio_cfgs,
1185 ARRAY_SIZE(samsung_gpio_cfgs));
1186 samsung_gpiolib_add_2bit_chips(s3c64xx_gpios_2bit,
1187 ARRAY_SIZE(s3c64xx_gpios_2bit),
1188 S3C64XX_VA_GPIO + 0xE0, 0x20);
1189 samsung_gpiolib_add_4bit_chips(s3c64xx_gpios_4bit,
1190 ARRAY_SIZE(s3c64xx_gpios_4bit),
1191 S3C64XX_VA_GPIO);
1192 samsung_gpiolib_add_4bit2_chips(s3c64xx_gpios_4bit2,
1193 ARRAY_SIZE(s3c64xx_gpios_4bit2));
1194 }
1195
1196 return 0;
1197 }
1198 core_initcall(samsung_gpiolib_init);
1199
1200 int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
1201 {
1202 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
1203 unsigned long flags;
1204 int offset;
1205 int ret;
1206
1207 if (!chip)
1208 return -EINVAL;
1209
1210 offset = pin - chip->chip.base;
1211
1212 samsung_gpio_lock(chip, flags);
1213 ret = samsung_gpio_do_setcfg(chip, offset, config);
1214 samsung_gpio_unlock(chip, flags);
1215
1216 return ret;
1217 }
1218 EXPORT_SYMBOL(s3c_gpio_cfgpin);
1219
1220 int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
1221 unsigned int cfg)
1222 {
1223 int ret;
1224
1225 for (; nr > 0; nr--, start++) {
1226 ret = s3c_gpio_cfgpin(start, cfg);
1227 if (ret != 0)
1228 return ret;
1229 }
1230
1231 return 0;
1232 }
1233 EXPORT_SYMBOL_GPL(s3c_gpio_cfgpin_range);
1234
1235 int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
1236 unsigned int cfg, samsung_gpio_pull_t pull)
1237 {
1238 int ret;
1239
1240 for (; nr > 0; nr--, start++) {
1241 s3c_gpio_setpull(start, pull);
1242 ret = s3c_gpio_cfgpin(start, cfg);
1243 if (ret != 0)
1244 return ret;
1245 }
1246
1247 return 0;
1248 }
1249 EXPORT_SYMBOL_GPL(s3c_gpio_cfgall_range);
1250
1251 unsigned s3c_gpio_getcfg(unsigned int pin)
1252 {
1253 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
1254 unsigned long flags;
1255 unsigned ret = 0;
1256 int offset;
1257
1258 if (chip) {
1259 offset = pin - chip->chip.base;
1260
1261 samsung_gpio_lock(chip, flags);
1262 ret = samsung_gpio_do_getcfg(chip, offset);
1263 samsung_gpio_unlock(chip, flags);
1264 }
1265
1266 return ret;
1267 }
1268 EXPORT_SYMBOL(s3c_gpio_getcfg);
1269
1270 int s3c_gpio_setpull(unsigned int pin, samsung_gpio_pull_t pull)
1271 {
1272 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
1273 unsigned long flags;
1274 int offset, ret;
1275
1276 if (!chip)
1277 return -EINVAL;
1278
1279 offset = pin - chip->chip.base;
1280
1281 samsung_gpio_lock(chip, flags);
1282 ret = samsung_gpio_do_setpull(chip, offset, pull);
1283 samsung_gpio_unlock(chip, flags);
1284
1285 return ret;
1286 }
1287 EXPORT_SYMBOL(s3c_gpio_setpull);
1288
1289 samsung_gpio_pull_t s3c_gpio_getpull(unsigned int pin)
1290 {
1291 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
1292 unsigned long flags;
1293 int offset;
1294 u32 pup = 0;
1295
1296 if (chip) {
1297 offset = pin - chip->chip.base;
1298
1299 samsung_gpio_lock(chip, flags);
1300 pup = samsung_gpio_do_getpull(chip, offset);
1301 samsung_gpio_unlock(chip, flags);
1302 }
1303
1304 return (__force samsung_gpio_pull_t)pup;
1305 }
1306 EXPORT_SYMBOL(s3c_gpio_getpull);
1307
1308 #ifdef CONFIG_PLAT_S3C24XX
1309 unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
1310 {
1311 unsigned long flags;
1312 unsigned long misccr;
1313
1314 local_irq_save(flags);
1315 misccr = __raw_readl(S3C24XX_MISCCR);
1316 misccr &= ~clear;
1317 misccr ^= change;
1318 __raw_writel(misccr, S3C24XX_MISCCR);
1319 local_irq_restore(flags);
1320
1321 return misccr;
1322 }
1323 EXPORT_SYMBOL(s3c2410_modify_misccr);
1324 #endif