Merge tag 'gpio-v4.8-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 27 Jul 2016 02:16:01 +0000 (19:16 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 27 Jul 2016 02:16:01 +0000 (19:16 -0700)
Pull GPIO updates from Linus Walleij:
 "This is the bulk of GPIO changes for the v4.8 kernel cycle.  The big
  news is the completion of the chardev ABI which I'm very happy about
  and apart from that it's an ordinary, quite busy cycle.  The details
  are below.

  The patches are tested in linux-next for some time, patches to other
  subsystem mostly have ACKs.

  I got overly ambitious with configureing lines as input for IRQ lines
  but it turns out that some controllers have their interrupt-enable and
  input-enabling in orthogonal settings so the assumption that all IRQ
  lines are input lines does not hold.  Oh well, revert and back to the
  drawing board with that.

  Core changes:

   - The big item is of course the completion of the character device
     ABI.  It has now replaced and surpassed the former unmaintainable
     sysfs ABI: we can now hammer (bitbang) individual lines or sets of
     lines and read individual lines or sets of lines from userspace,
     and we can also register to listen to GPIO events from userspace.

     As a tie-in we have two new tools in tools/gpio: gpio-hammer and
     gpio-event-mon that illustrate the proper use of the new ABI.  As
     someone said: the wild west days of GPIO are now over.

   - Continued to remove the pointless ARCH_[WANT_OPTIONAL|REQUIRE]_GPIOLIB
     Kconfig symbols.  I'm patching hexagon, openrisc, powerpc, sh,
     unicore, ia64 and microblaze.  These are either ACKed by their
     maintainers or patched anyways after a grace period and no response
     from maintainers.

     Some archs (ARM) come in from their trees, and others (x86) are
     still not fixed, so I might send a second pull request to root it
     out later in this merge window, or just defer to v4.9.

   - The GPIO tools are moved to the tools build system.

  New drivers:

   - New driver for the MAX77620/MAX20024.

   - New driver for the Intel Merrifield.

   - Enabled PCA953x for the TI PCA9536.

   - Enabled PCA953x for the Intel Edison.

   - Enabled R8A7792 in the RCAR driver.

  Driver improvements:

   - The STMPE and F7188x now supports the .get_direction() callback.

   - The Xilinx driver supports setting multiple lines at once.

   - ACPI support for the Vulcan GPIO controller.

   - The MMIO GPIO driver supports device tree probing.

   - The Acer One 10 is supported through the _DEP ACPI attribute.

  Cleanups:

   - A major cleanup of the OF/DT support code.  It is way easier to
     read and understand now, probably this improves performance too.

   - Drop a few redundant .owner assignments.

   - Remove CLPS711x boardfile support: we are 100% DT"

* tag 'gpio-v4.8-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (67 commits)
  MAINTAINERS: Add INTEL MERRIFIELD GPIO entry
  gpio: dwapb: add missing fwnode_handle_put() in dwapb_gpio_get_pdata()
  gpio: merrifield: Protect irq_ack() and gpio_set() by lock
  gpio: merrifield: Introduce GPIO driver to support Merrifield
  gpio: intel-mid: Make it depend to X86_INTEL_MID
  gpio: intel-mid: Sort header block alphabetically
  gpio: intel-mid: Remove potentially harmful code
  gpio: rcar: add R8A7792 support
  gpiolib: remove duplicated include from gpiolib.c
  Revert "gpio: convince line to become input in irq helper"
  gpiolib: of_find_gpio(): Don't discard errors
  gpio: of: Allow overriding the device node
  gpio: free handles in fringe cases
  gpio: tps65218: Add platform_device_id table
  gpio: max77620: get gpio value based on direction
  gpio: lynxpoint: avoid potential warning on error path
  tools/gpio: add install section
  tools/gpio: move to tools buildsystem
  gpio: intel-mid: switch to devm_gpiochip_add_data()
  gpio: 74x164: Use spi_write() helper instead of open coding
  ...

1  2 
MAINTAINERS
arch/ia64/Kconfig
arch/powerpc/Kconfig
drivers/Makefile
drivers/gpio/Kconfig
drivers/gpio/gpiolib-of.c
drivers/gpio/gpiolib.c

diff --combined MAINTAINERS
@@@ -288,7 -288,6 +288,7 @@@ F: include/linux/acpi.
  F:    include/acpi/
  F:    Documentation/acpi/
  F:    Documentation/ABI/testing/sysfs-bus-acpi
 +F:    Documentation/ABI/testing/configfs-acpi
  F:    drivers/pci/*acpi*
  F:    drivers/pci/*/*acpi*
  F:    drivers/pci/*/*/*acpi*
@@@ -596,10 -595,6 +596,10 @@@ S:       Odd Fixe
  L:    linux-alpha@vger.kernel.org
  F:    arch/alpha/
  
 +ALPS PS/2 TOUCHPAD DRIVER
 +R:    Pali Rohár <pali.rohar@gmail.com>
 +F:    drivers/input/mouse/alps.*
 +
  ALTERA MAILBOX DRIVER
  M:    Ley Foon Tan <lftan@altera.com>
  L:    nios2-dev@lists.rocketboards.org (moderated for non-subscribers)
@@@ -1164,7 -1159,6 +1164,7 @@@ F:      arch/arm/mach-footbridge
  ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
  M:    Shawn Guo <shawnguo@kernel.org>
  M:    Sascha Hauer <kernel@pengutronix.de>
 +R:    Fabio Estevam <fabio.estevam@nxp.com>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  S:    Maintained
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git
@@@ -1648,13 -1642,6 +1648,13 @@@ L:    linux-media@vger.kernel.or
  S:    Maintained
  F:    drivers/media/platform/s5p-tv/
  
 +ARM/SAMSUNG S5P SERIES HDMI CEC SUBSYSTEM SUPPORT
 +M:    Kyungmin Park <kyungmin.park@samsung.com>
 +L:    linux-arm-kernel@lists.infradead.org
 +L:    linux-media@vger.kernel.org
 +S:    Maintained
 +F:    drivers/staging/media/platform/s5p-cec/
 +
  ARM/SAMSUNG S5P SERIES JPEG CODEC SUPPORT
  M:    Andrzej Pietrasiewicz <andrzej.p@samsung.com>
  M:    Jacek Anaszewski <j.anaszewski@samsung.com>
@@@ -1677,6 -1664,7 +1677,6 @@@ F:      arch/arm/boot/dts/sh
  F:    arch/arm/configs/shmobile_defconfig
  F:    arch/arm/include/debug/renesas-scif.S
  F:    arch/arm/mach-shmobile/
 -F:    drivers/sh/
  F:    drivers/soc/renesas/
  F:    include/linux/soc/renesas/
  
@@@ -1701,6 -1689,8 +1701,6 @@@ S:      Maintaine
  F:    drivers/edac/altera_edac.
  
  ARM/STI ARCHITECTURE
 -M:    Srinivas Kandagatla <srinivas.kandagatla@gmail.com>
 -M:    Maxime Coquelin <maxime.coquelin@st.com>
  M:    Patrice Chotard <patrice.chotard@st.com>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  L:    kernel@stlinux.com
@@@ -1733,7 -1723,6 +1733,7 @@@ F:      drivers/ata/ahci_st.
  
  ARM/STM32 ARCHITECTURE
  M:    Maxime Coquelin <mcoquelin.stm32@gmail.com>
 +M:    Alexandre Torgue <alexandre.torgue@st.com>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  S:    Maintained
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/mcoquelin/stm32.git
@@@ -2253,8 -2242,7 +2253,8 @@@ F:      include/net/ax25.
  F:    net/ax25/
  
  AZ6007 DVB DRIVER
 -M:    Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 +M:    Mauro Carvalho Chehab <mchehab@s-opensource.com>
 +M:    Mauro Carvalho Chehab <mchehab@kernel.org>
  L:    linux-media@vger.kernel.org
  W:    https://linuxtv.org
  T:    git git://linuxtv.org/media_tree.git
@@@ -2721,8 -2709,7 +2721,8 @@@ F:      Documentation/filesystems/btrfs.tx
  F:    fs/btrfs/
  
  BTTV VIDEO4LINUX DRIVER
 -M:    Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 +M:    Mauro Carvalho Chehab <mchehab@s-opensource.com>
 +M:    Mauro Carvalho Chehab <mchehab@kernel.org>
  L:    linux-media@vger.kernel.org
  W:    https://linuxtv.org
  T:    git git://linuxtv.org/media_tree.git
@@@ -2786,9 -2773,9 +2786,9 @@@ F:      include/net/caif
  F:    net/caif/
  
  CALGARY x86-64 IOMMU
 -M:    Muli Ben-Yehuda <muli@il.ibm.com>
 -M:    "Jon D. Mason" <jdmason@kudzu.us>
 -L:    discuss@x86-64.org
 +M:    Muli Ben-Yehuda <mulix@mulix.org>
 +M:    Jon Mason <jdmason@kudzu.us>
 +L:    iommu@lists.linux-foundation.org
  S:    Maintained
  F:    arch/x86/kernel/pci-calgary_64.c
  F:    arch/x86/kernel/tce_64.c
@@@ -2858,22 -2845,6 +2858,22 @@@ F:    drivers/net/ieee802154/cc2520.
  F:    include/linux/spi/cc2520.h
  F:    Documentation/devicetree/bindings/net/ieee802154/cc2520.txt
  
 +CEC DRIVER
 +M:    Hans Verkuil <hans.verkuil@cisco.com>
 +L:    linux-media@vger.kernel.org
 +T:    git git://linuxtv.org/media_tree.git
 +W:    http://linuxtv.org
 +S:    Supported
 +F:    Documentation/cec.txt
 +F:    Documentation/DocBook/media/v4l/cec*
 +F:    drivers/staging/media/cec/
 +F:    drivers/media/cec-edid.c
 +F:    drivers/media/rc/keymaps/rc-cec.c
 +F:    include/media/cec.h
 +F:    include/media/cec-edid.h
 +F:    include/linux/cec.h
 +F:    include/linux/cec-funcs.h
 +
  CELL BROADBAND ENGINE ARCHITECTURE
  M:    Arnd Bergmann <arnd@arndb.de>
  L:    linuxppc-dev@lists.ozlabs.org
@@@ -3115,7 -3086,6 +3115,7 @@@ M:      Stephen Boyd <sboyd@codeaurora.org
  L:    linux-clk@vger.kernel.org
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git
  S:    Maintained
 +F:    Documentation/devicetree/bindings/clock/
  F:    drivers/clk/
  X:    drivers/clk/clkdev.c
  F:    include/linux/clk-pr*
@@@ -3310,7 -3280,6 +3310,7 @@@ T:      git git://git.kernel.org/pub/scm/lin
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6.git
  S:    Maintained
  F:    Documentation/crypto/
 +F:    Documentation/devicetree/bindings/crypto/
  F:    Documentation/DocBook/crypto-API.tmpl
  F:    arch/*/crypto/
  F:    crypto/
@@@ -3374,8 -3343,7 +3374,8 @@@ S:      Maintaine
  F:    drivers/media/dvb-frontends/cx24120*
  
  CX88 VIDEO4LINUX DRIVER
 -M:    Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 +M:    Mauro Carvalho Chehab <mchehab@s-opensource.com>
 +M:    Mauro Carvalho Chehab <mchehab@kernel.org>
  L:    linux-media@vger.kernel.org
  W:    https://linuxtv.org
  T:    git git://linuxtv.org/media_tree.git
@@@ -3805,7 -3773,6 +3805,7 @@@ Q:      https://patchwork.kernel.org/project
  S:    Maintained
  F:    drivers/dma/
  F:    include/linux/dmaengine.h
 +F:    Documentation/devicetree/bindings/dma/
  F:    Documentation/dmaengine/
  T:    git git://git.infradead.org/users/vkoul/slave-dma.git
  
@@@ -4323,8 -4290,7 +4323,8 @@@ F:      fs/ecryptfs
  EDAC-CORE
  M:    Doug Thompson <dougthompson@xmission.com>
  M:    Borislav Petkov <bp@alien8.de>
 -M:    Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 +M:    Mauro Carvalho Chehab <mchehab@s-opensource.com>
 +M:    Mauro Carvalho Chehab <mchehab@kernel.org>
  L:    linux-edac@vger.kernel.org
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp.git for-next
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-edac.git linux_next
@@@ -4369,8 -4335,7 +4369,8 @@@ S:      Maintaine
  F:    drivers/edac/e7xxx_edac.c
  
  EDAC-GHES
 -M:    Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 +M:    Mauro Carvalho Chehab <mchehab@s-opensource.com>
 +M:    Mauro Carvalho Chehab <mchehab@kernel.org>
  L:    linux-edac@vger.kernel.org
  S:    Maintained
  F:    drivers/edac/ghes_edac.c
@@@ -4394,22 -4359,19 +4394,22 @@@ S:   Maintaine
  F:    drivers/edac/i5000_edac.c
  
  EDAC-I5400
 -M:    Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 +M:    Mauro Carvalho Chehab <mchehab@s-opensource.com>
 +M:    Mauro Carvalho Chehab <mchehab@kernel.org>
  L:    linux-edac@vger.kernel.org
  S:    Maintained
  F:    drivers/edac/i5400_edac.c
  
  EDAC-I7300
 -M:    Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 +M:    Mauro Carvalho Chehab <mchehab@s-opensource.com>
 +M:    Mauro Carvalho Chehab <mchehab@kernel.org>
  L:    linux-edac@vger.kernel.org
  S:    Maintained
  F:    drivers/edac/i7300_edac.c
  
  EDAC-I7CORE
 -M:    Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 +M:    Mauro Carvalho Chehab <mchehab@s-opensource.com>
 +M:    Mauro Carvalho Chehab <mchehab@kernel.org>
  L:    linux-edac@vger.kernel.org
  S:    Maintained
  F:    drivers/edac/i7core_edac.c
@@@ -4446,8 -4408,7 +4446,8 @@@ S:      Maintaine
  F:    drivers/edac/r82600_edac.c
  
  EDAC-SBRIDGE
 -M:    Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 +M:    Mauro Carvalho Chehab <mchehab@s-opensource.com>
 +M:    Mauro Carvalho Chehab <mchehab@kernel.org>
  L:    linux-edac@vger.kernel.org
  S:    Maintained
  F:    drivers/edac/sb_edac.c
@@@ -4500,14 -4461,13 +4500,14 @@@ S:   Orpha
  F:    fs/efs/
  
  EHEA (IBM pSeries eHEA 10Gb ethernet adapter) DRIVER
 -M:    Thadeu Lima de Souza Cascardo <cascardo@linux.vnet.ibm.com>
 +M:    Douglas Miller <dougmill@linux.vnet.ibm.com>
  L:    netdev@vger.kernel.org
  S:    Maintained
  F:    drivers/net/ethernet/ibm/ehea/
  
  EM28XX VIDEO4LINUX DRIVER
 -M:    Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 +M:    Mauro Carvalho Chehab <mchehab@s-opensource.com>
 +M:    Mauro Carvalho Chehab <mchehab@kernel.org>
  L:    linux-media@vger.kernel.org
  W:    https://linuxtv.org
  T:    git git://linuxtv.org/media_tree.git
@@@ -4965,13 -4925,6 +4965,13 @@@ F:    Documentation/filesystems/caching
  F:    fs/fscache/
  F:    include/linux/fscache*.h
  
 +FS-CRYPTO: FILE SYSTEM LEVEL ENCRYPTION SUPPORT
 +M:    Theodore Y. Ts'o <tytso@mit.edu>
 +M:    Jaegeuk Kim <jaegeuk@kernel.org>
 +S:    Supported
 +F:    fs/crypto/
 +F:    include/linux/fscrypto.h
 +
  F2FS FILE SYSTEM
  M:    Jaegeuk Kim <jaegeuk@kernel.org>
  M:    Changman Lee <cm224.lee@samsung.com>
@@@ -5200,10 -5153,10 +5200,10 @@@ S:   Maintaine
  F:    drivers/media/usb/gspca/m5602/
  
  GSPCA PAC207 SONIXB SUBDRIVER
 -M:    Hans de Goede <hdegoede@redhat.com>
 +M:    Hans Verkuil <hverkuil@xs4all.nl>
  L:    linux-media@vger.kernel.org
  T:    git git://linuxtv.org/media_tree.git
 -S:    Maintained
 +S:    Odd Fixes
  F:    drivers/media/usb/gspca/pac207.c
  
  GSPCA SN9C20X SUBDRIVER
@@@ -5221,10 -5174,10 +5221,10 @@@ S:   Maintaine
  F:    drivers/media/usb/gspca/t613.c
  
  GSPCA USB WEBCAM DRIVER
 -M:    Hans de Goede <hdegoede@redhat.com>
 +M:    Hans Verkuil <hverkuil@xs4all.nl>
  L:    linux-media@vger.kernel.org
  T:    git git://linuxtv.org/media_tree.git
 -S:    Maintained
 +S:    Odd Fixes
  F:    drivers/media/usb/gspca/
  
  GUID PARTITION TABLE (GPT)
@@@ -5305,7 -5258,6 +5305,7 @@@ M:      Matt Mackall <mpm@selenic.com
  M:    Herbert Xu <herbert@gondor.apana.org.au>
  L:    linux-crypto@vger.kernel.org
  S:    Odd fixes
 +F:    Documentation/devicetree/bindings/rng/
  F:    Documentation/hw_random.txt
  F:    drivers/char/hw_random/
  F:    include/linux/hw_random.h
@@@ -5820,9 -5772,7 +5820,9 @@@ R:      Hartmut Knaack <knaack.h@gmx.de
  R:    Lars-Peter Clausen <lars@metafoo.de>
  R:    Peter Meerwald-Stadler <pmeerw@pmeerw.net>
  L:    linux-iio@vger.kernel.org
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git
  S:    Maintained
 +F:    Documentation/devicetree/bindings/iio/
  F:    drivers/iio/
  F:    drivers/staging/iio/
  F:    include/linux/iio/
@@@ -5952,12 -5902,6 +5952,12 @@@ L:    platform-driver-x86@vger.kernel.or
  S:    Maintained
  F:    drivers/platform/x86/intel-hid.c
  
 +INTEL VIRTUAL BUTTON DRIVER
 +M:    AceLan Kao <acelan.kao@canonical.com>
 +L:    platform-driver-x86@vger.kernel.org
 +S:    Maintained
 +F:    drivers/platform/x86/intel-vbtn.c
 +
  INTEL IDLE DRIVER
  M:    Len Brown <lenb@kernel.org>
  L:    linux-pm@vger.kernel.org
@@@ -6060,6 -6004,12 +6060,12 @@@ L:     linux-rdma@vger.kernel.or
  S:     Supported
  F:     drivers/infiniband/hw/i40iw/
  
+ INTEL MERRIFIELD GPIO DRIVER
+ M:    Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+ L:    linux-gpio@vger.kernel.org
+ S:    Maintained
+ F:    drivers/gpio/gpio-merrifield.c
  INTEL-MID GPIO DRIVER
  M:    David Cohen <david.a.cohen@linux.intel.com>
  L:    linux-gpio@vger.kernel.org
@@@ -6274,6 -6224,7 +6280,6 @@@ F:      Documentation/devicetree/bindings/in
  F:    drivers/irqchip/
  
  IRQ DOMAINS (IRQ NUMBER MAPPING LIBRARY)
 -M:    Jiang Liu <jiang.liu@linux.intel.com>
  M:    Marc Zyngier <marc.zyngier@arm.com>
  S:    Maintained
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core
@@@ -6541,7 -6492,6 +6547,7 @@@ F:      include/uapi/linux/sunrpc
  
  KERNEL SELFTEST FRAMEWORK
  M:    Shuah Khan <shuahkh@osg.samsung.com>
 +M:    Shuah Khan <shuah@kernel.org>
  L:    linux-kselftest@vger.kernel.org
  T:    git git://git.kernel.org/pub/scm/shuah/linux-kselftest
  S:    Maintained
@@@ -6805,7 -6755,6 +6811,7 @@@ S:      Maintaine
  F:    drivers/ata/
  F:    include/linux/ata.h
  F:    include/linux/libata.h
 +F:    Documentation/devicetree/bindings/ata/
  
  LIBATA PATA ARASAN COMPACT FLASH CONTROLLER
  M:    Viresh Kumar <vireshk@kernel.org>
@@@ -7010,7 -6959,7 +7016,7 @@@ T:      git git://git.kernel.org/pub/scm/lin
  LINUX KERNEL DUMP TEST MODULE (LKDTM)
  M:    Kees Cook <keescook@chromium.org>
  S:    Maintained
 -F:    drivers/misc/lkdtm.c
 +F:    drivers/misc/lkdtm*
  
  LLC (802.2)
  M:    Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
@@@ -7063,23 -7012,15 +7069,23 @@@ Q:   http://patchwork.linuxtv.org/project
  S:    Maintained
  F:    drivers/media/usb/dvb-usb-v2/lmedm04*
  
 -LOCKDEP AND LOCKSTAT
 +LOCKING PRIMITIVES
  M:    Peter Zijlstra <peterz@infradead.org>
  M:    Ingo Molnar <mingo@redhat.com>
  L:    linux-kernel@vger.kernel.org
 -T:    git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git core/locking
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git locking/core
  S:    Maintained
 -F:    Documentation/locking/lockdep*.txt
 -F:    Documentation/locking/lockstat.txt
 +F:    Documentation/locking/
  F:    include/linux/lockdep.h
 +F:    include/linux/spinlock*.h
 +F:    arch/*/include/asm/spinlock*.h
 +F:    include/linux/rwlock*.h
 +F:    include/linux/mutex*.h
 +F:    arch/*/include/asm/mutex*.h
 +F:    include/linux/rwsem*.h
 +F:    arch/*/include/asm/rwsem.h
 +F:    include/linux/seqlock.h
 +F:    lib/locking*.[ch]
  F:    kernel/locking/
  
  LOGICAL DISK MANAGER SUPPORT (LDM, Windows 2000/XP/Vista Dynamic Disks)
@@@ -7367,16 -7308,6 +7373,16 @@@ L:    linux-iio@vger.kernel.or
  S:    Maintained
  F:    drivers/iio/potentiometer/mcp4531.c
  
 +MEDIA DRIVERS FOR RENESAS - FCP
 +M:    Laurent Pinchart <laurent.pinchart@ideasonboard.com>
 +L:    linux-media@vger.kernel.org
 +L:    linux-renesas-soc@vger.kernel.org
 +T:    git git://linuxtv.org/media_tree.git
 +S:    Supported
 +F:    Documentation/devicetree/bindings/media/renesas,fcp.txt
 +F:    drivers/media/platform/rcar-fcp.c
 +F:    include/media/rcar-fcp.h
 +
  MEDIA DRIVERS FOR RENESAS - VSP1
  M:    Laurent Pinchart <laurent.pinchart@ideasonboard.com>
  L:    linux-media@vger.kernel.org
@@@ -7386,18 -7317,8 +7392,18 @@@ S:    Supporte
  F:    Documentation/devicetree/bindings/media/renesas,vsp1.txt
  F:    drivers/media/platform/vsp1/
  
 +MEDIA DRIVERS FOR HELENE
 +M:    Abylay Ospan <aospan@netup.ru>
 +L:    linux-media@vger.kernel.org
 +W:    https://linuxtv.org
 +W:    http://netup.tv/
 +T:    git git://linuxtv.org/media_tree.git
 +S:    Supported
 +F:    drivers/media/dvb-frontends/helene*
 +
  MEDIA DRIVERS FOR ASCOT2E
  M:    Sergey Kozlov <serjk@netup.ru>
 +M:    Abylay Ospan <aospan@netup.ru>
  L:    linux-media@vger.kernel.org
  W:    https://linuxtv.org
  W:    http://netup.tv/
@@@ -7407,7 -7328,6 +7413,7 @@@ F:      drivers/media/dvb-frontends/ascot2e
  
  MEDIA DRIVERS FOR CXD2841ER
  M:    Sergey Kozlov <serjk@netup.ru>
 +M:    Abylay Ospan <aospan@netup.ru>
  L:    linux-media@vger.kernel.org
  W:    https://linuxtv.org
  W:    http://netup.tv/
@@@ -7417,7 -7337,6 +7423,7 @@@ F:      drivers/media/dvb-frontends/cxd2841e
  
  MEDIA DRIVERS FOR HORUS3A
  M:    Sergey Kozlov <serjk@netup.ru>
 +M:    Abylay Ospan <aospan@netup.ru>
  L:    linux-media@vger.kernel.org
  W:    https://linuxtv.org
  W:    http://netup.tv/
@@@ -7427,7 -7346,6 +7433,7 @@@ F:      drivers/media/dvb-frontends/horus3a
  
  MEDIA DRIVERS FOR LNBH25
  M:    Sergey Kozlov <serjk@netup.ru>
 +M:    Abylay Ospan <aospan@netup.ru>
  L:    linux-media@vger.kernel.org
  W:    https://linuxtv.org
  W:    http://netup.tv/
@@@ -7437,7 -7355,6 +7443,7 @@@ F:      drivers/media/dvb-frontends/lnbh25
  
  MEDIA DRIVERS FOR NETUP PCI UNIVERSAL DVB devices
  M:    Sergey Kozlov <serjk@netup.ru>
 +M:    Abylay Ospan <aospan@netup.ru>
  L:    linux-media@vger.kernel.org
  W:    https://linuxtv.org
  W:    http://netup.tv/
@@@ -7446,8 -7363,7 +7452,8 @@@ S:      Supporte
  F:    drivers/media/pci/netup_unidvb/*
  
  MEDIA INPUT INFRASTRUCTURE (V4L/DVB)
 -M:    Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 +M:    Mauro Carvalho Chehab <mchehab@s-opensource.com>
 +M:    Mauro Carvalho Chehab <mchehab@kernel.org>
  P:    LinuxTV.org Project
  L:    linux-media@vger.kernel.org
  W:    https://linuxtv.org
@@@ -7495,7 -7411,7 +7501,7 @@@ F:      drivers/scsi/megaraid.
  F:    drivers/scsi/megaraid/
  
  MELLANOX ETHERNET DRIVER (mlx4_en)
 -M:    Eugenia Emantayev <eugenia@mellanox.com>
 +M:    Tariq Toukan <tariqt@mellanox.com>
  L:    netdev@vger.kernel.org
  S:    Supported
  W:    http://www.mellanox.com
@@@ -7547,7 -7463,6 +7553,7 @@@ Q:      http://patchwork.ozlabs.org/project/
  T:    git git://git.infradead.org/linux-mtd.git
  T:    git git://git.infradead.org/l2-mtd.git
  S:    Maintained
 +F:    Documentation/devicetree/bindings/mtd/
  F:    drivers/mtd/
  F:    include/linux/mtd/
  F:    include/uapi/mtd/
@@@ -7687,8 -7602,10 +7693,8 @@@ L:     linux-media@vger.kernel.or
  W:    https://linuxtv.org
  W:    http://palosaari.fi/linux/
  Q:    http://patchwork.linuxtv.org/project/linux-media/list/
 -T:    git git://linuxtv.org/anttip/media_tree.git
  S:    Maintained
 -F:    drivers/staging/media/mn88472/
 -F:    drivers/media/dvb-frontends/mn88472.h
 +F:    drivers/media/dvb-frontends/mn88472*
  
  MN88473 MEDIA DRIVER
  M:    Antti Palosaari <crope@iki.fi>
@@@ -8097,7 -8014,6 +8103,7 @@@ Q:      http://patchwork.kernel.org/project/
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers.git
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next.git
  S:    Maintained
 +F:    Documentation/devicetree/bindings/net/wireless/
  F:    drivers/net/wireless/
  
  NETXEN (1/10) GbE SUPPORT
@@@ -8243,13 -8159,6 +8249,13 @@@ S:    Supporte
  F:    drivers/nvme/host/
  F:    include/linux/nvme.h
  
 +NVM EXPRESS TARGET DRIVER
 +M:    Christoph Hellwig <hch@lst.de>
 +M:    Sagi Grimberg <sagi@grimberg.me>
 +L:    linux-nvme@lists.infradead.org
 +S:    Supported
 +F:    drivers/nvme/target/
 +
  NVMEM FRAMEWORK
  M:    Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
  M:    Maxime Ripard <maxime.ripard@free-electrons.com>
@@@ -8502,9 -8411,10 +8508,9 @@@ F:     drivers/i2c/busses/i2c-ocores.
  OPEN FIRMWARE AND FLATTENED DEVICE TREE
  M:    Rob Herring <robh+dt@kernel.org>
  M:    Frank Rowand <frowand.list@gmail.com>
 -M:    Grant Likely <grant.likely@linaro.org>
  L:    devicetree@vger.kernel.org
  W:    http://www.devicetree.org/
 -T:    git git://git.kernel.org/pub/scm/linux/kernel/git/glikely/linux.git
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git
  S:    Maintained
  F:    drivers/of/
  F:    include/linux/of*.h
@@@ -8512,10 -8422,12 +8518,10 @@@ F:   scripts/dtc
  
  OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS
  M:    Rob Herring <robh+dt@kernel.org>
 -M:    Pawel Moll <pawel.moll@arm.com>
  M:    Mark Rutland <mark.rutland@arm.com>
 -M:    Ian Campbell <ijc+devicetree@hellion.org.uk>
 -M:    Kumar Gala <galak@codeaurora.org>
  L:    devicetree@vger.kernel.org
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git
 +Q:    http://patchwork.ozlabs.org/project/devicetree-bindings/list/
  S:    Maintained
  F:    Documentation/devicetree/
  F:    arch/*/boot/dts/
@@@ -9040,7 -8952,6 +9046,7 @@@ L:      linux-gpio@vger.kernel.or
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git
  S:    Maintained
  F:    Documentation/devicetree/bindings/pinctrl/
 +F:    Documentation/pinctrl.txt
  F:    drivers/pinctrl/
  F:    include/linux/pinctrl/
  
@@@ -9300,13 -9211,6 +9306,13 @@@ F:    include/linux/tracehook.
  F:    include/uapi/linux/ptrace.h
  F:    kernel/ptrace.c
  
 +PULSE8-CEC DRIVER
 +M:    Hans Verkuil <hverkuil@xs4all.nl>
 +L:    linux-media@vger.kernel.org
 +T:    git git://linuxtv.org/media_tree.git
 +S:    Maintained
 +F:    drivers/staging/media/pulse8-cec
 +
  PVRUSB2 VIDEO4LINUX DRIVER
  M:    Mike Isely <isely@pobox.com>
  L:    pvrusb2@isely.net       (subscribers-only)
@@@ -9318,10 -9222,10 +9324,10 @@@ F:   Documentation/video4linux/README.pvr
  F:    drivers/media/usb/pvrusb2/
  
  PWC WEBCAM DRIVER
 -M:    Hans de Goede <hdegoede@redhat.com>
 +M:    Hans Verkuil <hverkuil@xs4all.nl>
  L:    linux-media@vger.kernel.org
  T:    git git://linuxtv.org/media_tree.git
 -S:    Maintained
 +S:    Odd Fixes
  F:    drivers/media/usb/pwc/*
  
  PWM FAN DRIVER
@@@ -9394,8 -9298,7 +9400,8 @@@ L:      rtc-linux@googlegroups.co
  S:    Maintained
  
  QAT DRIVER
 -M:    Tadeusz Struk <tadeusz.struk@intel.com>
 +M:    Giovanni Cabiddu <giovanni.cabiddu@intel.com>
 +M:    Salvatore Benedetto <salvatore.benedetto@intel.com>
  L:    qat-linux@intel.com
  S:    Supported
  F:    drivers/crypto/qat/
@@@ -9537,14 -9440,14 +9543,14 @@@ F:   drivers/video/fbdev/aty/radeon
  F:    include/uapi/linux/radeonfb.h
  
  RADIOSHARK RADIO DRIVER
 -M:    Hans de Goede <hdegoede@redhat.com>
 +M:    Hans Verkuil <hverkuil@xs4all.nl>
  L:    linux-media@vger.kernel.org
  T:    git git://linuxtv.org/media_tree.git
  S:    Maintained
  F:    drivers/media/radio/radio-shark.c
  
  RADIOSHARK2 RADIO DRIVER
 -M:    Hans de Goede <hdegoede@redhat.com>
 +M:    Hans Verkuil <hverkuil@xs4all.nl>
  L:    linux-media@vger.kernel.org
  T:    git git://linuxtv.org/media_tree.git
  S:    Maintained
@@@ -9956,8 -9859,7 +9962,8 @@@ S:      Odd Fixe
  F:    drivers/media/i2c/saa6588*
  
  SAA7134 VIDEO4LINUX DRIVER
 -M:    Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 +M:    Mauro Carvalho Chehab <mchehab@s-opensource.com>
 +M:    Mauro Carvalho Chehab <mchehab@kernel.org>
  L:    linux-media@vger.kernel.org
  W:    https://linuxtv.org
  T:    git git://linuxtv.org/media_tree.git
@@@ -10086,7 -9988,6 +10092,7 @@@ SERIAL DRIVER
  M:    Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  L:    linux-serial@vger.kernel.org
  S:    Maintained
 +F:    Documentation/devicetree/bindings/serial/
  F:    drivers/tty/serial/
  
  SYNOPSYS DESIGNWARE DMAC DRIVER
@@@ -10477,8 -10378,7 +10483,8 @@@ S:   Maintaine
  F:    drivers/media/radio/si4713/radio-usb-si4713.c
  
  SIANO DVB DRIVER
 -M:    Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 +M:    Mauro Carvalho Chehab <mchehab@s-opensource.com>
 +M:    Mauro Carvalho Chehab <mchehab@kernel.org>
  L:    linux-media@vger.kernel.org
  W:    https://linuxtv.org
  T:    git git://linuxtv.org/media_tree.git
@@@ -10947,7 -10847,6 +10953,7 @@@ STAGING - INDUSTRIAL I
  M:    Jonathan Cameron <jic23@kernel.org>
  L:    linux-iio@vger.kernel.org
  S:    Odd Fixes
 +F:    Documentation/devicetree/bindings/staging/iio/
  F:    drivers/staging/iio/
  
  STAGING - LIRC (LINUX INFRARED REMOTE CONTROL) DRIVERS
@@@ -11245,8 -11144,7 +11251,8 @@@ S:   Maintaine
  F:    drivers/media/i2c/tda9840*
  
  TEA5761 TUNER DRIVER
 -M:    Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 +M:    Mauro Carvalho Chehab <mchehab@s-opensource.com>
 +M:    Mauro Carvalho Chehab <mchehab@kernel.org>
  L:    linux-media@vger.kernel.org
  W:    https://linuxtv.org
  T:    git git://linuxtv.org/media_tree.git
@@@ -11254,8 -11152,7 +11260,8 @@@ S:   Odd fixe
  F:    drivers/media/tuners/tea5761.*
  
  TEA5767 TUNER DRIVER
 -M:    Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 +M:    Mauro Carvalho Chehab <mchehab@s-opensource.com>
 +M:    Mauro Carvalho Chehab <mchehab@kernel.org>
  L:    linux-media@vger.kernel.org
  W:    https://linuxtv.org
  T:    git git://linuxtv.org/media_tree.git
@@@ -11642,8 -11539,7 +11648,8 @@@ F:   include/linux/shmem_fs.
  F:    mm/shmem.c
  
  TM6000 VIDEO4LINUX DRIVER
 -M:    Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 +M:    Mauro Carvalho Chehab <mchehab@s-opensource.com>
 +M:    Mauro Carvalho Chehab <mchehab@kernel.org>
  L:    linux-media@vger.kernel.org
  W:    https://linuxtv.org
  T:    git git://linuxtv.org/media_tree.git
@@@ -11997,8 -11893,7 +12003,8 @@@ F:   drivers/usb/common/usb-otg-fsm.
  
  USB OVER IP DRIVER
  M:    Valentina Manea <valentina.manea.m@gmail.com>
 -M:    Shuah Khan <shuah.kh@samsung.com>
 +M:    Shuah Khan <shuahkh@osg.samsung.com>
 +M:    Shuah Khan <shuah@kernel.org>
  L:    linux-usb@vger.kernel.org
  S:    Maintained
  F:    Documentation/usb/usbip_protocol.txt
@@@ -12069,7 -11964,6 +12075,7 @@@ L:   linux-usb@vger.kernel.or
  W:    http://www.linux-usb.org
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git
  S:    Supported
 +F:    Documentation/devicetree/bindings/usb/
  F:    Documentation/usb/
  F:    drivers/usb/
  F:    include/linux/usb.h
@@@ -12243,7 -12137,6 +12249,7 @@@ VIRTIO CORE, NET AND BLOCK DRIVER
  M:    "Michael S. Tsirkin" <mst@redhat.com>
  L:    virtualization@lists.linux-foundation.org
  S:    Maintained
 +F:    Documentation/devicetree/bindings/virtio/
  F:    drivers/virtio/
  F:    tools/virtio/
  F:    drivers/net/virtio_net.c
@@@ -12632,8 -12525,7 +12638,8 @@@ S:   Maintaine
  F:    arch/x86/entry/vdso/
  
  XC2028/3028 TUNER DRIVER
 -M:    Mauro Carvalho Chehab <mchehab@osg.samsung.com>
 +M:    Mauro Carvalho Chehab <mchehab@s-opensource.com>
 +M:    Mauro Carvalho Chehab <mchehab@kernel.org>
  L:    linux-media@vger.kernel.org
  W:    https://linuxtv.org
  T:    git git://linuxtv.org/media_tree.git
diff --combined arch/ia64/Kconfig
@@@ -39,13 -39,12 +39,12 @@@ config IA6
        select GENERIC_PENDING_IRQ if SMP
        select GENERIC_IRQ_SHOW
        select GENERIC_IRQ_LEGACY
-       select ARCH_WANT_OPTIONAL_GPIOLIB
        select ARCH_HAVE_NMI_SAFE_CMPXCHG
        select GENERIC_IOMAP
        select GENERIC_SMP_IDLE_THREAD
        select ARCH_INIT_TASK
        select ARCH_TASK_STRUCT_ALLOCATOR
 -      select ARCH_THREAD_INFO_ALLOCATOR
 +      select ARCH_THREAD_STACK_ALLOCATOR
        select ARCH_CLOCKSOURCE_DATA
        select GENERIC_TIME_VSYSCALL_OLD
        select SYSCTL_ARCH_UNALIGN_NO_WARN
diff --combined arch/powerpc/Kconfig
@@@ -98,7 -98,6 +98,6 @@@ config PP
        select HAVE_FUNCTION_TRACER
        select HAVE_FUNCTION_GRAPH_TRACER
        select SYSCTL_EXCEPTION_TRACE
-       select ARCH_WANT_OPTIONAL_GPIOLIB
        select VIRT_TO_BUS if !PPC64
        select HAVE_IDE
        select HAVE_IOREMAP_PROT
        select IRQ_FORCED_THREADING
        select HAVE_RCU_TABLE_FREE if SMP
        select HAVE_SYSCALL_TRACEPOINTS
 -      select HAVE_CBPF_JIT
 +      select HAVE_CBPF_JIT if CPU_BIG_ENDIAN
        select HAVE_ARCH_JUMP_LABEL
        select ARCH_HAVE_NMI_SAFE_CMPXCHG
        select ARCH_HAS_GCOV_PROFILE_ALL
diff --combined drivers/Makefile
@@@ -12,7 -12,7 +12,7 @@@ obj-$(CONFIG_GENERIC_PHY)     += phy
  
  # GPIO must come after pinctrl as gpios may need to mux pins etc
  obj-$(CONFIG_PINCTRL)         += pinctrl/
- obj-y                         += gpio/
+ obj-$(CONFIG_GPIOLIB)         += gpio/
  obj-y                         += pwm/
  obj-$(CONFIG_PCI)             += pci/
  obj-$(CONFIG_PARISC)          += parisc/
@@@ -128,6 -128,7 +128,6 @@@ obj-$(CONFIG_SGI_SN)               += sn
  obj-y                         += firmware/
  obj-$(CONFIG_CRYPTO)          += crypto/
  obj-$(CONFIG_SUPERH)          += sh/
 -obj-$(CONFIG_ARCH_SHMOBILE)   += sh/
  ifndef CONFIG_ARCH_USES_GETTIMEOFFSET
  obj-y                         += clocksource/
  endif
diff --combined drivers/gpio/Kconfig
@@@ -33,7 -33,6 +33,7 @@@ config ARCH_REQUIRE_GPIOLI
  
  menuconfig GPIOLIB
        bool "GPIO Support"
 +      select ANON_INODES
        help
          This enables GPIO support through the generic GPIO library.
          You only need to enable this, if you also want to enable
@@@ -49,7 -48,7 +49,7 @@@ config GPIO_DEVRE
  
  config OF_GPIO
        def_bool y
 -      depends on OF || COMPILE_TEST
 +      depends on OF
  
  config GPIO_ACPI
        def_bool y
@@@ -250,7 -249,7 +250,7 @@@ config GPIO_LOONGSO
          driver for GPIO functionality on Loongson-2F/3A/3B processors.
  
  config GPIO_LPC18XX
-       bool "NXP LPC18XX/43XX GPIO support"
+       tristate "NXP LPC18XX/43XX GPIO support"
        default y if ARCH_LPC18XX
        depends on OF_GPIO && (ARCH_LPC18XX || COMPILE_TEST)
        help
@@@ -402,12 -401,9 +402,12 @@@ config GPIO_TB10
        select OF_GPIO
  
  config GPIO_TEGRA
 -      bool
 -      default y
 +      bool "NVIDIA Tegra GPIO support"
 +      default ARCH_TEGRA
        depends on ARCH_TEGRA || COMPILE_TEST
 +      depends on OF
 +      help
 +        Say yes here to support GPIO pins on NVIDIA Tegra SoCs.
  
  config GPIO_TS4800
        tristate "TS-4800 DIO blocks and compatibles"
@@@ -534,7 -530,7 +534,7 @@@ menu "Port-mapped I/O GPIO drivers
  
  config GPIO_104_DIO_48E
        tristate "ACCES 104-DIO-48E GPIO support"
 -      depends on ISA
 +      depends on ISA_BUS_API
        select GPIOLIB_IRQCHIP
        help
          Enables GPIO support for the ACCES 104-DIO-48E series (104-DIO-48E,
  
  config GPIO_104_IDIO_16
        tristate "ACCES 104-IDIO-16 GPIO support"
 -      depends on ISA
 +      depends on ISA_BUS_API
        select GPIOLIB_IRQCHIP
        help
          Enables GPIO support for the ACCES 104-IDIO-16 family (104-IDIO-16,
  
  config GPIO_104_IDI_48
        tristate "ACCES 104-IDI-48 GPIO support"
 -      depends on ISA
 +      depends on ISA_BUS_API
        select GPIOLIB_IRQCHIP
        help
          Enables GPIO support for the ACCES 104-IDI-48 family (104-IDI-48A,
@@@ -631,7 -627,7 +631,7 @@@ config GPIO_TS550
  
  config GPIO_WS16C48
        tristate "WinSystems WS16C48 GPIO support"
 -      depends on ISA
 +      depends on ISA_BUS_API
        select GPIOLIB_IRQCHIP
        help
          Enables GPIO support for the WinSystems WS16C48. The base port
@@@ -874,6 -870,15 +874,15 @@@ config GPIO_LP394
          LP3943 can be used as a GPIO expander which provides up to 16 GPIOs.
          Open drain outputs are required for this usage.
  
+ config GPIO_MAX77620
+       tristate "GPIO support for PMIC MAX77620 and MAX20024"
+       depends on MFD_MAX77620
+       help
+         GPIO driver for MAX77620 and MAX20024 PMIC from Maxim Semiconductor.
+         MAX77620 PMIC has 8 pins that can be configured as GPIOs. The
+         driver also provides interrupt support for each of the gpios.
+         Say yes here to enable the max77620 to be used as gpio controller.
  config GPIO_MSIC
        bool "Intel MSIC mixed signal gpio support"
        depends on MFD_INTEL_MSIC
@@@ -1029,11 -1034,18 +1038,18 @@@ config GPIO_BT8X
          If unsure, say N.
  
  config GPIO_INTEL_MID
-       bool "Intel Mid GPIO support"
-       depends on X86
+       bool "Intel MID GPIO support"
+       depends on X86_INTEL_MID
+       select GPIOLIB_IRQCHIP
+       help
+         Say Y here to support Intel MID GPIO.
+ config GPIO_MERRIFIELD
+       tristate "Intel Merrifield GPIO support"
+       depends on X86_INTEL_MID
        select GPIOLIB_IRQCHIP
        help
-         Say Y here to support Intel Mid GPIO.
+         Say Y here to support Intel Merrifield GPIO.
  
  config GPIO_ML_IOH
        tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support"
@@@ -16,7 -16,6 +16,7 @@@
  #include <linux/errno.h>
  #include <linux/module.h>
  #include <linux/io.h>
 +#include <linux/io-mapping.h>
  #include <linux/gpio/consumer.h>
  #include <linux/of.h>
  #include <linux/of_address.h>
  
  #include "gpiolib.h"
  
- /* Private data structure for of_gpiochip_find_and_xlate */
struct gg_data {
-       enum of_gpio_flags *flags;
-       struct of_phandle_args gpiospec;
+ static int of_gpiochip_match_node(struct gpio_chip *chip, void *data)
+ {
+       return chip->gpiodev->dev.of_node == data;
+ }
  
-       struct gpio_desc *out_gpio;
- };
+ static struct gpio_chip *of_find_gpiochip_by_node(struct device_node *np)
+ {
+       return gpiochip_find(np, of_gpiochip_match_node);
+ }
  
- /* Private function for resolving node pointer to gpio_chip */
- static int of_gpiochip_find_and_xlate(struct gpio_chip *gc, void *data)
+ static struct gpio_desc *of_xlate_and_get_gpiod_flags(struct gpio_chip *chip,
+                                       struct of_phandle_args *gpiospec,
+                                       enum of_gpio_flags *flags)
  {
-       struct gg_data *gg_data = data;
        int ret;
  
-       if ((gc->of_node != gg_data->gpiospec.np) ||
-           (gc->of_gpio_n_cells != gg_data->gpiospec.args_count) ||
-           (!gc->of_xlate))
-               return false;
-       ret = gc->of_xlate(gc, &gg_data->gpiospec, gg_data->flags);
-       if (ret < 0) {
-               /* We've found a gpio chip, but the translation failed.
-                * Store translation error in out_gpio.
-                * Return false to keep looking, as more than one gpio chip
-                * could be registered per of-node.
-                */
-               gg_data->out_gpio = ERR_PTR(ret);
-               return false;
-        }
-       gg_data->out_gpio = gpiochip_get_desc(gc, ret);
-       return true;
+       if (chip->of_gpio_n_cells != gpiospec->args_count)
+               return ERR_PTR(-EINVAL);
+       ret = chip->of_xlate(chip, gpiospec, flags);
+       if (ret < 0)
+               return ERR_PTR(ret);
+       return gpiochip_get_desc(chip, ret);
  }
  
  /**
  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 = ERR_PTR(-EPROBE_DEFER)
-       };
+       struct of_phandle_args gpiospec;
+       struct gpio_chip *chip;
+       struct gpio_desc *desc;
        int ret;
  
-       /* .of_xlate might decide to not fill in the flags, so clear it. */
-       if (flags)
-               *flags = 0;
        ret = of_parse_phandle_with_args(np, propname, "#gpio-cells", index,
-                                        &gg_data.gpiospec);
+                                        &gpiospec);
        if (ret) {
                pr_debug("%s: can't parse '%s' property of node '%s[%d]'\n",
                        __func__, propname, np->full_name, index);
                return ERR_PTR(ret);
        }
  
-       gpiochip_find(&gg_data, of_gpiochip_find_and_xlate);
+       chip = of_find_gpiochip_by_node(gpiospec.np);
+       if (!chip) {
+               desc = ERR_PTR(-EPROBE_DEFER);
+               goto out;
+       }
+       desc = of_xlate_and_get_gpiod_flags(chip, &gpiospec, flags);
+       if (IS_ERR(desc))
+               goto out;
  
-       of_node_put(gg_data.gpiospec.np);
        pr_debug("%s: parsed '%s' property of node '%s[%d]' - status (%d)\n",
                 __func__, propname, np->full_name, index,
-                PTR_ERR_OR_ZERO(gg_data.out_gpio));
-       return gg_data.out_gpio;
+                PTR_ERR_OR_ZERO(desc));
+ out:
+       of_node_put(gpiospec.np);
+       return desc;
  }
  
  int of_get_named_gpio_flags(struct device_node *np, const char *list_name,
@@@ -122,6 -116,7 +117,7 @@@ EXPORT_SYMBOL(of_get_named_gpio_flags)
  /**
   * of_parse_own_gpio() - Get a GPIO hog descriptor, names and flags for GPIO API
   * @np:               device node to get GPIO from
+  * @chip:     GPIO chip whose hog is parsed
   * @name:     GPIO line name
   * @lflags:   gpio_lookup_flags - returned from of_find_gpio() or
   *            of_parse_own_gpio()
   * value on the error condition.
   */
  static struct gpio_desc *of_parse_own_gpio(struct device_node *np,
+                                          struct gpio_chip *chip,
                                           const char **name,
                                           enum gpio_lookup_flags *lflags,
                                           enum gpiod_flags *dflags)
  {
        struct device_node *chip_np;
        enum of_gpio_flags xlate_flags;
-       struct gg_data gg_data = {
-               .flags = &xlate_flags,
-       };
+       struct of_phandle_args gpiospec;
+       struct gpio_desc *desc;
        u32 tmp;
-       int i, ret;
+       int ret;
  
-       chip_np = np->parent;
+       chip_np = chip->of_node;
        if (!chip_np)
                return ERR_PTR(-EINVAL);
  
        if (ret)
                return ERR_PTR(ret);
  
-       if (tmp > MAX_PHANDLE_ARGS)
-               return ERR_PTR(-EINVAL);
+       gpiospec.np = chip_np;
+       gpiospec.args_count = tmp;
  
-       gg_data.gpiospec.args_count = tmp;
-       gg_data.gpiospec.np = chip_np;
-       for (i = 0; i < tmp; i++) {
-               ret = of_property_read_u32_index(np, "gpios", i,
-                                          &gg_data.gpiospec.args[i]);
-               if (ret)
-                       return ERR_PTR(ret);
-       }
+       ret = of_property_read_u32_array(np, "gpios", gpiospec.args, tmp);
+       if (ret)
+               return ERR_PTR(ret);
  
-       gpiochip_find(&gg_data, of_gpiochip_find_and_xlate);
-       if (!gg_data.out_gpio) {
-               if (np->parent == np)
-                       return ERR_PTR(-ENXIO);
-               else
-                       return ERR_PTR(-EINVAL);
-       }
+       desc = of_xlate_and_get_gpiod_flags(chip, &gpiospec, &xlate_flags);
+       if (IS_ERR(desc))
+               return desc;
  
        if (xlate_flags & OF_GPIO_ACTIVE_LOW)
                *lflags |= GPIO_ACTIVE_LOW;
                *dflags |= GPIOD_OUT_HIGH;
        else {
                pr_warn("GPIO line %d (%s): no hogging state specified, bailing out\n",
-                       desc_to_gpio(gg_data.out_gpio), np->name);
+                       desc_to_gpio(desc), np->name);
                return ERR_PTR(-EINVAL);
        }
  
        if (name && of_property_read_string(np, "line-name", name))
                *name = np->name;
  
-       return gg_data.out_gpio;
+       return desc;
  }
  
  /**
@@@ -262,7 -248,7 +249,7 @@@ static int of_gpiochip_scan_gpios(struc
                if (!of_property_read_bool(np, "gpio-hog"))
                        continue;
  
-               desc = of_parse_own_gpio(np, &name, &lflags, &dflags);
+               desc = of_parse_own_gpio(np, chip, &name, &lflags, &dflags);
                if (IS_ERR(desc))
                        continue;
  
@@@ -410,6 -396,7 +397,7 @@@ static int of_gpiochip_add_pin_range(st
                        break;
  
                pctldev = of_pinctrl_get(pinspec.np);
+               of_node_put(pinspec.np);
                if (!pctldev)
                        return -EPROBE_DEFER;
  
@@@ -487,6 -474,9 +475,9 @@@ int of_gpiochip_add(struct gpio_chip *c
                chip->of_xlate = of_gpio_simple_xlate;
        }
  
+       if (chip->of_gpio_n_cells > MAX_PHANDLE_ARGS)
+               return -EINVAL;
        status = of_gpiochip_add_pin_range(chip);
        if (status)
                return status;
diff --combined drivers/gpio/gpiolib.c
  #include <linux/gpio/driver.h>
  #include <linux/gpio/machine.h>
  #include <linux/pinctrl/consumer.h>
- #include <linux/idr.h>
  #include <linux/cdev.h>
  #include <linux/fs.h>
  #include <linux/uaccess.h>
  #include <linux/compat.h>
+ #include <linux/anon_inodes.h>
+ #include <linux/kfifo.h>
+ #include <linux/poll.h>
+ #include <linux/timekeeping.h>
  #include <uapi/linux/gpio.h>
  
  #include "gpiolib.h"
@@@ -310,6 -313,497 +313,497 @@@ static int gpiochip_set_desc_names(stru
        return 0;
  }
  
+ /*
+  * GPIO line handle management
+  */
+ /**
+  * struct linehandle_state - contains the state of a userspace handle
+  * @gdev: the GPIO device the handle pertains to
+  * @label: consumer label used to tag descriptors
+  * @descs: the GPIO descriptors held by this handle
+  * @numdescs: the number of descriptors held in the descs array
+  */
+ struct linehandle_state {
+       struct gpio_device *gdev;
+       const char *label;
+       struct gpio_desc *descs[GPIOHANDLES_MAX];
+       u32 numdescs;
+ };
+ static long linehandle_ioctl(struct file *filep, unsigned int cmd,
+                            unsigned long arg)
+ {
+       struct linehandle_state *lh = filep->private_data;
+       void __user *ip = (void __user *)arg;
+       struct gpiohandle_data ghd;
+       int i;
+       if (cmd == GPIOHANDLE_GET_LINE_VALUES_IOCTL) {
+               int val;
+               /* TODO: check if descriptors are really input */
+               for (i = 0; i < lh->numdescs; i++) {
+                       val = gpiod_get_value_cansleep(lh->descs[i]);
+                       if (val < 0)
+                               return val;
+                       ghd.values[i] = val;
+               }
+               if (copy_to_user(ip, &ghd, sizeof(ghd)))
+                       return -EFAULT;
+               return 0;
+       } else if (cmd == GPIOHANDLE_SET_LINE_VALUES_IOCTL) {
+               int vals[GPIOHANDLES_MAX];
+               /* TODO: check if descriptors are really output */
+               if (copy_from_user(&ghd, ip, sizeof(ghd)))
+                       return -EFAULT;
+               /* Clamp all values to [0,1] */
+               for (i = 0; i < lh->numdescs; i++)
+                       vals[i] = !!ghd.values[i];
+               /* Reuse the array setting function */
+               gpiod_set_array_value_complex(false,
+                                             true,
+                                             lh->numdescs,
+                                             lh->descs,
+                                             vals);
+               return 0;
+       }
+       return -EINVAL;
+ }
+ #ifdef CONFIG_COMPAT
+ static long linehandle_ioctl_compat(struct file *filep, unsigned int cmd,
+                            unsigned long arg)
+ {
+       return linehandle_ioctl(filep, cmd, (unsigned long)compat_ptr(arg));
+ }
+ #endif
+ static int linehandle_release(struct inode *inode, struct file *filep)
+ {
+       struct linehandle_state *lh = filep->private_data;
+       struct gpio_device *gdev = lh->gdev;
+       int i;
+       for (i = 0; i < lh->numdescs; i++)
+               gpiod_free(lh->descs[i]);
+       kfree(lh->label);
+       kfree(lh);
+       put_device(&gdev->dev);
+       return 0;
+ }
+ static const struct file_operations linehandle_fileops = {
+       .release = linehandle_release,
+       .owner = THIS_MODULE,
+       .llseek = noop_llseek,
+       .unlocked_ioctl = linehandle_ioctl,
+ #ifdef CONFIG_COMPAT
+       .compat_ioctl = linehandle_ioctl_compat,
+ #endif
+ };
+ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
+ {
+       struct gpiohandle_request handlereq;
+       struct linehandle_state *lh;
+       int fd, i, ret;
+       if (copy_from_user(&handlereq, ip, sizeof(handlereq)))
+               return -EFAULT;
+       if ((handlereq.lines == 0) || (handlereq.lines > GPIOHANDLES_MAX))
+               return -EINVAL;
+       lh = kzalloc(sizeof(*lh), GFP_KERNEL);
+       if (!lh)
+               return -ENOMEM;
+       lh->gdev = gdev;
+       get_device(&gdev->dev);
+       /* Make sure this is terminated */
+       handlereq.consumer_label[sizeof(handlereq.consumer_label)-1] = '\0';
+       if (strlen(handlereq.consumer_label)) {
+               lh->label = kstrdup(handlereq.consumer_label,
+                                   GFP_KERNEL);
+               if (!lh->label) {
+                       ret = -ENOMEM;
+                       goto out_free_lh;
+               }
+       }
+       /* Request each GPIO */
+       for (i = 0; i < handlereq.lines; i++) {
+               u32 offset = handlereq.lineoffsets[i];
+               u32 lflags = handlereq.flags;
+               struct gpio_desc *desc;
+               desc = &gdev->descs[offset];
+               ret = gpiod_request(desc, lh->label);
+               if (ret)
+                       goto out_free_descs;
+               lh->descs[i] = desc;
+               if (lflags & GPIOHANDLE_REQUEST_ACTIVE_LOW)
+                       set_bit(FLAG_ACTIVE_LOW, &desc->flags);
+               if (lflags & GPIOHANDLE_REQUEST_OPEN_DRAIN)
+                       set_bit(FLAG_OPEN_DRAIN, &desc->flags);
+               if (lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE)
+                       set_bit(FLAG_OPEN_SOURCE, &desc->flags);
+               /*
+                * Lines have to be requested explicitly for input
+                * or output, else the line will be treated "as is".
+                */
+               if (lflags & GPIOHANDLE_REQUEST_OUTPUT) {
+                       int val = !!handlereq.default_values[i];
+                       ret = gpiod_direction_output(desc, val);
+                       if (ret)
+                               goto out_free_descs;
+               } else if (lflags & GPIOHANDLE_REQUEST_INPUT) {
+                       ret = gpiod_direction_input(desc);
+                       if (ret)
+                               goto out_free_descs;
+               }
+               dev_dbg(&gdev->dev, "registered chardev handle for line %d\n",
+                       offset);
+       }
+       /* Let i point at the last handle */
+       i--;
+       lh->numdescs = handlereq.lines;
+       fd = anon_inode_getfd("gpio-linehandle",
+                             &linehandle_fileops,
+                             lh,
+                             O_RDONLY | O_CLOEXEC);
+       if (fd < 0) {
+               ret = fd;
+               goto out_free_descs;
+       }
+       handlereq.fd = fd;
+       if (copy_to_user(ip, &handlereq, sizeof(handlereq))) {
+               ret = -EFAULT;
+               goto out_free_descs;
+       }
+       dev_dbg(&gdev->dev, "registered chardev handle for %d lines\n",
+               lh->numdescs);
+       return 0;
+ out_free_descs:
+       for (; i >= 0; i--)
+               gpiod_free(lh->descs[i]);
+       kfree(lh->label);
+ out_free_lh:
+       kfree(lh);
+       put_device(&gdev->dev);
+       return ret;
+ }
+ /*
+  * GPIO line event management
+  */
+ /**
+  * struct lineevent_state - contains the state of a userspace event
+  * @gdev: the GPIO device the event pertains to
+  * @label: consumer label used to tag descriptors
+  * @desc: the GPIO descriptor held by this event
+  * @eflags: the event flags this line was requested with
+  * @irq: the interrupt that trigger in response to events on this GPIO
+  * @wait: wait queue that handles blocking reads of events
+  * @events: KFIFO for the GPIO events
+  * @read_lock: mutex lock to protect reads from colliding with adding
+  * new events to the FIFO
+  */
+ struct lineevent_state {
+       struct gpio_device *gdev;
+       const char *label;
+       struct gpio_desc *desc;
+       u32 eflags;
+       int irq;
+       wait_queue_head_t wait;
+       DECLARE_KFIFO(events, struct gpioevent_data, 16);
+       struct mutex read_lock;
+ };
+ static unsigned int lineevent_poll(struct file *filep,
+                                  struct poll_table_struct *wait)
+ {
+       struct lineevent_state *le = filep->private_data;
+       unsigned int events = 0;
+       poll_wait(filep, &le->wait, wait);
+       if (!kfifo_is_empty(&le->events))
+               events = POLLIN | POLLRDNORM;
+       return events;
+ }
+ static ssize_t lineevent_read(struct file *filep,
+                             char __user *buf,
+                             size_t count,
+                             loff_t *f_ps)
+ {
+       struct lineevent_state *le = filep->private_data;
+       unsigned int copied;
+       int ret;
+       if (count < sizeof(struct gpioevent_data))
+               return -EINVAL;
+       do {
+               if (kfifo_is_empty(&le->events)) {
+                       if (filep->f_flags & O_NONBLOCK)
+                               return -EAGAIN;
+                       ret = wait_event_interruptible(le->wait,
+                                       !kfifo_is_empty(&le->events));
+                       if (ret)
+                               return ret;
+               }
+               if (mutex_lock_interruptible(&le->read_lock))
+                       return -ERESTARTSYS;
+               ret = kfifo_to_user(&le->events, buf, count, &copied);
+               mutex_unlock(&le->read_lock);
+               if (ret)
+                       return ret;
+               /*
+                * If we couldn't read anything from the fifo (a different
+                * thread might have been faster) we either return -EAGAIN if
+                * the file descriptor is non-blocking, otherwise we go back to
+                * sleep and wait for more data to arrive.
+                */
+               if (copied == 0 && (filep->f_flags & O_NONBLOCK))
+                       return -EAGAIN;
+       } while (copied == 0);
+       return copied;
+ }
+ static int lineevent_release(struct inode *inode, struct file *filep)
+ {
+       struct lineevent_state *le = filep->private_data;
+       struct gpio_device *gdev = le->gdev;
+       free_irq(le->irq, le);
+       gpiod_free(le->desc);
+       kfree(le->label);
+       kfree(le);
+       put_device(&gdev->dev);
+       return 0;
+ }
+ static long lineevent_ioctl(struct file *filep, unsigned int cmd,
+                           unsigned long arg)
+ {
+       struct lineevent_state *le = filep->private_data;
+       void __user *ip = (void __user *)arg;
+       struct gpiohandle_data ghd;
+       /*
+        * We can get the value for an event line but not set it,
+        * because it is input by definition.
+        */
+       if (cmd == GPIOHANDLE_GET_LINE_VALUES_IOCTL) {
+               int val;
+               val = gpiod_get_value_cansleep(le->desc);
+               if (val < 0)
+                       return val;
+               ghd.values[0] = val;
+               if (copy_to_user(ip, &ghd, sizeof(ghd)))
+                       return -EFAULT;
+               return 0;
+       }
+       return -EINVAL;
+ }
+ #ifdef CONFIG_COMPAT
+ static long lineevent_ioctl_compat(struct file *filep, unsigned int cmd,
+                                  unsigned long arg)
+ {
+       return lineevent_ioctl(filep, cmd, (unsigned long)compat_ptr(arg));
+ }
+ #endif
+ static const struct file_operations lineevent_fileops = {
+       .release = lineevent_release,
+       .read = lineevent_read,
+       .poll = lineevent_poll,
+       .owner = THIS_MODULE,
+       .llseek = noop_llseek,
+       .unlocked_ioctl = lineevent_ioctl,
+ #ifdef CONFIG_COMPAT
+       .compat_ioctl = lineevent_ioctl_compat,
+ #endif
+ };
+ static irqreturn_t lineevent_irq_thread(int irq, void *p)
+ {
+       struct lineevent_state *le = p;
+       struct gpioevent_data ge;
+       int ret;
+       ge.timestamp = ktime_get_real_ns();
+       if (le->eflags & GPIOEVENT_REQUEST_BOTH_EDGES) {
+               int level = gpiod_get_value_cansleep(le->desc);
+               if (level)
+                       /* Emit low-to-high event */
+                       ge.id = GPIOEVENT_EVENT_RISING_EDGE;
+               else
+                       /* Emit high-to-low event */
+                       ge.id = GPIOEVENT_EVENT_FALLING_EDGE;
+       } else if (le->eflags & GPIOEVENT_REQUEST_RISING_EDGE) {
+               /* Emit low-to-high event */
+               ge.id = GPIOEVENT_EVENT_RISING_EDGE;
+       } else if (le->eflags & GPIOEVENT_REQUEST_FALLING_EDGE) {
+               /* Emit high-to-low event */
+               ge.id = GPIOEVENT_EVENT_FALLING_EDGE;
+       } else {
+               return IRQ_NONE;
+       }
+       ret = kfifo_put(&le->events, ge);
+       if (ret != 0)
+               wake_up_poll(&le->wait, POLLIN);
+       return IRQ_HANDLED;
+ }
+ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
+ {
+       struct gpioevent_request eventreq;
+       struct lineevent_state *le;
+       struct gpio_desc *desc;
+       u32 offset;
+       u32 lflags;
+       u32 eflags;
+       int fd;
+       int ret;
+       int irqflags = 0;
+       if (copy_from_user(&eventreq, ip, sizeof(eventreq)))
+               return -EFAULT;
+       le = kzalloc(sizeof(*le), GFP_KERNEL);
+       if (!le)
+               return -ENOMEM;
+       le->gdev = gdev;
+       get_device(&gdev->dev);
+       /* Make sure this is terminated */
+       eventreq.consumer_label[sizeof(eventreq.consumer_label)-1] = '\0';
+       if (strlen(eventreq.consumer_label)) {
+               le->label = kstrdup(eventreq.consumer_label,
+                                   GFP_KERNEL);
+               if (!le->label) {
+                       ret = -ENOMEM;
+                       goto out_free_le;
+               }
+       }
+       offset = eventreq.lineoffset;
+       lflags = eventreq.handleflags;
+       eflags = eventreq.eventflags;
+       /* This is just wrong: we don't look for events on output lines */
+       if (lflags & GPIOHANDLE_REQUEST_OUTPUT) {
+               ret = -EINVAL;
+               goto out_free_label;
+       }
+       desc = &gdev->descs[offset];
+       ret = gpiod_request(desc, le->label);
+       if (ret)
+               goto out_free_desc;
+       le->desc = desc;
+       le->eflags = eflags;
+       if (lflags & GPIOHANDLE_REQUEST_ACTIVE_LOW)
+               set_bit(FLAG_ACTIVE_LOW, &desc->flags);
+       if (lflags & GPIOHANDLE_REQUEST_OPEN_DRAIN)
+               set_bit(FLAG_OPEN_DRAIN, &desc->flags);
+       if (lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE)
+               set_bit(FLAG_OPEN_SOURCE, &desc->flags);
+       ret = gpiod_direction_input(desc);
+       if (ret)
+               goto out_free_desc;
+       le->irq = gpiod_to_irq(desc);
+       if (le->irq <= 0) {
+               ret = -ENODEV;
+               goto out_free_desc;
+       }
+       if (eflags & GPIOEVENT_REQUEST_RISING_EDGE)
+               irqflags |= IRQF_TRIGGER_RISING;
+       if (eflags & GPIOEVENT_REQUEST_FALLING_EDGE)
+               irqflags |= IRQF_TRIGGER_FALLING;
+       irqflags |= IRQF_ONESHOT;
+       irqflags |= IRQF_SHARED;
+       INIT_KFIFO(le->events);
+       init_waitqueue_head(&le->wait);
+       mutex_init(&le->read_lock);
+       /* Request a thread to read the events */
+       ret = request_threaded_irq(le->irq,
+                       NULL,
+                       lineevent_irq_thread,
+                       irqflags,
+                       le->label,
+                       le);
+       if (ret)
+               goto out_free_desc;
+       fd = anon_inode_getfd("gpio-event",
+                             &lineevent_fileops,
+                             le,
+                             O_RDONLY | O_CLOEXEC);
+       if (fd < 0) {
+               ret = fd;
+               goto out_free_irq;
+       }
+       eventreq.fd = fd;
+       if (copy_to_user(ip, &eventreq, sizeof(eventreq))) {
+               ret = -EFAULT;
+               goto out_free_irq;
+       }
+       return 0;
+ out_free_irq:
+       free_irq(le->irq, le);
+ out_free_desc:
+       gpiod_free(le->desc);
+ out_free_label:
+       kfree(le->label);
+ out_free_le:
+       kfree(le);
+       put_device(&gdev->dev);
+       return ret;
+ }
  /**
   * gpio_ioctl() - ioctl handler for the GPIO chardev
   */
@@@ -385,6 -879,10 +879,10 @@@ static long gpio_ioctl(struct file *fil
                if (copy_to_user(ip, &lineinfo, sizeof(lineinfo)))
                        return -EFAULT;
                return 0;
+       } else if (cmd == GPIO_GET_LINEHANDLE_IOCTL) {
+               return linehandle_create(gdev, ip);
+       } else if (cmd == GPIO_GET_LINEEVENT_IOCTL) {
+               return lineevent_create(gdev, ip);
        }
        return -EINVAL;
  }
@@@ -449,6 -947,7 +947,6 @@@ static void gpiodevice_release(struct d
  {
        struct gpio_device *gdev = dev_get_drvdata(dev);
  
 -      cdev_del(&gdev->chrdev);
        list_del(&gdev->list);
        ida_simple_remove(&gpio_ida, gdev->id);
        kfree(gdev->label);
@@@ -481,6 -980,7 +979,6 @@@ static int gpiochip_setup_dev(struct gp
  
        /* From this point, the .release() function cleans up gpio_device */
        gdev->dev.release = gpiodevice_release;
 -      get_device(&gdev->dev);
        pr_debug("%s: registered GPIOs %d to %d on device: %s (%s)\n",
                 __func__, gdev->base, gdev->base + gdev->ngpio - 1,
                 dev_name(&gdev->dev), gdev->chip->label ? : "generic");
@@@ -548,13 -1048,14 +1046,14 @@@ int gpiochip_add_data(struct gpio_chip 
        if (chip->parent) {
                gdev->dev.parent = chip->parent;
                gdev->dev.of_node = chip->parent->of_node;
-       } else {
+       }
  #ifdef CONFIG_OF_GPIO
        /* If the gpiochip has an assigned OF node this takes precedence */
-               if (chip->of_node)
-                       gdev->dev.of_node = chip->of_node;
+       if (chip->of_node)
+               gdev->dev.of_node = chip->of_node;
  #endif
-       }
        gdev->id = ida_simple_get(&gpio_ida, 0, 0, GFP_KERNEL);
        if (gdev->id < 0) {
                status = gdev->id;
@@@ -768,8 -1269,6 +1267,8 @@@ void gpiochip_remove(struct gpio_chip *
         * be removed, else it will be dangling until the last user is
         * gone.
         */
 +      cdev_del(&gdev->chrdev);
 +      device_del(&gdev->dev);
        put_device(&gdev->dev);
  }
  EXPORT_SYMBOL_GPL(gpiochip_remove);
@@@ -869,7 -1368,7 +1368,7 @@@ struct gpio_chip *gpiochip_find(void *d
  
        spin_lock_irqsave(&gpio_lock, flags);
        list_for_each_entry(gdev, &gpio_devices, list)
 -              if (match(gdev->chip, data))
 +              if (gdev->chip && match(gdev->chip, data))
                        break;
  
        /* No match? */
@@@ -1352,6 -1851,14 +1851,6 @@@ static int __gpiod_request(struct gpio_
                spin_lock_irqsave(&gpio_lock, flags);
        }
  done:
 -      if (status < 0) {
 -              /* Clear flags that might have been set by the caller before
 -               * requesting the GPIO.
 -               */
 -              clear_bit(FLAG_ACTIVE_LOW, &desc->flags);
 -              clear_bit(FLAG_OPEN_DRAIN, &desc->flags);
 -              clear_bit(FLAG_OPEN_SOURCE, &desc->flags);
 -      }
        spin_unlock_irqrestore(&gpio_lock, flags);
        return status;
  }
  #define VALIDATE_DESC(desc) do { \
        if (!desc) \
                return 0; \
 +      if (IS_ERR(desc)) {                                             \
 +              pr_warn("%s: invalid GPIO (errorpointer)\n", __func__); \
 +              return PTR_ERR(desc); \
 +      } \
        if (!desc->gdev) { \
 -              pr_warn("%s: invalid GPIO\n", __func__); \
 +              pr_warn("%s: invalid GPIO (no device)\n", __func__); \
                return -EINVAL; \
        } \
        if ( !desc->gdev->chip ) { \
  #define VALIDATE_DESC_VOID(desc) do { \
        if (!desc) \
                return; \
 +      if (IS_ERR(desc)) {                                             \
 +              pr_warn("%s: invalid GPIO (errorpointer)\n", __func__); \
 +              return; \
 +      } \
        if (!desc->gdev) { \
 -              pr_warn("%s: invalid GPIO\n", __func__); \
 +              pr_warn("%s: invalid GPIO (no device)\n", __func__); \
                return; \
        } \
        if (!desc->gdev->chip) { \
@@@ -2056,14 -2555,7 +2555,14 @@@ int gpiod_to_irq(const struct gpio_des
        struct gpio_chip *chip;
        int offset;
  
 -      VALIDATE_DESC(desc);
 +      /*
 +       * Cannot VALIDATE_DESC() here as gpiod_to_irq() consumer semantics
 +       * requires this function to not return zero on an invalid descriptor
 +       * but rather a negative error number.
 +       */
 +      if (!desc || IS_ERR(desc) || !desc->gdev || !desc->gdev->chip)
 +              return -EINVAL;
 +
        chip = desc->gdev->chip;
        offset = gpio_chip_hwgpio(desc);
        if (chip->to_irq) {
@@@ -2333,7 -2825,7 +2832,7 @@@ static struct gpio_desc *of_find_gpio(s
  
                desc = of_get_named_gpiod_flags(dev->of_node, prop_name, idx,
                                                &of_flags);
-               if (!IS_ERR(desc) || (PTR_ERR(desc) == -EPROBE_DEFER))
+               if (!IS_ERR(desc) || (PTR_ERR(desc) != -ENOENT))
                        break;
        }
  
@@@ -2579,13 -3071,28 +3078,13 @@@ struct gpio_desc *__must_check gpiod_ge
  }
  EXPORT_SYMBOL_GPL(gpiod_get_optional);
  
 -/**
 - * gpiod_parse_flags - helper function to parse GPIO lookup flags
 - * @desc:     gpio to be setup
 - * @lflags:   gpio_lookup_flags - returned from of_find_gpio() or
 - *            of_get_gpio_hog()
 - *
 - * Set the GPIO descriptor flags based on the given GPIO lookup flags.
 - */
 -static void gpiod_parse_flags(struct gpio_desc *desc, unsigned long lflags)
 -{
 -      if (lflags & GPIO_ACTIVE_LOW)
 -              set_bit(FLAG_ACTIVE_LOW, &desc->flags);
 -      if (lflags & GPIO_OPEN_DRAIN)
 -              set_bit(FLAG_OPEN_DRAIN, &desc->flags);
 -      if (lflags & GPIO_OPEN_SOURCE)
 -              set_bit(FLAG_OPEN_SOURCE, &desc->flags);
 -}
  
  /**
   * gpiod_configure_flags - helper function to configure a given GPIO
   * @desc:     gpio whose value will be assigned
   * @con_id:   function within the GPIO consumer
 + * @lflags:   gpio_lookup_flags - returned from of_find_gpio() or
 + *            of_get_gpio_hog()
   * @dflags:   gpiod_flags - optional GPIO initialization flags
   *
   * Return 0 on success, -ENOENT if no GPIO has been assigned to the
   * occurred while trying to acquire the GPIO.
   */
  static int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
 -                               enum gpiod_flags dflags)
 +              unsigned long lflags, enum gpiod_flags dflags)
  {
        int status;
  
 +      if (lflags & GPIO_ACTIVE_LOW)
 +              set_bit(FLAG_ACTIVE_LOW, &desc->flags);
 +      if (lflags & GPIO_OPEN_DRAIN)
 +              set_bit(FLAG_OPEN_DRAIN, &desc->flags);
 +      if (lflags & GPIO_OPEN_SOURCE)
 +              set_bit(FLAG_OPEN_SOURCE, &desc->flags);
 +
        /* No particular flag request, return here... */
        if (!(dflags & GPIOD_FLAGS_BIT_DIR_SET)) {
                pr_debug("no flags found for %s\n", con_id);
@@@ -2670,11 -3170,13 +3169,11 @@@ struct gpio_desc *__must_check gpiod_ge
                return desc;
        }
  
 -      gpiod_parse_flags(desc, lookupflags);
 -
        status = gpiod_request(desc, con_id);
        if (status < 0)
                return ERR_PTR(status);
  
 -      status = gpiod_configure_flags(desc, con_id, flags);
 +      status = gpiod_configure_flags(desc, con_id, lookupflags, flags);
        if (status < 0) {
                dev_dbg(dev, "setup of GPIO %s failed\n", con_id);
                gpiod_put(desc);
@@@ -2730,10 -3232,6 +3229,10 @@@ struct gpio_desc *fwnode_get_named_gpio
        if (IS_ERR(desc))
                return desc;
  
 +      ret = gpiod_request(desc, NULL);
 +      if (ret)
 +              return ERR_PTR(ret);
 +
        if (active_low)
                set_bit(FLAG_ACTIVE_LOW, &desc->flags);
  
                        set_bit(FLAG_OPEN_SOURCE, &desc->flags);
        }
  
 -      ret = gpiod_request(desc, NULL);
 -      if (ret)
 -              return ERR_PTR(ret);
 -
        return desc;
  }
  EXPORT_SYMBOL_GPL(fwnode_get_named_gpiod);
@@@ -2796,6 -3298,8 +3295,6 @@@ int gpiod_hog(struct gpio_desc *desc, c
        chip = gpiod_to_chip(desc);
        hwnum = gpio_chip_hwgpio(desc);
  
 -      gpiod_parse_flags(desc, lflags);
 -
        local_desc = gpiochip_request_own_desc(chip, hwnum, name);
        if (IS_ERR(local_desc)) {
                status = PTR_ERR(local_desc);
                return status;
        }
  
 -      status = gpiod_configure_flags(desc, name, dflags);
 +      status = gpiod_configure_flags(desc, name, lflags, dflags);
        if (status < 0) {
                pr_err("setup of hog GPIO %s (chip %s, offset %d) failed, %d\n",
                       name, chip->label, hwnum, status);