linux/drivers/gpio/gpio-samsung.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
   3 *              http://www.samsung.com/
   4 *
   5 * Copyright 2008 Openmoko, Inc.
   6 * Copyright 2008 Simtec Electronics
   7 *      Ben Dooks <ben@simtec.co.uk>
   8 *      http://armlinux.simtec.co.uk/
   9 *
  10 * SAMSUNG - GPIOlib support
  11 *
  12 * This program is free software; you can redistribute it and/or modify
  13 * it under the terms of the GNU General Public License version 2 as
  14 * published by the Free Software Foundation.
  15 */
  16
  17#include <linux/kernel.h>
  18#include <linux/irq.h>
  19#include <linux/io.h>
  20#include <linux/gpio.h>
  21#include <linux/init.h>
  22#include <linux/spinlock.h>
  23#include <linux/module.h>
  24#include <linux/interrupt.h>
  25#include <linux/sysdev.h>
  26#include <linux/ioport.h>
  27
  28#include <asm/irq.h>
  29
  30#include <mach/hardware.h>
  31#include <mach/map.h>
  32#include <mach/regs-clock.h>
  33#include <mach/regs-gpio.h>
  34
  35#include <plat/cpu.h>
  36#include <plat/gpio-core.h>
  37#include <plat/gpio-cfg.h>
  38#include <plat/gpio-cfg-helpers.h>
  39#include <plat/gpio-fns.h>
  40#include <plat/pm.h>
  41
  42#ifndef DEBUG_GPIO
  43#define gpio_dbg(x...) do { } while (0)
  44#else
  45#define gpio_dbg(x...) printk(KERN_DEBUG x)
  46#endif
  47
  48int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip,
  49                                unsigned int off, samsung_gpio_pull_t pull)
  50{
  51        void __iomem *reg = chip->base + 0x08;
  52        int shift = off * 2;
  53        u32 pup;
  54
  55        pup = __raw_readl(reg);
  56        pup &= ~(3 << shift);
  57        pup |= pull << shift;
  58        __raw_writel(pup, reg);
  59
  60        return 0;
  61}
  62
  63samsung_gpio_pull_t samsung_gpio_getpull_updown(struct samsung_gpio_chip *chip,
  64                                                unsigned int off)
  65{
  66        void __iomem *reg = chip->base + 0x08;
  67        int shift = off * 2;
  68        u32 pup = __raw_readl(reg);
  69
  70        pup >>= shift;
  71        pup &= 0x3;
  72
  73        return (__force samsung_gpio_pull_t)pup;
  74}
  75
  76int s3c2443_gpio_setpull(struct samsung_gpio_chip *chip,
  77                         unsigned int off, samsung_gpio_pull_t pull)
  78{
  79        switch (pull) {
  80        case S3C_GPIO_PULL_NONE:
  81                pull = 0x01;
  82                break;
  83        case S3C_GPIO_PULL_UP:
  84                pull = 0x00;
  85                break;
  86        case S3C_GPIO_PULL_DOWN:
  87                pull = 0x02;
  88                break;
  89        }
  90        return samsung_gpio_setpull_updown(chip, off, pull);
  91}
  92
  93samsung_gpio_pull_t s3c2443_gpio_getpull(struct samsung_gpio_chip *chip,
  94                                         unsigned int off)
  95{
  96        samsung_gpio_pull_t pull;
  97
  98        pull = samsung_gpio_getpull_updown(chip, off);
  99
 100        switch (pull) {
 101        case 0x00:
 102                pull = S3C_GPIO_PULL_UP;
 103                break;
 104        case 0x01:
 105        case 0x03:
 106                pull = S3C_GPIO_PULL_NONE;
 107                break;
 108        case 0x02:
 109                pull = S3C_GPIO_PULL_DOWN;
 110                break;
 111        }
 112
 113        return pull;
 114}
 115
 116static int s3c24xx_gpio_setpull_1(struct samsung_gpio_chip *chip,
 117                                  unsigned int off, samsung_gpio_pull_t pull,
 118                                  samsung_gpio_pull_t updown)
 119{
 120        void __iomem *reg = chip->base + 0x08;
 121        u32 pup = __raw_readl(reg);
 122
 123        if (pull == updown)
 124                pup &= ~(1 << off);
 125        else if (pull == S3C_GPIO_PULL_NONE)
 126                pup |= (1 << off);
 127        else
 128                return -EINVAL;
 129
 130        __raw_writel(pup, reg);
 131        return 0;
 132}
 133
 134static samsung_gpio_pull_t s3c24xx_gpio_getpull_1(struct samsung_gpio_chip *chip,
 135                                                  unsigned int off,
 136                                                  samsung_gpio_pull_t updown)
 137{
 138        void __iomem *reg = chip->base + 0x08;
 139        u32 pup = __raw_readl(reg);
 140
 141        pup &= (1 << off);
 142        return pup ? S3C_GPIO_PULL_NONE : updown;
 143}
 144
 145samsung_gpio_pull_t s3c24xx_gpio_getpull_1up(struct samsung_gpio_chip *chip,
 146                                             unsigned int off)
 147{
 148        return s3c24xx_gpio_getpull_1(chip, off, S3C_GPIO_PULL_UP);
 149}
 150
 151int s3c24xx_gpio_setpull_1up(struct samsung_gpio_chip *chip,
 152                             unsigned int off, samsung_gpio_pull_t pull)
 153{
 154        return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_UP);
 155}
 156
 157samsung_gpio_pull_t s3c24xx_gpio_getpull_1down(struct samsung_gpio_chip *chip,
 158                                               unsigned int off)
 159{
 160        return s3c24xx_gpio_getpull_1(chip, off, S3C_GPIO_PULL_DOWN);
 161}
 162
 163int s3c24xx_gpio_setpull_1down(struct samsung_gpio_chip *chip,
 164                               unsigned int off, samsung_gpio_pull_t pull)
 165{
 166        return s3c24xx_gpio_setpull_1(chip, off, pull, S3C_GPIO_PULL_DOWN);
 167}
 168
 169static int exynos4_gpio_setpull(struct samsung_gpio_chip *chip,
 170                                unsigned int off, samsung_gpio_pull_t pull)
 171{
 172        if (pull == S3C_GPIO_PULL_UP)
 173                pull = 3;
 174
 175        return samsung_gpio_setpull_updown(chip, off, pull);
 176}
 177
 178static samsung_gpio_pull_t exynos4_gpio_getpull(struct samsung_gpio_chip *chip,
 179                                                unsigned int off)
 180{
 181        samsung_gpio_pull_t pull;
 182
 183        pull = samsung_gpio_getpull_updown(chip, off);
 184
 185        if (pull == 3)
 186                pull = S3C_GPIO_PULL_UP;
 187
 188        return pull;
 189}
 190
 191/*
 192 * samsung_gpio_setcfg_2bit - Samsung 2bit style GPIO configuration.
 193 * @chip: The gpio chip that is being configured.
 194 * @off: The offset for the GPIO being configured.
 195 * @cfg: The configuration value to set.
 196 *
 197 * This helper deal with the GPIO cases where the control register
 198 * has two bits of configuration per gpio, which have the following
 199 * functions:
 200 *      00 = input
 201 *      01 = output
 202 *      1x = special function
 203 */
 204
 205static int samsung_gpio_setcfg_2bit(struct samsung_gpio_chip *chip,
 206                                    unsigned int off, unsigned int cfg)
 207{
 208        void __iomem *reg = chip->base;
 209        unsigned int shift = off * 2;
 210        u32 con;
 211
 212        if (samsung_gpio_is_cfg_special(cfg)) {
 213                cfg &= 0xf;
 214                if (cfg > 3)
 215                        return -EINVAL;
 216
 217                cfg <<= shift;
 218        }
 219
 220        con = __raw_readl(reg);
 221        con &= ~(0x3 << shift);
 222        con |= cfg;
 223        __raw_writel(con, reg);
 224
 225        return 0;
 226}
 227
 228/*
 229 * samsung_gpio_getcfg_2bit - Samsung 2bit style GPIO configuration read.
 230 * @chip: The gpio chip that is being configured.
 231 * @off: The offset for the GPIO being configured.
 232 *
 233 * The reverse of samsung_gpio_setcfg_2bit(). Will return a value whicg
 234 * could be directly passed back to samsung_gpio_setcfg_2bit(), from the
 235 * S3C_GPIO_SPECIAL() macro.
 236 */
 237
 238static unsigned int samsung_gpio_getcfg_2bit(struct samsung_gpio_chip *chip,
 239                                             unsigned int off)
 240{
 241        u32 con;
 242
 243        con = __raw_readl(chip->base);
 244        con >>= off * 2;
 245        con &= 3;
 246
 247        /* this conversion works for IN and OUT as well as special mode */
 248        return S3C_GPIO_SPECIAL(con);
 249}
 250
 251/*
 252 * samsung_gpio_setcfg_4bit - Samsung 4bit single register GPIO config.
 253 * @chip: The gpio chip that is being configured.
 254 * @off: The offset for the GPIO being configured.
 255 * @cfg: The configuration value to set.
 256 *
 257 * This helper deal with the GPIO cases where the control register has 4 bits
 258 * of control per GPIO, generally in the form of:
 259 *      0000 = Input
 260 *      0001 = Output
 261 *      others = Special functions (dependent on bank)
 262 *
 263 * Note, since the code to deal with the case where there are two control
 264 * registers instead of one, we do not have a separate set of functions for
 265 * each case.
 266 */
 267
 268static int samsung_gpio_setcfg_4bit(struct samsung_gpio_chip *chip,
 269                                    unsigned int off, unsigned int cfg)
 270{
 271        void __iomem *reg = chip->base;
 272        unsigned int shift = (off & 7) * 4;
 273        u32 con;
 274
 275        if (off < 8 && chip->chip.ngpio > 8)
 276                reg -= 4;
 277
 278        if (samsung_gpio_is_cfg_special(cfg)) {
 279                cfg &= 0xf;
 280                cfg <<= shift;
 281        }
 282
 283        con = __raw_readl(reg);
 284        con &= ~(0xf << shift);
 285        con |= cfg;
 286        __raw_writel(con, reg);
 287
 288        return 0;
 289}
 290
 291/*
 292 * samsung_gpio_getcfg_4bit - Samsung 4bit single register GPIO config read.
 293 * @chip: The gpio chip that is being configured.
 294 * @off: The offset for the GPIO being configured.
 295 *
 296 * The reverse of samsung_gpio_setcfg_4bit(), turning a gpio configuration
 297 * register setting into a value the software can use, such as could be passed
 298 * to samsung_gpio_setcfg_4bit().
 299 *
 300 * @sa samsung_gpio_getcfg_2bit
 301 */
 302
 303static unsigned samsung_gpio_getcfg_4bit(struct samsung_gpio_chip *chip,
 304                                         unsigned int off)
 305{
 306        void __iomem *reg = chip->base;
 307        unsigned int shift = (off & 7) * 4;
 308        u32 con;
 309
 310        if (off < 8 && chip->chip.ngpio > 8)
 311                reg -= 4;
 312
 313        con = __raw_readl(reg);
 314        con >>= shift;
 315        con &= 0xf;
 316
 317        /* this conversion works for IN and OUT as well as special mode */
 318        return S3C_GPIO_SPECIAL(con);
 319}
 320
 321#ifdef CONFIG_PLAT_S3C24XX
 322/*
 323 * s3c24xx_gpio_setcfg_abank - S3C24XX style GPIO configuration (Bank A)
 324 * @chip: The gpio chip that is being configured.
 325 * @off: The offset for the GPIO being configured.
 326 * @cfg: The configuration value to set.
 327 *
 328 * This helper deal with the GPIO cases where the control register
 329 * has one bit of configuration for the gpio, where setting the bit
 330 * means the pin is in special function mode and unset means output.
 331 */
 332
 333static int s3c24xx_gpio_setcfg_abank(struct samsung_gpio_chip *chip,
 334                                     unsigned int off, unsigned int cfg)
 335{
 336        void __iomem *reg = chip->base;
 337        unsigned int shift = off;
 338        u32 con;
 339
 340        if (samsung_gpio_is_cfg_special(cfg)) {
 341                cfg &= 0xf;
 342
 343                /* Map output to 0, and SFN2 to 1 */
 344                cfg -= 1;
 345                if (cfg > 1)
 346                        return -EINVAL;
 347
 348                cfg <<= shift;
 349        }
 350
 351        con = __raw_readl(reg);
 352        con &= ~(0x1 << shift);
 353        con |= cfg;
 354        __raw_writel(con, reg);
 355
 356        return 0;
 357}
 358
 359/*
 360 * s3c24xx_gpio_getcfg_abank - S3C24XX style GPIO configuration read (Bank A)
 361 * @chip: The gpio chip that is being configured.
 362 * @off: The offset for the GPIO being configured.
 363 *
 364 * The reverse of s3c24xx_gpio_setcfg_abank() turning an GPIO into a usable
 365 * GPIO configuration value.
 366 *
 367 * @sa samsung_gpio_getcfg_2bit
 368 * @sa samsung_gpio_getcfg_4bit
 369 */
 370
 371static unsigned s3c24xx_gpio_getcfg_abank(struct samsung_gpio_chip *chip,
 372                                          unsigned int off)
 373{
 374        u32 con;
 375
 376        con = __raw_readl(chip->base);
 377        con >>= off;
 378        con &= 1;
 379        con++;
 380
 381        return S3C_GPIO_SFN(con);
 382}
 383#endif
 384
 385#if defined(CONFIG_CPU_S5P6440) || defined(CONFIG_CPU_S5P6450)
 386static int s5p64x0_gpio_setcfg_rbank(struct samsung_gpio_chip *chip,
 387                                     unsigned int off, unsigned int cfg)
 388{
 389        void __iomem *reg = chip->base;
 390        unsigned int shift;
 391        u32 con;
 392
 393        switch (off) {
 394        case 0:
 395        case 1:
 396        case 2:
 397        case 3:
 398        case 4:
 399        case 5:
 400                shift = (off & 7) * 4;
 401                reg -= 4;
 402                break;
 403        case 6:
 404                shift = ((off + 1) & 7) * 4;
 405                reg -= 4;
 406        default:
 407                shift = ((off + 1) & 7) * 4;
 408                break;
 409        }
 410
 411        if (samsung_gpio_is_cfg_special(cfg)) {
 412                cfg &= 0xf;
 413                cfg <<= shift;
 414        }
 415
 416        con = __raw_readl(reg);
 417        con &= ~(0xf << shift);
 418        con |= cfg;
 419        __raw_writel(con, reg);
 420
 421        return 0;
 422}
 423#endif
 424
 425static void __init samsung_gpiolib_set_cfg(struct samsung_gpio_cfg *chipcfg,
 426                                           int nr_chips)
 427{
 428        for (; nr_chips > 0; nr_chips--, chipcfg++) {
 429                if (!chipcfg->set_config)
 430                        chipcfg->set_config = samsung_gpio_setcfg_4bit;
 431                if (!chipcfg->get_config)
 432                        chipcfg->get_config = samsung_gpio_getcfg_4bit;
 433                if (!chipcfg->set_pull)
 434                        chipcfg->set_pull = samsung_gpio_setpull_updown;
 435                if (!chipcfg->get_pull)
 436                        chipcfg->get_pull = samsung_gpio_getpull_updown;
 437        }
 438}
 439
 440struct samsung_gpio_cfg s3c24xx_gpiocfg_default = {
 441        .set_config     = samsung_gpio_setcfg_2bit,
 442        .get_config     = samsung_gpio_getcfg_2bit,
 443};
 444
 445#ifdef CONFIG_PLAT_S3C24XX
 446static struct samsung_gpio_cfg s3c24xx_gpiocfg_banka = {
 447        .set_config     = s3c24xx_gpio_setcfg_abank,
 448        .get_config     = s3c24xx_gpio_getcfg_abank,
 449};
 450#endif
 451
 452static struct samsung_gpio_cfg exynos4_gpio_cfg = {
 453        .set_pull       = exynos4_gpio_setpull,
 454        .get_pull       = exynos4_gpio_getpull,
 455        .set_config     = samsung_gpio_setcfg_4bit,
 456        .get_config     = samsung_gpio_getcfg_4bit,
 457};
 458
 459#if defined(CONFIG_CPU_S5P6440) || defined(CONFIG_CPU_S5P6450)
 460static struct samsung_gpio_cfg s5p64x0_gpio_cfg_rbank = {
 461        .cfg_eint       = 0x3,
 462        .set_config     = s5p64x0_gpio_setcfg_rbank,
 463        .get_config     = samsung_gpio_getcfg_4bit,
 464        .set_pull       = samsung_gpio_setpull_updown,
 465        .get_pull       = samsung_gpio_getpull_updown,
 466};
 467#endif
 468
 469static struct samsung_gpio_cfg samsung_gpio_cfgs[] = {
 470        {
 471                .cfg_eint       = 0x0,
 472        }, {
 473                .cfg_eint       = 0x3,
 474        }, {
 475                .cfg_eint       = 0x7,
 476        }, {
 477                .cfg_eint       = 0xF,
 478        }, {
 479                .cfg_eint       = 0x0,
 480                .set_config     = samsung_gpio_setcfg_2bit,
 481                .get_config     = samsung_gpio_getcfg_2bit,
 482        }, {
 483                .cfg_eint       = 0x2,
 484                .set_config     = samsung_gpio_setcfg_2bit,
 485                .get_config     = samsung_gpio_getcfg_2bit,
 486        }, {
 487                .cfg_eint       = 0x3,
 488                .set_config     = samsung_gpio_setcfg_2bit,
 489                .get_config     = samsung_gpio_getcfg_2bit,
 490        }, {
 491                .set_config     = samsung_gpio_setcfg_2bit,
 492                .get_config     = samsung_gpio_getcfg_2bit,
 493        }, {
 494                .set_pull       = exynos4_gpio_setpull,
 495                .get_pull       = exynos4_gpio_getpull,
 496        }, {
 497                .cfg_eint       = 0x3,
 498                .set_pull       = exynos4_gpio_setpull,
 499                .get_pull       = exynos4_gpio_getpull,
 500        }
 501};
 502
 503/*
 504 * Default routines for controlling GPIO, based on the original S3C24XX
 505 * GPIO functions which deal with the case where each gpio bank of the
 506 * chip is as following:
 507 *
 508 * base + 0x00: Control register, 2 bits per gpio
 509 *              gpio n: 2 bits starting at (2*n)
 510 *              00 = input, 01 = output, others mean special-function
 511 * base + 0x04: Data register, 1 bit per gpio
 512 *              bit n: data bit n
 513*/
 514
 515static int samsung_gpiolib_2bit_input(struct gpio_chip *chip, unsigned offset)
 516{
 517        struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
 518        void __iomem *base = ourchip->base;
 519        unsigned long flags;
 520        unsigned long con;
 521
 522        samsung_gpio_lock(ourchip, flags);
 523
 524        con = __raw_readl(base + 0x00);
 525        con &= ~(3 << (offset * 2));
 526
 527        __raw_writel(con, base + 0x00);
 528
 529        samsung_gpio_unlock(ourchip, flags);
 530        return 0;
 531}
 532
 533static int samsung_gpiolib_2bit_output(struct gpio_chip *chip,
 534                                       unsigned offset, int value)
 535{
 536        struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
 537        void __iomem *base = ourchip->base;
 538        unsigned long flags;
 539        unsigned long dat;
 540        unsigned long con;
 541
 542        samsung_gpio_lock(ourchip, flags);
 543
 544        dat = __raw_readl(base + 0x04);
 545        dat &= ~(1 << offset);
 546        if (value)
 547                dat |= 1 << offset;
 548        __raw_writel(dat, base + 0x04);
 549
 550        con = __raw_readl(base + 0x00);
 551        con &= ~(3 << (offset * 2));
 552        con |= 1 << (offset * 2);
 553
 554        __raw_writel(con, base + 0x00);
 555        __raw_writel(dat, base + 0x04);
 556
 557        samsung_gpio_unlock(ourchip, flags);
 558        return 0;
 559}
 560
 561/*
 562 * The samsung_gpiolib_4bit routines are to control the gpio banks where
 563 * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
 564 * following example:
 565 *
 566 * base + 0x00: Control register, 4 bits per gpio
 567 *              gpio n: 4 bits starting at (4*n)
 568 *              0000 = input, 0001 = output, others mean special-function
 569 * base + 0x04: Data register, 1 bit per gpio
 570 *              bit n: data bit n
 571 *
 572 * Note, since the data register is one bit per gpio and is at base + 0x4
 573 * we can use samsung_gpiolib_get and samsung_gpiolib_set to change the
 574 * state of the output.
 575 */
 576
 577static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
 578                                      unsigned int offset)
 579{
 580        struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
 581        void __iomem *base = ourchip->base;
 582        unsigned long con;
 583
 584        con = __raw_readl(base + GPIOCON_OFF);
 585        con &= ~(0xf << con_4bit_shift(offset));
 586        __raw_writel(con, base + GPIOCON_OFF);
 587
 588        gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con);
 589
 590        return 0;
 591}
 592
 593static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
 594                                       unsigned int offset, int value)
 595{
 596        struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
 597        void __iomem *base = ourchip->base;
 598        unsigned long con;
 599        unsigned long dat;
 600
 601        con = __raw_readl(base + GPIOCON_OFF);
 602        con &= ~(0xf << con_4bit_shift(offset));
 603        con |= 0x1 << con_4bit_shift(offset);
 604
 605        dat = __raw_readl(base + GPIODAT_OFF);
 606
 607        if (value)
 608                dat |= 1 << offset;
 609        else
 610                dat &= ~(1 << offset);
 611
 612        __raw_writel(dat, base + GPIODAT_OFF);
 613        __raw_writel(con, base + GPIOCON_OFF);
 614        __raw_writel(dat, base + GPIODAT_OFF);
 615
 616        gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
 617
 618        return 0;
 619}
 620
 621/*
 622 * The next set of routines are for the case where the GPIO configuration
 623 * registers are 4 bits per GPIO but there is more than one register (the
 624 * bank has more than 8 GPIOs.
 625 *
 626 * This case is the similar to the 4 bit case, but the registers are as
 627 * follows:
 628 *
 629 * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
 630 *              gpio n: 4 bits starting at (4*n)
 631 *              0000 = input, 0001 = output, others mean special-function
 632 * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
 633 *              gpio n: 4 bits starting at (4*n)
 634 *              0000 = input, 0001 = output, others mean special-function
 635 * base + 0x08: Data register, 1 bit per gpio
 636 *              bit n: data bit n
 637 *
 638 * To allow us to use the samsung_gpiolib_get and samsung_gpiolib_set
 639 * routines we store the 'base + 0x4' address so that these routines see
 640 * the data register at ourchip->base + 0x04.
 641 */
 642
 643static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
 644                                       unsigned int offset)
 645{
 646        struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
 647        void __iomem *base = ourchip->base;
 648        void __iomem *regcon = base;
 649        unsigned long con;
 650
 651        if (offset > 7)
 652                offset -= 8;
 653        else
 654                regcon -= 4;
 655
 656        con = __raw_readl(regcon);
 657        con &= ~(0xf << con_4bit_shift(offset));
 658        __raw_writel(con, regcon);
 659
 660        gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con);
 661
 662        return 0;
 663}
 664
 665static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
 666                                        unsigned int offset, int value)
 667{
 668        struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
 669        void __iomem *base = ourchip->base;
 670        void __iomem *regcon = base;
 671        unsigned long con;
 672        unsigned long dat;
 673        unsigned con_offset = offset;
 674
 675        if (con_offset > 7)
 676                con_offset -= 8;
 677        else
 678                regcon -= 4;
 679
 680        con = __raw_readl(regcon);
 681        con &= ~(0xf << con_4bit_shift(con_offset));
 682        con |= 0x1 << con_4bit_shift(con_offset);
 683
 684        dat = __raw_readl(base + GPIODAT_OFF);
 685
 686        if (value)
 687                dat |= 1 << offset;
 688        else
 689                dat &= ~(1 << offset);
 690
 691        __raw_writel(dat, base + GPIODAT_OFF);
 692        __raw_writel(con, regcon);
 693        __raw_writel(dat, base + GPIODAT_OFF);
 694
 695        gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
 696
 697        return 0;
 698}
 699
 700#ifdef CONFIG_PLAT_S3C24XX
 701/* The next set of routines are for the case of s3c24xx bank a */
 702
 703static int s3c24xx_gpiolib_banka_input(struct gpio_chip *chip, unsigned offset)
 704{
 705        return -EINVAL;
 706}
 707
 708static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip,
 709                                        unsigned offset, int value)
 710{
 711        struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
 712        void __iomem *base = ourchip->base;
 713        unsigned long flags;
 714        unsigned long dat;
 715        unsigned long con;
 716
 717        local_irq_save(flags);
 718
 719        con = __raw_readl(base + 0x00);
 720        dat = __raw_readl(base + 0x04);
 721
 722        dat &= ~(1 << offset);
 723        if (value)
 724                dat |= 1 << offset;
 725
 726        __raw_writel(dat, base + 0x04);
 727
 728        con &= ~(1 << offset);
 729
 730        __raw_writel(con, base + 0x00);
 731        __raw_writel(dat, base + 0x04);
 732
 733        local_irq_restore(flags);
 734        return 0;
 735}
 736#endif
 737
 738/* The next set of routines are for the case of s5p64x0 bank r */
 739
 740static int s5p64x0_gpiolib_rbank_input(struct gpio_chip *chip,
 741                                       unsigned int offset)
 742{
 743        struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
 744        void __iomem *base = ourchip->base;
 745        void __iomem *regcon = base;
 746        unsigned long con;
 747        unsigned long flags;
 748
 749        switch (offset) {
 750        case 6:
 751                offset += 1;
 752        case 0:
 753        case 1:
 754        case 2:
 755        case 3:
 756        case 4:
 757        case 5:
 758                regcon -= 4;
 759                break;
 760        default:
 761                offset -= 7;
 762                break;
 763        }
 764
 765        samsung_gpio_lock(ourchip, flags);
 766
 767        con = __raw_readl(regcon);
 768        con &= ~(0xf << con_4bit_shift(offset));
 769        __raw_writel(con, regcon);
 770
 771        samsung_gpio_unlock(ourchip, flags);
 772
 773        return 0;
 774}
 775
 776static int s5p64x0_gpiolib_rbank_output(struct gpio_chip *chip,
 777                                        unsigned int offset, int value)
 778{
 779        struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
 780        void __iomem *base = ourchip->base;
 781        void __iomem *regcon = base;
 782        unsigned long con;
 783        unsigned long dat;
 784        unsigned long flags;
 785        unsigned con_offset  = offset;
 786
 787        switch (con_offset) {
 788        case 6:
 789                con_offset += 1;
 790        case 0:
 791        case 1:
 792        case 2:
 793        case 3:
 794        case 4:
 795        case 5:
 796                regcon -= 4;
 797                break;
 798        default:
 799                con_offset -= 7;
 800                break;
 801        }
 802
 803        samsung_gpio_lock(ourchip, flags);
 804
 805        con = __raw_readl(regcon);
 806        con &= ~(0xf << con_4bit_shift(con_offset));
 807        con |= 0x1 << con_4bit_shift(con_offset);
 808
 809        dat = __raw_readl(base + GPIODAT_OFF);
 810        if (value)
 811                dat |= 1 << offset;
 812        else
 813                dat &= ~(1 << offset);
 814
 815        __raw_writel(con, regcon);
 816        __raw_writel(dat, base + GPIODAT_OFF);
 817
 818        samsung_gpio_unlock(ourchip, flags);
 819
 820        return 0;
 821}
 822
 823static void samsung_gpiolib_set(struct gpio_chip *chip,
 824                                unsigned offset, int value)
 825{
 826        struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
 827        void __iomem *base = ourchip->base;
 828        unsigned long flags;
 829        unsigned long dat;
 830
 831        samsung_gpio_lock(ourchip, flags);
 832
 833        dat = __raw_readl(base + 0x04);
 834        dat &= ~(1 << offset);
 835        if (value)
 836                dat |= 1 << offset;
 837        __raw_writel(dat, base + 0x04);
 838
 839        samsung_gpio_unlock(ourchip, flags);
 840}
 841
 842static int samsung_gpiolib_get(struct gpio_chip *chip, unsigned offset)
 843{
 844        struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
 845        unsigned long val;
 846
 847        val = __raw_readl(ourchip->base + 0x04);
 848        val >>= offset;
 849        val &= 1;
 850
 851        return val;
 852}
 853
 854/*
 855 * CONFIG_S3C_GPIO_TRACK enables the tracking of the s3c specific gpios
 856 * for use with the configuration calls, and other parts of the s3c gpiolib
 857 * support code.
 858 *
 859 * Not all s3c support code will need this, as some configurations of cpu
 860 * may only support one or two different configuration options and have an
 861 * easy gpio to samsung_gpio_chip mapping function. If this is the case, then
 862 * the machine support file should provide its own samsung_gpiolib_getchip()
 863 * and any other necessary functions.
 864 */
 865
 866#ifdef CONFIG_S3C_GPIO_TRACK
 867struct samsung_gpio_chip *s3c_gpios[S3C_GPIO_END];
 868
 869static __init void s3c_gpiolib_track(struct samsung_gpio_chip *chip)
 870{
 871        unsigned int gpn;
 872        int i;
 873
 874        gpn = chip->chip.base;
 875        for (i = 0; i < chip->chip.ngpio; i++, gpn++) {
 876                BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios));
 877                s3c_gpios[gpn] = chip;
 878        }
 879}
 880#endif /* CONFIG_S3C_GPIO_TRACK */
 881
 882/*
 883 * samsung_gpiolib_add() - add the Samsung gpio_chip.
 884 * @chip: The chip to register
 885 *
 886 * This is a wrapper to gpiochip_add() that takes our specific gpio chip
 887 * information and makes the necessary alterations for the platform and
 888 * notes the information for use with the configuration systems and any
 889 * other parts of the system.
 890 */
 891
 892static void __init samsung_gpiolib_add(struct samsung_gpio_chip *chip)
 893{
 894        struct gpio_chip *gc = &chip->chip;
 895        int ret;
 896
 897        BUG_ON(!chip->base);
 898        BUG_ON(!gc->label);
 899        BUG_ON(!gc->ngpio);
 900
 901        spin_lock_init(&chip->lock);
 902
 903        if (!gc->direction_input)
 904                gc->direction_input = samsung_gpiolib_2bit_input;
 905        if (!gc->direction_output)
 906                gc->direction_output = samsung_gpiolib_2bit_output;
 907        if (!gc->set)
 908                gc->set = samsung_gpiolib_set;
 909        if (!gc->get)
 910                gc->get = samsung_gpiolib_get;
 911
 912#ifdef CONFIG_PM
 913        if (chip->pm != NULL) {
 914                if (!chip->pm->save || !chip->pm->resume)
 915                        printk(KERN_ERR "gpio: %s has missing PM functions\n",
 916                               gc->label);
 917        } else
 918                printk(KERN_ERR "gpio: %s has no PM function\n", gc->label);
 919#endif
 920
 921        /* gpiochip_add() prints own failure message on error. */
 922        ret = gpiochip_add(gc);
 923        if (ret >= 0)
 924                s3c_gpiolib_track(chip);
 925}
 926
 927static void __init s3c24xx_gpiolib_add_chips(struct samsung_gpio_chip *chip,
 928                                             int nr_chips, void __iomem *base)
 929{
 930        int i;
 931        struct gpio_chip *gc = &chip->chip;
 932
 933        for (i = 0 ; i < nr_chips; i++, chip++) {
 934                /* skip banks not present on SoC */
 935                if (chip->chip.base >= S3C_GPIO_END)
 936                        continue;
 937
 938                if (!chip->config)
 939                        chip->config = &s3c24xx_gpiocfg_default;
 940                if (!chip->pm)
 941                        chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
 942                if ((base != NULL) && (chip->base == NULL))
 943                        chip->base = base + ((i) * 0x10);
 944
 945                if (!gc->direction_input)
 946                        gc->direction_input = samsung_gpiolib_2bit_input;
 947                if (!gc->direction_output)
 948                        gc->direction_output = samsung_gpiolib_2bit_output;
 949
 950                samsung_gpiolib_add(chip);
 951        }
 952}
 953
 954static void __init samsung_gpiolib_add_2bit_chips(struct samsung_gpio_chip *chip,
 955                                                  int nr_chips, void __iomem *base,
 956                                                  unsigned int offset)
 957{
 958        int i;
 959
 960        for (i = 0 ; i < nr_chips; i++, chip++) {
 961                chip->chip.direction_input = samsung_gpiolib_2bit_input;
 962                chip->chip.direction_output = samsung_gpiolib_2bit_output;
 963
 964                if (!chip->config)
 965                        chip->config = &samsung_gpio_cfgs[7];
 966                if (!chip->pm)
 967                        chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
 968                if ((base != NULL) && (chip->base == NULL))
 969                        chip->base = base + ((i) * offset);
 970
 971                samsung_gpiolib_add(chip);
 972        }
 973}
 974
 975/*
 976 * samsung_gpiolib_add_4bit_chips - 4bit single register GPIO config.
 977 * @chip: The gpio chip that is being configured.
 978 * @nr_chips: The no of chips (gpio ports) for the GPIO being configured.
 979 *
 980 * This helper deal with the GPIO cases where the control register has 4 bits
 981 * of control per GPIO, generally in the form of:
 982 * 0000 = Input
 983 * 0001 = Output
 984 * others = Special functions (dependent on bank)
 985 *
 986 * Note, since the code to deal with the case where there are two control
 987 * registers instead of one, we do not have a separate set of function
 988 * (samsung_gpiolib_add_4bit2_chips)for each case.
 989 */
 990
 991static void __init samsung_gpiolib_add_4bit_chips(struct samsung_gpio_chip *chip,
 992                                                  int nr_chips, void __iomem *base)
 993{
 994        int i;
 995
 996        for (i = 0 ; i < nr_chips; i++, chip++) {
 997                chip->chip.direction_input = samsung_gpiolib_4bit_input;
 998                chip->chip.direction_output = samsung_gpiolib_4bit_output;
 999
1000                if (!chip->config)
1001                        chip->config = &samsung_gpio_cfgs[2];
1002                if (!chip->pm)
1003                        chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
1004                if ((base != NULL) && (chip->base == NULL))
1005                        chip->base = base + ((i) * 0x20);
1006
1007                samsung_gpiolib_add(chip);
1008        }
1009}
1010
1011static void __init samsung_gpiolib_add_4bit2_chips(struct samsung_gpio_chip *chip,
1012                                                   int nr_chips)
1013{
1014        for (; nr_chips > 0; nr_chips--, chip++) {
1015                chip->chip.direction_input = samsung_gpiolib_4bit2_input;
1016                chip->chip.direction_output = samsung_gpiolib_4bit2_output;
1017
1018                if (!chip->config)
1019                        chip->config = &samsung_gpio_cfgs[2];
1020                if (!chip->pm)
1021                        chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
1022
1023                samsung_gpiolib_add(chip);
1024        }
1025}
1026
1027static void __init s5p64x0_gpiolib_add_rbank(struct samsung_gpio_chip *chip,
1028                                             int nr_chips)
1029{
1030        for (; nr_chips > 0; nr_chips--, chip++) {
1031                chip->chip.direction_input = s5p64x0_gpiolib_rbank_input;
1032                chip->chip.direction_output = s5p64x0_gpiolib_rbank_output;
1033
1034                if (!chip->pm)
1035                        chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
1036
1037                samsung_gpiolib_add(chip);
1038        }
1039}
1040
1041int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
1042{
1043        struct samsung_gpio_chip *samsung_chip = container_of(chip, struct samsung_gpio_chip, chip);
1044
1045        return samsung_chip->irq_base + offset;
1046}
1047
1048#ifdef CONFIG_PLAT_S3C24XX
1049static int s3c24xx_gpiolib_fbank_to_irq(struct gpio_chip *chip, unsigned offset)
1050{
1051        if (offset < 4)
1052                return IRQ_EINT0 + offset;
1053
1054        if (offset < 8)
1055                return IRQ_EINT4 + offset - 4;
1056
1057        return -EINVAL;
1058}
1059#endif
1060
1061#ifdef CONFIG_PLAT_S3C64XX
1062static int s3c64xx_gpiolib_mbank_to_irq(struct gpio_chip *chip, unsigned pin)
1063{
1064        return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO;
1065}
1066
1067static int s3c64xx_gpiolib_lbank_to_irq(struct gpio_chip *chip, unsigned pin)
1068{
1069        return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO;
1070}
1071#endif
1072
1073struct samsung_gpio_chip s3c24xx_gpios[] = {
1074#ifdef CONFIG_PLAT_S3C24XX
1075        {
1076                .config = &s3c24xx_gpiocfg_banka,
1077                .chip   = {
1078                        .base                   = S3C2410_GPA(0),
1079                        .owner                  = THIS_MODULE,
1080                        .label                  = "GPIOA",
1081                        .ngpio                  = 24,
1082                        .direction_input        = s3c24xx_gpiolib_banka_input,
1083                        .direction_output       = s3c24xx_gpiolib_banka_output,
1084                },
1085        }, {
1086                .chip   = {
1087                        .base   = S3C2410_GPB(0),
1088                        .owner  = THIS_MODULE,
1089                        .label  = "GPIOB",
1090                        .ngpio  = 16,
1091                },
1092        }, {
1093                .chip   = {
1094                        .base   = S3C2410_GPC(0),
1095                        .owner  = THIS_MODULE,
1096                        .label  = "GPIOC",
1097                        .ngpio  = 16,
1098                },
1099        }, {
1100                .chip   = {
1101                        .base   = S3C2410_GPD(0),
1102                        .owner  = THIS_MODULE,
1103                        .label  = "GPIOD",
1104                        .ngpio  = 16,
1105                },
1106        }, {
1107                .chip   = {
1108                        .base   = S3C2410_GPE(0),
1109                        .label  = "GPIOE",
1110                        .owner  = THIS_MODULE,
1111                        .ngpio  = 16,
1112                },
1113        }, {
1114                .chip   = {
1115                        .base   = S3C2410_GPF(0),
1116                        .owner  = THIS_MODULE,
1117                        .label  = "GPIOF",
1118                        .ngpio  = 8,
1119                        .to_irq = s3c24xx_gpiolib_fbank_to_irq,
1120                },
1121        }, {
1122                .irq_base = IRQ_EINT8,
1123                .chip   = {
1124                        .base   = S3C2410_GPG(0),
1125                        .owner  = THIS_MODULE,
1126                        .label  = "GPIOG",
1127                        .ngpio  = 16,
1128                        .to_irq = samsung_gpiolib_to_irq,
1129                },
1130        }, {
1131                .chip   = {
1132                        .base   = S3C2410_GPH(0),
1133                        .owner  = THIS_MODULE,
1134                        .label  = "GPIOH",
1135                        .ngpio  = 11,
1136                },
1137        },
1138                /* GPIOS for the S3C2443 and later devices. */
1139        {
1140                .base   = S3C2440_GPJCON,
1141                .chip   = {
1142                        .base   = S3C2410_GPJ(0),
1143                        .owner  = THIS_MODULE,
1144                        .label  = "GPIOJ",
1145                        .ngpio  = 16,
1146                },
1147        }, {
1148                .base   = S3C2443_GPKCON,
1149                .chip   = {
1150                        .base   = S3C2410_GPK(0),
1151                        .owner  = THIS_MODULE,
1152                        .label  = "GPIOK",
1153                        .ngpio  = 16,
1154                },
1155        }, {
1156                .base   = S3C2443_GPLCON,
1157                .chip   = {
1158                        .base   = S3C2410_GPL(0),
1159                        .owner  = THIS_MODULE,
1160                        .label  = "GPIOL",
1161                        .ngpio  = 15,
1162                },
1163        }, {
1164                .base   = S3C2443_GPMCON,
1165                .chip   = {
1166                        .base   = S3C2410_GPM(0),
1167                        .owner  = THIS_MODULE,
1168                        .label  = "GPIOM",
1169                        .ngpio  = 2,
1170                },
1171        },
1172#endif
1173};
1174
1175/*
1176 * GPIO bank summary:
1177 *
1178 * Bank GPIOs   Style   SlpCon  ExtInt Group
1179 * A    8       4Bit    Yes     1
1180 * B    7       4Bit    Yes     1
1181 * C    8       4Bit    Yes     2
1182 * D    5       4Bit    Yes     3
1183 * E    5       4Bit    Yes     None
1184 * F    16      2Bit    Yes     4 [1]
1185 * G    7       4Bit    Yes     5
1186 * H    10      4Bit[2] Yes     6
1187 * I    16      2Bit    Yes     None
1188 * J    12      2Bit    Yes     None
1189 * K    16      4Bit[2] No      None
1190 * L    15      4Bit[2] No      None
1191 * M    6       4Bit    No      IRQ_EINT
1192 * N    16      2Bit    No      IRQ_EINT
1193 * O    16      2Bit    Yes     7
1194 * P    15      2Bit    Yes     8
1195 * Q    9       2Bit    Yes     9
1196 *
1197 * [1] BANKF pins 14,15 do not form part of the external interrupt sources
1198 * [2] BANK has two control registers, GPxCON0 and GPxCON1
1199 */
1200
1201static struct samsung_gpio_chip s3c64xx_gpios_4bit[] = {
1202#ifdef CONFIG_PLAT_S3C64XX
1203        {
1204                .chip   = {
1205                        .base   = S3C64XX_GPA(0),
1206                        .ngpio  = S3C64XX_GPIO_A_NR,
1207                        .label  = "GPA",
1208                },
1209        }, {
1210                .chip   = {
1211                        .base   = S3C64XX_GPB(0),
1212                        .ngpio  = S3C64XX_GPIO_B_NR,
1213                        .label  = "GPB",
1214                },
1215        }, {
1216                .chip   = {
1217                        .base   = S3C64XX_GPC(0),
1218                        .ngpio  = S3C64XX_GPIO_C_NR,
1219                        .label  = "GPC",
1220                },
1221        }, {
1222                .chip   = {
1223                        .base   = S3C64XX_GPD(0),
1224                        .ngpio  = S3C64XX_GPIO_D_NR,
1225                        .label  = "GPD",
1226                },
1227        }, {
1228                .config = &samsung_gpio_cfgs[0],
1229                .chip   = {
1230                        .base   = S3C64XX_GPE(0),
1231                        .ngpio  = S3C64XX_GPIO_E_NR,
1232                        .label  = "GPE",
1233                },
1234        }, {
1235                .base   = S3C64XX_GPG_BASE,
1236                .chip   = {
1237                        .base   = S3C64XX_GPG(0),
1238                        .ngpio  = S3C64XX_GPIO_G_NR,
1239                        .label  = "GPG",
1240                },
1241        }, {
1242                .base   = S3C64XX_GPM_BASE,
1243                .config = &samsung_gpio_cfgs[1],
1244                .chip   = {
1245                        .base   = S3C64XX_GPM(0),
1246                        .ngpio  = S3C64XX_GPIO_M_NR,
1247                        .label  = "GPM",
1248                        .to_irq = s3c64xx_gpiolib_mbank_to_irq,
1249                },
1250        },
1251#endif
1252};
1253
1254static struct samsung_gpio_chip s3c64xx_gpios_4bit2[] = {
1255#ifdef CONFIG_PLAT_S3C64XX
1256        {
1257                .base   = S3C64XX_GPH_BASE + 0x4,
1258                .chip   = {
1259                        .base   = S3C64XX_GPH(0),
1260                        .ngpio  = S3C64XX_GPIO_H_NR,
1261                        .label  = "GPH",
1262                },
1263        }, {
1264                .base   = S3C64XX_GPK_BASE + 0x4,
1265                .config = &samsung_gpio_cfgs[0],
1266                .chip   = {
1267                        .base   = S3C64XX_GPK(0),
1268                        .ngpio  = S3C64XX_GPIO_K_NR,
1269                        .label  = "GPK",
1270                },
1271        }, {
1272                .base   = S3C64XX_GPL_BASE + 0x4,
1273                .config = &samsung_gpio_cfgs[1],
1274                .chip   = {
1275                        .base   = S3C64XX_GPL(0),
1276                        .ngpio  = S3C64XX_GPIO_L_NR,
1277                        .label  = "GPL",
1278                        .to_irq = s3c64xx_gpiolib_lbank_to_irq,
1279                },
1280        },
1281#endif
1282};
1283
1284static struct samsung_gpio_chip s3c64xx_gpios_2bit[] = {
1285#ifdef CONFIG_PLAT_S3C64XX
1286        {
1287                .base   = S3C64XX_GPF_BASE,
1288                .config = &samsung_gpio_cfgs[6],
1289                .chip   = {
1290                        .base   = S3C64XX_GPF(0),
1291                        .ngpio  = S3C64XX_GPIO_F_NR,
1292                        .label  = "GPF",
1293                },
1294        }, {
1295                .config = &samsung_gpio_cfgs[7],
1296                .chip   = {
1297                        .base   = S3C64XX_GPI(0),
1298                        .ngpio  = S3C64XX_GPIO_I_NR,
1299                        .label  = "GPI",
1300                },
1301        }, {
1302                .config = &samsung_gpio_cfgs[7],
1303                .chip   = {
1304                        .base   = S3C64XX_GPJ(0),
1305                        .ngpio  = S3C64XX_GPIO_J_NR,
1306                        .label  = "GPJ",
1307                },
1308        }, {
1309                .config = &samsung_gpio_cfgs[6],
1310                .chip   = {
1311                        .base   = S3C64XX_GPO(0),
1312                        .ngpio  = S3C64XX_GPIO_O_NR,
1313                        .label  = "GPO",
1314                },
1315        }, {
1316                .config = &samsung_gpio_cfgs[6],
1317                .chip   = {
1318                        .base   = S3C64XX_GPP(0),
1319                        .ngpio  = S3C64XX_GPIO_P_NR,
1320                        .label  = "GPP",
1321                },
1322        }, {
1323                .config = &samsung_gpio_cfgs[6],
1324                .chip   = {
1325                        .base   = S3C64XX_GPQ(0),
1326                        .ngpio  = S3C64XX_GPIO_Q_NR,
1327                        .label  = "GPQ",
1328                },
1329        }, {
1330                .base   = S3C64XX_GPN_BASE,
1331                .irq_base = IRQ_EINT(0),
1332                .config = &samsung_gpio_cfgs[5],
1333                .chip   = {
1334                        .base   = S3C64XX_GPN(0),
1335                        .ngpio  = S3C64XX_GPIO_N_NR,
1336                        .label  = "GPN",
1337                        .to_irq = samsung_gpiolib_to_irq,
1338                },
1339        },
1340#endif
1341};
1342
1343/*
1344 * S5P6440 GPIO bank summary:
1345 *
1346 * Bank GPIOs   Style   SlpCon  ExtInt Group
1347 * A    6       4Bit    Yes     1
1348 * B    7       4Bit    Yes     1
1349 * C    8       4Bit    Yes     2
1350 * F    2       2Bit    Yes     4 [1]
1351 * G    7       4Bit    Yes     5
1352 * H    10      4Bit[2] Yes     6
1353 * I    16      2Bit    Yes     None
1354 * J    12      2Bit    Yes     None
1355 * N    16      2Bit    No      IRQ_EINT
1356 * P    8       2Bit    Yes     8
1357 * R    15      4Bit[2] Yes     8
1358 */
1359
1360static struct samsung_gpio_chip s5p6440_gpios_4bit[] = {
1361#ifdef CONFIG_CPU_S5P6440
1362        {
1363                .chip   = {
1364                        .base   = S5P6440_GPA(0),
1365                        .ngpio  = S5P6440_GPIO_A_NR,
1366                        .label  = "GPA",
1367                },
1368        }, {
1369                .chip   = {
1370                        .base   = S5P6440_GPB(0),
1371                        .ngpio  = S5P6440_GPIO_B_NR,
1372                        .label  = "GPB",
1373                },
1374        }, {
1375                .chip   = {
1376                        .base   = S5P6440_GPC(0),
1377                        .ngpio  = S5P6440_GPIO_C_NR,
1378                        .label  = "GPC",
1379                },
1380        }, {
1381                .base   = S5P64X0_GPG_BASE,
1382                .chip   = {
1383                        .base   = S5P6440_GPG(0),
1384                        .ngpio  = S5P6440_GPIO_G_NR,
1385                        .label  = "GPG",
1386                },
1387        },
1388#endif
1389};
1390
1391static struct samsung_gpio_chip s5p6440_gpios_4bit2[] = {
1392#ifdef CONFIG_CPU_S5P6440
1393        {
1394                .base   = S5P64X0_GPH_BASE + 0x4,
1395                .chip   = {
1396                        .base   = S5P6440_GPH(0),
1397                        .ngpio  = S5P6440_GPIO_H_NR,
1398                        .label  = "GPH",
1399                },
1400        },
1401#endif
1402};
1403
1404static struct samsung_gpio_chip s5p6440_gpios_rbank[] = {
1405#ifdef CONFIG_CPU_S5P6440
1406        {
1407                .base   = S5P64X0_GPR_BASE + 0x4,
1408                .config = &s5p64x0_gpio_cfg_rbank,
1409                .chip   = {
1410                        .base   = S5P6440_GPR(0),
1411                        .ngpio  = S5P6440_GPIO_R_NR,
1412                        .label  = "GPR",
1413                },
1414        },
1415#endif
1416};
1417
1418static struct samsung_gpio_chip s5p6440_gpios_2bit[] = {
1419#ifdef CONFIG_CPU_S5P6440
1420        {
1421                .base   = S5P64X0_GPF_BASE,
1422                .config = &samsung_gpio_cfgs[6],
1423                .chip   = {
1424                        .base   = S5P6440_GPF(0),
1425                        .ngpio  = S5P6440_GPIO_F_NR,
1426                        .label  = "GPF",
1427                },
1428        }, {
1429                .base   = S5P64X0_GPI_BASE,
1430                .config = &samsung_gpio_cfgs[4],
1431                .chip   = {
1432                        .base   = S5P6440_GPI(0),
1433                        .ngpio  = S5P6440_GPIO_I_NR,
1434                        .label  = "GPI",
1435                },
1436        }, {
1437                .base   = S5P64X0_GPJ_BASE,
1438                .config = &samsung_gpio_cfgs[4],
1439                .chip   = {
1440                        .base   = S5P6440_GPJ(0),
1441                        .ngpio  = S5P6440_GPIO_J_NR,
1442                        .label  = "GPJ",
1443                },
1444        }, {
1445                .base   = S5P64X0_GPN_BASE,
1446                .config = &samsung_gpio_cfgs[5],
1447                .chip   = {
1448                        .base   = S5P6440_GPN(0),
1449                        .ngpio  = S5P6440_GPIO_N_NR,
1450                        .label  = "GPN",
1451                },
1452        }, {
1453                .base   = S5P64X0_GPP_BASE,
1454                .config = &samsung_gpio_cfgs[6],
1455                .chip   = {
1456                        .base   = S5P6440_GPP(0),
1457                        .ngpio  = S5P6440_GPIO_P_NR,
1458                        .label  = "GPP",
1459                },
1460        },
1461#endif
1462};
1463
1464/*
1465 * S5P6450 GPIO bank summary:
1466 *
1467 * Bank GPIOs   Style   SlpCon  ExtInt Group
1468 * A    6       4Bit    Yes     1
1469 * B    7       4Bit    Yes     1
1470 * C    8       4Bit    Yes     2
1471 * D    8       4Bit    Yes     None
1472 * F    2       2Bit    Yes     None
1473 * G    14      4Bit[2] Yes     5
1474 * H    10      4Bit[2] Yes     6
1475 * I    16      2Bit    Yes     None
1476 * J    12      2Bit    Yes     None
1477 * K    5       4Bit    Yes     None
1478 * N    16      2Bit    No      IRQ_EINT
1479 * P    11      2Bit    Yes     8
1480 * Q    14      2Bit    Yes     None
1481 * R    15      4Bit[2] Yes     None
1482 * S    8       2Bit    Yes     None
1483 *
1484 * [1] BANKF pins 14,15 do not form part of the external interrupt sources
1485 * [2] BANK has two control registers, GPxCON0 and GPxCON1
1486 */
1487
1488static struct samsung_gpio_chip s5p6450_gpios_4bit[] = {
1489#ifdef CONFIG_CPU_S5P6450
1490        {
1491                .chip   = {
1492                        .base   = S5P6450_GPA(0),
1493                        .ngpio  = S5P6450_GPIO_A_NR,
1494                        .label  = "GPA",
1495                },
1496        }, {
1497                .chip   = {
1498                        .base   = S5P6450_GPB(0),
1499                        .ngpio  = S5P6450_GPIO_B_NR,
1500                        .label  = "GPB",
1501                },
1502        }, {
1503                .chip   = {
1504                        .base   = S5P6450_GPC(0),
1505                        .ngpio  = S5P6450_GPIO_C_NR,
1506                        .label  = "GPC",
1507                },
1508        }, {
1509                .chip   = {
1510                        .base   = S5P6450_GPD(0),
1511                        .ngpio  = S5P6450_GPIO_D_NR,
1512                        .label  = "GPD",
1513                },
1514        }, {
1515                .base   = S5P6450_GPK_BASE,
1516                .chip   = {
1517                        .base   = S5P6450_GPK(0),
1518                        .ngpio  = S5P6450_GPIO_K_NR,
1519                        .label  = "GPK",
1520                },
1521        },
1522#endif
1523};
1524
1525static struct samsung_gpio_chip s5p6450_gpios_4bit2[] = {
1526#ifdef CONFIG_CPU_S5P6450
1527        {
1528                .base   = S5P64X0_GPG_BASE + 0x4,
1529                .chip   = {
1530                        .base   = S5P6450_GPG(0),
1531                        .ngpio  = S5P6450_GPIO_G_NR,
1532                        .label  = "GPG",
1533                },
1534        }, {
1535                .base   = S5P64X0_GPH_BASE + 0x4,
1536                .chip   = {
1537                        .base   = S5P6450_GPH(0),
1538                        .ngpio  = S5P6450_GPIO_H_NR,
1539                        .label  = "GPH",
1540                },
1541        },
1542#endif
1543};
1544
1545static struct samsung_gpio_chip s5p6450_gpios_rbank[] = {
1546#ifdef CONFIG_CPU_S5P6450
1547        {
1548                .base   = S5P64X0_GPR_BASE + 0x4,
1549                .config = &s5p64x0_gpio_cfg_rbank,
1550                .chip   = {
1551                        .base   = S5P6450_GPR(0),
1552                        .ngpio  = S5P6450_GPIO_R_NR,
1553                        .label  = "GPR",
1554                },
1555        },
1556#endif
1557};
1558
1559static struct samsung_gpio_chip s5p6450_gpios_2bit[] = {
1560#ifdef CONFIG_CPU_S5P6450
1561        {
1562                .base   = S5P64X0_GPF_BASE,
1563                .config = &samsung_gpio_cfgs[6],
1564                .chip   = {
1565                        .base   = S5P6450_GPF(0),
1566                        .ngpio  = S5P6450_GPIO_F_NR,
1567                        .label  = "GPF",
1568                },
1569        }, {
1570                .base   = S5P64X0_GPI_BASE,
1571                .config = &samsung_gpio_cfgs[4],
1572                .chip   = {
1573                        .base   = S5P6450_GPI(0),
1574                        .ngpio  = S5P6450_GPIO_I_NR,
1575                        .label  = "GPI",
1576                },
1577        }, {
1578                .base   = S5P64X0_GPJ_BASE,
1579                .config = &samsung_gpio_cfgs[4],
1580                .chip   = {
1581                        .base   = S5P6450_GPJ(0),
1582                        .ngpio  = S5P6450_GPIO_J_NR,
1583                        .label  = "GPJ",
1584                },
1585        }, {
1586                .base   = S5P64X0_GPN_BASE,
1587                .config = &samsung_gpio_cfgs[5],
1588                .chip   = {
1589                        .base   = S5P6450_GPN(0),
1590                        .ngpio  = S5P6450_GPIO_N_NR,
1591                        .label  = "GPN",
1592                },
1593        }, {
1594                .base   = S5P64X0_GPP_BASE,
1595                .config = &samsung_gpio_cfgs[6],
1596                .chip   = {
1597                        .base   = S5P6450_GPP(0),
1598                        .ngpio  = S5P6450_GPIO_P_NR,
1599                        .label  = "GPP",
1600                },
1601        }, {
1602                .base   = S5P6450_GPQ_BASE,
1603                .config = &samsung_gpio_cfgs[5],
1604                .chip   = {
1605                        .base   = S5P6450_GPQ(0),
1606                        .ngpio  = S5P6450_GPIO_Q_NR,
1607                        .label  = "GPQ",
1608                },
1609        }, {
1610                .base   = S5P6450_GPS_BASE,
1611                .config = &samsung_gpio_cfgs[6],
1612                .chip   = {
1613                        .base   = S5P6450_GPS(0),
1614                        .ngpio  = S5P6450_GPIO_S_NR,
1615                        .label  = "GPS",
1616                },
1617        },
1618#endif
1619};
1620
1621/*
1622 * S5PC100 GPIO bank summary:
1623 *
1624 * Bank GPIOs   Style   INT Type
1625 * A0   8       4Bit    GPIO_INT0
1626 * A1   5       4Bit    GPIO_INT1
1627 * B    8       4Bit    GPIO_INT2
1628 * C    5       4Bit    GPIO_INT3
1629 * D    7       4Bit    GPIO_INT4
1630 * E0   8       4Bit    GPIO_INT5
1631 * E1   6       4Bit    GPIO_INT6
1632 * F0   8       4Bit    GPIO_INT7
1633 * F1   8       4Bit    GPIO_INT8
1634 * F2   8       4Bit    GPIO_INT9
1635 * F3   4       4Bit    GPIO_INT10
1636 * G0   8       4Bit    GPIO_INT11
1637 * G1   3       4Bit    GPIO_INT12
1638 * G2   7       4Bit    GPIO_INT13
1639 * G3   7       4Bit    GPIO_INT14
1640 * H0   8       4Bit    WKUP_INT
1641 * H1   8       4Bit    WKUP_INT
1642 * H2   8       4Bit    WKUP_INT
1643 * H3   8       4Bit    WKUP_INT
1644 * I    8       4Bit    GPIO_INT15
1645 * J0   8       4Bit    GPIO_INT16
1646 * J1   5       4Bit    GPIO_INT17
1647 * J2   8       4Bit    GPIO_INT18
1648 * J3   8       4Bit    GPIO_INT19
1649 * J4   4       4Bit    GPIO_INT20
1650 * K0   8       4Bit    None
1651 * K1   6       4Bit    None
1652 * K2   8       4Bit    None
1653 * K3   8       4Bit    None
1654 * L0   8       4Bit    None
1655 * L1   8       4Bit    None
1656 * L2   8       4Bit    None
1657 * L3   8       4Bit    None
1658 */
1659
1660static struct samsung_gpio_chip s5pc100_gpios_4bit[] = {
1661#ifdef CONFIG_CPU_S5PC100
1662        {
1663                .chip   = {
1664                        .base   = S5PC100_GPA0(0),
1665                        .ngpio  = S5PC100_GPIO_A0_NR,
1666                        .label  = "GPA0",
1667                },
1668        }, {
1669                .chip   = {
1670                        .base   = S5PC100_GPA1(0),
1671                        .ngpio  = S5PC100_GPIO_A1_NR,
1672                        .label  = "GPA1",
1673                },
1674        }, {
1675                .chip   = {
1676                        .base   = S5PC100_GPB(0),
1677                        .ngpio  = S5PC100_GPIO_B_NR,
1678                        .label  = "GPB",
1679                },
1680        }, {
1681                .chip   = {
1682                        .base   = S5PC100_GPC(0),
1683                        .ngpio  = S5PC100_GPIO_C_NR,
1684                        .label  = "GPC",
1685                },
1686        }, {
1687                .chip   = {
1688                        .base   = S5PC100_GPD(0),
1689                        .ngpio  = S5PC100_GPIO_D_NR,
1690                        .label  = "GPD",
1691                },
1692        }, {
1693                .chip   = {
1694                        .base   = S5PC100_GPE0(0),
1695                        .ngpio  = S5PC100_GPIO_E0_NR,
1696                        .label  = "GPE0",
1697                },
1698        }, {
1699                .chip   = {
1700                        .base   = S5PC100_GPE1(0),
1701                        .ngpio  = S5PC100_GPIO_E1_NR,
1702                        .label  = "GPE1",
1703                },
1704        }, {
1705                .chip   = {
1706                        .base   = S5PC100_GPF0(0),
1707                        .ngpio  = S5PC100_GPIO_F0_NR,
1708                        .label  = "GPF0",
1709                },
1710        }, {
1711                .chip   = {
1712                        .base   = S5PC100_GPF1(0),
1713                        .ngpio  = S5PC100_GPIO_F1_NR,
1714                        .label  = "GPF1",
1715                },
1716        }, {
1717                .chip   = {
1718                        .base   = S5PC100_GPF2(0),
1719                        .ngpio  = S5PC100_GPIO_F2_NR,
1720                        .label  = "GPF2",
1721                },
1722        }, {
1723                .chip   = {
1724                        .base   = S5PC100_GPF3(0),
1725                        .ngpio  = S5PC100_GPIO_F3_NR,
1726                        .label  = "GPF3",
1727                },
1728        }, {
1729                .chip   = {
1730                        .base   = S5PC100_GPG0(0),
1731                        .ngpio  = S5PC100_GPIO_G0_NR,
1732                        .label  = "GPG0",
1733                },
1734        }, {
1735                .chip   = {
1736                        .base   = S5PC100_GPG1(0),
1737                        .ngpio  = S5PC100_GPIO_G1_NR,
1738                        .label  = "GPG1",
1739                },
1740        }, {
1741                .chip   = {
1742                        .base   = S5PC100_GPG2(0),
1743                        .ngpio  = S5PC100_GPIO_G2_NR,
1744                        .label  = "GPG2",
1745                },
1746        }, {
1747                .chip   = {
1748                        .base   = S5PC100_GPG3(0),
1749                        .ngpio  = S5PC100_GPIO_G3_NR,
1750                        .label  = "GPG3",
1751                },
1752        }, {
1753                .chip   = {
1754                        .base   = S5PC100_GPI(0),
1755                        .ngpio  = S5PC100_GPIO_I_NR,
1756                        .label  = "GPI",
1757                },
1758        }, {
1759                .chip   = {
1760                        .base   = S5PC100_GPJ0(0),
1761                        .ngpio  = S5PC100_GPIO_J0_NR,
1762                        .label  = "GPJ0",
1763                },
1764        }, {
1765                .chip   = {
1766                        .base   = S5PC100_GPJ1(0),
1767                        .ngpio  = S5PC100_GPIO_J1_NR,
1768                        .label  = "GPJ1",
1769                },
1770        }, {
1771                .chip   = {
1772                        .base   = S5PC100_GPJ2(0),
1773                        .ngpio  = S5PC100_GPIO_J2_NR,
1774                        .label  = "GPJ2",
1775                },
1776        }, {
1777                .chip   = {
1778                        .base   = S5PC100_GPJ3(0),
1779                        .ngpio  = S5PC100_GPIO_J3_NR,
1780                        .label  = "GPJ3",
1781                },
1782        }, {
1783                .chip   = {
1784                        .base   = S5PC100_GPJ4(0),
1785                        .ngpio  = S5PC100_GPIO_J4_NR,
1786                        .label  = "GPJ4",
1787                },
1788        }, {
1789                .chip   = {
1790                        .base   = S5PC100_GPK0(0),
1791                        .ngpio  = S5PC100_GPIO_K0_NR,
1792                        .label  = "GPK0",
1793                },
1794        }, {
1795                .chip   = {
1796                        .base   = S5PC100_GPK1(0),
1797                        .ngpio  = S5PC100_GPIO_K1_NR,
1798                        .label  = "GPK1",
1799                },
1800        }, {
1801                .chip   = {
1802                        .base   = S5PC100_GPK2(0),
1803                        .ngpio  = S5PC100_GPIO_K2_NR,
1804                        .label  = "GPK2",
1805                },
1806        }, {
1807                .chip   = {
1808                        .base   = S5PC100_GPK3(0),
1809                        .ngpio  = S5PC100_GPIO_K3_NR,
1810                        .label  = "GPK3",
1811                },
1812        }, {
1813                .chip   = {
1814                        .base   = S5PC100_GPL0(0),
1815                        .ngpio  = S5PC100_GPIO_L0_NR,
1816                        .label  = "GPL0",
1817                },
1818        }, {
1819                .chip   = {
1820                        .base   = S5PC100_GPL1(0),
1821                        .ngpio  = S5PC100_GPIO_L1_NR,
1822                        .label  = "GPL1",
1823                },
1824        }, {
1825                .chip   = {
1826                        .base   = S5PC100_GPL2(0),
1827                        .ngpio  = S5PC100_GPIO_L2_NR,
1828                        .label  = "GPL2",
1829                },
1830        }, {
1831                .chip   = {
1832                        .base   = S5PC100_GPL3(0),
1833                        .ngpio  = S5PC100_GPIO_L3_NR,
1834                        .label  = "GPL3",
1835                },
1836        }, {
1837                .chip   = {
1838                        .base   = S5PC100_GPL4(0),
1839                        .ngpio  = S5PC100_GPIO_L4_NR,
1840                        .label  = "GPL4",
1841                },
1842        }, {
1843                .base   = (S5P_VA_GPIO + 0xC00),
1844                .irq_base = IRQ_EINT(0),
1845                .chip   = {
1846                        .base   = S5PC100_GPH0(0),
1847                        .ngpio  = S5PC100_GPIO_H0_NR,
1848                        .label  = "GPH0",
1849                        .to_irq = samsung_gpiolib_to_irq,
1850                },
1851        }, {
1852                .base   = (S5P_VA_GPIO + 0xC20),
1853                .irq_base = IRQ_EINT(8),
1854                .chip   = {
1855                        .base   = S5PC100_GPH1(0),
1856                        .ngpio  = S5PC100_GPIO_H1_NR,
1857                        .label  = "GPH1",
1858                        .to_irq = samsung_gpiolib_to_irq,
1859                },
1860        }, {
1861                .base   = (S5P_VA_GPIO + 0xC40),
1862                .irq_base = IRQ_EINT(16),
1863                .chip   = {
1864                        .base   = S5PC100_GPH2(0),
1865                        .ngpio  = S5PC100_GPIO_H2_NR,
1866                        .label  = "GPH2",
1867                        .to_irq = samsung_gpiolib_to_irq,
1868                },
1869        }, {
1870                .base   = (S5P_VA_GPIO + 0xC60),
1871                .irq_base = IRQ_EINT(24),
1872                .chip   = {
1873                        .base   = S5PC100_GPH3(0),
1874                        .ngpio  = S5PC100_GPIO_H3_NR,
1875                        .label  = "GPH3",
1876                        .to_irq = samsung_gpiolib_to_irq,
1877                },
1878        },
1879#endif
1880};
1881
1882/*
1883 * Followings are the gpio banks in S5PV210/S5PC110
1884 *
1885 * The 'config' member when left to NULL, is initialized to the default
1886 * structure samsung_gpio_cfgs[3] in the init function below.
1887 *
1888 * The 'base' member is also initialized in the init function below.
1889 * Note: The initialization of 'base' member of samsung_gpio_chip structure
1890 * uses the above macro and depends on the banks being listed in order here.
1891 */
1892
1893static struct samsung_gpio_chip s5pv210_gpios_4bit[] = {
1894#ifdef CONFIG_CPU_S5PV210
1895        {
1896                .chip   = {
1897                        .base   = S5PV210_GPA0(0),
1898                        .ngpio  = S5PV210_GPIO_A0_NR,
1899                        .label  = "GPA0",
1900                },
1901        }, {
1902                .chip   = {
1903                        .base   = S5PV210_GPA1(0),
1904                        .ngpio  = S5PV210_GPIO_A1_NR,
1905                        .label  = "GPA1",
1906                },
1907        }, {
1908                .chip   = {
1909                        .base   = S5PV210_GPB(0),
1910                        .ngpio  = S5PV210_GPIO_B_NR,
1911                        .label  = "GPB",
1912                },
1913        }, {
1914                .chip   = {
1915                        .base   = S5PV210_GPC0(0),
1916                        .ngpio  = S5PV210_GPIO_C0_NR,
1917                        .label  = "GPC0",
1918                },
1919        }, {
1920                .chip   = {
1921                        .base   = S5PV210_GPC1(0),
1922                        .ngpio  = S5PV210_GPIO_C1_NR,
1923                        .label  = "GPC1",
1924                },
1925        }, {
1926                .chip   = {
1927                        .base   = S5PV210_GPD0(0),
1928                        .ngpio  = S5PV210_GPIO_D0_NR,
1929                        .label  = "GPD0",
1930                },
1931        }, {
1932                .chip   = {
1933                        .base   = S5PV210_GPD1(0),
1934                        .ngpio  = S5PV210_GPIO_D1_NR,
1935                        .label  = "GPD1",
1936                },
1937        }, {
1938                .chip   = {
1939                        .base   = S5PV210_GPE0(0),
1940                        .ngpio  = S5PV210_GPIO_E0_NR,
1941                        .label  = "GPE0",
1942                },
1943        }, {
1944                .chip   = {
1945                        .base   = S5PV210_GPE1(0),
1946                        .ngpio  = S5PV210_GPIO_E1_NR,
1947                        .label  = "GPE1",
1948                },
1949        }, {
1950                .chip   = {
1951                        .base   = S5PV210_GPF0(0),
1952                        .ngpio  = S5PV210_GPIO_F0_NR,
1953                        .label  = "GPF0",
1954                },
1955        }, {
1956                .chip   = {
1957                        .base   = S5PV210_GPF1(0),
1958                        .ngpio  = S5PV210_GPIO_F1_NR,
1959                        .label  = "GPF1",
1960                },
1961        }, {
1962                .chip   = {
1963                        .base   = S5PV210_GPF2(0),
1964                        .ngpio  = S5PV210_GPIO_F2_NR,
1965                        .label  = "GPF2",
1966                },
1967        }, {
1968                .chip   = {
1969                        .base   = S5PV210_GPF3(0),
1970                        .ngpio  = S5PV210_GPIO_F3_NR,
1971                        .label  = "GPF3",
1972                },
1973        }, {
1974                .chip   = {
1975                        .base   = S5PV210_GPG0(0),
1976                        .ngpio  = S5PV210_GPIO_G0_NR,
1977                        .label  = "GPG0",
1978                },
1979        }, {
1980                .chip   = {
1981                        .base   = S5PV210_GPG1(0),
1982                        .ngpio  = S5PV210_GPIO_G1_NR,
1983                        .label  = "GPG1",
1984                },
1985        }, {
1986                .chip   = {
1987                        .base   = S5PV210_GPG2(0),
1988                        .ngpio  = S5PV210_GPIO_G2_NR,
1989                        .label  = "GPG2",
1990                },
1991        }, {
1992                .chip   = {
1993                        .base   = S5PV210_GPG3(0),
1994                        .ngpio  = S5PV210_GPIO_G3_NR,
1995                        .label  = "GPG3",
1996                },
1997        }, {
1998                .chip   = {
1999                        .base   = S5PV210_GPI(0),
2000                        .ngpio  = S5PV210_GPIO_I_NR,
2001                        .label  = "GPI",
2002                },
2003        }, {
2004                .chip   = {
2005                        .base   = S5PV210_GPJ0(0),
2006                        .ngpio  = S5PV210_GPIO_J0_NR,
2007                        .label  = "GPJ0",
2008                },
2009        }, {
2010                .chip   = {
2011                        .base   = S5PV210_GPJ1(0),
2012                        .ngpio  = S5PV210_GPIO_J1_NR,
2013                        .label  = "GPJ1",
2014                },
2015        }, {
2016                .chip   = {
2017                        .base   = S5PV210_GPJ2(0),
2018                        .ngpio  = S5PV210_GPIO_J2_NR,
2019                        .label  = "GPJ2",
2020                },
2021        }, {
2022                .chip   = {
2023                        .base   = S5PV210_GPJ3(0),
2024                        .ngpio  = S5PV210_GPIO_J3_NR,
2025                        .label  = "GPJ3",
2026                },
2027        }, {
2028                .chip   = {
2029                        .base   = S5PV210_GPJ4(0),
2030                        .ngpio  = S5PV210_GPIO_J4_NR,
2031                        .label  = "GPJ4",
2032                },
2033        }, {
2034                .chip   = {
2035                        .base   = S5PV210_MP01(0),
2036                        .ngpio  = S5PV210_GPIO_MP01_NR,
2037                        .label  = "MP01",
2038                },
2039        }, {
2040                .chip   = {
2041                        .base   = S5PV210_MP02(0),
2042                        .ngpio  = S5PV210_GPIO_MP02_NR,
2043                        .label  = "MP02",
2044                },
2045        }, {
2046                .chip   = {
2047                        .base   = S5PV210_MP03(0),
2048                        .ngpio  = S5PV210_GPIO_MP03_NR,
2049                        .label  = "MP03",
2050                },
2051        }, {
2052                .chip   = {
2053                        .base   = S5PV210_MP04(0),
2054                        .ngpio  = S5PV210_GPIO_MP04_NR,
2055                        .label  = "MP04",
2056                },
2057        }, {
2058                .chip   = {
2059                        .base   = S5PV210_MP05(0),
2060                        .ngpio  = S5PV210_GPIO_MP05_NR,
2061                        .label  = "MP05",
2062                },
2063        }, {
2064                .base   = (S5P_VA_GPIO + 0xC00),
2065                .irq_base = IRQ_EINT(0),
2066                .chip   = {
2067                        .base   = S5PV210_GPH0(0),
2068                        .ngpio  = S5PV210_GPIO_H0_NR,
2069                        .label  = "GPH0",
2070                        .to_irq = samsung_gpiolib_to_irq,
2071                },
2072        }, {
2073                .base   = (S5P_VA_GPIO + 0xC20),
2074                .irq_base = IRQ_EINT(8),
2075                .chip   = {
2076                        .base   = S5PV210_GPH1(0),
2077                        .ngpio  = S5PV210_GPIO_H1_NR,
2078                        .label  = "GPH1",
2079                        .to_irq = samsung_gpiolib_to_irq,
2080                },
2081        }, {
2082                .base   = (S5P_VA_GPIO + 0xC40),
2083                .irq_base = IRQ_EINT(16),
2084                .chip   = {
2085                        .base   = S5PV210_GPH2(0),
2086                        .ngpio  = S5PV210_GPIO_H2_NR,
2087                        .label  = "GPH2",
2088                        .to_irq = samsung_gpiolib_to_irq,
2089                },
2090        }, {
2091                .base   = (S5P_VA_GPIO + 0xC60),
2092                .irq_base = IRQ_EINT(24),
2093                .chip   = {
2094                        .base   = S5PV210_GPH3(0),
2095                        .ngpio  = S5PV210_GPIO_H3_NR,
2096                        .label  = "GPH3",
2097                        .to_irq = samsung_gpiolib_to_irq,
2098                },
2099        },
2100#endif
2101};
2102
2103/*
2104 * Followings are the gpio banks in EXYNOS4210
2105 *
2106 * The 'config' member when left to NULL, is initialized to the default
2107 * structure samsung_gpio_cfgs[3] in the init function below.
2108 *
2109 * The 'base' member is also initialized in the init function below.
2110 * Note: The initialization of 'base' member of samsung_gpio_chip structure
2111 * uses the above macro and depends on the banks being listed in order here.
2112 */
2113
2114static struct samsung_gpio_chip exynos4_gpios_1[] = {
2115#ifdef CONFIG_ARCH_EXYNOS4
2116        {
2117                .chip   = {
2118                        .base   = EXYNOS4_GPA0(0),
2119                        .ngpio  = EXYNOS4_GPIO_A0_NR,
2120                        .label  = "GPA0",
2121                },
2122        }, {
2123                .chip   = {
2124                        .base   = EXYNOS4_GPA1(0),
2125                        .ngpio  = EXYNOS4_GPIO_A1_NR,
2126                        .label  = "GPA1",
2127                },
2128        }, {
2129                .chip   = {
2130                        .base   = EXYNOS4_GPB(0),
2131                        .ngpio  = EXYNOS4_GPIO_B_NR,
2132                        .label  = "GPB",
2133                },
2134        }, {
2135                .chip   = {
2136                        .base   = EXYNOS4_GPC0(0),
2137                        .ngpio  = EXYNOS4_GPIO_C0_NR,
2138                        .label  = "GPC0",
2139                },
2140        }, {
2141                .chip   = {
2142                        .base   = EXYNOS4_GPC1(0),
2143                        .ngpio  = EXYNOS4_GPIO_C1_NR,
2144                        .label  = "GPC1",
2145                },
2146        }, {
2147                .chip   = {
2148                        .base   = EXYNOS4_GPD0(0),
2149                        .ngpio  = EXYNOS4_GPIO_D0_NR,
2150                        .label  = "GPD0",
2151                },
2152        }, {
2153                .chip   = {
2154                        .base   = EXYNOS4_GPD1(0),
2155                        .ngpio  = EXYNOS4_GPIO_D1_NR,
2156                        .label  = "GPD1",
2157                },
2158        }, {
2159                .chip   = {
2160                        .base   = EXYNOS4_GPE0(0),
2161                        .ngpio  = EXYNOS4_GPIO_E0_NR,
2162                        .label  = "GPE0",
2163                },
2164        }, {
2165                .chip   = {
2166                        .base   = EXYNOS4_GPE1(0),
2167                        .ngpio  = EXYNOS4_GPIO_E1_NR,
2168                        .label  = "GPE1",
2169                },
2170        }, {
2171                .chip   = {
2172                        .base   = EXYNOS4_GPE2(0),
2173                        .ngpio  = EXYNOS4_GPIO_E2_NR,
2174                        .label  = "GPE2",
2175                },
2176        }, {
2177                .chip   = {
2178                        .base   = EXYNOS4_GPE3(0),
2179                        .ngpio  = EXYNOS4_GPIO_E3_NR,
2180                        .label  = "GPE3",
2181                },
2182        }, {
2183                .chip   = {
2184                        .base   = EXYNOS4_GPE4(0),
2185                        .ngpio  = EXYNOS4_GPIO_E4_NR,
2186                        .label  = "GPE4",
2187                },
2188        }, {
2189                .chip   = {
2190                        .base   = EXYNOS4_GPF0(0),
2191                        .ngpio  = EXYNOS4_GPIO_F0_NR,
2192                        .label  = "GPF0",
2193                },
2194        }, {
2195                .chip   = {
2196                        .base   = EXYNOS4_GPF1(0),
2197                        .ngpio  = EXYNOS4_GPIO_F1_NR,
2198                        .label  = "GPF1",
2199                },
2200        }, {
2201                .chip   = {
2202                        .base   = EXYNOS4_GPF2(0),
2203                        .ngpio  = EXYNOS4_GPIO_F2_NR,
2204                        .label  = "GPF2",
2205                },
2206        }, {
2207                .chip   = {
2208                        .base   = EXYNOS4_GPF3(0),
2209                        .ngpio  = EXYNOS4_GPIO_F3_NR,
2210                        .label  = "GPF3",
2211                },
2212        },
2213#endif
2214};
2215
2216static struct samsung_gpio_chip exynos4_gpios_2[] = {
2217#ifdef CONFIG_ARCH_EXYNOS4
2218        {
2219                .chip   = {
2220                        .base   = EXYNOS4_GPJ0(0),
2221                        .ngpio  = EXYNOS4_GPIO_J0_NR,
2222                        .label  = "GPJ0",
2223                },
2224        }, {
2225                .chip   = {
2226                        .base   = EXYNOS4_GPJ1(0),
2227                        .ngpio  = EXYNOS4_GPIO_J1_NR,
2228                        .label  = "GPJ1",
2229                },
2230        }, {
2231                .chip   = {
2232                        .base   = EXYNOS4_GPK0(0),
2233                        .ngpio  = EXYNOS4_GPIO_K0_NR,
2234                        .label  = "GPK0",
2235                },
2236        }, {
2237                .chip   = {
2238                        .base   = EXYNOS4_GPK1(0),
2239                        .ngpio  = EXYNOS4_GPIO_K1_NR,
2240                        .label  = "GPK1",
2241                },
2242        }, {
2243                .chip   = {
2244                        .base   = EXYNOS4_GPK2(0),
2245                        .ngpio  = EXYNOS4_GPIO_K2_NR,
2246                        .label  = "GPK2",
2247                },
2248        }, {
2249                .chip   = {
2250                        .base   = EXYNOS4_GPK3(0),
2251                        .ngpio  = EXYNOS4_GPIO_K3_NR,
2252                        .label  = "GPK3",
2253                },
2254        }, {
2255                .chip   = {
2256                        .base   = EXYNOS4_GPL0(0),
2257                        .ngpio  = EXYNOS4_GPIO_L0_NR,
2258                        .label  = "GPL0",
2259                },
2260        }, {
2261                .chip   = {
2262                        .base   = EXYNOS4_GPL1(0),
2263                        .ngpio  = EXYNOS4_GPIO_L1_NR,
2264                        .label  = "GPL1",
2265                },
2266        }, {
2267                .chip   = {
2268                        .base   = EXYNOS4_GPL2(0),
2269                        .ngpio  = EXYNOS4_GPIO_L2_NR,
2270                        .label  = "GPL2",
2271                },
2272        }, {
2273                .config = &samsung_gpio_cfgs[8],
2274                .chip   = {
2275                        .base   = EXYNOS4_GPY0(0),
2276                        .ngpio  = EXYNOS4_GPIO_Y0_NR,
2277                        .label  = "GPY0",
2278                },
2279        }, {
2280                .config = &samsung_gpio_cfgs[8],
2281                .chip   = {
2282                        .base   = EXYNOS4_GPY1(0),
2283                        .ngpio  = EXYNOS4_GPIO_Y1_NR,
2284                        .label  = "GPY1",
2285                },
2286        }, {
2287                .config = &samsung_gpio_cfgs[8],
2288                .chip   = {
2289                        .base   = EXYNOS4_GPY2(0),
2290                        .ngpio  = EXYNOS4_GPIO_Y2_NR,
2291                        .label  = "GPY2",
2292                },
2293        }, {
2294                .config = &samsung_gpio_cfgs[8],
2295                .chip   = {
2296                        .base   = EXYNOS4_GPY3(0),
2297                        .ngpio  = EXYNOS4_GPIO_Y3_NR,
2298                        .label  = "GPY3",
2299                },
2300        }, {
2301                .config = &samsung_gpio_cfgs[8],
2302                .chip   = {
2303                        .base   = EXYNOS4_GPY4(0),
2304                        .ngpio  = EXYNOS4_GPIO_Y4_NR,
2305                        .label  = "GPY4",
2306                },
2307        }, {
2308                .config = &samsung_gpio_cfgs[8],
2309                .chip   = {
2310                        .base   = EXYNOS4_GPY5(0),
2311                        .ngpio  = EXYNOS4_GPIO_Y5_NR,
2312                        .label  = "GPY5",
2313                },
2314        }, {
2315                .config = &samsung_gpio_cfgs[8],
2316                .chip   = {
2317                        .base   = EXYNOS4_GPY6(0),
2318                        .ngpio  = EXYNOS4_GPIO_Y6_NR,
2319                        .label  = "GPY6",
2320                },
2321        }, {
2322                .base   = (S5P_VA_GPIO2 + 0xC00),
2323                .config = &samsung_gpio_cfgs[9],
2324                .irq_base = IRQ_EINT(0),
2325                .chip   = {
2326                        .base   = EXYNOS4_GPX0(0),
2327                        .ngpio  = EXYNOS4_GPIO_X0_NR,
2328                        .label  = "GPX0",
2329                        .to_irq = samsung_gpiolib_to_irq,
2330                },
2331        }, {
2332                .base   = (S5P_VA_GPIO2 + 0xC20),
2333                .config = &samsung_gpio_cfgs[9],
2334                .irq_base = IRQ_EINT(8),
2335                .chip   = {
2336                        .base   = EXYNOS4_GPX1(0),
2337                        .ngpio  = EXYNOS4_GPIO_X1_NR,
2338                        .label  = "GPX1",
2339                        .to_irq = samsung_gpiolib_to_irq,
2340                },
2341        }, {
2342                .base   = (S5P_VA_GPIO2 + 0xC40),
2343                .config = &samsung_gpio_cfgs[9],
2344                .irq_base = IRQ_EINT(16),
2345                .chip   = {
2346                        .base   = EXYNOS4_GPX2(0),
2347                        .ngpio  = EXYNOS4_GPIO_X2_NR,
2348                        .label  = "GPX2",
2349                        .to_irq = samsung_gpiolib_to_irq,
2350                },
2351        }, {
2352                .base   = (S5P_VA_GPIO2 + 0xC60),
2353                .config = &samsung_gpio_cfgs[9],
2354                .irq_base = IRQ_EINT(24),
2355                .chip   = {
2356                        .base   = EXYNOS4_GPX3(0),
2357                        .ngpio  = EXYNOS4_GPIO_X3_NR,
2358                        .label  = "GPX3",
2359                        .to_irq = samsung_gpiolib_to_irq,
2360                },
2361        },
2362#endif
2363};
2364
2365static struct samsung_gpio_chip exynos4_gpios_3[] = {
2366#ifdef CONFIG_ARCH_EXYNOS4
2367        {
2368                .chip   = {
2369                        .base   = EXYNOS4_GPZ(0),
2370                        .ngpio  = EXYNOS4_GPIO_Z_NR,
2371                        .label  = "GPZ",
2372                },
2373        },
2374#endif
2375};
2376
2377/* TODO: cleanup soc_is_* */
2378static __init int samsung_gpiolib_init(void)
2379{
2380        struct samsung_gpio_chip *chip;
2381        int i, nr_chips;
2382        int group = 0;
2383
2384        samsung_gpiolib_set_cfg(samsung_gpio_cfgs, ARRAY_SIZE(samsung_gpio_cfgs));
2385
2386        if (soc_is_s3c24xx()) {
2387                s3c24xx_gpiolib_add_chips(s3c24xx_gpios,
2388                                ARRAY_SIZE(s3c24xx_gpios), S3C24XX_VA_GPIO);
2389        } else if (soc_is_s3c64xx()) {
2390                samsung_gpiolib_add_2bit_chips(s3c64xx_gpios_2bit,
2391                                ARRAY_SIZE(s3c64xx_gpios_2bit),
2392                                S3C64XX_VA_GPIO + 0xE0, 0x20);
2393                samsung_gpiolib_add_4bit_chips(s3c64xx_gpios_4bit,
2394                                ARRAY_SIZE(s3c64xx_gpios_4bit),
2395                                S3C64XX_VA_GPIO);
2396                samsung_gpiolib_add_4bit2_chips(s3c64xx_gpios_4bit2,
2397                                ARRAY_SIZE(s3c64xx_gpios_4bit2));
2398        } else if (soc_is_s5p6440()) {
2399                samsung_gpiolib_add_2bit_chips(s5p6440_gpios_2bit,
2400                                ARRAY_SIZE(s5p6440_gpios_2bit), NULL, 0x0);
2401                samsung_gpiolib_add_4bit_chips(s5p6440_gpios_4bit,
2402                                ARRAY_SIZE(s5p6440_gpios_4bit), S5P_VA_GPIO);
2403                samsung_gpiolib_add_4bit2_chips(s5p6440_gpios_4bit2,
2404                                ARRAY_SIZE(s5p6440_gpios_4bit2));
2405                s5p64x0_gpiolib_add_rbank(s5p6440_gpios_rbank,
2406                                ARRAY_SIZE(s5p6440_gpios_rbank));
2407        } else if (soc_is_s5p6450()) {
2408                samsung_gpiolib_add_2bit_chips(s5p6450_gpios_2bit,
2409                                ARRAY_SIZE(s5p6450_gpios_2bit), NULL, 0x0);
2410                samsung_gpiolib_add_4bit_chips(s5p6450_gpios_4bit,
2411                                ARRAY_SIZE(s5p6450_gpios_4bit), S5P_VA_GPIO);
2412                samsung_gpiolib_add_4bit2_chips(s5p6450_gpios_4bit2,
2413                                ARRAY_SIZE(s5p6450_gpios_4bit2));
2414                s5p64x0_gpiolib_add_rbank(s5p6450_gpios_rbank,
2415                                ARRAY_SIZE(s5p6450_gpios_rbank));
2416        } else if (soc_is_s5pc100()) {
2417                group = 0;
2418                chip = s5pc100_gpios_4bit;
2419                nr_chips = ARRAY_SIZE(s5pc100_gpios_4bit);
2420
2421                for (i = 0; i < nr_chips; i++, chip++) {
2422                        if (!chip->config) {
2423                                chip->config = &samsung_gpio_cfgs[3];
2424                                chip->group = group++;
2425                        }
2426                }
2427                samsung_gpiolib_add_4bit_chips(s5pc100_gpios_4bit, nr_chips, S5P_VA_GPIO);
2428#if defined(CONFIG_CPU_S5PC100) && defined(CONFIG_S5P_GPIO_INT)
2429                s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
2430#endif
2431        } else if (soc_is_s5pv210()) {
2432                group = 0;
2433                chip = s5pv210_gpios_4bit;
2434                nr_chips = ARRAY_SIZE(s5pv210_gpios_4bit);
2435
2436                for (i = 0; i < nr_chips; i++, chip++) {
2437                        if (!chip->config) {
2438                                chip->config = &samsung_gpio_cfgs[3];
2439                                chip->group = group++;
2440                        }
2441                }
2442                samsung_gpiolib_add_4bit_chips(s5pv210_gpios_4bit, nr_chips, S5P_VA_GPIO);
2443#if defined(CONFIG_CPU_S5PV210) && defined(CONFIG_S5P_GPIO_INT)
2444                s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
2445#endif
2446        } else if (soc_is_exynos4210()) {
2447                group = 0;
2448
2449                /* gpio part1 */
2450                chip = exynos4_gpios_1;
2451                nr_chips = ARRAY_SIZE(exynos4_gpios_1);
2452
2453                for (i = 0; i < nr_chips; i++, chip++) {
2454                        if (!chip->config) {
2455                                chip->config = &exynos4_gpio_cfg;
2456                                chip->group = group++;
2457                        }
2458                }
2459                samsung_gpiolib_add_4bit_chips(exynos4_gpios_1, nr_chips, S5P_VA_GPIO1);
2460
2461                /* gpio part2 */
2462                chip = exynos4_gpios_2;
2463                nr_chips = ARRAY_SIZE(exynos4_gpios_2);
2464
2465                for (i = 0; i < nr_chips; i++, chip++) {
2466                        if (!chip->config) {
2467                                chip->config = &exynos4_gpio_cfg;
2468                                chip->group = group++;
2469                        }
2470                }
2471                samsung_gpiolib_add_4bit_chips(exynos4_gpios_2, nr_chips, S5P_VA_GPIO2);
2472
2473                /* gpio part3 */
2474                chip = exynos4_gpios_3;
2475                nr_chips = ARRAY_SIZE(exynos4_gpios_3);
2476
2477                for (i = 0; i < nr_chips; i++, chip++) {
2478                        if (!chip->config) {
2479                                chip->config = &exynos4_gpio_cfg;
2480                                chip->group = group++;
2481                        }
2482                }
2483                samsung_gpiolib_add_4bit_chips(exynos4_gpios_3, nr_chips, S5P_VA_GPIO3);
2484
2485#if defined(CONFIG_CPU_EXYNOS4210) && defined(CONFIG_S5P_GPIO_INT)
2486                s5p_register_gpioint_bank(IRQ_GPIO_XA, 0, IRQ_GPIO1_NR_GROUPS);
2487                s5p_register_gpioint_bank(IRQ_GPIO_XB, IRQ_GPIO1_NR_GROUPS, IRQ_GPIO2_NR_GROUPS);
2488#endif
2489        } else {
2490                WARN(1, "Unknown SoC in gpio-samsung, no GPIOs added\n");
2491                return -ENODEV;
2492        }
2493
2494        return 0;
2495}
2496core_initcall(samsung_gpiolib_init);
2497
2498int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
2499{
2500        struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2501        unsigned long flags;
2502        int offset;
2503        int ret;
2504
2505        if (!chip)
2506                return -EINVAL;
2507
2508        offset = pin - chip->chip.base;
2509
2510        samsung_gpio_lock(chip, flags);
2511        ret = samsung_gpio_do_setcfg(chip, offset, config);
2512        samsung_gpio_unlock(chip, flags);
2513
2514        return ret;
2515}
2516EXPORT_SYMBOL(s3c_gpio_cfgpin);
2517
2518int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
2519                          unsigned int cfg)
2520{
2521        int ret;
2522
2523        for (; nr > 0; nr--, start++) {
2524                ret = s3c_gpio_cfgpin(start, cfg);
2525                if (ret != 0)
2526                        return ret;
2527        }
2528
2529        return 0;
2530}
2531EXPORT_SYMBOL_GPL(s3c_gpio_cfgpin_range);
2532
2533int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
2534                          unsigned int cfg, samsung_gpio_pull_t pull)
2535{
2536        int ret;
2537
2538        for (; nr > 0; nr--, start++) {
2539                s3c_gpio_setpull(start, pull);
2540                ret = s3c_gpio_cfgpin(start, cfg);
2541                if (ret != 0)
2542                        return ret;
2543        }
2544
2545        return 0;
2546}
2547EXPORT_SYMBOL_GPL(s3c_gpio_cfgall_range);
2548
2549unsigned s3c_gpio_getcfg(unsigned int pin)
2550{
2551        struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2552        unsigned long flags;
2553        unsigned ret = 0;
2554        int offset;
2555
2556        if (chip) {
2557                offset = pin - chip->chip.base;
2558
2559                samsung_gpio_lock(chip, flags);
2560                ret = samsung_gpio_do_getcfg(chip, offset);
2561                samsung_gpio_unlock(chip, flags);
2562        }
2563
2564        return ret;
2565}
2566EXPORT_SYMBOL(s3c_gpio_getcfg);
2567
2568int s3c_gpio_setpull(unsigned int pin, samsung_gpio_pull_t pull)
2569{
2570        struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2571        unsigned long flags;
2572        int offset, ret;
2573
2574        if (!chip)
2575                return -EINVAL;
2576
2577        offset = pin - chip->chip.base;
2578
2579        samsung_gpio_lock(chip, flags);
2580        ret = samsung_gpio_do_setpull(chip, offset, pull);
2581        samsung_gpio_unlock(chip, flags);
2582
2583        return ret;
2584}
2585EXPORT_SYMBOL(s3c_gpio_setpull);
2586
2587samsung_gpio_pull_t s3c_gpio_getpull(unsigned int pin)
2588{
2589        struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2590        unsigned long flags;
2591        int offset;
2592        u32 pup = 0;
2593
2594        if (chip) {
2595                offset = pin - chip->chip.base;
2596
2597                samsung_gpio_lock(chip, flags);
2598                pup = samsung_gpio_do_getpull(chip, offset);
2599                samsung_gpio_unlock(chip, flags);
2600        }
2601
2602        return (__force samsung_gpio_pull_t)pup;
2603}
2604EXPORT_SYMBOL(s3c_gpio_getpull);
2605
2606/* gpiolib wrappers until these are totally eliminated */
2607
2608void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
2609{
2610        int ret;
2611
2612        WARN_ON(to);    /* should be none of these left */
2613
2614        if (!to) {
2615                /* if pull is enabled, try first with up, and if that
2616                 * fails, try using down */
2617
2618                ret = s3c_gpio_setpull(pin, S3C_GPIO_PULL_UP);
2619                if (ret)
2620                        s3c_gpio_setpull(pin, S3C_GPIO_PULL_DOWN);
2621        } else {
2622                s3c_gpio_setpull(pin, S3C_GPIO_PULL_NONE);
2623        }
2624}
2625EXPORT_SYMBOL(s3c2410_gpio_pullup);
2626
2627void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
2628{
2629        /* do this via gpiolib until all users removed */
2630
2631        gpio_request(pin, "temporary");
2632        gpio_set_value(pin, to);
2633        gpio_free(pin);
2634}
2635EXPORT_SYMBOL(s3c2410_gpio_setpin);
2636
2637unsigned int s3c2410_gpio_getpin(unsigned int pin)
2638{
2639        struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2640        unsigned long offs = pin - chip->chip.base;
2641
2642        return __raw_readl(chip->base + 0x04) & (1 << offs);
2643}
2644EXPORT_SYMBOL(s3c2410_gpio_getpin);
2645
2646#ifdef CONFIG_S5P_GPIO_DRVSTR
2647s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin)
2648{
2649        struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2650        unsigned int off;
2651        void __iomem *reg;
2652        int shift;
2653        u32 drvstr;
2654
2655        if (!chip)
2656                return -EINVAL;
2657
2658        off = pin - chip->chip.base;
2659        shift = off * 2;
2660        reg = chip->base + 0x0C;
2661
2662        drvstr = __raw_readl(reg);
2663        drvstr = drvstr >> shift;
2664        drvstr &= 0x3;
2665
2666        return (__force s5p_gpio_drvstr_t)drvstr;
2667}
2668EXPORT_SYMBOL(s5p_gpio_get_drvstr);
2669
2670int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr)
2671{
2672        struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
2673        unsigned int off;
2674        void __iomem *reg;
2675        int shift;
2676        u32 tmp;
2677
2678        if (!chip)
2679                return -EINVAL;
2680
2681        off = pin - chip->chip.base;
2682        shift = off * 2;
2683        reg = chip->base + 0x0C;
2684
2685        tmp = __raw_readl(reg);
2686        tmp &= ~(0x3 << shift);
2687        tmp |= drvstr << shift;
2688
2689        __raw_writel(tmp, reg);
2690
2691        return 0;
2692}
2693EXPORT_SYMBOL(s5p_gpio_set_drvstr);
2694#endif  /* CONFIG_S5P_GPIO_DRVSTR */
2695
2696#ifdef CONFIG_PLAT_S3C24XX
2697unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
2698{
2699        unsigned long flags;
2700        unsigned long misccr;
2701
2702        local_irq_save(flags);
2703        misccr = __raw_readl(S3C24XX_MISCCR);
2704        misccr &= ~clear;
2705        misccr ^= change;
2706        __raw_writel(misccr, S3C24XX_MISCCR);
2707        local_irq_restore(flags);
2708
2709        return misccr;
2710}
2711EXPORT_SYMBOL(s3c2410_modify_misccr);
2712#endif
2713