]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge remote-tracking branch 'gpio/for-next'
authorThierry Reding <treding@nvidia.com>
Thu, 24 Oct 2013 12:59:44 +0000 (14:59 +0200)
committerThierry Reding <treding@nvidia.com>
Thu, 24 Oct 2013 12:59:44 +0000 (14:59 +0200)
1  2 
MAINTAINERS
arch/arm/Kconfig
drivers/gpio/gpio-mpc8xxx.c
drivers/gpio/gpiolib-of.c
drivers/gpio/gpiolib.c
include/asm-generic/gpio.h
include/linux/gpio.h

diff --combined MAINTAINERS
index 13a631bb788fdb604d69af172427cc2a73c2c6f2,b16ee242e7432b5caf0ae5352feb9e4f6bd0d6cd..5a7ed4c3590e131ff07d35e6a2076b8905b2e574
@@@ -253,20 -253,6 +253,20 @@@ F:       drivers/pci/*acpi
  F:    drivers/pci/*/*acpi*
  F:    drivers/pci/*/*/*acpi*
  
 +ACPI COMPONENT ARCHITECTURE (ACPICA)
 +M:    Robert Moore <robert.moore@intel.com>
 +M:    Lv Zheng <lv.zheng@intel.com>
 +M:    Rafael J. Wysocki <rafael.j.wysocki@intel.com>
 +L:    linux-acpi@vger.kernel.org
 +L:    devel@acpica.org
 +W:    https://acpica.org/
 +W:    https://github.com/acpica/acpica/
 +Q:    https://patchwork.kernel.org/project/linux-acpi/list/
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
 +S:    Supported
 +F:    drivers/acpi/acpica/
 +F:    include/acpi/
 +
  ACPI FAN DRIVER
  M:    Zhang Rui <rui.zhang@intel.com>
  L:    linux-acpi@vger.kernel.org
@@@ -1416,7 -1402,7 +1416,7 @@@ M:      Wolfram Sang <wsa@the-dreams.de
  L:    linux-i2c@vger.kernel.org
  S:    Maintained
  F:    drivers/misc/eeprom/at24.c
 -F:    include/linux/i2c/at24.h
 +F:    include/linux/platform_data/at24.h
  
  ATA OVER ETHERNET (AOE) DRIVER
  M:    "Ed L. Cashin" <ecashin@coraid.com>
@@@ -1672,9 -1658,9 +1672,9 @@@ F:      drivers/video/backlight
  F:    include/linux/backlight.h
  
  BATMAN ADVANCED
 -M:    Marek Lindner <lindner_marek@yahoo.de>
 -M:    Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
 -M:    Antonio Quartulli <ordex@autistici.org>
 +M:    Marek Lindner <mareklindner@neomailbox.ch>
 +M:    Simon Wunderlich <sw@simonwunderlich.de>
 +M:    Antonio Quartulli <antonio@meshcoding.com>
  L:    b.a.t.m.a.n@lists.open-mesh.org
  W:    http://www.open-mesh.org/
  S:    Maintained
@@@ -1805,7 -1791,6 +1805,7 @@@ F:      include/net/bluetooth
  
  BONDING DRIVER
  M:    Jay Vosburgh <fubar@us.ibm.com>
 +M:    Veaceslav Falico <vfalico@redhat.com>
  M:    Andy Gospodarek <andy@greyhouse.net>
  L:    netdev@vger.kernel.org
  W:    http://sourceforge.net/projects/bonding/
@@@ -1872,7 -1857,7 +1872,7 @@@ S:      Supporte
  F:    drivers/net/wireless/brcm80211/
  
  BROADCOM BNX2FC 10 GIGABIT FCOE DRIVER
 -M:    Bhanu Prakash Gollapudi <bprakash@broadcom.com>
 +M:    Eddie Wai <eddie.wai@broadcom.com>
  L:    linux-scsi@vger.kernel.org
  S:    Supported
  F:    drivers/scsi/bnx2fc/
@@@ -2733,8 -2718,6 +2733,8 @@@ T:      git git://git.linaro.org/people/sumi
  DMA GENERIC OFFLOAD ENGINE SUBSYSTEM
  M:    Vinod Koul <vinod.koul@intel.com>
  M:    Dan Williams <dan.j.williams@intel.com>
 +L:    dmaengine@vger.kernel.org
 +Q:    https://patchwork.kernel.org/project/linux-dmaengine/list/
  S:    Supported
  F:    drivers/dma/
  F:    include/linux/dma*
@@@ -2839,9 -2822,7 +2839,9 @@@ L:      dri-devel@lists.freedesktop.or
  L:    linux-tegra@vger.kernel.org
  T:    git git://anongit.freedesktop.org/tegra/linux.git
  S:    Maintained
 +F:    drivers/gpu/drm/tegra/
  F:    drivers/gpu/host1x/
 +F:    include/linux/host1x.h
  F:    include/uapi/drm/tegra_drm.h
  F:    Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt
  
@@@ -3698,14 -3679,6 +3698,14 @@@ S:    Maintaine
  F:    include/asm-generic/
  F:    include/uapi/asm-generic/
  
 +GENERIC PHY FRAMEWORK
 +M:    Kishon Vijay Abraham I <kishon@ti.com>
 +L:    linux-kernel@vger.kernel.org
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/kishon/linux-phy.git
 +S:    Supported
 +F:    drivers/phy/
 +F:    include/linux/phy/
 +
  GENERIC UIO DRIVER FOR PCI DEVICES
  M:    "Michael S. Tsirkin" <mst@redhat.com>
  L:    kvm@vger.kernel.org
@@@ -4247,7 -4220,7 +4247,7 @@@ S:      Maintaine
  F:    drivers/media/rc/iguanair.c
  
  IIO SUBSYSTEM AND DRIVERS
 -M:    Jonathan Cameron <jic23@cam.ac.uk>
 +M:    Jonathan Cameron <jic23@kernel.org>
  L:    linux-iio@vger.kernel.org
  S:    Maintained
  F:    drivers/iio/
@@@ -4384,10 -4357,7 +4384,10 @@@ F:    arch/x86/kernel/microcode_intel.
  
  INTEL I/OAT DMA DRIVER
  M:    Dan Williams <dan.j.williams@intel.com>
 -S:    Maintained
 +M:    Dave Jiang <dave.jiang@intel.com>
 +L:    dmaengine@vger.kernel.org
 +Q:    https://patchwork.kernel.org/project/linux-dmaengine/list/
 +S:    Supported
  F:    drivers/dma/ioat*
  
  INTEL IOMMU (VT-d)
@@@ -4446,6 -4416,12 +4446,12 @@@ F:    Documentation/networking/ixgbevf.tx
  F:    Documentation/networking/i40e.txt
  F:    drivers/net/ethernet/intel/
  
+ INTEL-MID GPIO DRIVER
+ M:    David Cohen <david.a.cohen@linux.intel.com>
+ L:    linux-gpio@vger.kernel.org
+ S:    Maintained
+ F:    drivers/gpio/gpio-intel-mid.c
  INTEL PRO/WIRELESS 2100, 2200BG, 2915ABG NETWORK CONNECTION SUPPORT
  M:    Stanislav Yakovlev <stas.yakovlev@gmail.com>
  L:    linux-wireless@vger.kernel.org
@@@ -4784,13 -4760,6 +4790,13 @@@ S:    Maintaine
  F:    Documentation/hwmon/k8temp
  F:    drivers/hwmon/k8temp.c
  
 +KTAP
 +M:    Jovi Zhangwei <jovi.zhangwei@gmail.com>
 +W:    http://www.ktap.org
 +L:    ktap@freelists.org
 +S:    Maintained
 +F:    drivers/staging/ktap/
 +
  KCONFIG
  M:    Michal Marek <mmarek@suse.cz>
  L:    linux-kbuild@vger.kernel.org
@@@ -6415,12 -6384,6 +6421,12 @@@ S:    Supporte
  F:    Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt
  F:    drivers/pci/host/pci-tegra.c
  
 +PCI DRIVER FOR SAMSUNG EXYNOS
 +M:    Jingoo Han <jg1.han@samsung.com>
 +L:    linux-pci@vger.kernel.org
 +S:    Maintained
 +F:    drivers/pci/host/pci-exynos.c
 +
  PCMCIA SUBSYSTEM
  P:    Linux PCMCIA Team
  L:    linux-pcmcia@lists.infradead.org
@@@ -6891,14 -6854,6 +6897,14 @@@ L:    linux-hexagon@vger.kernel.or
  S:    Supported
  F:    arch/hexagon/
  
 +QUALCOMM WCN36XX WIRELESS DRIVER
 +M:    Eugene Krasnikov <k.eugene.e@gmail.com>
 +L:    wcn36xx@lists.infradead.org
 +W:    http://wireless.kernel.org/en/users/Drivers/wcn36xx
 +T:    git git://github.com/KrasnikovEugene/wcn36xx.git
 +S:    Supported
 +F:    drivers/net/wireless/ath/wcn36xx/
 +
  QUICKCAM PARALLEL PORT WEBCAMS
  M:    Hans Verkuil <hverkuil@xs4all.nl>
  L:    linux-media@vger.kernel.org
@@@ -6986,7 -6941,7 +6992,7 @@@ M:      "Paul E. McKenney" <paulmck@linux.vn
  S:    Supported
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git
  F:    Documentation/RCU/torture.txt
 -F:    kernel/rcutorture.c
 +F:    kernel/rcu/torture.c
  
  RDC R-321X SoC
  M:    Florian Fainelli <florian@openwrt.org>
@@@ -7013,9 -6968,8 +7019,9 @@@ T:      git git://git.kernel.org/pub/scm/lin
  F:    Documentation/RCU/
  X:    Documentation/RCU/torture.txt
  F:    include/linux/rcu*
 -F:    kernel/rcu*
 -X:    kernel/rcutorture.c
 +X:    include/linux/srcu.h
 +F:    kernel/rcu/
 +X:    kernel/rcu/torture.c
  
  REAL TIME CLOCK (RTC) SUBSYSTEM
  M:    Alessandro Zummo <a.zummo@towertech.it>
@@@ -7340,8 -7294,6 +7346,8 @@@ S:      Maintaine
  F:    kernel/sched/
  F:    include/linux/sched.h
  F:    include/uapi/linux/sched.h
 +F:    kernel/wait.c
 +F:    include/linux/wait.h
  
  SCORE ARCHITECTURE
  M:    Chen Liqin <liqin.linux@gmail.com>
@@@ -7476,10 -7428,9 +7482,10 @@@ SELINUX SECURITY MODUL
  M:    Stephen Smalley <sds@tycho.nsa.gov>
  M:    James Morris <james.l.morris@oracle.com>
  M:    Eric Paris <eparis@parisplace.org>
 +M:    Paul Moore <paul@paul-moore.com>
  L:    selinux@tycho.nsa.gov (subscribers-only, general discussion)
  W:    http://selinuxproject.org
 -T:    git git://git.infradead.org/users/eparis/selinux.git
 +T:    git git://git.infradead.org/users/pcmoore/selinux
  S:    Supported
  F:    include/linux/selinux*
  F:    security/selinux/
@@@ -7705,8 -7656,8 +7711,8 @@@ M:      "Paul E. McKenney" <paulmck@linux.vn
  W:    http://www.rdrop.com/users/paulmck/RCU/
  S:    Supported
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git
 -F:    include/linux/srcu*
 -F:    kernel/srcu*
 +F:    include/linux/srcu.h
 +F:    kernel/rcu/srcu.c
  
  SMACK SECURITY MODULE
  M:    Casey Schaufler <casey@schaufler-ca.com>
@@@ -7877,13 -7828,6 +7883,13 @@@ F:    Documentation/sound/alsa/soc
  F:    sound/soc/
  F:    include/sound/soc*
  
 +SOUND - DMAENGINE HELPERS
 +M:    Lars-Peter Clausen <lars@metafoo.de>
 +S:    Supported
 +F:    include/sound/dmaengine_pcm.h
 +F:    sound/core/pcm_dmaengine.c
 +F:    sound/soc/soc-generic-dmaengine-pcm.c
 +
  SPARC + UltraSPARC (sparc/sparc64)
  M:    "David S. Miller" <davem@davemloft.net>
  L:    sparclinux@vger.kernel.org
@@@ -8041,7 -7985,7 +8047,7 @@@ S:      Maintaine
  F:    drivers/staging/media/go7007/
  
  STAGING - INDUSTRIAL IO
 -M:    Jonathan Cameron <jic23@cam.ac.uk>
 +M:    Jonathan Cameron <jic23@kernel.org>
  L:    linux-iio@vger.kernel.org
  S:    Odd Fixes
  F:    drivers/staging/iio/
@@@ -8568,7 -8512,6 +8574,7 @@@ F:      drivers/media/usb/tm6000
  TPM DEVICE DRIVER
  M:    Leonidas Da Silva Barbosa <leosilva@linux.vnet.ibm.com>
  M:    Ashley Lai <ashley@ashleylai.com>
 +M:    Peter Huewe <peterhuewe@gmx.de>
  M:    Rajiv Andrade <mail@srajiv.net>
  W:    http://tpmdd.sourceforge.net
  M:    Marcel Selhorst <tpmdd@selhorst.net>
@@@ -8665,6 -8608,14 +8671,6 @@@ S:     Maintaine
  F:    arch/m68k/*/*_no.*
  F:    arch/m68k/include/asm/*_no.*
  
 -UCLINUX FOR RENESAS H8/300 (H8300)
 -M:    Yoshinori Sato <ysato@users.sourceforge.jp>
 -W:    http://uclinux-h8.sourceforge.jp/
 -S:    Supported
 -F:    arch/h8300/
 -F:    drivers/ide/ide-h8300.c
 -F:    drivers/net/ethernet/8390/ne-h8300.c
 -
  UDF FILESYSTEM
  M:    Jan Kara <jack@suse.cz>
  S:    Maintained
diff --combined arch/arm/Kconfig
index 5e27ab643757e84871ef6616b5ae8acb100d72d7,c6debe07f036c45169f4612aae6e420546fcfcfb..e64b97c8f0fe556681a476752baf8dcd8a7ea456
@@@ -5,8 -5,6 +5,8 @@@ config AR
        select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
        select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
        select ARCH_HAVE_CUSTOM_GPIO_H
 +      select ARCH_USE_CMPXCHG_LOCKREF
 +      select ARCH_MIGHT_HAVE_PC_PARPORT
        select ARCH_WANT_IPC_PARSE_VERSION
        select BUILDTIME_EXTABLE_SORT if MMU
        select CLONE_BACKWARDS
        select HAVE_MOD_ARCH_SPECIFIC if ARM_UNWIND
        select HAVE_OPROFILE if (HAVE_PERF_EVENTS)
        select HAVE_PERF_EVENTS
 +      select HAVE_PERF_REGS
 +      select HAVE_PERF_USER_STACK_DUMP
        select HAVE_REGS_AND_STACK_ACCESS_API
        select HAVE_SYSCALL_TRACEPOINTS
        select HAVE_UID16
 +      select HAVE_VIRT_CPU_ACCOUNTING_GEN
        select IRQ_FORCED_THREADING
        select KTIME_SCALAR
        select MODULES_USE_ELF_REL
@@@ -393,7 -388,6 +393,6 @@@ config ARCH_GEMIN
        select ARCH_REQUIRE_GPIOLIB
        select ARCH_USES_GETTIMEOFFSET
        select CPU_FA526
-       select NEED_MACH_GPIO_H
        help
          Support for the Cortina Systems Gemini family SoCs
  
@@@ -462,7 -456,7 +461,7 @@@ config ARCH_IOP32
        depends on MMU
        select ARCH_REQUIRE_GPIOLIB
        select CPU_XSCALE
-       select NEED_MACH_GPIO_H
+       select GPIO_IOP
        select NEED_RET_TO_USER
        select PCI
        select PLAT_IOP
@@@ -475,7 -469,7 +474,7 @@@ config ARCH_IOP33
        depends on MMU
        select ARCH_REQUIRE_GPIOLIB
        select CPU_XSCALE
-       select NEED_MACH_GPIO_H
+       select GPIO_IOP
        select NEED_RET_TO_USER
        select PCI
        select PLAT_IOP
@@@ -564,7 -558,6 +563,6 @@@ config ARCH_MM
        select GPIO_PXA
        select IRQ_DOMAIN
        select MULTI_IRQ_HANDLER
-       select NEED_MACH_GPIO_H
        select PINCTRL
        select PLAT_PXA
        select SPARSE_IRQ
@@@ -627,7 -620,6 +625,6 @@@ config ARCH_PX
        select GPIO_PXA
        select HAVE_IDE
        select MULTI_IRQ_HANDLER
-       select NEED_MACH_GPIO_H
        select PLAT_PXA
        select SPARSE_IRQ
        help
@@@ -697,6 -689,7 +694,6 @@@ config ARCH_SA110
        select GENERIC_CLOCKEVENTS
        select HAVE_IDE
        select ISA
 -      select NEED_MACH_GPIO_H
        select NEED_MACH_MEMORY_H
        select SPARSE_IRQ
        help
@@@ -1553,32 -1546,6 +1550,32 @@@ config MCP
          for (multi-)cluster based systems, such as big.LITTLE based
          systems.
  
 +config BIG_LITTLE
 +      bool "big.LITTLE support (Experimental)"
 +      depends on CPU_V7 && SMP
 +      select MCPM
 +      help
 +        This option enables support selections for the big.LITTLE
 +        system architecture.
 +
 +config BL_SWITCHER
 +      bool "big.LITTLE switcher support"
 +      depends on BIG_LITTLE && MCPM && HOTPLUG_CPU
 +      select CPU_PM
 +      select ARM_CPU_SUSPEND
 +      help
 +        The big.LITTLE "switcher" provides the core functionality to
 +        transparently handle transition between a cluster of A15's
 +        and a cluster of A7's in a big.LITTLE system.
 +
 +config BL_SWITCHER_DUMMY_IF
 +      tristate "Simple big.LITTLE switcher user interface"
 +      depends on BL_SWITCHER && DEBUG_KERNEL
 +      help
 +        This is a simple and dummy char dev interface to control
 +        the big.LITTLE switcher core code.  It is meant for
 +        debugging purposes only.
 +
  choice
        prompt "Memory split"
        default VMSPLIT_3G
index de9630b08b99d9c87ba3b3cedd7d03110cd41983,b350649b976455c7ed3df2067057d8b7a33a1712..914e859e3eda38724642a8bdf60ea8bb7d4adcd6
@@@ -14,7 -14,6 +14,7 @@@
  #include <linux/io.h>
  #include <linux/of.h>
  #include <linux/of_gpio.h>
 +#include <linux/of_irq.h>
  #include <linux/gpio.h>
  #include <linux/slab.h>
  #include <linux/irq.h>
@@@ -283,16 -282,16 +283,16 @@@ static struct irq_chip mpc8xxx_irq_chi
        .irq_set_type   = mpc8xxx_irq_set_type,
  };
  
- static int mpc8xxx_gpio_irq_map(struct irq_domain *h, unsigned int virq,
-                               irq_hw_number_t hw)
+ static int mpc8xxx_gpio_irq_map(struct irq_domain *h, unsigned int irq,
+                               irq_hw_number_t hwirq)
  {
        struct mpc8xxx_gpio_chip *mpc8xxx_gc = h->host_data;
  
        if (mpc8xxx_gc->of_dev_id_data)
                mpc8xxx_irq_chip.irq_set_type = mpc8xxx_gc->of_dev_id_data;
  
-       irq_set_chip_data(virq, h->host_data);
-       irq_set_chip_and_handler(virq, &mpc8xxx_irq_chip, handle_level_irq);
+       irq_set_chip_data(irq, h->host_data);
+       irq_set_chip_and_handler(irq, &mpc8xxx_irq_chip, handle_level_irq);
  
        return 0;
  }
index e78760921bd72d9631ad89814f23fd15faf2331a,32a396d891beaad5188500a238d3b3760929f561..e0a98f581f58d5fd7266a4d805286d7df14e4452
  #include <linux/errno.h>
  #include <linux/module.h>
  #include <linux/io.h>
- #include <linux/gpio.h>
+ #include <linux/gpio/consumer.h>
  #include <linux/of.h>
  #include <linux/of_address.h>
  #include <linux/of_gpio.h>
  #include <linux/pinctrl/pinctrl.h>
  #include <linux/slab.h>
  
+ struct gpio_desc;
  /* Private data structure for of_gpiochip_find_and_xlate */
  struct gg_data {
        enum of_gpio_flags *flags;
        struct of_phandle_args gpiospec;
  
-       int out_gpio;
+       struct gpio_desc *out_gpio;
  };
  
  /* Private function for resolving node pointer to gpio_chip */
@@@ -45,28 -47,31 +47,31 @@@ static int of_gpiochip_find_and_xlate(s
        if (ret < 0)
                return false;
  
-       gg_data->out_gpio = ret + gc->base;
+       gg_data->out_gpio = gpio_to_desc(ret + gc->base);
        return true;
  }
  
  /**
-  * of_get_named_gpio_flags() - Get a GPIO number and flags to use with GPIO API
+  * of_get_named_gpiod_flags() - Get a GPIO descriptor and flags for GPIO API
   * @np:               device node to get GPIO from
   * @propname: property name containing gpio specifier(s)
   * @index:    index of the GPIO
   * @flags:    a flags pointer to fill in
   *
-  * Returns GPIO number to use with Linux generic GPIO API, or one of the errno
+  * Returns GPIO descriptor to use with Linux GPIO API, or one of the errno
   * value on the error condition. If @flags is not NULL the function also fills
   * in flags for the GPIO.
   */
int of_get_named_gpio_flags(struct device_node *np, const char *propname,
-                          int index, enum of_gpio_flags *flags)
struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
+                    const char *propname, int index, enum of_gpio_flags *flags)
  {
        /* Return -EPROBE_DEFER to support probe() functions to be called
         * later when the GPIO actually becomes available
         */
-       struct gg_data gg_data = { .flags = flags, .out_gpio = -EPROBE_DEFER };
+       struct gg_data gg_data = {
+               .flags = flags,
+               .out_gpio = ERR_PTR(-EPROBE_DEFER)
+       };
        int ret;
  
        /* .of_xlate might decide to not fill in the flags, so clear it. */
        if (ret) {
                pr_debug("%s: can't parse gpios property of node '%s[%d]'\n",
                        __func__, np->full_name, index);
-               return ret;
+               return ERR_PTR(ret);
        }
  
        gpiochip_find(&gg_data, of_gpiochip_find_and_xlate);
  
        of_node_put(gg_data.gpiospec.np);
-       pr_debug("%s exited with status %d\n", __func__, gg_data.out_gpio);
+       pr_debug("%s exited with status %d\n", __func__,
+                PTR_RET(gg_data.out_gpio));
        return gg_data.out_gpio;
  }
- EXPORT_SYMBOL(of_get_named_gpio_flags);
+ EXPORT_SYMBOL(of_get_named_gpiod_flags);
  
  /**
   * of_gpio_simple_xlate - translate gpio_spec to the GPIO number and flags
@@@ -190,15 -196,10 +196,15 @@@ static void of_gpiochip_add_pin_range(s
        struct of_phandle_args pinspec;
        struct pinctrl_dev *pctldev;
        int index = 0, ret;
 +      const char *name;
 +      static const char group_names_propname[] = "gpio-ranges-group-names";
 +      struct property *group_names;
  
        if (!np)
                return;
  
 +      group_names = of_find_property(np, group_names_propname, NULL);
 +
        for (;; index++) {
                ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3,
                                index, &pinspec);
                if (!pctldev)
                        break;
  
 -              ret = gpiochip_add_pin_range(chip,
 -                                           pinctrl_dev_get_devname(pctldev),
 -                                           pinspec.args[0],
 -                                           pinspec.args[1],
 -                                           pinspec.args[2]);
 -
 -              if (ret)
 -                      break;
 +              if (pinspec.args[2]) {
 +                      if (group_names) {
 +                              ret = of_property_read_string_index(np,
 +                                              group_names_propname,
 +                                              index, &name);
 +                              if (strlen(name)) {
 +                                      pr_err("%s: Group name of numeric GPIO ranges must be the empty string.\n",
 +                                              np->full_name);
 +                                      break;
 +                              }
 +                      }
 +                      /* npins != 0: linear range */
 +                      ret = gpiochip_add_pin_range(chip,
 +                                      pinctrl_dev_get_devname(pctldev),
 +                                      pinspec.args[0],
 +                                      pinspec.args[1],
 +                                      pinspec.args[2]);
 +                      if (ret)
 +                              break;
 +              } else {
 +                      /* npins == 0: special range */
 +                      if (pinspec.args[1]) {
 +                              pr_err("%s: Illegal gpio-range format.\n",
 +                                      np->full_name);
 +                              break;
 +                      }
 +
 +                      if (!group_names) {
 +                              pr_err("%s: GPIO group range requested but no %s property.\n",
 +                                      np->full_name, group_names_propname);
 +                              break;
 +                      }
 +
 +                      ret = of_property_read_string_index(np,
 +                                              group_names_propname,
 +                                              index, &name);
 +                      if (ret)
 +                              break;
 +
 +                      if (!strlen(name)) {
 +                              pr_err("%s: Group name of GPIO group range cannot be the empty string.\n",
 +                              np->full_name);
 +                              break;
 +                      }
 +
 +                      ret = gpiochip_add_pingroup_range(chip, pctldev,
 +                                              pinspec.args[0], name);
 +                      if (ret)
 +                              break;
 +              }
        }
  }
  
diff --combined drivers/gpio/gpiolib.c
index 4a34ca9c1768ea75fe7c8155bf8c07e2a7a11e7e,9f3326b95e6063ddd4b718791253bdb705451f70..7dd4461502940952ebf6323dbb04e1af7e6a5230
  #include <linux/seq_file.h>
  #include <linux/gpio.h>
  #include <linux/of_gpio.h>
+ #include <linux/acpi_gpio.h>
  #include <linux/idr.h>
  #include <linux/slab.h>
  
  #define CREATE_TRACE_POINTS
  #include <trace/events/gpio.h>
  
- /* Optional implementation infrastructure for GPIO interfaces.
+ /* Implementation infrastructure for GPIO interfaces.
   *
-  * Platforms may want to use this if they tend to use very many GPIOs
-  * that aren't part of a System-On-Chip core; or across I2C/SPI/etc.
-  *
-  * When kernel footprint or instruction count is an issue, simpler
-  * implementations may be preferred.  The GPIO programming interface
-  * allows for inlining speed-critical get/set operations for common
-  * cases, so that access to SOC-integrated GPIOs can sometimes cost
-  * only an instruction or two per bit.
+  * The GPIO programming interface allows for inlining speed-critical
+  * get/set operations for common cases, so that access to SOC-integrated
+  * GPIOs can sometimes cost only an instruction or two per bit.
   */
  
  
@@@ -57,9 -53,10 +53,10 @@@ struct gpio_desc 
  #define FLAG_SYSFS    3       /* exported via /sys/class/gpio/control */
  #define FLAG_TRIG_FALL        4       /* trigger on falling edge */
  #define FLAG_TRIG_RISE        5       /* trigger on rising edge */
- #define FLAG_ACTIVE_LOW       6       /* sysfs value has active low */
+ #define FLAG_ACTIVE_LOW       6       /* value has active low */
  #define FLAG_OPEN_DRAIN       7       /* Gpio is open drain type */
  #define FLAG_OPEN_SOURCE 8    /* Gpio is open source type */
+ #define FLAG_USED_AS_IRQ 9    /* GPIO is connected to an IRQ */
  
  #define ID_SHIFT      16      /* add new flags before this one */
  
@@@ -74,34 -71,50 +71,50 @@@ static struct gpio_desc gpio_desc[ARCH_
  
  #define GPIO_OFFSET_VALID(chip, offset) (offset >= 0 && offset < chip->ngpio)
  
+ static DEFINE_MUTEX(gpio_lookup_lock);
+ static LIST_HEAD(gpio_lookup_list);
  static LIST_HEAD(gpio_chips);
  
  #ifdef CONFIG_GPIO_SYSFS
  static DEFINE_IDR(dirent_idr);
  #endif
  
- /*
-  * Internal gpiod_* API using descriptors instead of the integer namespace.
-  * Most of this should eventually go public.
-  */
  static int gpiod_request(struct gpio_desc *desc, const char *label);
  static void gpiod_free(struct gpio_desc *desc);
- static int gpiod_direction_input(struct gpio_desc *desc);
- static int gpiod_direction_output(struct gpio_desc *desc, int value);
- static int gpiod_get_direction(const struct gpio_desc *desc);
- static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce);
- static int gpiod_get_value_cansleep(const struct gpio_desc *desc);
- static void gpiod_set_value_cansleep(struct gpio_desc *desc, int value);
- static int gpiod_get_value(const struct gpio_desc *desc);
- static void gpiod_set_value(struct gpio_desc *desc, int value);
- static int gpiod_cansleep(const struct gpio_desc *desc);
- static int gpiod_to_irq(const struct gpio_desc *desc);
- static int gpiod_export(struct gpio_desc *desc, bool direction_may_change);
- static int gpiod_export_link(struct device *dev, const char *name,
-                            struct gpio_desc *desc);
- static int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value);
- static void gpiod_unexport(struct gpio_desc *desc);
  
+ #ifdef CONFIG_DEBUG_FS
+ #define gpiod_emerg(desc, fmt, ...)                                   \
+       pr_emerg("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label, \
+                  ##__VA_ARGS__)
+ #define gpiod_crit(desc, fmt, ...)                                    \
+       pr_crit("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label,  \
+                  ##__VA_ARGS__)
+ #define gpiod_err(desc, fmt, ...)                                     \
+       pr_err("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label,   \
+                  ##__VA_ARGS__)
+ #define gpiod_warn(desc, fmt, ...)                                    \
+       pr_warn("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label,  \
+                  ##__VA_ARGS__)
+ #define gpiod_info(desc, fmt, ...)                                    \
+       pr_info("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label,  \
+                 ##__VA_ARGS__)
+ #define gpiod_dbg(desc, fmt, ...)                                \
+       pr_debug("gpio-%d (%s): " fmt, desc_to_gpio(desc), desc->label, \
+                  ##__VA_ARGS__)
+ #else
+ #define gpiod_emerg(desc, fmt, ...)                              \
+       pr_emerg("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__)
+ #define gpiod_crit(desc, fmt, ...)                               \
+       pr_crit("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__)
+ #define gpiod_err(desc, fmt, ...)                                \
+       pr_err("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__)
+ #define gpiod_warn(desc, fmt, ...)                               \
+       pr_warn("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__)
+ #define gpiod_info(desc, fmt, ...)                               \
+       pr_info("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__)
+ #define gpiod_dbg(desc, fmt, ...)                                \
+       pr_debug("gpio-%d: " fmt, desc_to_gpio(desc), ##__VA_ARGS__)
+ #endif
  
  static inline void desc_set_label(struct gpio_desc *d, const char *label)
  {
@@@ -121,23 -134,36 +134,36 @@@ static int gpio_chip_hwgpio(const struc
  /**
   * Convert a GPIO number to its descriptor
   */
- static struct gpio_desc *gpio_to_desc(unsigned gpio)
+ struct gpio_desc *gpio_to_desc(unsigned gpio)
  {
        if (WARN(!gpio_is_valid(gpio), "invalid GPIO %d\n", gpio))
                return NULL;
        else
                return &gpio_desc[gpio];
  }
+ EXPORT_SYMBOL_GPL(gpio_to_desc);
+ /**
+  * Convert an offset on a certain chip to a corresponding descriptor
+  */
+ static struct gpio_desc *gpiochip_offset_to_desc(struct gpio_chip *chip,
+                                                unsigned int offset)
+ {
+       unsigned int gpio = chip->base + offset;
+       return gpio_to_desc(gpio);
+ }
  
  /**
   * Convert a GPIO descriptor to the integer namespace.
   * This should disappear in the future but is needed since we still
   * use GPIO numbers for error messages and sysfs nodes
   */
static int desc_to_gpio(const struct gpio_desc *desc)
+ int desc_to_gpio(const struct gpio_desc *desc)
  {
        return desc - &gpio_desc[0];
  }
+ EXPORT_SYMBOL_GPL(desc_to_gpio);
  
  
  /* Warn when drivers omit gpio_request() calls -- legal but ill-advised
@@@ -172,16 -198,15 +198,15 @@@ static int gpio_ensure_requested(struc
        return 0;
  }
  
- static struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc)
+ /**
+  * gpiod_to_chip - Return the GPIO chip to which a GPIO descriptor belongs
+  * @desc:     descriptor to return the chip of
+  */
+ struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc)
  {
        return desc ? desc->chip : NULL;
  }
- /* caller holds gpio_lock *OR* gpio is marked as requested */
- struct gpio_chip *gpio_to_chip(unsigned gpio)
- {
-       return gpiod_to_chip(gpio_to_desc(gpio));
- }
+ EXPORT_SYMBOL_GPL(gpiod_to_chip);
  
  /* dynamic allocation of GPIOs, e.g. on a hotplugged device */
  static int gpiochip_find_base(int ngpio)
        }
  }
  
- /* caller ensures gpio is valid and requested, chip->get_direction may sleep  */
- static int gpiod_get_direction(const struct gpio_desc *desc)
+ /**
+  * gpiod_get_direction - return the current direction of a GPIO
+  * @desc:     GPIO to get the direction of
+  *
+  * Return GPIOF_DIR_IN or GPIOF_DIR_OUT, or an error code in case of error.
+  *
+  * This function may sleep if gpiod_cansleep() is true.
+  */
+ int gpiod_get_direction(const struct gpio_desc *desc)
  {
        struct gpio_chip        *chip;
        unsigned                offset;
        }
        return status;
  }
+ EXPORT_SYMBOL_GPL(gpiod_get_direction);
  
  #ifdef CONFIG_GPIO_SYSFS
  
@@@ -318,17 -351,10 +351,10 @@@ static ssize_t gpio_value_show(struct d
  
        mutex_lock(&sysfs_lock);
  
-       if (!test_bit(FLAG_EXPORT, &desc->flags)) {
+       if (!test_bit(FLAG_EXPORT, &desc->flags))
                status = -EIO;
-       } else {
-               int value;
-               value = !!gpiod_get_value_cansleep(desc);
-               if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
-                       value = !value;
-               status = sprintf(buf, "%d\n", value);
-       }
+       else
+               status = sprintf(buf, "%d\n", gpiod_get_value_cansleep(desc));
  
        mutex_unlock(&sysfs_lock);
        return status;
@@@ -351,9 -377,7 +377,7 @@@ static ssize_t gpio_value_store(struct 
  
                status = kstrtol(buf, 0, &value);
                if (status == 0) {
-                       if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
-                               value = !value;
-                       gpiod_set_value_cansleep(desc, value != 0);
+                       gpiod_set_value_cansleep(desc, value);
                        status = size;
                }
        }
@@@ -395,6 -419,7 +419,7 @@@ static int gpio_setup_irq(struct gpio_d
        desc->flags &= ~GPIO_TRIGGER_MASK;
  
        if (!gpio_flags) {
+               gpiod_unlock_as_irq(desc);
                ret = 0;
                goto free_id;
        }
                        IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
  
        if (!value_sd) {
 -              value_sd = sysfs_get_dirent(dev->kobj.sd, NULL, "value");
 +              value_sd = sysfs_get_dirent(dev->kobj.sd, "value");
                if (!value_sd) {
                        ret = -ENODEV;
                        goto err_out;
        if (ret < 0)
                goto free_id;
  
+       ret = gpiod_lock_as_irq(desc);
+       if (ret < 0) {
+               gpiod_warn(desc, "failed to flag the GPIO for IRQ\n");
+               goto free_id;
+       }
        desc->flags |= gpio_flags;
        return 0;
  
@@@ -736,7 -767,7 +767,7 @@@ static struct class gpio_class = 
  
  
  /**
-  * gpio_export - export a GPIO through sysfs
+  * gpiod_export - export a GPIO through sysfs
   * @gpio: gpio to make available, already requested
   * @direction_may_change: true if userspace may change gpio direction
   * Context: arch_initcall or later
   *
   * Returns zero on success, else an error.
   */
static int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
+ int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
  {
        unsigned long           flags;
        int                     status;
@@@ -828,12 -859,7 +859,7 @@@ fail_unlock
                 status);
        return status;
  }
- int gpio_export(unsigned gpio, bool direction_may_change)
- {
-       return gpiod_export(gpio_to_desc(gpio), direction_may_change);
- }
- EXPORT_SYMBOL_GPL(gpio_export);
+ EXPORT_SYMBOL_GPL(gpiod_export);
  
  static int match_export(struct device *dev, const void *data)
  {
  }
  
  /**
-  * gpio_export_link - create a sysfs link to an exported GPIO node
+  * gpiod_export_link - create a sysfs link to an exported GPIO node
   * @dev: device under which to create symlink
   * @name: name of the symlink
   * @gpio: gpio to create symlink to, already exported
   *
   * Returns zero on success, else an error.
   */
static int gpiod_export_link(struct device *dev, const char *name,
-                            struct gpio_desc *desc)
+ int gpiod_export_link(struct device *dev, const char *name,
+                     struct gpio_desc *desc)
  {
        int                     status = -EINVAL;
  
  
        return status;
  }
- int gpio_export_link(struct device *dev, const char *name, unsigned gpio)
- {
-       return gpiod_export_link(dev, name, gpio_to_desc(gpio));
- }
- EXPORT_SYMBOL_GPL(gpio_export_link);
+ EXPORT_SYMBOL_GPL(gpiod_export_link);
  
  /**
-  * gpio_sysfs_set_active_low - set the polarity of gpio sysfs value
+  * gpiod_sysfs_set_active_low - set the polarity of gpio sysfs value
   * @gpio: gpio to change
   * @value: non-zero to use active low, i.e. inverted values
   *
   *
   * Returns zero on success, else an error.
   */
static int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value)
+ int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value)
  {
        struct device           *dev = NULL;
        int                     status = -EINVAL;
@@@ -933,20 -954,15 +954,15 @@@ unlock
  
        return status;
  }
- int gpio_sysfs_set_active_low(unsigned gpio, int value)
- {
-       return gpiod_sysfs_set_active_low(gpio_to_desc(gpio), value);
- }
- EXPORT_SYMBOL_GPL(gpio_sysfs_set_active_low);
+ EXPORT_SYMBOL_GPL(gpiod_sysfs_set_active_low);
  
  /**
-  * gpio_unexport - reverse effect of gpio_export()
+  * gpiod_unexport - reverse effect of gpio_export()
   * @gpio: gpio to make unavailable
   *
   * This is implicit on gpio_free().
   */
static void gpiod_unexport(struct gpio_desc *desc)
+ void gpiod_unexport(struct gpio_desc *desc)
  {
        int                     status = 0;
        struct device           *dev = NULL;
                pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc),
                         status);
  }
- void gpio_unexport(unsigned gpio)
- {
-       gpiod_unexport(gpio_to_desc(gpio));
- }
- EXPORT_SYMBOL_GPL(gpio_unexport);
+ EXPORT_SYMBOL_GPL(gpiod_unexport);
  
  static int gpiochip_export(struct gpio_chip *chip)
  {
@@@ -1091,27 -1102,6 +1102,6 @@@ static inline void gpiochip_unexport(st
  {
  }
  
- static inline int gpiod_export(struct gpio_desc *desc,
-                              bool direction_may_change)
- {
-       return -ENOSYS;
- }
- static inline int gpiod_export_link(struct device *dev, const char *name,
-                                   struct gpio_desc *desc)
- {
-       return -ENOSYS;
- }
- static inline int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value)
- {
-       return -ENOSYS;
- }
- static inline void gpiod_unexport(struct gpio_desc *desc)
- {
- }
  #endif /* CONFIG_GPIO_SYSFS */
  
  /*
@@@ -1319,53 -1309,6 +1309,53 @@@ EXPORT_SYMBOL_GPL(gpiochip_find)
  
  #ifdef CONFIG_PINCTRL
  
 +/**
 + * gpiochip_add_pingroup_range() - add a range for GPIO <-> pin mapping
 + * @chip: the gpiochip to add the range for
 + * @pinctrl: the dev_name() of the pin controller to map to
 + * @gpio_offset: the start offset in the current gpio_chip number space
 + * @pin_group: name of the pin group inside the pin controller
 + */
 +int gpiochip_add_pingroup_range(struct gpio_chip *chip,
 +                      struct pinctrl_dev *pctldev,
 +                      unsigned int gpio_offset, const char *pin_group)
 +{
 +      struct gpio_pin_range *pin_range;
 +      int ret;
 +
 +      pin_range = kzalloc(sizeof(*pin_range), GFP_KERNEL);
 +      if (!pin_range) {
 +              pr_err("%s: GPIO chip: failed to allocate pin ranges\n",
 +                              chip->label);
 +              return -ENOMEM;
 +      }
 +
 +      /* Use local offset as range ID */
 +      pin_range->range.id = gpio_offset;
 +      pin_range->range.gc = chip;
 +      pin_range->range.name = chip->label;
 +      pin_range->range.base = chip->base + gpio_offset;
 +      pin_range->pctldev = pctldev;
 +
 +      ret = pinctrl_get_group_pins(pctldev, pin_group,
 +                                      &pin_range->range.pins,
 +                                      &pin_range->range.npins);
 +      if (ret < 0)
 +              return ret;
 +
 +      pinctrl_add_gpio_range(pctldev, &pin_range->range);
 +
 +      pr_debug("GPIO chip %s: created GPIO range %d->%d ==> %s PINGRP %s\n",
 +               chip->label, gpio_offset,
 +               gpio_offset + pin_range->range.npins - 1,
 +               pinctrl_dev_get_devname(pctldev), pin_group);
 +
 +      list_add_tail(&pin_range->node, &chip->pin_ranges);
 +
 +      return 0;
 +}
 +EXPORT_SYMBOL_GPL(gpiochip_add_pingroup_range);
 +
  /**
   * gpiochip_add_pin_range() - add a range for GPIO <-> pin mapping
   * @chip: the gpiochip to add the range for
@@@ -1670,7 -1613,16 +1660,16 @@@ EXPORT_SYMBOL_GPL(gpiochip_is_requested
   * rely on gpio_request() having been called beforehand.
   */
  
- static int gpiod_direction_input(struct gpio_desc *desc)
+ /**
+  * gpiod_direction_input - set the GPIO direction to input
+  * @desc:     GPIO to set to input
+  *
+  * Set the direction of the passed GPIO to input, such as gpiod_get_value() can
+  * be called safely on it.
+  *
+  * Return 0 in case of success, else an error code.
+  */
+ int gpiod_direction_input(struct gpio_desc *desc)
  {
        unsigned long           flags;
        struct gpio_chip        *chip;
  
        chip = desc->chip;
        if (!chip->get || !chip->direction_input) {
-               pr_warn("%s: missing get() or direction_input() operations\n",
-                       __func__);
+               gpiod_warn(desc,
+                       "%s: missing get() or direction_input() operations\n",
+                        __func__);
                return -EIO;
        }
  
        if (status) {
                status = chip->request(chip, offset);
                if (status < 0) {
-                       pr_debug("GPIO-%d: chip request fail, %d\n",
-                               desc_to_gpio(desc), status);
+                       gpiod_dbg(desc, "chip request fail, %d\n", status);
                        /* and it's not available to anyone else ...
                         * gpio_request() is the fully clean solution.
                         */
@@@ -1724,18 -1676,22 +1723,22 @@@ lose
  fail:
        spin_unlock_irqrestore(&gpio_lock, flags);
        if (status)
-               pr_debug("%s: gpio-%d status %d\n", __func__,
-                        desc_to_gpio(desc), status);
+               gpiod_dbg(desc, "%s status %d\n", __func__, status);
        return status;
  }
+ EXPORT_SYMBOL_GPL(gpiod_direction_input);
  
- int gpio_direction_input(unsigned gpio)
- {
-       return gpiod_direction_input(gpio_to_desc(gpio));
- }
- EXPORT_SYMBOL_GPL(gpio_direction_input);
- static int gpiod_direction_output(struct gpio_desc *desc, int value)
+ /**
+  * gpiod_direction_output - set the GPIO direction to input
+  * @desc:     GPIO to set to output
+  * @value:    initial output value of the GPIO
+  *
+  * Set the direction of the passed GPIO to output, such as gpiod_set_value() can
+  * be called safely on it. The initial value of the output must be specified.
+  *
+  * Return 0 in case of success, else an error code.
+  */
+ int gpiod_direction_output(struct gpio_desc *desc, int value)
  {
        unsigned long           flags;
        struct gpio_chip        *chip;
                return -EINVAL;
        }
  
+       /* GPIOs used for IRQs shall not be set as output */
+       if (test_bit(FLAG_USED_AS_IRQ, &desc->flags)) {
+               gpiod_err(desc,
+                         "%s: tried to set a GPIO tied to an IRQ as output\n",
+                         __func__);
+               return -EIO;
+       }
        /* Open drain pin should not be driven to 1 */
        if (value && test_bit(FLAG_OPEN_DRAIN,  &desc->flags))
                return gpiod_direction_input(desc);
  
        chip = desc->chip;
        if (!chip->set || !chip->direction_output) {
-               pr_warn("%s: missing set() or direction_output() operations\n",
-                       __func__);
+               gpiod_warn(desc,
+                      "%s: missing set() or direction_output() operations\n",
+                      __func__);
                return -EIO;
        }
  
        if (status) {
                status = chip->request(chip, offset);
                if (status < 0) {
-                       pr_debug("GPIO-%d: chip request fail, %d\n",
-                               desc_to_gpio(desc), status);
+                       gpiod_dbg(desc, "chip request fail, %d\n", status);
                        /* and it's not available to anyone else ...
                         * gpio_request() is the fully clean solution.
                         */
@@@ -1797,26 -1761,20 +1808,20 @@@ lose
  fail:
        spin_unlock_irqrestore(&gpio_lock, flags);
        if (status)
-               pr_debug("%s: gpio-%d status %d\n", __func__,
-                        desc_to_gpio(desc), status);
+               gpiod_dbg(desc, "%s: gpio status %d\n", __func__, status);
        return status;
  }
- int gpio_direction_output(unsigned gpio, int value)
- {
-       return gpiod_direction_output(gpio_to_desc(gpio), value);
- }
- EXPORT_SYMBOL_GPL(gpio_direction_output);
+ EXPORT_SYMBOL_GPL(gpiod_direction_output);
  
  /**
-  * gpio_set_debounce - sets @debounce time for a @gpio
+  * gpiod_set_debounce - sets @debounce time for a @gpio
   * @gpio: the gpio to set debounce time
   * @debounce: debounce time is microseconds
   *
   * returns -ENOTSUPP if the controller does not support setting
   * debounce.
   */
static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
+ int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
  {
        unsigned long           flags;
        struct gpio_chip        *chip;
  
        chip = desc->chip;
        if (!chip->set || !chip->set_debounce) {
-               pr_debug("%s: missing set() or set_debounce() operations\n",
-                       __func__);
+               gpiod_dbg(desc,
+                         "%s: missing set() or set_debounce() operations\n",
+                         __func__);
                return -ENOTSUPP;
        }
  
  fail:
        spin_unlock_irqrestore(&gpio_lock, flags);
        if (status)
-               pr_debug("%s: gpio-%d status %d\n", __func__,
-                        desc_to_gpio(desc), status);
+               gpiod_dbg(desc, "%s: status %d\n", __func__, status);
  
        return status;
  }
+ EXPORT_SYMBOL_GPL(gpiod_set_debounce);
  
- int gpio_set_debounce(unsigned gpio, unsigned debounce)
+ /**
+  * gpiod_is_active_low - test whether a GPIO is active-low or not
+  * @desc: the gpio descriptor to test
+  *
+  * Returns 1 if the GPIO is active-low, 0 otherwise.
+  */
+ int gpiod_is_active_low(const struct gpio_desc *desc)
  {
-       return gpiod_set_debounce(gpio_to_desc(gpio), debounce);
+       return test_bit(FLAG_ACTIVE_LOW, &desc->flags);
  }
- EXPORT_SYMBOL_GPL(gpio_set_debounce);
+ EXPORT_SYMBOL_GPL(gpiod_is_active_low);
  
  /* I/O calls are only valid after configuration completed; the relevant
   * "is this a valid GPIO" error checks should already have been done.
   * that the GPIO was actually requested.
   */
  
- /**
-  * __gpio_get_value() - return a gpio's value
-  * @gpio: gpio whose value will be returned
-  * Context: any
-  *
-  * This is used directly or indirectly to implement gpio_get_value().
-  * It returns the zero or nonzero value provided by the associated
-  * gpio_chip.get() method; or zero if no such method is provided.
-  */
- static int gpiod_get_value(const struct gpio_desc *desc)
+ static int _gpiod_get_raw_value(const struct gpio_desc *desc)
  {
        struct gpio_chip        *chip;
        int value;
        int offset;
  
-       if (!desc)
-               return 0;
        chip = desc->chip;
        offset = gpio_chip_hwgpio(desc);
-       /* Should be using gpio_get_value_cansleep() */
-       WARN_ON(chip->can_sleep);
        value = chip->get ? chip->get(chip, offset) : 0;
        trace_gpio_value(desc_to_gpio(desc), 1, value);
        return value;
  }
  
- int __gpio_get_value(unsigned gpio)
+ /**
+  * gpiod_get_raw_value() - return a gpio's raw value
+  * @desc: gpio whose value will be returned
+  *
+  * Return the GPIO's raw value, i.e. the value of the physical line disregarding
+  * its ACTIVE_LOW status.
+  *
+  * This function should be called from contexts where we cannot sleep, and will
+  * complain if the GPIO chip functions potentially sleep.
+  */
+ int gpiod_get_raw_value(const struct gpio_desc *desc)
+ {
+       if (!desc)
+               return 0;
+       /* Should be using gpio_get_value_cansleep() */
+       WARN_ON(desc->chip->can_sleep);
+       return _gpiod_get_raw_value(desc);
+ }
+ EXPORT_SYMBOL_GPL(gpiod_get_raw_value);
+ /**
+  * gpiod_get_value() - return a gpio's value
+  * @desc: gpio whose value will be returned
+  *
+  * Return the GPIO's logical value, i.e. taking the ACTIVE_LOW status into
+  * account.
+  *
+  * This function should be called from contexts where we cannot sleep, and will
+  * complain if the GPIO chip functions potentially sleep.
+  */
+ int gpiod_get_value(const struct gpio_desc *desc)
  {
-       return gpiod_get_value(gpio_to_desc(gpio));
+       int value;
+       if (!desc)
+               return 0;
+       /* Should be using gpio_get_value_cansleep() */
+       WARN_ON(desc->chip->can_sleep);
+       value = _gpiod_get_raw_value(desc);
+       if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
+               value = !value;
+       return value;
  }
- EXPORT_SYMBOL_GPL(__gpio_get_value);
+ EXPORT_SYMBOL_GPL(gpiod_get_value);
  
  /*
   *  _gpio_set_open_drain_value() - Set the open drain gpio's value.
-  * @gpio: Gpio whose state need to be set.
-  * @chip: Gpio chip.
+  * @desc: gpio descriptor whose state need to be set.
   * @value: Non-zero for setting it HIGH otherise it will set to LOW.
   */
  static void _gpio_set_open_drain_value(struct gpio_desc *desc, int value)
        }
        trace_gpio_direction(desc_to_gpio(desc), value, err);
        if (err < 0)
-               pr_err("%s: Error in set_value for open drain gpio%d err %d\n",
-                                       __func__, desc_to_gpio(desc), err);
+               gpiod_err(desc,
+                         "%s: Error in set_value for open drain err %d\n",
+                         __func__, err);
  }
  
  /*
-  *  _gpio_set_open_source() - Set the open source gpio's value.
-  * @gpio: Gpio whose state need to be set.
-  * @chip: Gpio chip.
+  *  _gpio_set_open_source_value() - Set the open source gpio's value.
+  * @desc: gpio descriptor whose state need to be set.
   * @value: Non-zero for setting it HIGH otherise it will set to LOW.
   */
  static void _gpio_set_open_source_value(struct gpio_desc *desc, int value)
        }
        trace_gpio_direction(desc_to_gpio(desc), !value, err);
        if (err < 0)
-               pr_err("%s: Error in set_value for open source gpio%d err %d\n",
-                                       __func__, desc_to_gpio(desc), err);
+               gpiod_err(desc,
+                         "%s: Error in set_value for open source err %d\n",
+                         __func__, err);
  }
  
- /**
-  * __gpio_set_value() - assign a gpio's value
-  * @gpio: gpio whose value will be assigned
-  * @value: value to assign
-  * Context: any
-  *
-  * This is used directly or indirectly to implement gpio_set_value().
-  * It invokes the associated gpio_chip.set() method.
-  */
- static void gpiod_set_value(struct gpio_desc *desc, int value)
+ static void _gpiod_set_raw_value(struct gpio_desc *desc, int value)
  {
        struct gpio_chip        *chip;
  
-       if (!desc)
-               return;
        chip = desc->chip;
-       /* Should be using gpio_set_value_cansleep() */
-       WARN_ON(chip->can_sleep);
        trace_gpio_value(desc_to_gpio(desc), 0, value);
        if (test_bit(FLAG_OPEN_DRAIN, &desc->flags))
                _gpio_set_open_drain_value(desc, value);
                chip->set(chip, gpio_chip_hwgpio(desc), value);
  }
  
- void __gpio_set_value(unsigned gpio, int value)
+ /**
+  * gpiod_set_raw_value() - assign a gpio's raw value
+  * @desc: gpio whose value will be assigned
+  * @value: value to assign
+  *
+  * Set the raw value of the GPIO, i.e. the value of its physical line without
+  * regard for its ACTIVE_LOW status.
+  *
+  * This function should be called from contexts where we cannot sleep, and will
+  * complain if the GPIO chip functions potentially sleep.
+  */
+ void gpiod_set_raw_value(struct gpio_desc *desc, int value)
  {
-       return gpiod_set_value(gpio_to_desc(gpio), value);
+       if (!desc)
+               return;
+       /* Should be using gpio_set_value_cansleep() */
+       WARN_ON(desc->chip->can_sleep);
+       _gpiod_set_raw_value(desc, value);
  }
- EXPORT_SYMBOL_GPL(__gpio_set_value);
+ EXPORT_SYMBOL_GPL(gpiod_set_raw_value);
  
  /**
-  * __gpio_cansleep() - report whether gpio value access will sleep
-  * @gpio: gpio in question
-  * Context: any
+  * gpiod_set_value() - assign a gpio's value
+  * @desc: gpio whose value will be assigned
+  * @value: value to assign
+  *
+  * Set the logical value of the GPIO, i.e. taking its ACTIVE_LOW status into
+  * account
   *
-  * This is used directly or indirectly to implement gpio_cansleep().  It
-  * returns nonzero if access reading or writing the GPIO value can sleep.
+  * This function should be called from contexts where we cannot sleep, and will
+  * complain if the GPIO chip functions potentially sleep.
   */
static int gpiod_cansleep(const struct gpio_desc *desc)
void gpiod_set_value(struct gpio_desc *desc, int value)
  {
        if (!desc)
-               return 0;
-       /* only call this on GPIOs that are valid! */
-       return desc->chip->can_sleep;
+               return;
+       /* Should be using gpio_set_value_cansleep() */
+       WARN_ON(desc->chip->can_sleep);
+       if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
+               value = !value;
+       _gpiod_set_raw_value(desc, value);
  }
+ EXPORT_SYMBOL_GPL(gpiod_set_value);
  
- int __gpio_cansleep(unsigned gpio)
+ /**
+  * gpiod_cansleep() - report whether gpio value access may sleep
+  * @desc: gpio to check
+  *
+  */
+ int gpiod_cansleep(const struct gpio_desc *desc)
  {
-       return gpiod_cansleep(gpio_to_desc(gpio));
+       if (!desc)
+               return 0;
+       return desc->chip->can_sleep;
  }
- EXPORT_SYMBOL_GPL(__gpio_cansleep);
+ EXPORT_SYMBOL_GPL(gpiod_cansleep);
  
  /**
-  * __gpio_to_irq() - return the IRQ corresponding to a GPIO
-  * @gpio: gpio whose IRQ will be returned (already requested)
-  * Context: any
+  * gpiod_to_irq() - return the IRQ corresponding to a GPIO
+  * @desc: gpio whose IRQ will be returned (already requested)
   *
-  * This is used directly or indirectly to implement gpio_to_irq().
-  * It returns the number of the IRQ signaled by this (input) GPIO,
-  * or a negative errno.
+  * Return the IRQ corresponding to the passed GPIO, or an error code in case of
+  * error.
   */
static int gpiod_to_irq(const struct gpio_desc *desc)
+ int gpiod_to_irq(const struct gpio_desc *desc)
  {
        struct gpio_chip        *chip;
        int                     offset;
        offset = gpio_chip_hwgpio(desc);
        return chip->to_irq ? chip->to_irq(chip, offset) : -ENXIO;
  }
+ EXPORT_SYMBOL_GPL(gpiod_to_irq);
  
- int __gpio_to_irq(unsigned gpio)
+ /**
+  * gpiod_lock_as_irq() - lock a GPIO to be used as IRQ
+  * @gpio: the GPIO line to lock as used for IRQ
+  *
+  * This is used directly by GPIO drivers that want to lock down
+  * a certain GPIO line to be used as IRQs, for example in the
+  * .to_irq() callback of their gpio_chip, or in the .irq_enable()
+  * of its irq_chip implementation if the GPIO is known from that
+  * code.
+  */
+ int gpiod_lock_as_irq(struct gpio_desc *desc)
  {
-       return gpiod_to_irq(gpio_to_desc(gpio));
+       if (!desc)
+               return -EINVAL;
+       if (test_bit(FLAG_IS_OUT, &desc->flags)) {
+               gpiod_err(desc,
+                         "%s: tried to flag a GPIO set as output for IRQ\n",
+                         __func__);
+               return -EIO;
+       }
+       set_bit(FLAG_USED_AS_IRQ, &desc->flags);
+       return 0;
  }
- EXPORT_SYMBOL_GPL(__gpio_to_irq);
+ EXPORT_SYMBOL_GPL(gpiod_lock_as_irq);
  
+ int gpio_lock_as_irq(struct gpio_chip *chip, unsigned int offset)
+ {
+       return gpiod_lock_as_irq(gpiochip_offset_to_desc(chip, offset));
+ }
+ EXPORT_SYMBOL_GPL(gpio_lock_as_irq);
  
- /* There's no value in making it easy to inline GPIO calls that may sleep.
-  * Common examples include ones connected to I2C or SPI chips.
+ /**
+  * gpiod_unlock_as_irq() - unlock a GPIO used as IRQ
+  * @gpio: the GPIO line to unlock from IRQ usage
+  *
+  * This is used directly by GPIO drivers that want to indicate
+  * that a certain GPIO is no longer used exclusively for IRQ.
   */
+ void gpiod_unlock_as_irq(struct gpio_desc *desc)
+ {
+       if (!desc)
+               return;
  
- static int gpiod_get_value_cansleep(const struct gpio_desc *desc)
+       clear_bit(FLAG_USED_AS_IRQ, &desc->flags);
+ }
+ EXPORT_SYMBOL_GPL(gpiod_unlock_as_irq);
+ void gpio_unlock_as_irq(struct gpio_chip *chip, unsigned int offset)
+ {
+       return gpiod_unlock_as_irq(gpiochip_offset_to_desc(chip, offset));
+ }
+ EXPORT_SYMBOL_GPL(gpio_unlock_as_irq);
+ /**
+  * gpiod_get_raw_value_cansleep() - return a gpio's raw value
+  * @desc: gpio whose value will be returned
+  *
+  * Return the GPIO's raw value, i.e. the value of the physical line disregarding
+  * its ACTIVE_LOW status.
+  *
+  * This function is to be called from contexts that can sleep.
+  */
+ int gpiod_get_raw_value_cansleep(const struct gpio_desc *desc)
+ {
+       might_sleep_if(extra_checks);
+       if (!desc)
+               return 0;
+       return _gpiod_get_raw_value(desc);
+ }
+ EXPORT_SYMBOL_GPL(gpiod_get_raw_value_cansleep);
+ /**
+  * gpiod_get_value_cansleep() - return a gpio's value
+  * @desc: gpio whose value will be returned
+  *
+  * Return the GPIO's logical value, i.e. taking the ACTIVE_LOW status into
+  * account.
+  *
+  * This function is to be called from contexts that can sleep.
+  */
+ int gpiod_get_value_cansleep(const struct gpio_desc *desc)
  {
-       struct gpio_chip        *chip;
        int value;
-       int offset;
  
        might_sleep_if(extra_checks);
        if (!desc)
                return 0;
-       chip = desc->chip;
-       offset = gpio_chip_hwgpio(desc);
-       value = chip->get ? chip->get(chip, offset) : 0;
-       trace_gpio_value(desc_to_gpio(desc), 1, value);
+       value = _gpiod_get_raw_value(desc);
+       if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
+               value = !value;
        return value;
  }
+ EXPORT_SYMBOL_GPL(gpiod_get_value_cansleep);
  
- int gpio_get_value_cansleep(unsigned gpio)
+ /**
+  * gpiod_set_raw_value_cansleep() - assign a gpio's raw value
+  * @desc: gpio whose value will be assigned
+  * @value: value to assign
+  *
+  * Set the raw value of the GPIO, i.e. the value of its physical line without
+  * regard for its ACTIVE_LOW status.
+  *
+  * This function is to be called from contexts that can sleep.
+  */
+ void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, int value)
  {
-       return gpiod_get_value_cansleep(gpio_to_desc(gpio));
+       might_sleep_if(extra_checks);
+       if (!desc)
+               return;
+       _gpiod_set_raw_value(desc, value);
  }
- EXPORT_SYMBOL_GPL(gpio_get_value_cansleep);
+ EXPORT_SYMBOL_GPL(gpiod_set_raw_value_cansleep);
  
- static void gpiod_set_value_cansleep(struct gpio_desc *desc, int value)
+ /**
+  * gpiod_set_value_cansleep() - assign a gpio's value
+  * @desc: gpio whose value will be assigned
+  * @value: value to assign
+  *
+  * Set the logical value of the GPIO, i.e. taking its ACTIVE_LOW status into
+  * account
+  *
+  * This function is to be called from contexts that can sleep.
+  */
+ void gpiod_set_value_cansleep(struct gpio_desc *desc, int value)
  {
-       struct gpio_chip        *chip;
        might_sleep_if(extra_checks);
        if (!desc)
                return;
-       chip = desc->chip;
-       trace_gpio_value(desc_to_gpio(desc), 0, value);
-       if (test_bit(FLAG_OPEN_DRAIN,  &desc->flags))
-               _gpio_set_open_drain_value(desc, value);
-       else if (test_bit(FLAG_OPEN_SOURCE,  &desc->flags))
-               _gpio_set_open_source_value(desc, value);
+       if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
+               value = !value;
+       _gpiod_set_raw_value(desc, value);
+ }
+ EXPORT_SYMBOL_GPL(gpiod_set_value_cansleep);
+ /**
+  * gpiod_add_table() - register GPIO device consumers
+  * @table: array of consumers to register
+  * @num: number of consumers in table
+  */
+ void gpiod_add_table(struct gpiod_lookup *table, size_t size)
+ {
+       mutex_lock(&gpio_lookup_lock);
+       while (size--) {
+               list_add_tail(&table->list, &gpio_lookup_list);
+               table++;
+       }
+       mutex_unlock(&gpio_lookup_lock);
+ }
+ /*
+  * Caller must have a acquired gpio_lookup_lock
+  */
+ static struct gpio_chip *find_chip_by_name(const char *name)
+ {
+       struct gpio_chip *chip = NULL;
+       list_for_each_entry(chip, &gpio_lookup_list, list) {
+               if (chip->label == NULL)
+                       continue;
+               if (!strcmp(chip->label, name))
+                       break;
+       }
+       return chip;
+ }
+ #ifdef CONFIG_OF
+ static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
+                                     unsigned int idx, unsigned long *flags)
+ {
+       char prop_name[32]; /* 32 is max size of property name */
+       enum of_gpio_flags of_flags;
+       struct gpio_desc *desc;
+       if (con_id)
+               snprintf(prop_name, 32, "%s-gpios", con_id);
        else
-               chip->set(chip, gpio_chip_hwgpio(desc), value);
+               snprintf(prop_name, 32, "gpios");
+       desc = of_get_named_gpiod_flags(dev->of_node, prop_name, idx,
+                                       &of_flags);
+       if (IS_ERR(desc))
+               return desc;
+       if (of_flags & OF_GPIO_ACTIVE_LOW)
+               *flags |= GPIOF_ACTIVE_LOW;
+       return desc;
+ }
+ #else
+ static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
+                                     unsigned int idx, unsigned long *flags)
+ {
+       return ERR_PTR(-ENODEV);
  }
+ #endif
  
- void gpio_set_value_cansleep(unsigned gpio, int value)
+ static struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id,
+                                       unsigned int idx, unsigned long *flags)
  {
-       return gpiod_set_value_cansleep(gpio_to_desc(gpio), value);
+       struct acpi_gpio_info info;
+       struct gpio_desc *desc;
+       desc = acpi_get_gpiod_by_index(dev, idx, &info);
+       if (IS_ERR(desc))
+               return desc;
+       if (info.gpioint && info.active_low)
+               *flags |= GPIOF_ACTIVE_LOW;
+       return desc;
+ }
+ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id,
+                                   unsigned int idx, unsigned long *flags)
+ {
+       const char *dev_id = dev ? dev_name(dev) : NULL;
+       struct gpio_desc *desc = ERR_PTR(-ENODEV);
+       unsigned int match, best = 0;
+       struct gpiod_lookup *p;
+       mutex_lock(&gpio_lookup_lock);
+       list_for_each_entry(p, &gpio_lookup_list, list) {
+               match = 0;
+               if (p->dev_id) {
+                       if (!dev_id || strcmp(p->dev_id, dev_id))
+                               continue;
+                       match += 2;
+               }
+               if (p->con_id) {
+                       if (!con_id || strcmp(p->con_id, con_id))
+                               continue;
+                       match += 1;
+               }
+               if (p->idx != idx)
+                       continue;
+               if (match > best) {
+                       struct gpio_chip *chip;
+                       chip = find_chip_by_name(p->chip_label);
+                       if (!chip) {
+                               dev_warn(dev, "cannot find GPIO chip %s\n",
+                                        p->chip_label);
+                               continue;
+                       }
+                       if (chip->ngpio >= p->chip_hwnum) {
+                               dev_warn(dev, "GPIO chip %s has %d GPIOs\n",
+                                        chip->label, chip->ngpio);
+                               continue;
+                       }
+                       desc = gpio_to_desc(chip->base + p->chip_hwnum);
+                       *flags = p->flags;
+                       if (match != 3)
+                               best = match;
+                       else
+                               break;
+               }
+       }
+       mutex_unlock(&gpio_lookup_lock);
+       return desc;
+ }
+ /**
+  * gpio_get - obtain a GPIO for a given GPIO function
+  * @dev:      GPIO consumer
+  * @con_id:   function within the GPIO consumer
+  *
+  * Return the GPIO descriptor corresponding to the function con_id of device
+  * dev, or an IS_ERR() condition if an error occured.
+  */
+ struct gpio_desc *__must_check gpiod_get(struct device *dev, const char *con_id)
+ {
+       return gpiod_get_index(dev, con_id, 0);
+ }
+ EXPORT_SYMBOL_GPL(gpiod_get);
+ /**
+  * gpiod_get_index - obtain a GPIO from a multi-index GPIO function
+  * @dev:      GPIO consumer
+  * @con_id:   function within the GPIO consumer
+  * @idx:      index of the GPIO to obtain in the consumer
+  *
+  * This variant of gpiod_get() allows to access GPIOs other than the first
+  * defined one for functions that define several GPIOs.
+  *
+  * Return a valid GPIO descriptor, or an IS_ERR() condition in case of error.
+  */
+ struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
+                                              const char *con_id,
+                                              unsigned int idx)
+ {
+       struct gpio_desc *desc;
+       int status;
+       unsigned long flags = 0;
+       dev_dbg(dev, "GPIO lookup for consumer %s\n", con_id);
+       /* Using device tree? */
+       if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node) {
+               dev_dbg(dev, "using device tree for GPIO lookup\n");
+               desc = of_find_gpio(dev, con_id, idx, &flags);
+       } else if (IS_ENABLED(CONFIG_ACPI) && dev && ACPI_HANDLE(dev)) {
+               dev_dbg(dev, "using ACPI for GPIO lookup\n");
+               desc = acpi_find_gpio(dev, con_id, idx, &flags);
+       } else {
+               dev_dbg(dev, "using lookup tables for GPIO lookup");
+               desc = gpiod_find(dev, con_id, idx, &flags);
+       }
+       if (IS_ERR(desc)) {
+               dev_warn(dev, "lookup for GPIO %s failed\n", con_id);
+               return desc;
+       }
+       status = gpiod_request(desc, con_id);
+       if (status < 0)
+               return ERR_PTR(status);
+       if (flags & GPIOF_ACTIVE_LOW)
+               set_bit(FLAG_ACTIVE_LOW, &desc->flags);
+       return desc;
+ }
+ EXPORT_SYMBOL_GPL(gpiod_get_index);
+ /**
+  * gpiod_put - dispose of a GPIO descriptor
+  * @desc:     GPIO descriptor to dispose of
+  *
+  * No descriptor can be used after gpiod_put() has been called on it.
+  */
+ void gpiod_put(struct gpio_desc *desc)
+ {
+       gpiod_free(desc);
  }
- EXPORT_SYMBOL_GPL(gpio_set_value_cansleep);
+ EXPORT_SYMBOL_GPL(gpiod_put);
  
  #ifdef CONFIG_DEBUG_FS
  
@@@ -2113,6 -2423,7 +2470,7 @@@ static void gpiolib_dbg_show(struct seq
        unsigned                gpio = chip->base;
        struct gpio_desc        *gdesc = &chip->desc[0];
        int                     is_out;
+       int                     is_irq;
  
        for (i = 0; i < chip->ngpio; i++, gpio++, gdesc++) {
                if (!test_bit(FLAG_REQUESTED, &gdesc->flags))
  
                gpiod_get_direction(gdesc);
                is_out = test_bit(FLAG_IS_OUT, &gdesc->flags);
-               seq_printf(s, " gpio-%-3d (%-20.20s) %s %s",
+               is_irq = test_bit(FLAG_USED_AS_IRQ, &gdesc->flags);
+               seq_printf(s, " gpio-%-3d (%-20.20s) %s %s %s",
                        gpio, gdesc->label,
                        is_out ? "out" : "in ",
                        chip->get
                                ? (chip->get(chip, i) ? "hi" : "lo")
-                               : "?  ");
+                               : "?  ",
+                       is_irq ? "IRQ" : "   ");
                seq_printf(s, "\n");
        }
  }
index 523f4052553574082a256a239f3a573432e501e9,00f8f0a9edcd7df174b4e1becb749898af340a02..a5f56a0213a7e59ad3315fe8a8ddbaae1a402290
@@@ -10,6 -10,8 +10,8 @@@
  #ifdef CONFIG_GPIOLIB
  
  #include <linux/compiler.h>
+ #include <linux/gpio/driver.h>
+ #include <linux/gpio/consumer.h>
  
  /* Platforms may implement their GPIO interface with library code,
   * at a small performance cost for non-inlined operations and some
@@@ -49,122 -51,11 +51,11 @@@ struct module
  struct device_node;
  struct gpio_desc;
  
- /**
-  * struct gpio_chip - abstract a GPIO controller
-  * @label: for diagnostics
-  * @dev: optional device providing the GPIOs
-  * @owner: helps prevent removal of modules exporting active GPIOs
-  * @list: links gpio_chips together for traversal
-  * @request: optional hook for chip-specific activation, such as
-  *    enabling module power and clock; may sleep
-  * @free: optional hook for chip-specific deactivation, such as
-  *    disabling module power and clock; may sleep
-  * @get_direction: returns direction for signal "offset", 0=out, 1=in,
-  *    (same as GPIOF_DIR_XXX), or negative error
-  * @direction_input: configures signal "offset" as input, or returns error
-  * @get: returns value for signal "offset"; for output signals this
-  *    returns either the value actually sensed, or zero
-  * @direction_output: configures signal "offset" as output, or returns error
-  * @set_debounce: optional hook for setting debounce time for specified gpio in
-  *      interrupt triggered gpio chips
-  * @set: assigns output value for signal "offset"
-  * @to_irq: optional hook supporting non-static gpio_to_irq() mappings;
-  *    implementation may not sleep
-  * @dbg_show: optional routine to show contents in debugfs; default code
-  *    will be used when this is omitted, but custom code can show extra
-  *    state (such as pullup/pulldown configuration).
-  * @base: identifies the first GPIO number handled by this chip; or, if
-  *    negative during registration, requests dynamic ID allocation.
-  * @ngpio: the number of GPIOs handled by this controller; the last GPIO
-  *    handled is (base + ngpio - 1).
-  * @desc: array of ngpio descriptors. Private.
-  * @can_sleep: flag must be set iff get()/set() methods sleep, as they
-  *    must while accessing GPIO expander chips over I2C or SPI
-  * @names: if set, must be an array of strings to use as alternative
-  *      names for the GPIOs in this chip. Any entry in the array
-  *      may be NULL if there is no alias for the GPIO, however the
-  *      array must be @ngpio entries long.  A name can include a single printk
-  *      format specifier for an unsigned int.  It is substituted by the actual
-  *      number of the gpio.
-  *
-  * A gpio_chip can help platforms abstract various sources of GPIOs so
-  * they can all be accessed through a common programing interface.
-  * Example sources would be SOC controllers, FPGAs, multifunction
-  * chips, dedicated GPIO expanders, and so on.
-  *
-  * Each chip controls a number of signals, identified in method calls
-  * by "offset" values in the range 0..(@ngpio - 1).  When those signals
-  * are referenced through calls like gpio_get_value(gpio), the offset
-  * is calculated by subtracting @base from the gpio number.
-  */
- struct gpio_chip {
-       const char              *label;
-       struct device           *dev;
-       struct module           *owner;
-       struct list_head        list;
-       int                     (*request)(struct gpio_chip *chip,
-                                               unsigned offset);
-       void                    (*free)(struct gpio_chip *chip,
-                                               unsigned offset);
-       int                     (*get_direction)(struct gpio_chip *chip,
-                                               unsigned offset);
-       int                     (*direction_input)(struct gpio_chip *chip,
-                                               unsigned offset);
-       int                     (*get)(struct gpio_chip *chip,
-                                               unsigned offset);
-       int                     (*direction_output)(struct gpio_chip *chip,
-                                               unsigned offset, int value);
-       int                     (*set_debounce)(struct gpio_chip *chip,
-                                               unsigned offset, unsigned debounce);
-       void                    (*set)(struct gpio_chip *chip,
-                                               unsigned offset, int value);
-       int                     (*to_irq)(struct gpio_chip *chip,
-                                               unsigned offset);
-       void                    (*dbg_show)(struct seq_file *s,
-                                               struct gpio_chip *chip);
-       int                     base;
-       u16                     ngpio;
-       struct gpio_desc        *desc;
-       const char              *const *names;
-       unsigned                can_sleep:1;
-       unsigned                exported:1;
- #if defined(CONFIG_OF_GPIO)
-       /*
-        * If CONFIG_OF is enabled, then all GPIO controllers described in the
-        * device tree automatically may have an OF translation
-        */
-       struct device_node *of_node;
-       int of_gpio_n_cells;
-       int (*of_xlate)(struct gpio_chip *gc,
-                       const struct of_phandle_args *gpiospec, u32 *flags);
- #endif
- #ifdef CONFIG_PINCTRL
-       /*
-        * If CONFIG_PINCTRL is enabled, then gpio controllers can optionally
-        * describe the actual pin range which they serve in an SoC. This
-        * information would be used by pinctrl subsystem to configure
-        * corresponding pins for gpio usage.
-        */
-       struct list_head pin_ranges;
- #endif
- };
- extern const char *gpiochip_is_requested(struct gpio_chip *chip,
-                       unsigned offset);
- extern struct gpio_chip *gpio_to_chip(unsigned gpio);
- /* add/remove chips */
- extern int gpiochip_add(struct gpio_chip *chip);
- extern int __must_check gpiochip_remove(struct gpio_chip *chip);
- extern struct gpio_chip *gpiochip_find(void *data,
-                                       int (*match)(struct gpio_chip *chip,
-                                                    void *data));
+ /* caller holds gpio_lock *OR* gpio is marked as requested */
+ static inline struct gpio_chip *gpio_to_chip(unsigned gpio)
+ {
+       return gpiod_to_chip(gpio_to_desc(gpio));
+ }
  
  /* Always use the library code for GPIO management calls,
   * or when sleeping may be involved.
  extern int gpio_request(unsigned gpio, const char *label);
  extern void gpio_free(unsigned gpio);
  
- extern int gpio_direction_input(unsigned gpio);
- extern int gpio_direction_output(unsigned gpio, int value);
+ static inline int gpio_direction_input(unsigned gpio)
+ {
+       return gpiod_direction_input(gpio_to_desc(gpio));
+ }
+ static inline int gpio_direction_output(unsigned gpio, int value)
+ {
+       return gpiod_direction_output(gpio_to_desc(gpio), value);
+ }
  
- extern int gpio_set_debounce(unsigned gpio, unsigned debounce);
+ static inline int gpio_set_debounce(unsigned gpio, unsigned debounce)
+ {
+       return gpiod_set_debounce(gpio_to_desc(gpio), debounce);
+ }
  
- extern int gpio_get_value_cansleep(unsigned gpio);
- extern void gpio_set_value_cansleep(unsigned gpio, int value);
+ static inline int gpio_get_value_cansleep(unsigned gpio)
+ {
+       return gpiod_get_raw_value_cansleep(gpio_to_desc(gpio));
+ }
+ static inline void gpio_set_value_cansleep(unsigned gpio, int value)
+ {
+       return gpiod_set_raw_value_cansleep(gpio_to_desc(gpio), value);
+ }
  
  
  /* A platform's <asm/gpio.h> code may want to inline the I/O calls when
   * the GPIO is constant and refers to some always-present controller,
   * giving direct access to chip registers and tight bitbanging loops.
   */
- extern int __gpio_get_value(unsigned gpio);
- extern void __gpio_set_value(unsigned gpio, int value);
+ static inline int __gpio_get_value(unsigned gpio)
+ {
+       return gpiod_get_raw_value(gpio_to_desc(gpio));
+ }
+ static inline void __gpio_set_value(unsigned gpio, int value)
+ {
+       return gpiod_set_raw_value(gpio_to_desc(gpio), value);
+ }
+ static inline int __gpio_cansleep(unsigned gpio)
+ {
+       return gpiod_cansleep(gpio_to_desc(gpio));
+ }
  
- extern int __gpio_cansleep(unsigned gpio);
+ static inline int __gpio_to_irq(unsigned gpio)
+ {
+       return gpiod_to_irq(gpio_to_desc(gpio));
+ }
  
- extern int __gpio_to_irq(unsigned gpio);
+ extern int gpio_lock_as_irq(struct gpio_chip *chip, unsigned int offset);
+ extern void gpio_unlock_as_irq(struct gpio_chip *chip, unsigned int offset);
  
  extern int gpio_request_one(unsigned gpio, unsigned long flags, const char *label);
  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
  /*
   * A sysfs interface can be exported by individual drivers if they want,
   * but more typically is configured entirely from userspace.
   */
- extern int gpio_export(unsigned gpio, bool direction_may_change);
- extern int gpio_export_link(struct device *dev, const char *name,
-                       unsigned gpio);
- extern int gpio_sysfs_set_active_low(unsigned gpio, int value);
- extern void gpio_unexport(unsigned gpio);
+ static inline int gpio_export(unsigned gpio, bool direction_may_change)
+ {
+       return gpiod_export(gpio_to_desc(gpio), direction_may_change);
+ }
  
- #endif        /* CONFIG_GPIO_SYSFS */
+ static inline int gpio_export_link(struct device *dev, const char *name,
+                                  unsigned gpio)
+ {
+       return gpiod_export_link(dev, name, gpio_to_desc(gpio));
+ }
+ static inline int gpio_sysfs_set_active_low(unsigned gpio, int value)
+ {
+       return gpiod_sysfs_set_active_low(gpio_to_desc(gpio), value);
+ }
+ static inline void gpio_unexport(unsigned gpio)
+ {
+       gpiod_unexport(gpio_to_desc(gpio));
+ }
  
  #ifdef CONFIG_PINCTRL
  
@@@ -228,9 -160,6 +160,9 @@@ struct gpio_pin_range 
  int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
                           unsigned int gpio_offset, unsigned int pin_offset,
                           unsigned int npins);
 +int gpiochip_add_pingroup_range(struct gpio_chip *chip,
 +                      struct pinctrl_dev *pctldev,
 +                      unsigned int gpio_offset, const char *pin_group);
  void gpiochip_remove_pin_ranges(struct gpio_chip *chip);
  
  #else
@@@ -242,13 -171,6 +174,13 @@@ gpiochip_add_pin_range(struct gpio_chi
  {
        return 0;
  }
 +static inline int
 +gpiochip_add_pingroup_range(struct gpio_chip *chip,
 +                      struct pinctrl_dev *pctldev,
 +                      unsigned int gpio_offset, const char *pin_group)
 +{
 +      return 0;
 +}
  
  static inline void
  gpiochip_remove_pin_ranges(struct gpio_chip *chip)
@@@ -288,31 -210,4 +220,4 @@@ static inline void gpio_set_value_cansl
  
  #endif /* !CONFIG_GPIOLIB */
  
- #ifndef CONFIG_GPIO_SYSFS
- struct device;
- /* sysfs support is only available with gpiolib, where it's optional */
- static inline int gpio_export(unsigned gpio, bool direction_may_change)
- {
-       return -ENOSYS;
- }
- static inline int gpio_export_link(struct device *dev, const char *name,
-                               unsigned gpio)
- {
-       return -ENOSYS;
- }
- static inline int gpio_sysfs_set_active_low(unsigned gpio, int value)
- {
-       return -ENOSYS;
- }
- static inline void gpio_unexport(unsigned gpio)
- {
- }
- #endif        /* CONFIG_GPIO_SYSFS */
  #endif /* _ASM_GENERIC_GPIO_H */
diff --combined include/linux/gpio.h
index b8d0e53a802f0eacadcd44f4f3fba8ec1163eda5,c691df04445812c7ffae964be58d66c63e8ecaa6..7b92e0a235b427bc2ad13ec293a5b04afa1969ad
  #define GPIOF_OUT_INIT_LOW    (GPIOF_DIR_OUT | GPIOF_INIT_LOW)
  #define GPIOF_OUT_INIT_HIGH   (GPIOF_DIR_OUT | GPIOF_INIT_HIGH)
  
+ /* Gpio pin is active-low */
+ #define GPIOF_ACTIVE_LOW        (1 << 2)
  /* Gpio pin is open drain */
- #define GPIOF_OPEN_DRAIN      (1 << 2)
+ #define GPIOF_OPEN_DRAIN      (1 << 3)
  
  /* Gpio pin is open source */
- #define GPIOF_OPEN_SOURCE     (1 << 3)
+ #define GPIOF_OPEN_SOURCE     (1 << 4)
  
- #define GPIOF_EXPORT          (1 << 4)
- #define GPIOF_EXPORT_CHANGEABLE       (1 << 5)
+ #define GPIOF_EXPORT          (1 << 5)
+ #define GPIOF_EXPORT_CHANGEABLE       (1 << 6)
  #define GPIOF_EXPORT_DIR_FIXED        (GPIOF_EXPORT)
  #define GPIOF_EXPORT_DIR_CHANGEABLE (GPIOF_EXPORT | GPIOF_EXPORT_CHANGEABLE)
  
@@@ -80,7 -83,6 +83,7 @@@ static inline int irq_to_gpio(unsigned 
  #include <linux/types.h>
  #include <linux/errno.h>
  #include <linux/bug.h>
 +#include <linux/pinctrl/pinctrl.h>
  
  struct device;
  struct gpio_chip;
@@@ -205,6 -207,18 +208,18 @@@ static inline int gpio_to_irq(unsigned 
        return -EINVAL;
  }
  
+ static inline int gpio_lock_as_irq(struct gpio_chip *chip, unsigned int offset)
+ {
+       WARN_ON(1);
+       return -EINVAL;
+ }
+ static inline void gpio_unlock_as_irq(struct gpio_chip *chip,
+                                     unsigned int offset)
+ {
+       WARN_ON(1);
+ }
  static inline int irq_to_gpio(unsigned irq)
  {
        /* irq can never have been returned from gpio_to_irq() */
@@@ -221,15 -235,6 +236,15 @@@ gpiochip_add_pin_range(struct gpio_chi
        return -EINVAL;
  }
  
 +static inline int
 +gpiochip_add_pingroup_range(struct gpio_chip *chip,
 +                      struct pinctrl_dev *pctldev,
 +                      unsigned int gpio_offset, const char *pin_group)
 +{
 +      WARN_ON(1);
 +      return -EINVAL;
 +}
 +
  static inline void
  gpiochip_remove_pin_ranges(struct gpio_chip *chip)
  {