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