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/map.h>
  34#include <mach/regs-gpio.h>
  35#include <mach/gpio-samsung.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
 358static void __init samsung_gpiolib_set_cfg(struct samsung_gpio_cfg *chipcfg,
 359                                           int nr_chips)
 360{
 361        for (; nr_chips > 0; nr_chips--, chipcfg++) {
 362                if (!chipcfg->set_config)
 363                        chipcfg->set_config = samsung_gpio_setcfg_4bit;
 364                if (!chipcfg->get_config)
 365                        chipcfg->get_config = samsung_gpio_getcfg_4bit;
 366                if (!chipcfg->set_pull)
 367                        chipcfg->set_pull = samsung_gpio_setpull_updown;
 368                if (!chipcfg->get_pull)
 369                        chipcfg->get_pull = samsung_gpio_getpull_updown;
 370        }
 371}
 372
 373struct samsung_gpio_cfg s3c24xx_gpiocfg_default = {
 374        .set_config     = samsung_gpio_setcfg_2bit,
 375        .get_config     = samsung_gpio_getcfg_2bit,
 376};
 377
 378#ifdef CONFIG_PLAT_S3C24XX
 379static struct samsung_gpio_cfg s3c24xx_gpiocfg_banka = {
 380        .set_config     = s3c24xx_gpio_setcfg_abank,
 381        .get_config     = s3c24xx_gpio_getcfg_abank,
 382};
 383#endif
 384
 385static struct samsung_gpio_cfg samsung_gpio_cfgs[] = {
 386        [0] = {
 387                .cfg_eint       = 0x0,
 388        },
 389        [1] = {
 390                .cfg_eint       = 0x3,
 391        },
 392        [2] = {
 393                .cfg_eint       = 0x7,
 394        },
 395        [3] = {
 396                .cfg_eint       = 0xF,
 397        },
 398        [4] = {
 399                .cfg_eint       = 0x0,
 400                .set_config     = samsung_gpio_setcfg_2bit,
 401                .get_config     = samsung_gpio_getcfg_2bit,
 402        },
 403        [5] = {
 404                .cfg_eint       = 0x2,
 405                .set_config     = samsung_gpio_setcfg_2bit,
 406                .get_config     = samsung_gpio_getcfg_2bit,
 407        },
 408        [6] = {
 409                .cfg_eint       = 0x3,
 410                .set_config     = samsung_gpio_setcfg_2bit,
 411                .get_config     = samsung_gpio_getcfg_2bit,
 412        },
 413        [7] = {
 414                .set_config     = samsung_gpio_setcfg_2bit,
 415                .get_config     = samsung_gpio_getcfg_2bit,
 416        },
 417};
 418
 419/*
 420 * Default routines for controlling GPIO, based on the original S3C24XX
 421 * GPIO functions which deal with the case where each gpio bank of the
 422 * chip is as following:
 423 *
 424 * base + 0x00: Control register, 2 bits per gpio
 425 *              gpio n: 2 bits starting at (2*n)
 426 *              00 = input, 01 = output, others mean special-function
 427 * base + 0x04: Data register, 1 bit per gpio
 428 *              bit n: data bit n
 429*/
 430
 431static int samsung_gpiolib_2bit_input(struct gpio_chip *chip, unsigned offset)
 432{
 433        struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
 434        void __iomem *base = ourchip->base;
 435        unsigned long flags;
 436        unsigned long con;
 437
 438        samsung_gpio_lock(ourchip, flags);
 439
 440        con = __raw_readl(base + 0x00);
 441        con &= ~(3 << (offset * 2));
 442
 443        __raw_writel(con, base + 0x00);
 444
 445        samsung_gpio_unlock(ourchip, flags);
 446        return 0;
 447}
 448
 449static int samsung_gpiolib_2bit_output(struct gpio_chip *chip,
 450                                       unsigned offset, int value)
 451{
 452        struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
 453        void __iomem *base = ourchip->base;
 454        unsigned long flags;
 455        unsigned long dat;
 456        unsigned long con;
 457
 458        samsung_gpio_lock(ourchip, flags);
 459
 460        dat = __raw_readl(base + 0x04);
 461        dat &= ~(1 << offset);
 462        if (value)
 463                dat |= 1 << offset;
 464        __raw_writel(dat, base + 0x04);
 465
 466        con = __raw_readl(base + 0x00);
 467        con &= ~(3 << (offset * 2));
 468        con |= 1 << (offset * 2);
 469
 470        __raw_writel(con, base + 0x00);
 471        __raw_writel(dat, base + 0x04);
 472
 473        samsung_gpio_unlock(ourchip, flags);
 474        return 0;
 475}
 476
 477/*
 478 * The samsung_gpiolib_4bit routines are to control the gpio banks where
 479 * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
 480 * following example:
 481 *
 482 * base + 0x00: Control register, 4 bits per gpio
 483 *              gpio n: 4 bits starting at (4*n)
 484 *              0000 = input, 0001 = output, others mean special-function
 485 * base + 0x04: Data register, 1 bit per gpio
 486 *              bit n: data bit n
 487 *
 488 * Note, since the data register is one bit per gpio and is at base + 0x4
 489 * we can use samsung_gpiolib_get and samsung_gpiolib_set to change the
 490 * state of the output.
 491 */
 492
 493static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
 494                                      unsigned int offset)
 495{
 496        struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
 497        void __iomem *base = ourchip->base;
 498        unsigned long con;
 499
 500        con = __raw_readl(base + GPIOCON_OFF);
 501        if (ourchip->bitmap_gpio_int & BIT(offset))
 502                con |= 0xf << con_4bit_shift(offset);
 503        else
 504                con &= ~(0xf << con_4bit_shift(offset));
 505        __raw_writel(con, base + GPIOCON_OFF);
 506
 507        pr_debug("%s: %p: CON now %08lx\n", __func__, base, con);
 508
 509        return 0;
 510}
 511
 512static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
 513                                       unsigned int offset, int value)
 514{
 515        struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
 516        void __iomem *base = ourchip->base;
 517        unsigned long con;
 518        unsigned long dat;
 519
 520        con = __raw_readl(base + GPIOCON_OFF);
 521        con &= ~(0xf << con_4bit_shift(offset));
 522        con |= 0x1 << con_4bit_shift(offset);
 523
 524        dat = __raw_readl(base + GPIODAT_OFF);
 525
 526        if (value)
 527                dat |= 1 << offset;
 528        else
 529                dat &= ~(1 << offset);
 530
 531        __raw_writel(dat, base + GPIODAT_OFF);
 532        __raw_writel(con, base + GPIOCON_OFF);
 533        __raw_writel(dat, base + GPIODAT_OFF);
 534
 535        pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
 536
 537        return 0;
 538}
 539
 540/*
 541 * The next set of routines are for the case where the GPIO configuration
 542 * registers are 4 bits per GPIO but there is more than one register (the
 543 * bank has more than 8 GPIOs.
 544 *
 545 * This case is the similar to the 4 bit case, but the registers are as
 546 * follows:
 547 *
 548 * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
 549 *              gpio n: 4 bits starting at (4*n)
 550 *              0000 = input, 0001 = output, others mean special-function
 551 * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
 552 *              gpio n: 4 bits starting at (4*n)
 553 *              0000 = input, 0001 = output, others mean special-function
 554 * base + 0x08: Data register, 1 bit per gpio
 555 *              bit n: data bit n
 556 *
 557 * To allow us to use the samsung_gpiolib_get and samsung_gpiolib_set
 558 * routines we store the 'base + 0x4' address so that these routines see
 559 * the data register at ourchip->base + 0x04.
 560 */
 561
 562static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
 563                                       unsigned int offset)
 564{
 565        struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
 566        void __iomem *base = ourchip->base;
 567        void __iomem *regcon = base;
 568        unsigned long con;
 569
 570        if (offset > 7)
 571                offset -= 8;
 572        else
 573                regcon -= 4;
 574
 575        con = __raw_readl(regcon);
 576        con &= ~(0xf << con_4bit_shift(offset));
 577        __raw_writel(con, regcon);
 578
 579        pr_debug("%s: %p: CON %08lx\n", __func__, base, con);
 580
 581        return 0;
 582}
 583
 584static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
 585                                        unsigned int offset, int value)
 586{
 587        struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
 588        void __iomem *base = ourchip->base;
 589        void __iomem *regcon = base;
 590        unsigned long con;
 591        unsigned long dat;
 592        unsigned con_offset = offset;
 593
 594        if (con_offset > 7)
 595                con_offset -= 8;
 596        else
 597                regcon -= 4;
 598
 599        con = __raw_readl(regcon);
 600        con &= ~(0xf << con_4bit_shift(con_offset));
 601        con |= 0x1 << con_4bit_shift(con_offset);
 602
 603        dat = __raw_readl(base + GPIODAT_OFF);
 604
 605        if (value)
 606                dat |= 1 << offset;
 607        else
 608                dat &= ~(1 << offset);
 609
 610        __raw_writel(dat, base + GPIODAT_OFF);
 611        __raw_writel(con, regcon);
 612        __raw_writel(dat, base + GPIODAT_OFF);
 613
 614        pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
 615
 616        return 0;
 617}
 618
 619#ifdef CONFIG_PLAT_S3C24XX
 620/* The next set of routines are for the case of s3c24xx bank a */
 621
 622static int s3c24xx_gpiolib_banka_input(struct gpio_chip *chip, unsigned offset)
 623{
 624        return -EINVAL;
 625}
 626
 627static int s3c24xx_gpiolib_banka_output(struct gpio_chip *chip,
 628                                        unsigned offset, int value)
 629{
 630        struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
 631        void __iomem *base = ourchip->base;
 632        unsigned long flags;
 633        unsigned long dat;
 634        unsigned long con;
 635
 636        local_irq_save(flags);
 637
 638        con = __raw_readl(base + 0x00);
 639        dat = __raw_readl(base + 0x04);
 640
 641        dat &= ~(1 << offset);
 642        if (value)
 643                dat |= 1 << offset;
 644
 645        __raw_writel(dat, base + 0x04);
 646
 647        con &= ~(1 << offset);
 648
 649        __raw_writel(con, base + 0x00);
 650        __raw_writel(dat, base + 0x04);
 651
 652        local_irq_restore(flags);
 653        return 0;
 654}
 655#endif
 656
 657static void samsung_gpiolib_set(struct gpio_chip *chip,
 658                                unsigned offset, int value)
 659{
 660        struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
 661        void __iomem *base = ourchip->base;
 662        unsigned long flags;
 663        unsigned long dat;
 664
 665        samsung_gpio_lock(ourchip, flags);
 666
 667        dat = __raw_readl(base + 0x04);
 668        dat &= ~(1 << offset);
 669        if (value)
 670                dat |= 1 << offset;
 671        __raw_writel(dat, base + 0x04);
 672
 673        samsung_gpio_unlock(ourchip, flags);
 674}
 675
 676static int samsung_gpiolib_get(struct gpio_chip *chip, unsigned offset)
 677{
 678        struct samsung_gpio_chip *ourchip = to_samsung_gpio(chip);
 679        unsigned long val;
 680
 681        val = __raw_readl(ourchip->base + 0x04);
 682        val >>= offset;
 683        val &= 1;
 684
 685        return val;
 686}
 687
 688/*
 689 * CONFIG_S3C_GPIO_TRACK enables the tracking of the s3c specific gpios
 690 * for use with the configuration calls, and other parts of the s3c gpiolib
 691 * support code.
 692 *
 693 * Not all s3c support code will need this, as some configurations of cpu
 694 * may only support one or two different configuration options and have an
 695 * easy gpio to samsung_gpio_chip mapping function. If this is the case, then
 696 * the machine support file should provide its own samsung_gpiolib_getchip()
 697 * and any other necessary functions.
 698 */
 699
 700#ifdef CONFIG_S3C_GPIO_TRACK
 701struct samsung_gpio_chip *s3c_gpios[S3C_GPIO_END];
 702
 703static __init void s3c_gpiolib_track(struct samsung_gpio_chip *chip)
 704{
 705        unsigned int gpn;
 706        int i;
 707
 708        gpn = chip->chip.base;
 709        for (i = 0; i < chip->chip.ngpio; i++, gpn++) {
 710                BUG_ON(gpn >= ARRAY_SIZE(s3c_gpios));
 711                s3c_gpios[gpn] = chip;
 712        }
 713}
 714#endif /* CONFIG_S3C_GPIO_TRACK */
 715
 716/*
 717 * samsung_gpiolib_add() - add the Samsung gpio_chip.
 718 * @chip: The chip to register
 719 *
 720 * This is a wrapper to gpiochip_add() that takes our specific gpio chip
 721 * information and makes the necessary alterations for the platform and
 722 * notes the information for use with the configuration systems and any
 723 * other parts of the system.
 724 */
 725
 726static void __init samsung_gpiolib_add(struct samsung_gpio_chip *chip)
 727{
 728        struct gpio_chip *gc = &chip->chip;
 729        int ret;
 730
 731        BUG_ON(!chip->base);
 732        BUG_ON(!gc->label);
 733        BUG_ON(!gc->ngpio);
 734
 735        spin_lock_init(&chip->lock);
 736
 737        if (!gc->direction_input)
 738                gc->direction_input = samsung_gpiolib_2bit_input;
 739        if (!gc->direction_output)
 740                gc->direction_output = samsung_gpiolib_2bit_output;
 741        if (!gc->set)
 742                gc->set = samsung_gpiolib_set;
 743        if (!gc->get)
 744                gc->get = samsung_gpiolib_get;
 745
 746#ifdef CONFIG_PM
 747        if (chip->pm != NULL) {
 748                if (!chip->pm->save || !chip->pm->resume)
 749                        pr_err("gpio: %s has missing PM functions\n",
 750                               gc->label);
 751        } else
 752                pr_err("gpio: %s has no PM function\n", gc->label);
 753#endif
 754
 755        /* gpiochip_add() prints own failure message on error. */
 756        ret = gpiochip_add(gc);
 757        if (ret >= 0)
 758                s3c_gpiolib_track(chip);
 759}
 760
 761static void __init s3c24xx_gpiolib_add_chips(struct samsung_gpio_chip *chip,
 762                                             int nr_chips, void __iomem *base)
 763{
 764        int i;
 765        struct gpio_chip *gc = &chip->chip;
 766
 767        for (i = 0 ; i < nr_chips; i++, chip++) {
 768                /* skip banks not present on SoC */
 769                if (chip->chip.base >= S3C_GPIO_END)
 770                        continue;
 771
 772                if (!chip->config)
 773                        chip->config = &s3c24xx_gpiocfg_default;
 774                if (!chip->pm)
 775                        chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
 776                if ((base != NULL) && (chip->base == NULL))
 777                        chip->base = base + ((i) * 0x10);
 778
 779                if (!gc->direction_input)
 780                        gc->direction_input = samsung_gpiolib_2bit_input;
 781                if (!gc->direction_output)
 782                        gc->direction_output = samsung_gpiolib_2bit_output;
 783
 784                samsung_gpiolib_add(chip);
 785        }
 786}
 787
 788static void __init samsung_gpiolib_add_2bit_chips(struct samsung_gpio_chip *chip,
 789                                                  int nr_chips, void __iomem *base,
 790                                                  unsigned int offset)
 791{
 792        int i;
 793
 794        for (i = 0 ; i < nr_chips; i++, chip++) {
 795                chip->chip.direction_input = samsung_gpiolib_2bit_input;
 796                chip->chip.direction_output = samsung_gpiolib_2bit_output;
 797
 798                if (!chip->config)
 799                        chip->config = &samsung_gpio_cfgs[7];
 800                if (!chip->pm)
 801                        chip->pm = __gpio_pm(&samsung_gpio_pm_2bit);
 802                if ((base != NULL) && (chip->base == NULL))
 803                        chip->base = base + ((i) * offset);
 804
 805                samsung_gpiolib_add(chip);
 806        }
 807}
 808
 809/*
 810 * samsung_gpiolib_add_4bit_chips - 4bit single register GPIO config.
 811 * @chip: The gpio chip that is being configured.
 812 * @nr_chips: The no of chips (gpio ports) for the GPIO being configured.
 813 *
 814 * This helper deal with the GPIO cases where the control register has 4 bits
 815 * of control per GPIO, generally in the form of:
 816 * 0000 = Input
 817 * 0001 = Output
 818 * others = Special functions (dependent on bank)
 819 *
 820 * Note, since the code to deal with the case where there are two control
 821 * registers instead of one, we do not have a separate set of function
 822 * (samsung_gpiolib_add_4bit2_chips)for each case.
 823 */
 824
 825static void __init samsung_gpiolib_add_4bit_chips(struct samsung_gpio_chip *chip,
 826                                                  int nr_chips, void __iomem *base)
 827{
 828        int i;
 829
 830        for (i = 0 ; i < nr_chips; i++, chip++) {
 831                chip->chip.direction_input = samsung_gpiolib_4bit_input;
 832                chip->chip.direction_output = samsung_gpiolib_4bit_output;
 833
 834                if (!chip->config)
 835                        chip->config = &samsung_gpio_cfgs[2];
 836                if (!chip->pm)
 837                        chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
 838                if ((base != NULL) && (chip->base == NULL))
 839                        chip->base = base + ((i) * 0x20);
 840
 841                chip->bitmap_gpio_int = 0;
 842
 843                samsung_gpiolib_add(chip);
 844        }
 845}
 846
 847static void __init samsung_gpiolib_add_4bit2_chips(struct samsung_gpio_chip *chip,
 848                                                   int nr_chips)
 849{
 850        for (; nr_chips > 0; nr_chips--, chip++) {
 851                chip->chip.direction_input = samsung_gpiolib_4bit2_input;
 852                chip->chip.direction_output = samsung_gpiolib_4bit2_output;
 853
 854                if (!chip->config)
 855                        chip->config = &samsung_gpio_cfgs[2];
 856                if (!chip->pm)
 857                        chip->pm = __gpio_pm(&samsung_gpio_pm_4bit);
 858
 859                samsung_gpiolib_add(chip);
 860        }
 861}
 862
 863int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
 864{
 865        struct samsung_gpio_chip *samsung_chip = container_of(chip, struct samsung_gpio_chip, chip);
 866
 867        return samsung_chip->irq_base + offset;
 868}
 869
 870#ifdef CONFIG_PLAT_S3C24XX
 871static int s3c24xx_gpiolib_fbank_to_irq(struct gpio_chip *chip, unsigned offset)
 872{
 873        if (offset < 4) {
 874                if (soc_is_s3c2412())
 875                        return IRQ_EINT0_2412 + offset;
 876                else
 877                        return IRQ_EINT0 + offset;
 878        }
 879
 880        if (offset < 8)
 881                return IRQ_EINT4 + offset - 4;
 882
 883        return -EINVAL;
 884}
 885#endif
 886
 887#ifdef CONFIG_ARCH_S3C64XX
 888static int s3c64xx_gpiolib_mbank_to_irq(struct gpio_chip *chip, unsigned pin)
 889{
 890        return pin < 5 ? IRQ_EINT(23) + pin : -ENXIO;
 891}
 892
 893static int s3c64xx_gpiolib_lbank_to_irq(struct gpio_chip *chip, unsigned pin)
 894{
 895        return pin >= 8 ? IRQ_EINT(16) + pin - 8 : -ENXIO;
 896}
 897#endif
 898
 899struct samsung_gpio_chip s3c24xx_gpios[] = {
 900#ifdef CONFIG_PLAT_S3C24XX
 901        {
 902                .config = &s3c24xx_gpiocfg_banka,
 903                .chip   = {
 904                        .base                   = S3C2410_GPA(0),
 905                        .owner                  = THIS_MODULE,
 906                        .label                  = "GPIOA",
 907                        .ngpio                  = 27,
 908                        .direction_input        = s3c24xx_gpiolib_banka_input,
 909                        .direction_output       = s3c24xx_gpiolib_banka_output,
 910                },
 911        }, {
 912                .chip   = {
 913                        .base   = S3C2410_GPB(0),
 914                        .owner  = THIS_MODULE,
 915                        .label  = "GPIOB",
 916                        .ngpio  = 11,
 917                },
 918        }, {
 919                .chip   = {
 920                        .base   = S3C2410_GPC(0),
 921                        .owner  = THIS_MODULE,
 922                        .label  = "GPIOC",
 923                        .ngpio  = 16,
 924                },
 925        }, {
 926                .chip   = {
 927                        .base   = S3C2410_GPD(0),
 928                        .owner  = THIS_MODULE,
 929                        .label  = "GPIOD",
 930                        .ngpio  = 16,
 931                },
 932        }, {
 933                .chip   = {
 934                        .base   = S3C2410_GPE(0),
 935                        .label  = "GPIOE",
 936                        .owner  = THIS_MODULE,
 937                        .ngpio  = 16,
 938                },
 939        }, {
 940                .chip   = {
 941                        .base   = S3C2410_GPF(0),
 942                        .owner  = THIS_MODULE,
 943                        .label  = "GPIOF",
 944                        .ngpio  = 8,
 945                        .to_irq = s3c24xx_gpiolib_fbank_to_irq,
 946                },
 947        }, {
 948                .irq_base = IRQ_EINT8,
 949                .chip   = {
 950                        .base   = S3C2410_GPG(0),
 951                        .owner  = THIS_MODULE,
 952                        .label  = "GPIOG",
 953                        .ngpio  = 16,
 954                        .to_irq = samsung_gpiolib_to_irq,
 955                },
 956        }, {
 957                .chip   = {
 958                        .base   = S3C2410_GPH(0),
 959                        .owner  = THIS_MODULE,
 960                        .label  = "GPIOH",
 961                        .ngpio  = 15,
 962                },
 963        },
 964                /* GPIOS for the S3C2443 and later devices. */
 965        {
 966                .base   = S3C2440_GPJCON,
 967                .chip   = {
 968                        .base   = S3C2410_GPJ(0),
 969                        .owner  = THIS_MODULE,
 970                        .label  = "GPIOJ",
 971                        .ngpio  = 16,
 972                },
 973        }, {
 974                .base   = S3C2443_GPKCON,
 975                .chip   = {
 976                        .base   = S3C2410_GPK(0),
 977                        .owner  = THIS_MODULE,
 978                        .label  = "GPIOK",
 979                        .ngpio  = 16,
 980                },
 981        }, {
 982                .base   = S3C2443_GPLCON,
 983                .chip   = {
 984                        .base   = S3C2410_GPL(0),
 985                        .owner  = THIS_MODULE,
 986                        .label  = "GPIOL",
 987                        .ngpio  = 15,
 988                },
 989        }, {
 990                .base   = S3C2443_GPMCON,
 991                .chip   = {
 992                        .base   = S3C2410_GPM(0),
 993                        .owner  = THIS_MODULE,
 994                        .label  = "GPIOM",
 995                        .ngpio  = 2,
 996                },
 997        },
 998#endif
 999};
1000
1001/*
1002 * GPIO bank summary:
1003 *
1004 * Bank GPIOs   Style   SlpCon  ExtInt Group
1005 * A    8       4Bit    Yes     1
1006 * B    7       4Bit    Yes     1
1007 * C    8       4Bit    Yes     2
1008 * D    5       4Bit    Yes     3
1009 * E    5       4Bit    Yes     None
1010 * F    16      2Bit    Yes     4 [1]
1011 * G    7       4Bit    Yes     5
1012 * H    10      4Bit[2] Yes     6
1013 * I    16      2Bit    Yes     None
1014 * J    12      2Bit    Yes     None
1015 * K    16      4Bit[2] No      None
1016 * L    15      4Bit[2] No      None
1017 * M    6       4Bit    No      IRQ_EINT
1018 * N    16      2Bit    No      IRQ_EINT
1019 * O    16      2Bit    Yes     7
1020 * P    15      2Bit    Yes     8
1021 * Q    9       2Bit    Yes     9
1022 *
1023 * [1] BANKF pins 14,15 do not form part of the external interrupt sources
1024 * [2] BANK has two control registers, GPxCON0 and GPxCON1
1025 */
1026
1027static struct samsung_gpio_chip s3c64xx_gpios_4bit[] = {
1028#ifdef CONFIG_ARCH_S3C64XX
1029        {
1030                .chip   = {
1031                        .base   = S3C64XX_GPA(0),
1032                        .ngpio  = S3C64XX_GPIO_A_NR,
1033                        .label  = "GPA",
1034                },
1035        }, {
1036                .chip   = {
1037                        .base   = S3C64XX_GPB(0),
1038                        .ngpio  = S3C64XX_GPIO_B_NR,
1039                        .label  = "GPB",
1040                },
1041        }, {
1042                .chip   = {
1043                        .base   = S3C64XX_GPC(0),
1044                        .ngpio  = S3C64XX_GPIO_C_NR,
1045                        .label  = "GPC",
1046                },
1047        }, {
1048                .chip   = {
1049                        .base   = S3C64XX_GPD(0),
1050                        .ngpio  = S3C64XX_GPIO_D_NR,
1051                        .label  = "GPD",
1052                },
1053        }, {
1054                .config = &samsung_gpio_cfgs[0],
1055                .chip   = {
1056                        .base   = S3C64XX_GPE(0),
1057                        .ngpio  = S3C64XX_GPIO_E_NR,
1058                        .label  = "GPE",
1059                },
1060        }, {
1061                .base   = S3C64XX_GPG_BASE,
1062                .chip   = {
1063                        .base   = S3C64XX_GPG(0),
1064                        .ngpio  = S3C64XX_GPIO_G_NR,
1065                        .label  = "GPG",
1066                },
1067        }, {
1068                .base   = S3C64XX_GPM_BASE,
1069                .config = &samsung_gpio_cfgs[1],
1070                .chip   = {
1071                        .base   = S3C64XX_GPM(0),
1072                        .ngpio  = S3C64XX_GPIO_M_NR,
1073                        .label  = "GPM",
1074                        .to_irq = s3c64xx_gpiolib_mbank_to_irq,
1075                },
1076        },
1077#endif
1078};
1079
1080static struct samsung_gpio_chip s3c64xx_gpios_4bit2[] = {
1081#ifdef CONFIG_ARCH_S3C64XX
1082        {
1083                .base   = S3C64XX_GPH_BASE + 0x4,
1084                .chip   = {
1085                        .base   = S3C64XX_GPH(0),
1086                        .ngpio  = S3C64XX_GPIO_H_NR,
1087                        .label  = "GPH",
1088                },
1089        }, {
1090                .base   = S3C64XX_GPK_BASE + 0x4,
1091                .config = &samsung_gpio_cfgs[0],
1092                .chip   = {
1093                        .base   = S3C64XX_GPK(0),
1094                        .ngpio  = S3C64XX_GPIO_K_NR,
1095                        .label  = "GPK",
1096                },
1097        }, {
1098                .base   = S3C64XX_GPL_BASE + 0x4,
1099                .config = &samsung_gpio_cfgs[1],
1100                .chip   = {
1101                        .base   = S3C64XX_GPL(0),
1102                        .ngpio  = S3C64XX_GPIO_L_NR,
1103                        .label  = "GPL",
1104                        .to_irq = s3c64xx_gpiolib_lbank_to_irq,
1105                },
1106        },
1107#endif
1108};
1109
1110static struct samsung_gpio_chip s3c64xx_gpios_2bit[] = {
1111#ifdef CONFIG_ARCH_S3C64XX
1112        {
1113                .base   = S3C64XX_GPF_BASE,
1114                .config = &samsung_gpio_cfgs[6],
1115                .chip   = {
1116                        .base   = S3C64XX_GPF(0),
1117                        .ngpio  = S3C64XX_GPIO_F_NR,
1118                        .label  = "GPF",
1119                },
1120        }, {
1121                .config = &samsung_gpio_cfgs[7],
1122                .chip   = {
1123                        .base   = S3C64XX_GPI(0),
1124                        .ngpio  = S3C64XX_GPIO_I_NR,
1125                        .label  = "GPI",
1126                },
1127        }, {
1128                .config = &samsung_gpio_cfgs[7],
1129                .chip   = {
1130                        .base   = S3C64XX_GPJ(0),
1131                        .ngpio  = S3C64XX_GPIO_J_NR,
1132                        .label  = "GPJ",
1133                },
1134        }, {
1135                .config = &samsung_gpio_cfgs[6],
1136                .chip   = {
1137                        .base   = S3C64XX_GPO(0),
1138                        .ngpio  = S3C64XX_GPIO_O_NR,
1139                        .label  = "GPO",
1140                },
1141        }, {
1142                .config = &samsung_gpio_cfgs[6],
1143                .chip   = {
1144                        .base   = S3C64XX_GPP(0),
1145                        .ngpio  = S3C64XX_GPIO_P_NR,
1146                        .label  = "GPP",
1147                },
1148        }, {
1149                .config = &samsung_gpio_cfgs[6],
1150                .chip   = {
1151                        .base   = S3C64XX_GPQ(0),
1152                        .ngpio  = S3C64XX_GPIO_Q_NR,
1153                        .label  = "GPQ",
1154                },
1155        }, {
1156                .base   = S3C64XX_GPN_BASE,
1157                .irq_base = IRQ_EINT(0),
1158                .config = &samsung_gpio_cfgs[5],
1159                .chip   = {
1160                        .base   = S3C64XX_GPN(0),
1161                        .ngpio  = S3C64XX_GPIO_N_NR,
1162                        .label  = "GPN",
1163                        .to_irq = samsung_gpiolib_to_irq,
1164                },
1165        },
1166#endif
1167};
1168
1169/* TODO: cleanup soc_is_* */
1170static __init int samsung_gpiolib_init(void)
1171{
1172        /*
1173         * Currently there are two drivers that can provide GPIO support for
1174         * Samsung SoCs. For device tree enabled platforms, the new
1175         * pinctrl-samsung driver is used, providing both GPIO and pin control
1176         * interfaces. For legacy (non-DT) platforms this driver is used.
1177         */
1178        if (of_have_populated_dt())
1179                return -ENODEV;
1180
1181        samsung_gpiolib_set_cfg(samsung_gpio_cfgs, ARRAY_SIZE(samsung_gpio_cfgs));
1182
1183        if (soc_is_s3c24xx()) {
1184                s3c24xx_gpiolib_add_chips(s3c24xx_gpios,
1185                                ARRAY_SIZE(s3c24xx_gpios), S3C24XX_VA_GPIO);
1186        } else if (soc_is_s3c64xx()) {
1187                samsung_gpiolib_add_2bit_chips(s3c64xx_gpios_2bit,
1188                                ARRAY_SIZE(s3c64xx_gpios_2bit),
1189                                S3C64XX_VA_GPIO + 0xE0, 0x20);
1190                samsung_gpiolib_add_4bit_chips(s3c64xx_gpios_4bit,
1191                                ARRAY_SIZE(s3c64xx_gpios_4bit),
1192                                S3C64XX_VA_GPIO);
1193                samsung_gpiolib_add_4bit2_chips(s3c64xx_gpios_4bit2,
1194                                ARRAY_SIZE(s3c64xx_gpios_4bit2));
1195        } else {
1196                WARN(1, "Unknown SoC in gpio-samsung, no GPIOs added\n");
1197                return -ENODEV;
1198        }
1199
1200        return 0;
1201}
1202core_initcall(samsung_gpiolib_init);
1203
1204int s3c_gpio_cfgpin(unsigned int pin, unsigned int config)
1205{
1206        struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
1207        unsigned long flags;
1208        int offset;
1209        int ret;
1210
1211        if (!chip)
1212                return -EINVAL;
1213
1214        offset = pin - chip->chip.base;
1215
1216        samsung_gpio_lock(chip, flags);
1217        ret = samsung_gpio_do_setcfg(chip, offset, config);
1218        samsung_gpio_unlock(chip, flags);
1219
1220        return ret;
1221}
1222EXPORT_SYMBOL(s3c_gpio_cfgpin);
1223
1224int s3c_gpio_cfgpin_range(unsigned int start, unsigned int nr,
1225                          unsigned int cfg)
1226{
1227        int ret;
1228
1229        for (; nr > 0; nr--, start++) {
1230                ret = s3c_gpio_cfgpin(start, cfg);
1231                if (ret != 0)
1232                        return ret;
1233        }
1234
1235        return 0;
1236}
1237EXPORT_SYMBOL_GPL(s3c_gpio_cfgpin_range);
1238
1239int s3c_gpio_cfgall_range(unsigned int start, unsigned int nr,
1240                          unsigned int cfg, samsung_gpio_pull_t pull)
1241{
1242        int ret;
1243
1244        for (; nr > 0; nr--, start++) {
1245                s3c_gpio_setpull(start, pull);
1246                ret = s3c_gpio_cfgpin(start, cfg);
1247                if (ret != 0)
1248                        return ret;
1249        }
1250
1251        return 0;
1252}
1253EXPORT_SYMBOL_GPL(s3c_gpio_cfgall_range);
1254
1255unsigned s3c_gpio_getcfg(unsigned int pin)
1256{
1257        struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
1258        unsigned long flags;
1259        unsigned ret = 0;
1260        int offset;
1261
1262        if (chip) {
1263                offset = pin - chip->chip.base;
1264
1265                samsung_gpio_lock(chip, flags);
1266                ret = samsung_gpio_do_getcfg(chip, offset);
1267                samsung_gpio_unlock(chip, flags);
1268        }
1269
1270        return ret;
1271}
1272EXPORT_SYMBOL(s3c_gpio_getcfg);
1273
1274int s3c_gpio_setpull(unsigned int pin, samsung_gpio_pull_t pull)
1275{
1276        struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
1277        unsigned long flags;
1278        int offset, ret;
1279
1280        if (!chip)
1281                return -EINVAL;
1282
1283        offset = pin - chip->chip.base;
1284
1285        samsung_gpio_lock(chip, flags);
1286        ret = samsung_gpio_do_setpull(chip, offset, pull);
1287        samsung_gpio_unlock(chip, flags);
1288
1289        return ret;
1290}
1291EXPORT_SYMBOL(s3c_gpio_setpull);
1292
1293samsung_gpio_pull_t s3c_gpio_getpull(unsigned int pin)
1294{
1295        struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
1296        unsigned long flags;
1297        int offset;
1298        u32 pup = 0;
1299
1300        if (chip) {
1301                offset = pin - chip->chip.base;
1302
1303                samsung_gpio_lock(chip, flags);
1304                pup = samsung_gpio_do_getpull(chip, offset);
1305                samsung_gpio_unlock(chip, flags);
1306        }
1307
1308        return (__force samsung_gpio_pull_t)pup;
1309}
1310EXPORT_SYMBOL(s3c_gpio_getpull);
1311
1312#ifdef CONFIG_PLAT_S3C24XX
1313unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change)
1314{
1315        unsigned long flags;
1316        unsigned long misccr;
1317
1318        local_irq_save(flags);
1319        misccr = __raw_readl(S3C24XX_MISCCR);
1320        misccr &= ~clear;
1321        misccr ^= change;
1322        __raw_writel(misccr, S3C24XX_MISCCR);
1323        local_irq_restore(flags);
1324
1325        return misccr;
1326}
1327EXPORT_SYMBOL(s3c2410_modify_misccr);
1328#endif
1329