0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/kernel.h>
0014 #include <linux/irq.h>
0015 #include <linux/io.h>
0016 #include <linux/gpio.h>
0017 #include <linux/init.h>
0018 #include <linux/spinlock.h>
0019 #include <linux/module.h>
0020 #include <linux/interrupt.h>
0021 #include <linux/device.h>
0022 #include <linux/ioport.h>
0023 #include <linux/of.h>
0024 #include <linux/slab.h>
0025 #include <linux/of_address.h>
0026
0027 #include <asm/irq.h>
0028
0029 #include "irqs.h"
0030 #include "map.h"
0031 #include "regs-gpio.h"
0032 #include "gpio-samsung.h"
0033
0034 #include "cpu.h"
0035 #include "gpio-core.h"
0036 #include "gpio-cfg.h"
0037 #include "gpio-cfg-helpers.h"
0038 #include "hardware-s3c24xx.h"
0039 #include "pm.h"
0040
0041 int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip,
0042 unsigned int off, samsung_gpio_pull_t pull)
0043 {
0044 void __iomem *reg = chip->base + 0x08;
0045 int shift = off * 2;
0046 u32 pup;
0047
0048 pup = __raw_readl(reg);
0049 pup &= ~(3 << shift);
0050 pup |= pull << shift;
0051 __raw_writel(pup, reg);
0052
0053 return 0;
0054 }
0055
0056 samsung_gpio_pull_t samsung_gpio_getpull_updown(struct samsung_gpio_chip *chip,
0057 unsigned int off)
0058 {
0059 void __iomem *reg = chip->base + 0x08;
0060 int shift = off * 2;
0061 u32 pup = __raw_readl(reg);
0062
0063 pup >>= shift;
0064 pup &= 0x3;
0065
0066 return (__force samsung_gpio_pull_t)pup;
0067 }
0068
0069 int s3c2443_gpio_setpull(struct samsung_gpio_chip *chip,
0070 unsigned int off, samsung_gpio_pull_t pull)
0071 {
0072 switch (pull) {
0073 case S3C_GPIO_PULL_NONE:
0074 pull = 0x01;
0075 break;
0076 case S3C_GPIO_PULL_UP:
0077 pull = 0x00;
0078 break;
0079 case S3C_GPIO_PULL_DOWN:
0080 pull = 0x02;
0081 break;
0082 }
0083 return samsung_gpio_setpull_updown(chip, off, pull);
0084 }
0085
0086 samsung_gpio_pull_t s3c2443_gpio_getpull(struct samsung_gpio_chip *chip,
0087 unsigned int off)
0088 {
0089 samsung_gpio_pull_t pull;
0090
0091 pull = samsung_gpio_getpull_updown(chip, off);
0092
0093 switch (pull) {
0094 case 0x00:
0095 pull = S3C_GPIO_PULL_UP;
0096 break;
0097 case 0x01:
0098 case 0x03:
0099 pull = S3C_GPIO_PULL_NONE;
0100 break;
0101 case 0x02:
0102 pull = S3C_GPIO_PULL_DOWN;
0103 break;
0104 }
0105
0106 return pull;
0107 }
0108
0109 static int s3c24xx_gpio_setpull_1(struct samsung_gpio_chip *chip,
0110 unsigned int off, samsung_gpio_pull_t pull,
0111 samsung_gpio_pull_t updown)
0112 {
0113 void __iomem *reg = chip->base + 0x08;
0114 u32 pup = __raw_readl(reg);
0115
0116 if (pull == updown)
0117 pup &= ~(1 << off);
0118 else if (pull == S3C_GPIO_PULL_NONE)
0119 pup |= (1 << off);
0120 else
0121 return -EINVAL;
0122
0123 __raw_writel(pup, reg);
0124 return 0;
0125 }
0126
0127 static samsung_gpio_pull_t s3c24xx_gpio_getpull_1(struct samsung_gpio_chip *chip,
0128 unsigned int off,
0129 samsung_gpio_pull_t updown)
0130 {
0131 void __iomem *reg = chip->base + 0x08;
0132 u32 pup = __raw_readl(reg);
0133
0134 pup &= (1 << off);
0135 return pup ? S3C_GPIO_PULL_NONE : updown;
0136 }
0137
0138 samsung_gpio_pull_t s3c24xx_gpio_getpull_1up(struct samsung_gpio_chip *chip,
0139 unsigned int off)
0140 {
0141 return s3c24xx_gpio_getpull_1(chip, off, S3C_GPIO_PULL_UP);
0142 }
0143
0144 int s3c24xx_gpio_setpull_1up(struct samsung_gpio_chip *chip,
0145 unsigned int off, samsung_gpio_pull_t pull)
0146 {
0147 return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_UP);
0148 }
0149
0150 samsung_gpio_pull_t s3c24xx_gpio_getpull_1down(struct samsung_gpio_chip *chip,
0151 unsigned int off)
0152 {
0153 return s3c24xx_gpio_getpull_1(chip, off, S3C_GPIO_PULL_DOWN);
0154 }
0155
0156 int s3c24xx_gpio_setpull_1down(struct samsung_gpio_chip *chip,
0157 unsigned int off, samsung_gpio_pull_t pull)
0158 {
0159 return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_DOWN);
0160 }
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176 static int samsung_gpio_setcfg_2bit(struct samsung_gpio_chip *chip,
0177 unsigned int off, unsigned int cfg)
0178 {
0179 void __iomem *reg = chip->base;
0180 unsigned int shift = off * 2;
0181 u32 con;
0182
0183 if (samsung_gpio_is_cfg_special(cfg)) {
0184 cfg &= 0xf;
0185 if (cfg > 3)
0186 return -EINVAL;
0187
0188 cfg <<= shift;
0189 }
0190
0191 con = __raw_readl(reg);
0192 con &= ~(0x3 << shift);
0193 con |= cfg;
0194 __raw_writel(con, reg);
0195
0196 return 0;
0197 }
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209 static unsigned int samsung_gpio_getcfg_2bit(struct samsung_gpio_chip *chip,
0210 unsigned int off)
0211 {
0212 u32 con;
0213
0214 con = __raw_readl(chip->base);
0215 con >>= off * 2;
0216 con &= 3;
0217
0218
0219 return S3C_GPIO_SPECIAL(con);
0220 }
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239 static int samsung_gpio_setcfg_4bit(struct samsung_gpio_chip *chip,
0240 unsigned int off, unsigned int cfg)
0241 {
0242 void __iomem *reg = chip->base;
0243 unsigned int shift = (off & 7) * 4;
0244 u32 con;
0245
0246 if (off < 8 && chip->chip.ngpio > 8)
0247 reg -= 4;
0248
0249 if (samsung_gpio_is_cfg_special(cfg)) {
0250 cfg &= 0xf;
0251 cfg <<= shift;
0252 }
0253
0254 con = __raw_readl(reg);
0255 con &= ~(0xf << shift);
0256 con |= cfg;
0257 __raw_writel(con, reg);
0258
0259 return 0;
0260 }
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274 static unsigned samsung_gpio_getcfg_4bit(struct samsung_gpio_chip *chip,
0275 unsigned int off)
0276 {
0277 void __iomem *reg = chip->base;
0278 unsigned int shift = (off & 7) * 4;
0279 u32 con;
0280
0281 if (off < 8 && chip->chip.ngpio > 8)
0282 reg -= 4;
0283
0284 con = __raw_readl(reg);
0285 con >>= shift;
0286 con &= 0xf;
0287
0288
0289 return S3C_GPIO_SPECIAL(con);
0290 }
0291
0292 #ifdef CONFIG_PLAT_S3C24XX
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304 static int s3c24xx_gpio_setcfg_abank(struct samsung_gpio_chip *chip,
0305 unsigned int off, unsigned int cfg)
0306 {
0307 void __iomem *reg = chip->base;
0308 unsigned int shift = off;
0309 u32 con;
0310
0311 if (samsung_gpio_is_cfg_special(cfg)) {
0312 cfg &= 0xf;
0313
0314
0315 cfg -= 1;
0316 if (cfg > 1)
0317 return -EINVAL;
0318
0319 cfg <<= shift;
0320 }
0321
0322 con = __raw_readl(reg);
0323 con &= ~(0x1 << shift);
0324 con |= cfg;
0325 __raw_writel(con, reg);
0326
0327 return 0;
0328 }
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342 static unsigned s3c24xx_gpio_getcfg_abank(struct samsung_gpio_chip *chip,
0343 unsigned int off)
0344 {
0345 u32 con;
0346
0347 con = __raw_readl(chip->base);
0348 con >>= off;
0349 con &= 1;
0350 con++;
0351
0352 return S3C_GPIO_SFN(con);
0353 }
0354 #endif
0355
0356 static void __init samsung_gpiolib_set_cfg(struct samsung_gpio_cfg *chipcfg,
0357 int nr_chips)
0358 {
0359 for (; nr_chips > 0; nr_chips--, chipcfg++) {
0360 if (!chipcfg->set_config)
0361 chipcfg->set_config = samsung_gpio_setcfg_4bit;
0362 if (!chipcfg->get_config)
0363 chipcfg->get_config = samsung_gpio_getcfg_4bit;
0364 if (!chipcfg->set_pull)
0365 chipcfg->set_pull = samsung_gpio_setpull_updown;
0366 if (!chipcfg->get_pull)
0367 chipcfg->get_pull = samsung_gpio_getpull_updown;
0368 }
0369 }
0370
0371 struct samsung_gpio_cfg s3c24xx_gpiocfg_default = {
0372 .set_config = samsung_gpio_setcfg_2bit,
0373 .get_config = samsung_gpio_getcfg_2bit,
0374 };
0375
0376 #ifdef CONFIG_PLAT_S3C24XX
0377 static struct samsung_gpio_cfg s3c24xx_gpiocfg_banka = {
0378 .set_config = s3c24xx_gpio_setcfg_abank,
0379 .get_config = s3c24xx_gpio_getcfg_abank,
0380 };
0381 #endif
0382
0383 static struct samsung_gpio_cfg samsung_gpio_cfgs[] = {
0384 [0] = {
0385 .cfg_eint = 0x0,
0386 },
0387 [1] = {
0388 .cfg_eint = 0x3,
0389 },
0390 [2] = {
0391 .cfg_eint = 0x7,
0392 },
0393 [3] = {
0394 .cfg_eint = 0xF,
0395 },
0396 [4] = {
0397 .cfg_eint = 0x0,
0398 .set_config = samsung_gpio_setcfg_2bit,
0399 .get_config = samsung_gpio_getcfg_2bit,
0400 },
0401 [5] = {
0402 .cfg_eint = 0x2,
0403 .set_config = samsung_gpio_setcfg_2bit,
0404 .get_config = samsung_gpio_getcfg_2bit,
0405 },
0406 [6] = {
0407 .cfg_eint = 0x3,
0408 .set_config = samsung_gpio_setcfg_2bit,
0409 .get_config = samsung_gpio_getcfg_2bit,
0410 },
0411 [7] = {
0412 .set_config = samsung_gpio_setcfg_2bit,
0413 .get_config = samsung_gpio_getcfg_2bit,
0414 },
0415 };
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427
0428
0429 static int samsung_gpiolib_2bit_input(struct gpio_chip *chip, unsigned offset)
0430 {
0431 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
0432 void __iomem *base = ourchip->base;
0433 unsigned long flags;
0434 unsigned long con;
0435
0436 samsung_gpio_lock(ourchip, flags);
0437
0438 con = __raw_readl(base + 0x00);
0439 con &= ~(3 << (offset * 2));
0440
0441 __raw_writel(con, base + 0x00);
0442
0443 samsung_gpio_unlock(ourchip, flags);
0444 return 0;
0445 }
0446
0447 static int samsung_gpiolib_2bit_output(struct gpio_chip *chip,
0448 unsigned offset, int value)
0449 {
0450 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
0451 void __iomem *base = ourchip->base;
0452 unsigned long flags;
0453 unsigned long dat;
0454 unsigned long con;
0455
0456 samsung_gpio_lock(ourchip, flags);
0457
0458 dat = __raw_readl(base + 0x04);
0459 dat &= ~(1 << offset);
0460 if (value)
0461 dat |= 1 << offset;
0462 __raw_writel(dat, base + 0x04);
0463
0464 con = __raw_readl(base + 0x00);
0465 con &= ~(3 << (offset * 2));
0466 con |= 1 << (offset * 2);
0467
0468 __raw_writel(con, base + 0x00);
0469 __raw_writel(dat, base + 0x04);
0470
0471 samsung_gpio_unlock(ourchip, flags);
0472 return 0;
0473 }
0474
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484
0485
0486
0487
0488
0489
0490
0491 static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
0492 unsigned int offset)
0493 {
0494 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
0495 void __iomem *base = ourchip->base;
0496 unsigned long con;
0497
0498 con = __raw_readl(base + GPIOCON_OFF);
0499 if (ourchip->bitmap_gpio_int & BIT(offset))
0500 con |= 0xf << con_4bit_shift(offset);
0501 else
0502 con &= ~(0xf << con_4bit_shift(offset));
0503 __raw_writel(con, base + GPIOCON_OFF);
0504
0505 pr_debug("%s: %p: CON now %08lx\n", __func__, base, con);
0506
0507 return 0;
0508 }
0509
0510 static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
0511 unsigned int offset, int value)
0512 {
0513 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
0514 void __iomem *base = ourchip->base;
0515 unsigned long con;
0516 unsigned long dat;
0517
0518 con = __raw_readl(base + GPIOCON_OFF);
0519 con &= ~(0xf << con_4bit_shift(offset));
0520 con |= 0x1 << con_4bit_shift(offset);
0521
0522 dat = __raw_readl(base + GPIODAT_OFF);
0523
0524 if (value)
0525 dat |= 1 << offset;
0526 else
0527 dat &= ~(1 << offset);
0528
0529 __raw_writel(dat, base + GPIODAT_OFF);
0530 __raw_writel(con, base + GPIOCON_OFF);
0531 __raw_writel(dat, base + GPIODAT_OFF);
0532
0533 pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
0534
0535 return 0;
0536 }
0537
0538
0539
0540
0541
0542
0543
0544
0545
0546
0547
0548
0549
0550
0551
0552
0553
0554
0555
0556
0557
0558
0559
0560 static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
0561 unsigned int offset)
0562 {
0563 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
0564 void __iomem *base = ourchip->base;
0565 void __iomem *regcon = base;
0566 unsigned long con;
0567
0568 if (offset > 7)
0569 offset -= 8;
0570 else
0571 regcon -= 4;
0572
0573 con = __raw_readl(regcon);
0574 con &= ~(0xf << con_4bit_shift(offset));
0575 __raw_writel(con, regcon);
0576
0577 pr_debug("%s: %p: CON %08lx\n", __func__, base, con);
0578
0579 return 0;
0580 }
0581
0582 static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
0583 unsigned int offset, int value)
0584 {
0585 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
0586 void __iomem *base = ourchip->base;
0587 void __iomem *regcon = base;
0588 unsigned long con;
0589 unsigned long dat;
0590 unsigned con_offset = offset;
0591
0592 if (con_offset > 7)
0593 con_offset -= 8;
0594 else
0595 regcon -= 4;
0596
0597 con = __raw_readl(regcon);
0598 con &= ~(0xf << con_4bit_shift(con_offset));
0599 con |= 0x1 << con_4bit_shift(con_offset);
0600
0601 dat = __raw_readl(base + GPIODAT_OFF);
0602
0603 if (value)
0604 dat |= 1 << offset;
0605 else
0606 dat &= ~(1 << offset);
0607
0608 __raw_writel(dat, base + GPIODAT_OFF);
0609 __raw_writel(con, regcon);
0610 __raw_writel(dat, base + GPIODAT_OFF);
0611
0612 pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
0613
0614 return 0;
0615 }
0616
0617 #ifdef CONFIG_PLAT_S3C24XX
0618
0619
0620 static int s3c24xx_gpiolib_banka_input(struct gpio_chip *chip, unsigned offset)
0621 {
0622 return -EINVAL;
0623 }
0624
0625 static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip,
0626 unsigned offset, int value)
0627 {
0628 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
0629 void __iomem *base = ourchip->base;
0630 unsigned long flags;
0631 unsigned long dat;
0632 unsigned long con;
0633
0634 local_irq_save(flags);
0635
0636 con = __raw_readl(base + 0x00);
0637 dat = __raw_readl(base + 0x04);
0638
0639 dat &= ~(1 << offset);
0640 if (value)
0641 dat |= 1 << offset;
0642
0643 __raw_writel(dat, base + 0x04);
0644
0645 con &= ~(1 << offset);
0646
0647 __raw_writel(con, base + 0x00);
0648 __raw_writel(dat, base + 0x04);
0649
0650 local_irq_restore(flags);
0651 return 0;
0652 }
0653 #endif
0654
0655 static void samsung_gpiolib_set(struct gpio_chip *chip,
0656 unsigned offset, int value)
0657 {
0658 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
0659 void __iomem *base = ourchip->base;
0660 unsigned long flags;
0661 unsigned long dat;
0662
0663 samsung_gpio_lock(ourchip, flags);
0664
0665 dat = __raw_readl(base + 0x04);
0666 dat &= ~(1 << offset);
0667 if (value)
0668 dat |= 1 << offset;
0669 __raw_writel(dat, base + 0x04);
0670
0671 samsung_gpio_unlock(ourchip, flags);
0672 }
0673
0674 static int samsung_gpiolib_get(struct gpio_chip *chip, unsigned offset)
0675 {
0676 struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
0677 unsigned long val;
0678
0679 val = __raw_readl(ourchip->base + 0x04);
0680 val >>= offset;
0681 val &= 1;
0682
0683 return val;
0684 }
0685
0686
0687
0688
0689
0690
0691
0692
0693
0694
0695
0696
0697
0698 #ifdef CONFIG_S3C_GPIO_TRACK
0699 struct samsung_gpio_chip *s3c_gpios[S3C_GPIO_END];
0700
0701 static __init void s3c_gpiolib_track(struct samsung_gpio_chip *chip)
0702 {
0703 unsigned int gpn;
0704 int i;
0705
0706 gpn = chip->chip.base;
0707 for (i = 0; i < chip->chip.ngpio; i++, gpn++) {
0708 BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios));
0709 s3c_gpios[gpn] = chip;
0710 }
0711 }
0712 #endif
0713
0714
0715
0716
0717
0718
0719
0720
0721
0722
0723
0724 static void __init samsung_gpiolib_add(struct samsung_gpio_chip *chip)
0725 {
0726 struct gpio_chip *gc = &chip->chip;
0727 int ret;
0728
0729 BUG_ON(!chip->base);
0730 BUG_ON(!gc->label);
0731 BUG_ON(!gc->ngpio);
0732
0733 spin_lock_init(&chip->lock);
0734
0735 if (!gc->direction_input)
0736 gc->direction_input = samsung_gpiolib_2bit_input;
0737 if (!gc->direction_output)
0738 gc->direction_output = samsung_gpiolib_2bit_output;
0739 if (!gc->set)
0740 gc->set = samsung_gpiolib_set;
0741 if (!gc->get)
0742 gc->get = samsung_gpiolib_get;
0743
0744 #ifdef CONFIG_PM
0745 if (chip->pm != NULL) {
0746 if (!chip->pm->save || !chip->pm->resume)
0747 pr_err("gpio: %s has missing PM functions\n",
0748 gc->label);
0749 } else
0750 pr_err("gpio: %s has no PM function\n", gc->label);
0751 #endif
0752
0753
0754 ret = gpiochip_add_data(gc, chip);
0755 if (ret >= 0)
0756 s3c_gpiolib_track(chip);
0757 }
0758
0759 static void __init s3c24xx_gpiolib_add_chips(struct samsung_gpio_chip *chip,
0760 int nr_chips, void __iomem *base)
0761 {
0762 int i;
0763 struct gpio_chip *gc = &chip->chip;
0764
0765 for (i = 0 ; i < nr_chips; i++, chip++) {
0766
0767 if (chip->chip.base >= S3C_GPIO_END)
0768 continue;
0769
0770 if (!chip->config)
0771 chip->config = &s3c24xx_gpiocfg_default;
0772 if (!chip->pm)
0773 chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
0774 if ((base != NULL) && (chip->base == NULL))
0775 chip->base = base + ((i) * 0x10);
0776
0777 if (!gc->direction_input)
0778 gc->direction_input = samsung_gpiolib_2bit_input;
0779 if (!gc->direction_output)
0780 gc->direction_output = samsung_gpiolib_2bit_output;
0781
0782 samsung_gpiolib_add(chip);
0783 }
0784 }
0785
0786 static void __init samsung_gpiolib_add_2bit_chips(struct samsung_gpio_chip *chip,
0787 int nr_chips, void __iomem *base,
0788 unsigned int offset)
0789 {
0790 int i;
0791
0792 for (i = 0 ; i < nr_chips; i++, chip++) {
0793 chip->chip.direction_input = samsung_gpiolib_2bit_input;
0794 chip->chip.direction_output = samsung_gpiolib_2bit_output;
0795
0796 if (!chip->config)
0797 chip->config = &samsung_gpio_cfgs[7];
0798 if (!chip->pm)
0799 chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
0800 if ((base != NULL) && (chip->base == NULL))
0801 chip->base = base + ((i) * offset);
0802
0803 samsung_gpiolib_add(chip);
0804 }
0805 }
0806
0807
0808
0809
0810
0811
0812
0813
0814
0815
0816
0817
0818
0819
0820
0821
0822
0823 static void __init samsung_gpiolib_add_4bit_chips(struct samsung_gpio_chip *chip,
0824 int nr_chips, void __iomem *base)
0825 {
0826 int i;
0827
0828 for (i = 0 ; i < nr_chips; i++, chip++) {
0829 chip->chip.direction_input = samsung_gpiolib_4bit_input;
0830 chip->chip.direction_output = samsung_gpiolib_4bit_output;
0831
0832 if (!chip->config)
0833 chip->config = &samsung_gpio_cfgs[2];
0834 if (!chip->pm)
0835 chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
0836 if ((base != NULL) && (chip->base == NULL))
0837 chip->base = base + ((i) * 0x20);
0838
0839 chip->bitmap_gpio_int = 0;
0840
0841 samsung_gpiolib_add(chip);
0842 }
0843 }
0844
0845 static void __init samsung_gpiolib_add_4bit2_chips(struct samsung_gpio_chip *chip,
0846 int nr_chips)
0847 {
0848 for (; nr_chips > 0; nr_chips--, chip++) {
0849 chip->chip.direction_input = samsung_gpiolib_4bit2_input;
0850 chip->chip.direction_output = samsung_gpiolib_4bit2_output;
0851
0852 if (!chip->config)
0853 chip->config = &samsung_gpio_cfgs[2];
0854 if (!chip->pm)
0855 chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
0856
0857 samsung_gpiolib_add(chip);
0858 }
0859 }
0860
0861 int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
0862 {
0863 struct samsung_gpio_chip *samsung_chip = gpiochip_get_data(chip);
0864
0865 return samsung_chip->irq_base + offset;
0866 }
0867
0868 #ifdef CONFIG_PLAT_S3C24XX
0869 static int s3c24xx_gpiolib_fbank_to_irq(struct gpio_chip *chip, unsigned offset)
0870 {
0871 if (offset < 4) {
0872 if (soc_is_s3c2412())
0873 return IRQ_EINT0_2412 + offset;
0874 else
0875 return IRQ_EINT0 + offset;
0876 }
0877
0878 if (offset < 8)
0879 return IRQ_EINT4 + offset - 4;
0880
0881 return -EINVAL;
0882 }
0883 #endif
0884
0885 #ifdef CONFIG_ARCH_S3C64XX
0886 static int s3c64xx_gpiolib_mbank_to_irq(struct gpio_chip *chip, unsigned pin)
0887 {
0888 return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO;
0889 }
0890
0891 static int s3c64xx_gpiolib_lbank_to_irq(struct gpio_chip *chip, unsigned pin)
0892 {
0893 return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO;
0894 }
0895 #endif
0896
0897 struct samsung_gpio_chip s3c24xx_gpios[] = {
0898 #ifdef CONFIG_PLAT_S3C24XX
0899 {
0900 .config = &s3c24xx_gpiocfg_banka,
0901 .chip = {
0902 .base = S3C2410_GPA(0),
0903 .owner = THIS_MODULE,
0904 .label = "GPIOA",
0905 .ngpio = 27,
0906 .direction_input = s3c24xx_gpiolib_banka_input,
0907 .direction_output = s3c24xx_gpiolib_banka_output,
0908 },
0909 }, {
0910 .chip = {
0911 .base = S3C2410_GPB(0),
0912 .owner = THIS_MODULE,
0913 .label = "GPIOB",
0914 .ngpio = 11,
0915 },
0916 }, {
0917 .chip = {
0918 .base = S3C2410_GPC(0),
0919 .owner = THIS_MODULE,
0920 .label = "GPIOC",
0921 .ngpio = 16,
0922 },
0923 }, {
0924 .chip = {
0925 .base = S3C2410_GPD(0),
0926 .owner = THIS_MODULE,
0927 .label = "GPIOD",
0928 .ngpio = 16,
0929 },
0930 }, {
0931 .chip = {
0932 .base = S3C2410_GPE(0),
0933 .label = "GPIOE",
0934 .owner = THIS_MODULE,
0935 .ngpio = 16,
0936 },
0937 }, {
0938 .chip = {
0939 .base = S3C2410_GPF(0),
0940 .owner = THIS_MODULE,
0941 .label = "GPIOF",
0942 .ngpio = 8,
0943 .to_irq = s3c24xx_gpiolib_fbank_to_irq,
0944 },
0945 }, {
0946 .irq_base = IRQ_EINT8,
0947 .chip = {
0948 .base = S3C2410_GPG(0),
0949 .owner = THIS_MODULE,
0950 .label = "GPIOG",
0951 .ngpio = 16,
0952 .to_irq = samsung_gpiolib_to_irq,
0953 },
0954 }, {
0955 .chip = {
0956 .base = S3C2410_GPH(0),
0957 .owner = THIS_MODULE,
0958 .label = "GPIOH",
0959 .ngpio = 15,
0960 },
0961 },
0962
0963 {
0964 .base = S3C2440_GPJCON,
0965 .chip = {
0966 .base = S3C2410_GPJ(0),
0967 .owner = THIS_MODULE,
0968 .label = "GPIOJ",
0969 .ngpio = 16,
0970 },
0971 }, {
0972 .base = S3C2443_GPKCON,
0973 .chip = {
0974 .base = S3C2410_GPK(0),
0975 .owner = THIS_MODULE,
0976 .label = "GPIOK",
0977 .ngpio = 16,
0978 },
0979 }, {
0980 .base = S3C2443_GPLCON,
0981 .chip = {
0982 .base = S3C2410_GPL(0),
0983 .owner = THIS_MODULE,
0984 .label = "GPIOL",
0985 .ngpio = 15,
0986 },
0987 }, {
0988 .base = S3C2443_GPMCON,
0989 .chip = {
0990 .base = S3C2410_GPM(0),
0991 .owner = THIS_MODULE,
0992 .label = "GPIOM",
0993 .ngpio = 2,
0994 },
0995 },
0996 #endif
0997 };
0998
0999
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
1025 static struct samsung_gpio_chip s3c64xx_gpios_4bit[] = {
1026 #ifdef CONFIG_ARCH_S3C64XX
1027 {
1028 .chip = {
1029 .base = S3C64XX_GPA(0),
1030 .ngpio = S3C64XX_GPIO_A_NR,
1031 .label = "GPA",
1032 },
1033 }, {
1034 .chip = {
1035 .base = S3C64XX_GPB(0),
1036 .ngpio = S3C64XX_GPIO_B_NR,
1037 .label = "GPB",
1038 },
1039 }, {
1040 .chip = {
1041 .base = S3C64XX_GPC(0),
1042 .ngpio = S3C64XX_GPIO_C_NR,
1043 .label = "GPC",
1044 },
1045 }, {
1046 .chip = {
1047 .base = S3C64XX_GPD(0),
1048 .ngpio = S3C64XX_GPIO_D_NR,
1049 .label = "GPD",
1050 },
1051 }, {
1052 .config = &samsung_gpio_cfgs[0],
1053 .chip = {
1054 .base = S3C64XX_GPE(0),
1055 .ngpio = S3C64XX_GPIO_E_NR,
1056 .label = "GPE",
1057 },
1058 }, {
1059 .base = S3C64XX_GPG_BASE,
1060 .chip = {
1061 .base = S3C64XX_GPG(0),
1062 .ngpio = S3C64XX_GPIO_G_NR,
1063 .label = "GPG",
1064 },
1065 }, {
1066 .base = S3C64XX_GPM_BASE,
1067 .config = &samsung_gpio_cfgs[1],
1068 .chip = {
1069 .base = S3C64XX_GPM(0),
1070 .ngpio = S3C64XX_GPIO_M_NR,
1071 .label = "GPM",
1072 .to_irq = s3c64xx_gpiolib_mbank_to_irq,
1073 },
1074 },
1075 #endif
1076 };
1077
1078 static struct samsung_gpio_chip s3c64xx_gpios_4bit2[] = {
1079 #ifdef CONFIG_ARCH_S3C64XX
1080 {
1081 .base = S3C64XX_GPH_BASE + 0x4,
1082 .chip = {
1083 .base = S3C64XX_GPH(0),
1084 .ngpio = S3C64XX_GPIO_H_NR,
1085 .label = "GPH",
1086 },
1087 }, {
1088 .base = S3C64XX_GPK_BASE + 0x4,
1089 .config = &samsung_gpio_cfgs[0],
1090 .chip = {
1091 .base = S3C64XX_GPK(0),
1092 .ngpio = S3C64XX_GPIO_K_NR,
1093 .label = "GPK",
1094 },
1095 }, {
1096 .base = S3C64XX_GPL_BASE + 0x4,
1097 .config = &samsung_gpio_cfgs[1],
1098 .chip = {
1099 .base = S3C64XX_GPL(0),
1100 .ngpio = S3C64XX_GPIO_L_NR,
1101 .label = "GPL",
1102 .to_irq = s3c64xx_gpiolib_lbank_to_irq,
1103 },
1104 },
1105 #endif
1106 };
1107
1108 static struct samsung_gpio_chip s3c64xx_gpios_2bit[] = {
1109 #ifdef CONFIG_ARCH_S3C64XX
1110 {
1111 .base = S3C64XX_GPF_BASE,
1112 .config = &samsung_gpio_cfgs[6],
1113 .chip = {
1114 .base = S3C64XX_GPF(0),
1115 .ngpio = S3C64XX_GPIO_F_NR,
1116 .label = "GPF",
1117 },
1118 }, {
1119 .config = &samsung_gpio_cfgs[7],
1120 .chip = {
1121 .base = S3C64XX_GPI(0),
1122 .ngpio = S3C64XX_GPIO_I_NR,
1123 .label = "GPI",
1124 },
1125 }, {
1126 .config = &samsung_gpio_cfgs[7],
1127 .chip = {
1128 .base = S3C64XX_GPJ(0),
1129 .ngpio = S3C64XX_GPIO_J_NR,
1130 .label = "GPJ",
1131 },
1132 }, {
1133 .config = &samsung_gpio_cfgs[6],
1134 .chip = {
1135 .base = S3C64XX_GPO(0),
1136 .ngpio = S3C64XX_GPIO_O_NR,
1137 .label = "GPO",
1138 },
1139 }, {
1140 .config = &samsung_gpio_cfgs[6],
1141 .chip = {
1142 .base = S3C64XX_GPP(0),
1143 .ngpio = S3C64XX_GPIO_P_NR,
1144 .label = "GPP",
1145 },
1146 }, {
1147 .config = &samsung_gpio_cfgs[6],
1148 .chip = {
1149 .base = S3C64XX_GPQ(0),
1150 .ngpio = S3C64XX_GPIO_Q_NR,
1151 .label = "GPQ",
1152 },
1153 }, {
1154 .base = S3C64XX_GPN_BASE,
1155 .irq_base = IRQ_EINT(0),
1156 .config = &samsung_gpio_cfgs[5],
1157 .chip = {
1158 .base = S3C64XX_GPN(0),
1159 .ngpio = S3C64XX_GPIO_N_NR,
1160 .label = "GPN",
1161 .to_irq = samsung_gpiolib_to_irq,
1162 },
1163 },
1164 #endif
1165 };
1166
1167
1168 static __init int samsung_gpiolib_init(void)
1169 {
1170
1171
1172
1173
1174
1175
1176 if (of_have_populated_dt())
1177 return 0;
1178
1179 if (soc_is_s3c24xx()) {
1180 samsung_gpiolib_set_cfg(samsung_gpio_cfgs,
1181 ARRAY_SIZE(samsung_gpio_cfgs));
1182 s3c24xx_gpiolib_add_chips(s3c24xx_gpios,
1183 ARRAY_SIZE(s3c24xx_gpios), S3C24XX_VA_GPIO);
1184 } else if (soc_is_s3c64xx()) {
1185 samsung_gpiolib_set_cfg(samsung_gpio_cfgs,
1186 ARRAY_SIZE(samsung_gpio_cfgs));
1187 samsung_gpiolib_add_2bit_chips(s3c64xx_gpios_2bit,
1188 ARRAY_SIZE(s3c64xx_gpios_2bit),
1189 S3C64XX_VA_GPIO + 0xE0, 0x20);
1190 samsung_gpiolib_add_4bit_chips(s3c64xx_gpios_4bit,
1191 ARRAY_SIZE(s3c64xx_gpios_4bit),
1192 S3C64XX_VA_GPIO);
1193 samsung_gpiolib_add_4bit2_chips(s3c64xx_gpios_4bit2,
1194 ARRAY_SIZE(s3c64xx_gpios_4bit2));
1195 }
1196
1197 return 0;
1198 }
1199 core_initcall(samsung_gpiolib_init);
1200
1201 int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
1202 {
1203 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
1204 unsigned long flags;
1205 int offset;
1206 int ret;
1207
1208 if (!chip)
1209 return -EINVAL;
1210
1211 offset = pin - chip->chip.base;
1212
1213 samsung_gpio_lock(chip, flags);
1214 ret = samsung_gpio_do_setcfg(chip, offset, config);
1215 samsung_gpio_unlock(chip, flags);
1216
1217 return ret;
1218 }
1219 EXPORT_SYMBOL(s3c_gpio_cfgpin);
1220
1221 int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
1222 unsigned int cfg)
1223 {
1224 int ret;
1225
1226 for (; nr > 0; nr--, start++) {
1227 ret = s3c_gpio_cfgpin(start, cfg);
1228 if (ret != 0)
1229 return ret;
1230 }
1231
1232 return 0;
1233 }
1234 EXPORT_SYMBOL_GPL(s3c_gpio_cfgpin_range);
1235
1236 int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
1237 unsigned int cfg, samsung_gpio_pull_t pull)
1238 {
1239 int ret;
1240
1241 for (; nr > 0; nr--, start++) {
1242 s3c_gpio_setpull(start, pull);
1243 ret = s3c_gpio_cfgpin(start, cfg);
1244 if (ret != 0)
1245 return ret;
1246 }
1247
1248 return 0;
1249 }
1250 EXPORT_SYMBOL_GPL(s3c_gpio_cfgall_range);
1251
1252 unsigned s3c_gpio_getcfg(unsigned int pin)
1253 {
1254 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
1255 unsigned long flags;
1256 unsigned ret = 0;
1257 int offset;
1258
1259 if (chip) {
1260 offset = pin - chip->chip.base;
1261
1262 samsung_gpio_lock(chip, flags);
1263 ret = samsung_gpio_do_getcfg(chip, offset);
1264 samsung_gpio_unlock(chip, flags);
1265 }
1266
1267 return ret;
1268 }
1269 EXPORT_SYMBOL(s3c_gpio_getcfg);
1270
1271 int s3c_gpio_setpull(unsigned int pin, samsung_gpio_pull_t pull)
1272 {
1273 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
1274 unsigned long flags;
1275 int offset, ret;
1276
1277 if (!chip)
1278 return -EINVAL;
1279
1280 offset = pin - chip->chip.base;
1281
1282 samsung_gpio_lock(chip, flags);
1283 ret = samsung_gpio_do_setpull(chip, offset, pull);
1284 samsung_gpio_unlock(chip, flags);
1285
1286 return ret;
1287 }
1288 EXPORT_SYMBOL(s3c_gpio_setpull);
1289
1290 samsung_gpio_pull_t s3c_gpio_getpull(unsigned int pin)
1291 {
1292 struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
1293 unsigned long flags;
1294 int offset;
1295 u32 pup = 0;
1296
1297 if (chip) {
1298 offset = pin - chip->chip.base;
1299
1300 samsung_gpio_lock(chip, flags);
1301 pup = samsung_gpio_do_getpull(chip, offset);
1302 samsung_gpio_unlock(chip, flags);
1303 }
1304
1305 return (__force samsung_gpio_pull_t)pup;
1306 }
1307 EXPORT_SYMBOL(s3c_gpio_getpull);
1308
1309 #ifdef CONFIG_PLAT_S3C24XX
1310 unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
1311 {
1312 unsigned long flags;
1313 unsigned long misccr;
1314
1315 local_irq_save(flags);
1316 misccr = __raw_readl(S3C24XX_MISCCR);
1317 misccr &= ~clear;
1318 misccr ^= change;
1319 __raw_writel(misccr, S3C24XX_MISCCR);
1320 local_irq_restore(flags);
1321
1322 return misccr;
1323 }
1324 EXPORT_SYMBOL(s3c2410_modify_misccr);
1325 #endif