Merge branch 'gpio/next' of git://git.secretlab.ca/git/linux-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 28 May 2011 17:56:34 +0000 (10:56 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 28 May 2011 17:56:34 +0000 (10:56 -0700)
* 'gpio/next' of git://git.secretlab.ca/git/linux-2.6:
  gpio/pch_gpio: Support new device ML7223
  gpio: make gpio_{request,free}_array gpio array parameter const
  GPIO: OMAP: move to drivers/gpio
  GPIO: OMAP: move register offset defines into <plat/gpio.h>
  gpio: Convert gpio_is_valid to return bool
  gpio: Move the s5pc100 GPIO to drivers/gpio
  gpio: Move the s5pv210 GPIO to drivers/gpio
  gpio: Move the exynos4 GPIO to drivers/gpio
  gpio: Move to Samsung common GPIO library to drivers/gpio
  gpio/nomadik: add function to read GPIO pull down status
  gpio/nomadik: show all pins in debug
  gpio: move Nomadik GPIO driver to drivers/gpio
  gpio: move U300 GPIO driver to drivers/gpio
  langwell_gpio: add runtime pm support
  gpio/pca953x: Add support for pca9574 and pca9575 devices
  gpio/cs5535: Show explicit dependency between gpio_cs5535 and mfd_cs5535

34 files changed:
arch/arm/mach-exynos4/Makefile
arch/arm/mach-exynos4/gpiolib.c [deleted file]
arch/arm/mach-nomadik/Kconfig
arch/arm/mach-s5pc100/Makefile
arch/arm/mach-s5pc100/gpiolib.c [deleted file]
arch/arm/mach-s5pv210/Makefile
arch/arm/mach-s5pv210/gpiolib.c [deleted file]
arch/arm/mach-u300/Makefile
arch/arm/mach-u300/gpio.c [deleted file]
arch/arm/mach-ux500/Kconfig
arch/arm/plat-nomadik/Kconfig
arch/arm/plat-nomadik/Makefile
arch/arm/plat-nomadik/gpio.c [deleted file]
arch/arm/plat-nomadik/include/plat/gpio.h
arch/arm/plat-omap/Makefile
arch/arm/plat-omap/gpio.c [deleted file]
arch/arm/plat-omap/include/plat/gpio.h
arch/arm/plat-samsung/Makefile
arch/arm/plat-samsung/gpiolib.c [deleted file]
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/gpio-exynos4.c [new file with mode: 0644]
drivers/gpio/gpio-nomadik.c [new file with mode: 0644]
drivers/gpio/gpio-omap.c [new file with mode: 0644]
drivers/gpio/gpio-plat-samsung.c [new file with mode: 0644]
drivers/gpio/gpio-s5pc100.c [new file with mode: 0644]
drivers/gpio/gpio-s5pv210.c [new file with mode: 0644]
drivers/gpio/gpio-u300.c [new file with mode: 0644]
drivers/gpio/gpiolib.c
drivers/gpio/langwell_gpio.c
drivers/gpio/pca953x.c
drivers/gpio/pch_gpio.c
include/asm-generic/gpio.h
include/linux/gpio.h

index 683fc387c8af39d612b91b5f1e1074da24ea2b73..a9bb94fabaa71c3ca31e823d9ad87aa409f0bfb2 100644 (file)
@@ -13,7 +13,7 @@ obj-                          :=
 # Core support for EXYNOS4 system
 
 obj-$(CONFIG_CPU_EXYNOS4210)   += cpu.o init.o clock.o irq-combiner.o
-obj-$(CONFIG_CPU_EXYNOS4210)   += setup-i2c0.o gpiolib.o irq-eint.o dma.o
+obj-$(CONFIG_CPU_EXYNOS4210)   += setup-i2c0.o irq-eint.o dma.o
 obj-$(CONFIG_PM)               += pm.o sleep.o
 obj-$(CONFIG_CPU_FREQ)         += cpufreq.o
 obj-$(CONFIG_CPU_IDLE)         += cpuidle.o
diff --git a/arch/arm/mach-exynos4/gpiolib.c b/arch/arm/mach-exynos4/gpiolib.c
deleted file mode 100644 (file)
index d54ca6a..0000000
+++ /dev/null
@@ -1,365 +0,0 @@
-/* linux/arch/arm/mach-exynos4/gpiolib.c
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * EXYNOS4 - GPIOlib support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-
-#include <mach/map.h>
-
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-
-static struct s3c_gpio_cfg gpio_cfg = {
-       .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
-       .set_pull       = s3c_gpio_setpull_updown,
-       .get_pull       = s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_cfg_noint = {
-       .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
-       .set_pull       = s3c_gpio_setpull_updown,
-       .get_pull       = s3c_gpio_getpull_updown,
-};
-
-/*
- * Following are the gpio banks in v310.
- *
- * The 'config' member when left to NULL, is initialized to the default
- * structure gpio_cfg in the init function below.
- *
- * The 'base' member is also initialized in the init function below.
- * Note: The initialization of 'base' member of s3c_gpio_chip structure
- * uses the above macro and depends on the banks being listed in order here.
- */
-static struct s3c_gpio_chip exynos4_gpio_part1_4bit[] = {
-       {
-               .chip   = {
-                       .base   = EXYNOS4_GPA0(0),
-                       .ngpio  = EXYNOS4_GPIO_A0_NR,
-                       .label  = "GPA0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPA1(0),
-                       .ngpio  = EXYNOS4_GPIO_A1_NR,
-                       .label  = "GPA1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPB(0),
-                       .ngpio  = EXYNOS4_GPIO_B_NR,
-                       .label  = "GPB",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPC0(0),
-                       .ngpio  = EXYNOS4_GPIO_C0_NR,
-                       .label  = "GPC0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPC1(0),
-                       .ngpio  = EXYNOS4_GPIO_C1_NR,
-                       .label  = "GPC1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPD0(0),
-                       .ngpio  = EXYNOS4_GPIO_D0_NR,
-                       .label  = "GPD0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPD1(0),
-                       .ngpio  = EXYNOS4_GPIO_D1_NR,
-                       .label  = "GPD1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPE0(0),
-                       .ngpio  = EXYNOS4_GPIO_E0_NR,
-                       .label  = "GPE0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPE1(0),
-                       .ngpio  = EXYNOS4_GPIO_E1_NR,
-                       .label  = "GPE1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPE2(0),
-                       .ngpio  = EXYNOS4_GPIO_E2_NR,
-                       .label  = "GPE2",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPE3(0),
-                       .ngpio  = EXYNOS4_GPIO_E3_NR,
-                       .label  = "GPE3",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPE4(0),
-                       .ngpio  = EXYNOS4_GPIO_E4_NR,
-                       .label  = "GPE4",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPF0(0),
-                       .ngpio  = EXYNOS4_GPIO_F0_NR,
-                       .label  = "GPF0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPF1(0),
-                       .ngpio  = EXYNOS4_GPIO_F1_NR,
-                       .label  = "GPF1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPF2(0),
-                       .ngpio  = EXYNOS4_GPIO_F2_NR,
-                       .label  = "GPF2",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPF3(0),
-                       .ngpio  = EXYNOS4_GPIO_F3_NR,
-                       .label  = "GPF3",
-               },
-       },
-};
-
-static struct s3c_gpio_chip exynos4_gpio_part2_4bit[] = {
-       {
-               .chip   = {
-                       .base   = EXYNOS4_GPJ0(0),
-                       .ngpio  = EXYNOS4_GPIO_J0_NR,
-                       .label  = "GPJ0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPJ1(0),
-                       .ngpio  = EXYNOS4_GPIO_J1_NR,
-                       .label  = "GPJ1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPK0(0),
-                       .ngpio  = EXYNOS4_GPIO_K0_NR,
-                       .label  = "GPK0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPK1(0),
-                       .ngpio  = EXYNOS4_GPIO_K1_NR,
-                       .label  = "GPK1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPK2(0),
-                       .ngpio  = EXYNOS4_GPIO_K2_NR,
-                       .label  = "GPK2",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPK3(0),
-                       .ngpio  = EXYNOS4_GPIO_K3_NR,
-                       .label  = "GPK3",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPL0(0),
-                       .ngpio  = EXYNOS4_GPIO_L0_NR,
-                       .label  = "GPL0",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPL1(0),
-                       .ngpio  = EXYNOS4_GPIO_L1_NR,
-                       .label  = "GPL1",
-               },
-       }, {
-               .chip   = {
-                       .base   = EXYNOS4_GPL2(0),
-                       .ngpio  = EXYNOS4_GPIO_L2_NR,
-                       .label  = "GPL2",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = EXYNOS4_GPY0(0),
-                       .ngpio  = EXYNOS4_GPIO_Y0_NR,
-                       .label  = "GPY0",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = EXYNOS4_GPY1(0),
-                       .ngpio  = EXYNOS4_GPIO_Y1_NR,
-                       .label  = "GPY1",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = EXYNOS4_GPY2(0),
-                       .ngpio  = EXYNOS4_GPIO_Y2_NR,
-                       .label  = "GPY2",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = EXYNOS4_GPY3(0),
-                       .ngpio  = EXYNOS4_GPIO_Y3_NR,
-                       .label  = "GPY3",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = EXYNOS4_GPY4(0),
-                       .ngpio  = EXYNOS4_GPIO_Y4_NR,
-                       .label  = "GPY4",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = EXYNOS4_GPY5(0),
-                       .ngpio  = EXYNOS4_GPIO_Y5_NR,
-                       .label  = "GPY5",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = EXYNOS4_GPY6(0),
-                       .ngpio  = EXYNOS4_GPIO_Y6_NR,
-                       .label  = "GPY6",
-               },
-       }, {
-               .base   = (S5P_VA_GPIO2 + 0xC00),
-               .config = &gpio_cfg_noint,
-               .irq_base = IRQ_EINT(0),
-               .chip   = {
-                       .base   = EXYNOS4_GPX0(0),
-                       .ngpio  = EXYNOS4_GPIO_X0_NR,
-                       .label  = "GPX0",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .base   = (S5P_VA_GPIO2 + 0xC20),
-               .config = &gpio_cfg_noint,
-               .irq_base = IRQ_EINT(8),
-               .chip   = {
-                       .base   = EXYNOS4_GPX1(0),
-                       .ngpio  = EXYNOS4_GPIO_X1_NR,
-                       .label  = "GPX1",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .base   = (S5P_VA_GPIO2 + 0xC40),
-               .config = &gpio_cfg_noint,
-               .irq_base = IRQ_EINT(16),
-               .chip   = {
-                       .base   = EXYNOS4_GPX2(0),
-                       .ngpio  = EXYNOS4_GPIO_X2_NR,
-                       .label  = "GPX2",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .base   = (S5P_VA_GPIO2 + 0xC60),
-               .config = &gpio_cfg_noint,
-               .irq_base = IRQ_EINT(24),
-               .chip   = {
-                       .base   = EXYNOS4_GPX3(0),
-                       .ngpio  = EXYNOS4_GPIO_X3_NR,
-                       .label  = "GPX3",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       },
-};
-
-static struct s3c_gpio_chip exynos4_gpio_part3_4bit[] = {
-       {
-               .chip   = {
-                       .base   = EXYNOS4_GPZ(0),
-                       .ngpio  = EXYNOS4_GPIO_Z_NR,
-                       .label  = "GPZ",
-               },
-       },
-};
-
-static __init int exynos4_gpiolib_init(void)
-{
-       struct s3c_gpio_chip *chip;
-       int i;
-       int group = 0;
-       int nr_chips;
-
-       /* GPIO part 1 */
-
-       chip = exynos4_gpio_part1_4bit;
-       nr_chips = ARRAY_SIZE(exynos4_gpio_part1_4bit);
-
-       for (i = 0; i < nr_chips; i++, chip++) {
-               if (chip->config == NULL) {
-                       chip->config = &gpio_cfg;
-                       /* Assign the GPIO interrupt group */
-                       chip->group = group++;
-               }
-               if (chip->base == NULL)
-                       chip->base = S5P_VA_GPIO1 + (i) * 0x20;
-       }
-
-       samsung_gpiolib_add_4bit_chips(exynos4_gpio_part1_4bit, nr_chips);
-
-       /* GPIO part 2 */
-
-       chip = exynos4_gpio_part2_4bit;
-       nr_chips = ARRAY_SIZE(exynos4_gpio_part2_4bit);
-
-       for (i = 0; i < nr_chips; i++, chip++) {
-               if (chip->config == NULL) {
-                       chip->config = &gpio_cfg;
-                       /* Assign the GPIO interrupt group */
-                       chip->group = group++;
-               }
-               if (chip->base == NULL)
-                       chip->base = S5P_VA_GPIO2 + (i) * 0x20;
-       }
-
-       samsung_gpiolib_add_4bit_chips(exynos4_gpio_part2_4bit, nr_chips);
-
-       /* GPIO part 3 */
-
-       chip = exynos4_gpio_part3_4bit;
-       nr_chips = ARRAY_SIZE(exynos4_gpio_part3_4bit);
-
-       for (i = 0; i < nr_chips; i++, chip++) {
-               if (chip->config == NULL) {
-                       chip->config = &gpio_cfg;
-                       /* Assign the GPIO interrupt group */
-                       chip->group = group++;
-               }
-               if (chip->base == NULL)
-                       chip->base = S5P_VA_GPIO3 + (i) * 0x20;
-       }
-
-       samsung_gpiolib_add_4bit_chips(exynos4_gpio_part3_4bit, nr_chips);
-       s5p_register_gpioint_bank(IRQ_GPIO_XA, 0, IRQ_GPIO1_NR_GROUPS);
-       s5p_register_gpioint_bank(IRQ_GPIO_XB, IRQ_GPIO1_NR_GROUPS, IRQ_GPIO2_NR_GROUPS);
-
-       return 0;
-}
-core_initcall(exynos4_gpiolib_init);
index 71f3ea623974b487d8bd44cb3dd6edbf24d21fb8..3c5e0f522e9ce507f6ceb95fcd605ef3bd734334 100644 (file)
@@ -6,7 +6,6 @@ config MACH_NOMADIK_8815NHK
        bool "ST 8815 Nomadik Hardware Kit (evaluation board)"
        select NOMADIK_8815
        select HAS_MTU
-       select NOMADIK_GPIO
 
 endmenu
 
index eecab57d2e5d4f4727b43d51818d59c5968df51d..a5e6e608b498ccd1b285123550dc13ad5a5e9d1e 100644 (file)
@@ -11,7 +11,7 @@ obj-                          :=
 
 # Core support for S5PC100 system
 
-obj-$(CONFIG_CPU_S5PC100)      += cpu.o init.o clock.o gpiolib.o
+obj-$(CONFIG_CPU_S5PC100)      += cpu.o init.o clock.o
 obj-$(CONFIG_CPU_S5PC100)      += setup-i2c0.o
 obj-$(CONFIG_CPU_S5PC100)      += dma.o
 
diff --git a/arch/arm/mach-s5pc100/gpiolib.c b/arch/arm/mach-s5pc100/gpiolib.c
deleted file mode 100644 (file)
index 2842394..0000000
+++ /dev/null
@@ -1,355 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/gpiolib.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- *  Copyright 2009 Samsung Electronics Co
- *  Kyungmin Park <kyungmin.park@samsung.com>
- *
- * S5PC100 - GPIOlib support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-
-#include <mach/map.h>
-#include <mach/regs-gpio.h>
-
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-
-/* S5PC100 GPIO bank summary:
- *
- * Bank        GPIOs   Style   INT Type
- * A0  8       4Bit    GPIO_INT0
- * A1  5       4Bit    GPIO_INT1
- * B   8       4Bit    GPIO_INT2
- * C   5       4Bit    GPIO_INT3
- * D   7       4Bit    GPIO_INT4
- * E0  8       4Bit    GPIO_INT5
- * E1  6       4Bit    GPIO_INT6
- * F0  8       4Bit    GPIO_INT7
- * F1  8       4Bit    GPIO_INT8
- * F2  8       4Bit    GPIO_INT9
- * F3  4       4Bit    GPIO_INT10
- * G0  8       4Bit    GPIO_INT11
- * G1  3       4Bit    GPIO_INT12
- * G2  7       4Bit    GPIO_INT13
- * G3  7       4Bit    GPIO_INT14
- * H0  8       4Bit    WKUP_INT
- * H1  8       4Bit    WKUP_INT
- * H2  8       4Bit    WKUP_INT
- * H3  8       4Bit    WKUP_INT
- * I   8       4Bit    GPIO_INT15
- * J0  8       4Bit    GPIO_INT16
- * J1  5       4Bit    GPIO_INT17
- * J2  8       4Bit    GPIO_INT18
- * J3  8       4Bit    GPIO_INT19
- * J4  4       4Bit    GPIO_INT20
- * K0  8       4Bit    None
- * K1  6       4Bit    None
- * K2  8       4Bit    None
- * K3  8       4Bit    None
- * L0  8       4Bit    None
- * L1  8       4Bit    None
- * L2  8       4Bit    None
- * L3  8       4Bit    None
- */
-
-static struct s3c_gpio_cfg gpio_cfg = {
-       .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
-       .set_pull       = s3c_gpio_setpull_updown,
-       .get_pull       = s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_cfg_eint = {
-       .cfg_eint       = 0xf,
-       .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
-       .set_pull       = s3c_gpio_setpull_updown,
-       .get_pull       = s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_cfg_noint = {
-       .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
-       .set_pull       = s3c_gpio_setpull_updown,
-       .get_pull       = s3c_gpio_getpull_updown,
-};
-
-/*
- * GPIO bank's base address given the index of the bank in the
- * list of all gpio banks.
- */
-#define S5PC100_BANK_BASE(bank_nr)     (S5P_VA_GPIO + ((bank_nr) * 0x20))
-
-/*
- * Following are the gpio banks in S5PC100.
- *
- * The 'config' member when left to NULL, is initialized to the default
- * structure gpio_cfg in the init function below.
- *
- * The 'base' member is also initialized in the init function below.
- * Note: The initialization of 'base' member of s3c_gpio_chip structure
- * uses the above macro and depends on the banks being listed in order here.
- */
-static struct s3c_gpio_chip s5pc100_gpio_chips[] = {
-       {
-               .chip   = {
-                       .base   = S5PC100_GPA0(0),
-                       .ngpio  = S5PC100_GPIO_A0_NR,
-                       .label  = "GPA0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPA1(0),
-                       .ngpio  = S5PC100_GPIO_A1_NR,
-                       .label  = "GPA1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPB(0),
-                       .ngpio  = S5PC100_GPIO_B_NR,
-                       .label  = "GPB",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPC(0),
-                       .ngpio  = S5PC100_GPIO_C_NR,
-                       .label  = "GPC",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPD(0),
-                       .ngpio  = S5PC100_GPIO_D_NR,
-                       .label  = "GPD",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPE0(0),
-                       .ngpio  = S5PC100_GPIO_E0_NR,
-                       .label  = "GPE0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPE1(0),
-                       .ngpio  = S5PC100_GPIO_E1_NR,
-                       .label  = "GPE1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPF0(0),
-                       .ngpio  = S5PC100_GPIO_F0_NR,
-                       .label  = "GPF0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPF1(0),
-                       .ngpio  = S5PC100_GPIO_F1_NR,
-                       .label  = "GPF1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPF2(0),
-                       .ngpio  = S5PC100_GPIO_F2_NR,
-                       .label  = "GPF2",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPF3(0),
-                       .ngpio  = S5PC100_GPIO_F3_NR,
-                       .label  = "GPF3",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPG0(0),
-                       .ngpio  = S5PC100_GPIO_G0_NR,
-                       .label  = "GPG0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPG1(0),
-                       .ngpio  = S5PC100_GPIO_G1_NR,
-                       .label  = "GPG1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPG2(0),
-                       .ngpio  = S5PC100_GPIO_G2_NR,
-                       .label  = "GPG2",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPG3(0),
-                       .ngpio  = S5PC100_GPIO_G3_NR,
-                       .label  = "GPG3",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPI(0),
-                       .ngpio  = S5PC100_GPIO_I_NR,
-                       .label  = "GPI",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPJ0(0),
-                       .ngpio  = S5PC100_GPIO_J0_NR,
-                       .label  = "GPJ0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPJ1(0),
-                       .ngpio  = S5PC100_GPIO_J1_NR,
-                       .label  = "GPJ1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPJ2(0),
-                       .ngpio  = S5PC100_GPIO_J2_NR,
-                       .label  = "GPJ2",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPJ3(0),
-                       .ngpio  = S5PC100_GPIO_J3_NR,
-                       .label  = "GPJ3",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PC100_GPJ4(0),
-                       .ngpio  = S5PC100_GPIO_J4_NR,
-                       .label  = "GPJ4",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PC100_GPK0(0),
-                       .ngpio  = S5PC100_GPIO_K0_NR,
-                       .label  = "GPK0",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PC100_GPK1(0),
-                       .ngpio  = S5PC100_GPIO_K1_NR,
-                       .label  = "GPK1",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PC100_GPK2(0),
-                       .ngpio  = S5PC100_GPIO_K2_NR,
-                       .label  = "GPK2",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PC100_GPK3(0),
-                       .ngpio  = S5PC100_GPIO_K3_NR,
-                       .label  = "GPK3",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PC100_GPL0(0),
-                       .ngpio  = S5PC100_GPIO_L0_NR,
-                       .label  = "GPL0",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PC100_GPL1(0),
-                       .ngpio  = S5PC100_GPIO_L1_NR,
-                       .label  = "GPL1",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PC100_GPL2(0),
-                       .ngpio  = S5PC100_GPIO_L2_NR,
-                       .label  = "GPL2",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PC100_GPL3(0),
-                       .ngpio  = S5PC100_GPIO_L3_NR,
-                       .label  = "GPL3",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PC100_GPL4(0),
-                       .ngpio  = S5PC100_GPIO_L4_NR,
-                       .label  = "GPL4",
-               },
-       }, {
-               .base   = (S5P_VA_GPIO + 0xC00),
-               .config = &gpio_cfg_eint,
-               .irq_base = IRQ_EINT(0),
-               .chip   = {
-                       .base   = S5PC100_GPH0(0),
-                       .ngpio  = S5PC100_GPIO_H0_NR,
-                       .label  = "GPH0",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .base   = (S5P_VA_GPIO + 0xC20),
-               .config = &gpio_cfg_eint,
-               .irq_base = IRQ_EINT(8),
-               .chip   = {
-                       .base   = S5PC100_GPH1(0),
-                       .ngpio  = S5PC100_GPIO_H1_NR,
-                       .label  = "GPH1",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .base   = (S5P_VA_GPIO + 0xC40),
-               .config = &gpio_cfg_eint,
-               .irq_base = IRQ_EINT(16),
-               .chip   = {
-                       .base   = S5PC100_GPH2(0),
-                       .ngpio  = S5PC100_GPIO_H2_NR,
-                       .label  = "GPH2",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .base   = (S5P_VA_GPIO + 0xC60),
-               .config = &gpio_cfg_eint,
-               .irq_base = IRQ_EINT(24),
-               .chip   = {
-                       .base   = S5PC100_GPH3(0),
-                       .ngpio  = S5PC100_GPIO_H3_NR,
-                       .label  = "GPH3",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       },
-};
-
-static __init int s5pc100_gpiolib_init(void)
-{
-       struct s3c_gpio_chip *chip = s5pc100_gpio_chips;
-       int nr_chips = ARRAY_SIZE(s5pc100_gpio_chips);
-       int gpioint_group = 0;
-       int i;
-
-       for (i = 0; i < nr_chips; i++, chip++) {
-               if (chip->config == NULL) {
-                       chip->config = &gpio_cfg;
-                       chip->group = gpioint_group++;
-               }
-               if (chip->base == NULL)
-                       chip->base = S5PC100_BANK_BASE(i);
-       }
-
-       samsung_gpiolib_add_4bit_chips(s5pc100_gpio_chips, nr_chips);
-       s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
-
-       return 0;
-}
-core_initcall(s5pc100_gpiolib_init);
index 11f17907b4e8ff7024400975851f74fc04f5617b..50907aca006c4d49d70432cca4fe09e69310158a 100644 (file)
@@ -12,7 +12,7 @@ obj-                          :=
 
 # Core support for S5PV210 system
 
-obj-$(CONFIG_CPU_S5PV210)      += cpu.o init.o clock.o dma.o gpiolib.o
+obj-$(CONFIG_CPU_S5PV210)      += cpu.o init.o clock.o dma.o
 obj-$(CONFIG_CPU_S5PV210)      += setup-i2c0.o
 obj-$(CONFIG_S5PV210_PM)       += pm.o sleep.o
 obj-$(CONFIG_CPU_FREQ)         += cpufreq.o
diff --git a/arch/arm/mach-s5pv210/gpiolib.c b/arch/arm/mach-s5pv210/gpiolib.c
deleted file mode 100644 (file)
index 1ba20a7..0000000
+++ /dev/null
@@ -1,288 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/gpiolib.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * S5PV210 - GPIOlib support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-#include <mach/map.h>
-
-static struct s3c_gpio_cfg gpio_cfg = {
-       .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
-       .set_pull       = s3c_gpio_setpull_updown,
-       .get_pull       = s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_cfg_noint = {
-       .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
-       .set_pull       = s3c_gpio_setpull_updown,
-       .get_pull       = s3c_gpio_getpull_updown,
-};
-
-/* GPIO bank's base address given the index of the bank in the
- * list of all gpio banks.
- */
-#define S5PV210_BANK_BASE(bank_nr)     (S5P_VA_GPIO + ((bank_nr) * 0x20))
-
-/*
- * Following are the gpio banks in v210.
- *
- * The 'config' member when left to NULL, is initialized to the default
- * structure gpio_cfg in the init function below.
- *
- * The 'base' member is also initialized in the init function below.
- * Note: The initialization of 'base' member of s3c_gpio_chip structure
- * uses the above macro and depends on the banks being listed in order here.
- */
-static struct s3c_gpio_chip s5pv210_gpio_4bit[] = {
-       {
-               .chip   = {
-                       .base   = S5PV210_GPA0(0),
-                       .ngpio  = S5PV210_GPIO_A0_NR,
-                       .label  = "GPA0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPA1(0),
-                       .ngpio  = S5PV210_GPIO_A1_NR,
-                       .label  = "GPA1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPB(0),
-                       .ngpio  = S5PV210_GPIO_B_NR,
-                       .label  = "GPB",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPC0(0),
-                       .ngpio  = S5PV210_GPIO_C0_NR,
-                       .label  = "GPC0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPC1(0),
-                       .ngpio  = S5PV210_GPIO_C1_NR,
-                       .label  = "GPC1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPD0(0),
-                       .ngpio  = S5PV210_GPIO_D0_NR,
-                       .label  = "GPD0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPD1(0),
-                       .ngpio  = S5PV210_GPIO_D1_NR,
-                       .label  = "GPD1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPE0(0),
-                       .ngpio  = S5PV210_GPIO_E0_NR,
-                       .label  = "GPE0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPE1(0),
-                       .ngpio  = S5PV210_GPIO_E1_NR,
-                       .label  = "GPE1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPF0(0),
-                       .ngpio  = S5PV210_GPIO_F0_NR,
-                       .label  = "GPF0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPF1(0),
-                       .ngpio  = S5PV210_GPIO_F1_NR,
-                       .label  = "GPF1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPF2(0),
-                       .ngpio  = S5PV210_GPIO_F2_NR,
-                       .label  = "GPF2",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPF3(0),
-                       .ngpio  = S5PV210_GPIO_F3_NR,
-                       .label  = "GPF3",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPG0(0),
-                       .ngpio  = S5PV210_GPIO_G0_NR,
-                       .label  = "GPG0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPG1(0),
-                       .ngpio  = S5PV210_GPIO_G1_NR,
-                       .label  = "GPG1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPG2(0),
-                       .ngpio  = S5PV210_GPIO_G2_NR,
-                       .label  = "GPG2",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPG3(0),
-                       .ngpio  = S5PV210_GPIO_G3_NR,
-                       .label  = "GPG3",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PV210_GPI(0),
-                       .ngpio  = S5PV210_GPIO_I_NR,
-                       .label  = "GPI",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPJ0(0),
-                       .ngpio  = S5PV210_GPIO_J0_NR,
-                       .label  = "GPJ0",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPJ1(0),
-                       .ngpio  = S5PV210_GPIO_J1_NR,
-                       .label  = "GPJ1",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPJ2(0),
-                       .ngpio  = S5PV210_GPIO_J2_NR,
-                       .label  = "GPJ2",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPJ3(0),
-                       .ngpio  = S5PV210_GPIO_J3_NR,
-                       .label  = "GPJ3",
-               },
-       }, {
-               .chip   = {
-                       .base   = S5PV210_GPJ4(0),
-                       .ngpio  = S5PV210_GPIO_J4_NR,
-                       .label  = "GPJ4",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PV210_MP01(0),
-                       .ngpio  = S5PV210_GPIO_MP01_NR,
-                       .label  = "MP01",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PV210_MP02(0),
-                       .ngpio  = S5PV210_GPIO_MP02_NR,
-                       .label  = "MP02",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PV210_MP03(0),
-                       .ngpio  = S5PV210_GPIO_MP03_NR,
-                       .label  = "MP03",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PV210_MP04(0),
-                       .ngpio  = S5PV210_GPIO_MP04_NR,
-                       .label  = "MP04",
-               },
-       }, {
-               .config = &gpio_cfg_noint,
-               .chip   = {
-                       .base   = S5PV210_MP05(0),
-                       .ngpio  = S5PV210_GPIO_MP05_NR,
-                       .label  = "MP05",
-               },
-       }, {
-               .base   = (S5P_VA_GPIO + 0xC00),
-               .config = &gpio_cfg_noint,
-               .irq_base = IRQ_EINT(0),
-               .chip   = {
-                       .base   = S5PV210_GPH0(0),
-                       .ngpio  = S5PV210_GPIO_H0_NR,
-                       .label  = "GPH0",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .base   = (S5P_VA_GPIO + 0xC20),
-               .config = &gpio_cfg_noint,
-               .irq_base = IRQ_EINT(8),
-               .chip   = {
-                       .base   = S5PV210_GPH1(0),
-                       .ngpio  = S5PV210_GPIO_H1_NR,
-                       .label  = "GPH1",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .base   = (S5P_VA_GPIO + 0xC40),
-               .config = &gpio_cfg_noint,
-               .irq_base = IRQ_EINT(16),
-               .chip   = {
-                       .base   = S5PV210_GPH2(0),
-                       .ngpio  = S5PV210_GPIO_H2_NR,
-                       .label  = "GPH2",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       }, {
-               .base   = (S5P_VA_GPIO + 0xC60),
-               .config = &gpio_cfg_noint,
-               .irq_base = IRQ_EINT(24),
-               .chip   = {
-                       .base   = S5PV210_GPH3(0),
-                       .ngpio  = S5PV210_GPIO_H3_NR,
-                       .label  = "GPH3",
-                       .to_irq = samsung_gpiolib_to_irq,
-               },
-       },
-};
-
-static __init int s5pv210_gpiolib_init(void)
-{
-       struct s3c_gpio_chip *chip = s5pv210_gpio_4bit;
-       int nr_chips = ARRAY_SIZE(s5pv210_gpio_4bit);
-       int gpioint_group = 0;
-       int i = 0;
-
-       for (i = 0; i < nr_chips; i++, chip++) {
-               if (chip->config == NULL) {
-                       chip->config = &gpio_cfg;
-                       chip->group = gpioint_group++;
-               }
-               if (chip->base == NULL)
-                       chip->base = S5PV210_BANK_BASE(i);
-       }
-
-       samsung_gpiolib_add_4bit_chips(s5pv210_gpio_4bit, nr_chips);
-       s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
-
-       return 0;
-}
-core_initcall(s5pv210_gpiolib_init);
index fab46fe9a71f7b7061d2aa9e8f485f1449b625f1..8fd354aaf0a7f5c9aa309ee69b490e604868fc65 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for the linux kernel, U300 machine.
 #
 
-obj-y          := core.o clock.o timer.o gpio.o padmux.o
+obj-y          := core.o clock.o timer.o padmux.o
 obj-m          :=
 obj-n          :=
 obj-           :=
diff --git a/arch/arm/mach-u300/gpio.c b/arch/arm/mach-u300/gpio.c
deleted file mode 100644 (file)
index d927901..0000000
+++ /dev/null
@@ -1,700 +0,0 @@
-/*
- *
- * arch/arm/mach-u300/gpio.c
- *
- *
- * Copyright (C) 2007-2009 ST-Ericsson AB
- * License terms: GNU General Public License (GPL) version 2
- * U300 GPIO module.
- * This can driver either of the two basic GPIO cores
- * available in the U300 platforms:
- * COH 901 335   - Used in DB3150 (U300 1.0) and DB3200 (U330 1.0)
- * COH 901 571/3 - Used in DB3210 (U365 2.0) and DB3350 (U335 1.0)
- * Notice that you also have inline macros in <asm-arch/gpio.h>
- * Author: Linus Walleij <linus.walleij@stericsson.com>
- * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
- *
- */
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-
-/* Reference to GPIO block clock */
-static struct clk *clk;
-
-/* Memory resource */
-static struct resource *memres;
-static void __iomem *virtbase;
-static struct device *gpiodev;
-
-struct u300_gpio_port {
-       const char *name;
-       int irq;
-       int number;
-};
-
-
-static struct u300_gpio_port gpio_ports[] = {
-       {
-               .name = "gpio0",
-               .number = 0,
-       },
-       {
-               .name = "gpio1",
-               .number = 1,
-       },
-       {
-               .name = "gpio2",
-               .number = 2,
-       },
-#ifdef U300_COH901571_3
-       {
-               .name = "gpio3",
-               .number = 3,
-       },
-       {
-               .name = "gpio4",
-               .number = 4,
-       },
-#ifdef CONFIG_MACH_U300_BS335
-       {
-               .name = "gpio5",
-               .number = 5,
-       },
-       {
-               .name = "gpio6",
-               .number = 6,
-       },
-#endif
-#endif
-
-};
-
-
-#ifdef U300_COH901571_3
-
-/* Default input value */
-#define DEFAULT_OUTPUT_LOW   0
-#define DEFAULT_OUTPUT_HIGH  1
-
-/* GPIO Pull-Up status */
-#define DISABLE_PULL_UP  0
-#define ENABLE_PULL_UP  1
-
-#define GPIO_NOT_USED 0
-#define GPIO_IN       1
-#define GPIO_OUT      2
-
-struct u300_gpio_configuration_data {
-       unsigned char pin_usage;
-       unsigned char default_output_value;
-       unsigned char pull_up;
-};
-
-/* Initial configuration */
-const struct u300_gpio_configuration_data
-u300_gpio_config[U300_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = {
-#ifdef CONFIG_MACH_U300_BS335
-       /* Port 0, pins 0-7 */
-       {
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_OUT, DEFAULT_OUTPUT_HIGH,  DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
-       },
-       /* Port 1, pins 0-7 */
-       {
-               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_OUT, DEFAULT_OUTPUT_HIGH,  DISABLE_PULL_UP},
-               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
-       },
-       /* Port 2, pins 0-7 */
-       {
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP}
-       },
-       /* Port 3, pins 0-7 */
-       {
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
-       },
-       /* Port 4, pins 0-7 */
-       {
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
-       },
-       /* Port 5, pins 0-7 */
-       {
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
-       },
-       /* Port 6, pind 0-7 */
-       {
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
-       }
-#endif
-
-#ifdef CONFIG_MACH_U300_BS365
-       /* Port 0, pins 0-7 */
-       {
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
-       },
-       /* Port 1, pins 0-7 */
-       {
-               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_OUT, DEFAULT_OUTPUT_HIGH,  DISABLE_PULL_UP},
-               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
-       },
-       /* Port 2, pins 0-7 */
-       {
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP}
-       },
-       /* Port 3, pins 0-7 */
-       {
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP}
-       },
-       /* Port 4, pins 0-7 */
-       {
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-               /* These 4 pins doesn't exist on DB3210 */
-               {GPIO_OUT, DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-               {GPIO_OUT, DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-               {GPIO_OUT, DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
-               {GPIO_OUT, DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP}
-       }
-#endif
-};
-#endif
-
-
-/* No users == we can power down GPIO */
-static int gpio_users;
-
-struct gpio_struct {
-       int (*callback)(void *);
-       void *data;
-       int users;
-};
-
-static struct gpio_struct gpio_pin[U300_GPIO_MAX];
-
-/*
- * Let drivers register callback in order to get notified when there is
- * an interrupt on the gpio pin
- */
-int gpio_register_callback(unsigned gpio, int (*func)(void *arg), void *data)
-{
-       if (gpio_pin[gpio].callback)
-               dev_warn(gpiodev, "%s: WARNING: callback already "
-                        "registered for gpio pin#%d\n", __func__, gpio);
-       gpio_pin[gpio].callback = func;
-       gpio_pin[gpio].data = data;
-
-       return 0;
-}
-EXPORT_SYMBOL(gpio_register_callback);
-
-int gpio_unregister_callback(unsigned gpio)
-{
-       if (!gpio_pin[gpio].callback)
-               dev_warn(gpiodev, "%s: WARNING: callback already "
-                        "unregistered for gpio pin#%d\n", __func__, gpio);
-       gpio_pin[gpio].callback = NULL;
-       gpio_pin[gpio].data = NULL;
-
-       return 0;
-}
-EXPORT_SYMBOL(gpio_unregister_callback);
-
-/* Non-zero means valid */
-int gpio_is_valid(int number)
-{
-       if (number >= 0 &&
-           number < (U300_GPIO_NUM_PORTS * U300_GPIO_PINS_PER_PORT))
-               return 1;
-       return 0;
-}
-EXPORT_SYMBOL(gpio_is_valid);
-
-int gpio_request(unsigned gpio, const char *label)
-{
-       if (gpio_pin[gpio].users)
-               return -EINVAL;
-       else
-               gpio_pin[gpio].users++;
-
-       gpio_users++;
-
-       return 0;
-}
-EXPORT_SYMBOL(gpio_request);
-
-void gpio_free(unsigned gpio)
-{
-       gpio_users--;
-       gpio_pin[gpio].users--;
-       if (unlikely(gpio_pin[gpio].users < 0)) {
-               dev_warn(gpiodev, "warning: gpio#%d release mismatch\n",
-                        gpio);
-               gpio_pin[gpio].users = 0;
-       }
-
-       return;
-}
-EXPORT_SYMBOL(gpio_free);
-
-/* This returns zero or nonzero */
-int gpio_get_value(unsigned gpio)
-{
-       return readl(virtbase + U300_GPIO_PXPDIR +
-         PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING) & (1 << (gpio & 0x07));
-}
-EXPORT_SYMBOL(gpio_get_value);
-
-/*
- * We hope that the compiler will optimize away the unused branch
- * in case "value" is a constant
- */
-void gpio_set_value(unsigned gpio, int value)
-{
-       u32 val;
-       unsigned long flags;
-
-       local_irq_save(flags);
-       if (value) {
-               /* set */
-               val = readl(virtbase + U300_GPIO_PXPDOR +
-                 PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING)
-                 & (1 << (gpio & 0x07));
-               writel(val | (1 << (gpio & 0x07)), virtbase +
-                 U300_GPIO_PXPDOR +
-                 PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING);
-       } else {
-               /* clear */
-               val = readl(virtbase + U300_GPIO_PXPDOR +
-                 PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING)
-                 & (1 << (gpio & 0x07));
-               writel(val & ~(1 << (gpio & 0x07)), virtbase +
-                 U300_GPIO_PXPDOR +
-                 PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING);
-       }
-       local_irq_restore(flags);
-}
-EXPORT_SYMBOL(gpio_set_value);
-
-int gpio_direction_input(unsigned gpio)
-{
-       unsigned long flags;
-       u32 val;
-
-       if (gpio > U300_GPIO_MAX)
-               return -EINVAL;
-
-       local_irq_save(flags);
-       val = readl(virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) *
-                               U300_GPIO_PORTX_SPACING);
-       /* Mask out this pin*/
-       val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << ((gpio & 0x07) << 1));
-       /* This is not needed since it sets the bits to zero.*/
-       /* val |= (U300_GPIO_PXPCR_PIN_MODE_INPUT << (gpio*2)); */
-       writel(val, virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) *
-                               U300_GPIO_PORTX_SPACING);
-       local_irq_restore(flags);
-       return 0;
-}
-EXPORT_SYMBOL(gpio_direction_input);
-
-int gpio_direction_output(unsigned gpio, int value)
-{
-       unsigned long flags;
-       u32 val;
-
-       if (gpio > U300_GPIO_MAX)
-               return -EINVAL;
-
-       local_irq_save(flags);
-       val = readl(virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) *
-                               U300_GPIO_PORTX_SPACING);
-       /* Mask out this pin */
-       val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << ((gpio & 0x07) << 1));
-       /*
-        * FIXME: configure for push/pull, open drain or open source per pin
-        * in setup. The current driver will only support push/pull.
-        */
-       val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL
-                       << ((gpio & 0x07) << 1));
-       writel(val, virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) *
-                               U300_GPIO_PORTX_SPACING);
-       gpio_set_value(gpio, value);
-       local_irq_restore(flags);
-       return 0;
-}
-EXPORT_SYMBOL(gpio_direction_output);
-
-/*
- * Enable an IRQ, edge is rising edge (!= 0) or falling edge (==0).
- */
-void enable_irq_on_gpio_pin(unsigned gpio, int edge)
-{
-       u32 val;
-       unsigned long flags;
-       local_irq_save(flags);
-
-       val = readl(virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) *
-                               U300_GPIO_PORTX_SPACING);
-       val |= (1 << (gpio & 0x07));
-       writel(val, virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) *
-                               U300_GPIO_PORTX_SPACING);
-       val = readl(virtbase + U300_GPIO_PXICR + PIN_TO_PORT(gpio) *
-                               U300_GPIO_PORTX_SPACING);
-       if (edge)
-               val |= (1 << (gpio & 0x07));
-       else
-               val &= ~(1 << (gpio & 0x07));
-       writel(val, virtbase + U300_GPIO_PXICR + PIN_TO_PORT(gpio) *
-                               U300_GPIO_PORTX_SPACING);
-       local_irq_restore(flags);
-}
-EXPORT_SYMBOL(enable_irq_on_gpio_pin);
-
-void disable_irq_on_gpio_pin(unsigned gpio)
-{
-       u32 val;
-       unsigned long flags;
-
-       local_irq_save(flags);
-       val = readl(virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) *
-                               U300_GPIO_PORTX_SPACING);
-       val &= ~(1 << (gpio & 0x07));
-       writel(val, virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) *
-                               U300_GPIO_PORTX_SPACING);
-       local_irq_restore(flags);
-}
-EXPORT_SYMBOL(disable_irq_on_gpio_pin);
-
-/* Enable (value == 0) or disable (value == 1) internal pullup */
-void gpio_pullup(unsigned gpio, int value)
-{
-       u32 val;
-       unsigned long flags;
-
-       local_irq_save(flags);
-       if (value) {
-               val = readl(virtbase + U300_GPIO_PXPER + PIN_TO_PORT(gpio) *
-                                       U300_GPIO_PORTX_SPACING);
-               writel(val | (1 << (gpio & 0x07)), virtbase + U300_GPIO_PXPER +
-                               PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING);
-       } else {
-               val = readl(virtbase + U300_GPIO_PXPER + PIN_TO_PORT(gpio) *
-                                       U300_GPIO_PORTX_SPACING);
-               writel(val & ~(1 << (gpio & 0x07)), virtbase + U300_GPIO_PXPER +
-                               PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING);
-       }
-       local_irq_restore(flags);
-}
-EXPORT_SYMBOL(gpio_pullup);
-
-static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
-{
-       struct u300_gpio_port *port = dev_id;
-       u32 val;
-       int pin;
-
-       /* Read event register */
-       val = readl(virtbase + U300_GPIO_PXIEV + port->number *
-                               U300_GPIO_PORTX_SPACING);
-       /* Mask with enable register */
-       val &= readl(virtbase + U300_GPIO_PXIEV + port->number *
-                               U300_GPIO_PORTX_SPACING);
-       /* Mask relevant bits */
-       val &= U300_GPIO_PXIEV_ALL_IRQ_EVENT_MASK;
-       /* ACK IRQ (clear event) */
-       writel(val, virtbase + U300_GPIO_PXIEV + port->number *
-                               U300_GPIO_PORTX_SPACING);
-       /* Print message */
-       while (val != 0) {
-               unsigned gpio;
-
-               pin = __ffs(val);
-               /* mask off this pin */
-               val &= ~(1 << pin);
-               gpio = (port->number << 3) + pin;
-
-               if (gpio_pin[gpio].callback)
-                       (void)gpio_pin[gpio].callback(gpio_pin[gpio].data);
-               else
-                       dev_dbg(gpiodev, "stray GPIO IRQ on line %d\n",
-                              gpio);
-       }
-       return IRQ_HANDLED;
-}
-
-static void gpio_set_initial_values(void)
-{
-#ifdef U300_COH901571_3
-       int i, j;
-       unsigned long flags;
-       u32 val;
-
-       /* Write default values to all pins */
-       for (i = 0; i < U300_GPIO_NUM_PORTS; i++) {
-               val = 0;
-               for (j = 0; j < 8; j++)
-                       val |= (u32) (u300_gpio_config[i][j].default_output_value != DEFAULT_OUTPUT_LOW) << j;
-               local_irq_save(flags);
-               writel(val, virtbase + U300_GPIO_PXPDOR + i * U300_GPIO_PORTX_SPACING);
-               local_irq_restore(flags);
-       }
-
-       /*
-        * Put all pins that are set to either 'GPIO_OUT' or 'GPIO_NOT_USED'
-        * to output and 'GPIO_IN' to input for each port. And initialize
-        * default value on outputs.
-        */
-       for (i = 0; i < U300_GPIO_NUM_PORTS; i++) {
-               for (j = 0; j < U300_GPIO_PINS_PER_PORT; j++) {
-                       local_irq_save(flags);
-                       val = readl(virtbase + U300_GPIO_PXPCR +
-                                        i * U300_GPIO_PORTX_SPACING);
-                       /* Mask out this pin */
-                       val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << (j << 1));
-
-                       if (u300_gpio_config[i][j].pin_usage != GPIO_IN)
-                               val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL << (j << 1));
-                       writel(val, virtbase + U300_GPIO_PXPCR +
-                                        i * U300_GPIO_PORTX_SPACING);
-                       local_irq_restore(flags);
-               }
-       }
-
-       /* Enable or disable the internal pull-ups in the GPIO ASIC block */
-       for (i = 0; i < U300_GPIO_MAX; i++) {
-               val = 0;
-               for (j = 0; j < 8; j++)
-                       val |= (u32)((u300_gpio_config[i][j].pull_up == DISABLE_PULL_UP) << j);
-               local_irq_save(flags);
-               writel(val, virtbase + U300_GPIO_PXPER + i * U300_GPIO_PORTX_SPACING);
-               local_irq_restore(flags);
-       }
-#endif
-}
-
-static int __init gpio_probe(struct platform_device *pdev)
-{
-       u32 val;
-       int err = 0;
-       int i;
-       int num_irqs;
-
-       gpiodev = &pdev->dev;
-       memset(gpio_pin, 0, sizeof(gpio_pin));
-
-       /* Get GPIO clock */
-       clk = clk_get(&pdev->dev, NULL);
-       if (IS_ERR(clk)) {
-               err = PTR_ERR(clk);
-               dev_err(gpiodev, "could not get GPIO clock\n");
-               goto err_no_clk;
-       }
-       err = clk_enable(clk);
-       if (err) {
-               dev_err(gpiodev, "could not enable GPIO clock\n");
-               goto err_no_clk_enable;
-       }
-
-       memres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!memres)
-               goto err_no_resource;
-
-       if (request_mem_region(memres->start, memres->end - memres->start, "GPIO Controller")
-           == NULL) {
-               err = -ENODEV;
-               goto err_no_ioregion;
-       }
-
-       virtbase = ioremap(memres->start, resource_size(memres));
-       if (!virtbase) {
-               err = -ENOMEM;
-               goto err_no_ioremap;
-       }
-       dev_info(gpiodev, "remapped 0x%08x to %p\n",
-                memres->start, virtbase);
-
-#ifdef U300_COH901335
-       dev_info(gpiodev, "initializing GPIO Controller COH 901 335\n");
-       /* Turn on the GPIO block */
-       writel(U300_GPIO_CR_BLOCK_CLOCK_ENABLE, virtbase + U300_GPIO_CR);
-#endif
-
-#ifdef U300_COH901571_3
-       dev_info(gpiodev, "initializing GPIO Controller COH 901 571/3\n");
-       val = readl(virtbase + U300_GPIO_CR);
-       dev_info(gpiodev, "COH901571/3 block version: %d, " \
-              "number of cores: %d\n",
-              ((val & 0x0000FE00) >> 9),
-              ((val & 0x000001FC) >> 2));
-       writel(U300_GPIO_CR_BLOCK_CLKRQ_ENABLE, virtbase + U300_GPIO_CR);
-#endif
-
-       gpio_set_initial_values();
-
-       for (num_irqs = 0 ; num_irqs < U300_GPIO_NUM_PORTS; num_irqs++) {
-
-               gpio_ports[num_irqs].irq =
-                       platform_get_irq_byname(pdev,
-                                               gpio_ports[num_irqs].name);
-
-               err = request_irq(gpio_ports[num_irqs].irq,
-                                 gpio_irq_handler, IRQF_DISABLED,
-                                 gpio_ports[num_irqs].name,
-                                 &gpio_ports[num_irqs]);
-               if (err) {
-                       dev_err(gpiodev, "cannot allocate IRQ for %s!\n",
-                               gpio_ports[num_irqs].name);
-                       goto err_no_irq;
-               }
-               /* Turns off PortX_irq_force */
-               writel(0x0, virtbase + U300_GPIO_PXIFR +
-                                num_irqs * U300_GPIO_PORTX_SPACING);
-       }
-
-       return 0;
-
- err_no_irq:
-       for (i = 0; i < num_irqs; i++)
-               free_irq(gpio_ports[i].irq, &gpio_ports[i]);
-       iounmap(virtbase);
- err_no_ioremap:
-       release_mem_region(memres->start, memres->end - memres->start);
- err_no_ioregion:
- err_no_resource:
-       clk_disable(clk);
- err_no_clk_enable:
-       clk_put(clk);
- err_no_clk:
-       dev_info(gpiodev, "module ERROR:%d\n", err);
-       return err;
-}
-
-static int __exit gpio_remove(struct platform_device *pdev)
-{
-       int i;
-
-       /* Turn off the GPIO block */
-       writel(0x00000000U, virtbase + U300_GPIO_CR);
-       for (i = 0 ; i < U300_GPIO_NUM_PORTS; i++)
-               free_irq(gpio_ports[i].irq, &gpio_ports[i]);
-       iounmap(virtbase);
-       release_mem_region(memres->start, memres->end - memres->start);
-       clk_disable(clk);
-       clk_put(clk);
-       return 0;
-}
-
-static struct platform_driver gpio_driver = {
-       .driver         = {
-               .name   = "u300-gpio",
-       },
-       .remove         = __exit_p(gpio_remove),
-};
-
-
-static int __init u300_gpio_init(void)
-{
-       return platform_driver_probe(&gpio_driver, gpio_probe);
-}
-
-static void __exit u300_gpio_exit(void)
-{
-       platform_driver_unregister(&gpio_driver);
-}
-
-arch_initcall(u300_gpio_init);
-module_exit(u300_gpio_exit);
-
-MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>");
-
-#ifdef U300_COH901571_3
-MODULE_DESCRIPTION("ST-Ericsson AB COH 901 571/3 GPIO driver");
-#endif
-
-#ifdef U300_COH901335
-MODULE_DESCRIPTION("ST-Ericsson AB COH 901 335 GPIO driver");
-#endif
-
-MODULE_LICENSE("GPL");
index 54429d0159547d89399f252fca89a48abddff876..f8b9392ee3471b7628a7f8fcfd7ce50d7d52f269 100644 (file)
@@ -5,7 +5,6 @@ config UX500_SOC_COMMON
        default y
        select ARM_GIC
        select HAS_MTU
-       select NOMADIK_GPIO
        select ARM_ERRATA_753970
 
 menu "Ux500 SoC"
index 18296ee68802708b876ec68b3f2b23c2b9d65599..ce659015535e4a86bc6e708fa3abcc2e59742ec0 100644 (file)
@@ -21,9 +21,4 @@ config HAS_MTU
          to multiple interrupt generating programmable
          32-bit free running decrementing counters.
 
-config NOMADIK_GPIO
-       bool
-       help
-         Support for the Nomadik GPIO controller.
-
 endif
index c33547361bd75b9e54306d867d212a4ac49f3e11..37c7cdd0f8f017979e64f80b00f09736f74d2c21 100644 (file)
@@ -3,4 +3,3 @@
 # Licensed under GPLv2
 
 obj-$(CONFIG_HAS_MTU)  += timer.o
-obj-$(CONFIG_NOMADIK_GPIO)     += gpio.o
diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c
deleted file mode 100644 (file)
index 307b813..0000000
+++ /dev/null
@@ -1,1020 +0,0 @@
-/*
- * Generic GPIO driver for logic cells found in the Nomadik SoC
- *
- * Copyright (C) 2008,2009 STMicroelectronics
- * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it>
- *   Rewritten based on work by Prafulla WADASKAR <prafulla.wadaskar@st.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/gpio.h>
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/slab.h>
-
-#include <asm/mach/irq.h>
-
-#include <plat/pincfg.h>
-#include <mach/hardware.h>
-#include <mach/gpio.h>
-
-/*
- * The GPIO module in the Nomadik family of Systems-on-Chip is an
- * AMBA device, managing 32 pins and alternate functions.  The logic block
- * is currently used in the Nomadik and ux500.
- *
- * Symbols in this file are called "nmk_gpio" for "nomadik gpio"
- */
-
-#define NMK_GPIO_PER_CHIP      32
-
-struct nmk_gpio_chip {
-       struct gpio_chip chip;
-       void __iomem *addr;
-       struct clk *clk;
-       unsigned int bank;
-       unsigned int parent_irq;
-       int secondary_parent_irq;
-       u32 (*get_secondary_status)(unsigned int bank);
-       void (*set_ioforce)(bool enable);
-       spinlock_t lock;
-       /* Keep track of configured edges */
-       u32 edge_rising;
-       u32 edge_falling;
-       u32 real_wake;
-       u32 rwimsc;
-       u32 fwimsc;
-       u32 slpm;
-       u32 enabled;
-};
-
-static struct nmk_gpio_chip *
-nmk_gpio_chips[DIV_ROUND_UP(ARCH_NR_GPIOS, NMK_GPIO_PER_CHIP)];
-
-static DEFINE_SPINLOCK(nmk_gpio_slpm_lock);
-
-#define NUM_BANKS ARRAY_SIZE(nmk_gpio_chips)
-
-static void __nmk_gpio_set_mode(struct nmk_gpio_chip *nmk_chip,
-                               unsigned offset, int gpio_mode)
-{
-       u32 bit = 1 << offset;
-       u32 afunc, bfunc;
-
-       afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & ~bit;
-       bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & ~bit;
-       if (gpio_mode & NMK_GPIO_ALT_A)
-               afunc |= bit;
-       if (gpio_mode & NMK_GPIO_ALT_B)
-               bfunc |= bit;
-       writel(afunc, nmk_chip->addr + NMK_GPIO_AFSLA);
-       writel(bfunc, nmk_chip->addr + NMK_GPIO_AFSLB);
-}
-
-static void __nmk_gpio_set_slpm(struct nmk_gpio_chip *nmk_chip,
-                               unsigned offset, enum nmk_gpio_slpm mode)
-{
-       u32 bit = 1 << offset;
-       u32 slpm;
-
-       slpm = readl(nmk_chip->addr + NMK_GPIO_SLPC);
-       if (mode == NMK_GPIO_SLPM_NOCHANGE)
-               slpm |= bit;
-       else
-               slpm &= ~bit;
-       writel(slpm, nmk_chip->addr + NMK_GPIO_SLPC);
-}
-
-static void __nmk_gpio_set_pull(struct nmk_gpio_chip *nmk_chip,
-                               unsigned offset, enum nmk_gpio_pull pull)
-{
-       u32 bit = 1 << offset;
-       u32 pdis;
-
-       pdis = readl(nmk_chip->addr + NMK_GPIO_PDIS);
-       if (pull == NMK_GPIO_PULL_NONE)
-               pdis |= bit;
-       else
-               pdis &= ~bit;
-       writel(pdis, nmk_chip->addr + NMK_GPIO_PDIS);
-
-       if (pull == NMK_GPIO_PULL_UP)
-               writel(bit, nmk_chip->addr + NMK_GPIO_DATS);
-       else if (pull == NMK_GPIO_PULL_DOWN)
-               writel(bit, nmk_chip->addr + NMK_GPIO_DATC);
-}
-
-static void __nmk_gpio_make_input(struct nmk_gpio_chip *nmk_chip,
-                                 unsigned offset)
-{
-       writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC);
-}
-
-static void __nmk_gpio_set_output(struct nmk_gpio_chip *nmk_chip,
-                                 unsigned offset, int val)
-{
-       if (val)
-               writel(1 << offset, nmk_chip->addr + NMK_GPIO_DATS);
-       else
-               writel(1 << offset, nmk_chip->addr + NMK_GPIO_DATC);
-}
-
-static void __nmk_gpio_make_output(struct nmk_gpio_chip *nmk_chip,
-                                 unsigned offset, int val)
-{
-       writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRS);
-       __nmk_gpio_set_output(nmk_chip, offset, val);
-}
-
-static void __nmk_gpio_set_mode_safe(struct nmk_gpio_chip *nmk_chip,
-                                    unsigned offset, int gpio_mode,
-                                    bool glitch)
-{
-       u32 rwimsc = readl(nmk_chip->addr + NMK_GPIO_RWIMSC);
-       u32 fwimsc = readl(nmk_chip->addr + NMK_GPIO_FWIMSC);
-
-       if (glitch && nmk_chip->set_ioforce) {
-               u32 bit = BIT(offset);
-
-               /* Prevent spurious wakeups */
-               writel(rwimsc & ~bit, nmk_chip->addr + NMK_GPIO_RWIMSC);
-               writel(fwimsc & ~bit, nmk_chip->addr + NMK_GPIO_FWIMSC);
-
-               nmk_chip->set_ioforce(true);
-       }
-
-       __nmk_gpio_set_mode(nmk_chip, offset, gpio_mode);
-
-       if (glitch && nmk_chip->set_ioforce) {
-               nmk_chip->set_ioforce(false);
-
-               writel(rwimsc, nmk_chip->addr + NMK_GPIO_RWIMSC);
-               writel(fwimsc, nmk_chip->addr + NMK_GPIO_FWIMSC);
-       }
-}
-
-static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
-                            pin_cfg_t cfg, bool sleep, unsigned int *slpmregs)
-{
-       static const char *afnames[] = {
-               [NMK_GPIO_ALT_GPIO]     = "GPIO",
-               [NMK_GPIO_ALT_A]        = "A",
-               [NMK_GPIO_ALT_B]        = "B",
-               [NMK_GPIO_ALT_C]        = "C"
-       };
-       static const char *pullnames[] = {
-               [NMK_GPIO_PULL_NONE]    = "none",
-               [NMK_GPIO_PULL_UP]      = "up",
-               [NMK_GPIO_PULL_DOWN]    = "down",
-               [3] /* illegal */       = "??"
-       };
-       static const char *slpmnames[] = {
-               [NMK_GPIO_SLPM_INPUT]           = "input/wakeup",
-               [NMK_GPIO_SLPM_NOCHANGE]        = "no-change/no-wakeup",
-       };
-
-       int pin = PIN_NUM(cfg);
-       int pull = PIN_PULL(cfg);
-       int af = PIN_ALT(cfg);
-       int slpm = PIN_SLPM(cfg);
-       int output = PIN_DIR(cfg);
-       int val = PIN_VAL(cfg);
-       bool glitch = af == NMK_GPIO_ALT_C;
-
-       dev_dbg(nmk_chip->chip.dev, "pin %d [%#lx]: af %s, pull %s, slpm %s (%s%s)\n",
-               pin, cfg, afnames[af], pullnames[pull], slpmnames[slpm],
-               output ? "output " : "input",
-               output ? (val ? "high" : "low") : "");
-
-       if (sleep) {
-               int slpm_pull = PIN_SLPM_PULL(cfg);
-               int slpm_output = PIN_SLPM_DIR(cfg);
-               int slpm_val = PIN_SLPM_VAL(cfg);
-
-               af = NMK_GPIO_ALT_GPIO;
-
-               /*
-                * The SLPM_* values are normal values + 1 to allow zero to
-                * mean "same as normal".
-                */
-               if (slpm_pull)
-                       pull = slpm_pull - 1;
-               if (slpm_output)
-                       output = slpm_output - 1;
-               if (slpm_val)
-                       val = slpm_val - 1;
-
-               dev_dbg(nmk_chip->chip.dev, "pin %d: sleep pull %s, dir %s, val %s\n",
-                       pin,
-                       slpm_pull ? pullnames[pull] : "same",
-                       slpm_output ? (output ? "output" : "input") : "same",
-                       slpm_val ? (val ? "high" : "low") : "same");
-       }
-
-       if (output)
-               __nmk_gpio_make_output(nmk_chip, offset, val);
-       else {
-               __nmk_gpio_make_input(nmk_chip, offset);
-               __nmk_gpio_set_pull(nmk_chip, offset, pull);
-       }
-
-       /*
-        * If we've backed up the SLPM registers (glitch workaround), modify
-        * the backups since they will be restored.
-        */
-       if (slpmregs) {
-               if (slpm == NMK_GPIO_SLPM_NOCHANGE)
-                       slpmregs[nmk_chip->bank] |= BIT(offset);
-               else
-                       slpmregs[nmk_chip->bank] &= ~BIT(offset);
-       } else
-               __nmk_gpio_set_slpm(nmk_chip, offset, slpm);
-
-       __nmk_gpio_set_mode_safe(nmk_chip, offset, af, glitch);
-}
-
-/*
- * Safe sequence used to switch IOs between GPIO and Alternate-C mode:
- *  - Save SLPM registers
- *  - Set SLPM=0 for the IOs you want to switch and others to 1
- *  - Configure the GPIO registers for the IOs that are being switched
- *  - Set IOFORCE=1
- *  - Modify the AFLSA/B registers for the IOs that are being switched
- *  - Set IOFORCE=0
- *  - Restore SLPM registers
- *  - Any spurious wake up event during switch sequence to be ignored and
- *    cleared
- */
-static void nmk_gpio_glitch_slpm_init(unsigned int *slpm)
-{
-       int i;
-
-       for (i = 0; i < NUM_BANKS; i++) {
-               struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
-               unsigned int temp = slpm[i];
-
-               if (!chip)
-                       break;
-
-               slpm[i] = readl(chip->addr + NMK_GPIO_SLPC);
-               writel(temp, chip->addr + NMK_GPIO_SLPC);
-       }
-}
-
-static void nmk_gpio_glitch_slpm_restore(unsigned int *slpm)
-{
-       int i;
-
-       for (i = 0; i < NUM_BANKS; i++) {
-               struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
-
-               if (!chip)
-                       break;
-
-               writel(slpm[i], chip->addr + NMK_GPIO_SLPC);
-       }
-}
-
-static int __nmk_config_pins(pin_cfg_t *cfgs, int num, bool sleep)
-{
-       static unsigned int slpm[NUM_BANKS];
-       unsigned long flags;
-       bool glitch = false;
-       int ret = 0;
-       int i;
-
-       for (i = 0; i < num; i++) {
-               if (PIN_ALT(cfgs[i]) == NMK_GPIO_ALT_C) {
-                       glitch = true;
-                       break;
-               }
-       }
-
-       spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
-
-       if (glitch) {
-               memset(slpm, 0xff, sizeof(slpm));
-
-               for (i = 0; i < num; i++) {
-                       int pin = PIN_NUM(cfgs[i]);
-                       int offset = pin % NMK_GPIO_PER_CHIP;
-
-                       if (PIN_ALT(cfgs[i]) == NMK_GPIO_ALT_C)
-                               slpm[pin / NMK_GPIO_PER_CHIP] &= ~BIT(offset);
-               }
-
-               nmk_gpio_glitch_slpm_init(slpm);
-       }
-
-       for (i = 0; i < num; i++) {
-               struct nmk_gpio_chip *nmk_chip;
-               int pin = PIN_NUM(cfgs[i]);
-
-               nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(pin));
-               if (!nmk_chip) {
-                       ret = -EINVAL;
-                       break;
-               }
-
-               spin_lock(&nmk_chip->lock);
-               __nmk_config_pin(nmk_chip, pin - nmk_chip->chip.base,
-                                cfgs[i], sleep, glitch ? slpm : NULL);
-               spin_unlock(&nmk_chip->lock);
-       }
-
-       if (glitch)
-               nmk_gpio_glitch_slpm_restore(slpm);
-
-       spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
-
-       return ret;
-}
-
-/**
- * nmk_config_pin - configure a pin's mux attributes
- * @cfg: pin confguration
- *
- * Configures a pin's mode (alternate function or GPIO), its pull up status,
- * and its sleep mode based on the specified configuration.  The @cfg is
- * usually one of the SoC specific macros defined in mach/<soc>-pins.h.  These
- * are constructed using, and can be further enhanced with, the macros in
- * plat/pincfg.h.
- *
- * If a pin's mode is set to GPIO, it is configured as an input to avoid
- * side-effects.  The gpio can be manipulated later using standard GPIO API
- * calls.
- */
-int nmk_config_pin(pin_cfg_t cfg, bool sleep)
-{
-       return __nmk_config_pins(&cfg, 1, sleep);
-}
-EXPORT_SYMBOL(nmk_config_pin);
-
-/**
- * nmk_config_pins - configure several pins at once
- * @cfgs: array of pin configurations
- * @num: number of elments in the array
- *
- * Configures several pins using nmk_config_pin().  Refer to that function for
- * further information.
- */
-int nmk_config_pins(pin_cfg_t *cfgs, int num)
-{
-       return __nmk_config_pins(cfgs, num, false);
-}
-EXPORT_SYMBOL(nmk_config_pins);
-
-int nmk_config_pins_sleep(pin_cfg_t *cfgs, int num)
-{
-       return __nmk_config_pins(cfgs, num, true);
-}
-EXPORT_SYMBOL(nmk_config_pins_sleep);
-
-/**
- * nmk_gpio_set_slpm() - configure the sleep mode of a pin
- * @gpio: pin number
- * @mode: NMK_GPIO_SLPM_INPUT or NMK_GPIO_SLPM_NOCHANGE,
- *
- * Sets the sleep mode of a pin.  If @mode is NMK_GPIO_SLPM_INPUT, the pin is
- * changed to an input (with pullup/down enabled) in sleep and deep sleep.  If
- * @mode is NMK_GPIO_SLPM_NOCHANGE, the pin remains in the state it was
- * configured even when in sleep and deep sleep.
- *
- * On DB8500v2 onwards, this setting loses the previous meaning and instead
- * indicates if wakeup detection is enabled on the pin.  Note that
- * enable_irq_wake() will automatically enable wakeup detection.
- */
-int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode)
-{
-       struct nmk_gpio_chip *nmk_chip;
-       unsigned long flags;
-
-       nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
-       if (!nmk_chip)
-               return -EINVAL;
-
-       spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
-       spin_lock(&nmk_chip->lock);
-
-       __nmk_gpio_set_slpm(nmk_chip, gpio - nmk_chip->chip.base, mode);
-
-       spin_unlock(&nmk_chip->lock);
-       spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
-
-       return 0;
-}
-
-/**
- * nmk_gpio_set_pull() - enable/disable pull up/down on a gpio
- * @gpio: pin number
- * @pull: one of NMK_GPIO_PULL_DOWN, NMK_GPIO_PULL_UP, and NMK_GPIO_PULL_NONE
- *
- * Enables/disables pull up/down on a specified pin.  This only takes effect if
- * the pin is configured as an input (either explicitly or by the alternate
- * function).
- *
- * NOTE: If enabling the pull up/down, the caller must ensure that the GPIO is
- * configured as an input.  Otherwise, due to the way the controller registers
- * work, this function will change the value output on the pin.
- */
-int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull)
-{
-       struct nmk_gpio_chip *nmk_chip;
-       unsigned long flags;
-
-       nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
-       if (!nmk_chip)
-               return -EINVAL;
-
-       spin_lock_irqsave(&nmk_chip->lock, flags);
-       __nmk_gpio_set_pull(nmk_chip, gpio - nmk_chip->chip.base, pull);
-       spin_unlock_irqrestore(&nmk_chip->lock, flags);
-
-       return 0;
-}
-
-/* Mode functions */
-/**
- * nmk_gpio_set_mode() - set the mux mode of a gpio pin
- * @gpio: pin number
- * @gpio_mode: one of NMK_GPIO_ALT_GPIO, NMK_GPIO_ALT_A,
- *            NMK_GPIO_ALT_B, and NMK_GPIO_ALT_C
- *
- * Sets the mode of the specified pin to one of the alternate functions or
- * plain GPIO.
- */
-int nmk_gpio_set_mode(int gpio, int gpio_mode)
-{
-       struct nmk_gpio_chip *nmk_chip;
-       unsigned long flags;
-
-       nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
-       if (!nmk_chip)
-               return -EINVAL;
-
-       spin_lock_irqsave(&nmk_chip->lock, flags);
-       __nmk_gpio_set_mode(nmk_chip, gpio - nmk_chip->chip.base, gpio_mode);
-       spin_unlock_irqrestore(&nmk_chip->lock, flags);
-
-       return 0;
-}
-EXPORT_SYMBOL(nmk_gpio_set_mode);
-
-int nmk_gpio_get_mode(int gpio)
-{
-       struct nmk_gpio_chip *nmk_chip;
-       u32 afunc, bfunc, bit;
-
-       nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
-       if (!nmk_chip)
-               return -EINVAL;
-
-       bit = 1 << (gpio - nmk_chip->chip.base);
-
-       afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & bit;
-       bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & bit;
-
-       return (afunc ? NMK_GPIO_ALT_A : 0) | (bfunc ? NMK_GPIO_ALT_B : 0);
-}
-EXPORT_SYMBOL(nmk_gpio_get_mode);
-
-
-/* IRQ functions */
-static inline int nmk_gpio_get_bitmask(int gpio)
-{
-       return 1 << (gpio % 32);
-}
-
-static void nmk_gpio_irq_ack(struct irq_data *d)
-{
-       int gpio;
-       struct nmk_gpio_chip *nmk_chip;
-
-       gpio = NOMADIK_IRQ_TO_GPIO(d->irq);
-       nmk_chip = irq_data_get_irq_chip_data(d);
-       if (!nmk_chip)
-               return;
-       writel(nmk_gpio_get_bitmask(gpio), nmk_chip->addr + NMK_GPIO_IC);
-}
-
-enum nmk_gpio_irq_type {
-       NORMAL,
-       WAKE,
-};
-
-static void __nmk_gpio_irq_modify(struct nmk_gpio_chip *nmk_chip,
-                                 int gpio, enum nmk_gpio_irq_type which,
-                                 bool enable)
-{
-       u32 rimsc = which == WAKE ? NMK_GPIO_RWIMSC : NMK_GPIO_RIMSC;
-       u32 fimsc = which == WAKE ? NMK_GPIO_FWIMSC : NMK_GPIO_FIMSC;
-       u32 bitmask = nmk_gpio_get_bitmask(gpio);
-       u32 reg;
-
-       /* we must individually set/clear the two edges */
-       if (nmk_chip->edge_rising & bitmask) {
-               reg = readl(nmk_chip->addr + rimsc);
-               if (enable)
-                       reg |= bitmask;
-               else
-                       reg &= ~bitmask;
-               writel(reg, nmk_chip->addr + rimsc);
-       }
-       if (nmk_chip->edge_falling & bitmask) {
-               reg = readl(nmk_chip->addr + fimsc);
-               if (enable)
-                       reg |= bitmask;
-               else
-                       reg &= ~bitmask;
-               writel(reg, nmk_chip->addr + fimsc);
-       }
-}
-
-static void __nmk_gpio_set_wake(struct nmk_gpio_chip *nmk_chip,
-                               int gpio, bool on)
-{
-       __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, on);
-}
-
-static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable)
-{
-       int gpio;
-       struct nmk_gpio_chip *nmk_chip;
-       unsigned long flags;
-       u32 bitmask;
-
-       gpio = NOMADIK_IRQ_TO_GPIO(d->irq);
-       nmk_chip = irq_data_get_irq_chip_data(d);
-       bitmask = nmk_gpio_get_bitmask(gpio);
-       if (!nmk_chip)
-               return -EINVAL;
-
-       if (enable)
-               nmk_chip->enabled |= bitmask;
-       else
-               nmk_chip->enabled &= ~bitmask;
-
-       spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
-       spin_lock(&nmk_chip->lock);
-
-       __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, enable);
-
-       if (!(nmk_chip->real_wake & bitmask))
-               __nmk_gpio_set_wake(nmk_chip, gpio, enable);
-
-       spin_unlock(&nmk_chip->lock);
-       spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
-
-       return 0;
-}
-
-static void nmk_gpio_irq_mask(struct irq_data *d)
-{
-       nmk_gpio_irq_maskunmask(d, false);
-}
-
-static void nmk_gpio_irq_unmask(struct irq_data *d)
-{
-       nmk_gpio_irq_maskunmask(d, true);
-}
-
-static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
-{
-       struct nmk_gpio_chip *nmk_chip;
-       unsigned long flags;
-       u32 bitmask;
-       int gpio;
-
-       gpio = NOMADIK_IRQ_TO_GPIO(d->irq);
-       nmk_chip = irq_data_get_irq_chip_data(d);
-       if (!nmk_chip)
-               return -EINVAL;
-       bitmask = nmk_gpio_get_bitmask(gpio);
-
-       spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
-       spin_lock(&nmk_chip->lock);
-
-       if (!(nmk_chip->enabled & bitmask))
-               __nmk_gpio_set_wake(nmk_chip, gpio, on);
-
-       if (on)
-               nmk_chip->real_wake |= bitmask;
-       else
-               nmk_chip->real_wake &= ~bitmask;
-
-       spin_unlock(&nmk_chip->lock);
-       spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
-
-       return 0;
-}
-
-static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
-{
-       bool enabled, wake = irqd_is_wakeup_set(d);
-       int gpio;
-       struct nmk_gpio_chip *nmk_chip;
-       unsigned long flags;
-       u32 bitmask;
-
-       gpio = NOMADIK_IRQ_TO_GPIO(d->irq);
-       nmk_chip = irq_data_get_irq_chip_data(d);
-       bitmask = nmk_gpio_get_bitmask(gpio);
-       if (!nmk_chip)
-               return -EINVAL;
-
-       if (type & IRQ_TYPE_LEVEL_HIGH)
-               return -EINVAL;
-       if (type & IRQ_TYPE_LEVEL_LOW)
-               return -EINVAL;
-
-       enabled = nmk_chip->enabled & bitmask;
-
-       spin_lock_irqsave(&nmk_chip->lock, flags);
-
-       if (enabled)
-               __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, false);
-
-       if (enabled || wake)
-               __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, false);
-
-       nmk_chip->edge_rising &= ~bitmask;
-       if (type & IRQ_TYPE_EDGE_RISING)
-               nmk_chip->edge_rising |= bitmask;
-
-       nmk_chip->edge_falling &= ~bitmask;
-       if (type & IRQ_TYPE_EDGE_FALLING)
-               nmk_chip->edge_falling |= bitmask;
-
-       if (enabled)
-               __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, true);
-
-       if (enabled || wake)
-               __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, true);
-
-       spin_unlock_irqrestore(&nmk_chip->lock, flags);
-
-       return 0;
-}
-
-static struct irq_chip nmk_gpio_irq_chip = {
-       .name           = "Nomadik-GPIO",
-       .irq_ack        = nmk_gpio_irq_ack,
-       .irq_mask       = nmk_gpio_irq_mask,
-       .irq_unmask     = nmk_gpio_irq_unmask,
-       .irq_set_type   = nmk_gpio_irq_set_type,
-       .irq_set_wake   = nmk_gpio_irq_set_wake,
-};
-
-static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc,
-                                  u32 status)
-{
-       struct nmk_gpio_chip *nmk_chip;
-       struct irq_chip *host_chip = irq_get_chip(irq);
-       unsigned int first_irq;
-
-       chained_irq_enter(host_chip, desc);
-
-       nmk_chip = irq_get_handler_data(irq);
-       first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base);
-       while (status) {
-               int bit = __ffs(status);
-
-               generic_handle_irq(first_irq + bit);
-               status &= ~BIT(bit);
-       }
-
-       chained_irq_exit(host_chip, desc);
-}
-
-static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
-{
-       struct nmk_gpio_chip *nmk_chip = irq_get_handler_data(irq);
-       u32 status = readl(nmk_chip->addr + NMK_GPIO_IS);
-
-       __nmk_gpio_irq_handler(irq, desc, status);
-}
-
-static void nmk_gpio_secondary_irq_handler(unsigned int irq,
-                                          struct irq_desc *desc)
-{
-       struct nmk_gpio_chip *nmk_chip = irq_get_handler_data(irq);
-       u32 status = nmk_chip->get_secondary_status(nmk_chip->bank);
-
-       __nmk_gpio_irq_handler(irq, desc, status);
-}
-
-static int nmk_gpio_init_irq(struct nmk_gpio_chip *nmk_chip)
-{
-       unsigned int first_irq;
-       int i;
-
-       first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base);
-       for (i = first_irq; i < first_irq + nmk_chip->chip.ngpio; i++) {
-               irq_set_chip_and_handler(i, &nmk_gpio_irq_chip,
-                                        handle_edge_irq);
-               set_irq_flags(i, IRQF_VALID);
-               irq_set_chip_data(i, nmk_chip);
-               irq_set_irq_type(i, IRQ_TYPE_EDGE_FALLING);
-       }
-
-       irq_set_chained_handler(nmk_chip->parent_irq, nmk_gpio_irq_handler);
-       irq_set_handler_data(nmk_chip->parent_irq, nmk_chip);
-
-       if (nmk_chip->secondary_parent_irq >= 0) {
-               irq_set_chained_handler(nmk_chip->secondary_parent_irq,
-                                       nmk_gpio_secondary_irq_handler);
-               irq_set_handler_data(nmk_chip->secondary_parent_irq, nmk_chip);
-       }
-
-       return 0;
-}
-
-/* I/O Functions */
-static int nmk_gpio_make_input(struct gpio_chip *chip, unsigned offset)
-{
-       struct nmk_gpio_chip *nmk_chip =
-               container_of(chip, struct nmk_gpio_chip, chip);
-
-       writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC);
-       return 0;
-}
-
-static int nmk_gpio_get_input(struct gpio_chip *chip, unsigned offset)
-{
-       struct nmk_gpio_chip *nmk_chip =
-               container_of(chip, struct nmk_gpio_chip, chip);
-       u32 bit = 1 << offset;
-
-       return (readl(nmk_chip->addr + NMK_GPIO_DAT) & bit) != 0;
-}
-
-static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned offset,
-                               int val)
-{
-       struct nmk_gpio_chip *nmk_chip =
-               container_of(chip, struct nmk_gpio_chip, chip);
-
-       __nmk_gpio_set_output(nmk_chip, offset, val);
-}
-
-static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset,
-                               int val)
-{
-       struct nmk_gpio_chip *nmk_chip =
-               container_of(chip, struct nmk_gpio_chip, chip);
-
-       __nmk_gpio_make_output(nmk_chip, offset, val);
-
-       return 0;
-}
-
-static int nmk_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-       struct nmk_gpio_chip *nmk_chip =
-               container_of(chip, struct nmk_gpio_chip, chip);
-
-       return NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base) + offset;
-}
-
-#ifdef CONFIG_DEBUG_FS
-
-#include <linux/seq_file.h>
-
-static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
-{
-       int mode;
-       unsigned                i;
-       unsigned                gpio = chip->base;
-       int                     is_out;
-       struct nmk_gpio_chip *nmk_chip =
-               container_of(chip, struct nmk_gpio_chip, chip);
-       const char *modes[] = {
-               [NMK_GPIO_ALT_GPIO]     = "gpio",
-               [NMK_GPIO_ALT_A]        = "altA",
-               [NMK_GPIO_ALT_B]        = "altB",
-               [NMK_GPIO_ALT_C]        = "altC",
-       };
-
-       for (i = 0; i < chip->ngpio; i++, gpio++) {
-               const char *label = gpiochip_is_requested(chip, i);
-               bool pull;
-               u32 bit = 1 << i;
-
-               if (!label)
-                       continue;
-
-               is_out = readl(nmk_chip->addr + NMK_GPIO_DIR) & bit;
-               pull = !(readl(nmk_chip->addr + NMK_GPIO_PDIS) & bit);
-               mode = nmk_gpio_get_mode(gpio);
-               seq_printf(s, " gpio-%-3d (%-20.20s) %s %s %s %s",
-                       gpio, label,
-                       is_out ? "out" : "in ",
-                       chip->get
-                               ? (chip->get(chip, i) ? "hi" : "lo")
-                               : "?  ",
-                       (mode < 0) ? "unknown" : modes[mode],
-                       pull ? "pull" : "none");
-               seq_printf(s, "\n");
-       }
-}
-
-#else
-#define nmk_gpio_dbg_show      NULL
-#endif
-
-/* This structure is replicated for each GPIO block allocated at probe time */
-static struct gpio_chip nmk_gpio_template = {
-       .direction_input        = nmk_gpio_make_input,
-       .get                    = nmk_gpio_get_input,
-       .direction_output       = nmk_gpio_make_output,
-       .set                    = nmk_gpio_set_output,
-       .to_irq                 = nmk_gpio_to_irq,
-       .dbg_show               = nmk_gpio_dbg_show,
-       .can_sleep              = 0,
-};
-
-/*
- * Called from the suspend/resume path to only keep the real wakeup interrupts
- * (those that have had set_irq_wake() called on them) as wakeup interrupts,
- * and not the rest of the interrupts which we needed to have as wakeups for
- * cpuidle.
- *
- * PM ops are not used since this needs to be done at the end, after all the
- * other drivers are done with their suspend callbacks.
- */
-void nmk_gpio_wakeups_suspend(void)
-{
-       int i;
-
-       for (i = 0; i < NUM_BANKS; i++) {
-               struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
-
-               if (!chip)
-                       break;
-
-               chip->rwimsc = readl(chip->addr + NMK_GPIO_RWIMSC);
-               chip->fwimsc = readl(chip->addr + NMK_GPIO_FWIMSC);
-
-               writel(chip->rwimsc & chip->real_wake,
-                      chip->addr + NMK_GPIO_RWIMSC);
-               writel(chip->fwimsc & chip->real_wake,
-                      chip->addr + NMK_GPIO_FWIMSC);
-
-               if (cpu_is_u8500v2()) {
-                       chip->slpm = readl(chip->addr + NMK_GPIO_SLPC);
-
-                       /* 0 -> wakeup enable */
-                       writel(~chip->real_wake, chip->addr + NMK_GPIO_SLPC);
-               }
-       }
-}
-
-void nmk_gpio_wakeups_resume(void)
-{
-       int i;
-
-       for (i = 0; i < NUM_BANKS; i++) {
-               struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
-
-               if (!chip)
-                       break;
-
-               writel(chip->rwimsc, chip->addr + NMK_GPIO_RWIMSC);
-               writel(chip->fwimsc, chip->addr + NMK_GPIO_FWIMSC);
-
-               if (cpu_is_u8500v2())
-                       writel(chip->slpm, chip->addr + NMK_GPIO_SLPC);
-       }
-}
-
-static int __devinit nmk_gpio_probe(struct platform_device *dev)
-{
-       struct nmk_gpio_platform_data *pdata = dev->dev.platform_data;
-       struct nmk_gpio_chip *nmk_chip;
-       struct gpio_chip *chip;
-       struct resource *res;
-       struct clk *clk;
-       int secondary_irq;
-       int irq;
-       int ret;
-
-       if (!pdata)
-               return -ENODEV;
-
-       res = platform_get_resource(dev, IORESOURCE_MEM, 0);
-       if (!res) {
-               ret = -ENOENT;
-               goto out;
-       }
-
-       irq = platform_get_irq(dev, 0);
-       if (irq < 0) {
-               ret = irq;
-               goto out;
-       }
-
-       secondary_irq = platform_get_irq(dev, 1);
-       if (secondary_irq >= 0 && !pdata->get_secondary_status) {
-               ret = -EINVAL;
-               goto out;
-       }
-
-       if (request_mem_region(res->start, resource_size(res),
-                              dev_name(&dev->dev)) == NULL) {
-               ret = -EBUSY;
-               goto out;
-       }
-
-       clk = clk_get(&dev->dev, NULL);
-       if (IS_ERR(clk)) {
-               ret = PTR_ERR(clk);
-               goto out_release;
-       }
-
-       clk_enable(clk);
-
-       nmk_chip = kzalloc(sizeof(*nmk_chip), GFP_KERNEL);
-       if (!nmk_chip) {
-               ret = -ENOMEM;
-               goto out_clk;
-       }
-       /*
-        * The virt address in nmk_chip->addr is in the nomadik register space,
-        * so we can simply convert the resource address, without remapping
-        */
-       nmk_chip->bank = dev->id;
-       nmk_chip->clk = clk;
-       nmk_chip->addr = io_p2v(res->start);
-       nmk_chip->chip = nmk_gpio_template;
-       nmk_chip->parent_irq = irq;
-       nmk_chip->secondary_parent_irq = secondary_irq;
-       nmk_chip->get_secondary_status = pdata->get_secondary_status;
-       nmk_chip->set_ioforce = pdata->set_ioforce;
-       spin_lock_init(&nmk_chip->lock);
-
-       chip = &nmk_chip->chip;
-       chip->base = pdata->first_gpio;
-       chip->ngpio = pdata->num_gpio;
-       chip->label = pdata->name ?: dev_name(&dev->dev);
-       chip->dev = &dev->dev;
-       chip->owner = THIS_MODULE;
-
-       ret = gpiochip_add(&nmk_chip->chip);
-       if (ret)
-               goto out_free;
-
-       BUG_ON(nmk_chip->bank >= ARRAY_SIZE(nmk_gpio_chips));
-
-       nmk_gpio_chips[nmk_chip->bank] = nmk_chip;
-       platform_set_drvdata(dev, nmk_chip);
-
-       nmk_gpio_init_irq(nmk_chip);
-
-       dev_info(&dev->dev, "Bits %i-%i at address %p\n",
-                nmk_chip->chip.base, nmk_chip->chip.base+31, nmk_chip->addr);
-       return 0;
-
-out_free:
-       kfree(nmk_chip);
-out_clk:
-       clk_disable(clk);
-       clk_put(clk);
-out_release:
-       release_mem_region(res->start, resource_size(res));
-out:
-       dev_err(&dev->dev, "Failure %i for GPIO %i-%i\n", ret,
-                 pdata->first_gpio, pdata->first_gpio+31);
-       return ret;
-}
-
-static struct platform_driver nmk_gpio_driver = {
-       .driver = {
-               .owner = THIS_MODULE,
-               .name = "gpio",
-       },
-       .probe = nmk_gpio_probe,
-};
-
-static int __init nmk_gpio_init(void)
-{
-       return platform_driver_register(&nmk_gpio_driver);
-}
-
-core_initcall(nmk_gpio_init);
-
-MODULE_AUTHOR("Prafulla WADASKAR and Alessandro Rubini");
-MODULE_DESCRIPTION("Nomadik GPIO Driver");
-MODULE_LICENSE("GPL");
-
-
index 1b9f6f0843d1227cf67f896511ac43467f62d617..ea19a5b2f22754814d99732686c5982c02eef527 100644 (file)
@@ -78,6 +78,8 @@ extern int nmk_gpio_get_mode(int gpio);
 extern void nmk_gpio_wakeups_suspend(void);
 extern void nmk_gpio_wakeups_resume(void);
 
+extern void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up);
+
 /*
  * Platform data to register a block: only the initial gpio/irq number.
  */
index a4a12859fdd57c6bc4a65870ac57682c6f92f28d..f0233e6abcdff0e9d72fe4967df9be6a36e8e4e6 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 # Common support
-obj-y := common.o sram.o clock.o devices.o dma.o mux.o gpio.o \
+obj-y := common.o sram.o clock.o devices.o dma.o mux.o \
         usb.o fb.o io.o counter_32k.o
 obj-m :=
 obj-n :=
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
deleted file mode 100644 (file)
index efb8693..0000000
+++ /dev/null
@@ -1,2112 +0,0 @@
-/*
- *  linux/arch/arm/plat-omap/gpio.c
- *
- * Support functions for OMAP GPIO
- *
- * Copyright (C) 2003-2005 Nokia Corporation
- * Written by Juha Yrjölä <juha.yrjola@nokia.com>
- *
- * Copyright (C) 2009 Texas Instruments
- * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/syscore_ops.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/pm_runtime.h>
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <mach/irqs.h>
-#include <mach/gpio.h>
-#include <asm/mach/irq.h>
-
-/*
- * OMAP1510 GPIO registers
- */
-#define OMAP1510_GPIO_DATA_INPUT       0x00
-#define OMAP1510_GPIO_DATA_OUTPUT      0x04
-#define OMAP1510_GPIO_DIR_CONTROL      0x08
-#define OMAP1510_GPIO_INT_CONTROL      0x0c
-#define OMAP1510_GPIO_INT_MASK         0x10
-#define OMAP1510_GPIO_INT_STATUS       0x14
-#define OMAP1510_GPIO_PIN_CONTROL      0x18
-
-#define OMAP1510_IH_GPIO_BASE          64
-
-/*
- * OMAP1610 specific GPIO registers
- */
-#define OMAP1610_GPIO_REVISION         0x0000
-#define OMAP1610_GPIO_SYSCONFIG                0x0010
-#define OMAP1610_GPIO_SYSSTATUS                0x0014
-#define OMAP1610_GPIO_IRQSTATUS1       0x0018
-#define OMAP1610_GPIO_IRQENABLE1       0x001c
-#define OMAP1610_GPIO_WAKEUPENABLE     0x0028
-#define OMAP1610_GPIO_DATAIN           0x002c
-#define OMAP1610_GPIO_DATAOUT          0x0030
-#define OMAP1610_GPIO_DIRECTION                0x0034
-#define OMAP1610_GPIO_EDGE_CTRL1       0x0038
-#define OMAP1610_GPIO_EDGE_CTRL2       0x003c
-#define OMAP1610_GPIO_CLEAR_IRQENABLE1 0x009c
-#define OMAP1610_GPIO_CLEAR_WAKEUPENA  0x00a8
-#define OMAP1610_GPIO_CLEAR_DATAOUT    0x00b0
-#define OMAP1610_GPIO_SET_IRQENABLE1   0x00dc
-#define OMAP1610_GPIO_SET_WAKEUPENA    0x00e8
-#define OMAP1610_GPIO_SET_DATAOUT      0x00f0
-
-/*
- * OMAP7XX specific GPIO registers
- */
-#define OMAP7XX_GPIO_DATA_INPUT                0x00
-#define OMAP7XX_GPIO_DATA_OUTPUT       0x04
-#define OMAP7XX_GPIO_DIR_CONTROL       0x08
-#define OMAP7XX_GPIO_INT_CONTROL       0x0c
-#define OMAP7XX_GPIO_INT_MASK          0x10
-#define OMAP7XX_GPIO_INT_STATUS                0x14
-
-/*
- * omap2+ specific GPIO registers
- */
-#define OMAP24XX_GPIO_REVISION         0x0000
-#define OMAP24XX_GPIO_IRQSTATUS1       0x0018
-#define OMAP24XX_GPIO_IRQSTATUS2       0x0028
-#define OMAP24XX_GPIO_IRQENABLE2       0x002c
-#define OMAP24XX_GPIO_IRQENABLE1       0x001c
-#define OMAP24XX_GPIO_WAKE_EN          0x0020
-#define OMAP24XX_GPIO_CTRL             0x0030
-#define OMAP24XX_GPIO_OE               0x0034
-#define OMAP24XX_GPIO_DATAIN           0x0038
-#define OMAP24XX_GPIO_DATAOUT          0x003c
-#define OMAP24XX_GPIO_LEVELDETECT0     0x0040
-#define OMAP24XX_GPIO_LEVELDETECT1     0x0044
-#define OMAP24XX_GPIO_RISINGDETECT     0x0048
-#define OMAP24XX_GPIO_FALLINGDETECT    0x004c
-#define OMAP24XX_GPIO_DEBOUNCE_EN      0x0050
-#define OMAP24XX_GPIO_DEBOUNCE_VAL     0x0054
-#define OMAP24XX_GPIO_CLEARIRQENABLE1  0x0060
-#define OMAP24XX_GPIO_SETIRQENABLE1    0x0064
-#define OMAP24XX_GPIO_CLEARWKUENA      0x0080
-#define OMAP24XX_GPIO_SETWKUENA                0x0084
-#define OMAP24XX_GPIO_CLEARDATAOUT     0x0090
-#define OMAP24XX_GPIO_SETDATAOUT       0x0094
-
-#define OMAP4_GPIO_REVISION            0x0000
-#define OMAP4_GPIO_EOI                 0x0020
-#define OMAP4_GPIO_IRQSTATUSRAW0       0x0024
-#define OMAP4_GPIO_IRQSTATUSRAW1       0x0028
-#define OMAP4_GPIO_IRQSTATUS0          0x002c
-#define OMAP4_GPIO_IRQSTATUS1          0x0030
-#define OMAP4_GPIO_IRQSTATUSSET0       0x0034
-#define OMAP4_GPIO_IRQSTATUSSET1       0x0038
-#define OMAP4_GPIO_IRQSTATUSCLR0       0x003c
-#define OMAP4_GPIO_IRQSTATUSCLR1       0x0040
-#define OMAP4_GPIO_IRQWAKEN0           0x0044
-#define OMAP4_GPIO_IRQWAKEN1           0x0048
-#define OMAP4_GPIO_IRQENABLE1          0x011c
-#define OMAP4_GPIO_WAKE_EN             0x0120
-#define OMAP4_GPIO_IRQSTATUS2          0x0128
-#define OMAP4_GPIO_IRQENABLE2          0x012c
-#define OMAP4_GPIO_CTRL                        0x0130
-#define OMAP4_GPIO_OE                  0x0134
-#define OMAP4_GPIO_DATAIN              0x0138
-#define OMAP4_GPIO_DATAOUT             0x013c
-#define OMAP4_GPIO_LEVELDETECT0                0x0140
-#define OMAP4_GPIO_LEVELDETECT1                0x0144
-#define OMAP4_GPIO_RISINGDETECT                0x0148
-#define OMAP4_GPIO_FALLINGDETECT       0x014c
-#define OMAP4_GPIO_DEBOUNCENABLE       0x0150
-#define OMAP4_GPIO_DEBOUNCINGTIME      0x0154
-#define OMAP4_GPIO_CLEARIRQENABLE1     0x0160
-#define OMAP4_GPIO_SETIRQENABLE1       0x0164
-#define OMAP4_GPIO_CLEARWKUENA         0x0180
-#define OMAP4_GPIO_SETWKUENA           0x0184
-#define OMAP4_GPIO_CLEARDATAOUT                0x0190
-#define OMAP4_GPIO_SETDATAOUT          0x0194
-
-struct gpio_bank {
-       unsigned long pbase;
-       void __iomem *base;
-       u16 irq;
-       u16 virtual_irq_start;
-       int method;
-#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS)
-       u32 suspend_wakeup;
-       u32 saved_wakeup;
-#endif
-       u32 non_wakeup_gpios;
-       u32 enabled_non_wakeup_gpios;
-
-       u32 saved_datain;
-       u32 saved_fallingdetect;
-       u32 saved_risingdetect;
-       u32 level_mask;
-       u32 toggle_mask;
-       spinlock_t lock;
-       struct gpio_chip chip;
-       struct clk *dbck;
-       u32 mod_usage;
-       u32 dbck_enable_mask;
-       struct device *dev;
-       bool dbck_flag;
-       int stride;
-};
-
-#ifdef CONFIG_ARCH_OMAP3
-struct omap3_gpio_regs {
-       u32 irqenable1;
-       u32 irqenable2;
-       u32 wake_en;
-       u32 ctrl;
-       u32 oe;
-       u32 leveldetect0;
-       u32 leveldetect1;
-       u32 risingdetect;
-       u32 fallingdetect;
-       u32 dataout;
-};
-
-static struct omap3_gpio_regs gpio_context[OMAP34XX_NR_GPIOS];
-#endif
-
-/*
- * TODO: Cleanup gpio_bank usage as it is having information
- * related to all instances of the device
- */
-static struct gpio_bank *gpio_bank;
-
-static int bank_width;
-
-/* TODO: Analyze removing gpio_bank_count usage from driver code */
-int gpio_bank_count;
-
-static inline struct gpio_bank *get_gpio_bank(int gpio)
-{
-       if (cpu_is_omap15xx()) {
-               if (OMAP_GPIO_IS_MPUIO(gpio))
-                       return &gpio_bank[0];
-               return &gpio_bank[1];
-       }
-       if (cpu_is_omap16xx()) {
-               if (OMAP_GPIO_IS_MPUIO(gpio))
-                       return &gpio_bank[0];
-               return &gpio_bank[1 + (gpio >> 4)];
-       }
-       if (cpu_is_omap7xx()) {
-               if (OMAP_GPIO_IS_MPUIO(gpio))
-                       return &gpio_bank[0];
-               return &gpio_bank[1 + (gpio >> 5)];
-       }
-       if (cpu_is_omap24xx())
-               return &gpio_bank[gpio >> 5];
-       if (cpu_is_omap34xx() || cpu_is_omap44xx())
-               return &gpio_bank[gpio >> 5];
-       BUG();
-       return NULL;
-}
-
-static inline int get_gpio_index(int gpio)
-{
-       if (cpu_is_omap7xx())
-               return gpio & 0x1f;
-       if (cpu_is_omap24xx())
-               return gpio & 0x1f;
-       if (cpu_is_omap34xx() || cpu_is_omap44xx())
-               return gpio & 0x1f;
-       return gpio & 0x0f;
-}
-
-static inline int gpio_valid(int gpio)
-{
-       if (gpio < 0)
-               return -1;
-       if (cpu_class_is_omap1() && OMAP_GPIO_IS_MPUIO(gpio)) {
-               if (gpio >= OMAP_MAX_GPIO_LINES + 16)
-                       return -1;
-               return 0;
-       }
-       if (cpu_is_omap15xx() && gpio < 16)
-               return 0;
-       if ((cpu_is_omap16xx()) && gpio < 64)
-               return 0;
-       if (cpu_is_omap7xx() && gpio < 192)
-               return 0;
-       if (cpu_is_omap2420() && gpio < 128)
-               return 0;
-       if (cpu_is_omap2430() && gpio < 160)
-               return 0;
-       if ((cpu_is_omap34xx() || cpu_is_omap44xx()) && gpio < 192)
-               return 0;
-       return -1;
-}
-
-static int check_gpio(int gpio)
-{
-       if (unlikely(gpio_valid(gpio) < 0)) {
-               printk(KERN_ERR "omap-gpio: invalid GPIO %d\n", gpio);
-               dump_stack();
-               return -1;
-       }
-       return 0;
-}
-
-static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
-{
-       void __iomem *reg = bank->base;
-       u32 l;
-
-       switch (bank->method) {
-#ifdef CONFIG_ARCH_OMAP1
-       case METHOD_MPUIO:
-               reg += OMAP_MPUIO_IO_CNTL / bank->stride;
-               break;
-#endif
-#ifdef CONFIG_ARCH_OMAP15XX
-       case METHOD_GPIO_1510:
-               reg += OMAP1510_GPIO_DIR_CONTROL;
-               break;
-#endif
-#ifdef CONFIG_ARCH_OMAP16XX
-       case METHOD_GPIO_1610:
-               reg += OMAP1610_GPIO_DIRECTION;
-               break;
-#endif
-#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
-       case METHOD_GPIO_7XX:
-               reg += OMAP7XX_GPIO_DIR_CONTROL;
-               break;
-#endif
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-       case METHOD_GPIO_24XX:
-               reg += OMAP24XX_GPIO_OE;
-               break;
-#endif
-#if defined(CONFIG_ARCH_OMAP4)
-       case METHOD_GPIO_44XX:
-               reg += OMAP4_GPIO_OE;
-               break;
-#endif
-       default:
-               WARN_ON(1);
-               return;
-       }
-       l = __raw_readl(reg);
-       if (is_input)
-               l |= 1 << gpio;
-       else
-               l &= ~(1 << gpio);
-       __raw_writel(l, reg);
-}
-
-static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable)
-{
-       void __iomem *reg = bank->base;
-       u32 l = 0;
-
-       switch (bank->method) {
-#ifdef CONFIG_ARCH_OMAP1
-       case METHOD_MPUIO:
-               reg += OMAP_MPUIO_OUTPUT / bank->stride;
-               l = __raw_readl(reg);
-               if (enable)
-                       l |= 1 << gpio;
-               else
-                       l &= ~(1 << gpio);
-               break;
-#endif
-#ifdef CONFIG_ARCH_OMAP15XX
-       case METHOD_GPIO_1510:
-               reg += OMAP1510_GPIO_DATA_OUTPUT;
-               l = __raw_readl(reg);
-               if (enable)
-                       l |= 1 << gpio;
-               else
-                       l &= ~(1 << gpio);
-               break;
-#endif
-#ifdef CONFIG_ARCH_OMAP16XX
-       case METHOD_GPIO_1610:
-               if (enable)
-                       reg += OMAP1610_GPIO_SET_DATAOUT;
-               else
-                       reg += OMAP1610_GPIO_CLEAR_DATAOUT;
-               l = 1 << gpio;
-               break;
-#endif
-#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
-       case METHOD_GPIO_7XX:
-               reg += OMAP7XX_GPIO_DATA_OUTPUT;
-               l = __raw_readl(reg);
-               if (enable)
-                       l |= 1 << gpio;
-               else
-                       l &= ~(1 << gpio);
-               break;
-#endif
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-       case METHOD_GPIO_24XX:
-               if (enable)
-                       reg += OMAP24XX_GPIO_SETDATAOUT;
-               else
-                       reg += OMAP24XX_GPIO_CLEARDATAOUT;
-               l = 1 << gpio;
-               break;
-#endif
-#ifdef CONFIG_ARCH_OMAP4
-       case METHOD_GPIO_44XX:
-               if (enable)
-                       reg += OMAP4_GPIO_SETDATAOUT;
-               else
-                       reg += OMAP4_GPIO_CLEARDATAOUT;
-               l = 1 << gpio;
-               break;
-#endif
-       default:
-               WARN_ON(1);
-               return;
-       }
-       __raw_writel(l, reg);
-}
-
-static int _get_gpio_datain(struct gpio_bank *bank, int gpio)
-{
-       void __iomem *reg;
-
-       if (check_gpio(gpio) < 0)
-               return -EINVAL;
-       reg = bank->base;
-       switch (bank->method) {
-#ifdef CONFIG_ARCH_OMAP1
-       case METHOD_MPUIO:
-               reg += OMAP_MPUIO_INPUT_LATCH / bank->stride;
-               break;
-#endif
-#ifdef CONFIG_ARCH_OMAP15XX
-       case METHOD_GPIO_1510:
-               reg += OMAP1510_GPIO_DATA_INPUT;
-               break;
-#endif
-#ifdef CONFIG_ARCH_OMAP16XX
-       case METHOD_GPIO_1610:
-               reg += OMAP1610_GPIO_DATAIN;
-               break;
-#endif
-#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
-       case METHOD_GPIO_7XX:
-               reg += OMAP7XX_GPIO_DATA_INPUT;
-               break;
-#endif
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-       case METHOD_GPIO_24XX:
-               reg += OMAP24XX_GPIO_DATAIN;
-               break;
-#endif
-#ifdef CONFIG_ARCH_OMAP4
-       case METHOD_GPIO_44XX:
-               reg += OMAP4_GPIO_DATAIN;
-               break;
-#endif
-       default:
-               return -EINVAL;
-       }
-       return (__raw_readl(reg)
-                       & (1 << get_gpio_index(gpio))) != 0;
-}
-
-static int _get_gpio_dataout(struct gpio_bank *bank, int gpio)
-{
-       void __iomem *reg;
-
-       if (check_gpio(gpio) < 0)
-               return -EINVAL;
-       reg = bank->base;
-
-       switch (bank->method) {
-#ifdef CONFIG_ARCH_OMAP1
-       case METHOD_MPUIO:
-               reg += OMAP_MPUIO_OUTPUT / bank->stride;
-               break;
-#endif
-#ifdef CONFIG_ARCH_OMAP15XX
-       case METHOD_GPIO_1510:
-               reg += OMAP1510_GPIO_DATA_OUTPUT;
-               break;
-#endif
-#ifdef CONFIG_ARCH_OMAP16XX
-       case METHOD_GPIO_1610:
-               reg += OMAP1610_GPIO_DATAOUT;
-               break;
-#endif
-#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
-       case METHOD_GPIO_7XX:
-               reg += OMAP7XX_GPIO_DATA_OUTPUT;
-               break;
-#endif
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-       case METHOD_GPIO_24XX:
-               reg += OMAP24XX_GPIO_DATAOUT;
-               break;
-#endif
-#ifdef CONFIG_ARCH_OMAP4
-       case METHOD_GPIO_44XX:
-               reg += OMAP4_GPIO_DATAOUT;
-               break;
-#endif
-       default:
-               return -EINVAL;
-       }
-
-       return (__raw_readl(reg) & (1 << get_gpio_index(gpio))) != 0;
-}
-
-#define MOD_REG_BIT(reg, bit_mask, set)        \
-do {   \
-       int l = __raw_readl(base + reg); \
-       if (set) l |= bit_mask; \
-       else l &= ~bit_mask; \
-       __raw_writel(l, base + reg); \
-} while(0)
-
-/**
- * _set_gpio_debounce - low level gpio debounce time
- * @bank: the gpio bank we're acting upon
- * @gpio: the gpio number on this @gpio
- * @debounce: debounce time to use
- *
- * OMAP's debounce time is in 31us steps so we need
- * to convert and round up to the closest unit.
- */
-static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
-               unsigned debounce)
-{
-       void __iomem            *reg = bank->base;
-       u32                     val;
-       u32                     l;
-
-       if (!bank->dbck_flag)
-               return;
-
-       if (debounce < 32)
-               debounce = 0x01;
-       else if (debounce > 7936)
-               debounce = 0xff;
-       else
-               debounce = (debounce / 0x1f) - 1;
-
-       l = 1 << get_gpio_index(gpio);
-
-       if (bank->method == METHOD_GPIO_44XX)
-               reg += OMAP4_GPIO_DEBOUNCINGTIME;
-       else
-               reg += OMAP24XX_GPIO_DEBOUNCE_VAL;
-
-       __raw_writel(debounce, reg);
-
-       reg = bank->base;
-       if (bank->method == METHOD_GPIO_44XX)
-               reg += OMAP4_GPIO_DEBOUNCENABLE;
-       else
-               reg += OMAP24XX_GPIO_DEBOUNCE_EN;
-
-       val = __raw_readl(reg);
-
-       if (debounce) {
-               val |= l;
-               clk_enable(bank->dbck);
-       } else {
-               val &= ~l;
-               clk_disable(bank->dbck);
-       }
-       bank->dbck_enable_mask = val;
-
-       __raw_writel(val, reg);
-}
-
-#ifdef CONFIG_ARCH_OMAP2PLUS
-static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio,
-                                               int trigger)
-{
-       void __iomem *base = bank->base;
-       u32 gpio_bit = 1 << gpio;
-       u32 val;
-
-       if (cpu_is_omap44xx()) {
-               MOD_REG_BIT(OMAP4_GPIO_LEVELDETECT0, gpio_bit,
-                       trigger & IRQ_TYPE_LEVEL_LOW);
-               MOD_REG_BIT(OMAP4_GPIO_LEVELDETECT1, gpio_bit,
-                       trigger & IRQ_TYPE_LEVEL_HIGH);
-               MOD_REG_BIT(OMAP4_GPIO_RISINGDETECT, gpio_bit,
-                       trigger & IRQ_TYPE_EDGE_RISING);
-               MOD_REG_BIT(OMAP4_GPIO_FALLINGDETECT, gpio_bit,
-                       trigger & IRQ_TYPE_EDGE_FALLING);
-       } else {
-               MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit,
-                       trigger & IRQ_TYPE_LEVEL_LOW);
-               MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT1, gpio_bit,
-                       trigger & IRQ_TYPE_LEVEL_HIGH);
-               MOD_REG_BIT(OMAP24XX_GPIO_RISINGDETECT, gpio_bit,
-                       trigger & IRQ_TYPE_EDGE_RISING);
-               MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit,
-                       trigger & IRQ_TYPE_EDGE_FALLING);
-       }
-       if (likely(!(bank->non_wakeup_gpios & gpio_bit))) {
-               if (cpu_is_omap44xx()) {
-                       if (trigger != 0)
-                               __raw_writel(1 << gpio, bank->base+
-                                               OMAP4_GPIO_IRQWAKEN0);
-                       else {
-                               val = __raw_readl(bank->base +
-                                                       OMAP4_GPIO_IRQWAKEN0);
-                               __raw_writel(val & (~(1 << gpio)), bank->base +
-                                                        OMAP4_GPIO_IRQWAKEN0);
-                       }
-               } else {
-                       /*
-                        * GPIO wakeup request can only be generated on edge
-                        * transitions
-                        */
-                       if (trigger & IRQ_TYPE_EDGE_BOTH)
-                               __raw_writel(1 << gpio, bank->base
-                                       + OMAP24XX_GPIO_SETWKUENA);
-                       else
-                               __raw_writel(1 << gpio, bank->base
-                                       + OMAP24XX_GPIO_CLEARWKUENA);
-               }
-       }
-       /* This part needs to be executed always for OMAP34xx */
-       if (cpu_is_omap34xx() || (bank->non_wakeup_gpios & gpio_bit)) {
-               /*
-                * Log the edge gpio and manually trigger the IRQ
-                * after resume if the input level changes
-                * to avoid irq lost during PER RET/OFF mode
-                * Applies for omap2 non-wakeup gpio and all omap3 gpios
-                */
-               if (trigger & IRQ_TYPE_EDGE_BOTH)
-                       bank->enabled_non_wakeup_gpios |= gpio_bit;
-               else
-                       bank->enabled_non_wakeup_gpios &= ~gpio_bit;
-       }
-
-       if (cpu_is_omap44xx()) {
-               bank->level_mask =
-                       __raw_readl(bank->base + OMAP4_GPIO_LEVELDETECT0) |
-                       __raw_readl(bank->base + OMAP4_GPIO_LEVELDETECT1);
-       } else {
-               bank->level_mask =
-                       __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0) |
-                       __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1);
-       }
-}
-#endif
-
-#ifdef CONFIG_ARCH_OMAP1
-/*
- * This only applies to chips that can't do both rising and falling edge
- * detection at once.  For all other chips, this function is a noop.
- */
-static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio)
-{
-       void __iomem *reg = bank->base;
-       u32 l = 0;
-
-       switch (bank->method) {
-       case METHOD_MPUIO:
-               reg += OMAP_MPUIO_GPIO_INT_EDGE / bank->stride;
-               break;
-#ifdef CONFIG_ARCH_OMAP15XX
-       case METHOD_GPIO_1510:
-               reg += OMAP1510_GPIO_INT_CONTROL;
-               break;
-#endif
-#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
-       case METHOD_GPIO_7XX:
-               reg += OMAP7XX_GPIO_INT_CONTROL;
-               break;
-#endif
-       default:
-               return;
-       }
-
-       l = __raw_readl(reg);
-       if ((l >> gpio) & 1)
-               l &= ~(1 << gpio);
-       else
-               l |= 1 << gpio;
-
-       __raw_writel(l, reg);
-}
-#endif
-
-static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
-{
-       void __iomem *reg = bank->base;
-       u32 l = 0;
-
-       switch (bank->method) {
-#ifdef CONFIG_ARCH_OMAP1
-       case METHOD_MPUIO:
-               reg += OMAP_MPUIO_GPIO_INT_EDGE / bank->stride;
-               l = __raw_readl(reg);
-               if ((trigger & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH)
-                       bank->toggle_mask |= 1 << gpio;
-               if (trigger & IRQ_TYPE_EDGE_RISING)
-                       l |= 1 << gpio;
-               else if (trigger & IRQ_TYPE_EDGE_FALLING)
-                       l &= ~(1 << gpio);
-               else
-                       goto bad;
-               break;
-#endif
-#ifdef CONFIG_ARCH_OMAP15XX
-       case METHOD_GPIO_1510:
-               reg += OMAP1510_GPIO_INT_CONTROL;
-               l = __raw_readl(reg);
-               if ((trigger & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH)
-                       bank->toggle_mask |= 1 << gpio;
-               if (trigger & IRQ_TYPE_EDGE_RISING)
-                       l |= 1 << gpio;
-               else if (trigger & IRQ_TYPE_EDGE_FALLING)
-                       l &= ~(1 << gpio);
-               else
-                       goto bad;
-               break;
-#endif
-#ifdef CONFIG_ARCH_OMAP16XX
-       case METHOD_GPIO_1610:
-               if (gpio & 0x08)
-                       reg += OMAP1610_GPIO_EDGE_CTRL2;
-               else
-                       reg += OMAP1610_GPIO_EDGE_CTRL1;
-               gpio &= 0x07;
-               l = __raw_readl(reg);
-               l &= ~(3 << (gpio << 1));
-               if (trigger & IRQ_TYPE_EDGE_RISING)
-                       l |= 2 << (gpio << 1);
-               if (trigger & IRQ_TYPE_EDGE_FALLING)
-                       l |= 1 << (gpio << 1);
-               if (trigger)
-                       /* Enable wake-up during idle for dynamic tick */
-                       __raw_writel(1 << gpio, bank->base + OMAP1610_GPIO_SET_WAKEUPENA);
-               else
-                       __raw_writel(1 << gpio, bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA);
-               break;
-#endif
-#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
-       case METHOD_GPIO_7XX:
-               reg += OMAP7XX_GPIO_INT_CONTROL;
-               l = __raw_readl(reg);
-               if ((trigger & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH)
-                       bank->toggle_mask |= 1 << gpio;
-               if (trigger & IRQ_TYPE_EDGE_RISING)
-                       l |= 1 << gpio;
-               else if (trigger & IRQ_TYPE_EDGE_FALLING)
-                       l &= ~(1 << gpio);
-               else
-                       goto bad;
-               break;
-#endif
-#ifdef CONFIG_ARCH_OMAP2PLUS
-       case METHOD_GPIO_24XX:
-       case METHOD_GPIO_44XX:
-               set_24xx_gpio_triggering(bank, gpio, trigger);
-               return 0;
-#endif
-       default:
-               goto bad;
-       }
-       __raw_writel(l, reg);
-       return 0;
-bad:
-       return -EINVAL;
-}
-
-static int gpio_irq_type(struct irq_data *d, unsigned type)
-{
-       struct gpio_bank *bank;
-       unsigned gpio;
-       int retval;
-       unsigned long flags;
-
-       if (!cpu_class_is_omap2() && d->irq > IH_MPUIO_BASE)
-               gpio = OMAP_MPUIO(d->irq - IH_MPUIO_BASE);
-       else
-               gpio = d->irq - IH_GPIO_BASE;
-
-       if (check_gpio(gpio) < 0)
-               return -EINVAL;
-
-       if (type & ~IRQ_TYPE_SENSE_MASK)
-               return -EINVAL;
-
-       /* OMAP1 allows only only edge triggering */
-       if (!cpu_class_is_omap2()
-                       && (type & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH)))
-               return -EINVAL;
-
-       bank = irq_data_get_irq_chip_data(d);
-       spin_lock_irqsave(&bank->lock, flags);
-       retval = _set_gpio_triggering(bank, get_gpio_index(gpio), type);
-       spin_unlock_irqrestore(&bank->lock, flags);
-
-       if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
-               __irq_set_handler_locked(d->irq, handle_level_irq);
-       else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
-               __irq_set_handler_locked(d->irq, handle_edge_irq);
-
-       return retval;
-}
-
-static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
-{
-       void __iomem *reg = bank->base;
-
-       switch (bank->method) {
-#ifdef CONFIG_ARCH_OMAP1
-       case METHOD_MPUIO:
-               /* MPUIO irqstatus is reset by reading the status register,
-                * so do nothing here */
-               return;
-#endif
-#ifdef CONFIG_ARCH_OMAP15XX
-       case METHOD_GPIO_1510:
-               reg += OMAP1510_GPIO_INT_STATUS;
-               break;
-#endif
-#ifdef CONFIG_ARCH_OMAP16XX
-       case METHOD_GPIO_1610:
-               reg += OMAP1610_GPIO_IRQSTATUS1;
-               break;
-#endif
-#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
-       case METHOD_GPIO_7XX:
-               reg += OMAP7XX_GPIO_INT_STATUS;
-               break;
-#endif
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-       case METHOD_GPIO_24XX:
-               reg += OMAP24XX_GPIO_IRQSTATUS1;
-               break;
-#endif
-#if defined(CONFIG_ARCH_OMAP4)
-       case METHOD_GPIO_44XX:
-               reg += OMAP4_GPIO_IRQSTATUS0;
-               break;
-#endif
-       default:
-               WARN_ON(1);
-               return;
-       }
-       __raw_writel(gpio_mask, reg);
-
-       /* Workaround for clearing DSP GPIO interrupts to allow retention */
-       if (cpu_is_omap24xx() || cpu_is_omap34xx())
-               reg = bank->base + OMAP24XX_GPIO_IRQSTATUS2;
-       else if (cpu_is_omap44xx())
-               reg = bank->base + OMAP4_GPIO_IRQSTATUS1;
-
-       if (cpu_is_omap24xx() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
-               __raw_writel(gpio_mask, reg);
-
-       /* Flush posted write for the irq status to avoid spurious interrupts */
-       __raw_readl(reg);
-       }
-}
-
-static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio)
-{
-       _clear_gpio_irqbank(bank, 1 << get_gpio_index(gpio));
-}
-
-static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank)
-{
-       void __iomem *reg = bank->base;
-       int inv = 0;
-       u32 l;
-       u32 mask;
-
-       switch (bank->method) {
-#ifdef CONFIG_ARCH_OMAP1
-       case METHOD_MPUIO:
-               reg += OMAP_MPUIO_GPIO_MASKIT / bank->stride;
-               mask = 0xffff;
-               inv = 1;
-               break;
-#endif
-#ifdef CONFIG_ARCH_OMAP15XX
-       case METHOD_GPIO_1510:
-               reg += OMAP1510_GPIO_INT_MASK;
-               mask = 0xffff;
-               inv = 1;
-               break;
-#endif
-#ifdef CONFIG_ARCH_OMAP16XX
-       case METHOD_GPIO_1610:
-               reg += OMAP1610_GPIO_IRQENABLE1;
-               mask = 0xffff;
-               break;
-#endif
-#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
-       case METHOD_GPIO_7XX:
-               reg += OMAP7XX_GPIO_INT_MASK;
-               mask = 0xffffffff;
-               inv = 1;
-               break;
-#endif
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-       case METHOD_GPIO_24XX:
-               reg += OMAP24XX_GPIO_IRQENABLE1;
-               mask = 0xffffffff;
-               break;
-#endif
-#if defined(CONFIG_ARCH_OMAP4)
-       case METHOD_GPIO_44XX:
-               reg += OMAP4_GPIO_IRQSTATUSSET0;
-               mask = 0xffffffff;
-               break;
-#endif
-       default:
-               WARN_ON(1);
-               return 0;
-       }
-
-       l = __raw_readl(reg);
-       if (inv)
-               l = ~l;
-       l &= mask;
-       return l;
-}
-
-static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enable)
-{
-       void __iomem *reg = bank->base;
-       u32 l;
-
-       switch (bank->method) {
-#ifdef CONFIG_ARCH_OMAP1
-       case METHOD_MPUIO:
-               reg += OMAP_MPUIO_GPIO_MASKIT / bank->stride;
-               l = __raw_readl(reg);
-               if (enable)
-                       l &= ~(gpio_mask);
-               else
-                       l |= gpio_mask;
-               break;
-#endif
-#ifdef CONFIG_ARCH_OMAP15XX
-       case METHOD_GPIO_1510:
-               reg += OMAP1510_GPIO_INT_MASK;
-               l = __raw_readl(reg);
-               if (enable)
-                       l &= ~(gpio_mask);
-               else
-                       l |= gpio_mask;
-               break;
-#endif
-#ifdef CONFIG_ARCH_OMAP16XX
-       case METHOD_GPIO_1610:
-               if (enable)
-                       reg += OMAP1610_GPIO_SET_IRQENABLE1;
-               else
-                       reg += OMAP1610_GPIO_CLEAR_IRQENABLE1;
-               l = gpio_mask;
-               break;
-#endif
-#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
-       case METHOD_GPIO_7XX:
-               reg += OMAP7XX_GPIO_INT_MASK;
-               l = __raw_readl(reg);
-               if (enable)
-                       l &= ~(gpio_mask);
-               else
-                       l |= gpio_mask;
-               break;
-#endif
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-       case METHOD_GPIO_24XX:
-               if (enable)
-                       reg += OMAP24XX_GPIO_SETIRQENABLE1;
-               else
-                       reg += OMAP24XX_GPIO_CLEARIRQENABLE1;
-               l = gpio_mask;
-               break;
-#endif
-#ifdef CONFIG_ARCH_OMAP4
-       case METHOD_GPIO_44XX:
-               if (enable)
-                       reg += OMAP4_GPIO_IRQSTATUSSET0;
-               else
-                       reg += OMAP4_GPIO_IRQSTATUSCLR0;
-               l = gpio_mask;
-               break;
-#endif
-       default:
-               WARN_ON(1);
-               return;
-       }
-       __raw_writel(l, reg);
-}
-
-static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int enable)
-{
-       _enable_gpio_irqbank(bank, 1 << get_gpio_index(gpio), enable);
-}
-
-/*
- * Note that ENAWAKEUP needs to be enabled in GPIO_SYSCONFIG register.
- * 1510 does not seem to have a wake-up register. If JTAG is connected
- * to the target, system will wake up always on GPIO events. While
- * system is running all registered GPIO interrupts need to have wake-up
- * enabled. When system is suspended, only selected GPIO interrupts need
- * to have wake-up enabled.
- */
-static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
-{
-       unsigned long uninitialized_var(flags);
-
-       switch (bank->method) {
-#ifdef CONFIG_ARCH_OMAP16XX
-       case METHOD_MPUIO:
-       case METHOD_GPIO_1610:
-               spin_lock_irqsave(&bank->lock, flags);
-               if (enable)
-                       bank->suspend_wakeup |= (1 << gpio);
-               else
-                       bank->suspend_wakeup &= ~(1 << gpio);
-               spin_unlock_irqrestore(&bank->lock, flags);
-               return 0;
-#endif
-#ifdef CONFIG_ARCH_OMAP2PLUS
-       case METHOD_GPIO_24XX:
-       case METHOD_GPIO_44XX:
-               if (bank->non_wakeup_gpios & (1 << gpio)) {
-                       printk(KERN_ERR "Unable to modify wakeup on "
-                                       "non-wakeup GPIO%d\n",
-                                       (bank - gpio_bank) * 32 + gpio);
-                       return -EINVAL;
-               }
-               spin_lock_irqsave(&bank->lock, flags);
-               if (enable)
-                       bank->suspend_wakeup |= (1 << gpio);
-               else
-                       bank->suspend_wakeup &= ~(1 << gpio);
-               spin_unlock_irqrestore(&bank->lock, flags);
-               return 0;
-#endif
-       default:
-               printk(KERN_ERR "Can't enable GPIO wakeup for method %i\n",
-                      bank->method);
-               return -EINVAL;
-       }
-}
-
-static void _reset_gpio(struct gpio_bank *bank, int gpio)
-{
-       _set_gpio_direction(bank, get_gpio_index(gpio), 1);
-       _set_gpio_irqenable(bank, gpio, 0);
-       _clear_gpio_irqstatus(bank, gpio);
-       _set_gpio_triggering(bank, get_gpio_index(gpio), IRQ_TYPE_NONE);
-}
-
-/* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
-static int gpio_wake_enable(struct irq_data *d, unsigned int enable)
-{
-       unsigned int gpio = d->irq - IH_GPIO_BASE;
-       struct gpio_bank *bank;
-       int retval;
-
-       if (check_gpio(gpio) < 0)
-               return -ENODEV;
-       bank = irq_data_get_irq_chip_data(d);
-       retval = _set_gpio_wakeup(bank, get_gpio_index(gpio), enable);
-
-       return retval;
-}
-
-static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
-       struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip);
-       unsigned long flags;
-
-       spin_lock_irqsave(&bank->lock, flags);
-
-       /* Set trigger to none. You need to enable the desired trigger with
-        * request_irq() or set_irq_type().
-        */
-       _set_gpio_triggering(bank, offset, IRQ_TYPE_NONE);
-
-#ifdef CONFIG_ARCH_OMAP15XX
-       if (bank->method == METHOD_GPIO_1510) {
-               void __iomem *reg;
-
-               /* Claim the pin for MPU */
-               reg = bank->base + OMAP1510_GPIO_PIN_CONTROL;
-               __raw_writel(__raw_readl(reg) | (1 << offset), reg);
-       }
-#endif
-       if (!cpu_class_is_omap1()) {
-               if (!bank->mod_usage) {
-                       void __iomem *reg = bank->base;
-                       u32 ctrl;
-
-                       if (cpu_is_omap24xx() || cpu_is_omap34xx())
-                               reg += OMAP24XX_GPIO_CTRL;
-                       else if (cpu_is_omap44xx())
-                               reg += OMAP4_GPIO_CTRL;
-                       ctrl = __raw_readl(reg);
-                       /* Module is enabled, clocks are not gated */
-                       ctrl &= 0xFFFFFFFE;
-                       __raw_writel(ctrl, reg);
-               }
-               bank->mod_usage |= 1 << offset;
-       }
-       spin_unlock_irqrestore(&bank->lock, flags);
-
-       return 0;
-}
-
-static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
-       struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip);
-       unsigned long flags;
-
-       spin_lock_irqsave(&bank->lock, flags);
-#ifdef CONFIG_ARCH_OMAP16XX
-       if (bank->method == METHOD_GPIO_1610) {
-               /* Disable wake-up during idle for dynamic tick */
-               void __iomem *reg = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
-               __raw_writel(1 << offset, reg);
-       }
-#endif
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-       if (bank->method == METHOD_GPIO_24XX) {
-               /* Disable wake-up during idle for dynamic tick */
-               void __iomem *reg = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
-               __raw_writel(1 << offset, reg);
-       }
-#endif
-#ifdef CONFIG_ARCH_OMAP4
-       if (bank->method == METHOD_GPIO_44XX) {
-               /* Disable wake-up during idle for dynamic tick */
-               void __iomem *reg = bank->base + OMAP4_GPIO_IRQWAKEN0;
-               __raw_writel(1 << offset, reg);
-       }
-#endif
-       if (!cpu_class_is_omap1()) {
-               bank->mod_usage &= ~(1 << offset);
-               if (!bank->mod_usage) {
-                       void __iomem *reg = bank->base;
-                       u32 ctrl;
-
-                       if (cpu_is_omap24xx() || cpu_is_omap34xx())
-                               reg += OMAP24XX_GPIO_CTRL;
-                       else if (cpu_is_omap44xx())
-                               reg += OMAP4_GPIO_CTRL;
-                       ctrl = __raw_readl(reg);
-                       /* Module is disabled, clocks are gated */
-                       ctrl |= 1;
-                       __raw_writel(ctrl, reg);
-               }
-       }
-       _reset_gpio(bank, bank->chip.base + offset);
-       spin_unlock_irqrestore(&bank->lock, flags);
-}
-
-/*
- * We need to unmask the GPIO bank interrupt as soon as possible to
- * avoid missing GPIO interrupts for other lines in the bank.
- * Then we need to mask-read-clear-unmask the triggered GPIO lines
- * in the bank to avoid missing nested interrupts for a GPIO line.
- * If we wait to unmask individual GPIO lines in the bank after the
- * line's interrupt handler has been run, we may miss some nested
- * interrupts.
- */
-static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
-{
-       void __iomem *isr_reg = NULL;
-       u32 isr;
-       unsigned int gpio_irq, gpio_index;
-       struct gpio_bank *bank;
-       u32 retrigger = 0;
-       int unmasked = 0;
-       struct irq_chip *chip = irq_desc_get_chip(desc);
-
-       chained_irq_enter(chip, desc);
-
-       bank = irq_get_handler_data(irq);
-#ifdef CONFIG_ARCH_OMAP1
-       if (bank->method == METHOD_MPUIO)
-               isr_reg = bank->base +
-                               OMAP_MPUIO_GPIO_INT / bank->stride;
-#endif
-#ifdef CONFIG_ARCH_OMAP15XX
-       if (bank->method == METHOD_GPIO_1510)
-               isr_reg = bank->base + OMAP1510_GPIO_INT_STATUS;
-#endif
-#if defined(CONFIG_ARCH_OMAP16XX)
-       if (bank->method == METHOD_GPIO_1610)
-               isr_reg = bank->base + OMAP1610_GPIO_IRQSTATUS1;
-#endif
-#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
-       if (bank->method == METHOD_GPIO_7XX)
-               isr_reg = bank->base + OMAP7XX_GPIO_INT_STATUS;
-#endif
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-       if (bank->method == METHOD_GPIO_24XX)
-               isr_reg = bank->base + OMAP24XX_GPIO_IRQSTATUS1;
-#endif
-#if defined(CONFIG_ARCH_OMAP4)
-       if (bank->method == METHOD_GPIO_44XX)
-               isr_reg = bank->base + OMAP4_GPIO_IRQSTATUS0;
-#endif
-
-       if (WARN_ON(!isr_reg))
-               goto exit;
-
-       while(1) {
-               u32 isr_saved, level_mask = 0;
-               u32 enabled;
-
-               enabled = _get_gpio_irqbank_mask(bank);
-               isr_saved = isr = __raw_readl(isr_reg) & enabled;
-
-               if (cpu_is_omap15xx() && (bank->method == METHOD_MPUIO))
-                       isr &= 0x0000ffff;
-
-               if (cpu_class_is_omap2()) {
-                       level_mask = bank->level_mask & enabled;
-               }
-
-               /* clear edge sensitive interrupts before handler(s) are
-               called so that we don't miss any interrupt occurred while
-               executing them */
-               _enable_gpio_irqbank(bank, isr_saved & ~level_mask, 0);
-               _clear_gpio_irqbank(bank, isr_saved & ~level_mask);
-               _enable_gpio_irqbank(bank, isr_saved & ~level_mask, 1);
-
-               /* if there is only edge sensitive GPIO pin interrupts
-               configured, we could unmask GPIO bank interrupt immediately */
-               if (!level_mask && !unmasked) {
-                       unmasked = 1;
-                       chained_irq_exit(chip, desc);
-               }
-
-               isr |= retrigger;
-               retrigger = 0;
-               if (!isr)
-                       break;
-
-               gpio_irq = bank->virtual_irq_start;
-               for (; isr != 0; isr >>= 1, gpio_irq++) {
-                       gpio_index = get_gpio_index(irq_to_gpio(gpio_irq));
-
-                       if (!(isr & 1))
-                               continue;
-
-#ifdef CONFIG_ARCH_OMAP1
-                       /*
-                        * Some chips can't respond to both rising and falling
-                        * at the same time.  If this irq was requested with
-                        * both flags, we need to flip the ICR data for the IRQ
-                        * to respond to the IRQ for the opposite direction.
-                        * This will be indicated in the bank toggle_mask.
-                        */
-                       if (bank->toggle_mask & (1 << gpio_index))
-                               _toggle_gpio_edge_triggering(bank, gpio_index);
-#endif
-
-                       generic_handle_irq(gpio_irq);
-               }
-       }
-       /* if bank has any level sensitive GPIO pin interrupt
-       configured, we must unmask the bank interrupt only after
-       handler(s) are executed in order to avoid spurious bank
-       interrupt */
-exit:
-       if (!unmasked)
-               chained_irq_exit(chip, desc);
-}
-
-static void gpio_irq_shutdown(struct irq_data *d)
-{
-       unsigned int gpio = d->irq - IH_GPIO_BASE;
-       struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
-
-       _reset_gpio(bank, gpio);
-}
-
-static void gpio_ack_irq(struct irq_data *d)
-{
-       unsigned int gpio = d->irq - IH_GPIO_BASE;
-       struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
-
-       _clear_gpio_irqstatus(bank, gpio);
-}
-
-static void gpio_mask_irq(struct irq_data *d)
-{
-       unsigned int gpio = d->irq - IH_GPIO_BASE;
-       struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
-
-       _set_gpio_irqenable(bank, gpio, 0);
-       _set_gpio_triggering(bank, get_gpio_index(gpio), IRQ_TYPE_NONE);
-}
-
-static void gpio_unmask_irq(struct irq_data *d)
-{
-       unsigned int gpio = d->irq - IH_GPIO_BASE;
-       struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
-       unsigned int irq_mask = 1 << get_gpio_index(gpio);
-       u32 trigger = irqd_get_trigger_type(d);
-
-       if (trigger)
-               _set_gpio_triggering(bank, get_gpio_index(gpio), trigger);
-
-       /* For level-triggered GPIOs, the clearing must be done after
-        * the HW source is cleared, thus after the handler has run */
-       if (bank->level_mask & irq_mask) {
-               _set_gpio_irqenable(bank, gpio, 0);
-               _clear_gpio_irqstatus(bank, gpio);
-       }
-
-       _set_gpio_irqenable(bank, gpio, 1);
-}
-
-static struct irq_chip gpio_irq_chip = {
-       .name           = "GPIO",
-       .irq_shutdown   = gpio_irq_shutdown,
-       .irq_ack        = gpio_ack_irq,
-       .irq_mask       = gpio_mask_irq,
-       .irq_unmask     = gpio_unmask_irq,
-       .irq_set_type   = gpio_irq_type,
-       .irq_set_wake   = gpio_wake_enable,
-};
-
-/*---------------------------------------------------------------------*/
-
-#ifdef CONFIG_ARCH_OMAP1
-
-/* MPUIO uses the always-on 32k clock */
-
-static void mpuio_ack_irq(struct irq_data *d)
-{
-       /* The ISR is reset automatically, so do nothing here. */
-}
-
-static void mpuio_mask_irq(struct irq_data *d)
-{
-       unsigned int gpio = OMAP_MPUIO(d->irq - IH_MPUIO_BASE);
-       struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
-
-       _set_gpio_irqenable(bank, gpio, 0);
-}
-
-static void mpuio_unmask_irq(struct irq_data *d)
-{
-       unsigned int gpio = OMAP_MPUIO(d->irq - IH_MPUIO_BASE);
-       struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
-
-       _set_gpio_irqenable(bank, gpio, 1);
-}
-
-static struct irq_chip mpuio_irq_chip = {
-       .name           = "MPUIO",
-       .irq_ack        = mpuio_ack_irq,
-       .irq_mask       = mpuio_mask_irq,
-       .irq_unmask     = mpuio_unmask_irq,
-       .irq_set_type   = gpio_irq_type,
-#ifdef CONFIG_ARCH_OMAP16XX
-       /* REVISIT: assuming only 16xx supports MPUIO wake events */
-       .irq_set_wake   = gpio_wake_enable,
-#endif
-};
-
-
-#define bank_is_mpuio(bank)    ((bank)->method == METHOD_MPUIO)
-
-
-#ifdef CONFIG_ARCH_OMAP16XX
-
-#include <linux/platform_device.h>
-
-static int omap_mpuio_suspend_noirq(struct device *dev)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       struct gpio_bank        *bank = platform_get_drvdata(pdev);
-       void __iomem            *mask_reg = bank->base +
-                                       OMAP_MPUIO_GPIO_MASKIT / bank->stride;
-       unsigned long           flags;
-
-       spin_lock_irqsave(&bank->lock, flags);
-       bank->saved_wakeup = __raw_readl(mask_reg);
-       __raw_writel(0xffff & ~bank->suspend_wakeup, mask_reg);
-       spin_unlock_irqrestore(&bank->lock, flags);
-
-       return 0;
-}
-
-static int omap_mpuio_resume_noirq(struct device *dev)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       struct gpio_bank        *bank = platform_get_drvdata(pdev);
-       void __iomem            *mask_reg = bank->base +
-                                       OMAP_MPUIO_GPIO_MASKIT / bank->stride;
-       unsigned long           flags;
-
-       spin_lock_irqsave(&bank->lock, flags);
-       __raw_writel(bank->saved_wakeup, mask_reg);
-       spin_unlock_irqrestore(&bank->lock, flags);
-
-       return 0;
-}
-
-static const struct dev_pm_ops omap_mpuio_dev_pm_ops = {
-       .suspend_noirq = omap_mpuio_suspend_noirq,
-       .resume_noirq = omap_mpuio_resume_noirq,
-};
-
-/* use platform_driver for this. */
-static struct platform_driver omap_mpuio_driver = {
-       .driver         = {
-               .name   = "mpuio",
-               .pm     = &omap_mpuio_dev_pm_ops,
-       },
-};
-
-static struct platform_device omap_mpuio_device = {
-       .name           = "mpuio",
-       .id             = -1,
-       .dev = {
-               .driver = &omap_mpuio_driver.driver,
-       }
-       /* could list the /proc/iomem resources */
-};
-
-static inline void mpuio_init(void)
-{
-       struct gpio_bank *bank = get_gpio_bank(OMAP_MPUIO(0));
-       platform_set_drvdata(&omap_mpuio_device, bank);
-
-       if (platform_driver_register(&omap_mpuio_driver) == 0)
-               (void) platform_device_register(&omap_mpuio_device);
-}
-
-#else
-static inline void mpuio_init(void) {}
-#endif /* 16xx */
-
-#else
-
-extern struct irq_chip mpuio_irq_chip;
-
-#define bank_is_mpuio(bank)    0
-static inline void mpuio_init(void) {}
-
-#endif
-
-/*---------------------------------------------------------------------*/
-
-/* REVISIT these are stupid implementations!  replace by ones that
- * don't switch on METHOD_* and which mostly avoid spinlocks
- */
-
-static int gpio_input(struct gpio_chip *chip, unsigned offset)
-{
-       struct gpio_bank *bank;
-       unsigned long flags;
-
-       bank = container_of(chip, struct gpio_bank, chip);
-       spin_lock_irqsave(&bank->lock, flags);
-       _set_gpio_direction(bank, offset, 1);
-       spin_unlock_irqrestore(&bank->lock, flags);
-       return 0;
-}
-
-static int gpio_is_input(struct gpio_bank *bank, int mask)
-{
-       void __iomem *reg = bank->base;
-
-       switch (bank->method) {
-       case METHOD_MPUIO:
-               reg += OMAP_MPUIO_IO_CNTL / bank->stride;
-               break;
-       case METHOD_GPIO_1510:
-               reg += OMAP1510_GPIO_DIR_CONTROL;
-               break;
-       case METHOD_GPIO_1610:
-               reg += OMAP1610_GPIO_DIRECTION;
-               break;
-       case METHOD_GPIO_7XX:
-               reg += OMAP7XX_GPIO_DIR_CONTROL;
-               break;
-       case METHOD_GPIO_24XX:
-               reg += OMAP24XX_GPIO_OE;
-               break;
-       case METHOD_GPIO_44XX:
-               reg += OMAP4_GPIO_OE;
-               break;
-       default:
-               WARN_ONCE(1, "gpio_is_input: incorrect OMAP GPIO method");
-               return -EINVAL;
-       }
-       return __raw_readl(reg) & mask;
-}
-
-static int gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-       struct gpio_bank *bank;
-       void __iomem *reg;
-       int gpio;
-       u32 mask;
-
-       gpio = chip->base + offset;
-       bank = get_gpio_bank(gpio);
-       reg = bank->base;
-       mask = 1 << get_gpio_index(gpio);
-
-       if (gpio_is_input(bank, mask))
-               return _get_gpio_datain(bank, gpio);
-       else
-               return _get_gpio_dataout(bank, gpio);
-}
-
-static int gpio_output(struct gpio_chip *chip, unsigned offset, int value)
-{
-       struct gpio_bank *bank;
-       unsigned long flags;
-
-       bank = container_of(chip, struct gpio_bank, chip);
-       spin_lock_irqsave(&bank->lock, flags);
-       _set_gpio_dataout(bank, offset, value);
-       _set_gpio_direction(bank, offset, 0);
-       spin_unlock_irqrestore(&bank->lock, flags);
-       return 0;
-}
-
-static int gpio_debounce(struct gpio_chip *chip, unsigned offset,
-               unsigned debounce)
-{
-       struct gpio_bank *bank;
-       unsigned long flags;
-
-       bank = container_of(chip, struct gpio_bank, chip);
-
-       if (!bank->dbck) {
-               bank->dbck = clk_get(bank->dev, "dbclk");
-               if (IS_ERR(bank->dbck))
-                       dev_err(bank->dev, "Could not get gpio dbck\n");
-       }
-
-       spin_lock_irqsave(&bank->lock, flags);
-       _set_gpio_debounce(bank, offset, debounce);
-       spin_unlock_irqrestore(&bank->lock, flags);
-
-       return 0;
-}
-
-static void gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-       struct gpio_bank *bank;
-       unsigned long flags;
-
-       bank = container_of(chip, struct gpio_bank, chip);
-       spin_lock_irqsave(&bank->lock, flags);
-       _set_gpio_dataout(bank, offset, value);
-       spin_unlock_irqrestore(&bank->lock, flags);
-}
-
-static int gpio_2irq(struct gpio_chip *chip, unsigned offset)
-{
-       struct gpio_bank *bank;
-
-       bank = container_of(chip, struct gpio_bank, chip);
-       return bank->virtual_irq_start + offset;
-}
-
-/*---------------------------------------------------------------------*/
-
-static void __init omap_gpio_show_rev(struct gpio_bank *bank)
-{
-       u32 rev;
-
-       if (cpu_is_omap16xx() && !(bank->method != METHOD_MPUIO))
-               rev = __raw_readw(bank->base + OMAP1610_GPIO_REVISION);
-       else if (cpu_is_omap24xx() || cpu_is_omap34xx())
-               rev = __raw_readl(bank->base + OMAP24XX_GPIO_REVISION);
-       else if (cpu_is_omap44xx())
-               rev = __raw_readl(bank->base + OMAP4_GPIO_REVISION);
-       else
-               return;
-
-       printk(KERN_INFO "OMAP GPIO hardware version %d.%d\n",
-               (rev >> 4) & 0x0f, rev & 0x0f);
-}
-
-/* This lock class tells lockdep that GPIO irqs are in a different
- * category than their parents, so it won't report false recursion.
- */
-static struct lock_class_key gpio_lock_class;
-
-static inline int init_gpio_info(struct platform_device *pdev)
-{
-       /* TODO: Analyze removing gpio_bank_count usage from driver code */
-       gpio_bank = kzalloc(gpio_bank_count * sizeof(struct gpio_bank),
-                               GFP_KERNEL);
-       if (!gpio_bank) {
-               dev_err(&pdev->dev, "Memory alloc failed for gpio_bank\n");
-               return -ENOMEM;
-       }
-       return 0;
-}
-
-/* TODO: Cleanup cpu_is_* checks */
-static void omap_gpio_mod_init(struct gpio_bank *bank, int id)
-{
-       if (cpu_class_is_omap2()) {
-               if (cpu_is_omap44xx()) {
-                       __raw_writel(0xffffffff, bank->base +
-                                       OMAP4_GPIO_IRQSTATUSCLR0);
-                       __raw_writel(0x00000000, bank->base +
-                                        OMAP4_GPIO_DEBOUNCENABLE);
-                       /* Initialize interface clk ungated, module enabled */
-                       __raw_writel(0, bank->base + OMAP4_GPIO_CTRL);
-               } else if (cpu_is_omap34xx()) {
-                       __raw_writel(0x00000000, bank->base +
-                                       OMAP24XX_GPIO_IRQENABLE1);
-                       __raw_writel(0xffffffff, bank->base +
-                                       OMAP24XX_GPIO_IRQSTATUS1);
-                       __raw_writel(0x00000000, bank->base +
-                                       OMAP24XX_GPIO_DEBOUNCE_EN);
-
-                       /* Initialize interface clk ungated, module enabled */
-                       __raw_writel(0, bank->base + OMAP24XX_GPIO_CTRL);
-               } else if (cpu_is_omap24xx()) {
-                       static const u32 non_wakeup_gpios[] = {
-                               0xe203ffc0, 0x08700040
-                       };
-                       if (id < ARRAY_SIZE(non_wakeup_gpios))
-                               bank->non_wakeup_gpios = non_wakeup_gpios[id];
-               }
-       } else if (cpu_class_is_omap1()) {
-               if (bank_is_mpuio(bank))
-                       __raw_writew(0xffff, bank->base +
-                               OMAP_MPUIO_GPIO_MASKIT / bank->stride);
-               if (cpu_is_omap15xx() && bank->method == METHOD_GPIO_1510) {
-                       __raw_writew(0xffff, bank->base
-                                               + OMAP1510_GPIO_INT_MASK);
-                       __raw_writew(0x0000, bank->base
-                                               + OMAP1510_GPIO_INT_STATUS);
-               }
-               if (cpu_is_omap16xx() && bank->method == METHOD_GPIO_1610) {
-                       __raw_writew(0x0000, bank->base
-                                               + OMAP1610_GPIO_IRQENABLE1);
-                       __raw_writew(0xffff, bank->base
-                                               + OMAP1610_GPIO_IRQSTATUS1);
-                       __raw_writew(0x0014, bank->base
-                                               + OMAP1610_GPIO_SYSCONFIG);
-
-                       /*
-                        * Enable system clock for GPIO module.
-                        * The CAM_CLK_CTRL *is* really the right place.
-                        */
-                       omap_writel(omap_readl(ULPD_CAM_CLK_CTRL) | 0x04,
-                                               ULPD_CAM_CLK_CTRL);
-               }
-               if (cpu_is_omap7xx() && bank->method == METHOD_GPIO_7XX) {
-                       __raw_writel(0xffffffff, bank->base
-                                               + OMAP7XX_GPIO_INT_MASK);
-                       __raw_writel(0x00000000, bank->base
-                                               + OMAP7XX_GPIO_INT_STATUS);
-               }
-       }
-}
-
-static void __init omap_gpio_chip_init(struct gpio_bank *bank)
-{
-       int j;
-       static int gpio;
-
-       bank->mod_usage = 0;
-       /*
-        * REVISIT eventually switch from OMAP-specific gpio structs
-        * over to the generic ones
-        */
-       bank->chip.request = omap_gpio_request;
-       bank->chip.free = omap_gpio_free;
-       bank->chip.direction_input = gpio_input;
-       bank->chip.get = gpio_get;
-       bank->chip.direction_output = gpio_output;
-       bank->chip.set_debounce = gpio_debounce;
-       bank->chip.set = gpio_set;
-       bank->chip.to_irq = gpio_2irq;
-       if (bank_is_mpuio(bank)) {
-               bank->chip.label = "mpuio";
-#ifdef CONFIG_ARCH_OMAP16XX
-               bank->chip.dev = &omap_mpuio_device.dev;
-#endif
-               bank->chip.base = OMAP_MPUIO(0);
-       } else {
-               bank->chip.label = "gpio";
-               bank->chip.base = gpio;
-               gpio += bank_width;
-       }
-       bank->chip.ngpio = bank_width;
-
-       gpiochip_add(&bank->chip);
-
-       for (j = bank->virtual_irq_start;
-                    j < bank->virtual_irq_start + bank_width; j++) {
-               irq_set_lockdep_class(j, &gpio_lock_class);
-               irq_set_chip_data(j, bank);
-               if (bank_is_mpuio(bank))
-                       irq_set_chip(j, &mpuio_irq_chip);
-               else
-                       irq_set_chip(j, &gpio_irq_chip);
-               irq_set_handler(j, handle_simple_irq);
-               set_irq_flags(j, IRQF_VALID);
-       }
-       irq_set_chained_handler(bank->irq, gpio_irq_handler);
-       irq_set_handler_data(bank->irq, bank);
-}
-
-static int __devinit omap_gpio_probe(struct platform_device *pdev)
-{
-       static int gpio_init_done;
-       struct omap_gpio_platform_data *pdata;
-       struct resource *res;
-       int id;
-       struct gpio_bank *bank;
-
-       if (!pdev->dev.platform_data)
-               return -EINVAL;
-
-       pdata = pdev->dev.platform_data;
-
-       if (!gpio_init_done) {
-               int ret;
-
-               ret = init_gpio_info(pdev);
-               if (ret)
-                       return ret;
-       }
-
-       id = pdev->id;
-       bank = &gpio_bank[id];
-
-       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (unlikely(!res)) {
-               dev_err(&pdev->dev, "GPIO Bank %i Invalid IRQ resource\n", id);
-               return -ENODEV;
-       }
-
-       bank->irq = res->start;
-       bank->virtual_irq_start = pdata->virtual_irq_start;
-       bank->method = pdata->bank_type;
-       bank->dev = &pdev->dev;
-       bank->dbck_flag = pdata->dbck_flag;
-       bank->stride = pdata->bank_stride;
-       bank_width = pdata->bank_width;
-
-       spin_lock_init(&bank->lock);
-
-       /* Static mapping, never released */
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (unlikely(!res)) {
-               dev_err(&pdev->dev, "GPIO Bank %i Invalid mem resource\n", id);
-               return -ENODEV;
-       }
-
-       bank->base = ioremap(res->start, resource_size(res));
-       if (!bank->base) {
-               dev_err(&pdev->dev, "Could not ioremap gpio bank%i\n", id);
-               return -ENOMEM;
-       }
-
-       pm_runtime_enable(bank->dev);
-       pm_runtime_get_sync(bank->dev);
-
-       omap_gpio_mod_init(bank, id);
-       omap_gpio_chip_init(bank);
-       omap_gpio_show_rev(bank);
-
-       if (!gpio_init_done)
-               gpio_init_done = 1;
-
-       return 0;
-}
-
-#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS)
-static int omap_gpio_suspend(void)
-{
-       int i;
-
-       if (!cpu_class_is_omap2() && !cpu_is_omap16xx())
-               return 0;
-
-       for (i = 0; i < gpio_bank_count; i++) {
-               struct gpio_bank *bank = &gpio_bank[i];
-               void __iomem *wake_status;
-               void __iomem *wake_clear;
-               void __iomem *wake_set;
-               unsigned long flags;
-
-               switch (bank->method) {
-#ifdef CONFIG_ARCH_OMAP16XX
-               case METHOD_GPIO_1610:
-                       wake_status = bank->base + OMAP1610_GPIO_WAKEUPENABLE;
-                       wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
-                       wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
-                       break;
-#endif
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-               case METHOD_GPIO_24XX:
-                       wake_status = bank->base + OMAP24XX_GPIO_WAKE_EN;
-                       wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
-                       wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA;
-                       break;
-#endif
-#ifdef CONFIG_ARCH_OMAP4
-               case METHOD_GPIO_44XX:
-                       wake_status = bank->base + OMAP4_GPIO_IRQWAKEN0;
-                       wake_clear = bank->base + OMAP4_GPIO_IRQWAKEN0;
-                       wake_set = bank->base + OMAP4_GPIO_IRQWAKEN0;
-                       break;
-#endif
-               default:
-                       continue;
-               }
-
-               spin_lock_irqsave(&bank->lock, flags);
-               bank->saved_wakeup = __raw_readl(wake_status);
-               __raw_writel(0xffffffff, wake_clear);
-               __raw_writel(bank->suspend_wakeup, wake_set);
-               spin_unlock_irqrestore(&bank->lock, flags);
-       }
-
-       return 0;
-}
-
-static void omap_gpio_resume(void)
-{
-       int i;
-
-       if (!cpu_class_is_omap2() && !cpu_is_omap16xx())
-               return;
-
-       for (i = 0; i < gpio_bank_count; i++) {
-               struct gpio_bank *bank = &gpio_bank[i];
-               void __iomem *wake_clear;
-               void __iomem *wake_set;
-               unsigned long flags;
-
-               switch (bank->method) {
-#ifdef CONFIG_ARCH_OMAP16XX
-               case METHOD_GPIO_1610:
-                       wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
-                       wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
-                       break;
-#endif
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-               case METHOD_GPIO_24XX:
-                       wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
-                       wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA;
-                       break;
-#endif
-#ifdef CONFIG_ARCH_OMAP4
-               case METHOD_GPIO_44XX:
-                       wake_clear = bank->base + OMAP4_GPIO_IRQWAKEN0;
-                       wake_set = bank->base + OMAP4_GPIO_IRQWAKEN0;
-                       break;
-#endif
-               default:
-                       continue;
-               }
-
-               spin_lock_irqsave(&bank->lock, flags);
-               __raw_writel(0xffffffff, wake_clear);
-               __raw_writel(bank->saved_wakeup, wake_set);
-               spin_unlock_irqrestore(&bank->lock, flags);
-       }
-}
-
-static struct syscore_ops omap_gpio_syscore_ops = {
-       .suspend        = omap_gpio_suspend,
-       .resume         = omap_gpio_resume,
-};
-
-#endif
-
-#ifdef CONFIG_ARCH_OMAP2PLUS
-
-static int workaround_enabled;
-
-void omap2_gpio_prepare_for_idle(int off_mode)
-{
-       int i, c = 0;
-       int min = 0;
-
-       if (cpu_is_omap34xx())
-               min = 1;
-
-       for (i = min; i < gpio_bank_count; i++) {
-               struct gpio_bank *bank = &gpio_bank[i];
-               u32 l1 = 0, l2 = 0;
-               int j;
-
-               for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
-                       clk_disable(bank->dbck);
-
-               if (!off_mode)
-                       continue;
-
-               /* If going to OFF, remove triggering for all
-                * non-wakeup GPIOs.  Otherwise spurious IRQs will be
-                * generated.  See OMAP2420 Errata item 1.101. */
-               if (!(bank->enabled_non_wakeup_gpios))
-                       continue;
-
-               if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
-                       bank->saved_datain = __raw_readl(bank->base +
-                                       OMAP24XX_GPIO_DATAIN);
-                       l1 = __raw_readl(bank->base +
-                                       OMAP24XX_GPIO_FALLINGDETECT);
-                       l2 = __raw_readl(bank->base +
-                                       OMAP24XX_GPIO_RISINGDETECT);
-               }
-
-               if (cpu_is_omap44xx()) {
-                       bank->saved_datain = __raw_readl(bank->base +
-                                               OMAP4_GPIO_DATAIN);
-                       l1 = __raw_readl(bank->base +
-                                               OMAP4_GPIO_FALLINGDETECT);
-                       l2 = __raw_readl(bank->base +
-                                               OMAP4_GPIO_RISINGDETECT);
-               }
-
-               bank->saved_fallingdetect = l1;
-               bank->saved_risingdetect = l2;
-               l1 &= ~bank->enabled_non_wakeup_gpios;
-               l2 &= ~bank->enabled_non_wakeup_gpios;
-
-               if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
-                       __raw_writel(l1, bank->base +
-                                       OMAP24XX_GPIO_FALLINGDETECT);
-                       __raw_writel(l2, bank->base +
-                                       OMAP24XX_GPIO_RISINGDETECT);
-               }
-
-               if (cpu_is_omap44xx()) {
-                       __raw_writel(l1, bank->base + OMAP4_GPIO_FALLINGDETECT);
-                       __raw_writel(l2, bank->base + OMAP4_GPIO_RISINGDETECT);
-               }
-
-               c++;
-       }
-       if (!c) {
-               workaround_enabled = 0;
-               return;
-       }
-       workaround_enabled = 1;
-}
-
-void omap2_gpio_resume_after_idle(void)
-{
-       int i;
-       int min = 0;
-
-       if (cpu_is_omap34xx())
-               min = 1;
-       for (i = min; i < gpio_bank_count; i++) {
-               struct gpio_bank *bank = &gpio_bank[i];
-               u32 l = 0, gen, gen0, gen1;
-               int j;
-
-               for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
-                       clk_enable(bank->dbck);
-
-               if (!workaround_enabled)
-                       continue;
-
-               if (!(bank->enabled_non_wakeup_gpios))
-                       continue;
-
-               if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
-                       __raw_writel(bank->saved_fallingdetect,
-                                bank->base + OMAP24XX_GPIO_FALLINGDETECT);
-                       __raw_writel(bank->saved_risingdetect,
-                                bank->base + OMAP24XX_GPIO_RISINGDETECT);
-                       l = __raw_readl(bank->base + OMAP24XX_GPIO_DATAIN);
-               }
-
-               if (cpu_is_omap44xx()) {
-                       __raw_writel(bank->saved_fallingdetect,
-                                bank->base + OMAP4_GPIO_FALLINGDETECT);
-                       __raw_writel(bank->saved_risingdetect,
-                                bank->base + OMAP4_GPIO_RISINGDETECT);
-                       l = __raw_readl(bank->base + OMAP4_GPIO_DATAIN);
-               }
-
-               /* Check if any of the non-wakeup interrupt GPIOs have changed
-                * state.  If so, generate an IRQ by software.  This is
-                * horribly racy, but it's the best we can do to work around
-                * this silicon bug. */
-               l ^= bank->saved_datain;
-               l &= bank->enabled_non_wakeup_gpios;
-
-               /*
-                * No need to generate IRQs for the rising edge for gpio IRQs
-                * configured with falling edge only; and vice versa.
-                */
-               gen0 = l & bank->saved_fallingdetect;
-               gen0 &= bank->saved_datain;
-
-               gen1 = l & bank->saved_risingdetect;
-               gen1 &= ~(bank->saved_datain);
-
-               /* FIXME: Consider GPIO IRQs with level detections properly! */
-               gen = l & (~(bank->saved_fallingdetect) &
-                               ~(bank->saved_risingdetect));
-               /* Consider all GPIO IRQs needed to be updated */
-               gen |= gen0 | gen1;
-
-               if (gen) {
-                       u32 old0, old1;
-
-                       if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
-                               old0 = __raw_readl(bank->base +
-                                       OMAP24XX_GPIO_LEVELDETECT0);
-                               old1 = __raw_readl(bank->base +
-                                       OMAP24XX_GPIO_LEVELDETECT1);
-                               __raw_writel(old0 | gen, bank->base +
-                                       OMAP24XX_GPIO_LEVELDETECT0);
-                               __raw_writel(old1 | gen, bank->base +
-                                       OMAP24XX_GPIO_LEVELDETECT1);
-                               __raw_writel(old0, bank->base +
-                                       OMAP24XX_GPIO_LEVELDETECT0);
-                               __raw_writel(old1, bank->base +
-                                       OMAP24XX_GPIO_LEVELDETECT1);
-                       }
-
-                       if (cpu_is_omap44xx()) {
-                               old0 = __raw_readl(bank->base +
-                                               OMAP4_GPIO_LEVELDETECT0);
-                               old1 = __raw_readl(bank->base +
-                                               OMAP4_GPIO_LEVELDETECT1);
-                               __raw_writel(old0 | l, bank->base +
-                                               OMAP4_GPIO_LEVELDETECT0);
-                               __raw_writel(old1 | l, bank->base +
-                                               OMAP4_GPIO_LEVELDETECT1);
-                               __raw_writel(old0, bank->base +
-                                               OMAP4_GPIO_LEVELDETECT0);
-                               __raw_writel(old1, bank->base +
-                                               OMAP4_GPIO_LEVELDETECT1);
-                       }
-               }
-       }
-
-}
-
-#endif
-
-#ifdef CONFIG_ARCH_OMAP3
-/* save the registers of bank 2-6 */
-void omap_gpio_save_context(void)
-{
-       int i;
-
-       /* saving banks from 2-6 only since GPIO1 is in WKUP */
-       for (i = 1; i < gpio_bank_count; i++) {
-               struct gpio_bank *bank = &gpio_bank[i];
-               gpio_context[i].irqenable1 =
-                       __raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE1);
-               gpio_context[i].irqenable2 =
-                       __raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE2);
-               gpio_context[i].wake_en =
-                       __raw_readl(bank->base + OMAP24XX_GPIO_WAKE_EN);
-               gpio_context[i].ctrl =
-                       __raw_readl(bank->base + OMAP24XX_GPIO_CTRL);
-               gpio_context[i].oe =
-                       __raw_readl(bank->base + OMAP24XX_GPIO_OE);
-               gpio_context[i].leveldetect0 =
-                       __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0);
-               gpio_context[i].leveldetect1 =
-                       __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1);
-               gpio_context[i].risingdetect =
-                       __raw_readl(bank->base + OMAP24XX_GPIO_RISINGDETECT);
-               gpio_context[i].fallingdetect =
-                       __raw_readl(bank->base + OMAP24XX_GPIO_FALLINGDETECT);
-               gpio_context[i].dataout =
-                       __raw_readl(bank->base + OMAP24XX_GPIO_DATAOUT);
-       }
-}
-
-/* restore the required registers of bank 2-6 */
-void omap_gpio_restore_context(void)
-{
-       int i;
-
-       for (i = 1; i < gpio_bank_count; i++) {
-               struct gpio_bank *bank = &gpio_bank[i];
-               __raw_writel(gpio_context[i].irqenable1,
-                               bank->base + OMAP24XX_GPIO_IRQENABLE1);
-               __raw_writel(gpio_context[i].irqenable2,
-                               bank->base + OMAP24XX_GPIO_IRQENABLE2);
-               __raw_writel(gpio_context[i].wake_en,
-                               bank->base + OMAP24XX_GPIO_WAKE_EN);
-               __raw_writel(gpio_context[i].ctrl,
-                               bank->base + OMAP24XX_GPIO_CTRL);
-               __raw_writel(gpio_context[i].oe,
-                               bank->base + OMAP24XX_GPIO_OE);
-               __raw_writel(gpio_context[i].leveldetect0,
-                               bank->base + OMAP24XX_GPIO_LEVELDETECT0);
-               __raw_writel(gpio_context[i].leveldetect1,
-                               bank->base + OMAP24XX_GPIO_LEVELDETECT1);
-               __raw_writel(gpio_context[i].risingdetect,
-                               bank->base + OMAP24XX_GPIO_RISINGDETECT);
-               __raw_writel(gpio_context[i].fallingdetect,
-                               bank->base + OMAP24XX_GPIO_FALLINGDETECT);
-               __raw_writel(gpio_context[i].dataout,
-                               bank->base + OMAP24XX_GPIO_DATAOUT);
-       }
-}
-#endif
-
-static struct platform_driver omap_gpio_driver = {
-       .probe          = omap_gpio_probe,
-       .driver         = {
-               .name   = "omap_gpio",
-       },
-};
-
-/*
- * gpio driver register needs to be done before
- * machine_init functions access gpio APIs.
- * Hence omap_gpio_drv_reg() is a postcore_initcall.
- */
-static int __init omap_gpio_drv_reg(void)
-{
-       return platform_driver_register(&omap_gpio_driver);
-}
-postcore_initcall(omap_gpio_drv_reg);
-
-static int __init omap_gpio_sysinit(void)
-{
-       mpuio_init();
-
-#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS)
-       if (cpu_is_omap16xx() || cpu_class_is_omap2())
-               register_syscore_ops(&omap_gpio_syscore_ops);
-#endif
-
-       return 0;
-}
-
-arch_initcall(omap_gpio_sysinit);
index cac2e8ac696821f3c3d30304f41796a8a58dfd47..ec97e00cb5810a7709eecd679a324bdda4ae41c8 100644 (file)
 
 #define OMAP34XX_NR_GPIOS              6
 
+/*
+ * OMAP1510 GPIO registers
+ */
+#define OMAP1510_GPIO_DATA_INPUT       0x00
+#define OMAP1510_GPIO_DATA_OUTPUT      0x04
+#define OMAP1510_GPIO_DIR_CONTROL      0x08
+#define OMAP1510_GPIO_INT_CONTROL      0x0c
+#define OMAP1510_GPIO_INT_MASK         0x10
+#define OMAP1510_GPIO_INT_STATUS       0x14
+#define OMAP1510_GPIO_PIN_CONTROL      0x18
+
+#define OMAP1510_IH_GPIO_BASE          64
+
+/*
+ * OMAP1610 specific GPIO registers
+ */
+#define OMAP1610_GPIO_REVISION         0x0000
+#define OMAP1610_GPIO_SYSCONFIG                0x0010
+#define OMAP1610_GPIO_SYSSTATUS                0x0014
+#define OMAP1610_GPIO_IRQSTATUS1       0x0018
+#define OMAP1610_GPIO_IRQENABLE1       0x001c
+#define OMAP1610_GPIO_WAKEUPENABLE     0x0028
+#define OMAP1610_GPIO_DATAIN           0x002c
+#define OMAP1610_GPIO_DATAOUT          0x0030
+#define OMAP1610_GPIO_DIRECTION                0x0034
+#define OMAP1610_GPIO_EDGE_CTRL1       0x0038
+#define OMAP1610_GPIO_EDGE_CTRL2       0x003c
+#define OMAP1610_GPIO_CLEAR_IRQENABLE1 0x009c
+#define OMAP1610_GPIO_CLEAR_WAKEUPENA  0x00a8
+#define OMAP1610_GPIO_CLEAR_DATAOUT    0x00b0
+#define OMAP1610_GPIO_SET_IRQENABLE1   0x00dc
+#define OMAP1610_GPIO_SET_WAKEUPENA    0x00e8
+#define OMAP1610_GPIO_SET_DATAOUT      0x00f0
+
+/*
+ * OMAP7XX specific GPIO registers
+ */
+#define OMAP7XX_GPIO_DATA_INPUT                0x00
+#define OMAP7XX_GPIO_DATA_OUTPUT       0x04
+#define OMAP7XX_GPIO_DIR_CONTROL       0x08
+#define OMAP7XX_GPIO_INT_CONTROL       0x0c
+#define OMAP7XX_GPIO_INT_MASK          0x10
+#define OMAP7XX_GPIO_INT_STATUS                0x14
+
+/*
+ * omap2+ specific GPIO registers
+ */
+#define OMAP24XX_GPIO_REVISION         0x0000
+#define OMAP24XX_GPIO_IRQSTATUS1       0x0018
+#define OMAP24XX_GPIO_IRQSTATUS2       0x0028
+#define OMAP24XX_GPIO_IRQENABLE2       0x002c
+#define OMAP24XX_GPIO_IRQENABLE1       0x001c
+#define OMAP24XX_GPIO_WAKE_EN          0x0020
+#define OMAP24XX_GPIO_CTRL             0x0030
+#define OMAP24XX_GPIO_OE               0x0034
+#define OMAP24XX_GPIO_DATAIN           0x0038
+#define OMAP24XX_GPIO_DATAOUT          0x003c
+#define OMAP24XX_GPIO_LEVELDETECT0     0x0040
+#define OMAP24XX_GPIO_LEVELDETECT1     0x0044
+#define OMAP24XX_GPIO_RISINGDETECT     0x0048
+#define OMAP24XX_GPIO_FALLINGDETECT    0x004c
+#define OMAP24XX_GPIO_DEBOUNCE_EN      0x0050
+#define OMAP24XX_GPIO_DEBOUNCE_VAL     0x0054
+#define OMAP24XX_GPIO_CLEARIRQENABLE1  0x0060
+#define OMAP24XX_GPIO_SETIRQENABLE1    0x0064
+#define OMAP24XX_GPIO_CLEARWKUENA      0x0080
+#define OMAP24XX_GPIO_SETWKUENA                0x0084
+#define OMAP24XX_GPIO_CLEARDATAOUT     0x0090
+#define OMAP24XX_GPIO_SETDATAOUT       0x0094
+
+#define OMAP4_GPIO_REVISION            0x0000
+#define OMAP4_GPIO_EOI                 0x0020
+#define OMAP4_GPIO_IRQSTATUSRAW0       0x0024
+#define OMAP4_GPIO_IRQSTATUSRAW1       0x0028
+#define OMAP4_GPIO_IRQSTATUS0          0x002c
+#define OMAP4_GPIO_IRQSTATUS1          0x0030
+#define OMAP4_GPIO_IRQSTATUSSET0       0x0034
+#define OMAP4_GPIO_IRQSTATUSSET1       0x0038
+#define OMAP4_GPIO_IRQSTATUSCLR0       0x003c
+#define OMAP4_GPIO_IRQSTATUSCLR1       0x0040
+#define OMAP4_GPIO_IRQWAKEN0           0x0044
+#define OMAP4_GPIO_IRQWAKEN1           0x0048
+#define OMAP4_GPIO_IRQENABLE1          0x011c
+#define OMAP4_GPIO_WAKE_EN             0x0120
+#define OMAP4_GPIO_IRQSTATUS2          0x0128
+#define OMAP4_GPIO_IRQENABLE2          0x012c
+#define OMAP4_GPIO_CTRL                        0x0130
+#define OMAP4_GPIO_OE                  0x0134
+#define OMAP4_GPIO_DATAIN              0x0138
+#define OMAP4_GPIO_DATAOUT             0x013c
+#define OMAP4_GPIO_LEVELDETECT0                0x0140
+#define OMAP4_GPIO_LEVELDETECT1                0x0144
+#define OMAP4_GPIO_RISINGDETECT                0x0148
+#define OMAP4_GPIO_FALLINGDETECT       0x014c
+#define OMAP4_GPIO_DEBOUNCENABLE       0x0150
+#define OMAP4_GPIO_DEBOUNCINGTIME      0x0154
+#define OMAP4_GPIO_CLEARIRQENABLE1     0x0160
+#define OMAP4_GPIO_SETIRQENABLE1       0x0164
+#define OMAP4_GPIO_CLEARWKUENA         0x0180
+#define OMAP4_GPIO_SETWKUENA           0x0184
+#define OMAP4_GPIO_CLEARDATAOUT                0x0190
+#define OMAP4_GPIO_SETDATAOUT          0x0194
+
 #define OMAP_MPUIO(nr)         (OMAP_MAX_GPIO_LINES + (nr))
 #define OMAP_GPIO_IS_MPUIO(nr) ((nr) >= OMAP_MAX_GPIO_LINES)
 
index e9de58a2e2944eddba6a1b4df0fe27ee7684d825..53eb15b0a07d6efe6d1c26eb01d7c306eaff6f07 100644 (file)
@@ -19,7 +19,6 @@ obj-y                         += gpio.o
 obj-y                          += gpio-config.o
 obj-y                          += dev-asocdma.o
 
-obj-$(CONFIG_SAMSUNG_GPIOLIB_4BIT)     += gpiolib.o
 obj-$(CONFIG_SAMSUNG_CLKSRC)   += clock-clksrc.o
 
 obj-$(CONFIG_SAMSUNG_IRQ_UART) += irq-uart.o
diff --git a/arch/arm/plat-samsung/gpiolib.c b/arch/arm/plat-samsung/gpiolib.c
deleted file mode 100644 (file)
index ea37c04..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-/* arch/arm/plat-samsung/gpiolib.c
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * SAMSUNG - GPIOlib support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-
-#ifndef DEBUG_GPIO
-#define gpio_dbg(x...) do { } while (0)
-#else
-#define gpio_dbg(x...) printk(KERN_DEBUG x)
-#endif
-
-/* The samsung_gpiolib_4bit routines are to control the gpio banks where
- * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
- * following example:
- *
- * base + 0x00: Control register, 4 bits per gpio
- *             gpio n: 4 bits starting at (4*n)
- *             0000 = input, 0001 = output, others mean special-function
- * base + 0x04: Data register, 1 bit per gpio
- *             bit n: data bit n
- *
- * Note, since the data register is one bit per gpio and is at base + 0x4
- * we can use s3c_gpiolib_get and s3c_gpiolib_set to change the state of
- * the output.
-*/
-
-static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
-                                     unsigned int offset)
-{
-       struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-       void __iomem *base = ourchip->base;
-       unsigned long con;
-
-       con = __raw_readl(base + GPIOCON_OFF);
-       con &= ~(0xf << con_4bit_shift(offset));
-       __raw_writel(con, base + GPIOCON_OFF);
-
-       gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con);
-
-       return 0;
-}
-
-static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
-                                      unsigned int offset, int value)
-{
-       struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-       void __iomem *base = ourchip->base;
-       unsigned long con;
-       unsigned long dat;
-
-       con = __raw_readl(base + GPIOCON_OFF);
-       con &= ~(0xf << con_4bit_shift(offset));
-       con |= 0x1 << con_4bit_shift(offset);
-
-       dat = __raw_readl(base + GPIODAT_OFF);
-
-       if (value)
-               dat |= 1 << offset;
-       else
-               dat &= ~(1 << offset);
-
-       __raw_writel(dat, base + GPIODAT_OFF);
-       __raw_writel(con, base + GPIOCON_OFF);
-       __raw_writel(dat, base + GPIODAT_OFF);
-
-       gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
-
-       return 0;
-}
-
-/* The next set of routines are for the case where the GPIO configuration
- * registers are 4 bits per GPIO but there is more than one register (the
- * bank has more than 8 GPIOs.
- *
- * This case is the similar to the 4 bit case, but the registers are as
- * follows:
- *
- * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
- *             gpio n: 4 bits starting at (4*n)
- *             0000 = input, 0001 = output, others mean special-function
- * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
- *             gpio n: 4 bits starting at (4*n)
- *             0000 = input, 0001 = output, others mean special-function
- * base + 0x08: Data register, 1 bit per gpio
- *             bit n: data bit n
- *
- * To allow us to use the s3c_gpiolib_get and s3c_gpiolib_set routines we
- * store the 'base + 0x4' address so that these routines see the data
- * register at ourchip->base + 0x04.
- */
-
-static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
-                                      unsigned int offset)
-{
-       struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-       void __iomem *base = ourchip->base;
-       void __iomem *regcon = base;
-       unsigned long con;
-
-       if (offset > 7)
-               offset -= 8;
-       else
-               regcon -= 4;
-
-       con = __raw_readl(regcon);
-       con &= ~(0xf << con_4bit_shift(offset));
-       __raw_writel(con, regcon);
-
-       gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con);
-
-       return 0;
-}
-
-static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
-                                       unsigned int offset, int value)
-{
-       struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
-       void __iomem *base = ourchip->base;
-       void __iomem *regcon = base;
-       unsigned long con;
-       unsigned long dat;
-       unsigned con_offset = offset;
-
-       if (con_offset > 7)
-               con_offset -= 8;
-       else
-               regcon -= 4;
-
-       con = __raw_readl(regcon);
-       con &= ~(0xf << con_4bit_shift(con_offset));
-       con |= 0x1 << con_4bit_shift(con_offset);
-
-       dat = __raw_readl(base + GPIODAT_OFF);
-
-       if (value)
-               dat |= 1 << offset;
-       else
-               dat &= ~(1 << offset);
-
-       __raw_writel(dat, base + GPIODAT_OFF);
-       __raw_writel(con, regcon);
-       __raw_writel(dat, base + GPIODAT_OFF);
-
-       gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
-
-       return 0;
-}
-
-void __init samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip)
-{
-       chip->chip.direction_input = samsung_gpiolib_4bit_input;
-       chip->chip.direction_output = samsung_gpiolib_4bit_output;
-       chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
-}
-
-void __init samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip)
-{
-       chip->chip.direction_input = samsung_gpiolib_4bit2_input;
-       chip->chip.direction_output = samsung_gpiolib_4bit2_output;
-       chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
-}
-
-void __init samsung_gpiolib_add_4bit_chips(struct s3c_gpio_chip *chip,
-                                          int nr_chips)
-{
-       for (; nr_chips > 0; nr_chips--, chip++) {
-               samsung_gpiolib_add_4bit(chip);
-               s3c_gpiolib_add(chip);
-       }
-}
-
-void __init samsung_gpiolib_add_4bit2_chips(struct s3c_gpio_chip *chip,
-                                           int nr_chips)
-{
-       for (; nr_chips > 0; nr_chips--, chip++) {
-               samsung_gpiolib_add_4bit2(chip);
-               s3c_gpiolib_add(chip);
-       }
-}
-
-void __init samsung_gpiolib_add_2bit_chips(struct s3c_gpio_chip *chip,
-                                          int nr_chips)
-{
-       for (; nr_chips > 0; nr_chips--, chip++)
-               s3c_gpiolib_add(chip);
-}
index d213646037553cabba73180bc4beb1b6d6d68440..592397629ddc9c211403d5c04369b2ea9fc37ee7 100644 (file)
@@ -86,6 +86,30 @@ config GPIO_IT8761E
        help
          Say yes here to support GPIO functionality of IT8761E super I/O chip.
 
+config GPIO_EXYNOS4
+       bool "Samsung Exynos4 GPIO library support"
+       default y if CPU_EXYNOS4210
+       help
+         Say yes here to support Samsung Exynos4 series SoCs GPIO library
+
+config GPIO_PLAT_SAMSUNG
+       bool "Samsung SoCs GPIO library support"
+       default y if SAMSUNG_GPIOLIB_4BIT
+       help
+         Say yes here to support Samsung SoCs GPIO library
+
+config GPIO_S5PC100
+       bool "Samsung S5PC100 GPIO library support"
+       default y if CPU_S5PC100
+       help
+         Say yes here to support Samsung S5PC100 SoCs GPIO library
+
+config GPIO_S5PV210
+       bool "Samsung S5PV210/S5PC110 GPIO library support"
+       default y if CPU_S5PV210
+       help
+         Say yes here to support Samsung S5PV210/S5PC110 SoCs GPIO library
+
 config GPIO_PL061
        bool "PrimeCell PL061 GPIO support"
        depends on ARM_AMBA
@@ -303,7 +327,7 @@ comment "PCI GPIO expanders:"
 
 config GPIO_CS5535
        tristate "AMD CS5535/CS5536 GPIO support"
-       depends on PCI && X86 && !CS5535_GPIO
+       depends on PCI && X86 && !CS5535_GPIO && MFD_CS5535
        help
          The AMD CS5535 and CS5536 southbridges support 28 GPIO pins that
          can be used for quite a number of things.  The CS5535/6 is found on
@@ -334,13 +358,19 @@ config GPIO_LANGWELL
          Say Y here to support Intel Langwell/Penwell GPIO.
 
 config GPIO_PCH
-       tristate "PCH GPIO of Intel Topcliff"
+       tristate "Intel EG20T PCH / OKI SEMICONDUCTOR ML7223 IOH GPIO"
        depends on PCI && X86
        help
          This driver is for PCH(Platform controller Hub) GPIO of Intel Topcliff
          which is an IOH(Input/Output Hub) for x86 embedded processor.
          This driver can access PCH GPIO device.
 
+         This driver also can be used for OKI SEMICONDUCTOR IOH(Input/
+         Output Hub), ML7223.
+         ML7223 IOH is for MP(Media Phone) use.
+         ML7223 is companion chip for Intel Atom E6xx series.
+         ML7223 is completely compatible for Intel EG20T PCH.
+
 config GPIO_ML_IOH
        tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support"
        depends on PCI
index 6a3387acc0e5d71b8daae00da808f271bca6ed3f..b605f8ec6fbe0afc01e6c4604de67e6a85f98add 100644 (file)
@@ -8,6 +8,10 @@ obj-$(CONFIG_GPIO_ADP5520)     += adp5520-gpio.o
 obj-$(CONFIG_GPIO_ADP5588)     += adp5588-gpio.o
 obj-$(CONFIG_GPIO_BASIC_MMIO_CORE)     += basic_mmio_gpio.o
 obj-$(CONFIG_GPIO_BASIC_MMIO)  += basic_mmio_gpio.o
+obj-$(CONFIG_GPIO_EXYNOS4)     += gpio-exynos4.o
+obj-$(CONFIG_GPIO_PLAT_SAMSUNG)        += gpio-plat-samsung.o
+obj-$(CONFIG_GPIO_S5PC100)     += gpio-s5pc100.o
+obj-$(CONFIG_GPIO_S5PV210)     += gpio-s5pv210.o
 obj-$(CONFIG_GPIO_LANGWELL)    += langwell_gpio.o
 obj-$(CONFIG_GPIO_MAX730X)     += max730x.o
 obj-$(CONFIG_GPIO_MAX7300)     += max7300.o
@@ -16,6 +20,7 @@ obj-$(CONFIG_GPIO_MAX732X)    += max732x.o
 obj-$(CONFIG_GPIO_MC33880)     += mc33880.o
 obj-$(CONFIG_GPIO_MCP23S08)    += mcp23s08.o
 obj-$(CONFIG_GPIO_74X164)      += 74x164.o
+obj-$(CONFIG_ARCH_OMAP)         += gpio-omap.o
 obj-$(CONFIG_GPIO_PCA953X)     += pca953x.o
 obj-$(CONFIG_GPIO_PCF857X)     += pcf857x.o
 obj-$(CONFIG_GPIO_PCH)         += pch_gpio.o
@@ -34,6 +39,8 @@ obj-$(CONFIG_GPIO_WM831X)     += wm831x-gpio.o
 obj-$(CONFIG_GPIO_WM8350)      += wm8350-gpiolib.o
 obj-$(CONFIG_GPIO_WM8994)      += wm8994-gpio.o
 obj-$(CONFIG_GPIO_SCH)         += sch_gpio.o
+obj-$(CONFIG_MACH_U300)                += gpio-u300.o
+obj-$(CONFIG_PLAT_NOMADIK)     += gpio-nomadik.o
 obj-$(CONFIG_GPIO_RDC321X)     += rdc321x-gpio.o
 obj-$(CONFIG_GPIO_JANZ_TTL)    += janz-ttl.o
 obj-$(CONFIG_GPIO_SX150X)      += sx150x.o
diff --git a/drivers/gpio/gpio-exynos4.c b/drivers/gpio/gpio-exynos4.c
new file mode 100644 (file)
index 0000000..d54ca6a
--- /dev/null
@@ -0,0 +1,365 @@
+/* linux/arch/arm/mach-exynos4/gpiolib.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * EXYNOS4 - GPIOlib support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+
+#include <mach/map.h>
+
+#include <plat/gpio-core.h>
+#include <plat/gpio-cfg.h>
+#include <plat/gpio-cfg-helpers.h>
+
+static struct s3c_gpio_cfg gpio_cfg = {
+       .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
+       .set_pull       = s3c_gpio_setpull_updown,
+       .get_pull       = s3c_gpio_getpull_updown,
+};
+
+static struct s3c_gpio_cfg gpio_cfg_noint = {
+       .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
+       .set_pull       = s3c_gpio_setpull_updown,
+       .get_pull       = s3c_gpio_getpull_updown,
+};
+
+/*
+ * Following are the gpio banks in v310.
+ *
+ * The 'config' member when left to NULL, is initialized to the default
+ * structure gpio_cfg in the init function below.
+ *
+ * The 'base' member is also initialized in the init function below.
+ * Note: The initialization of 'base' member of s3c_gpio_chip structure
+ * uses the above macro and depends on the banks being listed in order here.
+ */
+static struct s3c_gpio_chip exynos4_gpio_part1_4bit[] = {
+       {
+               .chip   = {
+                       .base   = EXYNOS4_GPA0(0),
+                       .ngpio  = EXYNOS4_GPIO_A0_NR,
+                       .label  = "GPA0",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPA1(0),
+                       .ngpio  = EXYNOS4_GPIO_A1_NR,
+                       .label  = "GPA1",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPB(0),
+                       .ngpio  = EXYNOS4_GPIO_B_NR,
+                       .label  = "GPB",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPC0(0),
+                       .ngpio  = EXYNOS4_GPIO_C0_NR,
+                       .label  = "GPC0",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPC1(0),
+                       .ngpio  = EXYNOS4_GPIO_C1_NR,
+                       .label  = "GPC1",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPD0(0),
+                       .ngpio  = EXYNOS4_GPIO_D0_NR,
+                       .label  = "GPD0",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPD1(0),
+                       .ngpio  = EXYNOS4_GPIO_D1_NR,
+                       .label  = "GPD1",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPE0(0),
+                       .ngpio  = EXYNOS4_GPIO_E0_NR,
+                       .label  = "GPE0",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPE1(0),
+                       .ngpio  = EXYNOS4_GPIO_E1_NR,
+                       .label  = "GPE1",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPE2(0),
+                       .ngpio  = EXYNOS4_GPIO_E2_NR,
+                       .label  = "GPE2",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPE3(0),
+                       .ngpio  = EXYNOS4_GPIO_E3_NR,
+                       .label  = "GPE3",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPE4(0),
+                       .ngpio  = EXYNOS4_GPIO_E4_NR,
+                       .label  = "GPE4",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPF0(0),
+                       .ngpio  = EXYNOS4_GPIO_F0_NR,
+                       .label  = "GPF0",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPF1(0),
+                       .ngpio  = EXYNOS4_GPIO_F1_NR,
+                       .label  = "GPF1",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPF2(0),
+                       .ngpio  = EXYNOS4_GPIO_F2_NR,
+                       .label  = "GPF2",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPF3(0),
+                       .ngpio  = EXYNOS4_GPIO_F3_NR,
+                       .label  = "GPF3",
+               },
+       },
+};
+
+static struct s3c_gpio_chip exynos4_gpio_part2_4bit[] = {
+       {
+               .chip   = {
+                       .base   = EXYNOS4_GPJ0(0),
+                       .ngpio  = EXYNOS4_GPIO_J0_NR,
+                       .label  = "GPJ0",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPJ1(0),
+                       .ngpio  = EXYNOS4_GPIO_J1_NR,
+                       .label  = "GPJ1",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPK0(0),
+                       .ngpio  = EXYNOS4_GPIO_K0_NR,
+                       .label  = "GPK0",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPK1(0),
+                       .ngpio  = EXYNOS4_GPIO_K1_NR,
+                       .label  = "GPK1",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPK2(0),
+                       .ngpio  = EXYNOS4_GPIO_K2_NR,
+                       .label  = "GPK2",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPK3(0),
+                       .ngpio  = EXYNOS4_GPIO_K3_NR,
+                       .label  = "GPK3",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPL0(0),
+                       .ngpio  = EXYNOS4_GPIO_L0_NR,
+                       .label  = "GPL0",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPL1(0),
+                       .ngpio  = EXYNOS4_GPIO_L1_NR,
+                       .label  = "GPL1",
+               },
+       }, {
+               .chip   = {
+                       .base   = EXYNOS4_GPL2(0),
+                       .ngpio  = EXYNOS4_GPIO_L2_NR,
+                       .label  = "GPL2",
+               },
+       }, {
+               .config = &gpio_cfg_noint,
+               .chip   = {
+                       .base   = EXYNOS4_GPY0(0),
+                       .ngpio  = EXYNOS4_GPIO_Y0_NR,
+                       .label  = "GPY0",
+               },
+       }, {
+               .config = &gpio_cfg_noint,
+               .chip   = {
+                       .base   = EXYNOS4_GPY1(0),
+                       .ngpio  = EXYNOS4_GPIO_Y1_NR,
+                       .label  = "GPY1",
+               },
+       }, {
+               .config = &gpio_cfg_noint,
+               .chip   = {
+                       .base   = EXYNOS4_GPY2(0),
+                       .ngpio  = EXYNOS4_GPIO_Y2_NR,
+                       .label  = "GPY2",
+               },
+       }, {
+               .config = &gpio_cfg_noint,
+               .chip   = {
+                       .base   = EXYNOS4_GPY3(0),
+                       .ngpio  = EXYNOS4_GPIO_Y3_NR,
+                       .label  = "GPY3",
+               },
+       }, {
+               .config = &gpio_cfg_noint,
+               .chip   = {
+                       .base   = EXYNOS4_GPY4(0),
+                       .ngpio  = EXYNOS4_GPIO_Y4_NR,
+                       .label  = "GPY4",
+               },
+       }, {
+               .config = &gpio_cfg_noint,
+               .chip   = {
+                       .base   = EXYNOS4_GPY5(0),
+                       .ngpio  = EXYNOS4_GPIO_Y5_NR,
+                       .label  = "GPY5",
+               },
+       }, {
+               .config = &gpio_cfg_noint,
+               .chip   = {
+                       .base   = EXYNOS4_GPY6(0),
+                       .ngpio  = EXYNOS4_GPIO_Y6_NR,
+                       .label  = "GPY6",
+               },
+       }, {
+               .base   = (S5P_VA_GPIO2 + 0xC00),
+               .config = &gpio_cfg_noint,
+               .irq_base = IRQ_EINT(0),
+               .chip   = {
+                       .base   = EXYNOS4_GPX0(0),
+                       .ngpio  = EXYNOS4_GPIO_X0_NR,
+                       .label  = "GPX0",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       }, {
+               .base   = (S5P_VA_GPIO2 + 0xC20),
+               .config = &gpio_cfg_noint,
+               .irq_base = IRQ_EINT(8),
+               .chip   = {
+                       .base   = EXYNOS4_GPX1(0),
+                       .ngpio  = EXYNOS4_GPIO_X1_NR,
+                       .label  = "GPX1",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       }, {
+               .base   = (S5P_VA_GPIO2 + 0xC40),
+               .config = &gpio_cfg_noint,
+               .irq_base = IRQ_EINT(16),
+               .chip   = {
+                       .base   = EXYNOS4_GPX2(0),
+                       .ngpio  = EXYNOS4_GPIO_X2_NR,
+                       .label  = "GPX2",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       }, {
+               .base   = (S5P_VA_GPIO2 + 0xC60),
+               .config = &gpio_cfg_noint,
+               .irq_base = IRQ_EINT(24),
+               .chip   = {
+                       .base   = EXYNOS4_GPX3(0),
+                       .ngpio  = EXYNOS4_GPIO_X3_NR,
+                       .label  = "GPX3",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       },
+};
+
+static struct s3c_gpio_chip exynos4_gpio_part3_4bit[] = {
+       {
+               .chip   = {
+                       .base   = EXYNOS4_GPZ(0),
+                       .ngpio  = EXYNOS4_GPIO_Z_NR,
+                       .label  = "GPZ",
+               },
+       },
+};
+
+static __init int exynos4_gpiolib_init(void)
+{
+       struct s3c_gpio_chip *chip;
+       int i;
+       int group = 0;
+       int nr_chips;
+
+       /* GPIO part 1 */
+
+       chip = exynos4_gpio_part1_4bit;
+       nr_chips = ARRAY_SIZE(exynos4_gpio_part1_4bit);
+
+       for (i = 0; i < nr_chips; i++, chip++) {
+               if (chip->config == NULL) {
+                       chip->config = &gpio_cfg;
+                       /* Assign the GPIO interrupt group */
+                       chip->group = group++;
+               }
+               if (chip->base == NULL)
+                       chip->base = S5P_VA_GPIO1 + (i) * 0x20;
+       }
+
+       samsung_gpiolib_add_4bit_chips(exynos4_gpio_part1_4bit, nr_chips);
+
+       /* GPIO part 2 */
+
+       chip = exynos4_gpio_part2_4bit;
+       nr_chips = ARRAY_SIZE(exynos4_gpio_part2_4bit);
+
+       for (i = 0; i < nr_chips; i++, chip++) {
+               if (chip->config == NULL) {
+                       chip->config = &gpio_cfg;
+                       /* Assign the GPIO interrupt group */
+                       chip->group = group++;
+               }
+               if (chip->base == NULL)
+                       chip->base = S5P_VA_GPIO2 + (i) * 0x20;
+       }
+
+       samsung_gpiolib_add_4bit_chips(exynos4_gpio_part2_4bit, nr_chips);
+
+       /* GPIO part 3 */
+
+       chip = exynos4_gpio_part3_4bit;
+       nr_chips = ARRAY_SIZE(exynos4_gpio_part3_4bit);
+
+       for (i = 0; i < nr_chips; i++, chip++) {
+               if (chip->config == NULL) {
+                       chip->config = &gpio_cfg;
+                       /* Assign the GPIO interrupt group */
+                       chip->group = group++;
+               }
+               if (chip->base == NULL)
+                       chip->base = S5P_VA_GPIO3 + (i) * 0x20;
+       }
+
+       samsung_gpiolib_add_4bit_chips(exynos4_gpio_part3_4bit, nr_chips);
+       s5p_register_gpioint_bank(IRQ_GPIO_XA, 0, IRQ_GPIO1_NR_GROUPS);
+       s5p_register_gpioint_bank(IRQ_GPIO_XB, IRQ_GPIO1_NR_GROUPS, IRQ_GPIO2_NR_GROUPS);
+
+       return 0;
+}
+core_initcall(exynos4_gpiolib_init);
diff --git a/drivers/gpio/gpio-nomadik.c b/drivers/gpio/gpio-nomadik.c
new file mode 100644 (file)
index 0000000..4961ef9
--- /dev/null
@@ -0,0 +1,1069 @@
+/*
+ * Generic GPIO driver for logic cells found in the Nomadik SoC
+ *
+ * Copyright (C) 2008,2009 STMicroelectronics
+ * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it>
+ *   Rewritten based on work by Prafulla WADASKAR <prafulla.wadaskar@st.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+
+#include <asm/mach/irq.h>
+
+#include <plat/pincfg.h>
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+
+/*
+ * The GPIO module in the Nomadik family of Systems-on-Chip is an
+ * AMBA device, managing 32 pins and alternate functions.  The logic block
+ * is currently used in the Nomadik and ux500.
+ *
+ * Symbols in this file are called "nmk_gpio" for "nomadik gpio"
+ */
+
+#define NMK_GPIO_PER_CHIP      32
+
+struct nmk_gpio_chip {
+       struct gpio_chip chip;
+       void __iomem *addr;
+       struct clk *clk;
+       unsigned int bank;
+       unsigned int parent_irq;
+       int secondary_parent_irq;
+       u32 (*get_secondary_status)(unsigned int bank);
+       void (*set_ioforce)(bool enable);
+       spinlock_t lock;
+       /* Keep track of configured edges */
+       u32 edge_rising;
+       u32 edge_falling;
+       u32 real_wake;
+       u32 rwimsc;
+       u32 fwimsc;
+       u32 slpm;
+       u32 enabled;
+       u32 pull_up;
+};
+
+static struct nmk_gpio_chip *
+nmk_gpio_chips[DIV_ROUND_UP(ARCH_NR_GPIOS, NMK_GPIO_PER_CHIP)];
+
+static DEFINE_SPINLOCK(nmk_gpio_slpm_lock);
+
+#define NUM_BANKS ARRAY_SIZE(nmk_gpio_chips)
+
+static void __nmk_gpio_set_mode(struct nmk_gpio_chip *nmk_chip,
+                               unsigned offset, int gpio_mode)
+{
+       u32 bit = 1 << offset;
+       u32 afunc, bfunc;
+
+       afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & ~bit;
+       bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & ~bit;
+       if (gpio_mode & NMK_GPIO_ALT_A)
+               afunc |= bit;
+       if (gpio_mode & NMK_GPIO_ALT_B)
+               bfunc |= bit;
+       writel(afunc, nmk_chip->addr + NMK_GPIO_AFSLA);
+       writel(bfunc, nmk_chip->addr + NMK_GPIO_AFSLB);
+}
+
+static void __nmk_gpio_set_slpm(struct nmk_gpio_chip *nmk_chip,
+                               unsigned offset, enum nmk_gpio_slpm mode)
+{
+       u32 bit = 1 << offset;
+       u32 slpm;
+
+       slpm = readl(nmk_chip->addr + NMK_GPIO_SLPC);
+       if (mode == NMK_GPIO_SLPM_NOCHANGE)
+               slpm |= bit;
+       else
+               slpm &= ~bit;
+       writel(slpm, nmk_chip->addr + NMK_GPIO_SLPC);
+}
+
+static void __nmk_gpio_set_pull(struct nmk_gpio_chip *nmk_chip,
+                               unsigned offset, enum nmk_gpio_pull pull)
+{
+       u32 bit = 1 << offset;
+       u32 pdis;
+
+       pdis = readl(nmk_chip->addr + NMK_GPIO_PDIS);
+       if (pull == NMK_GPIO_PULL_NONE) {
+               pdis |= bit;
+               nmk_chip->pull_up &= ~bit;
+       } else {
+               pdis &= ~bit;
+       }
+
+       writel(pdis, nmk_chip->addr + NMK_GPIO_PDIS);
+
+       if (pull == NMK_GPIO_PULL_UP) {
+               nmk_chip->pull_up |= bit;
+               writel(bit, nmk_chip->addr + NMK_GPIO_DATS);
+       } else if (pull == NMK_GPIO_PULL_DOWN) {
+               nmk_chip->pull_up &= ~bit;
+               writel(bit, nmk_chip->addr + NMK_GPIO_DATC);
+       }
+}
+
+static void __nmk_gpio_make_input(struct nmk_gpio_chip *nmk_chip,
+                                 unsigned offset)
+{
+       writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC);
+}
+
+static void __nmk_gpio_set_output(struct nmk_gpio_chip *nmk_chip,
+                                 unsigned offset, int val)
+{
+       if (val)
+               writel(1 << offset, nmk_chip->addr + NMK_GPIO_DATS);
+       else
+               writel(1 << offset, nmk_chip->addr + NMK_GPIO_DATC);
+}
+
+static void __nmk_gpio_make_output(struct nmk_gpio_chip *nmk_chip,
+                                 unsigned offset, int val)
+{
+       writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRS);
+       __nmk_gpio_set_output(nmk_chip, offset, val);
+}
+
+static void __nmk_gpio_set_mode_safe(struct nmk_gpio_chip *nmk_chip,
+                                    unsigned offset, int gpio_mode,
+                                    bool glitch)
+{
+       u32 rwimsc = readl(nmk_chip->addr + NMK_GPIO_RWIMSC);
+       u32 fwimsc = readl(nmk_chip->addr + NMK_GPIO_FWIMSC);
+
+       if (glitch && nmk_chip->set_ioforce) {
+               u32 bit = BIT(offset);
+
+               /* Prevent spurious wakeups */
+               writel(rwimsc & ~bit, nmk_chip->addr + NMK_GPIO_RWIMSC);
+               writel(fwimsc & ~bit, nmk_chip->addr + NMK_GPIO_FWIMSC);
+
+               nmk_chip->set_ioforce(true);
+       }
+
+       __nmk_gpio_set_mode(nmk_chip, offset, gpio_mode);
+
+       if (glitch && nmk_chip->set_ioforce) {
+               nmk_chip->set_ioforce(false);
+
+               writel(rwimsc, nmk_chip->addr + NMK_GPIO_RWIMSC);
+               writel(fwimsc, nmk_chip->addr + NMK_GPIO_FWIMSC);
+       }
+}
+
+static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
+                            pin_cfg_t cfg, bool sleep, unsigned int *slpmregs)
+{
+       static const char *afnames[] = {
+               [NMK_GPIO_ALT_GPIO]     = "GPIO",
+               [NMK_GPIO_ALT_A]        = "A",
+               [NMK_GPIO_ALT_B]        = "B",
+               [NMK_GPIO_ALT_C]        = "C"
+       };
+       static const char *pullnames[] = {
+               [NMK_GPIO_PULL_NONE]    = "none",
+               [NMK_GPIO_PULL_UP]      = "up",
+               [NMK_GPIO_PULL_DOWN]    = "down",
+               [3] /* illegal */       = "??"
+       };
+       static const char *slpmnames[] = {
+               [NMK_GPIO_SLPM_INPUT]           = "input/wakeup",
+               [NMK_GPIO_SLPM_NOCHANGE]        = "no-change/no-wakeup",
+       };
+
+       int pin = PIN_NUM(cfg);
+       int pull = PIN_PULL(cfg);
+       int af = PIN_ALT(cfg);
+       int slpm = PIN_SLPM(cfg);
+       int output = PIN_DIR(cfg);
+       int val = PIN_VAL(cfg);
+       bool glitch = af == NMK_GPIO_ALT_C;
+
+       dev_dbg(nmk_chip->chip.dev, "pin %d [%#lx]: af %s, pull %s, slpm %s (%s%s)\n",
+               pin, cfg, afnames[af], pullnames[pull], slpmnames[slpm],
+               output ? "output " : "input",
+               output ? (val ? "high" : "low") : "");
+
+       if (sleep) {
+               int slpm_pull = PIN_SLPM_PULL(cfg);
+               int slpm_output = PIN_SLPM_DIR(cfg);
+               int slpm_val = PIN_SLPM_VAL(cfg);
+
+               af = NMK_GPIO_ALT_GPIO;
+
+               /*
+                * The SLPM_* values are normal values + 1 to allow zero to
+                * mean "same as normal".
+                */
+               if (slpm_pull)
+                       pull = slpm_pull - 1;
+               if (slpm_output)
+                       output = slpm_output - 1;
+               if (slpm_val)
+                       val = slpm_val - 1;
+
+               dev_dbg(nmk_chip->chip.dev, "pin %d: sleep pull %s, dir %s, val %s\n",
+                       pin,
+                       slpm_pull ? pullnames[pull] : "same",
+                       slpm_output ? (output ? "output" : "input") : "same",
+                       slpm_val ? (val ? "high" : "low") : "same");
+       }
+
+       if (output)
+               __nmk_gpio_make_output(nmk_chip, offset, val);
+       else {
+               __nmk_gpio_make_input(nmk_chip, offset);
+               __nmk_gpio_set_pull(nmk_chip, offset, pull);
+       }
+
+       /*
+        * If we've backed up the SLPM registers (glitch workaround), modify
+        * the backups since they will be restored.
+        */
+       if (slpmregs) {
+               if (slpm == NMK_GPIO_SLPM_NOCHANGE)
+                       slpmregs[nmk_chip->bank] |= BIT(offset);
+               else
+                       slpmregs[nmk_chip->bank] &= ~BIT(offset);
+       } else
+               __nmk_gpio_set_slpm(nmk_chip, offset, slpm);
+
+       __nmk_gpio_set_mode_safe(nmk_chip, offset, af, glitch);
+}
+
+/*
+ * Safe sequence used to switch IOs between GPIO and Alternate-C mode:
+ *  - Save SLPM registers
+ *  - Set SLPM=0 for the IOs you want to switch and others to 1
+ *  - Configure the GPIO registers for the IOs that are being switched
+ *  - Set IOFORCE=1
+ *  - Modify the AFLSA/B registers for the IOs that are being switched
+ *  - Set IOFORCE=0
+ *  - Restore SLPM registers
+ *  - Any spurious wake up event during switch sequence to be ignored and
+ *    cleared
+ */
+static void nmk_gpio_glitch_slpm_init(unsigned int *slpm)
+{
+       int i;
+
+       for (i = 0; i < NUM_BANKS; i++) {
+               struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
+               unsigned int temp = slpm[i];
+
+               if (!chip)
+                       break;
+
+               slpm[i] = readl(chip->addr + NMK_GPIO_SLPC);
+               writel(temp, chip->addr + NMK_GPIO_SLPC);
+       }
+}
+
+static void nmk_gpio_glitch_slpm_restore(unsigned int *slpm)
+{
+       int i;
+
+       for (i = 0; i < NUM_BANKS; i++) {
+               struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
+
+               if (!chip)
+                       break;
+
+               writel(slpm[i], chip->addr + NMK_GPIO_SLPC);
+       }
+}
+
+static int __nmk_config_pins(pin_cfg_t *cfgs, int num, bool sleep)
+{
+       static unsigned int slpm[NUM_BANKS];
+       unsigned long flags;
+       bool glitch = false;
+       int ret = 0;
+       int i;
+
+       for (i = 0; i < num; i++) {
+               if (PIN_ALT(cfgs[i]) == NMK_GPIO_ALT_C) {
+                       glitch = true;
+                       break;
+               }
+       }
+
+       spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
+
+       if (glitch) {
+               memset(slpm, 0xff, sizeof(slpm));
+
+               for (i = 0; i < num; i++) {
+                       int pin = PIN_NUM(cfgs[i]);
+                       int offset = pin % NMK_GPIO_PER_CHIP;
+
+                       if (PIN_ALT(cfgs[i]) == NMK_GPIO_ALT_C)
+                               slpm[pin / NMK_GPIO_PER_CHIP] &= ~BIT(offset);
+               }
+
+               nmk_gpio_glitch_slpm_init(slpm);
+       }
+
+       for (i = 0; i < num; i++) {
+               struct nmk_gpio_chip *nmk_chip;
+               int pin = PIN_NUM(cfgs[i]);
+
+               nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(pin));
+               if (!nmk_chip) {
+                       ret = -EINVAL;
+                       break;
+               }
+
+               spin_lock(&nmk_chip->lock);
+               __nmk_config_pin(nmk_chip, pin - nmk_chip->chip.base,
+                                cfgs[i], sleep, glitch ? slpm : NULL);
+               spin_unlock(&nmk_chip->lock);
+       }
+
+       if (glitch)
+               nmk_gpio_glitch_slpm_restore(slpm);
+
+       spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
+
+       return ret;
+}
+
+/**
+ * nmk_config_pin - configure a pin's mux attributes
+ * @cfg: pin confguration
+ *
+ * Configures a pin's mode (alternate function or GPIO), its pull up status,
+ * and its sleep mode based on the specified configuration.  The @cfg is
+ * usually one of the SoC specific macros defined in mach/<soc>-pins.h.  These
+ * are constructed using, and can be further enhanced with, the macros in
+ * plat/pincfg.h.
+ *
+ * If a pin's mode is set to GPIO, it is configured as an input to avoid
+ * side-effects.  The gpio can be manipulated later using standard GPIO API
+ * calls.
+ */
+int nmk_config_pin(pin_cfg_t cfg, bool sleep)
+{
+       return __nmk_config_pins(&cfg, 1, sleep);
+}
+EXPORT_SYMBOL(nmk_config_pin);
+
+/**
+ * nmk_config_pins - configure several pins at once
+ * @cfgs: array of pin configurations
+ * @num: number of elments in the array
+ *
+ * Configures several pins using nmk_config_pin().  Refer to that function for
+ * further information.
+ */
+int nmk_config_pins(pin_cfg_t *cfgs, int num)
+{
+       return __nmk_config_pins(cfgs, num, false);
+}
+EXPORT_SYMBOL(nmk_config_pins);
+
+int nmk_config_pins_sleep(pin_cfg_t *cfgs, int num)
+{
+       return __nmk_config_pins(cfgs, num, true);
+}
+EXPORT_SYMBOL(nmk_config_pins_sleep);
+
+/**
+ * nmk_gpio_set_slpm() - configure the sleep mode of a pin
+ * @gpio: pin number
+ * @mode: NMK_GPIO_SLPM_INPUT or NMK_GPIO_SLPM_NOCHANGE,
+ *
+ * Sets the sleep mode of a pin.  If @mode is NMK_GPIO_SLPM_INPUT, the pin is
+ * changed to an input (with pullup/down enabled) in sleep and deep sleep.  If
+ * @mode is NMK_GPIO_SLPM_NOCHANGE, the pin remains in the state it was
+ * configured even when in sleep and deep sleep.
+ *
+ * On DB8500v2 onwards, this setting loses the previous meaning and instead
+ * indicates if wakeup detection is enabled on the pin.  Note that
+ * enable_irq_wake() will automatically enable wakeup detection.
+ */
+int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode)
+{
+       struct nmk_gpio_chip *nmk_chip;
+       unsigned long flags;
+
+       nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
+       if (!nmk_chip)
+               return -EINVAL;
+
+       spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
+       spin_lock(&nmk_chip->lock);
+
+       __nmk_gpio_set_slpm(nmk_chip, gpio - nmk_chip->chip.base, mode);
+
+       spin_unlock(&nmk_chip->lock);
+       spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
+
+       return 0;
+}
+
+/**
+ * nmk_gpio_set_pull() - enable/disable pull up/down on a gpio
+ * @gpio: pin number
+ * @pull: one of NMK_GPIO_PULL_DOWN, NMK_GPIO_PULL_UP, and NMK_GPIO_PULL_NONE
+ *
+ * Enables/disables pull up/down on a specified pin.  This only takes effect if
+ * the pin is configured as an input (either explicitly or by the alternate
+ * function).
+ *
+ * NOTE: If enabling the pull up/down, the caller must ensure that the GPIO is
+ * configured as an input.  Otherwise, due to the way the controller registers
+ * work, this function will change the value output on the pin.
+ */
+int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull)
+{
+       struct nmk_gpio_chip *nmk_chip;
+       unsigned long flags;
+
+       nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
+       if (!nmk_chip)
+               return -EINVAL;
+
+       spin_lock_irqsave(&nmk_chip->lock, flags);
+       __nmk_gpio_set_pull(nmk_chip, gpio - nmk_chip->chip.base, pull);
+       spin_unlock_irqrestore(&nmk_chip->lock, flags);
+
+       return 0;
+}
+
+/* Mode functions */
+/**
+ * nmk_gpio_set_mode() - set the mux mode of a gpio pin
+ * @gpio: pin number
+ * @gpio_mode: one of NMK_GPIO_ALT_GPIO, NMK_GPIO_ALT_A,
+ *            NMK_GPIO_ALT_B, and NMK_GPIO_ALT_C
+ *
+ * Sets the mode of the specified pin to one of the alternate functions or
+ * plain GPIO.
+ */
+int nmk_gpio_set_mode(int gpio, int gpio_mode)
+{
+       struct nmk_gpio_chip *nmk_chip;
+       unsigned long flags;
+
+       nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
+       if (!nmk_chip)
+               return -EINVAL;
+
+       spin_lock_irqsave(&nmk_chip->lock, flags);
+       __nmk_gpio_set_mode(nmk_chip, gpio - nmk_chip->chip.base, gpio_mode);
+       spin_unlock_irqrestore(&nmk_chip->lock, flags);
+
+       return 0;
+}
+EXPORT_SYMBOL(nmk_gpio_set_mode);
+
+int nmk_gpio_get_mode(int gpio)
+{
+       struct nmk_gpio_chip *nmk_chip;
+       u32 afunc, bfunc, bit;
+
+       nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
+       if (!nmk_chip)
+               return -EINVAL;
+
+       bit = 1 << (gpio - nmk_chip->chip.base);
+
+       afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & bit;
+       bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & bit;
+
+       return (afunc ? NMK_GPIO_ALT_A : 0) | (bfunc ? NMK_GPIO_ALT_B : 0);
+}
+EXPORT_SYMBOL(nmk_gpio_get_mode);
+
+
+/* IRQ functions */
+static inline int nmk_gpio_get_bitmask(int gpio)
+{
+       return 1 << (gpio % 32);
+}
+
+static void nmk_gpio_irq_ack(struct irq_data *d)
+{
+       int gpio;
+       struct nmk_gpio_chip *nmk_chip;
+
+       gpio = NOMADIK_IRQ_TO_GPIO(d->irq);
+       nmk_chip = irq_data_get_irq_chip_data(d);
+       if (!nmk_chip)
+               return;
+       writel(nmk_gpio_get_bitmask(gpio), nmk_chip->addr + NMK_GPIO_IC);
+}
+
+enum nmk_gpio_irq_type {
+       NORMAL,
+       WAKE,
+};
+
+static void __nmk_gpio_irq_modify(struct nmk_gpio_chip *nmk_chip,
+                                 int gpio, enum nmk_gpio_irq_type which,
+                                 bool enable)
+{
+       u32 rimsc = which == WAKE ? NMK_GPIO_RWIMSC : NMK_GPIO_RIMSC;
+       u32 fimsc = which == WAKE ? NMK_GPIO_FWIMSC : NMK_GPIO_FIMSC;
+       u32 bitmask = nmk_gpio_get_bitmask(gpio);
+       u32 reg;
+
+       /* we must individually set/clear the two edges */
+       if (nmk_chip->edge_rising & bitmask) {
+               reg = readl(nmk_chip->addr + rimsc);
+               if (enable)
+                       reg |= bitmask;
+               else
+                       reg &= ~bitmask;
+               writel(reg, nmk_chip->addr + rimsc);
+       }
+       if (nmk_chip->edge_falling & bitmask) {
+               reg = readl(nmk_chip->addr + fimsc);
+               if (enable)
+                       reg |= bitmask;
+               else
+                       reg &= ~bitmask;
+               writel(reg, nmk_chip->addr + fimsc);
+       }
+}
+
+static void __nmk_gpio_set_wake(struct nmk_gpio_chip *nmk_chip,
+                               int gpio, bool on)
+{
+       __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, on);
+}
+
+static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable)
+{
+       int gpio;
+       struct nmk_gpio_chip *nmk_chip;
+       unsigned long flags;
+       u32 bitmask;
+
+       gpio = NOMADIK_IRQ_TO_GPIO(d->irq);
+       nmk_chip = irq_data_get_irq_chip_data(d);
+       bitmask = nmk_gpio_get_bitmask(gpio);
+       if (!nmk_chip)
+               return -EINVAL;
+
+       if (enable)
+               nmk_chip->enabled |= bitmask;
+       else
+               nmk_chip->enabled &= ~bitmask;
+
+       spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
+       spin_lock(&nmk_chip->lock);
+
+       __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, enable);
+
+       if (!(nmk_chip->real_wake & bitmask))
+               __nmk_gpio_set_wake(nmk_chip, gpio, enable);
+
+       spin_unlock(&nmk_chip->lock);
+       spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
+
+       return 0;
+}
+
+static void nmk_gpio_irq_mask(struct irq_data *d)
+{
+       nmk_gpio_irq_maskunmask(d, false);
+}
+
+static void nmk_gpio_irq_unmask(struct irq_data *d)
+{
+       nmk_gpio_irq_maskunmask(d, true);
+}
+
+static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
+{
+       struct nmk_gpio_chip *nmk_chip;
+       unsigned long flags;
+       u32 bitmask;
+       int gpio;
+
+       gpio = NOMADIK_IRQ_TO_GPIO(d->irq);
+       nmk_chip = irq_data_get_irq_chip_data(d);
+       if (!nmk_chip)
+               return -EINVAL;
+       bitmask = nmk_gpio_get_bitmask(gpio);
+
+       spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
+       spin_lock(&nmk_chip->lock);
+
+       if (!(nmk_chip->enabled & bitmask))
+               __nmk_gpio_set_wake(nmk_chip, gpio, on);
+
+       if (on)
+               nmk_chip->real_wake |= bitmask;
+       else
+               nmk_chip->real_wake &= ~bitmask;
+
+       spin_unlock(&nmk_chip->lock);
+       spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
+
+       return 0;
+}
+
+static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
+{
+       bool enabled, wake = irqd_is_wakeup_set(d);
+       int gpio;
+       struct nmk_gpio_chip *nmk_chip;
+       unsigned long flags;
+       u32 bitmask;
+
+       gpio = NOMADIK_IRQ_TO_GPIO(d->irq);
+       nmk_chip = irq_data_get_irq_chip_data(d);
+       bitmask = nmk_gpio_get_bitmask(gpio);
+       if (!nmk_chip)
+               return -EINVAL;
+
+       if (type & IRQ_TYPE_LEVEL_HIGH)
+               return -EINVAL;
+       if (type & IRQ_TYPE_LEVEL_LOW)
+               return -EINVAL;
+
+       enabled = nmk_chip->enabled & bitmask;
+
+       spin_lock_irqsave(&nmk_chip->lock, flags);
+
+       if (enabled)
+               __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, false);
+
+       if (enabled || wake)
+               __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, false);
+
+       nmk_chip->edge_rising &= ~bitmask;
+       if (type & IRQ_TYPE_EDGE_RISING)
+               nmk_chip->edge_rising |= bitmask;
+
+       nmk_chip->edge_falling &= ~bitmask;
+       if (type & IRQ_TYPE_EDGE_FALLING)
+               nmk_chip->edge_falling |= bitmask;
+
+       if (enabled)
+               __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, true);
+
+       if (enabled || wake)
+               __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, true);
+
+       spin_unlock_irqrestore(&nmk_chip->lock, flags);
+
+       return 0;
+}
+
+static struct irq_chip nmk_gpio_irq_chip = {
+       .name           = "Nomadik-GPIO",
+       .irq_ack        = nmk_gpio_irq_ack,
+       .irq_mask       = nmk_gpio_irq_mask,
+       .irq_unmask     = nmk_gpio_irq_unmask,
+       .irq_set_type   = nmk_gpio_irq_set_type,
+       .irq_set_wake   = nmk_gpio_irq_set_wake,
+};
+
+static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc,
+                                  u32 status)
+{
+       struct nmk_gpio_chip *nmk_chip;
+       struct irq_chip *host_chip = irq_get_chip(irq);
+       unsigned int first_irq;
+
+       chained_irq_enter(host_chip, desc);
+
+       nmk_chip = irq_get_handler_data(irq);
+       first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base);
+       while (status) {
+               int bit = __ffs(status);
+
+               generic_handle_irq(first_irq + bit);
+               status &= ~BIT(bit);
+       }
+
+       chained_irq_exit(host_chip, desc);
+}
+
+static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+       struct nmk_gpio_chip *nmk_chip = irq_get_handler_data(irq);
+       u32 status = readl(nmk_chip->addr + NMK_GPIO_IS);
+
+       __nmk_gpio_irq_handler(irq, desc, status);
+}
+
+static void nmk_gpio_secondary_irq_handler(unsigned int irq,
+                                          struct irq_desc *desc)
+{
+       struct nmk_gpio_chip *nmk_chip = irq_get_handler_data(irq);
+       u32 status = nmk_chip->get_secondary_status(nmk_chip->bank);
+
+       __nmk_gpio_irq_handler(irq, desc, status);
+}
+
+static int nmk_gpio_init_irq(struct nmk_gpio_chip *nmk_chip)
+{
+       unsigned int first_irq;
+       int i;
+
+       first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base);
+       for (i = first_irq; i < first_irq + nmk_chip->chip.ngpio; i++) {
+               irq_set_chip_and_handler(i, &nmk_gpio_irq_chip,
+                                        handle_edge_irq);
+               set_irq_flags(i, IRQF_VALID);
+               irq_set_chip_data(i, nmk_chip);
+               irq_set_irq_type(i, IRQ_TYPE_EDGE_FALLING);
+       }
+
+       irq_set_chained_handler(nmk_chip->parent_irq, nmk_gpio_irq_handler);
+       irq_set_handler_data(nmk_chip->parent_irq, nmk_chip);
+
+       if (nmk_chip->secondary_parent_irq >= 0) {
+               irq_set_chained_handler(nmk_chip->secondary_parent_irq,
+                                       nmk_gpio_secondary_irq_handler);
+               irq_set_handler_data(nmk_chip->secondary_parent_irq, nmk_chip);
+       }
+
+       return 0;
+}
+
+/* I/O Functions */
+static int nmk_gpio_make_input(struct gpio_chip *chip, unsigned offset)
+{
+       struct nmk_gpio_chip *nmk_chip =
+               container_of(chip, struct nmk_gpio_chip, chip);
+
+       writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC);
+       return 0;
+}
+
+static int nmk_gpio_get_input(struct gpio_chip *chip, unsigned offset)
+{
+       struct nmk_gpio_chip *nmk_chip =
+               container_of(chip, struct nmk_gpio_chip, chip);
+       u32 bit = 1 << offset;
+
+       return (readl(nmk_chip->addr + NMK_GPIO_DAT) & bit) != 0;
+}
+
+static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned offset,
+                               int val)
+{
+       struct nmk_gpio_chip *nmk_chip =
+               container_of(chip, struct nmk_gpio_chip, chip);
+
+       __nmk_gpio_set_output(nmk_chip, offset, val);
+}
+
+static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset,
+                               int val)
+{
+       struct nmk_gpio_chip *nmk_chip =
+               container_of(chip, struct nmk_gpio_chip, chip);
+
+       __nmk_gpio_make_output(nmk_chip, offset, val);
+
+       return 0;
+}
+
+static int nmk_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+       struct nmk_gpio_chip *nmk_chip =
+               container_of(chip, struct nmk_gpio_chip, chip);
+
+       return NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base) + offset;
+}
+
+#ifdef CONFIG_DEBUG_FS
+
+#include <linux/seq_file.h>
+
+static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+{
+       int mode;
+       unsigned                i;
+       unsigned                gpio = chip->base;
+       int                     is_out;
+       struct nmk_gpio_chip *nmk_chip =
+               container_of(chip, struct nmk_gpio_chip, chip);
+       const char *modes[] = {
+               [NMK_GPIO_ALT_GPIO]     = "gpio",
+               [NMK_GPIO_ALT_A]        = "altA",
+               [NMK_GPIO_ALT_B]        = "altB",
+               [NMK_GPIO_ALT_C]        = "altC",
+       };
+
+       for (i = 0; i < chip->ngpio; i++, gpio++) {
+               const char *label = gpiochip_is_requested(chip, i);
+               bool pull;
+               u32 bit = 1 << i;
+
+               is_out = readl(nmk_chip->addr + NMK_GPIO_DIR) & bit;
+               pull = !(readl(nmk_chip->addr + NMK_GPIO_PDIS) & bit);
+               mode = nmk_gpio_get_mode(gpio);
+               seq_printf(s, " gpio-%-3d (%-20.20s) %s %s %s %s",
+                       gpio, label ?: "(none)",
+                       is_out ? "out" : "in ",
+                       chip->get
+                               ? (chip->get(chip, i) ? "hi" : "lo")
+                               : "?  ",
+                       (mode < 0) ? "unknown" : modes[mode],
+                       pull ? "pull" : "none");
+
+               if (label && !is_out) {
+                       int             irq = gpio_to_irq(gpio);
+                       struct irq_desc *desc = irq_to_desc(irq);
+
+                       /* This races with request_irq(), set_irq_type(),
+                        * and set_irq_wake() ... but those are "rare".
+                        */
+                       if (irq >= 0 && desc->action) {
+                               char *trigger;
+                               u32 bitmask = nmk_gpio_get_bitmask(gpio);
+
+                               if (nmk_chip->edge_rising & bitmask)
+                                       trigger = "edge-rising";
+                               else if (nmk_chip->edge_falling & bitmask)
+                                       trigger = "edge-falling";
+                               else
+                                       trigger = "edge-undefined";
+
+                               seq_printf(s, " irq-%d %s%s",
+                                       irq, trigger,
+                                       irqd_is_wakeup_set(&desc->irq_data)
+                                               ? " wakeup" : "");
+                       }
+               }
+
+               seq_printf(s, "\n");
+       }
+}
+
+#else
+#define nmk_gpio_dbg_show      NULL
+#endif
+
+/* This structure is replicated for each GPIO block allocated at probe time */
+static struct gpio_chip nmk_gpio_template = {
+       .direction_input        = nmk_gpio_make_input,
+       .get                    = nmk_gpio_get_input,
+       .direction_output       = nmk_gpio_make_output,
+       .set                    = nmk_gpio_set_output,
+       .to_irq                 = nmk_gpio_to_irq,
+       .dbg_show               = nmk_gpio_dbg_show,
+       .can_sleep              = 0,
+};
+
+/*
+ * Called from the suspend/resume path to only keep the real wakeup interrupts
+ * (those that have had set_irq_wake() called on them) as wakeup interrupts,
+ * and not the rest of the interrupts which we needed to have as wakeups for
+ * cpuidle.
+ *
+ * PM ops are not used since this needs to be done at the end, after all the
+ * other drivers are done with their suspend callbacks.
+ */
+void nmk_gpio_wakeups_suspend(void)
+{
+       int i;
+
+       for (i = 0; i < NUM_BANKS; i++) {
+               struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
+
+               if (!chip)
+                       break;
+
+               chip->rwimsc = readl(chip->addr + NMK_GPIO_RWIMSC);
+               chip->fwimsc = readl(chip->addr + NMK_GPIO_FWIMSC);
+
+               writel(chip->rwimsc & chip->real_wake,
+                      chip->addr + NMK_GPIO_RWIMSC);
+               writel(chip->fwimsc & chip->real_wake,
+                      chip->addr + NMK_GPIO_FWIMSC);
+
+               if (cpu_is_u8500v2()) {
+                       chip->slpm = readl(chip->addr + NMK_GPIO_SLPC);
+
+                       /* 0 -> wakeup enable */
+                       writel(~chip->real_wake, chip->addr + NMK_GPIO_SLPC);
+               }
+       }
+}
+
+void nmk_gpio_wakeups_resume(void)
+{
+       int i;
+
+       for (i = 0; i < NUM_BANKS; i++) {
+               struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
+
+               if (!chip)
+                       break;
+
+               writel(chip->rwimsc, chip->addr + NMK_GPIO_RWIMSC);
+               writel(chip->fwimsc, chip->addr + NMK_GPIO_FWIMSC);
+
+               if (cpu_is_u8500v2())
+                       writel(chip->slpm, chip->addr + NMK_GPIO_SLPC);
+       }
+}
+
+/*
+ * Read the pull up/pull down status.
+ * A bit set in 'pull_up' means that pull up
+ * is selected if pull is enabled in PDIS register.
+ * Note: only pull up/down set via this driver can
+ * be detected due to HW limitations.
+ */
+void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up)
+{
+       if (gpio_bank < NUM_BANKS) {
+               struct nmk_gpio_chip *chip = nmk_gpio_chips[gpio_bank];
+
+               if (!chip)
+                       return;
+
+               *pull_up = chip->pull_up;
+       }
+}
+
+static int __devinit nmk_gpio_probe(struct platform_device *dev)
+{
+       struct nmk_gpio_platform_data *pdata = dev->dev.platform_data;
+       struct nmk_gpio_chip *nmk_chip;
+       struct gpio_chip *chip;
+       struct resource *res;
+       struct clk *clk;
+       int secondary_irq;
+       int irq;
+       int ret;
+
+       if (!pdata)
+               return -ENODEV;
+
+       res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+       if (!res) {
+               ret = -ENOENT;
+               goto out;
+       }
+
+       irq = platform_get_irq(dev, 0);
+       if (irq < 0) {
+               ret = irq;
+               goto out;
+       }
+
+       secondary_irq = platform_get_irq(dev, 1);
+       if (secondary_irq >= 0 && !pdata->get_secondary_status) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       if (request_mem_region(res->start, resource_size(res),
+                              dev_name(&dev->dev)) == NULL) {
+               ret = -EBUSY;
+               goto out;
+       }
+
+       clk = clk_get(&dev->dev, NULL);
+       if (IS_ERR(clk)) {
+               ret = PTR_ERR(clk);
+               goto out_release;
+       }
+
+       clk_enable(clk);
+
+       nmk_chip = kzalloc(sizeof(*nmk_chip), GFP_KERNEL);
+       if (!nmk_chip) {
+               ret = -ENOMEM;
+               goto out_clk;
+       }
+       /*
+        * The virt address in nmk_chip->addr is in the nomadik register space,
+        * so we can simply convert the resource address, without remapping
+        */
+       nmk_chip->bank = dev->id;
+       nmk_chip->clk = clk;
+       nmk_chip->addr = io_p2v(res->start);
+       nmk_chip->chip = nmk_gpio_template;
+       nmk_chip->parent_irq = irq;
+       nmk_chip->secondary_parent_irq = secondary_irq;
+       nmk_chip->get_secondary_status = pdata->get_secondary_status;
+       nmk_chip->set_ioforce = pdata->set_ioforce;
+       spin_lock_init(&nmk_chip->lock);
+
+       chip = &nmk_chip->chip;
+       chip->base = pdata->first_gpio;
+       chip->ngpio = pdata->num_gpio;
+       chip->label = pdata->name ?: dev_name(&dev->dev);
+       chip->dev = &dev->dev;
+       chip->owner = THIS_MODULE;
+
+       ret = gpiochip_add(&nmk_chip->chip);
+       if (ret)
+               goto out_free;
+
+       BUG_ON(nmk_chip->bank >= ARRAY_SIZE(nmk_gpio_chips));
+
+       nmk_gpio_chips[nmk_chip->bank] = nmk_chip;
+       platform_set_drvdata(dev, nmk_chip);
+
+       nmk_gpio_init_irq(nmk_chip);
+
+       dev_info(&dev->dev, "Bits %i-%i at address %p\n",
+                nmk_chip->chip.base, nmk_chip->chip.base+31, nmk_chip->addr);
+       return 0;
+
+out_free:
+       kfree(nmk_chip);
+out_clk:
+       clk_disable(clk);
+       clk_put(clk);
+out_release:
+       release_mem_region(res->start, resource_size(res));
+out:
+       dev_err(&dev->dev, "Failure %i for GPIO %i-%i\n", ret,
+                 pdata->first_gpio, pdata->first_gpio+31);
+       return ret;
+}
+
+static struct platform_driver nmk_gpio_driver = {
+       .driver = {
+               .owner = THIS_MODULE,
+               .name = "gpio",
+       },
+       .probe = nmk_gpio_probe,
+};
+
+static int __init nmk_gpio_init(void)
+{
+       return platform_driver_register(&nmk_gpio_driver);
+}
+
+core_initcall(nmk_gpio_init);
+
+MODULE_AUTHOR("Prafulla WADASKAR and Alessandro Rubini");
+MODULE_DESCRIPTION("Nomadik GPIO Driver");
+MODULE_LICENSE("GPL");
+
+
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
new file mode 100644 (file)
index 0000000..6c51191
--- /dev/null
@@ -0,0 +1,2007 @@
+/*
+ * Support functions for OMAP GPIO
+ *
+ * Copyright (C) 2003-2005 Nokia Corporation
+ * Written by Juha Yrjölä <juha.yrjola@nokia.com>
+ *
+ * Copyright (C) 2009 Texas Instruments
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/syscore_ops.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+
+#include <mach/hardware.h>
+#include <asm/irq.h>
+#include <mach/irqs.h>
+#include <mach/gpio.h>
+#include <asm/mach/irq.h>
+
+struct gpio_bank {
+       unsigned long pbase;
+       void __iomem *base;
+       u16 irq;
+       u16 virtual_irq_start;
+       int method;
+#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS)
+       u32 suspend_wakeup;
+       u32 saved_wakeup;
+#endif
+       u32 non_wakeup_gpios;
+       u32 enabled_non_wakeup_gpios;
+
+       u32 saved_datain;
+       u32 saved_fallingdetect;
+       u32 saved_risingdetect;
+       u32 level_mask;
+       u32 toggle_mask;
+       spinlock_t lock;
+       struct gpio_chip chip;
+       struct clk *dbck;
+       u32 mod_usage;
+       u32 dbck_enable_mask;
+       struct device *dev;
+       bool dbck_flag;
+       int stride;
+};
+
+#ifdef CONFIG_ARCH_OMAP3
+struct omap3_gpio_regs {
+       u32 irqenable1;
+       u32 irqenable2;
+       u32 wake_en;
+       u32 ctrl;
+       u32 oe;
+       u32 leveldetect0;
+       u32 leveldetect1;
+       u32 risingdetect;
+       u32 fallingdetect;
+       u32 dataout;
+};
+
+static struct omap3_gpio_regs gpio_context[OMAP34XX_NR_GPIOS];
+#endif
+
+/*
+ * TODO: Cleanup gpio_bank usage as it is having information
+ * related to all instances of the device
+ */
+static struct gpio_bank *gpio_bank;
+
+static int bank_width;
+
+/* TODO: Analyze removing gpio_bank_count usage from driver code */
+int gpio_bank_count;
+
+static inline struct gpio_bank *get_gpio_bank(int gpio)
+{
+       if (cpu_is_omap15xx()) {
+               if (OMAP_GPIO_IS_MPUIO(gpio))
+                       return &gpio_bank[0];
+               return &gpio_bank[1];
+       }
+       if (cpu_is_omap16xx()) {
+               if (OMAP_GPIO_IS_MPUIO(gpio))
+                       return &gpio_bank[0];
+               return &gpio_bank[1 + (gpio >> 4)];
+       }
+       if (cpu_is_omap7xx()) {
+               if (OMAP_GPIO_IS_MPUIO(gpio))
+                       return &gpio_bank[0];
+               return &gpio_bank[1 + (gpio >> 5)];
+       }
+       if (cpu_is_omap24xx())
+               return &gpio_bank[gpio >> 5];
+       if (cpu_is_omap34xx() || cpu_is_omap44xx())
+               return &gpio_bank[gpio >> 5];
+       BUG();
+       return NULL;
+}
+
+static inline int get_gpio_index(int gpio)
+{
+       if (cpu_is_omap7xx())
+               return gpio & 0x1f;
+       if (cpu_is_omap24xx())
+               return gpio & 0x1f;
+       if (cpu_is_omap34xx() || cpu_is_omap44xx())
+               return gpio & 0x1f;
+       return gpio & 0x0f;
+}
+
+static inline int gpio_valid(int gpio)
+{
+       if (gpio < 0)
+               return -1;
+       if (cpu_class_is_omap1() && OMAP_GPIO_IS_MPUIO(gpio)) {
+               if (gpio >= OMAP_MAX_GPIO_LINES + 16)
+                       return -1;
+               return 0;
+       }
+       if (cpu_is_omap15xx() && gpio < 16)
+               return 0;
+       if ((cpu_is_omap16xx()) && gpio < 64)
+               return 0;
+       if (cpu_is_omap7xx() && gpio < 192)
+               return 0;
+       if (cpu_is_omap2420() && gpio < 128)
+               return 0;
+       if (cpu_is_omap2430() && gpio < 160)
+               return 0;
+       if ((cpu_is_omap34xx() || cpu_is_omap44xx()) && gpio < 192)
+               return 0;
+       return -1;
+}
+
+static int check_gpio(int gpio)
+{
+       if (unlikely(gpio_valid(gpio) < 0)) {
+               printk(KERN_ERR "omap-gpio: invalid GPIO %d\n", gpio);
+               dump_stack();
+               return -1;
+       }
+       return 0;
+}
+
+static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
+{
+       void __iomem *reg = bank->base;
+       u32 l;
+
+       switch (bank->method) {
+#ifdef CONFIG_ARCH_OMAP1
+       case METHOD_MPUIO:
+               reg += OMAP_MPUIO_IO_CNTL / bank->stride;
+               break;
+#endif
+#ifdef CONFIG_ARCH_OMAP15XX
+       case METHOD_GPIO_1510:
+               reg += OMAP1510_GPIO_DIR_CONTROL;
+               break;
+#endif
+#ifdef CONFIG_ARCH_OMAP16XX
+       case METHOD_GPIO_1610:
+               reg += OMAP1610_GPIO_DIRECTION;
+               break;
+#endif
+#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+       case METHOD_GPIO_7XX:
+               reg += OMAP7XX_GPIO_DIR_CONTROL;
+               break;
+#endif
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+       case METHOD_GPIO_24XX:
+               reg += OMAP24XX_GPIO_OE;
+               break;
+#endif
+#if defined(CONFIG_ARCH_OMAP4)
+       case METHOD_GPIO_44XX:
+               reg += OMAP4_GPIO_OE;
+               break;
+#endif
+       default:
+               WARN_ON(1);
+               return;
+       }
+       l = __raw_readl(reg);
+       if (is_input)
+               l |= 1 << gpio;
+       else
+               l &= ~(1 << gpio);
+       __raw_writel(l, reg);
+}
+
+static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable)
+{
+       void __iomem *reg = bank->base;
+       u32 l = 0;
+
+       switch (bank->method) {
+#ifdef CONFIG_ARCH_OMAP1
+       case METHOD_MPUIO:
+               reg += OMAP_MPUIO_OUTPUT / bank->stride;
+               l = __raw_readl(reg);
+               if (enable)
+                       l |= 1 << gpio;
+               else
+                       l &= ~(1 << gpio);
+               break;
+#endif
+#ifdef CONFIG_ARCH_OMAP15XX
+       case METHOD_GPIO_1510:
+               reg += OMAP1510_GPIO_DATA_OUTPUT;
+               l = __raw_readl(reg);
+               if (enable)
+                       l |= 1 << gpio;
+               else
+                       l &= ~(1 << gpio);
+               break;
+#endif
+#ifdef CONFIG_ARCH_OMAP16XX
+       case METHOD_GPIO_1610:
+               if (enable)
+                       reg += OMAP1610_GPIO_SET_DATAOUT;
+               else
+                       reg += OMAP1610_GPIO_CLEAR_DATAOUT;
+               l = 1 << gpio;
+               break;
+#endif
+#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+       case METHOD_GPIO_7XX:
+               reg += OMAP7XX_GPIO_DATA_OUTPUT;
+               l = __raw_readl(reg);
+               if (enable)
+                       l |= 1 << gpio;
+               else
+                       l &= ~(1 << gpio);
+               break;
+#endif
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+       case METHOD_GPIO_24XX:
+               if (enable)
+                       reg += OMAP24XX_GPIO_SETDATAOUT;
+               else
+                       reg += OMAP24XX_GPIO_CLEARDATAOUT;
+               l = 1 << gpio;
+               break;
+#endif
+#ifdef CONFIG_ARCH_OMAP4
+       case METHOD_GPIO_44XX:
+               if (enable)
+                       reg += OMAP4_GPIO_SETDATAOUT;
+               else
+                       reg += OMAP4_GPIO_CLEARDATAOUT;
+               l = 1 << gpio;
+               break;
+#endif
+       default:
+               WARN_ON(1);
+               return;
+       }
+       __raw_writel(l, reg);
+}
+
+static int _get_gpio_datain(struct gpio_bank *bank, int gpio)
+{
+       void __iomem *reg;
+
+       if (check_gpio(gpio) < 0)
+               return -EINVAL;
+       reg = bank->base;
+       switch (bank->method) {
+#ifdef CONFIG_ARCH_OMAP1
+       case METHOD_MPUIO:
+               reg += OMAP_MPUIO_INPUT_LATCH / bank->stride;
+               break;
+#endif
+#ifdef CONFIG_ARCH_OMAP15XX
+       case METHOD_GPIO_1510:
+               reg += OMAP1510_GPIO_DATA_INPUT;
+               break;
+#endif
+#ifdef CONFIG_ARCH_OMAP16XX
+       case METHOD_GPIO_1610:
+               reg += OMAP1610_GPIO_DATAIN;
+               break;
+#endif
+#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+       case METHOD_GPIO_7XX:
+               reg += OMAP7XX_GPIO_DATA_INPUT;
+               break;
+#endif
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+       case METHOD_GPIO_24XX:
+               reg += OMAP24XX_GPIO_DATAIN;
+               break;
+#endif
+#ifdef CONFIG_ARCH_OMAP4
+       case METHOD_GPIO_44XX:
+               reg += OMAP4_GPIO_DATAIN;
+               break;
+#endif
+       default:
+               return -EINVAL;
+       }
+       return (__raw_readl(reg)
+                       & (1 << get_gpio_index(gpio))) != 0;
+}
+
+static int _get_gpio_dataout(struct gpio_bank *bank, int gpio)
+{
+       void __iomem *reg;
+
+       if (check_gpio(gpio) < 0)
+               return -EINVAL;
+       reg = bank->base;
+
+       switch (bank->method) {
+#ifdef CONFIG_ARCH_OMAP1
+       case METHOD_MPUIO:
+               reg += OMAP_MPUIO_OUTPUT / bank->stride;
+               break;
+#endif
+#ifdef CONFIG_ARCH_OMAP15XX
+       case METHOD_GPIO_1510:
+               reg += OMAP1510_GPIO_DATA_OUTPUT;
+               break;
+#endif
+#ifdef CONFIG_ARCH_OMAP16XX
+       case METHOD_GPIO_1610:
+               reg += OMAP1610_GPIO_DATAOUT;
+               break;
+#endif
+#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+       case METHOD_GPIO_7XX:
+               reg += OMAP7XX_GPIO_DATA_OUTPUT;
+               break;
+#endif
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+       case METHOD_GPIO_24XX:
+               reg += OMAP24XX_GPIO_DATAOUT;
+               break;
+#endif
+#ifdef CONFIG_ARCH_OMAP4
+       case METHOD_GPIO_44XX:
+               reg += OMAP4_GPIO_DATAOUT;
+               break;
+#endif
+       default:
+               return -EINVAL;
+       }
+
+       return (__raw_readl(reg) & (1 << get_gpio_index(gpio))) != 0;
+}
+
+#define MOD_REG_BIT(reg, bit_mask, set)        \
+do {   \
+       int l = __raw_readl(base + reg); \
+       if (set) l |= bit_mask; \
+       else l &= ~bit_mask; \
+       __raw_writel(l, base + reg); \
+} while(0)
+
+/**
+ * _set_gpio_debounce - low level gpio debounce time
+ * @bank: the gpio bank we're acting upon
+ * @gpio: the gpio number on this @gpio
+ * @debounce: debounce time to use
+ *
+ * OMAP's debounce time is in 31us steps so we need
+ * to convert and round up to the closest unit.
+ */
+static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
+               unsigned debounce)
+{
+       void __iomem            *reg = bank->base;
+       u32                     val;
+       u32                     l;
+
+       if (!bank->dbck_flag)
+               return;
+
+       if (debounce < 32)
+               debounce = 0x01;
+       else if (debounce > 7936)
+               debounce = 0xff;
+       else
+               debounce = (debounce / 0x1f) - 1;
+
+       l = 1 << get_gpio_index(gpio);
+
+       if (bank->method == METHOD_GPIO_44XX)
+               reg += OMAP4_GPIO_DEBOUNCINGTIME;
+       else
+               reg += OMAP24XX_GPIO_DEBOUNCE_VAL;
+
+       __raw_writel(debounce, reg);
+
+       reg = bank->base;
+       if (bank->method == METHOD_GPIO_44XX)
+               reg += OMAP4_GPIO_DEBOUNCENABLE;
+       else
+               reg += OMAP24XX_GPIO_DEBOUNCE_EN;
+
+       val = __raw_readl(reg);
+
+       if (debounce) {
+               val |= l;
+               clk_enable(bank->dbck);
+       } else {
+               val &= ~l;
+               clk_disable(bank->dbck);
+       }
+       bank->dbck_enable_mask = val;
+
+       __raw_writel(val, reg);
+}
+
+#ifdef CONFIG_ARCH_OMAP2PLUS
+static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio,
+                                               int trigger)
+{
+       void __iomem *base = bank->base;
+       u32 gpio_bit = 1 << gpio;
+       u32 val;
+
+       if (cpu_is_omap44xx()) {
+               MOD_REG_BIT(OMAP4_GPIO_LEVELDETECT0, gpio_bit,
+                       trigger & IRQ_TYPE_LEVEL_LOW);
+               MOD_REG_BIT(OMAP4_GPIO_LEVELDETECT1, gpio_bit,
+                       trigger & IRQ_TYPE_LEVEL_HIGH);
+               MOD_REG_BIT(OMAP4_GPIO_RISINGDETECT, gpio_bit,
+                       trigger & IRQ_TYPE_EDGE_RISING);
+               MOD_REG_BIT(OMAP4_GPIO_FALLINGDETECT, gpio_bit,
+                       trigger & IRQ_TYPE_EDGE_FALLING);
+       } else {
+               MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit,
+                       trigger & IRQ_TYPE_LEVEL_LOW);
+               MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT1, gpio_bit,
+                       trigger & IRQ_TYPE_LEVEL_HIGH);
+               MOD_REG_BIT(OMAP24XX_GPIO_RISINGDETECT, gpio_bit,
+                       trigger & IRQ_TYPE_EDGE_RISING);
+               MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit,
+                       trigger & IRQ_TYPE_EDGE_FALLING);
+       }
+       if (likely(!(bank->non_wakeup_gpios & gpio_bit))) {
+               if (cpu_is_omap44xx()) {
+                       if (trigger != 0)
+                               __raw_writel(1 << gpio, bank->base+
+                                               OMAP4_GPIO_IRQWAKEN0);
+                       else {
+                               val = __raw_readl(bank->base +
+                                                       OMAP4_GPIO_IRQWAKEN0);
+                               __raw_writel(val & (~(1 << gpio)), bank->base +
+                                                        OMAP4_GPIO_IRQWAKEN0);
+                       }
+               } else {
+                       /*
+                        * GPIO wakeup request can only be generated on edge
+                        * transitions
+                        */
+                       if (trigger & IRQ_TYPE_EDGE_BOTH)
+                               __raw_writel(1 << gpio, bank->base
+                                       + OMAP24XX_GPIO_SETWKUENA);
+                       else
+                               __raw_writel(1 << gpio, bank->base
+                                       + OMAP24XX_GPIO_CLEARWKUENA);
+               }
+       }
+       /* This part needs to be executed always for OMAP34xx */
+       if (cpu_is_omap34xx() || (bank->non_wakeup_gpios & gpio_bit)) {
+               /*
+                * Log the edge gpio and manually trigger the IRQ
+                * after resume if the input level changes
+                * to avoid irq lost during PER RET/OFF mode
+                * Applies for omap2 non-wakeup gpio and all omap3 gpios
+                */
+               if (trigger & IRQ_TYPE_EDGE_BOTH)
+                       bank->enabled_non_wakeup_gpios |= gpio_bit;
+               else
+                       bank->enabled_non_wakeup_gpios &= ~gpio_bit;
+       }
+
+       if (cpu_is_omap44xx()) {
+               bank->level_mask =
+                       __raw_readl(bank->base + OMAP4_GPIO_LEVELDETECT0) |
+                       __raw_readl(bank->base + OMAP4_GPIO_LEVELDETECT1);
+       } else {
+               bank->level_mask =
+                       __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0) |
+                       __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1);
+       }
+}
+#endif
+
+#ifdef CONFIG_ARCH_OMAP1
+/*
+ * This only applies to chips that can't do both rising and falling edge
+ * detection at once.  For all other chips, this function is a noop.
+ */
+static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio)
+{
+       void __iomem *reg = bank->base;
+       u32 l = 0;
+
+       switch (bank->method) {
+       case METHOD_MPUIO:
+               reg += OMAP_MPUIO_GPIO_INT_EDGE / bank->stride;
+               break;
+#ifdef CONFIG_ARCH_OMAP15XX
+       case METHOD_GPIO_1510:
+               reg += OMAP1510_GPIO_INT_CONTROL;
+               break;
+#endif
+#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+       case METHOD_GPIO_7XX:
+               reg += OMAP7XX_GPIO_INT_CONTROL;
+               break;
+#endif
+       default:
+               return;
+       }
+
+       l = __raw_readl(reg);
+       if ((l >> gpio) & 1)
+               l &= ~(1 << gpio);
+       else
+               l |= 1 << gpio;
+
+       __raw_writel(l, reg);
+}
+#endif
+
+static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
+{
+       void __iomem *reg = bank->base;
+       u32 l = 0;
+
+       switch (bank->method) {
+#ifdef CONFIG_ARCH_OMAP1
+       case METHOD_MPUIO:
+               reg += OMAP_MPUIO_GPIO_INT_EDGE / bank->stride;
+               l = __raw_readl(reg);
+               if ((trigger & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH)
+                       bank->toggle_mask |= 1 << gpio;
+               if (trigger & IRQ_TYPE_EDGE_RISING)
+                       l |= 1 << gpio;
+               else if (trigger & IRQ_TYPE_EDGE_FALLING)
+                       l &= ~(1 << gpio);
+               else
+                       goto bad;
+               break;
+#endif
+#ifdef CONFIG_ARCH_OMAP15XX
+       case METHOD_GPIO_1510:
+               reg += OMAP1510_GPIO_INT_CONTROL;
+               l = __raw_readl(reg);
+               if ((trigger & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH)
+                       bank->toggle_mask |= 1 << gpio;
+               if (trigger & IRQ_TYPE_EDGE_RISING)
+                       l |= 1 << gpio;
+               else if (trigger & IRQ_TYPE_EDGE_FALLING)
+                       l &= ~(1 << gpio);
+               else
+                       goto bad;
+               break;
+#endif
+#ifdef CONFIG_ARCH_OMAP16XX
+       case METHOD_GPIO_1610:
+               if (gpio & 0x08)
+                       reg += OMAP1610_GPIO_EDGE_CTRL2;
+               else
+                       reg += OMAP1610_GPIO_EDGE_CTRL1;
+               gpio &= 0x07;
+               l = __raw_readl(reg);
+               l &= ~(3 << (gpio << 1));
+               if (trigger & IRQ_TYPE_EDGE_RISING)
+                       l |= 2 << (gpio << 1);
+               if (trigger & IRQ_TYPE_EDGE_FALLING)
+                       l |= 1 << (gpio << 1);
+               if (trigger)
+                       /* Enable wake-up during idle for dynamic tick */
+                       __raw_writel(1 << gpio, bank->base + OMAP1610_GPIO_SET_WAKEUPENA);
+               else
+                       __raw_writel(1 << gpio, bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA);
+               break;
+#endif
+#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+       case METHOD_GPIO_7XX:
+               reg += OMAP7XX_GPIO_INT_CONTROL;
+               l = __raw_readl(reg);
+               if ((trigger & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH)
+                       bank->toggle_mask |= 1 << gpio;
+               if (trigger & IRQ_TYPE_EDGE_RISING)
+                       l |= 1 << gpio;
+               else if (trigger & IRQ_TYPE_EDGE_FALLING)
+                       l &= ~(1 << gpio);
+               else
+                       goto bad;
+               break;
+#endif
+#ifdef CONFIG_ARCH_OMAP2PLUS
+       case METHOD_GPIO_24XX:
+       case METHOD_GPIO_44XX:
+               set_24xx_gpio_triggering(bank, gpio, trigger);
+               return 0;
+#endif
+       default:
+               goto bad;
+       }
+       __raw_writel(l, reg);
+       return 0;
+bad:
+       return -EINVAL;
+}
+
+static int gpio_irq_type(struct irq_data *d, unsigned type)
+{
+       struct gpio_bank *bank;
+       unsigned gpio;
+       int retval;
+       unsigned long flags;
+
+       if (!cpu_class_is_omap2() && d->irq > IH_MPUIO_BASE)
+               gpio = OMAP_MPUIO(d->irq - IH_MPUIO_BASE);
+       else
+               gpio = d->irq - IH_GPIO_BASE;
+
+       if (check_gpio(gpio) < 0)
+               return -EINVAL;
+
+       if (type & ~IRQ_TYPE_SENSE_MASK)
+               return -EINVAL;
+
+       /* OMAP1 allows only only edge triggering */
+       if (!cpu_class_is_omap2()
+                       && (type & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH)))
+               return -EINVAL;
+
+       bank = irq_data_get_irq_chip_data(d);
+       spin_lock_irqsave(&bank->lock, flags);
+       retval = _set_gpio_triggering(bank, get_gpio_index(gpio), type);
+       spin_unlock_irqrestore(&bank->lock, flags);
+
+       if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
+               __irq_set_handler_locked(d->irq, handle_level_irq);
+       else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
+               __irq_set_handler_locked(d->irq, handle_edge_irq);
+
+       return retval;
+}
+
+static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask)
+{
+       void __iomem *reg = bank->base;
+
+       switch (bank->method) {
+#ifdef CONFIG_ARCH_OMAP1
+       case METHOD_MPUIO:
+               /* MPUIO irqstatus is reset by reading the status register,
+                * so do nothing here */
+               return;
+#endif
+#ifdef CONFIG_ARCH_OMAP15XX
+       case METHOD_GPIO_1510:
+               reg += OMAP1510_GPIO_INT_STATUS;
+               break;
+#endif
+#ifdef CONFIG_ARCH_OMAP16XX
+       case METHOD_GPIO_1610:
+               reg += OMAP1610_GPIO_IRQSTATUS1;
+               break;
+#endif
+#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+       case METHOD_GPIO_7XX:
+               reg += OMAP7XX_GPIO_INT_STATUS;
+               break;
+#endif
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+       case METHOD_GPIO_24XX:
+               reg += OMAP24XX_GPIO_IRQSTATUS1;
+               break;
+#endif
+#if defined(CONFIG_ARCH_OMAP4)
+       case METHOD_GPIO_44XX:
+               reg += OMAP4_GPIO_IRQSTATUS0;
+               break;
+#endif
+       default:
+               WARN_ON(1);
+               return;
+       }
+       __raw_writel(gpio_mask, reg);
+
+       /* Workaround for clearing DSP GPIO interrupts to allow retention */
+       if (cpu_is_omap24xx() || cpu_is_omap34xx())
+               reg = bank->base + OMAP24XX_GPIO_IRQSTATUS2;
+       else if (cpu_is_omap44xx())
+               reg = bank->base + OMAP4_GPIO_IRQSTATUS1;
+
+       if (cpu_is_omap24xx() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
+               __raw_writel(gpio_mask, reg);
+
+       /* Flush posted write for the irq status to avoid spurious interrupts */
+       __raw_readl(reg);
+       }
+}
+
+static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio)
+{
+       _clear_gpio_irqbank(bank, 1 << get_gpio_index(gpio));
+}
+
+static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank)
+{
+       void __iomem *reg = bank->base;
+       int inv = 0;
+       u32 l;
+       u32 mask;
+
+       switch (bank->method) {
+#ifdef CONFIG_ARCH_OMAP1
+       case METHOD_MPUIO:
+               reg += OMAP_MPUIO_GPIO_MASKIT / bank->stride;
+               mask = 0xffff;
+               inv = 1;
+               break;
+#endif
+#ifdef CONFIG_ARCH_OMAP15XX
+       case METHOD_GPIO_1510:
+               reg += OMAP1510_GPIO_INT_MASK;
+               mask = 0xffff;
+               inv = 1;
+               break;
+#endif
+#ifdef CONFIG_ARCH_OMAP16XX
+       case METHOD_GPIO_1610:
+               reg += OMAP1610_GPIO_IRQENABLE1;
+               mask = 0xffff;
+               break;
+#endif
+#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+       case METHOD_GPIO_7XX:
+               reg += OMAP7XX_GPIO_INT_MASK;
+               mask = 0xffffffff;
+               inv = 1;
+               break;
+#endif
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+       case METHOD_GPIO_24XX:
+               reg += OMAP24XX_GPIO_IRQENABLE1;
+               mask = 0xffffffff;
+               break;
+#endif
+#if defined(CONFIG_ARCH_OMAP4)
+       case METHOD_GPIO_44XX:
+               reg += OMAP4_GPIO_IRQSTATUSSET0;
+               mask = 0xffffffff;
+               break;
+#endif
+       default:
+               WARN_ON(1);
+               return 0;
+       }
+
+       l = __raw_readl(reg);
+       if (inv)
+               l = ~l;
+       l &= mask;
+       return l;
+}
+
+static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enable)
+{
+       void __iomem *reg = bank->base;
+       u32 l;
+
+       switch (bank->method) {
+#ifdef CONFIG_ARCH_OMAP1
+       case METHOD_MPUIO:
+               reg += OMAP_MPUIO_GPIO_MASKIT / bank->stride;
+               l = __raw_readl(reg);
+               if (enable)
+                       l &= ~(gpio_mask);
+               else
+                       l |= gpio_mask;
+               break;
+#endif
+#ifdef CONFIG_ARCH_OMAP15XX
+       case METHOD_GPIO_1510:
+               reg += OMAP1510_GPIO_INT_MASK;
+               l = __raw_readl(reg);
+               if (enable)
+                       l &= ~(gpio_mask);
+               else
+                       l |= gpio_mask;
+               break;
+#endif
+#ifdef CONFIG_ARCH_OMAP16XX
+       case METHOD_GPIO_1610:
+               if (enable)
+                       reg += OMAP1610_GPIO_SET_IRQENABLE1;
+               else
+                       reg += OMAP1610_GPIO_CLEAR_IRQENABLE1;
+               l = gpio_mask;
+               break;
+#endif
+#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+       case METHOD_GPIO_7XX:
+               reg += OMAP7XX_GPIO_INT_MASK;
+               l = __raw_readl(reg);
+               if (enable)
+                       l &= ~(gpio_mask);
+               else
+                       l |= gpio_mask;
+               break;
+#endif
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+       case METHOD_GPIO_24XX:
+               if (enable)
+                       reg += OMAP24XX_GPIO_SETIRQENABLE1;
+               else
+                       reg += OMAP24XX_GPIO_CLEARIRQENABLE1;
+               l = gpio_mask;
+               break;
+#endif
+#ifdef CONFIG_ARCH_OMAP4
+       case METHOD_GPIO_44XX:
+               if (enable)
+                       reg += OMAP4_GPIO_IRQSTATUSSET0;
+               else
+                       reg += OMAP4_GPIO_IRQSTATUSCLR0;
+               l = gpio_mask;
+               break;
+#endif
+       default:
+               WARN_ON(1);
+               return;
+       }
+       __raw_writel(l, reg);
+}
+
+static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int enable)
+{
+       _enable_gpio_irqbank(bank, 1 << get_gpio_index(gpio), enable);
+}
+
+/*
+ * Note that ENAWAKEUP needs to be enabled in GPIO_SYSCONFIG register.
+ * 1510 does not seem to have a wake-up register. If JTAG is connected
+ * to the target, system will wake up always on GPIO events. While
+ * system is running all registered GPIO interrupts need to have wake-up
+ * enabled. When system is suspended, only selected GPIO interrupts need
+ * to have wake-up enabled.
+ */
+static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable)
+{
+       unsigned long uninitialized_var(flags);
+
+       switch (bank->method) {
+#ifdef CONFIG_ARCH_OMAP16XX
+       case METHOD_MPUIO:
+       case METHOD_GPIO_1610:
+               spin_lock_irqsave(&bank->lock, flags);
+               if (enable)
+                       bank->suspend_wakeup |= (1 << gpio);
+               else
+                       bank->suspend_wakeup &= ~(1 << gpio);
+               spin_unlock_irqrestore(&bank->lock, flags);
+               return 0;
+#endif
+#ifdef CONFIG_ARCH_OMAP2PLUS
+       case METHOD_GPIO_24XX:
+       case METHOD_GPIO_44XX:
+               if (bank->non_wakeup_gpios & (1 << gpio)) {
+                       printk(KERN_ERR "Unable to modify wakeup on "
+                                       "non-wakeup GPIO%d\n",
+                                       (bank - gpio_bank) * 32 + gpio);
+                       return -EINVAL;
+               }
+               spin_lock_irqsave(&bank->lock, flags);
+               if (enable)
+                       bank->suspend_wakeup |= (1 << gpio);
+               else
+                       bank->suspend_wakeup &= ~(1 << gpio);
+               spin_unlock_irqrestore(&bank->lock, flags);
+               return 0;
+#endif
+       default:
+               printk(KERN_ERR "Can't enable GPIO wakeup for method %i\n",
+                      bank->method);
+               return -EINVAL;
+       }
+}
+
+static void _reset_gpio(struct gpio_bank *bank, int gpio)
+{
+       _set_gpio_direction(bank, get_gpio_index(gpio), 1);
+       _set_gpio_irqenable(bank, gpio, 0);
+       _clear_gpio_irqstatus(bank, gpio);
+       _set_gpio_triggering(bank, get_gpio_index(gpio), IRQ_TYPE_NONE);
+}
+
+/* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
+static int gpio_wake_enable(struct irq_data *d, unsigned int enable)
+{
+       unsigned int gpio = d->irq - IH_GPIO_BASE;
+       struct gpio_bank *bank;
+       int retval;
+
+       if (check_gpio(gpio) < 0)
+               return -ENODEV;
+       bank = irq_data_get_irq_chip_data(d);
+       retval = _set_gpio_wakeup(bank, get_gpio_index(gpio), enable);
+
+       return retval;
+}
+
+static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+       struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip);
+       unsigned long flags;
+
+       spin_lock_irqsave(&bank->lock, flags);
+
+       /* Set trigger to none. You need to enable the desired trigger with
+        * request_irq() or set_irq_type().
+        */
+       _set_gpio_triggering(bank, offset, IRQ_TYPE_NONE);
+
+#ifdef CONFIG_ARCH_OMAP15XX
+       if (bank->method == METHOD_GPIO_1510) {
+               void __iomem *reg;
+
+               /* Claim the pin for MPU */
+               reg = bank->base + OMAP1510_GPIO_PIN_CONTROL;
+               __raw_writel(__raw_readl(reg) | (1 << offset), reg);
+       }
+#endif
+       if (!cpu_class_is_omap1()) {
+               if (!bank->mod_usage) {
+                       void __iomem *reg = bank->base;
+                       u32 ctrl;
+
+                       if (cpu_is_omap24xx() || cpu_is_omap34xx())
+                               reg += OMAP24XX_GPIO_CTRL;
+                       else if (cpu_is_omap44xx())
+                               reg += OMAP4_GPIO_CTRL;
+                       ctrl = __raw_readl(reg);
+                       /* Module is enabled, clocks are not gated */
+                       ctrl &= 0xFFFFFFFE;
+                       __raw_writel(ctrl, reg);
+               }
+               bank->mod_usage |= 1 << offset;
+       }
+       spin_unlock_irqrestore(&bank->lock, flags);
+
+       return 0;
+}
+
+static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+       struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip);
+       unsigned long flags;
+
+       spin_lock_irqsave(&bank->lock, flags);
+#ifdef CONFIG_ARCH_OMAP16XX
+       if (bank->method == METHOD_GPIO_1610) {
+               /* Disable wake-up during idle for dynamic tick */
+               void __iomem *reg = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
+               __raw_writel(1 << offset, reg);
+       }
+#endif
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+       if (bank->method == METHOD_GPIO_24XX) {
+               /* Disable wake-up during idle for dynamic tick */
+               void __iomem *reg = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
+               __raw_writel(1 << offset, reg);
+       }
+#endif
+#ifdef CONFIG_ARCH_OMAP4
+       if (bank->method == METHOD_GPIO_44XX) {
+               /* Disable wake-up during idle for dynamic tick */
+               void __iomem *reg = bank->base + OMAP4_GPIO_IRQWAKEN0;
+               __raw_writel(1 << offset, reg);
+       }
+#endif
+       if (!cpu_class_is_omap1()) {
+               bank->mod_usage &= ~(1 << offset);
+               if (!bank->mod_usage) {
+                       void __iomem *reg = bank->base;
+                       u32 ctrl;
+
+                       if (cpu_is_omap24xx() || cpu_is_omap34xx())
+                               reg += OMAP24XX_GPIO_CTRL;
+                       else if (cpu_is_omap44xx())
+                               reg += OMAP4_GPIO_CTRL;
+                       ctrl = __raw_readl(reg);
+                       /* Module is disabled, clocks are gated */
+                       ctrl |= 1;
+                       __raw_writel(ctrl, reg);
+               }
+       }
+       _reset_gpio(bank, bank->chip.base + offset);
+       spin_unlock_irqrestore(&bank->lock, flags);
+}
+
+/*
+ * We need to unmask the GPIO bank interrupt as soon as possible to
+ * avoid missing GPIO interrupts for other lines in the bank.
+ * Then we need to mask-read-clear-unmask the triggered GPIO lines
+ * in the bank to avoid missing nested interrupts for a GPIO line.
+ * If we wait to unmask individual GPIO lines in the bank after the
+ * line's interrupt handler has been run, we may miss some nested
+ * interrupts.
+ */
+static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+       void __iomem *isr_reg = NULL;
+       u32 isr;
+       unsigned int gpio_irq, gpio_index;
+       struct gpio_bank *bank;
+       u32 retrigger = 0;
+       int unmasked = 0;
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+
+       chained_irq_enter(chip, desc);
+
+       bank = irq_get_handler_data(irq);
+#ifdef CONFIG_ARCH_OMAP1
+       if (bank->method == METHOD_MPUIO)
+               isr_reg = bank->base +
+                               OMAP_MPUIO_GPIO_INT / bank->stride;
+#endif
+#ifdef CONFIG_ARCH_OMAP15XX
+       if (bank->method == METHOD_GPIO_1510)
+               isr_reg = bank->base + OMAP1510_GPIO_INT_STATUS;
+#endif
+#if defined(CONFIG_ARCH_OMAP16XX)
+       if (bank->method == METHOD_GPIO_1610)
+               isr_reg = bank->base + OMAP1610_GPIO_IRQSTATUS1;
+#endif
+#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+       if (bank->method == METHOD_GPIO_7XX)
+               isr_reg = bank->base + OMAP7XX_GPIO_INT_STATUS;
+#endif
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+       if (bank->method == METHOD_GPIO_24XX)
+               isr_reg = bank->base + OMAP24XX_GPIO_IRQSTATUS1;
+#endif
+#if defined(CONFIG_ARCH_OMAP4)
+       if (bank->method == METHOD_GPIO_44XX)
+               isr_reg = bank->base + OMAP4_GPIO_IRQSTATUS0;
+#endif
+
+       if (WARN_ON(!isr_reg))
+               goto exit;
+
+       while(1) {
+               u32 isr_saved, level_mask = 0;
+               u32 enabled;
+
+               enabled = _get_gpio_irqbank_mask(bank);
+               isr_saved = isr = __raw_readl(isr_reg) & enabled;
+
+               if (cpu_is_omap15xx() && (bank->method == METHOD_MPUIO))
+                       isr &= 0x0000ffff;
+
+               if (cpu_class_is_omap2()) {
+                       level_mask = bank->level_mask & enabled;
+               }
+
+               /* clear edge sensitive interrupts before handler(s) are
+               called so that we don't miss any interrupt occurred while
+               executing them */
+               _enable_gpio_irqbank(bank, isr_saved & ~level_mask, 0);
+               _clear_gpio_irqbank(bank, isr_saved & ~level_mask);
+               _enable_gpio_irqbank(bank, isr_saved & ~level_mask, 1);
+
+               /* if there is only edge sensitive GPIO pin interrupts
+               configured, we could unmask GPIO bank interrupt immediately */
+               if (!level_mask && !unmasked) {
+                       unmasked = 1;
+                       chained_irq_exit(chip, desc);
+               }
+
+               isr |= retrigger;
+               retrigger = 0;
+               if (!isr)
+                       break;
+
+               gpio_irq = bank->virtual_irq_start;
+               for (; isr != 0; isr >>= 1, gpio_irq++) {
+                       gpio_index = get_gpio_index(irq_to_gpio(gpio_irq));
+
+                       if (!(isr & 1))
+                               continue;
+
+#ifdef CONFIG_ARCH_OMAP1
+                       /*
+                        * Some chips can't respond to both rising and falling
+                        * at the same time.  If this irq was requested with
+                        * both flags, we need to flip the ICR data for the IRQ
+                        * to respond to the IRQ for the opposite direction.
+                        * This will be indicated in the bank toggle_mask.
+                        */
+                       if (bank->toggle_mask & (1 << gpio_index))
+                               _toggle_gpio_edge_triggering(bank, gpio_index);
+#endif
+
+                       generic_handle_irq(gpio_irq);
+               }
+       }
+       /* if bank has any level sensitive GPIO pin interrupt
+       configured, we must unmask the bank interrupt only after
+       handler(s) are executed in order to avoid spurious bank
+       interrupt */
+exit:
+       if (!unmasked)
+               chained_irq_exit(chip, desc);
+}
+
+static void gpio_irq_shutdown(struct irq_data *d)
+{
+       unsigned int gpio = d->irq - IH_GPIO_BASE;
+       struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+
+       _reset_gpio(bank, gpio);
+}
+
+static void gpio_ack_irq(struct irq_data *d)
+{
+       unsigned int gpio = d->irq - IH_GPIO_BASE;
+       struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+
+       _clear_gpio_irqstatus(bank, gpio);
+}
+
+static void gpio_mask_irq(struct irq_data *d)
+{
+       unsigned int gpio = d->irq - IH_GPIO_BASE;
+       struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+
+       _set_gpio_irqenable(bank, gpio, 0);
+       _set_gpio_triggering(bank, get_gpio_index(gpio), IRQ_TYPE_NONE);
+}
+
+static void gpio_unmask_irq(struct irq_data *d)
+{
+       unsigned int gpio = d->irq - IH_GPIO_BASE;
+       struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       unsigned int irq_mask = 1 << get_gpio_index(gpio);
+       u32 trigger = irqd_get_trigger_type(d);
+
+       if (trigger)
+               _set_gpio_triggering(bank, get_gpio_index(gpio), trigger);
+
+       /* For level-triggered GPIOs, the clearing must be done after
+        * the HW source is cleared, thus after the handler has run */
+       if (bank->level_mask & irq_mask) {
+               _set_gpio_irqenable(bank, gpio, 0);
+               _clear_gpio_irqstatus(bank, gpio);
+       }
+
+       _set_gpio_irqenable(bank, gpio, 1);
+}
+
+static struct irq_chip gpio_irq_chip = {
+       .name           = "GPIO",
+       .irq_shutdown   = gpio_irq_shutdown,
+       .irq_ack        = gpio_ack_irq,
+       .irq_mask       = gpio_mask_irq,
+       .irq_unmask     = gpio_unmask_irq,
+       .irq_set_type   = gpio_irq_type,
+       .irq_set_wake   = gpio_wake_enable,
+};
+
+/*---------------------------------------------------------------------*/
+
+#ifdef CONFIG_ARCH_OMAP1
+
+/* MPUIO uses the always-on 32k clock */
+
+static void mpuio_ack_irq(struct irq_data *d)
+{
+       /* The ISR is reset automatically, so do nothing here. */
+}
+
+static void mpuio_mask_irq(struct irq_data *d)
+{
+       unsigned int gpio = OMAP_MPUIO(d->irq - IH_MPUIO_BASE);
+       struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+
+       _set_gpio_irqenable(bank, gpio, 0);
+}
+
+static void mpuio_unmask_irq(struct irq_data *d)
+{
+       unsigned int gpio = OMAP_MPUIO(d->irq - IH_MPUIO_BASE);
+       struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
+
+       _set_gpio_irqenable(bank, gpio, 1);
+}
+
+static struct irq_chip mpuio_irq_chip = {
+       .name           = "MPUIO",
+       .irq_ack        = mpuio_ack_irq,
+       .irq_mask       = mpuio_mask_irq,
+       .irq_unmask     = mpuio_unmask_irq,
+       .irq_set_type   = gpio_irq_type,
+#ifdef CONFIG_ARCH_OMAP16XX
+       /* REVISIT: assuming only 16xx supports MPUIO wake events */
+       .irq_set_wake   = gpio_wake_enable,
+#endif
+};
+
+
+#define bank_is_mpuio(bank)    ((bank)->method == METHOD_MPUIO)
+
+
+#ifdef CONFIG_ARCH_OMAP16XX
+
+#include <linux/platform_device.h>
+
+static int omap_mpuio_suspend_noirq(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct gpio_bank        *bank = platform_get_drvdata(pdev);
+       void __iomem            *mask_reg = bank->base +
+                                       OMAP_MPUIO_GPIO_MASKIT / bank->stride;
+       unsigned long           flags;
+
+       spin_lock_irqsave(&bank->lock, flags);
+       bank->saved_wakeup = __raw_readl(mask_reg);
+       __raw_writel(0xffff & ~bank->suspend_wakeup, mask_reg);
+       spin_unlock_irqrestore(&bank->lock, flags);
+
+       return 0;
+}
+
+static int omap_mpuio_resume_noirq(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct gpio_bank        *bank = platform_get_drvdata(pdev);
+       void __iomem            *mask_reg = bank->base +
+                                       OMAP_MPUIO_GPIO_MASKIT / bank->stride;
+       unsigned long           flags;
+
+       spin_lock_irqsave(&bank->lock, flags);
+       __raw_writel(bank->saved_wakeup, mask_reg);
+       spin_unlock_irqrestore(&bank->lock, flags);
+
+       return 0;
+}
+
+static const struct dev_pm_ops omap_mpuio_dev_pm_ops = {
+       .suspend_noirq = omap_mpuio_suspend_noirq,
+       .resume_noirq = omap_mpuio_resume_noirq,
+};
+
+/* use platform_driver for this. */
+static struct platform_driver omap_mpuio_driver = {
+       .driver         = {
+               .name   = "mpuio",
+               .pm     = &omap_mpuio_dev_pm_ops,
+       },
+};
+
+static struct platform_device omap_mpuio_device = {
+       .name           = "mpuio",
+       .id             = -1,
+       .dev = {
+               .driver = &omap_mpuio_driver.driver,
+       }
+       /* could list the /proc/iomem resources */
+};
+
+static inline void mpuio_init(void)
+{
+       struct gpio_bank *bank = get_gpio_bank(OMAP_MPUIO(0));
+       platform_set_drvdata(&omap_mpuio_device, bank);
+
+       if (platform_driver_register(&omap_mpuio_driver) == 0)
+               (void) platform_device_register(&omap_mpuio_device);
+}
+
+#else
+static inline void mpuio_init(void) {}
+#endif /* 16xx */
+
+#else
+
+extern struct irq_chip mpuio_irq_chip;
+
+#define bank_is_mpuio(bank)    0
+static inline void mpuio_init(void) {}
+
+#endif
+
+/*---------------------------------------------------------------------*/
+
+/* REVISIT these are stupid implementations!  replace by ones that
+ * don't switch on METHOD_* and which mostly avoid spinlocks
+ */
+
+static int gpio_input(struct gpio_chip *chip, unsigned offset)
+{
+       struct gpio_bank *bank;
+       unsigned long flags;
+
+       bank = container_of(chip, struct gpio_bank, chip);
+       spin_lock_irqsave(&bank->lock, flags);
+       _set_gpio_direction(bank, offset, 1);
+       spin_unlock_irqrestore(&bank->lock, flags);
+       return 0;
+}
+
+static int gpio_is_input(struct gpio_bank *bank, int mask)
+{
+       void __iomem *reg = bank->base;
+
+       switch (bank->method) {
+       case METHOD_MPUIO:
+               reg += OMAP_MPUIO_IO_CNTL / bank->stride;
+               break;
+       case METHOD_GPIO_1510:
+               reg += OMAP1510_GPIO_DIR_CONTROL;
+               break;
+       case METHOD_GPIO_1610:
+               reg += OMAP1610_GPIO_DIRECTION;
+               break;
+       case METHOD_GPIO_7XX:
+               reg += OMAP7XX_GPIO_DIR_CONTROL;
+               break;
+       case METHOD_GPIO_24XX:
+               reg += OMAP24XX_GPIO_OE;
+               break;
+       case METHOD_GPIO_44XX:
+               reg += OMAP4_GPIO_OE;
+               break;
+       default:
+               WARN_ONCE(1, "gpio_is_input: incorrect OMAP GPIO method");
+               return -EINVAL;
+       }
+       return __raw_readl(reg) & mask;
+}
+
+static int gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+       struct gpio_bank *bank;
+       void __iomem *reg;
+       int gpio;
+       u32 mask;
+
+       gpio = chip->base + offset;
+       bank = get_gpio_bank(gpio);
+       reg = bank->base;
+       mask = 1 << get_gpio_index(gpio);
+
+       if (gpio_is_input(bank, mask))
+               return _get_gpio_datain(bank, gpio);
+       else
+               return _get_gpio_dataout(bank, gpio);
+}
+
+static int gpio_output(struct gpio_chip *chip, unsigned offset, int value)
+{
+       struct gpio_bank *bank;
+       unsigned long flags;
+
+       bank = container_of(chip, struct gpio_bank, chip);
+       spin_lock_irqsave(&bank->lock, flags);
+       _set_gpio_dataout(bank, offset, value);
+       _set_gpio_direction(bank, offset, 0);
+       spin_unlock_irqrestore(&bank->lock, flags);
+       return 0;
+}
+
+static int gpio_debounce(struct gpio_chip *chip, unsigned offset,
+               unsigned debounce)
+{
+       struct gpio_bank *bank;
+       unsigned long flags;
+
+       bank = container_of(chip, struct gpio_bank, chip);
+
+       if (!bank->dbck) {
+               bank->dbck = clk_get(bank->dev, "dbclk");
+               if (IS_ERR(bank->dbck))
+                       dev_err(bank->dev, "Could not get gpio dbck\n");
+       }
+
+       spin_lock_irqsave(&bank->lock, flags);
+       _set_gpio_debounce(bank, offset, debounce);
+       spin_unlock_irqrestore(&bank->lock, flags);
+
+       return 0;
+}
+
+static void gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+       struct gpio_bank *bank;
+       unsigned long flags;
+
+       bank = container_of(chip, struct gpio_bank, chip);
+       spin_lock_irqsave(&bank->lock, flags);
+       _set_gpio_dataout(bank, offset, value);
+       spin_unlock_irqrestore(&bank->lock, flags);
+}
+
+static int gpio_2irq(struct gpio_chip *chip, unsigned offset)
+{
+       struct gpio_bank *bank;
+
+       bank = container_of(chip, struct gpio_bank, chip);
+       return bank->virtual_irq_start + offset;
+}
+
+/*---------------------------------------------------------------------*/
+
+static void __init omap_gpio_show_rev(struct gpio_bank *bank)
+{
+       u32 rev;
+
+       if (cpu_is_omap16xx() && !(bank->method != METHOD_MPUIO))
+               rev = __raw_readw(bank->base + OMAP1610_GPIO_REVISION);
+       else if (cpu_is_omap24xx() || cpu_is_omap34xx())
+               rev = __raw_readl(bank->base + OMAP24XX_GPIO_REVISION);
+       else if (cpu_is_omap44xx())
+               rev = __raw_readl(bank->base + OMAP4_GPIO_REVISION);
+       else
+               return;
+
+       printk(KERN_INFO "OMAP GPIO hardware version %d.%d\n",
+               (rev >> 4) & 0x0f, rev & 0x0f);
+}
+
+/* This lock class tells lockdep that GPIO irqs are in a different
+ * category than their parents, so it won't report false recursion.
+ */
+static struct lock_class_key gpio_lock_class;
+
+static inline int init_gpio_info(struct platform_device *pdev)
+{
+       /* TODO: Analyze removing gpio_bank_count usage from driver code */
+       gpio_bank = kzalloc(gpio_bank_count * sizeof(struct gpio_bank),
+                               GFP_KERNEL);
+       if (!gpio_bank) {
+               dev_err(&pdev->dev, "Memory alloc failed for gpio_bank\n");
+               return -ENOMEM;
+       }
+       return 0;
+}
+
+/* TODO: Cleanup cpu_is_* checks */
+static void omap_gpio_mod_init(struct gpio_bank *bank, int id)
+{
+       if (cpu_class_is_omap2()) {
+               if (cpu_is_omap44xx()) {
+                       __raw_writel(0xffffffff, bank->base +
+                                       OMAP4_GPIO_IRQSTATUSCLR0);
+                       __raw_writel(0x00000000, bank->base +
+                                        OMAP4_GPIO_DEBOUNCENABLE);
+                       /* Initialize interface clk ungated, module enabled */
+                       __raw_writel(0, bank->base + OMAP4_GPIO_CTRL);
+               } else if (cpu_is_omap34xx()) {
+                       __raw_writel(0x00000000, bank->base +
+                                       OMAP24XX_GPIO_IRQENABLE1);
+                       __raw_writel(0xffffffff, bank->base +
+                                       OMAP24XX_GPIO_IRQSTATUS1);
+                       __raw_writel(0x00000000, bank->base +
+                                       OMAP24XX_GPIO_DEBOUNCE_EN);
+
+                       /* Initialize interface clk ungated, module enabled */
+                       __raw_writel(0, bank->base + OMAP24XX_GPIO_CTRL);
+               } else if (cpu_is_omap24xx()) {
+                       static const u32 non_wakeup_gpios[] = {
+                               0xe203ffc0, 0x08700040
+                       };
+                       if (id < ARRAY_SIZE(non_wakeup_gpios))
+                               bank->non_wakeup_gpios = non_wakeup_gpios[id];
+               }
+       } else if (cpu_class_is_omap1()) {
+               if (bank_is_mpuio(bank))
+                       __raw_writew(0xffff, bank->base +
+                               OMAP_MPUIO_GPIO_MASKIT / bank->stride);
+               if (cpu_is_omap15xx() && bank->method == METHOD_GPIO_1510) {
+                       __raw_writew(0xffff, bank->base
+                                               + OMAP1510_GPIO_INT_MASK);
+                       __raw_writew(0x0000, bank->base
+                                               + OMAP1510_GPIO_INT_STATUS);
+               }
+               if (cpu_is_omap16xx() && bank->method == METHOD_GPIO_1610) {
+                       __raw_writew(0x0000, bank->base
+                                               + OMAP1610_GPIO_IRQENABLE1);
+                       __raw_writew(0xffff, bank->base
+                                               + OMAP1610_GPIO_IRQSTATUS1);
+                       __raw_writew(0x0014, bank->base
+                                               + OMAP1610_GPIO_SYSCONFIG);
+
+                       /*
+                        * Enable system clock for GPIO module.
+                        * The CAM_CLK_CTRL *is* really the right place.
+                        */
+                       omap_writel(omap_readl(ULPD_CAM_CLK_CTRL) | 0x04,
+                                               ULPD_CAM_CLK_CTRL);
+               }
+               if (cpu_is_omap7xx() && bank->method == METHOD_GPIO_7XX) {
+                       __raw_writel(0xffffffff, bank->base
+                                               + OMAP7XX_GPIO_INT_MASK);
+                       __raw_writel(0x00000000, bank->base
+                                               + OMAP7XX_GPIO_INT_STATUS);
+               }
+       }
+}
+
+static void __init omap_gpio_chip_init(struct gpio_bank *bank)
+{
+       int j;
+       static int gpio;
+
+       bank->mod_usage = 0;
+       /*
+        * REVISIT eventually switch from OMAP-specific gpio structs
+        * over to the generic ones
+        */
+       bank->chip.request = omap_gpio_request;
+       bank->chip.free = omap_gpio_free;
+       bank->chip.direction_input = gpio_input;
+       bank->chip.get = gpio_get;
+       bank->chip.direction_output = gpio_output;
+       bank->chip.set_debounce = gpio_debounce;
+       bank->chip.set = gpio_set;
+       bank->chip.to_irq = gpio_2irq;
+       if (bank_is_mpuio(bank)) {
+               bank->chip.label = "mpuio";
+#ifdef CONFIG_ARCH_OMAP16XX
+               bank->chip.dev = &omap_mpuio_device.dev;
+#endif
+               bank->chip.base = OMAP_MPUIO(0);
+       } else {
+               bank->chip.label = "gpio";
+               bank->chip.base = gpio;
+               gpio += bank_width;
+       }
+       bank->chip.ngpio = bank_width;
+
+       gpiochip_add(&bank->chip);
+
+       for (j = bank->virtual_irq_start;
+                    j < bank->virtual_irq_start + bank_width; j++) {
+               irq_set_lockdep_class(j, &gpio_lock_class);
+               irq_set_chip_data(j, bank);
+               if (bank_is_mpuio(bank))
+                       irq_set_chip(j, &mpuio_irq_chip);
+               else
+                       irq_set_chip(j, &gpio_irq_chip);
+               irq_set_handler(j, handle_simple_irq);
+               set_irq_flags(j, IRQF_VALID);
+       }
+       irq_set_chained_handler(bank->irq, gpio_irq_handler);
+       irq_set_handler_data(bank->irq, bank);
+}
+
+static int __devinit omap_gpio_probe(struct platform_device *pdev)
+{
+       static int gpio_init_done;
+       struct omap_gpio_platform_data *pdata;
+       struct resource *res;
+       int id;
+       struct gpio_bank *bank;
+
+       if (!pdev->dev.platform_data)
+               return -EINVAL;
+
+       pdata = pdev->dev.platform_data;
+
+       if (!gpio_init_done) {
+               int ret;
+
+               ret = init_gpio_info(pdev);
+               if (ret)
+                       return ret;
+       }
+
+       id = pdev->id;
+       bank = &gpio_bank[id];
+
+       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (unlikely(!res)) {
+               dev_err(&pdev->dev, "GPIO Bank %i Invalid IRQ resource\n", id);
+               return -ENODEV;
+       }
+
+       bank->irq = res->start;
+       bank->virtual_irq_start = pdata->virtual_irq_start;
+       bank->method = pdata->bank_type;
+       bank->dev = &pdev->dev;
+       bank->dbck_flag = pdata->dbck_flag;
+       bank->stride = pdata->bank_stride;
+       bank_width = pdata->bank_width;
+
+       spin_lock_init(&bank->lock);
+
+       /* Static mapping, never released */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (unlikely(!res)) {
+               dev_err(&pdev->dev, "GPIO Bank %i Invalid mem resource\n", id);
+               return -ENODEV;
+       }
+
+       bank->base = ioremap(res->start, resource_size(res));
+       if (!bank->base) {
+               dev_err(&pdev->dev, "Could not ioremap gpio bank%i\n", id);
+               return -ENOMEM;
+       }
+
+       pm_runtime_enable(bank->dev);
+       pm_runtime_get_sync(bank->dev);
+
+       omap_gpio_mod_init(bank, id);
+       omap_gpio_chip_init(bank);
+       omap_gpio_show_rev(bank);
+
+       if (!gpio_init_done)
+               gpio_init_done = 1;
+
+       return 0;
+}
+
+#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS)
+static int omap_gpio_suspend(void)
+{
+       int i;
+
+       if (!cpu_class_is_omap2() && !cpu_is_omap16xx())
+               return 0;
+
+       for (i = 0; i < gpio_bank_count; i++) {
+               struct gpio_bank *bank = &gpio_bank[i];
+               void __iomem *wake_status;
+               void __iomem *wake_clear;
+               void __iomem *wake_set;
+               unsigned long flags;
+
+               switch (bank->method) {
+#ifdef CONFIG_ARCH_OMAP16XX
+               case METHOD_GPIO_1610:
+                       wake_status = bank->base + OMAP1610_GPIO_WAKEUPENABLE;
+                       wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
+                       wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
+                       break;
+#endif
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+               case METHOD_GPIO_24XX:
+                       wake_status = bank->base + OMAP24XX_GPIO_WAKE_EN;
+                       wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
+                       wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA;
+                       break;
+#endif
+#ifdef CONFIG_ARCH_OMAP4
+               case METHOD_GPIO_44XX:
+                       wake_status = bank->base + OMAP4_GPIO_IRQWAKEN0;
+                       wake_clear = bank->base + OMAP4_GPIO_IRQWAKEN0;
+                       wake_set = bank->base + OMAP4_GPIO_IRQWAKEN0;
+                       break;
+#endif
+               default:
+                       continue;
+               }
+
+               spin_lock_irqsave(&bank->lock, flags);
+               bank->saved_wakeup = __raw_readl(wake_status);
+               __raw_writel(0xffffffff, wake_clear);
+               __raw_writel(bank->suspend_wakeup, wake_set);
+               spin_unlock_irqrestore(&bank->lock, flags);
+       }
+
+       return 0;
+}
+
+static void omap_gpio_resume(void)
+{
+       int i;
+
+       if (!cpu_class_is_omap2() && !cpu_is_omap16xx())
+               return;
+
+       for (i = 0; i < gpio_bank_count; i++) {
+               struct gpio_bank *bank = &gpio_bank[i];
+               void __iomem *wake_clear;
+               void __iomem *wake_set;
+               unsigned long flags;
+
+               switch (bank->method) {
+#ifdef CONFIG_ARCH_OMAP16XX
+               case METHOD_GPIO_1610:
+                       wake_clear = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA;
+                       wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA;
+                       break;
+#endif
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+               case METHOD_GPIO_24XX:
+                       wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA;
+                       wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA;
+                       break;
+#endif
+#ifdef CONFIG_ARCH_OMAP4
+               case METHOD_GPIO_44XX:
+                       wake_clear = bank->base + OMAP4_GPIO_IRQWAKEN0;
+                       wake_set = bank->base + OMAP4_GPIO_IRQWAKEN0;
+                       break;
+#endif
+               default:
+                       continue;
+               }
+
+               spin_lock_irqsave(&bank->lock, flags);
+               __raw_writel(0xffffffff, wake_clear);
+               __raw_writel(bank->saved_wakeup, wake_set);
+               spin_unlock_irqrestore(&bank->lock, flags);
+       }
+}
+
+static struct syscore_ops omap_gpio_syscore_ops = {
+       .suspend        = omap_gpio_suspend,
+       .resume         = omap_gpio_resume,
+};
+
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2PLUS
+
+static int workaround_enabled;
+
+void omap2_gpio_prepare_for_idle(int off_mode)
+{
+       int i, c = 0;
+       int min = 0;
+
+       if (cpu_is_omap34xx())
+               min = 1;
+
+       for (i = min; i < gpio_bank_count; i++) {
+               struct gpio_bank *bank = &gpio_bank[i];
+               u32 l1 = 0, l2 = 0;
+               int j;
+
+               for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
+                       clk_disable(bank->dbck);
+
+               if (!off_mode)
+                       continue;
+
+               /* If going to OFF, remove triggering for all
+                * non-wakeup GPIOs.  Otherwise spurious IRQs will be
+                * generated.  See OMAP2420 Errata item 1.101. */
+               if (!(bank->enabled_non_wakeup_gpios))
+                       continue;
+
+               if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
+                       bank->saved_datain = __raw_readl(bank->base +
+                                       OMAP24XX_GPIO_DATAIN);
+                       l1 = __raw_readl(bank->base +
+                                       OMAP24XX_GPIO_FALLINGDETECT);
+                       l2 = __raw_readl(bank->base +
+                                       OMAP24XX_GPIO_RISINGDETECT);
+               }
+
+               if (cpu_is_omap44xx()) {
+                       bank->saved_datain = __raw_readl(bank->base +
+                                               OMAP4_GPIO_DATAIN);
+                       l1 = __raw_readl(bank->base +
+                                               OMAP4_GPIO_FALLINGDETECT);
+                       l2 = __raw_readl(bank->base +
+                                               OMAP4_GPIO_RISINGDETECT);
+               }
+
+               bank->saved_fallingdetect = l1;
+               bank->saved_risingdetect = l2;
+               l1 &= ~bank->enabled_non_wakeup_gpios;
+               l2 &= ~bank->enabled_non_wakeup_gpios;
+
+               if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
+                       __raw_writel(l1, bank->base +
+                                       OMAP24XX_GPIO_FALLINGDETECT);
+                       __raw_writel(l2, bank->base +
+                                       OMAP24XX_GPIO_RISINGDETECT);
+               }
+
+               if (cpu_is_omap44xx()) {
+                       __raw_writel(l1, bank->base + OMAP4_GPIO_FALLINGDETECT);
+                       __raw_writel(l2, bank->base + OMAP4_GPIO_RISINGDETECT);
+               }
+
+               c++;
+       }
+       if (!c) {
+               workaround_enabled = 0;
+               return;
+       }
+       workaround_enabled = 1;
+}
+
+void omap2_gpio_resume_after_idle(void)
+{
+       int i;
+       int min = 0;
+
+       if (cpu_is_omap34xx())
+               min = 1;
+       for (i = min; i < gpio_bank_count; i++) {
+               struct gpio_bank *bank = &gpio_bank[i];
+               u32 l = 0, gen, gen0, gen1;
+               int j;
+
+               for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
+                       clk_enable(bank->dbck);
+
+               if (!workaround_enabled)
+                       continue;
+
+               if (!(bank->enabled_non_wakeup_gpios))
+                       continue;
+
+               if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
+                       __raw_writel(bank->saved_fallingdetect,
+                                bank->base + OMAP24XX_GPIO_FALLINGDETECT);
+                       __raw_writel(bank->saved_risingdetect,
+                                bank->base + OMAP24XX_GPIO_RISINGDETECT);
+                       l = __raw_readl(bank->base + OMAP24XX_GPIO_DATAIN);
+               }
+
+               if (cpu_is_omap44xx()) {
+                       __raw_writel(bank->saved_fallingdetect,
+                                bank->base + OMAP4_GPIO_FALLINGDETECT);
+                       __raw_writel(bank->saved_risingdetect,
+                                bank->base + OMAP4_GPIO_RISINGDETECT);
+                       l = __raw_readl(bank->base + OMAP4_GPIO_DATAIN);
+               }
+
+               /* Check if any of the non-wakeup interrupt GPIOs have changed
+                * state.  If so, generate an IRQ by software.  This is
+                * horribly racy, but it's the best we can do to work around
+                * this silicon bug. */
+               l ^= bank->saved_datain;
+               l &= bank->enabled_non_wakeup_gpios;
+
+               /*
+                * No need to generate IRQs for the rising edge for gpio IRQs
+                * configured with falling edge only; and vice versa.
+                */
+               gen0 = l & bank->saved_fallingdetect;
+               gen0 &= bank->saved_datain;
+
+               gen1 = l & bank->saved_risingdetect;
+               gen1 &= ~(bank->saved_datain);
+
+               /* FIXME: Consider GPIO IRQs with level detections properly! */
+               gen = l & (~(bank->saved_fallingdetect) &
+                               ~(bank->saved_risingdetect));
+               /* Consider all GPIO IRQs needed to be updated */
+               gen |= gen0 | gen1;
+
+               if (gen) {
+                       u32 old0, old1;
+
+                       if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
+                               old0 = __raw_readl(bank->base +
+                                       OMAP24XX_GPIO_LEVELDETECT0);
+                               old1 = __raw_readl(bank->base +
+                                       OMAP24XX_GPIO_LEVELDETECT1);
+                               __raw_writel(old0 | gen, bank->base +
+                                       OMAP24XX_GPIO_LEVELDETECT0);
+                               __raw_writel(old1 | gen, bank->base +
+                                       OMAP24XX_GPIO_LEVELDETECT1);
+                               __raw_writel(old0, bank->base +
+                                       OMAP24XX_GPIO_LEVELDETECT0);
+                               __raw_writel(old1, bank->base +
+                                       OMAP24XX_GPIO_LEVELDETECT1);
+                       }
+
+                       if (cpu_is_omap44xx()) {
+                               old0 = __raw_readl(bank->base +
+                                               OMAP4_GPIO_LEVELDETECT0);
+                               old1 = __raw_readl(bank->base +
+                                               OMAP4_GPIO_LEVELDETECT1);
+                               __raw_writel(old0 | l, bank->base +
+                                               OMAP4_GPIO_LEVELDETECT0);
+                               __raw_writel(old1 | l, bank->base +
+                                               OMAP4_GPIO_LEVELDETECT1);
+                               __raw_writel(old0, bank->base +
+                                               OMAP4_GPIO_LEVELDETECT0);
+                               __raw_writel(old1, bank->base +
+                                               OMAP4_GPIO_LEVELDETECT1);
+                       }
+               }
+       }
+
+}
+
+#endif
+
+#ifdef CONFIG_ARCH_OMAP3
+/* save the registers of bank 2-6 */
+void omap_gpio_save_context(void)
+{
+       int i;
+
+       /* saving banks from 2-6 only since GPIO1 is in WKUP */
+       for (i = 1; i < gpio_bank_count; i++) {
+               struct gpio_bank *bank = &gpio_bank[i];
+               gpio_context[i].irqenable1 =
+                       __raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE1);
+               gpio_context[i].irqenable2 =
+                       __raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE2);
+               gpio_context[i].wake_en =
+                       __raw_readl(bank->base + OMAP24XX_GPIO_WAKE_EN);
+               gpio_context[i].ctrl =
+                       __raw_readl(bank->base + OMAP24XX_GPIO_CTRL);
+               gpio_context[i].oe =
+                       __raw_readl(bank->base + OMAP24XX_GPIO_OE);
+               gpio_context[i].leveldetect0 =
+                       __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0);
+               gpio_context[i].leveldetect1 =
+                       __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1);
+               gpio_context[i].risingdetect =
+                       __raw_readl(bank->base + OMAP24XX_GPIO_RISINGDETECT);
+               gpio_context[i].fallingdetect =
+                       __raw_readl(bank->base + OMAP24XX_GPIO_FALLINGDETECT);
+               gpio_context[i].dataout =
+                       __raw_readl(bank->base + OMAP24XX_GPIO_DATAOUT);
+       }
+}
+
+/* restore the required registers of bank 2-6 */
+void omap_gpio_restore_context(void)
+{
+       int i;
+
+       for (i = 1; i < gpio_bank_count; i++) {
+               struct gpio_bank *bank = &gpio_bank[i];
+               __raw_writel(gpio_context[i].irqenable1,
+                               bank->base + OMAP24XX_GPIO_IRQENABLE1);
+               __raw_writel(gpio_context[i].irqenable2,
+                               bank->base + OMAP24XX_GPIO_IRQENABLE2);
+               __raw_writel(gpio_context[i].wake_en,
+                               bank->base + OMAP24XX_GPIO_WAKE_EN);
+               __raw_writel(gpio_context[i].ctrl,
+                               bank->base + OMAP24XX_GPIO_CTRL);
+               __raw_writel(gpio_context[i].oe,
+                               bank->base + OMAP24XX_GPIO_OE);
+               __raw_writel(gpio_context[i].leveldetect0,
+                               bank->base + OMAP24XX_GPIO_LEVELDETECT0);
+               __raw_writel(gpio_context[i].leveldetect1,
+                               bank->base + OMAP24XX_GPIO_LEVELDETECT1);
+               __raw_writel(gpio_context[i].risingdetect,
+                               bank->base + OMAP24XX_GPIO_RISINGDETECT);
+               __raw_writel(gpio_context[i].fallingdetect,
+                               bank->base + OMAP24XX_GPIO_FALLINGDETECT);
+               __raw_writel(gpio_context[i].dataout,
+                               bank->base + OMAP24XX_GPIO_DATAOUT);
+       }
+}
+#endif
+
+static struct platform_driver omap_gpio_driver = {
+       .probe          = omap_gpio_probe,
+       .driver         = {
+               .name   = "omap_gpio",
+       },
+};
+
+/*
+ * gpio driver register needs to be done before
+ * machine_init functions access gpio APIs.
+ * Hence omap_gpio_drv_reg() is a postcore_initcall.
+ */
+static int __init omap_gpio_drv_reg(void)
+{
+       return platform_driver_register(&omap_gpio_driver);
+}
+postcore_initcall(omap_gpio_drv_reg);
+
+static int __init omap_gpio_sysinit(void)
+{
+       mpuio_init();
+
+#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS)
+       if (cpu_is_omap16xx() || cpu_class_is_omap2())
+               register_syscore_ops(&omap_gpio_syscore_ops);
+#endif
+
+       return 0;
+}
+
+arch_initcall(omap_gpio_sysinit);
diff --git a/drivers/gpio/gpio-plat-samsung.c b/drivers/gpio/gpio-plat-samsung.c
new file mode 100644 (file)
index 0000000..ea37c04
--- /dev/null
@@ -0,0 +1,206 @@
+/* arch/arm/plat-samsung/gpiolib.c
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * SAMSUNG - GPIOlib support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <plat/gpio-core.h>
+#include <plat/gpio-cfg.h>
+#include <plat/gpio-cfg-helpers.h>
+
+#ifndef DEBUG_GPIO
+#define gpio_dbg(x...) do { } while (0)
+#else
+#define gpio_dbg(x...) printk(KERN_DEBUG x)
+#endif
+
+/* The samsung_gpiolib_4bit routines are to control the gpio banks where
+ * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the
+ * following example:
+ *
+ * base + 0x00: Control register, 4 bits per gpio
+ *             gpio n: 4 bits starting at (4*n)
+ *             0000 = input, 0001 = output, others mean special-function
+ * base + 0x04: Data register, 1 bit per gpio
+ *             bit n: data bit n
+ *
+ * Note, since the data register is one bit per gpio and is at base + 0x4
+ * we can use s3c_gpiolib_get and s3c_gpiolib_set to change the state of
+ * the output.
+*/
+
+static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
+                                     unsigned int offset)
+{
+       struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
+       void __iomem *base = ourchip->base;
+       unsigned long con;
+
+       con = __raw_readl(base + GPIOCON_OFF);
+       con &= ~(0xf << con_4bit_shift(offset));
+       __raw_writel(con, base + GPIOCON_OFF);
+
+       gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con);
+
+       return 0;
+}
+
+static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
+                                      unsigned int offset, int value)
+{
+       struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
+       void __iomem *base = ourchip->base;
+       unsigned long con;
+       unsigned long dat;
+
+       con = __raw_readl(base + GPIOCON_OFF);
+       con &= ~(0xf << con_4bit_shift(offset));
+       con |= 0x1 << con_4bit_shift(offset);
+
+       dat = __raw_readl(base + GPIODAT_OFF);
+
+       if (value)
+               dat |= 1 << offset;
+       else
+               dat &= ~(1 << offset);
+
+       __raw_writel(dat, base + GPIODAT_OFF);
+       __raw_writel(con, base + GPIOCON_OFF);
+       __raw_writel(dat, base + GPIODAT_OFF);
+
+       gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
+
+       return 0;
+}
+
+/* The next set of routines are for the case where the GPIO configuration
+ * registers are 4 bits per GPIO but there is more than one register (the
+ * bank has more than 8 GPIOs.
+ *
+ * This case is the similar to the 4 bit case, but the registers are as
+ * follows:
+ *
+ * base + 0x00: Control register, 4 bits per gpio (lower 8 GPIOs)
+ *             gpio n: 4 bits starting at (4*n)
+ *             0000 = input, 0001 = output, others mean special-function
+ * base + 0x04: Control register, 4 bits per gpio (up to 8 additions GPIOs)
+ *             gpio n: 4 bits starting at (4*n)
+ *             0000 = input, 0001 = output, others mean special-function
+ * base + 0x08: Data register, 1 bit per gpio
+ *             bit n: data bit n
+ *
+ * To allow us to use the s3c_gpiolib_get and s3c_gpiolib_set routines we
+ * store the 'base + 0x4' address so that these routines see the data
+ * register at ourchip->base + 0x04.
+ */
+
+static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
+                                      unsigned int offset)
+{
+       struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
+       void __iomem *base = ourchip->base;
+       void __iomem *regcon = base;
+       unsigned long con;
+
+       if (offset > 7)
+               offset -= 8;
+       else
+               regcon -= 4;
+
+       con = __raw_readl(regcon);
+       con &= ~(0xf << con_4bit_shift(offset));
+       __raw_writel(con, regcon);
+
+       gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con);
+
+       return 0;
+}
+
+static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
+                                       unsigned int offset, int value)
+{
+       struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip);
+       void __iomem *base = ourchip->base;
+       void __iomem *regcon = base;
+       unsigned long con;
+       unsigned long dat;
+       unsigned con_offset = offset;
+
+       if (con_offset > 7)
+               con_offset -= 8;
+       else
+               regcon -= 4;
+
+       con = __raw_readl(regcon);
+       con &= ~(0xf << con_4bit_shift(con_offset));
+       con |= 0x1 << con_4bit_shift(con_offset);
+
+       dat = __raw_readl(base + GPIODAT_OFF);
+
+       if (value)
+               dat |= 1 << offset;
+       else
+               dat &= ~(1 << offset);
+
+       __raw_writel(dat, base + GPIODAT_OFF);
+       __raw_writel(con, regcon);
+       __raw_writel(dat, base + GPIODAT_OFF);
+
+       gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
+
+       return 0;
+}
+
+void __init samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip)
+{
+       chip->chip.direction_input = samsung_gpiolib_4bit_input;
+       chip->chip.direction_output = samsung_gpiolib_4bit_output;
+       chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
+}
+
+void __init samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip)
+{
+       chip->chip.direction_input = samsung_gpiolib_4bit2_input;
+       chip->chip.direction_output = samsung_gpiolib_4bit2_output;
+       chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
+}
+
+void __init samsung_gpiolib_add_4bit_chips(struct s3c_gpio_chip *chip,
+                                          int nr_chips)
+{
+       for (; nr_chips > 0; nr_chips--, chip++) {
+               samsung_gpiolib_add_4bit(chip);
+               s3c_gpiolib_add(chip);
+       }
+}
+
+void __init samsung_gpiolib_add_4bit2_chips(struct s3c_gpio_chip *chip,
+                                           int nr_chips)
+{
+       for (; nr_chips > 0; nr_chips--, chip++) {
+               samsung_gpiolib_add_4bit2(chip);
+               s3c_gpiolib_add(chip);
+       }
+}
+
+void __init samsung_gpiolib_add_2bit_chips(struct s3c_gpio_chip *chip,
+                                          int nr_chips)
+{
+       for (; nr_chips > 0; nr_chips--, chip++)
+               s3c_gpiolib_add(chip);
+}
diff --git a/drivers/gpio/gpio-s5pc100.c b/drivers/gpio/gpio-s5pc100.c
new file mode 100644 (file)
index 0000000..2842394
--- /dev/null
@@ -0,0 +1,355 @@
+/* linux/arch/arm/mach-s5pc100/gpiolib.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ *  Copyright 2009 Samsung Electronics Co
+ *  Kyungmin Park <kyungmin.park@samsung.com>
+ *
+ * S5PC100 - GPIOlib support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+
+#include <mach/map.h>
+#include <mach/regs-gpio.h>
+
+#include <plat/gpio-core.h>
+#include <plat/gpio-cfg.h>
+#include <plat/gpio-cfg-helpers.h>
+
+/* S5PC100 GPIO bank summary:
+ *
+ * Bank        GPIOs   Style   INT Type
+ * A0  8       4Bit    GPIO_INT0
+ * A1  5       4Bit    GPIO_INT1
+ * B   8       4Bit    GPIO_INT2
+ * C   5       4Bit    GPIO_INT3
+ * D   7       4Bit    GPIO_INT4
+ * E0  8       4Bit    GPIO_INT5
+ * E1  6       4Bit    GPIO_INT6
+ * F0  8       4Bit    GPIO_INT7
+ * F1  8       4Bit    GPIO_INT8
+ * F2  8       4Bit    GPIO_INT9
+ * F3  4       4Bit    GPIO_INT10
+ * G0  8       4Bit    GPIO_INT11
+ * G1  3       4Bit    GPIO_INT12
+ * G2  7       4Bit    GPIO_INT13
+ * G3  7       4Bit    GPIO_INT14
+ * H0  8       4Bit    WKUP_INT
+ * H1  8       4Bit    WKUP_INT
+ * H2  8       4Bit    WKUP_INT
+ * H3  8       4Bit    WKUP_INT
+ * I   8       4Bit    GPIO_INT15
+ * J0  8       4Bit    GPIO_INT16
+ * J1  5       4Bit    GPIO_INT17
+ * J2  8       4Bit    GPIO_INT18
+ * J3  8       4Bit    GPIO_INT19
+ * J4  4       4Bit    GPIO_INT20
+ * K0  8       4Bit    None
+ * K1  6       4Bit    None
+ * K2  8       4Bit    None
+ * K3  8       4Bit    None
+ * L0  8       4Bit    None
+ * L1  8       4Bit    None
+ * L2  8       4Bit    None
+ * L3  8       4Bit    None
+ */
+
+static struct s3c_gpio_cfg gpio_cfg = {
+       .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
+       .set_pull       = s3c_gpio_setpull_updown,
+       .get_pull       = s3c_gpio_getpull_updown,
+};
+
+static struct s3c_gpio_cfg gpio_cfg_eint = {
+       .cfg_eint       = 0xf,
+       .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
+       .set_pull       = s3c_gpio_setpull_updown,
+       .get_pull       = s3c_gpio_getpull_updown,
+};
+
+static struct s3c_gpio_cfg gpio_cfg_noint = {
+       .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
+       .set_pull       = s3c_gpio_setpull_updown,
+       .get_pull       = s3c_gpio_getpull_updown,
+};
+
+/*
+ * GPIO bank's base address given the index of the bank in the
+ * list of all gpio banks.
+ */
+#define S5PC100_BANK_BASE(bank_nr)     (S5P_VA_GPIO + ((bank_nr) * 0x20))
+
+/*
+ * Following are the gpio banks in S5PC100.
+ *
+ * The 'config' member when left to NULL, is initialized to the default
+ * structure gpio_cfg in the init function below.
+ *
+ * The 'base' member is also initialized in the init function below.
+ * Note: The initialization of 'base' member of s3c_gpio_chip structure
+ * uses the above macro and depends on the banks being listed in order here.
+ */
+static struct s3c_gpio_chip s5pc100_gpio_chips[] = {
+       {
+               .chip   = {
+                       .base   = S5PC100_GPA0(0),
+                       .ngpio  = S5PC100_GPIO_A0_NR,
+                       .label  = "GPA0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPA1(0),
+                       .ngpio  = S5PC100_GPIO_A1_NR,
+                       .label  = "GPA1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPB(0),
+                       .ngpio  = S5PC100_GPIO_B_NR,
+                       .label  = "GPB",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPC(0),
+                       .ngpio  = S5PC100_GPIO_C_NR,
+                       .label  = "GPC",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPD(0),
+                       .ngpio  = S5PC100_GPIO_D_NR,
+                       .label  = "GPD",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPE0(0),
+                       .ngpio  = S5PC100_GPIO_E0_NR,
+                       .label  = "GPE0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPE1(0),
+                       .ngpio  = S5PC100_GPIO_E1_NR,
+                       .label  = "GPE1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPF0(0),
+                       .ngpio  = S5PC100_GPIO_F0_NR,
+                       .label  = "GPF0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPF1(0),
+                       .ngpio  = S5PC100_GPIO_F1_NR,
+                       .label  = "GPF1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPF2(0),
+                       .ngpio  = S5PC100_GPIO_F2_NR,
+                       .label  = "GPF2",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPF3(0),
+                       .ngpio  = S5PC100_GPIO_F3_NR,
+                       .label  = "GPF3",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPG0(0),
+                       .ngpio  = S5PC100_GPIO_G0_NR,
+                       .label  = "GPG0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPG1(0),
+                       .ngpio  = S5PC100_GPIO_G1_NR,
+                       .label  = "GPG1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPG2(0),
+                       .ngpio  = S5PC100_GPIO_G2_NR,
+                       .label  = "GPG2",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPG3(0),
+                       .ngpio  = S5PC100_GPIO_G3_NR,
+                       .label  = "GPG3",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPI(0),
+                       .ngpio  = S5PC100_GPIO_I_NR,
+                       .label  = "GPI",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPJ0(0),
+                       .ngpio  = S5PC100_GPIO_J0_NR,
+                       .label  = "GPJ0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPJ1(0),
+                       .ngpio  = S5PC100_GPIO_J1_NR,
+                       .label  = "GPJ1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPJ2(0),
+                       .ngpio  = S5PC100_GPIO_J2_NR,
+                       .label  = "GPJ2",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPJ3(0),
+                       .ngpio  = S5PC100_GPIO_J3_NR,
+                       .label  = "GPJ3",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PC100_GPJ4(0),
+                       .ngpio  = S5PC100_GPIO_J4_NR,
+                       .label  = "GPJ4",
+               },
+       }, {
+               .config = &gpio_cfg_noint,
+               .chip   = {
+                       .base   = S5PC100_GPK0(0),
+                       .ngpio  = S5PC100_GPIO_K0_NR,
+                       .label  = "GPK0",
+               },
+       }, {
+               .config = &gpio_cfg_noint,
+               .chip   = {
+                       .base   = S5PC100_GPK1(0),
+                       .ngpio  = S5PC100_GPIO_K1_NR,
+                       .label  = "GPK1",
+               },
+       }, {
+               .config = &gpio_cfg_noint,
+               .chip   = {
+                       .base   = S5PC100_GPK2(0),
+                       .ngpio  = S5PC100_GPIO_K2_NR,
+                       .label  = "GPK2",
+               },
+       }, {
+               .config = &gpio_cfg_noint,
+               .chip   = {
+                       .base   = S5PC100_GPK3(0),
+                       .ngpio  = S5PC100_GPIO_K3_NR,
+                       .label  = "GPK3",
+               },
+       }, {
+               .config = &gpio_cfg_noint,
+               .chip   = {
+                       .base   = S5PC100_GPL0(0),
+                       .ngpio  = S5PC100_GPIO_L0_NR,
+                       .label  = "GPL0",
+               },
+       }, {
+               .config = &gpio_cfg_noint,
+               .chip   = {
+                       .base   = S5PC100_GPL1(0),
+                       .ngpio  = S5PC100_GPIO_L1_NR,
+                       .label  = "GPL1",
+               },
+       }, {
+               .config = &gpio_cfg_noint,
+               .chip   = {
+                       .base   = S5PC100_GPL2(0),
+                       .ngpio  = S5PC100_GPIO_L2_NR,
+                       .label  = "GPL2",
+               },
+       }, {
+               .config = &gpio_cfg_noint,
+               .chip   = {
+                       .base   = S5PC100_GPL3(0),
+                       .ngpio  = S5PC100_GPIO_L3_NR,
+                       .label  = "GPL3",
+               },
+       }, {
+               .config = &gpio_cfg_noint,
+               .chip   = {
+                       .base   = S5PC100_GPL4(0),
+                       .ngpio  = S5PC100_GPIO_L4_NR,
+                       .label  = "GPL4",
+               },
+       }, {
+               .base   = (S5P_VA_GPIO + 0xC00),
+               .config = &gpio_cfg_eint,
+               .irq_base = IRQ_EINT(0),
+               .chip   = {
+                       .base   = S5PC100_GPH0(0),
+                       .ngpio  = S5PC100_GPIO_H0_NR,
+                       .label  = "GPH0",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       }, {
+               .base   = (S5P_VA_GPIO + 0xC20),
+               .config = &gpio_cfg_eint,
+               .irq_base = IRQ_EINT(8),
+               .chip   = {
+                       .base   = S5PC100_GPH1(0),
+                       .ngpio  = S5PC100_GPIO_H1_NR,
+                       .label  = "GPH1",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       }, {
+               .base   = (S5P_VA_GPIO + 0xC40),
+               .config = &gpio_cfg_eint,
+               .irq_base = IRQ_EINT(16),
+               .chip   = {
+                       .base   = S5PC100_GPH2(0),
+                       .ngpio  = S5PC100_GPIO_H2_NR,
+                       .label  = "GPH2",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       }, {
+               .base   = (S5P_VA_GPIO + 0xC60),
+               .config = &gpio_cfg_eint,
+               .irq_base = IRQ_EINT(24),
+               .chip   = {
+                       .base   = S5PC100_GPH3(0),
+                       .ngpio  = S5PC100_GPIO_H3_NR,
+                       .label  = "GPH3",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       },
+};
+
+static __init int s5pc100_gpiolib_init(void)
+{
+       struct s3c_gpio_chip *chip = s5pc100_gpio_chips;
+       int nr_chips = ARRAY_SIZE(s5pc100_gpio_chips);
+       int gpioint_group = 0;
+       int i;
+
+       for (i = 0; i < nr_chips; i++, chip++) {
+               if (chip->config == NULL) {
+                       chip->config = &gpio_cfg;
+                       chip->group = gpioint_group++;
+               }
+               if (chip->base == NULL)
+                       chip->base = S5PC100_BANK_BASE(i);
+       }
+
+       samsung_gpiolib_add_4bit_chips(s5pc100_gpio_chips, nr_chips);
+       s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
+
+       return 0;
+}
+core_initcall(s5pc100_gpiolib_init);
diff --git a/drivers/gpio/gpio-s5pv210.c b/drivers/gpio/gpio-s5pv210.c
new file mode 100644 (file)
index 0000000..1ba20a7
--- /dev/null
@@ -0,0 +1,288 @@
+/* linux/arch/arm/mach-s5pv210/gpiolib.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * S5PV210 - GPIOlib support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <plat/gpio-core.h>
+#include <plat/gpio-cfg.h>
+#include <plat/gpio-cfg-helpers.h>
+#include <mach/map.h>
+
+static struct s3c_gpio_cfg gpio_cfg = {
+       .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
+       .set_pull       = s3c_gpio_setpull_updown,
+       .get_pull       = s3c_gpio_getpull_updown,
+};
+
+static struct s3c_gpio_cfg gpio_cfg_noint = {
+       .set_config     = s3c_gpio_setcfg_s3c64xx_4bit,
+       .set_pull       = s3c_gpio_setpull_updown,
+       .get_pull       = s3c_gpio_getpull_updown,
+};
+
+/* GPIO bank's base address given the index of the bank in the
+ * list of all gpio banks.
+ */
+#define S5PV210_BANK_BASE(bank_nr)     (S5P_VA_GPIO + ((bank_nr) * 0x20))
+
+/*
+ * Following are the gpio banks in v210.
+ *
+ * The 'config' member when left to NULL, is initialized to the default
+ * structure gpio_cfg in the init function below.
+ *
+ * The 'base' member is also initialized in the init function below.
+ * Note: The initialization of 'base' member of s3c_gpio_chip structure
+ * uses the above macro and depends on the banks being listed in order here.
+ */
+static struct s3c_gpio_chip s5pv210_gpio_4bit[] = {
+       {
+               .chip   = {
+                       .base   = S5PV210_GPA0(0),
+                       .ngpio  = S5PV210_GPIO_A0_NR,
+                       .label  = "GPA0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPA1(0),
+                       .ngpio  = S5PV210_GPIO_A1_NR,
+                       .label  = "GPA1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPB(0),
+                       .ngpio  = S5PV210_GPIO_B_NR,
+                       .label  = "GPB",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPC0(0),
+                       .ngpio  = S5PV210_GPIO_C0_NR,
+                       .label  = "GPC0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPC1(0),
+                       .ngpio  = S5PV210_GPIO_C1_NR,
+                       .label  = "GPC1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPD0(0),
+                       .ngpio  = S5PV210_GPIO_D0_NR,
+                       .label  = "GPD0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPD1(0),
+                       .ngpio  = S5PV210_GPIO_D1_NR,
+                       .label  = "GPD1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPE0(0),
+                       .ngpio  = S5PV210_GPIO_E0_NR,
+                       .label  = "GPE0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPE1(0),
+                       .ngpio  = S5PV210_GPIO_E1_NR,
+                       .label  = "GPE1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPF0(0),
+                       .ngpio  = S5PV210_GPIO_F0_NR,
+                       .label  = "GPF0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPF1(0),
+                       .ngpio  = S5PV210_GPIO_F1_NR,
+                       .label  = "GPF1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPF2(0),
+                       .ngpio  = S5PV210_GPIO_F2_NR,
+                       .label  = "GPF2",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPF3(0),
+                       .ngpio  = S5PV210_GPIO_F3_NR,
+                       .label  = "GPF3",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPG0(0),
+                       .ngpio  = S5PV210_GPIO_G0_NR,
+                       .label  = "GPG0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPG1(0),
+                       .ngpio  = S5PV210_GPIO_G1_NR,
+                       .label  = "GPG1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPG2(0),
+                       .ngpio  = S5PV210_GPIO_G2_NR,
+                       .label  = "GPG2",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPG3(0),
+                       .ngpio  = S5PV210_GPIO_G3_NR,
+                       .label  = "GPG3",
+               },
+       }, {
+               .config = &gpio_cfg_noint,
+               .chip   = {
+                       .base   = S5PV210_GPI(0),
+                       .ngpio  = S5PV210_GPIO_I_NR,
+                       .label  = "GPI",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPJ0(0),
+                       .ngpio  = S5PV210_GPIO_J0_NR,
+                       .label  = "GPJ0",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPJ1(0),
+                       .ngpio  = S5PV210_GPIO_J1_NR,
+                       .label  = "GPJ1",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPJ2(0),
+                       .ngpio  = S5PV210_GPIO_J2_NR,
+                       .label  = "GPJ2",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPJ3(0),
+                       .ngpio  = S5PV210_GPIO_J3_NR,
+                       .label  = "GPJ3",
+               },
+       }, {
+               .chip   = {
+                       .base   = S5PV210_GPJ4(0),
+                       .ngpio  = S5PV210_GPIO_J4_NR,
+                       .label  = "GPJ4",
+               },
+       }, {
+               .config = &gpio_cfg_noint,
+               .chip   = {
+                       .base   = S5PV210_MP01(0),
+                       .ngpio  = S5PV210_GPIO_MP01_NR,
+                       .label  = "MP01",
+               },
+       }, {
+               .config = &gpio_cfg_noint,
+               .chip   = {
+                       .base   = S5PV210_MP02(0),
+                       .ngpio  = S5PV210_GPIO_MP02_NR,
+                       .label  = "MP02",
+               },
+       }, {
+               .config = &gpio_cfg_noint,
+               .chip   = {
+                       .base   = S5PV210_MP03(0),
+                       .ngpio  = S5PV210_GPIO_MP03_NR,
+                       .label  = "MP03",
+               },
+       }, {
+               .config = &gpio_cfg_noint,
+               .chip   = {
+                       .base   = S5PV210_MP04(0),
+                       .ngpio  = S5PV210_GPIO_MP04_NR,
+                       .label  = "MP04",
+               },
+       }, {
+               .config = &gpio_cfg_noint,
+               .chip   = {
+                       .base   = S5PV210_MP05(0),
+                       .ngpio  = S5PV210_GPIO_MP05_NR,
+                       .label  = "MP05",
+               },
+       }, {
+               .base   = (S5P_VA_GPIO + 0xC00),
+               .config = &gpio_cfg_noint,
+               .irq_base = IRQ_EINT(0),
+               .chip   = {
+                       .base   = S5PV210_GPH0(0),
+                       .ngpio  = S5PV210_GPIO_H0_NR,
+                       .label  = "GPH0",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       }, {
+               .base   = (S5P_VA_GPIO + 0xC20),
+               .config = &gpio_cfg_noint,
+               .irq_base = IRQ_EINT(8),
+               .chip   = {
+                       .base   = S5PV210_GPH1(0),
+                       .ngpio  = S5PV210_GPIO_H1_NR,
+                       .label  = "GPH1",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       }, {
+               .base   = (S5P_VA_GPIO + 0xC40),
+               .config = &gpio_cfg_noint,
+               .irq_base = IRQ_EINT(16),
+               .chip   = {
+                       .base   = S5PV210_GPH2(0),
+                       .ngpio  = S5PV210_GPIO_H2_NR,
+                       .label  = "GPH2",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       }, {
+               .base   = (S5P_VA_GPIO + 0xC60),
+               .config = &gpio_cfg_noint,
+               .irq_base = IRQ_EINT(24),
+               .chip   = {
+                       .base   = S5PV210_GPH3(0),
+                       .ngpio  = S5PV210_GPIO_H3_NR,
+                       .label  = "GPH3",
+                       .to_irq = samsung_gpiolib_to_irq,
+               },
+       },
+};
+
+static __init int s5pv210_gpiolib_init(void)
+{
+       struct s3c_gpio_chip *chip = s5pv210_gpio_4bit;
+       int nr_chips = ARRAY_SIZE(s5pv210_gpio_4bit);
+       int gpioint_group = 0;
+       int i = 0;
+
+       for (i = 0; i < nr_chips; i++, chip++) {
+               if (chip->config == NULL) {
+                       chip->config = &gpio_cfg;
+                       chip->group = gpioint_group++;
+               }
+               if (chip->base == NULL)
+                       chip->base = S5PV210_BANK_BASE(i);
+       }
+
+       samsung_gpiolib_add_4bit_chips(s5pv210_gpio_4bit, nr_chips);
+       s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
+
+       return 0;
+}
+core_initcall(s5pv210_gpiolib_init);
diff --git a/drivers/gpio/gpio-u300.c b/drivers/gpio/gpio-u300.c
new file mode 100644 (file)
index 0000000..d927901
--- /dev/null
@@ -0,0 +1,700 @@
+/*
+ *
+ * arch/arm/mach-u300/gpio.c
+ *
+ *
+ * Copyright (C) 2007-2009 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * U300 GPIO module.
+ * This can driver either of the two basic GPIO cores
+ * available in the U300 platforms:
+ * COH 901 335   - Used in DB3150 (U300 1.0) and DB3200 (U330 1.0)
+ * COH 901 571/3 - Used in DB3210 (U365 2.0) and DB3350 (U335 1.0)
+ * Notice that you also have inline macros in <asm-arch/gpio.h>
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
+ *
+ */
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+
+/* Reference to GPIO block clock */
+static struct clk *clk;
+
+/* Memory resource */
+static struct resource *memres;
+static void __iomem *virtbase;
+static struct device *gpiodev;
+
+struct u300_gpio_port {
+       const char *name;
+       int irq;
+       int number;
+};
+
+
+static struct u300_gpio_port gpio_ports[] = {
+       {
+               .name = "gpio0",
+               .number = 0,
+       },
+       {
+               .name = "gpio1",
+               .number = 1,
+       },
+       {
+               .name = "gpio2",
+               .number = 2,
+       },
+#ifdef U300_COH901571_3
+       {
+               .name = "gpio3",
+               .number = 3,
+       },
+       {
+               .name = "gpio4",
+               .number = 4,
+       },
+#ifdef CONFIG_MACH_U300_BS335
+       {
+               .name = "gpio5",
+               .number = 5,
+       },
+       {
+               .name = "gpio6",
+               .number = 6,
+       },
+#endif
+#endif
+
+};
+
+
+#ifdef U300_COH901571_3
+
+/* Default input value */
+#define DEFAULT_OUTPUT_LOW   0
+#define DEFAULT_OUTPUT_HIGH  1
+
+/* GPIO Pull-Up status */
+#define DISABLE_PULL_UP  0
+#define ENABLE_PULL_UP  1
+
+#define GPIO_NOT_USED 0
+#define GPIO_IN       1
+#define GPIO_OUT      2
+
+struct u300_gpio_configuration_data {
+       unsigned char pin_usage;
+       unsigned char default_output_value;
+       unsigned char pull_up;
+};
+
+/* Initial configuration */
+const struct u300_gpio_configuration_data
+u300_gpio_config[U300_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = {
+#ifdef CONFIG_MACH_U300_BS335
+       /* Port 0, pins 0-7 */
+       {
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_OUT, DEFAULT_OUTPUT_HIGH,  DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
+       },
+       /* Port 1, pins 0-7 */
+       {
+               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_OUT, DEFAULT_OUTPUT_HIGH,  DISABLE_PULL_UP},
+               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
+       },
+       /* Port 2, pins 0-7 */
+       {
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP}
+       },
+       /* Port 3, pins 0-7 */
+       {
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
+       },
+       /* Port 4, pins 0-7 */
+       {
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
+       },
+       /* Port 5, pins 0-7 */
+       {
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
+       },
+       /* Port 6, pind 0-7 */
+       {
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
+       }
+#endif
+
+#ifdef CONFIG_MACH_U300_BS365
+       /* Port 0, pins 0-7 */
+       {
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
+       },
+       /* Port 1, pins 0-7 */
+       {
+               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_OUT, DEFAULT_OUTPUT_HIGH,  DISABLE_PULL_UP},
+               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP}
+       },
+       /* Port 2, pins 0-7 */
+       {
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_OUT, DEFAULT_OUTPUT_LOW,   DISABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP}
+       },
+       /* Port 3, pins 0-7 */
+       {
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP}
+       },
+       /* Port 4, pins 0-7 */
+       {
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+               {GPIO_IN,  DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+               /* These 4 pins doesn't exist on DB3210 */
+               {GPIO_OUT, DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+               {GPIO_OUT, DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+               {GPIO_OUT, DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP},
+               {GPIO_OUT, DEFAULT_OUTPUT_LOW,    ENABLE_PULL_UP}
+       }
+#endif
+};
+#endif
+
+
+/* No users == we can power down GPIO */
+static int gpio_users;
+
+struct gpio_struct {
+       int (*callback)(void *);
+       void *data;
+       int users;
+};
+
+static struct gpio_struct gpio_pin[U300_GPIO_MAX];
+
+/*
+ * Let drivers register callback in order to get notified when there is
+ * an interrupt on the gpio pin
+ */
+int gpio_register_callback(unsigned gpio, int (*func)(void *arg), void *data)
+{
+       if (gpio_pin[gpio].callback)
+               dev_warn(gpiodev, "%s: WARNING: callback already "
+                        "registered for gpio pin#%d\n", __func__, gpio);
+       gpio_pin[gpio].callback = func;
+       gpio_pin[gpio].data = data;
+
+       return 0;
+}
+EXPORT_SYMBOL(gpio_register_callback);
+
+int gpio_unregister_callback(unsigned gpio)
+{
+       if (!gpio_pin[gpio].callback)
+               dev_warn(gpiodev, "%s: WARNING: callback already "
+                        "unregistered for gpio pin#%d\n", __func__, gpio);
+       gpio_pin[gpio].callback = NULL;
+       gpio_pin[gpio].data = NULL;
+
+       return 0;
+}
+EXPORT_SYMBOL(gpio_unregister_callback);
+
+/* Non-zero means valid */
+int gpio_is_valid(int number)
+{
+       if (number >= 0 &&
+           number < (U300_GPIO_NUM_PORTS * U300_GPIO_PINS_PER_PORT))
+               return 1;
+       return 0;
+}
+EXPORT_SYMBOL(gpio_is_valid);
+
+int gpio_request(unsigned gpio, const char *label)
+{
+       if (gpio_pin[gpio].users)
+               return -EINVAL;
+       else
+               gpio_pin[gpio].users++;
+
+       gpio_users++;
+
+       return 0;
+}
+EXPORT_SYMBOL(gpio_request);
+
+void gpio_free(unsigned gpio)
+{
+       gpio_users--;
+       gpio_pin[gpio].users--;
+       if (unlikely(gpio_pin[gpio].users < 0)) {
+               dev_warn(gpiodev, "warning: gpio#%d release mismatch\n",
+                        gpio);
+               gpio_pin[gpio].users = 0;
+       }
+
+       return;
+}
+EXPORT_SYMBOL(gpio_free);
+
+/* This returns zero or nonzero */
+int gpio_get_value(unsigned gpio)
+{
+       return readl(virtbase + U300_GPIO_PXPDIR +
+         PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING) & (1 << (gpio & 0x07));
+}
+EXPORT_SYMBOL(gpio_get_value);
+
+/*
+ * We hope that the compiler will optimize away the unused branch
+ * in case "value" is a constant
+ */
+void gpio_set_value(unsigned gpio, int value)
+{
+       u32 val;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       if (value) {
+               /* set */
+               val = readl(virtbase + U300_GPIO_PXPDOR +
+                 PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING)
+                 & (1 << (gpio & 0x07));
+               writel(val | (1 << (gpio & 0x07)), virtbase +
+                 U300_GPIO_PXPDOR +
+                 PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING);
+       } else {
+               /* clear */
+               val = readl(virtbase + U300_GPIO_PXPDOR +
+                 PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING)
+                 & (1 << (gpio & 0x07));
+               writel(val & ~(1 << (gpio & 0x07)), virtbase +
+                 U300_GPIO_PXPDOR +
+                 PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING);
+       }
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL(gpio_set_value);
+
+int gpio_direction_input(unsigned gpio)
+{
+       unsigned long flags;
+       u32 val;
+
+       if (gpio > U300_GPIO_MAX)
+               return -EINVAL;
+
+       local_irq_save(flags);
+       val = readl(virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) *
+                               U300_GPIO_PORTX_SPACING);
+       /* Mask out this pin*/
+       val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << ((gpio & 0x07) << 1));
+       /* This is not needed since it sets the bits to zero.*/
+       /* val |= (U300_GPIO_PXPCR_PIN_MODE_INPUT << (gpio*2)); */
+       writel(val, virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) *
+                               U300_GPIO_PORTX_SPACING);
+       local_irq_restore(flags);
+       return 0;
+}
+EXPORT_SYMBOL(gpio_direction_input);
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+       unsigned long flags;
+       u32 val;
+
+       if (gpio > U300_GPIO_MAX)
+               return -EINVAL;
+
+       local_irq_save(flags);
+       val = readl(virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) *
+                               U300_GPIO_PORTX_SPACING);
+       /* Mask out this pin */
+       val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << ((gpio & 0x07) << 1));
+       /*
+        * FIXME: configure for push/pull, open drain or open source per pin
+        * in setup. The current driver will only support push/pull.
+        */
+       val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL
+                       << ((gpio & 0x07) << 1));
+       writel(val, virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) *
+                               U300_GPIO_PORTX_SPACING);
+       gpio_set_value(gpio, value);
+       local_irq_restore(flags);
+       return 0;
+}
+EXPORT_SYMBOL(gpio_direction_output);
+
+/*
+ * Enable an IRQ, edge is rising edge (!= 0) or falling edge (==0).
+ */
+void enable_irq_on_gpio_pin(unsigned gpio, int edge)
+{
+       u32 val;
+       unsigned long flags;
+       local_irq_save(flags);
+
+       val = readl(virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) *
+                               U300_GPIO_PORTX_SPACING);
+       val |= (1 << (gpio & 0x07));
+       writel(val, virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) *
+                               U300_GPIO_PORTX_SPACING);
+       val = readl(virtbase + U300_GPIO_PXICR + PIN_TO_PORT(gpio) *
+                               U300_GPIO_PORTX_SPACING);
+       if (edge)
+               val |= (1 << (gpio & 0x07));
+       else
+               val &= ~(1 << (gpio & 0x07));
+       writel(val, virtbase + U300_GPIO_PXICR + PIN_TO_PORT(gpio) *
+                               U300_GPIO_PORTX_SPACING);
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL(enable_irq_on_gpio_pin);
+
+void disable_irq_on_gpio_pin(unsigned gpio)
+{
+       u32 val;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       val = readl(virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) *
+                               U300_GPIO_PORTX_SPACING);
+       val &= ~(1 << (gpio & 0x07));
+       writel(val, virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) *
+                               U300_GPIO_PORTX_SPACING);
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL(disable_irq_on_gpio_pin);
+
+/* Enable (value == 0) or disable (value == 1) internal pullup */
+void gpio_pullup(unsigned gpio, int value)
+{
+       u32 val;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       if (value) {
+               val = readl(virtbase + U300_GPIO_PXPER + PIN_TO_PORT(gpio) *
+                                       U300_GPIO_PORTX_SPACING);
+               writel(val | (1 << (gpio & 0x07)), virtbase + U300_GPIO_PXPER +
+                               PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING);
+       } else {
+               val = readl(virtbase + U300_GPIO_PXPER + PIN_TO_PORT(gpio) *
+                                       U300_GPIO_PORTX_SPACING);
+               writel(val & ~(1 << (gpio & 0x07)), virtbase + U300_GPIO_PXPER +
+                               PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING);
+       }
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL(gpio_pullup);
+
+static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
+{
+       struct u300_gpio_port *port = dev_id;
+       u32 val;
+       int pin;
+
+       /* Read event register */
+       val = readl(virtbase + U300_GPIO_PXIEV + port->number *
+                               U300_GPIO_PORTX_SPACING);
+       /* Mask with enable register */
+       val &= readl(virtbase + U300_GPIO_PXIEV + port->number *
+                               U300_GPIO_PORTX_SPACING);
+       /* Mask relevant bits */
+       val &= U300_GPIO_PXIEV_ALL_IRQ_EVENT_MASK;
+       /* ACK IRQ (clear event) */
+       writel(val, virtbase + U300_GPIO_PXIEV + port->number *
+                               U300_GPIO_PORTX_SPACING);
+       /* Print message */
+       while (val != 0) {
+               unsigned gpio;
+
+               pin = __ffs(val);
+               /* mask off this pin */
+               val &= ~(1 << pin);
+               gpio = (port->number << 3) + pin;
+
+               if (gpio_pin[gpio].callback)
+                       (void)gpio_pin[gpio].callback(gpio_pin[gpio].data);
+               else
+                       dev_dbg(gpiodev, "stray GPIO IRQ on line %d\n",
+                              gpio);
+       }
+       return IRQ_HANDLED;
+}
+
+static void gpio_set_initial_values(void)
+{
+#ifdef U300_COH901571_3
+       int i, j;
+       unsigned long flags;
+       u32 val;
+
+       /* Write default values to all pins */
+       for (i = 0; i < U300_GPIO_NUM_PORTS; i++) {
+               val = 0;
+               for (j = 0; j < 8; j++)
+                       val |= (u32) (u300_gpio_config[i][j].default_output_value != DEFAULT_OUTPUT_LOW) << j;
+               local_irq_save(flags);
+               writel(val, virtbase + U300_GPIO_PXPDOR + i * U300_GPIO_PORTX_SPACING);
+               local_irq_restore(flags);
+       }
+
+       /*
+        * Put all pins that are set to either 'GPIO_OUT' or 'GPIO_NOT_USED'
+        * to output and 'GPIO_IN' to input for each port. And initialize
+        * default value on outputs.
+        */
+       for (i = 0; i < U300_GPIO_NUM_PORTS; i++) {
+               for (j = 0; j < U300_GPIO_PINS_PER_PORT; j++) {
+                       local_irq_save(flags);
+                       val = readl(virtbase + U300_GPIO_PXPCR +
+                                        i * U300_GPIO_PORTX_SPACING);
+                       /* Mask out this pin */
+                       val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << (j << 1));
+
+                       if (u300_gpio_config[i][j].pin_usage != GPIO_IN)
+                               val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL << (j << 1));
+                       writel(val, virtbase + U300_GPIO_PXPCR +
+                                        i * U300_GPIO_PORTX_SPACING);
+                       local_irq_restore(flags);
+               }
+       }
+
+       /* Enable or disable the internal pull-ups in the GPIO ASIC block */
+       for (i = 0; i < U300_GPIO_MAX; i++) {
+               val = 0;
+               for (j = 0; j < 8; j++)
+                       val |= (u32)((u300_gpio_config[i][j].pull_up == DISABLE_PULL_UP) << j);
+               local_irq_save(flags);
+               writel(val, virtbase + U300_GPIO_PXPER + i * U300_GPIO_PORTX_SPACING);
+               local_irq_restore(flags);
+       }
+#endif
+}
+
+static int __init gpio_probe(struct platform_device *pdev)
+{
+       u32 val;
+       int err = 0;
+       int i;
+       int num_irqs;
+
+       gpiodev = &pdev->dev;
+       memset(gpio_pin, 0, sizeof(gpio_pin));
+
+       /* Get GPIO clock */
+       clk = clk_get(&pdev->dev, NULL);
+       if (IS_ERR(clk)) {
+               err = PTR_ERR(clk);
+               dev_err(gpiodev, "could not get GPIO clock\n");
+               goto err_no_clk;
+       }
+       err = clk_enable(clk);
+       if (err) {
+               dev_err(gpiodev, "could not enable GPIO clock\n");
+               goto err_no_clk_enable;
+       }
+
+       memres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!memres)
+               goto err_no_resource;
+
+       if (request_mem_region(memres->start, memres->end - memres->start, "GPIO Controller")
+           == NULL) {
+               err = -ENODEV;
+               goto err_no_ioregion;
+       }
+
+       virtbase = ioremap(memres->start, resource_size(memres));
+       if (!virtbase) {
+               err = -ENOMEM;
+               goto err_no_ioremap;
+       }
+       dev_info(gpiodev, "remapped 0x%08x to %p\n",
+                memres->start, virtbase);
+
+#ifdef U300_COH901335
+       dev_info(gpiodev, "initializing GPIO Controller COH 901 335\n");
+       /* Turn on the GPIO block */
+       writel(U300_GPIO_CR_BLOCK_CLOCK_ENABLE, virtbase + U300_GPIO_CR);
+#endif
+
+#ifdef U300_COH901571_3
+       dev_info(gpiodev, "initializing GPIO Controller COH 901 571/3\n");
+       val = readl(virtbase + U300_GPIO_CR);
+       dev_info(gpiodev, "COH901571/3 block version: %d, " \
+              "number of cores: %d\n",
+              ((val & 0x0000FE00) >> 9),
+              ((val & 0x000001FC) >> 2));
+       writel(U300_GPIO_CR_BLOCK_CLKRQ_ENABLE, virtbase + U300_GPIO_CR);
+#endif
+
+       gpio_set_initial_values();
+
+       for (num_irqs = 0 ; num_irqs < U300_GPIO_NUM_PORTS; num_irqs++) {
+
+               gpio_ports[num_irqs].irq =
+                       platform_get_irq_byname(pdev,
+                                               gpio_ports[num_irqs].name);
+
+               err = request_irq(gpio_ports[num_irqs].irq,
+                                 gpio_irq_handler, IRQF_DISABLED,
+                                 gpio_ports[num_irqs].name,
+                                 &gpio_ports[num_irqs]);
+               if (err) {
+                       dev_err(gpiodev, "cannot allocate IRQ for %s!\n",
+                               gpio_ports[num_irqs].name);
+                       goto err_no_irq;
+               }
+               /* Turns off PortX_irq_force */
+               writel(0x0, virtbase + U300_GPIO_PXIFR +
+                                num_irqs * U300_GPIO_PORTX_SPACING);
+       }
+
+       return 0;
+
+ err_no_irq:
+       for (i = 0; i < num_irqs; i++)
+               free_irq(gpio_ports[i].irq, &gpio_ports[i]);
+       iounmap(virtbase);
+ err_no_ioremap:
+       release_mem_region(memres->start, memres->end - memres->start);
+ err_no_ioregion:
+ err_no_resource:
+       clk_disable(clk);
+ err_no_clk_enable:
+       clk_put(clk);
+ err_no_clk:
+       dev_info(gpiodev, "module ERROR:%d\n", err);
+       return err;
+}
+
+static int __exit gpio_remove(struct platform_device *pdev)
+{
+       int i;
+
+       /* Turn off the GPIO block */
+       writel(0x00000000U, virtbase + U300_GPIO_CR);
+       for (i = 0 ; i < U300_GPIO_NUM_PORTS; i++)
+               free_irq(gpio_ports[i].irq, &gpio_ports[i]);
+       iounmap(virtbase);
+       release_mem_region(memres->start, memres->end - memres->start);
+       clk_disable(clk);
+       clk_put(clk);
+       return 0;
+}
+
+static struct platform_driver gpio_driver = {
+       .driver         = {
+               .name   = "u300-gpio",
+       },
+       .remove         = __exit_p(gpio_remove),
+};
+
+
+static int __init u300_gpio_init(void)
+{
+       return platform_driver_probe(&gpio_driver, gpio_probe);
+}
+
+static void __exit u300_gpio_exit(void)
+{
+       platform_driver_unregister(&gpio_driver);
+}
+
+arch_initcall(u300_gpio_init);
+module_exit(u300_gpio_exit);
+
+MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>");
+
+#ifdef U300_COH901571_3
+MODULE_DESCRIPTION("ST-Ericsson AB COH 901 571/3 GPIO driver");
+#endif
+
+#ifdef U300_COH901335
+MODULE_DESCRIPTION("ST-Ericsson AB COH 901 335 GPIO driver");
+#endif
+
+MODULE_LICENSE("GPL");
index 137a8ca678221f3b3c7121a481aaf9ce6d0872da..a971e3d043ba0535ed0539146b5530443cd8af17 100644 (file)
@@ -1296,7 +1296,7 @@ EXPORT_SYMBOL_GPL(gpio_request_one);
  * @array:     array of the 'struct gpio'
  * @num:       how many GPIOs in the array
  */
-int gpio_request_array(struct gpio *array, size_t num)
+int gpio_request_array(const struct gpio *array, size_t num)
 {
        int i, err;
 
@@ -1319,7 +1319,7 @@ EXPORT_SYMBOL_GPL(gpio_request_array);
  * @array:     array of the 'struct gpio'
  * @num:       how many GPIOs in the array
  */
-void gpio_free_array(struct gpio *array, size_t num)
+void gpio_free_array(const struct gpio *array, size_t num)
 {
        while (num--)
                gpio_free((array++)->gpio);
index 1b06f67e1f69b4f19f1318b1fbbe6b252e2a1df0..bd6571e0097a8be17b8fe3c27db173f3c8d9438b 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/io.h>
 #include <linux/gpio.h>
 #include <linux/slab.h>
+#include <linux/pm_runtime.h>
 
 /*
  * Langwell chip has 64 pins and thus there are 2 32bit registers to control
@@ -63,6 +64,7 @@ struct lnw_gpio {
        void                            *reg_base;
        spinlock_t                      lock;
        unsigned                        irq_base;
+       struct pci_dev                  *pdev;
 };
 
 static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset,
@@ -104,11 +106,18 @@ static int lnw_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
        u32 value;
        unsigned long flags;
 
+       if (lnw->pdev)
+               pm_runtime_get(&lnw->pdev->dev);
+
        spin_lock_irqsave(&lnw->lock, flags);
        value = readl(gpdr);
        value &= ~BIT(offset % 32);
        writel(value, gpdr);
        spin_unlock_irqrestore(&lnw->lock, flags);
+
+       if (lnw->pdev)
+               pm_runtime_put(&lnw->pdev->dev);
+
        return 0;
 }
 
@@ -120,11 +129,19 @@ static int lnw_gpio_direction_output(struct gpio_chip *chip,
        unsigned long flags;
 
        lnw_gpio_set(chip, offset, value);
+
+       if (lnw->pdev)
+               pm_runtime_get(&lnw->pdev->dev);
+
        spin_lock_irqsave(&lnw->lock, flags);
        value = readl(gpdr);
        value |= BIT(offset % 32);
        writel(value, gpdr);
        spin_unlock_irqrestore(&lnw->lock, flags);
+
+       if (lnw->pdev)
+               pm_runtime_put(&lnw->pdev->dev);
+
        return 0;
 }
 
@@ -145,6 +162,10 @@ static int lnw_irq_type(struct irq_data *d, unsigned type)
 
        if (gpio >= lnw->chip.ngpio)
                return -EINVAL;
+
+       if (lnw->pdev)
+               pm_runtime_get(&lnw->pdev->dev);
+
        spin_lock_irqsave(&lnw->lock, flags);
        if (type & IRQ_TYPE_EDGE_RISING)
                value = readl(grer) | BIT(gpio % 32);
@@ -159,6 +180,9 @@ static int lnw_irq_type(struct irq_data *d, unsigned type)
        writel(value, gfer);
        spin_unlock_irqrestore(&lnw->lock, flags);
 
+       if (lnw->pdev)
+               pm_runtime_put(&lnw->pdev->dev);
+
        return 0;
 }
 
@@ -211,6 +235,39 @@ static void lnw_irq_handler(unsigned irq, struct irq_desc *desc)
        chip->irq_eoi(data);
 }
 
+#ifdef CONFIG_PM
+static int lnw_gpio_runtime_resume(struct device *dev)
+{
+       return 0;
+}
+
+static int lnw_gpio_runtime_suspend(struct device *dev)
+{
+       return 0;
+}
+
+static int lnw_gpio_runtime_idle(struct device *dev)
+{
+       int err = pm_schedule_suspend(dev, 500);
+
+       if (!err)
+               return 0;
+
+       return -EBUSY;
+}
+
+#else
+#define lnw_gpio_runtime_suspend       NULL
+#define lnw_gpio_runtime_resume                NULL
+#define lnw_gpio_runtime_idle          NULL
+#endif
+
+static const struct dev_pm_ops lnw_gpio_pm_ops = {
+       .runtime_suspend = lnw_gpio_runtime_suspend,
+       .runtime_resume = lnw_gpio_runtime_resume,
+       .runtime_idle = lnw_gpio_runtime_idle,
+};
+
 static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
                        const struct pci_device_id *id)
 {
@@ -270,6 +327,7 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
        lnw->chip.base = gpio_base;
        lnw->chip.ngpio = id->driver_data;
        lnw->chip.can_sleep = 0;
+       lnw->pdev = pdev;
        pci_set_drvdata(pdev, lnw);
        retval = gpiochip_add(&lnw->chip);
        if (retval) {
@@ -285,6 +343,10 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
        }
 
        spin_lock_init(&lnw->lock);
+
+       pm_runtime_put_noidle(&pdev->dev);
+       pm_runtime_allow(&pdev->dev);
+
        goto done;
 err5:
        kfree(lnw);
@@ -302,6 +364,9 @@ static struct pci_driver lnw_gpio_driver = {
        .name           = "langwell_gpio",
        .id_table       = lnw_gpio_ids,
        .probe          = lnw_gpio_probe,
+       .driver         = {
+               .pm     = &lnw_gpio_pm_ops,
+       },
 };
 
 
index 78a843947d82150031cf9ed60ac6254eef3f0ab1..0451d7ac94ac1d51b062d0da4ce19e4e12b6bdf4 100644 (file)
 #include <linux/of_gpio.h>
 #endif
 
-#define PCA953X_INPUT          0
-#define PCA953X_OUTPUT         1
-#define PCA953X_INVERT         2
-#define PCA953X_DIRECTION      3
-
-#define PCA953X_GPIOS         0x00FF
-#define PCA953X_INT           0x0100
+#define PCA953X_INPUT          0
+#define PCA953X_OUTPUT         1
+#define PCA953X_INVERT         2
+#define PCA953X_DIRECTION      3
+
+#define PCA957X_IN             0
+#define PCA957X_INVRT          1
+#define PCA957X_BKEN           2
+#define PCA957X_PUPD           3
+#define PCA957X_CFG            4
+#define PCA957X_OUT            5
+#define PCA957X_MSK            6
+#define PCA957X_INTS           7
+
+#define PCA_GPIO_MASK          0x00FF
+#define PCA_INT                        0x0100
+#define PCA953X_TYPE           0x1000
+#define PCA957X_TYPE           0x2000
 
 static const struct i2c_device_id pca953x_id[] = {
-       { "pca9534", 8  | PCA953X_INT, },
-       { "pca9535", 16 | PCA953X_INT, },
-       { "pca9536", 4, },
-       { "pca9537", 4  | PCA953X_INT, },
-       { "pca9538", 8  | PCA953X_INT, },
-       { "pca9539", 16 | PCA953X_INT, },
-       { "pca9554", 8  | PCA953X_INT, },
-       { "pca9555", 16 | PCA953X_INT, },
-       { "pca9556", 8, },
-       { "pca9557", 8, },
-
-       { "max7310", 8, },
-       { "max7312", 16 | PCA953X_INT, },
-       { "max7313", 16 | PCA953X_INT, },
-       { "max7315", 8  | PCA953X_INT, },
-       { "pca6107", 8  | PCA953X_INT, },
-       { "tca6408", 8  | PCA953X_INT, },
-       { "tca6416", 16 | PCA953X_INT, },
+       { "pca9534", 8  | PCA953X_TYPE | PCA_INT, },
+       { "pca9535", 16 | PCA953X_TYPE | PCA_INT, },
+       { "pca9536", 4  | PCA953X_TYPE, },
+       { "pca9537", 4  | PCA953X_TYPE | PCA_INT, },
+       { "pca9538", 8  | PCA953X_TYPE | PCA_INT, },
+       { "pca9539", 16 | PCA953X_TYPE | PCA_INT, },
+       { "pca9554", 8  | PCA953X_TYPE | PCA_INT, },
+       { "pca9555", 16 | PCA953X_TYPE | PCA_INT, },
+       { "pca9556", 8  | PCA953X_TYPE, },
+       { "pca9557", 8  | PCA953X_TYPE, },
+       { "pca9574", 8  | PCA957X_TYPE | PCA_INT, },
+       { "pca9575", 16 | PCA957X_TYPE | PCA_INT, },
+
+       { "max7310", 8  | PCA953X_TYPE, },
+       { "max7312", 16 | PCA953X_TYPE | PCA_INT, },
+       { "max7313", 16 | PCA953X_TYPE | PCA_INT, },
+       { "max7315", 8  | PCA953X_TYPE | PCA_INT, },
+       { "pca6107", 8  | PCA953X_TYPE | PCA_INT, },
+       { "tca6408", 8  | PCA953X_TYPE | PCA_INT, },
+       { "tca6416", 16 | PCA953X_TYPE | PCA_INT, },
        /* NYET:  { "tca6424", 24, }, */
        { }
 };
@@ -75,16 +88,32 @@ struct pca953x_chip {
        struct pca953x_platform_data *dyn_pdata;
        struct gpio_chip gpio_chip;
        const char *const *names;
+       int     chip_type;
 };
 
 static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val)
 {
-       int ret;
+       int ret = 0;
 
        if (chip->gpio_chip.ngpio <= 8)
                ret = i2c_smbus_write_byte_data(chip->client, reg, val);
-       else
-               ret = i2c_smbus_write_word_data(chip->client, reg << 1, val);
+       else {
+               switch (chip->chip_type) {
+               case PCA953X_TYPE:
+                       ret = i2c_smbus_write_word_data(chip->client,
+                                                       reg << 1, val);
+                       break;
+               case PCA957X_TYPE:
+                       ret = i2c_smbus_write_byte_data(chip->client, reg << 1,
+                                                       val & 0xff);
+                       if (ret < 0)
+                               break;
+                       ret = i2c_smbus_write_byte_data(chip->client,
+                                                       (reg << 1) + 1,
+                                                       (val & 0xff00) >> 8);
+                       break;
+               }
+       }
 
        if (ret < 0) {
                dev_err(&chip->client->dev, "failed writing register\n");
@@ -116,13 +145,22 @@ static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
 {
        struct pca953x_chip *chip;
        uint16_t reg_val;
-       int ret;
+       int ret, offset = 0;
 
        chip = container_of(gc, struct pca953x_chip, gpio_chip);
 
        mutex_lock(&chip->i2c_lock);
        reg_val = chip->reg_direction | (1u << off);
-       ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val);
+
+       switch (chip->chip_type) {
+       case PCA953X_TYPE:
+               offset = PCA953X_DIRECTION;
+               break;
+       case PCA957X_TYPE:
+               offset = PCA957X_CFG;
+               break;
+       }
+       ret = pca953x_write_reg(chip, offset, reg_val);
        if (ret)
                goto exit;
 
@@ -138,7 +176,7 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,
 {
        struct pca953x_chip *chip;
        uint16_t reg_val;
-       int ret;
+       int ret, offset = 0;
 
        chip = container_of(gc, struct pca953x_chip, gpio_chip);
 
@@ -149,7 +187,15 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,
        else
                reg_val = chip->reg_output & ~(1u << off);
 
-       ret = pca953x_write_reg(chip, PCA953X_OUTPUT, reg_val);
+       switch (chip->chip_type) {
+       case PCA953X_TYPE:
+               offset = PCA953X_OUTPUT;
+               break;
+       case PCA957X_TYPE:
+               offset = PCA957X_OUT;
+               break;
+       }
+       ret = pca953x_write_reg(chip, offset, reg_val);
        if (ret)
                goto exit;
 
@@ -157,7 +203,15 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,
 
        /* then direction */
        reg_val = chip->reg_direction & ~(1u << off);
-       ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val);
+       switch (chip->chip_type) {
+       case PCA953X_TYPE:
+               offset = PCA953X_DIRECTION;
+               break;
+       case PCA957X_TYPE:
+               offset = PCA957X_CFG;
+               break;
+       }
+       ret = pca953x_write_reg(chip, offset, reg_val);
        if (ret)
                goto exit;
 
@@ -172,12 +226,20 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
 {
        struct pca953x_chip *chip;
        uint16_t reg_val;
-       int ret;
+       int ret, offset = 0;
 
        chip = container_of(gc, struct pca953x_chip, gpio_chip);
 
        mutex_lock(&chip->i2c_lock);
-       ret = pca953x_read_reg(chip, PCA953X_INPUT, &reg_val);
+       switch (chip->chip_type) {
+       case PCA953X_TYPE:
+               offset = PCA953X_INPUT;
+               break;
+       case PCA957X_TYPE:
+               offset = PCA957X_IN;
+               break;
+       }
+       ret = pca953x_read_reg(chip, offset, &reg_val);
        mutex_unlock(&chip->i2c_lock);
        if (ret < 0) {
                /* NOTE:  diagnostic already emitted; that's all we should
@@ -194,7 +256,7 @@ static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
 {
        struct pca953x_chip *chip;
        uint16_t reg_val;
-       int ret;
+       int ret, offset = 0;
 
        chip = container_of(gc, struct pca953x_chip, gpio_chip);
 
@@ -204,7 +266,15 @@ static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
        else
                reg_val = chip->reg_output & ~(1u << off);
 
-       ret = pca953x_write_reg(chip, PCA953X_OUTPUT, reg_val);
+       switch (chip->chip_type) {
+       case PCA953X_TYPE:
+               offset = PCA953X_OUTPUT;
+               break;
+       case PCA957X_TYPE:
+               offset = PCA957X_OUT;
+               break;
+       }
+       ret = pca953x_write_reg(chip, offset, reg_val);
        if (ret)
                goto exit;
 
@@ -322,9 +392,17 @@ static uint16_t pca953x_irq_pending(struct pca953x_chip *chip)
        uint16_t old_stat;
        uint16_t pending;
        uint16_t trigger;
-       int ret;
-
-       ret = pca953x_read_reg(chip, PCA953X_INPUT, &cur_stat);
+       int ret, offset = 0;
+
+       switch (chip->chip_type) {
+       case PCA953X_TYPE:
+               offset = PCA953X_INPUT;
+               break;
+       case PCA957X_TYPE:
+               offset = PCA957X_IN;
+               break;
+       }
+       ret = pca953x_read_reg(chip, offset, &cur_stat);
        if (ret)
                return 0;
 
@@ -372,14 +450,21 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
 {
        struct i2c_client *client = chip->client;
        struct pca953x_platform_data *pdata = client->dev.platform_data;
-       int ret;
+       int ret, offset = 0;
 
        if (pdata->irq_base != -1
-                       && (id->driver_data & PCA953X_INT)) {
+                       && (id->driver_data & PCA_INT)) {
                int lvl;
 
-               ret = pca953x_read_reg(chip, PCA953X_INPUT,
-                                      &chip->irq_stat);
+               switch (chip->chip_type) {
+               case PCA953X_TYPE:
+                       offset = PCA953X_INPUT;
+                       break;
+               case PCA957X_TYPE:
+                       offset = PCA957X_IN;
+                       break;
+               }
+               ret = pca953x_read_reg(chip, offset, &chip->irq_stat);
                if (ret)
                        goto out_failed;
 
@@ -439,7 +524,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
        struct i2c_client *client = chip->client;
        struct pca953x_platform_data *pdata = client->dev.platform_data;
 
-       if (pdata->irq_base != -1 && (id->driver_data & PCA953X_INT))
+       if (pdata->irq_base != -1 && (id->driver_data & PCA_INT))
                dev_warn(&client->dev, "interrupt support not compiled in\n");
 
        return 0;
@@ -499,12 +584,65 @@ pca953x_get_alt_pdata(struct i2c_client *client)
 }
 #endif
 
+static int __devinit device_pca953x_init(struct pca953x_chip *chip, int invert)
+{
+       int ret;
+
+       ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output);
+       if (ret)
+               goto out;
+
+       ret = pca953x_read_reg(chip, PCA953X_DIRECTION,
+                              &chip->reg_direction);
+       if (ret)
+               goto out;
+
+       /* set platform specific polarity inversion */
+       ret = pca953x_write_reg(chip, PCA953X_INVERT, invert);
+       if (ret)
+               goto out;
+       return 0;
+out:
+       return ret;
+}
+
+static int __devinit device_pca957x_init(struct pca953x_chip *chip, int invert)
+{
+       int ret;
+       uint16_t val = 0;
+
+       /* Let every port in proper state, that could save power */
+       pca953x_write_reg(chip, PCA957X_PUPD, 0x0);
+       pca953x_write_reg(chip, PCA957X_CFG, 0xffff);
+       pca953x_write_reg(chip, PCA957X_OUT, 0x0);
+
+       ret = pca953x_read_reg(chip, PCA957X_IN, &val);
+       if (ret)
+               goto out;
+       ret = pca953x_read_reg(chip, PCA957X_OUT, &chip->reg_output);
+       if (ret)
+               goto out;
+       ret = pca953x_read_reg(chip, PCA957X_CFG, &chip->reg_direction);
+       if (ret)
+               goto out;
+
+       /* set platform specific polarity inversion */
+       pca953x_write_reg(chip, PCA957X_INVRT, invert);
+
+       /* To enable register 6, 7 to controll pull up and pull down */
+       pca953x_write_reg(chip, PCA957X_BKEN, 0x202);
+
+       return 0;
+out:
+       return ret;
+}
+
 static int __devinit pca953x_probe(struct i2c_client *client,
                                   const struct i2c_device_id *id)
 {
        struct pca953x_platform_data *pdata;
        struct pca953x_chip *chip;
-       int ret;
+       int ret = 0;
 
        chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL);
        if (chip == NULL)
@@ -531,25 +669,20 @@ static int __devinit pca953x_probe(struct i2c_client *client,
        chip->gpio_start = pdata->gpio_base;
 
        chip->names = pdata->names;
+       chip->chip_type = id->driver_data & (PCA953X_TYPE | PCA957X_TYPE);
 
        mutex_init(&chip->i2c_lock);
 
        /* initialize cached registers from their original values.
         * we can't share this chip with another i2c master.
         */
-       pca953x_setup_gpio(chip, id->driver_data & PCA953X_GPIOS);
+       pca953x_setup_gpio(chip, id->driver_data & PCA_GPIO_MASK);
 
-       ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output);
-       if (ret)
-               goto out_failed;
-
-       ret = pca953x_read_reg(chip, PCA953X_DIRECTION, &chip->reg_direction);
-       if (ret)
-               goto out_failed;
-
-       /* set platform specific polarity inversion */
-       ret = pca953x_write_reg(chip, PCA953X_INVERT, pdata->invert);
-       if (ret)
+       if (chip->chip_type == PCA953X_TYPE)
+               device_pca953x_init(chip, pdata->invert);
+       else if (chip->chip_type == PCA957X_TYPE)
+               device_pca957x_init(chip, pdata->invert);
+       else
                goto out_failed;
 
        ret = pca953x_irq_setup(chip, id);
index f970a5f3585e03b5395b74f32f6103d21a67128d..36919e77c495cb97c3ae3a5896a6d7dabdce38df 100644 (file)
@@ -283,8 +283,10 @@ static int pch_gpio_resume(struct pci_dev *pdev)
 #define pch_gpio_resume NULL
 #endif
 
+#define PCI_VENDOR_ID_ROHM             0x10DB
 static DEFINE_PCI_DEVICE_TABLE(pch_gpio_pcidev_id) = {
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) },
+       { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8014) },
        { 0, }
 };
 MODULE_DEVICE_TABLE(pci, pch_gpio_pcidev_id);
index ff5c66080c8c947e64edd2c8db17436d98921ad7..fcdcb5d5c99539871c448411dbdb0fddd2be56b8 100644 (file)
@@ -35,9 +35,9 @@
  * platform data and other tables.
  */
 
-static inline int gpio_is_valid(int number)
+static inline bool gpio_is_valid(int number)
 {
-       return ((unsigned)number) < ARCH_NR_GPIOS;
+       return number >= 0 && number < ARCH_NR_GPIOS;
 }
 
 struct device;
@@ -193,8 +193,8 @@ struct gpio {
 };
 
 extern int gpio_request_one(unsigned gpio, unsigned long flags, const char *label);
-extern int gpio_request_array(struct gpio *array, size_t num);
-extern void gpio_free_array(struct gpio *array, size_t num);
+extern int gpio_request_array(const struct gpio *array, size_t num);
+extern void gpio_free_array(const struct gpio *array, size_t num);
 
 #ifdef CONFIG_GPIO_SYSFS
 
@@ -212,7 +212,7 @@ extern void gpio_unexport(unsigned gpio);
 
 #else  /* !CONFIG_GPIOLIB */
 
-static inline int gpio_is_valid(int number)
+static inline bool gpio_is_valid(int number)
 {
        /* only non-negative numbers are valid */
        return number >= 0;
index 32720baf70f1c8f1e46741ff8006d44da82f6188..32d47e710661e55879b5473f9850316948f484fe 100644 (file)
@@ -25,9 +25,9 @@ struct gpio_chip;
  * warning when something is wrongly called.
  */
 
-static inline int gpio_is_valid(int number)
+static inline bool gpio_is_valid(int number)
 {
-       return 0;
+       return false;
 }
 
 static inline int gpio_request(unsigned gpio, const char *label)
@@ -41,7 +41,7 @@ static inline int gpio_request_one(unsigned gpio,
        return -ENOSYS;
 }
 
-static inline int gpio_request_array(struct gpio *array, size_t num)
+static inline int gpio_request_array(const struct gpio *array, size_t num)
 {
        return -ENOSYS;
 }
@@ -54,7 +54,7 @@ static inline void gpio_free(unsigned gpio)
        WARN_ON(1);
 }
 
-static inline void gpio_free_array(struct gpio *array, size_t num)
+static inline void gpio_free_array(const struct gpio *array, size_t num)
 {
        might_sleep();