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
896#if defined(CONFIG_PLAT_S3C24XX) && defined(CONFIG_OF)
897static int s3c24xx_gpio_xlate(struct gpio_chip *gc,
898 const struct of_phandle_args *gpiospec, u32 *flags)
899{
900 unsigned int pin;
901
902 if (WARN_ON(gc->of_gpio_n_cells < 3))
903 return -EINVAL;
904
905 if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells))
906 return -EINVAL;
907
908 if (gpiospec->args[0] > gc->ngpio)
909 return -EINVAL;
910
911 pin = gc->base + gpiospec->args[0];
912
913 if (s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(gpiospec->args[1])))
914 pr_warn("gpio_xlate: failed to set pin function\n");
915 if (s3c_gpio_setpull(pin, gpiospec->args[2] & 0xffff))
916 pr_warn("gpio_xlate: failed to set pin pull up/down\n");
917
918 if (flags)
919 *flags = gpiospec->args[2] >> 16;
920
921 return gpiospec->args[0];
922}
923
924static const struct of_device_id s3c24xx_gpio_dt_match[] __initdata = {
925 { .compatible = "samsung,s3c24xx-gpio", },
926 {}
927};
928
929static __init void s3c24xx_gpiolib_attach_ofnode(struct samsung_gpio_chip *chip,
930 u64 base, u64 offset)
931{
932 struct gpio_chip *gc = &chip->chip;
933 u64 address;
934
935 if (!of_have_populated_dt())
936 return;
937
938 address = chip->base ? base + ((u32)chip->base & 0xfff) : base + offset;
939 gc->of_node = of_find_matching_node_by_address(NULL,
940 s3c24xx_gpio_dt_match, address);
941 if (!gc->of_node) {
942 pr_info("gpio: device tree node not found for gpio controller"
943 " with base address %08llx\n", address);
944 return;
945 }
946 gc->of_gpio_n_cells = 3;
947 gc->of_xlate = s3c24xx_gpio_xlate;
948}
949#else
950static __init void s3c24xx_gpiolib_attach_ofnode(struct samsung_gpio_chip *chip,
951 u64 base, u64 offset)
952{
953 return;
954}
955#endif
956
957static void __init s3c24xx_gpiolib_add_chips(struct samsung_gpio_chip *chip,
958 int nr_chips, void __iomem *base)
959{
960 int i;
961 struct gpio_chip *gc = &chip->chip;
962
963 for (i = 0 ; i < nr_chips; i++, chip++) {
964
965 if (chip->chip.base >= S3C_GPIO_END)
966 continue;
967
968 if (!chip->config)
969 chip->config = &s3c24xx_gpiocfg_default;
970 if (!chip->pm)
971 chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
972 if ((base != NULL) && (chip->base == NULL))
973 chip->base = base + ((i) * 0x10);
974
975 if (!gc->direction_input)
976 gc->direction_input = samsung_gpiolib_2bit_input;
977 if (!gc->direction_output)
978 gc->direction_output = samsung_gpiolib_2bit_output;
979
980 samsung_gpiolib_add(chip);
981
982 s3c24xx_gpiolib_attach_ofnode(chip, S3C24XX_PA_GPIO, i * 0x10);
983 }
984}
985
986static void __init samsung_gpiolib_add_2bit_chips(struct samsung_gpio_chip *chip,
987 int nr_chips, void __iomem *base,
988 unsigned int offset)
989{
990 int i;
991
992 for (i = 0 ; i < nr_chips; i++, chip++) {
993 chip->chip.direction_input = samsung_gpiolib_2bit_input;
994 chip->chip.direction_output = samsung_gpiolib_2bit_output;
995
996 if (!chip->config)
997 chip->config = &samsung_gpio_cfgs[7];
998 if (!chip->pm)
999 chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
1000 if ((base != NULL) && (chip->base == NULL))
1001 chip->base = base + ((i) * offset);
1002
1003 samsung_gpiolib_add(chip);
1004 }
1005}
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023static void __init samsung_gpiolib_add_4bit_chips(struct samsung_gpio_chip *chip,
1024 int nr_chips, void __iomem *base)
1025{
1026 int i;
1027
1028 for (i = 0 ; i < nr_chips; i++, chip++) {
1029 chip->chip.direction_input = samsung_gpiolib_4bit_input;
1030 chip->chip.direction_output = samsung_gpiolib_4bit_output;
1031
1032 if (!chip->config)
1033 chip->config = &samsung_gpio_cfgs[2];
1034 if (!chip->pm)
1035 chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
1036 if ((base != NULL) && (chip->base == NULL))
1037 chip->base = base + ((i) * 0x20);
1038
1039 chip->bitmap_gpio_int = 0;
1040
1041 samsung_gpiolib_add(chip);
1042 }
1043}
1044
1045static void __init samsung_gpiolib_add_4bit2_chips(struct samsung_gpio_chip *chip,
1046 int nr_chips)
1047{
1048 for (; nr_chips > 0; nr_chips--, chip++) {
1049 chip->chip.direction_input = samsung_gpiolib_4bit2_input;
1050 chip->chip.direction_output = samsung_gpiolib_4bit2_output;
1051
1052 if (!chip->config)
1053 chip->config = &samsung_gpio_cfgs[2];
1054 if (!chip->pm)
1055 chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
1056
1057 samsung_gpiolib_add(chip);
1058 }
1059}
1060
1061static void __init s5p64x0_gpiolib_add_rbank(struct samsung_gpio_chip *chip,
1062 int nr_chips)
1063{
1064 for (; nr_chips > 0; nr_chips--, chip++) {
1065 chip->chip.direction_input = s5p64x0_gpiolib_rbank_input;
1066 chip->chip.direction_output = s5p64x0_gpiolib_rbank_output;
1067
1068 if (!chip->pm)
1069 chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
1070
1071 samsung_gpiolib_add(chip);
1072 }
1073}
1074
1075int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
1076{
1077 struct samsung_gpio_chip *samsung_chip = container_of(chip, struct samsung_gpio_chip, chip);
1078
1079 return samsung_chip->irq_base + offset;
1080}
1081
1082#ifdef CONFIG_PLAT_S3C24XX
1083static int s3c24xx_gpiolib_fbank_to_irq(struct gpio_chip *chip, unsigned offset)
1084{
1085 if (offset < 4) {
1086 if (soc_is_s3c2412())
1087 return IRQ_EINT0_2412 + offset;
1088 else
1089 return IRQ_EINT0 + offset;
1090 }
1091
1092 if (offset < 8)
1093 return IRQ_EINT4 + offset - 4;
1094
1095 return -EINVAL;
1096}
1097#endif
1098
1099#ifdef CONFIG_ARCH_S3C64XX
1100static int s3c64xx_gpiolib_mbank_to_irq(struct gpio_chip *chip, unsigned pin)
1101{
1102 return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO;
1103}
1104
1105static int s3c64xx_gpiolib_lbank_to_irq(struct gpio_chip *chip, unsigned pin)
1106{
1107 return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO;
1108}
1109#endif
1110
1111struct samsung_gpio_chip s3c24xx_gpios[] = {
1112#ifdef CONFIG_PLAT_S3C24XX
1113 {
1114 .config = &s3c24xx_gpiocfg_banka,
1115 .chip = {
1116 .base = S3C2410_GPA(0),
1117 .owner = THIS_MODULE,
1118 .label = "GPIOA",
1119 .ngpio = 24,
1120 .direction_input = s3c24xx_gpiolib_banka_input,
1121 .direction_output = s3c24xx_gpiolib_banka_output,
1122 },
1123 }, {
1124 .chip = {
1125 .base = S3C2410_GPB(0),
1126 .owner = THIS_MODULE,
1127 .label = "GPIOB",
1128 .ngpio = 16,
1129 },
1130 }, {
1131 .chip = {
1132 .base = S3C2410_GPC(0),
1133 .owner = THIS_MODULE,
1134 .label = "GPIOC",
1135 .ngpio = 16,
1136 },
1137 }, {
1138 .chip = {
1139 .base = S3C2410_GPD(0),
1140 .owner = THIS_MODULE,
1141 .label = "GPIOD",
1142 .ngpio = 16,
1143 },
1144 }, {
1145 .chip = {
1146 .base = S3C2410_GPE(0),
1147 .label = "GPIOE",
1148 .owner = THIS_MODULE,
1149 .ngpio = 16,
1150 },
1151 }, {
1152 .chip = {
1153 .base = S3C2410_GPF(0),
1154 .owner = THIS_MODULE,
1155 .label = "GPIOF",
1156 .ngpio = 8,
1157 .to_irq = s3c24xx_gpiolib_fbank_to_irq,
1158 },
1159 }, {
1160 .irq_base = IRQ_EINT8,
1161 .chip = {
1162 .base = S3C2410_GPG(0),
1163 .owner = THIS_MODULE,
1164 .label = "GPIOG",
1165 .ngpio = 16,
1166 .to_irq = samsung_gpiolib_to_irq,
1167 },
1168 }, {
1169 .chip = {
1170 .base = S3C2410_GPH(0),
1171 .owner = THIS_MODULE,
1172 .label = "GPIOH",
1173 .ngpio = 11,
1174 },
1175 },
1176
1177 {
1178 .base = S3C2440_GPJCON,
1179 .chip = {
1180 .base = S3C2410_GPJ(0),
1181 .owner = THIS_MODULE,
1182 .label = "GPIOJ",
1183 .ngpio = 16,
1184 },
1185 }, {
1186 .base = S3C2443_GPKCON,
1187 .chip = {
1188 .base = S3C2410_GPK(0),
1189 .owner = THIS_MODULE,
1190 .label = "GPIOK",
1191 .ngpio = 16,
1192 },
1193 }, {
1194 .base = S3C2443_GPLCON,
1195 .chip = {
1196 .base = S3C2410_GPL(0),
1197 .owner = THIS_MODULE,
1198 .label = "GPIOL",
1199 .ngpio = 15,
1200 },
1201 }, {
1202 .base = S3C2443_GPMCON,
1203 .chip = {
1204 .base = S3C2410_GPM(0),
1205 .owner = THIS_MODULE,
1206 .label = "GPIOM",
1207 .ngpio = 2,
1208 },
1209 },
1210#endif
1211};
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239static struct samsung_gpio_chip s3c64xx_gpios_4bit[] = {
1240#ifdef CONFIG_ARCH_S3C64XX
1241 {
1242 .chip = {
1243 .base = S3C64XX_GPA(0),
1244 .ngpio = S3C64XX_GPIO_A_NR,
1245 .label = "GPA",
1246 },
1247 }, {
1248 .chip = {
1249 .base = S3C64XX_GPB(0),
1250 .ngpio = S3C64XX_GPIO_B_NR,
1251 .label = "GPB",
1252 },
1253 }, {
1254 .chip = {
1255 .base = S3C64XX_GPC(0),
1256 .ngpio = S3C64XX_GPIO_C_NR,
1257 .label = "GPC",
1258 },
1259 }, {
1260 .chip = {
1261 .base = S3C64XX_GPD(0),
1262 .ngpio = S3C64XX_GPIO_D_NR,
1263 .label = "GPD",
1264 },
1265 }, {
1266 .config = &samsung_gpio_cfgs[0],
1267 .chip = {
1268 .base = S3C64XX_GPE(0),
1269 .ngpio = S3C64XX_GPIO_E_NR,
1270 .label = "GPE",
1271 },
1272 }, {
1273 .base = S3C64XX_GPG_BASE,
1274 .chip = {
1275 .base = S3C64XX_GPG(0),
1276 .ngpio = S3C64XX_GPIO_G_NR,
1277 .label = "GPG",
1278 },
1279 }, {
1280 .base = S3C64XX_GPM_BASE,
1281 .config = &samsung_gpio_cfgs[1],
1282 .chip = {
1283 .base = S3C64XX_GPM(0),
1284 .ngpio = S3C64XX_GPIO_M_NR,
1285 .label = "GPM",
1286 .to_irq = s3c64xx_gpiolib_mbank_to_irq,
1287 },
1288 },
1289#endif
1290};
1291
1292static struct samsung_gpio_chip s3c64xx_gpios_4bit2[] = {
1293#ifdef CONFIG_ARCH_S3C64XX
1294 {
1295 .base = S3C64XX_GPH_BASE + 0x4,
1296 .chip = {
1297 .base = S3C64XX_GPH(0),
1298 .ngpio = S3C64XX_GPIO_H_NR,
1299 .label = "GPH",
1300 },
1301 }, {
1302 .base = S3C64XX_GPK_BASE + 0x4,
1303 .config = &samsung_gpio_cfgs[0],
1304 .chip = {
1305 .base = S3C64XX_GPK(0),
1306 .ngpio = S3C64XX_GPIO_K_NR,
1307 .label = "GPK",
1308 },
1309 }, {
1310 .base = S3C64XX_GPL_BASE + 0x4,
1311 .config = &samsung_gpio_cfgs[1],
1312 .chip = {
1313 .base = S3C64XX_GPL(0),
1314 .ngpio = S3C64XX_GPIO_L_NR,
1315 .label = "GPL",
1316 .to_irq = s3c64xx_gpiolib_lbank_to_irq,
1317 },
1318 },
1319#endif
1320};
1321
1322static struct samsung_gpio_chip s3c64xx_gpios_2bit[] = {
1323#ifdef CONFIG_ARCH_S3C64XX
1324 {
1325 .base = S3C64XX_GPF_BASE,
1326 .config = &samsung_gpio_cfgs[6],
1327 .chip = {
1328 .base = S3C64XX_GPF(0),
1329 .ngpio = S3C64XX_GPIO_F_NR,
1330 .label = "GPF",
1331 },
1332 }, {
1333 .config = &samsung_gpio_cfgs[7],
1334 .chip = {
1335 .base = S3C64XX_GPI(0),
1336 .ngpio = S3C64XX_GPIO_I_NR,
1337 .label = "GPI",
1338 },
1339 }, {
1340 .config = &samsung_gpio_cfgs[7],
1341 .chip = {
1342 .base = S3C64XX_GPJ(0),
1343 .ngpio = S3C64XX_GPIO_J_NR,
1344 .label = "GPJ",
1345 },
1346 }, {
1347 .config = &samsung_gpio_cfgs[6],
1348 .chip = {
1349 .base = S3C64XX_GPO(0),
1350 .ngpio = S3C64XX_GPIO_O_NR,
1351 .label = "GPO",
1352 },
1353 }, {
1354 .config = &samsung_gpio_cfgs[6],
1355 .chip = {
1356 .base = S3C64XX_GPP(0),
1357 .ngpio = S3C64XX_GPIO_P_NR,
1358 .label = "GPP",
1359 },
1360 }, {
1361 .config = &samsung_gpio_cfgs[6],
1362 .chip = {
1363 .base = S3C64XX_GPQ(0),
1364 .ngpio = S3C64XX_GPIO_Q_NR,
1365 .label = "GPQ",
1366 },
1367 }, {
1368 .base = S3C64XX_GPN_BASE,
1369 .irq_base = IRQ_EINT(0),
1370 .config = &samsung_gpio_cfgs[5],
1371 .chip = {
1372 .base = S3C64XX_GPN(0),
1373 .ngpio = S3C64XX_GPIO_N_NR,
1374 .label = "GPN",
1375 .to_irq = samsung_gpiolib_to_irq,
1376 },
1377 },
1378#endif
1379};
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398static struct samsung_gpio_chip s5p6440_gpios_4bit[] = {
1399#ifdef CONFIG_CPU_S5P6440
1400 {
1401 .chip = {
1402 .base = S5P6440_GPA(0),
1403 .ngpio = S5P6440_GPIO_A_NR,
1404 .label = "GPA",
1405 },
1406 }, {
1407 .chip = {
1408 .base = S5P6440_GPB(0),
1409 .ngpio = S5P6440_GPIO_B_NR,
1410 .label = "GPB",
1411 },
1412 }, {
1413 .chip = {
1414 .base = S5P6440_GPC(0),
1415 .ngpio = S5P6440_GPIO_C_NR,
1416 .label = "GPC",
1417 },
1418 }, {
1419 .base = S5P64X0_GPG_BASE,
1420 .chip = {
1421 .base = S5P6440_GPG(0),
1422 .ngpio = S5P6440_GPIO_G_NR,
1423 .label = "GPG",
1424 },
1425 },
1426#endif
1427};
1428
1429static struct samsung_gpio_chip s5p6440_gpios_4bit2[] = {
1430#ifdef CONFIG_CPU_S5P6440
1431 {
1432 .base = S5P64X0_GPH_BASE + 0x4,
1433 .chip = {
1434 .base = S5P6440_GPH(0),
1435 .ngpio = S5P6440_GPIO_H_NR,
1436 .label = "GPH",
1437 },
1438 },
1439#endif
1440};
1441
1442static struct samsung_gpio_chip s5p6440_gpios_rbank[] = {
1443#ifdef CONFIG_CPU_S5P6440
1444 {
1445 .base = S5P64X0_GPR_BASE + 0x4,
1446 .config = &s5p64x0_gpio_cfg_rbank,
1447 .chip = {
1448 .base = S5P6440_GPR(0),
1449 .ngpio = S5P6440_GPIO_R_NR,
1450 .label = "GPR",
1451 },
1452 },
1453#endif
1454};
1455
1456static struct samsung_gpio_chip s5p6440_gpios_2bit[] = {
1457#ifdef CONFIG_CPU_S5P6440
1458 {
1459 .base = S5P64X0_GPF_BASE,
1460 .config = &samsung_gpio_cfgs[6],
1461 .chip = {
1462 .base = S5P6440_GPF(0),
1463 .ngpio = S5P6440_GPIO_F_NR,
1464 .label = "GPF",
1465 },
1466 }, {
1467 .base = S5P64X0_GPI_BASE,
1468 .config = &samsung_gpio_cfgs[4],
1469 .chip = {
1470 .base = S5P6440_GPI(0),
1471 .ngpio = S5P6440_GPIO_I_NR,
1472 .label = "GPI",
1473 },
1474 }, {
1475 .base = S5P64X0_GPJ_BASE,
1476 .config = &samsung_gpio_cfgs[4],
1477 .chip = {
1478 .base = S5P6440_GPJ(0),
1479 .ngpio = S5P6440_GPIO_J_NR,
1480 .label = "GPJ",
1481 },
1482 }, {
1483 .base = S5P64X0_GPN_BASE,
1484 .config = &samsung_gpio_cfgs[5],
1485 .chip = {
1486 .base = S5P6440_GPN(0),
1487 .ngpio = S5P6440_GPIO_N_NR,
1488 .label = "GPN",
1489 },
1490 }, {
1491 .base = S5P64X0_GPP_BASE,
1492 .config = &samsung_gpio_cfgs[6],
1493 .chip = {
1494 .base = S5P6440_GPP(0),
1495 .ngpio = S5P6440_GPIO_P_NR,
1496 .label = "GPP",
1497 },
1498 },
1499#endif
1500};
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526static struct samsung_gpio_chip s5p6450_gpios_4bit[] = {
1527#ifdef CONFIG_CPU_S5P6450
1528 {
1529 .chip = {
1530 .base = S5P6450_GPA(0),
1531 .ngpio = S5P6450_GPIO_A_NR,
1532 .label = "GPA",
1533 },
1534 }, {
1535 .chip = {
1536 .base = S5P6450_GPB(0),
1537 .ngpio = S5P6450_GPIO_B_NR,
1538 .label = "GPB",
1539 },
1540 }, {
1541 .chip = {
1542 .base = S5P6450_GPC(0),
1543 .ngpio = S5P6450_GPIO_C_NR,
1544 .label = "GPC",
1545 },
1546 }, {
1547 .chip = {
1548 .base = S5P6450_GPD(0),
1549 .ngpio = S5P6450_GPIO_D_NR,
1550 .label = "GPD",
1551 },
1552 }, {
1553 .base = S5P6450_GPK_BASE,
1554 .chip = {
1555 .base = S5P6450_GPK(0),
1556 .ngpio = S5P6450_GPIO_K_NR,
1557 .label = "GPK",
1558 },
1559 },
1560#endif
1561};
1562
1563static struct samsung_gpio_chip s5p6450_gpios_4bit2[] = {
1564#ifdef CONFIG_CPU_S5P6450
1565 {
1566 .base = S5P64X0_GPG_BASE + 0x4,
1567 .chip = {
1568 .base = S5P6450_GPG(0),
1569 .ngpio = S5P6450_GPIO_G_NR,
1570 .label = "GPG",
1571 },
1572 }, {
1573 .base = S5P64X0_GPH_BASE + 0x4,
1574 .chip = {
1575 .base = S5P6450_GPH(0),
1576 .ngpio = S5P6450_GPIO_H_NR,
1577 .label = "GPH",
1578 },
1579 },
1580#endif
1581};
1582
1583static struct samsung_gpio_chip s5p6450_gpios_rbank[] = {
1584#ifdef CONFIG_CPU_S5P6450
1585 {
1586 .base = S5P64X0_GPR_BASE + 0x4,
1587 .config = &s5p64x0_gpio_cfg_rbank,
1588 .chip = {
1589 .base = S5P6450_GPR(0),
1590 .ngpio = S5P6450_GPIO_R_NR,
1591 .label = "GPR",
1592 },
1593 },
1594#endif
1595};
1596
1597static struct samsung_gpio_chip s5p6450_gpios_2bit[] = {
1598#ifdef CONFIG_CPU_S5P6450
1599 {
1600 .base = S5P64X0_GPF_BASE,
1601 .config = &samsung_gpio_cfgs[6],
1602 .chip = {
1603 .base = S5P6450_GPF(0),
1604 .ngpio = S5P6450_GPIO_F_NR,
1605 .label = "GPF",
1606 },
1607 }, {
1608 .base = S5P64X0_GPI_BASE,
1609 .config = &samsung_gpio_cfgs[4],
1610 .chip = {
1611 .base = S5P6450_GPI(0),
1612 .ngpio = S5P6450_GPIO_I_NR,
1613 .label = "GPI",
1614 },
1615 }, {
1616 .base = S5P64X0_GPJ_BASE,
1617 .config = &samsung_gpio_cfgs[4],
1618 .chip = {
1619 .base = S5P6450_GPJ(0),
1620 .ngpio = S5P6450_GPIO_J_NR,
1621 .label = "GPJ",
1622 },
1623 }, {
1624 .base = S5P64X0_GPN_BASE,
1625 .config = &samsung_gpio_cfgs[5],
1626 .chip = {
1627 .base = S5P6450_GPN(0),
1628 .ngpio = S5P6450_GPIO_N_NR,
1629 .label = "GPN",
1630 },
1631 }, {
1632 .base = S5P64X0_GPP_BASE,
1633 .config = &samsung_gpio_cfgs[6],
1634 .chip = {
1635 .base = S5P6450_GPP(0),
1636 .ngpio = S5P6450_GPIO_P_NR,
1637 .label = "GPP",
1638 },
1639 }, {
1640 .base = S5P6450_GPQ_BASE,
1641 .config = &samsung_gpio_cfgs[5],
1642 .chip = {
1643 .base = S5P6450_GPQ(0),
1644 .ngpio = S5P6450_GPIO_Q_NR,
1645 .label = "GPQ",
1646 },
1647 }, {
1648 .base = S5P6450_GPS_BASE,
1649 .config = &samsung_gpio_cfgs[6],
1650 .chip = {
1651 .base = S5P6450_GPS(0),
1652 .ngpio = S5P6450_GPIO_S_NR,
1653 .label = "GPS",
1654 },
1655 },
1656#endif
1657};
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698static struct samsung_gpio_chip s5pc100_gpios_4bit[] = {
1699#ifdef CONFIG_CPU_S5PC100
1700 {
1701 .chip = {
1702 .base = S5PC100_GPA0(0),
1703 .ngpio = S5PC100_GPIO_A0_NR,
1704 .label = "GPA0",
1705 },
1706 }, {
1707 .chip = {
1708 .base = S5PC100_GPA1(0),
1709 .ngpio = S5PC100_GPIO_A1_NR,
1710 .label = "GPA1",
1711 },
1712 }, {
1713 .chip = {
1714 .base = S5PC100_GPB(0),
1715 .ngpio = S5PC100_GPIO_B_NR,
1716 .label = "GPB",
1717 },
1718 }, {
1719 .chip = {
1720 .base = S5PC100_GPC(0),
1721 .ngpio = S5PC100_GPIO_C_NR,
1722 .label = "GPC",
1723 },
1724 }, {
1725 .chip = {
1726 .base = S5PC100_GPD(0),
1727 .ngpio = S5PC100_GPIO_D_NR,
1728 .label = "GPD",
1729 },
1730 }, {
1731 .chip = {
1732 .base = S5PC100_GPE0(0),
1733 .ngpio = S5PC100_GPIO_E0_NR,
1734 .label = "GPE0",
1735 },
1736 }, {
1737 .chip = {
1738 .base = S5PC100_GPE1(0),
1739 .ngpio = S5PC100_GPIO_E1_NR,
1740 .label = "GPE1",
1741 },
1742 }, {
1743 .chip = {
1744 .base = S5PC100_GPF0(0),
1745 .ngpio = S5PC100_GPIO_F0_NR,
1746 .label = "GPF0",
1747 },
1748 }, {
1749 .chip = {
1750 .base = S5PC100_GPF1(0),
1751 .ngpio = S5PC100_GPIO_F1_NR,
1752 .label = "GPF1",
1753 },
1754 }, {
1755 .chip = {
1756 .base = S5PC100_GPF2(0),
1757 .ngpio = S5PC100_GPIO_F2_NR,
1758 .label = "GPF2",
1759 },
1760 }, {
1761 .chip = {
1762 .base = S5PC100_GPF3(0),
1763 .ngpio = S5PC100_GPIO_F3_NR,
1764 .label = "GPF3",
1765 },
1766 }, {
1767 .chip = {
1768 .base = S5PC100_GPG0(0),
1769 .ngpio = S5PC100_GPIO_G0_NR,
1770 .label = "GPG0",
1771 },
1772 }, {
1773 .chip = {
1774 .base = S5PC100_GPG1(0),
1775 .ngpio = S5PC100_GPIO_G1_NR,
1776 .label = "GPG1",
1777 },
1778 }, {
1779 .chip = {
1780 .base = S5PC100_GPG2(0),
1781 .ngpio = S5PC100_GPIO_G2_NR,
1782 .label = "GPG2",
1783 },
1784 }, {
1785 .chip = {
1786 .base = S5PC100_GPG3(0),
1787 .ngpio = S5PC100_GPIO_G3_NR,
1788 .label = "GPG3",
1789 },
1790 }, {
1791 .chip = {
1792 .base = S5PC100_GPI(0),
1793 .ngpio = S5PC100_GPIO_I_NR,
1794 .label = "GPI",
1795 },
1796 }, {
1797 .chip = {
1798 .base = S5PC100_GPJ0(0),
1799 .ngpio = S5PC100_GPIO_J0_NR,
1800 .label = "GPJ0",
1801 },
1802 }, {
1803 .chip = {
1804 .base = S5PC100_GPJ1(0),
1805 .ngpio = S5PC100_GPIO_J1_NR,
1806 .label = "GPJ1",
1807 },
1808 }, {
1809 .chip = {
1810 .base = S5PC100_GPJ2(0),
1811 .ngpio = S5PC100_GPIO_J2_NR,
1812 .label = "GPJ2",
1813 },
1814 }, {
1815 .chip = {
1816 .base = S5PC100_GPJ3(0),
1817 .ngpio = S5PC100_GPIO_J3_NR,
1818 .label = "GPJ3",
1819 },
1820 }, {
1821 .chip = {
1822 .base = S5PC100_GPJ4(0),
1823 .ngpio = S5PC100_GPIO_J4_NR,
1824 .label = "GPJ4",
1825 },
1826 }, {
1827 .chip = {
1828 .base = S5PC100_GPK0(0),
1829 .ngpio = S5PC100_GPIO_K0_NR,
1830 .label = "GPK0",
1831 },
1832 }, {
1833 .chip = {
1834 .base = S5PC100_GPK1(0),
1835 .ngpio = S5PC100_GPIO_K1_NR,
1836 .label = "GPK1",
1837 },
1838 }, {
1839 .chip = {
1840 .base = S5PC100_GPK2(0),
1841 .ngpio = S5PC100_GPIO_K2_NR,
1842 .label = "GPK2",
1843 },
1844 }, {
1845 .chip = {
1846 .base = S5PC100_GPK3(0),
1847 .ngpio = S5PC100_GPIO_K3_NR,
1848 .label = "GPK3",
1849 },
1850 }, {
1851 .chip = {
1852 .base = S5PC100_GPL0(0),
1853 .ngpio = S5PC100_GPIO_L0_NR,
1854 .label = "GPL0",
1855 },
1856 }, {
1857 .chip = {
1858 .base = S5PC100_GPL1(0),
1859 .ngpio = S5PC100_GPIO_L1_NR,
1860 .label = "GPL1",
1861 },
1862 }, {
1863 .chip = {
1864 .base = S5PC100_GPL2(0),
1865 .ngpio = S5PC100_GPIO_L2_NR,
1866 .label = "GPL2",
1867 },
1868 }, {
1869 .chip = {
1870 .base = S5PC100_GPL3(0),
1871 .ngpio = S5PC100_GPIO_L3_NR,
1872 .label = "GPL3",
1873 },
1874 }, {
1875 .chip = {
1876 .base = S5PC100_GPL4(0),
1877 .ngpio = S5PC100_GPIO_L4_NR,
1878 .label = "GPL4",
1879 },
1880 }, {
1881 .base = (S5P_VA_GPIO + 0xC00),
1882 .irq_base = IRQ_EINT(0),
1883 .chip = {
1884 .base = S5PC100_GPH0(0),
1885 .ngpio = S5PC100_GPIO_H0_NR,
1886 .label = "GPH0",
1887 .to_irq = samsung_gpiolib_to_irq,
1888 },
1889 }, {
1890 .base = (S5P_VA_GPIO + 0xC20),
1891 .irq_base = IRQ_EINT(8),
1892 .chip = {
1893 .base = S5PC100_GPH1(0),
1894 .ngpio = S5PC100_GPIO_H1_NR,
1895 .label = "GPH1",
1896 .to_irq = samsung_gpiolib_to_irq,
1897 },
1898 }, {
1899 .base = (S5P_VA_GPIO + 0xC40),
1900 .irq_base = IRQ_EINT(16),
1901 .chip = {
1902 .base = S5PC100_GPH2(0),
1903 .ngpio = S5PC100_GPIO_H2_NR,
1904 .label = "GPH2",
1905 .to_irq = samsung_gpiolib_to_irq,
1906 },
1907 }, {
1908 .base = (S5P_VA_GPIO + 0xC60),
1909 .irq_base = IRQ_EINT(24),
1910 .chip = {
1911 .base = S5PC100_GPH3(0),
1912 .ngpio = S5PC100_GPIO_H3_NR,
1913 .label = "GPH3",
1914 .to_irq = samsung_gpiolib_to_irq,
1915 },
1916 },
1917#endif
1918};
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931static struct samsung_gpio_chip s5pv210_gpios_4bit[] = {
1932#ifdef CONFIG_CPU_S5PV210
1933 {
1934 .chip = {
1935 .base = S5PV210_GPA0(0),
1936 .ngpio = S5PV210_GPIO_A0_NR,
1937 .label = "GPA0",
1938 },
1939 }, {
1940 .chip = {
1941 .base = S5PV210_GPA1(0),
1942 .ngpio = S5PV210_GPIO_A1_NR,
1943 .label = "GPA1",
1944 },
1945 }, {
1946 .chip = {
1947 .base = S5PV210_GPB(0),
1948 .ngpio = S5PV210_GPIO_B_NR,
1949 .label = "GPB",
1950 },
1951 }, {
1952 .chip = {
1953 .base = S5PV210_GPC0(0),
1954 .ngpio = S5PV210_GPIO_C0_NR,
1955 .label = "GPC0",
1956 },
1957 }, {
1958 .chip = {
1959 .base = S5PV210_GPC1(0),
1960 .ngpio = S5PV210_GPIO_C1_NR,
1961 .label = "GPC1",
1962 },
1963 }, {
1964 .chip = {
1965 .base = S5PV210_GPD0(0),
1966 .ngpio = S5PV210_GPIO_D0_NR,
1967 .label = "GPD0",
1968 },
1969 }, {
1970 .chip = {
1971 .base = S5PV210_GPD1(0),
1972 .ngpio = S5PV210_GPIO_D1_NR,
1973 .label = "GPD1",
1974 },
1975 }, {
1976 .chip = {
1977 .base = S5PV210_GPE0(0),
1978 .ngpio = S5PV210_GPIO_E0_NR,
1979 .label = "GPE0",
1980 },
1981 }, {
1982 .chip = {
1983 .base = S5PV210_GPE1(0),
1984 .ngpio = S5PV210_GPIO_E1_NR,
1985 .label = "GPE1",
1986 },
1987 }, {
1988 .chip = {
1989 .base = S5PV210_GPF0(0),
1990 .ngpio = S5PV210_GPIO_F0_NR,
1991 .label = "GPF0",
1992 },
1993 }, {
1994 .chip = {
1995 .base = S5PV210_GPF1(0),
1996 .ngpio = S5PV210_GPIO_F1_NR,
1997 .label = "GPF1",
1998 },
1999 }, {
2000 .chip = {
2001 .base = S5PV210_GPF2(0),
2002 .ngpio = S5PV210_GPIO_F2_NR,
2003 .label = "GPF2",
2004 },
2005 }, {
2006 .chip = {
2007 .base = S5PV210_GPF3(0),
2008 .ngpio = S5PV210_GPIO_F3_NR,
2009 .label = "GPF3",
2010 },
2011 }, {
2012 .chip = {
2013 .base = S5PV210_GPG0(0),
2014 .ngpio = S5PV210_GPIO_G0_NR,
2015 .label = "GPG0",
2016 },
2017 }, {
2018 .chip = {
2019 .base = S5PV210_GPG1(0),
2020 .ngpio = S5PV210_GPIO_G1_NR,
2021 .label = "GPG1",
2022 },
2023 }, {
2024 .chip = {
2025 .base = S5PV210_GPG2(0),
2026 .ngpio = S5PV210_GPIO_G2_NR,
2027 .label = "GPG2",
2028 },
2029 }, {
2030 .chip = {
2031 .base = S5PV210_GPG3(0),
2032 .ngpio = S5PV210_GPIO_G3_NR,
2033 .label = "GPG3",
2034 },
2035 }, {
2036 .chip = {
2037 .base = S5PV210_GPI(0),
2038 .ngpio = S5PV210_GPIO_I_NR,
2039 .label = "GPI",
2040 },
2041 }, {
2042 .chip = {
2043 .base = S5PV210_GPJ0(0),
2044 .ngpio = S5PV210_GPIO_J0_NR,
2045 .label = "GPJ0",
2046 },
2047 }, {
2048 .chip = {
2049 .base = S5PV210_GPJ1(0),
2050 .ngpio = S5PV210_GPIO_J1_NR,
2051 .label = "GPJ1",
2052 },
2053 }, {
2054 .chip = {
2055 .base = S5PV210_GPJ2(0),
2056 .ngpio = S5PV210_GPIO_J2_NR,
2057 .label = "GPJ2",
2058 },
2059 }, {
2060 .chip = {
2061 .base = S5PV210_GPJ3(0),
2062 .ngpio = S5PV210_GPIO_J3_NR,
2063 .label = "GPJ3",
2064 },
2065 }, {
2066 .chip = {
2067 .base = S5PV210_GPJ4(0),
2068 .ngpio = S5PV210_GPIO_J4_NR,
2069 .label = "GPJ4",
2070 },
2071 }, {
2072 .chip = {
2073 .base = S5PV210_MP01(0),
2074 .ngpio = S5PV210_GPIO_MP01_NR,
2075 .label = "MP01",
2076 },
2077 }, {
2078 .chip = {
2079 .base = S5PV210_MP02(0),
2080 .ngpio = S5PV210_GPIO_MP02_NR,
2081 .label = "MP02",
2082 },
2083 }, {
2084 .chip = {
2085 .base = S5PV210_MP03(0),
2086 .ngpio = S5PV210_GPIO_MP03_NR,
2087 .label = "MP03",
2088 },
2089 }, {
2090 .chip = {
2091 .base = S5PV210_MP04(0),
2092 .ngpio = S5PV210_GPIO_MP04_NR,
2093 .label = "MP04",
2094 },
2095 }, {
2096 .chip = {
2097 .base = S5PV210_MP05(0),
2098 .ngpio = S5PV210_GPIO_MP05_NR,
2099 .label = "MP05",
2100 },
2101 }, {
2102 .base = (S5P_VA_GPIO + 0xC00),
2103 .irq_base = IRQ_EINT(0),
2104 .chip = {
2105 .base = S5PV210_GPH0(0),
2106 .ngpio = S5PV210_GPIO_H0_NR,
2107 .label = "GPH0",
2108 .to_irq = samsung_gpiolib_to_irq,
2109 },
2110 }, {
2111 .base = (S5P_VA_GPIO + 0xC20),
2112 .irq_base = IRQ_EINT(8),
2113 .chip = {
2114 .base = S5PV210_GPH1(0),
2115 .ngpio = S5PV210_GPIO_H1_NR,
2116 .label = "GPH1",
2117 .to_irq = samsung_gpiolib_to_irq,
2118 },
2119 }, {
2120 .base = (S5P_VA_GPIO + 0xC40),
2121 .irq_base = IRQ_EINT(16),
2122 .chip = {
2123 .base = S5PV210_GPH2(0),
2124 .ngpio = S5PV210_GPIO_H2_NR,
2125 .label = "GPH2",
2126 .to_irq = samsung_gpiolib_to_irq,
2127 },
2128 }, {
2129 .base = (S5P_VA_GPIO + 0xC60),
2130 .irq_base = IRQ_EINT(24),
2131 .chip = {
2132 .base = S5PV210_GPH3(0),
2133 .ngpio = S5PV210_GPIO_H3_NR,
2134 .label = "GPH3",
2135 .to_irq = samsung_gpiolib_to_irq,
2136 },
2137 },
2138#endif
2139};
2140
2141
2142static __init int samsung_gpiolib_init(void)
2143{
2144 struct samsung_gpio_chip *chip;
2145 int i, nr_chips;
2146 int group = 0;
2147
2148#if defined(CONFIG_PINCTRL_EXYNOS) || defined(CONFIG_PINCTRL_EXYNOS5440)
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160 struct device_node *pctrl_np;
2161 static const struct of_device_id exynos_pinctrl_ids[] = {
2162 { .compatible = "samsung,exynos4210-pinctrl", },
2163 { .compatible = "samsung,exynos4x12-pinctrl", },
2164 { .compatible = "samsung,exynos5250-pinctrl", },
2165 { .compatible = "samsung,exynos5440-pinctrl", },
2166 { }
2167 };
2168 for_each_matching_node(pctrl_np, exynos_pinctrl_ids)
2169 if (pctrl_np && of_device_is_available(pctrl_np))
2170 return -ENODEV;
2171#endif
2172
2173 samsung_gpiolib_set_cfg(samsung_gpio_cfgs, ARRAY_SIZE(samsung_gpio_cfgs));
2174
2175 if (soc_is_s3c24xx()) {
2176 s3c24xx_gpiolib_add_chips(s3c24xx_gpios,
2177 ARRAY_SIZE(s3c24xx_gpios), S3C24XX_VA_GPIO);
2178 } else if (soc_is_s3c64xx()) {
2179 samsung_gpiolib_add_2bit_chips(s3c64xx_gpios_2bit,
2180 ARRAY_SIZE(s3c64xx_gpios_2bit),
2181 S3C64XX_VA_GPIO + 0xE0, 0x20);
2182 samsung_gpiolib_add_4bit_chips(s3c64xx_gpios_4bit,
2183 ARRAY_SIZE(s3c64xx_gpios_4bit),
2184 S3C64XX_VA_GPIO);
2185 samsung_gpiolib_add_4bit2_chips(s3c64xx_gpios_4bit2,
2186 ARRAY_SIZE(s3c64xx_gpios_4bit2));
2187 } else if (soc_is_s5p6440()) {
2188 samsung_gpiolib_add_2bit_chips(s5p6440_gpios_2bit,
2189 ARRAY_SIZE(s5p6440_gpios_2bit), NULL, 0x0);
2190 samsung_gpiolib_add_4bit_chips(s5p6440_gpios_4bit,
2191 ARRAY_SIZE(s5p6440_gpios_4bit), S5P_VA_GPIO);
2192 samsung_gpiolib_add_4bit2_chips(s5p6440_gpios_4bit2,
2193 ARRAY_SIZE(s5p6440_gpios_4bit2));
2194 s5p64x0_gpiolib_add_rbank(s5p6440_gpios_rbank,
2195 ARRAY_SIZE(s5p6440_gpios_rbank));
2196 } else if (soc_is_s5p6450()) {
2197 samsung_gpiolib_add_2bit_chips(s5p6450_gpios_2bit,
2198 ARRAY_SIZE(s5p6450_gpios_2bit), NULL, 0x0);
2199 samsung_gpiolib_add_4bit_chips(s5p6450_gpios_4bit,
2200 ARRAY_SIZE(s5p6450_gpios_4bit), S5P_VA_GPIO);
2201 samsung_gpiolib_add_4bit2_chips(s5p6450_gpios_4bit2,
2202 ARRAY_SIZE(s5p6450_gpios_4bit2));
2203 s5p64x0_gpiolib_add_rbank(s5p6450_gpios_rbank,
2204 ARRAY_SIZE(s5p6450_gpios_rbank));
2205 } else if (soc_is_s5pc100()) {
2206 group = 0;
2207 chip = s5pc100_gpios_4bit;
2208 nr_chips = ARRAY_SIZE(s5pc100_gpios_4bit);
2209
2210 for (i = 0; i < nr_chips; i++, chip++) {
2211 if (!chip->config) {
2212 chip->config = &samsung_gpio_cfgs[3];
2213 chip->group = group++;
2214 }
2215 }
2216 samsung_gpiolib_add_4bit_chips(s5pc100_gpios_4bit, nr_chips, S5P_VA_GPIO);
2217#if defined(CONFIG_CPU_S5PC100) && defined(CONFIG_S5P_GPIO_INT)
2218 s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
2219#endif
2220 } else if (soc_is_s5pv210()) {
2221 group = 0;
2222 chip = s5pv210_gpios_4bit;
2223 nr_chips = ARRAY_SIZE(s5pv210_gpios_4bit);
2224
2225 for (i = 0; i < nr_chips; i++, chip++) {
2226 if (!chip->config) {
2227 chip->config = &samsung_gpio_cfgs[3];
2228 chip->group = group++;
2229 }
2230 }
2231 samsung_gpiolib_add_4bit_chips(s5pv210_gpios_4bit, nr_chips, S5P_VA_GPIO);
2232#if defined(CONFIG_CPU_S5PV210) && defined(CONFIG_S5P_GPIO_INT)
2233 s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
2234#endif
2235 } else {
2236 WARN(1, "Unknown SoC in gpio-samsung, no GPIOs added\n");
2237 return -ENODEV;
2238 }
2239
2240 return 0;
2241}
2242core_initcall(samsung_gpiolib_init);
2243
2244int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
2245{
2246 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2247 unsigned long flags;
2248 int offset;
2249 int ret;
2250
2251 if (!chip)
2252 return -EINVAL;
2253
2254 offset = pin - chip->chip.base;
2255
2256 samsung_gpio_lock(chip, flags);
2257 ret = samsung_gpio_do_setcfg(chip, offset, config);
2258 samsung_gpio_unlock(chip, flags);
2259
2260 return ret;
2261}
2262EXPORT_SYMBOL(s3c_gpio_cfgpin);
2263
2264int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
2265 unsigned int cfg)
2266{
2267 int ret;
2268
2269 for (; nr > 0; nr--, start++) {
2270 ret = s3c_gpio_cfgpin(start, cfg);
2271 if (ret != 0)
2272 return ret;
2273 }
2274
2275 return 0;
2276}
2277EXPORT_SYMBOL_GPL(s3c_gpio_cfgpin_range);
2278
2279int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
2280 unsigned int cfg, samsung_gpio_pull_t pull)
2281{
2282 int ret;
2283
2284 for (; nr > 0; nr--, start++) {
2285 s3c_gpio_setpull(start, pull);
2286 ret = s3c_gpio_cfgpin(start, cfg);
2287 if (ret != 0)
2288 return ret;
2289 }
2290
2291 return 0;
2292}
2293EXPORT_SYMBOL_GPL(s3c_gpio_cfgall_range);
2294
2295unsigned s3c_gpio_getcfg(unsigned int pin)
2296{
2297 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2298 unsigned long flags;
2299 unsigned ret = 0;
2300 int offset;
2301
2302 if (chip) {
2303 offset = pin - chip->chip.base;
2304
2305 samsung_gpio_lock(chip, flags);
2306 ret = samsung_gpio_do_getcfg(chip, offset);
2307 samsung_gpio_unlock(chip, flags);
2308 }
2309
2310 return ret;
2311}
2312EXPORT_SYMBOL(s3c_gpio_getcfg);
2313
2314int s3c_gpio_setpull(unsigned int pin, samsung_gpio_pull_t pull)
2315{
2316 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2317 unsigned long flags;
2318 int offset, ret;
2319
2320 if (!chip)
2321 return -EINVAL;
2322
2323 offset = pin - chip->chip.base;
2324
2325 samsung_gpio_lock(chip, flags);
2326 ret = samsung_gpio_do_setpull(chip, offset, pull);
2327 samsung_gpio_unlock(chip, flags);
2328
2329 return ret;
2330}
2331EXPORT_SYMBOL(s3c_gpio_setpull);
2332
2333samsung_gpio_pull_t s3c_gpio_getpull(unsigned int pin)
2334{
2335 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2336 unsigned long flags;
2337 int offset;
2338 u32 pup = 0;
2339
2340 if (chip) {
2341 offset = pin - chip->chip.base;
2342
2343 samsung_gpio_lock(chip, flags);
2344 pup = samsung_gpio_do_getpull(chip, offset);
2345 samsung_gpio_unlock(chip, flags);
2346 }
2347
2348 return (__force samsung_gpio_pull_t)pup;
2349}
2350EXPORT_SYMBOL(s3c_gpio_getpull);
2351
2352#ifdef CONFIG_S5P_GPIO_DRVSTR
2353s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin)
2354{
2355 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2356 unsigned int off;
2357 void __iomem *reg;
2358 int shift;
2359 u32 drvstr;
2360
2361 if (!chip)
2362 return -EINVAL;
2363
2364 off = pin - chip->chip.base;
2365 shift = off * 2;
2366 reg = chip->base + 0x0C;
2367
2368 drvstr = __raw_readl(reg);
2369 drvstr = drvstr >> shift;
2370 drvstr &= 0x3;
2371
2372 return (__force s5p_gpio_drvstr_t)drvstr;
2373}
2374EXPORT_SYMBOL(s5p_gpio_get_drvstr);
2375
2376int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr)
2377{
2378 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2379 unsigned int off;
2380 void __iomem *reg;
2381 int shift;
2382 u32 tmp;
2383
2384 if (!chip)
2385 return -EINVAL;
2386
2387 off = pin - chip->chip.base;
2388 shift = off * 2;
2389 reg = chip->base + 0x0C;
2390
2391 tmp = __raw_readl(reg);
2392 tmp &= ~(0x3 << shift);
2393 tmp |= drvstr << shift;
2394
2395 __raw_writel(tmp, reg);
2396
2397 return 0;
2398}
2399EXPORT_SYMBOL(s5p_gpio_set_drvstr);
2400#endif
2401
2402#ifdef CONFIG_PLAT_S3C24XX
2403unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
2404{
2405 unsigned long flags;
2406 unsigned long misccr;
2407
2408 local_irq_save(flags);
2409 misccr = __raw_readl(S3C24XX_MISCCR);
2410 misccr &= ~clear;
2411 misccr ^= change;
2412 __raw_writel(misccr, S3C24XX_MISCCR);
2413 local_irq_restore(flags);
2414
2415 return misccr;
2416}
2417EXPORT_SYMBOL(s3c2410_modify_misccr);
2418#endif
2419