Merge tag 'gpio-v4.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 4 Sep 2015 17:07:45 +0000 (10:07 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 4 Sep 2015 17:07:45 +0000 (10:07 -0700)
Pull GPIO updates from Linus Walleij:
 "This is the bulk of GPIO changes for the v4.3 kernel cycle.

  There is quite a lot going on in the GPIO subsystem this merge window,
  so the main matter is decribed below.

  The hits in other subsystems when making the GPIO flags optional are
  all ACKed by their respective subsystem maintainers.

  Core changes:

   - Root out the wrapper devm_gpiod_get() and gpiod_get() etc versions
     of the descriptor calls that did not use the flags argument on the
     end.  This was around for too long and eventually Uwe Kleine-König
     took the time to clean it out and the last users are removed along
     with the macros in this tag.  In several cases the use of flags
     simplifies the code.  For this reason we have (ACKed) patches
     hitting in DRM, IIO, media, NFC, USB+PHY up until we hammer in the
     nail with removing the macros.

   - Add a fat document describing how much ready-made GPIO stuff we
     have i the kernel to discourage people from reinventing a square
     wheel in userspace, as so often happens.

   - Create a separate lockdep class for each instance of a GPIO IRQ
     chip instead of using one class for all chips, as the current code
     will not work with systems with several GPIO chips doing lockdep
     debugging.

   - Protect against driver unloading also when a GPIO line is only used
     as IRQ for the GPIOLIB_IRQCHIP helpers.

   - If the GPIO chip has no designated owner, assign the parent device
     driver owner as owner.

   - Consolidation of chained IRQ handler install/remove replacing all
     call sites where irq_set_handler_data() and
     irq_set_chained_handler() were done in succession with a combined
     call to irq_set_chained_handler_and_data().

     This series was created by Thomas Gleixner after the problem was
     observed by Russell King.

   - Tglx also made another series of patches switching
     __irq_set_handler_locked() for irq_set_handler_locked() which is
     way cleaner.

   - Tglx and Jiang Liu wrote a good bunch of patches to make use of
     irq_desc_get_xxx() accessors and avoid looking up irq_descs from
     IRQ numbers.  The goal is to get rid of the irq number from the
     handlers in the IRQ flow which is nice.

   - Rob Herring killed off the set_irq_flags() for all GPIO drivers.
     This was an ARM specific function that is replaced with the generic
     irq_modify_status() where special flags are actually needed.

   - When an OF node has a pin range for its GPIOs, return -EPROBE_DEFER
     if the pin controller isn't available.  Pretty logical, yet needed
     to be fixed.

   - If a driver using GPIOLIB_IRQCHIP has its own irq_*_resources call
     back, then call these instead of the defaults provided by the
     GPIOLIB.

   - Fix an undocumented ABI hole: named GPIOs were not properly
     documented.

  Driver improvements:

   - Add get_direction() support to the generic GPIO driver, it's
     strange that we didn't have that before.

   - Make it possible to have input-only GPIO chips using the generic
     GPIO driver.

   - Clean out platform data support from the Emma Mobile (EM) driver

   - Finegrained runtime PM support for the RCAR driver.

   - Support r8a7795 (R-car H3) in the RCAR driver.

   - Support interrupts on GPIOs 16 thru 31 in the DaVinci driver.

   - Some consolidation and new support in the MPC8xxx driver, we now
     support MPC5125.

   - Preempt-RT-friendly patches: the OMAP, MPC8xxx, drivers uses raw
     spinlocks making it work better with the realime patches.

   - Interrupt support for the EXTRAXFS GPIO driver.

   - Make the ETRAXFS GPIO driver support also ARTPEC-3.

   - Interrupt and wakeup support for the BRCMSTB driver, also for
     wakeup from S5 cold boot.

   - Mask MXC IRQs during suspend.

   - Improve OMAP2 GPIO set_debounce() to work according to spec.

   - The VF610 driver handles IRQs properly.

  New drivers:

   - ZTE ZX GPIO driver"

* tag 'gpio-v4.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (87 commits)
  Revert "gpio: extraxfs: fix returnvar.cocci warnings"
  gpio: tc3589x: use static container helper
  gpio: xlp: fix error return code
  gpio: vf610: handle level IRQ's properly
  gpio: max732x: Fix error handling in probe()
  gpio: omap: fix clk_prepare/unprepare usage
  gpio: omap: protect regs access in omap_gpio_irq_handler
  gpio: omap: fix omap2_set_gpio_debounce
  gpio: omap: switch to use platform_get_irq
  gpio: omap: remove wrong irq_domain_remove usage in probe
  gpiolib: add description for gpio irqchip fields in struct gpio_chip
  gpio: extraxfs: fix returnvar.cocci warnings
  gpiolib: irqchip: use different lockdep class for each gpio irqchip
  gpio/grgpio: fix deadlock in grgpio_irq_unmap()
  Documentation: gpio: consumer: describe active low property
  gpio: mxc: fix section mismatch warning
  gpio/mxc: mask gpio interrupts in suspend
  gpio: omap: Fix missing raw locks conversion
  gpio: brcmstb: support wakeup from S5 cold boot
  gpio: brcmstb: Add interrupt and wakeup source support
  ...

61 files changed:
Documentation/ABI/testing/sysfs-gpio
Documentation/devicetree/bindings/gpio/brcm,brcmstb-gpio.txt
Documentation/devicetree/bindings/gpio/gpio-etraxfs.txt
Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt [new file with mode: 0644]
Documentation/devicetree/bindings/gpio/renesas,gpio-rcar.txt
Documentation/devicetree/bindings/gpio/zx296702-gpio.txt [new file with mode: 0644]
Documentation/gpio/00-INDEX
Documentation/gpio/consumer.txt
Documentation/gpio/drivers-on-gpio.txt [new file with mode: 0644]
Documentation/gpio/sysfs.txt
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/devres.c
drivers/gpio/gpio-74xx-mmio.c
drivers/gpio/gpio-adp5588.c
drivers/gpio/gpio-altera.c
drivers/gpio/gpio-bcm-kona.c
drivers/gpio/gpio-brcmstb.c
drivers/gpio/gpio-davinci.c
drivers/gpio/gpio-dwapb.c
drivers/gpio/gpio-em.c
drivers/gpio/gpio-ep93xx.c
drivers/gpio/gpio-etraxfs.c
drivers/gpio/gpio-generic.c
drivers/gpio/gpio-grgpio.c
drivers/gpio/gpio-max732x.c
drivers/gpio/gpio-mcp23s08.c
drivers/gpio/gpio-mpc8xxx.c
drivers/gpio/gpio-msm-v2.c
drivers/gpio/gpio-mvebu.c
drivers/gpio/gpio-mxc.c
drivers/gpio/gpio-mxs.c
drivers/gpio/gpio-omap.c
drivers/gpio/gpio-pcf857x.c
drivers/gpio/gpio-pch.c
drivers/gpio/gpio-pxa.c
drivers/gpio/gpio-rcar.c
drivers/gpio/gpio-sa1100.c
drivers/gpio/gpio-sta2x11.c
drivers/gpio/gpio-tc3589x.c
drivers/gpio/gpio-tegra.c
drivers/gpio/gpio-timberdale.c
drivers/gpio/gpio-tz1090.c
drivers/gpio/gpio-vf610.c
drivers/gpio/gpio-xlp.c
drivers/gpio/gpio-zx.c [new file with mode: 0644]
drivers/gpio/gpio-zynq.c
drivers/gpio/gpiolib-of.c
drivers/gpio/gpiolib.c
drivers/gpu/drm/msm/edp/edp_ctrl.c
drivers/gpu/drm/tilcdc/tilcdc_panel.c
drivers/iio/light/stk3310.c
drivers/iio/magnetometer/bmc150_magn.c
drivers/media/i2c/adp1653.c
drivers/nfc/nxp-nci/i2c.c
drivers/phy/phy-tusb1210.c
include/linux/basic_mmio_gpio.h
include/linux/gpio/consumer.h
include/linux/gpio/driver.h
include/linux/of_gpio.h
include/linux/platform_data/gpio-em.h [deleted file]

index 80f4c94c7befdc67e9ecfec2753238ee7811bc1b..55ffa2df1c10225ee01c38a7fb41334cd949286f 100644 (file)
@@ -16,7 +16,8 @@ Description:
     /sys/class/gpio
        /export ... asks the kernel to export a GPIO to userspace
        /unexport ... to return a GPIO to the kernel
-       /gpioN ... for each exported GPIO #N
+       /gpioN ... for each exported GPIO #N OR
+       /<LINE-NAME> ... for a properly named GPIO line
            /value ... always readable, writes fail for input GPIOs
            /direction ... r/w as: in, out (default low); write: high, low
            /edge ... r/w as: none, falling, rising, both
index 435f1bcca3415df7feb7a988c2b8945e3702e693..b405b4410bfb8968756447772108702a9317c989 100644 (file)
@@ -33,6 +33,13 @@ Optional properties:
 - interrupt-parent:
     phandle of the parent interrupt controller
 
+- interrupts-extended:
+    Alternate form of specifying interrupts and parents that allows for
+    multiple parents.  This takes precedence over 'interrupts' and
+    'interrupt-parent'.  Wakeup-capable GPIO controllers often route their
+    wakeup interrupt lines through a different interrupt controller than the
+    primary interrupt line, making this property necessary.
+
 - #interrupt-cells:
     Should be <2>.  The first cell is the GPIO number, the second should specify
     flags.  The following subset of flags is supported:
@@ -47,19 +54,33 @@ Optional properties:
 - interrupt-controller:
     Marks the device node as an interrupt controller
 
-- interrupt-names:
-    The name of the IRQ resource used by this controller
+- wakeup-source:
+    GPIOs for this controller can be used as a wakeup source
 
 Example:
        upg_gio: gpio@f040a700 {
-               #gpio-cells = <0x2>;
-               #interrupt-cells = <0x2>;
+               #gpio-cells = <2>;
+               #interrupt-cells = <2>;
                compatible = "brcm,bcm7445-gpio", "brcm,brcmstb-gpio";
                gpio-controller;
                interrupt-controller;
                reg = <0xf040a700 0x80>;
-               interrupt-parent = <0xf>;
+               interrupt-parent = <&irq0_intc>;
+               interrupts = <0x6>;
+               brcm,gpio-bank-widths = <32 32 32 24>;
+       };
+
+       upg_gio_aon: gpio@f04172c0 {
+               #gpio-cells = <2>;
+               #interrupt-cells = <2>;
+               compatible = "brcm,bcm7445-gpio", "brcm,brcmstb-gpio";
+               gpio-controller;
+               interrupt-controller;
+               reg = <0xf04172c0 0x40>;
+               interrupt-parent = <&irq0_aon_intc>;
                interrupts = <0x6>;
-               interrupt-names = "upg_gio";
-               brcm,gpio-bank-widths = <0x20 0x20 0x20 0x18>;
+               interrupts-extended = <&irq0_aon_intc 0x6>,
+                       <&aon_pm_l2_intc 0x5>;
+               wakeup-source;
+               brcm,gpio-bank-widths = <18 4>;
        };
index abf4db736c6e3f64d6b685f5ea6075530f374a4b..170194af3027005a7aaa5e583c94e19ee555f4eb 100644 (file)
@@ -2,8 +2,9 @@ Axis ETRAX FS General I/O controller bindings
 
 Required properties:
 
-- compatible:
+- compatible: one of:
   - "axis,etraxfs-gio"
+  - "axis,artpec3-gio"
 - reg: Physical base address and length of the controller's registers.
 - #gpio-cells: Should be 3
   - The first cell is the gpio offset number.
diff --git a/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt b/Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt
new file mode 100644 (file)
index 0000000..805ddcd
--- /dev/null
@@ -0,0 +1,22 @@
+* Freescale MPC512x/MPC8xxx GPIO controller
+
+Required properties:
+- compatible : Should be "fsl,<soc>-gpio"
+  The following <soc>s are known to be supported:
+    mpc5121, mpc5125, mpc8349, mpc8572, mpc8610, pq3, qoriq
+- reg : Address and length of the register set for the device
+- interrupts : Should be the port interrupt shared by all 32 pins.
+- #gpio-cells : Should be two.  The first cell is the pin number and
+  the second cell is used to specify the gpio polarity:
+      0 = active high
+      1 = active low
+
+Example:
+
+gpio0: gpio@1100 {
+       compatible = "fsl,mpc5125-gpio";
+       #gpio-cells = <2>;
+       reg = <0x1100 0x080>;
+       interrupts = <78 0x8>;
+       status = "okay";
+};
index 38fb86f28ba2ce1c6a364b47c0ba38e38632a39c..f60e2f477e93ca18ab3c6ef16375659f99eb8f0b 100644 (file)
@@ -9,6 +9,7 @@ Required Properties:
     - "renesas,gpio-r8a7791": for R8A7791 (R-Car M2-W) compatible GPIO controller.
     - "renesas,gpio-r8a7793": for R8A7793 (R-Car M2-N) compatible GPIO controller.
     - "renesas,gpio-r8a7794": for R8A7794 (R-Car E2) compatible GPIO controller.
+    - "renesas,gpio-r8a7795": for R8A7795 (R-Car H3) compatible GPIO controller.
     - "renesas,gpio-rcar": for generic R-Car GPIO controller.
 
   - reg: Base address and length of each memory resource used by the GPIO
diff --git a/Documentation/devicetree/bindings/gpio/zx296702-gpio.txt b/Documentation/devicetree/bindings/gpio/zx296702-gpio.txt
new file mode 100644 (file)
index 0000000..0dab156
--- /dev/null
@@ -0,0 +1,24 @@
+ZTE ZX296702 GPIO controller
+
+Required properties:
+- compatible : "zte,zx296702-gpio"
+- #gpio-cells : Should be two. The first cell is the pin number and the
+  second cell is used to specify optional parameters:
+  - bit 0 specifies polarity (0 for normal, 1 for inverted)
+- gpio-controller : Marks the device node as a GPIO controller.
+- interrupts : Interrupt mapping for GPIO IRQ.
+- gpio-ranges : Interaction with the PINCTRL subsystem.
+
+gpio1: gpio@b008040 {
+       compatible = "zte,zx296702-gpio";
+       reg = <0xb008040 0x40>;
+       gpio-controller;
+       #gpio-cells = <2>;
+       gpio-ranges = < &pmx0 0 54 2 &pmx0 2 59 14>;
+       interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+       interrupt-parent = <&intc>;
+       interrupt-controller;
+       #interrupt-cells = <2>;
+       clock-names = "gpio_pclk";
+       clocks = <&lsp0clk ZX296702_GPIO_CLK>;
+};
index 1de43ae46ae6b2ff32cf08ebffbc8f9328733ca4..179beb234f989ea17f0dba1e5f5b6d5e4fe07235 100644 (file)
@@ -6,6 +6,9 @@ consumer.txt
        - How to obtain and use GPIOs in a driver
 driver.txt
        - How to write a GPIO driver
+drivers-on-gpio.txt:
+       - Drivers in other subsystems that can use GPIO to provide more
+         complex functionality.
 board.txt
        - How to assign GPIOs to a consumer device and a function
 sysfs.txt
index 75542b91b766c2617dafd59739d5f87a0bb419d7..a206639454ab7acdbf797c2598d818d2dc372544 100644 (file)
@@ -237,6 +237,39 @@ Note that these functions should only be used with great moderation ; a driver
 should not have to care about the physical line level.
 
 
+The active-low property
+-----------------------
+
+As a driver should not have to care about the physical line level, all of the
+gpiod_set_value_xxx() or gpiod_set_array_value_xxx() functions operate with
+the *logical* value. With this they take the active-low property into account.
+This means that they check whether the GPIO is configured to be active-low,
+and if so, they manipulate the passed value before the physical line level is
+driven.
+
+With this, all the gpiod_set_(array)_value_xxx() functions interpret the
+parameter "value" as "active" ("1") or "inactive" ("0"). The physical line
+level will be driven accordingly.
+
+As an example, if the active-low property for a dedicated GPIO is set, and the
+gpiod_set_(array)_value_xxx() passes "active" ("1"), the physical line level
+will be driven low.
+
+To summarize:
+
+Function (example)               active-low proporty  physical line
+gpiod_set_raw_value(desc, 0);        don't care           low
+gpiod_set_raw_value(desc, 1);        don't care           high
+gpiod_set_value(desc, 0);       default (active-high)     low
+gpiod_set_value(desc, 1);       default (active-high)     high
+gpiod_set_value(desc, 0);             active-low          high
+gpiod_set_value(desc, 1);             active-low          low
+
+Please note again that the set_raw/get_raw functions should be avoided as much
+as possible, especially by drivers which should not care about the actual
+physical line level and worry about the logical value instead.
+
+
 Set multiple GPIO outputs with a single function call
 -----------------------------------------------------
 The following functions set the output values of an array of GPIOs:
diff --git a/Documentation/gpio/drivers-on-gpio.txt b/Documentation/gpio/drivers-on-gpio.txt
new file mode 100644 (file)
index 0000000..f612132
--- /dev/null
@@ -0,0 +1,95 @@
+Subsystem drivers using GPIO
+============================
+
+Note that standard kernel drivers exist for common GPIO tasks and will provide
+the right in-kernel and userspace APIs/ABIs for the job, and that these
+drivers can quite easily interconnect with other kernel subsystems using
+hardware descriptions such as device tree or ACPI:
+
+- leds-gpio: drivers/leds/leds-gpio.c will handle LEDs connected to  GPIO
+  lines, giving you the LED sysfs interface
+
+- ledtrig-gpio: drivers/leds/trigger/ledtrig-gpio.c will provide a LED trigger,
+  i.e. a LED will turn on/off in response to a GPIO line going high or low
+  (and that LED may in turn use the leds-gpio as per above).
+
+- gpio-keys: drivers/input/keyboard/gpio_keys.c is used when your GPIO line
+  can generate interrupts in response to a key press. Also supports debounce.
+
+- gpio-keys-polled: drivers/input/keyboard/gpio_keys_polled.c is used when your
+  GPIO line cannot generate interrupts, so it needs to be periodically polled
+  by a timer.
+
+- gpio_mouse: drivers/input/mouse/gpio_mouse.c is used to provide a mouse with
+  up to three buttons by simply using GPIOs and no mouse port. You can cut the
+  mouse cable and connect the wires to GPIO lines or solder a mouse connector
+  to the lines for a more permanent solution of this type.
+
+- gpio-beeper: drivers/input/misc/gpio-beeper.c is used to provide a beep from
+  an external speaker connected to a GPIO line.
+
+- gpio-tilt-polled: drivers/input/misc/gpio_tilt_polled.c provides tilt
+  detection switches using GPIO, which is useful for your homebrewn pinball
+  machine if for nothing else. It can detect different tilt angles of the
+  monitored object.
+
+- extcon-gpio: drivers/extcon/extcon-gpio.c is used when you need to read an
+  external connector status, such as a headset line for an audio driver or an
+  HDMI connector. It will provide a better userspace sysfs interface than GPIO.
+
+- restart-gpio: drivers/power/gpio-restart.c is used to restart/reboot the
+  system by pulling a GPIO line and will register a restart handler so
+  userspace can issue the right system call to restart the system.
+
+- poweroff-gpio: drivers/power/gpio-poweroff.c is used to power the system down
+  by pulling a GPIO line and will register a pm_power_off() callback so that
+  userspace can issue the right system call to power down the system.
+
+- gpio-gate-clock: drivers/clk/clk-gpio-gate.c is used to control a gated clock
+  (off/on) that uses a GPIO, and integrated with the clock subsystem.
+
+- i2c-gpio: drivers/i2c/busses/i2c-gpio.c is used to drive an I2C bus
+  (two wires, SDA and SCL lines) by hammering (bitbang) two GPIO lines. It will
+  appear as any other I2C bus to the system and makes it possible to connect
+  drivers for the I2C devices on the bus like any other I2C bus driver.
+
+- spi_gpio: drivers/spi/spi-gpio.c is used to drive an SPI bus (variable number
+  of wires, atleast SCK and optionally MISO, MOSI and chip select lines) using
+  GPIO hammering (bitbang). It will appear as any other SPI bus on the system
+  and makes it possible to connect drivers for SPI devices on the bus like
+  any other SPI bus driver. For example any MMC/SD card can then be connected
+  to this SPI by using the mmc_spi host from the MMC/SD card subsystem.
+
+- w1-gpio: drivers/w1/masters/w1-gpio.c is used to drive a one-wire bus using
+  a GPIO line, integrating with the W1 subsystem and handling devices on
+  the bus like any other W1 device.
+
+- gpio-fan: drivers/hwmon/gpio-fan.c is used to control a fan for cooling the
+  system, connected to a GPIO line (and optionally a GPIO alarm line),
+  presenting all the right in-kernel and sysfs interfaces to make your system
+  not overheat.
+
+- gpio-regulator: drivers/regulator/gpio-regulator.c is used to control a
+  regulator providing a certain voltage by pulling a GPIO line, integrating
+  with the regulator subsystem and giving you all the right interfaces.
+
+- gpio-wdt: drivers/watchdog/gpio_wdt.c is used to provide a watchdog timer
+  that will periodically "ping" a hardware connected to a GPIO line by toggling
+  it from 1-to-0-to-1. If that hardware does not recieve its "ping"
+  periodically, it will reset the system.
+
+- gpio-nand: drivers/mtd/nand/gpio.c is used to connect a NAND flash chip to
+  a set of simple GPIO lines: RDY, NCE, ALE, CLE, NWP. It interacts with the
+  NAND flash MTD subsystem and provides chip access and partition parsing like
+  any other NAND driving hardware.
+
+Apart from this there are special GPIO drivers in subsystems like MMC/SD to
+read card detect and write protect GPIO lines, and in the TTY serial subsystem
+to emulate MCTRL (modem control) signals CTS/RTS by using two GPIO lines. The
+MTD NOR flash has add-ons for extra GPIO lines too, though the address bus is
+usually connected directly to the flash.
+
+Use those instead of talking directly to the GPIOs using sysfs; they integrate
+with kernel frameworks better than your userspace code could. Needless to say,
+just using the apropriate kernel drivers will simplify and speed up your
+embedded hacking in particular by providing ready-made components.
index 535b6a8a7a7cca8ffdc37a272d8e6ad434cab7da..0700b55637f565cc47a734499657054b155e22ce 100644 (file)
@@ -20,11 +20,10 @@ userspace GPIO can be used to determine system configuration data that
 standard kernels won't know about. And for some tasks, simple userspace
 GPIO drivers could be all that the system really needs.
 
-Note that standard kernel drivers exist for common "LEDs and Buttons"
-GPIO tasks:  "leds-gpio" and "gpio_keys", respectively. Use those
-instead of talking directly to the GPIOs; they integrate with kernel
-frameworks better than your userspace code could.
-
+DO NOT ABUSE SYFS TO CONTROL HARDWARE THAT HAS PROPER KERNEL DRIVERS.
+PLEASE READ THE DOCUMENT NAMED "drivers-on-gpio.txt" IN THIS DOCUMENTATION
+DIRECTORY TO AVOID REINVENTING KERNEL WHEELS IN USERSPACE. I MEAN IT.
+REALLY.
 
 Paths in Sysfs
 --------------
index 8f1fe739c985ef555d35372e292d74b31e99118a..b4fc9e4d24c6b15857e2a2cd3c1000e0473af8f9 100644 (file)
@@ -113,7 +113,6 @@ config GPIO_74XX_MMIO
 config GPIO_ALTERA
        tristate "Altera GPIO"
        depends on OF_GPIO
-       select GPIO_GENERIC
        select GPIOLIB_IRQCHIP
        help
          Say Y or M here to build support for the Altera PIO device.
@@ -131,6 +130,7 @@ config GPIO_BRCMSTB
        default y if ARCH_BRCMSTB
        depends on OF_GPIO && (ARCH_BRCMSTB || COMPILE_TEST)
        select GPIO_GENERIC
+       select GPIOLIB_IRQCHIP
        help
          Say yes here to enable GPIO support for Broadcom STB (BCM7XXX) SoCs.
 
@@ -172,6 +172,7 @@ config GPIO_ETRAXFS
        depends on CRIS || COMPILE_TEST
        depends on OF
        select GPIO_GENERIC
+       select GPIOLIB_IRQCHIP
        help
          Say yes here to support the GPIO controller on Axis ETRAX FS SoCs.
 
@@ -308,7 +309,6 @@ config GPIO_MVEBU
        def_bool y
        depends on PLAT_ORION
        depends on OF
-       select GPIO_GENERIC
        select GENERIC_IRQ_CHIP
 
 config GPIO_MXC
@@ -1005,6 +1005,12 @@ config GPIO_MC33880
          SPI driver for Freescale MC33880 high-side/low-side switch.
          This provides GPIO interface supporting inputs and outputs.
 
+config GPIO_ZX
+       bool "ZTE ZX GPIO support"
+       select GPIOLIB_IRQCHIP
+       help
+         Say yes here to support the GPIO device on ZTE ZX SoCs.
+
 endmenu
 
 menu "USB GPIO expanders"
index 2b64f6177e33cb36d9f0b965f4524f1461101576..f79a7c482a993c5cc534072398fa0ff2226798c4 100644 (file)
@@ -117,3 +117,4 @@ obj-$(CONFIG_GPIO_XLP)              += gpio-xlp.o
 obj-$(CONFIG_GPIO_XTENSA)      += gpio-xtensa.o
 obj-$(CONFIG_GPIO_ZEVIO)       += gpio-zevio.o
 obj-$(CONFIG_GPIO_ZYNQ)                += gpio-zynq.o
+obj-$(CONFIG_GPIO_ZX)          += gpio-zx.o
index 07ba82317eceb04493d9fa56e46cacfa98f1c59e..903fcf4d04a06e557bdacdeb69890d0cbf8c8a15 100644 (file)
@@ -59,13 +59,13 @@ static int devm_gpiod_match_array(struct device *dev, void *res, void *data)
  * automatically disposed on driver detach. See gpiod_get() for detailed
  * information about behavior and return values.
  */
-struct gpio_desc *__must_check __devm_gpiod_get(struct device *dev,
+struct gpio_desc *__must_check devm_gpiod_get(struct device *dev,
                                              const char *con_id,
                                              enum gpiod_flags flags)
 {
        return devm_gpiod_get_index(dev, con_id, 0, flags);
 }
-EXPORT_SYMBOL(__devm_gpiod_get);
+EXPORT_SYMBOL(devm_gpiod_get);
 
 /**
  * devm_gpiod_get_optional - Resource-managed gpiod_get_optional()
@@ -77,13 +77,13 @@ EXPORT_SYMBOL(__devm_gpiod_get);
  * are automatically disposed on driver detach. See gpiod_get_optional() for
  * detailed information about behavior and return values.
  */
-struct gpio_desc *__must_check __devm_gpiod_get_optional(struct device *dev,
+struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev,
                                                       const char *con_id,
                                                       enum gpiod_flags flags)
 {
        return devm_gpiod_get_index_optional(dev, con_id, 0, flags);
 }
-EXPORT_SYMBOL(__devm_gpiod_get_optional);
+EXPORT_SYMBOL(devm_gpiod_get_optional);
 
 /**
  * devm_gpiod_get_index - Resource-managed gpiod_get_index()
@@ -96,7 +96,7 @@ EXPORT_SYMBOL(__devm_gpiod_get_optional);
  * automatically disposed on driver detach. See gpiod_get_index() for detailed
  * information about behavior and return values.
  */
-struct gpio_desc *__must_check __devm_gpiod_get_index(struct device *dev,
+struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
                                                    const char *con_id,
                                                    unsigned int idx,
                                                    enum gpiod_flags flags)
@@ -120,7 +120,7 @@ struct gpio_desc *__must_check __devm_gpiod_get_index(struct device *dev,
 
        return desc;
 }
-EXPORT_SYMBOL(__devm_gpiod_get_index);
+EXPORT_SYMBOL(devm_gpiod_get_index);
 
 /**
  * devm_get_gpiod_from_child - get a GPIO descriptor from a device's child node
@@ -182,10 +182,10 @@ EXPORT_SYMBOL(devm_get_gpiod_from_child);
  * gpiod_get_index_optional() for detailed information about behavior and
  * return values.
  */
-struct gpio_desc *__must_check __devm_gpiod_get_index_optional(struct device *dev,
+struct gpio_desc *__must_check devm_gpiod_get_index_optional(struct device *dev,
                                                             const char *con_id,
                                                             unsigned int index,
-                                                        enum gpiod_flags flags)
+                                                            enum gpiod_flags flags)
 {
        struct gpio_desc *desc;
 
@@ -197,7 +197,7 @@ struct gpio_desc *__must_check __devm_gpiod_get_index_optional(struct device *de
 
        return desc;
 }
-EXPORT_SYMBOL(__devm_gpiod_get_index_optional);
+EXPORT_SYMBOL(devm_gpiod_get_index_optional);
 
 /**
  * devm_gpiod_get_array - Resource-managed gpiod_get_array()
index 0763655cca6ccc1ffd6b46f6cb0261a6fa31e9fc..6ed7c0fb3378eac88af03b8c125d0a7c9749f3db 100644 (file)
@@ -129,7 +129,7 @@ static int mmio_74xx_gpio_probe(struct platform_device *pdev)
        if (IS_ERR(dat))
                return PTR_ERR(dat);
 
-       priv->flags = (unsigned)of_id->data;
+       priv->flags = (uintptr_t) of_id->data;
 
        err = bgpio_init(&priv->bgc, &pdev->dev,
                         DIV_ROUND_UP(MMIO_74XX_BIT_CNT(priv->flags), 8),
index d3fe6a6776daaa8c43023daba09f3008187c471d..984186ee58a099f6c5aa16fda7666fd4e28870a4 100644 (file)
@@ -305,15 +305,7 @@ static int adp5588_irq_setup(struct adp5588_gpio *dev)
                irq_set_chip_and_handler(irq, &adp5588_irq_chip,
                                         handle_level_irq);
                irq_set_nested_thread(irq, 1);
-#ifdef CONFIG_ARM
-               /*
-                * ARM needs us to explicitly flag the IRQ as VALID,
-                * once we do so, it will also set the noprobe.
-                */
-               set_irq_flags(irq, IRQF_VALID);
-#else
-               irq_set_noprobe(irq);
-#endif
+               irq_modify_status(irq, IRQ_NOREQUEST, IRQ_NOPROBE);
        }
 
        ret = request_threaded_irq(client->irq,
index 0f3d336d6303e9c4745f8da260ae5e7df8299805..9b7e0b3db387218865004332c8313616026d7ae4 100644 (file)
@@ -338,9 +338,9 @@ static int altera_gpio_remove(struct platform_device *pdev)
 {
        struct altera_gpio_chip *altera_gc = platform_get_drvdata(pdev);
 
-       gpiochip_remove(&altera_gc->mmchip.gc);
+       of_mm_gpiochip_remove(&altera_gc->mmchip);
 
-       return -EIO;
+       return 0;
 }
 
 static const struct of_device_id altera_gpio_of_match[] = {
index 40343fa92c7b9c344f1f86a824bdb779ab8dd91e..31b90ac15204b9bf987f0cfc5e454ff90637dc78 100644 (file)
@@ -438,7 +438,7 @@ static void bcm_kona_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
        void __iomem *reg_base;
        int bit, bank_id;
        unsigned long sta;
-       struct bcm_kona_gpio_bank *bank = irq_get_handler_data(irq);
+       struct bcm_kona_gpio_bank *bank = irq_desc_get_handler_data(desc);
        struct irq_chip *chip = irq_desc_get_chip(desc);
 
        chained_irq_enter(chip, desc);
@@ -525,11 +525,7 @@ static int bcm_kona_gpio_irq_map(struct irq_domain *d, unsigned int irq,
                return ret;
        irq_set_lockdep_class(irq, &gpio_lock_class);
        irq_set_chip_and_handler(irq, &bcm_gpio_irq_chip, handle_simple_irq);
-#ifdef CONFIG_ARM
-       set_irq_flags(irq, IRQF_VALID);
-#else
        irq_set_noprobe(irq);
-#endif
 
        return 0;
 }
@@ -644,17 +640,6 @@ static int bcm_kona_gpio_probe(struct platform_device *pdev)
                dev_err(dev, "Couldn't add GPIO chip -- %d\n", ret);
                goto err_irq_domain;
        }
-       for (i = 0; i < chip->ngpio; i++) {
-               int irq = bcm_kona_gpio_to_irq(chip, i);
-               irq_set_lockdep_class(irq, &gpio_lock_class);
-               irq_set_chip_and_handler(irq, &bcm_gpio_irq_chip,
-                                        handle_simple_irq);
-#ifdef CONFIG_ARM
-               set_irq_flags(irq, IRQF_VALID);
-#else
-               irq_set_noprobe(irq);
-#endif
-       }
        for (i = 0; i < kona_gpio->num_bank; i++) {
                bank = &kona_gpio->banks[i];
                irq_set_chained_handler_and_data(bank->irq,
index 4630a8133ea6b94726a84c48486ff75eb4075bb2..9ea86d2ac05462bb832f5fe14cae4c2b9132c2c1 100644 (file)
 #include <linux/of_irq.h>
 #include <linux/module.h>
 #include <linux/basic_mmio_gpio.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/interrupt.h>
+#include <linux/reboot.h>
 
 #define GIO_BANK_SIZE           0x20
 #define GIO_ODEN(bank)          (((bank) * GIO_BANK_SIZE) + 0x00)
@@ -34,14 +38,18 @@ struct brcmstb_gpio_bank {
        struct bgpio_chip bgc;
        struct brcmstb_gpio_priv *parent_priv;
        u32 width;
+       struct irq_chip irq_chip;
 };
 
 struct brcmstb_gpio_priv {
        struct list_head bank_list;
        void __iomem *reg_base;
-       int num_banks;
        struct platform_device *pdev;
+       int parent_irq;
        int gpio_base;
+       bool can_wake;
+       int parent_wake_irq;
+       struct notifier_block reboot_notifier;
 };
 
 #define MAX_GPIO_PER_BANK           32
@@ -63,6 +71,203 @@ brcmstb_gpio_gc_to_priv(struct gpio_chip *gc)
        return bank->parent_priv;
 }
 
+static void brcmstb_gpio_set_imask(struct brcmstb_gpio_bank *bank,
+               unsigned int offset, bool enable)
+{
+       struct bgpio_chip *bgc = &bank->bgc;
+       struct brcmstb_gpio_priv *priv = bank->parent_priv;
+       u32 mask = bgc->pin2mask(bgc, offset);
+       u32 imask;
+       unsigned long flags;
+
+       spin_lock_irqsave(&bgc->lock, flags);
+       imask = bgc->read_reg(priv->reg_base + GIO_MASK(bank->id));
+       if (enable)
+               imask |= mask;
+       else
+               imask &= ~mask;
+       bgc->write_reg(priv->reg_base + GIO_MASK(bank->id), imask);
+       spin_unlock_irqrestore(&bgc->lock, flags);
+}
+
+/* -------------------- IRQ chip functions -------------------- */
+
+static void brcmstb_gpio_irq_mask(struct irq_data *d)
+{
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct brcmstb_gpio_bank *bank = brcmstb_gpio_gc_to_bank(gc);
+
+       brcmstb_gpio_set_imask(bank, d->hwirq, false);
+}
+
+static void brcmstb_gpio_irq_unmask(struct irq_data *d)
+{
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct brcmstb_gpio_bank *bank = brcmstb_gpio_gc_to_bank(gc);
+
+       brcmstb_gpio_set_imask(bank, d->hwirq, true);
+}
+
+static int brcmstb_gpio_irq_set_type(struct irq_data *d, unsigned int type)
+{
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct brcmstb_gpio_bank *bank = brcmstb_gpio_gc_to_bank(gc);
+       struct brcmstb_gpio_priv *priv = bank->parent_priv;
+       u32 mask = BIT(d->hwirq);
+       u32 edge_insensitive, iedge_insensitive;
+       u32 edge_config, iedge_config;
+       u32 level, ilevel;
+       unsigned long flags;
+
+       switch (type) {
+       case IRQ_TYPE_LEVEL_LOW:
+               level = 0;
+               edge_config = 0;
+               edge_insensitive = 0;
+               break;
+       case IRQ_TYPE_LEVEL_HIGH:
+               level = mask;
+               edge_config = 0;
+               edge_insensitive = 0;
+               break;
+       case IRQ_TYPE_EDGE_FALLING:
+               level = 0;
+               edge_config = 0;
+               edge_insensitive = 0;
+               break;
+       case IRQ_TYPE_EDGE_RISING:
+               level = 0;
+               edge_config = mask;
+               edge_insensitive = 0;
+               break;
+       case IRQ_TYPE_EDGE_BOTH:
+               level = 0;
+               edge_config = 0;  /* don't care, but want known value */
+               edge_insensitive = mask;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       spin_lock_irqsave(&bank->bgc.lock, flags);
+
+       iedge_config = bank->bgc.read_reg(priv->reg_base +
+                       GIO_EC(bank->id)) & ~mask;
+       iedge_insensitive = bank->bgc.read_reg(priv->reg_base +
+                       GIO_EI(bank->id)) & ~mask;
+       ilevel = bank->bgc.read_reg(priv->reg_base +
+                       GIO_LEVEL(bank->id)) & ~mask;
+
+       bank->bgc.write_reg(priv->reg_base + GIO_EC(bank->id),
+                       iedge_config | edge_config);
+       bank->bgc.write_reg(priv->reg_base + GIO_EI(bank->id),
+                       iedge_insensitive | edge_insensitive);
+       bank->bgc.write_reg(priv->reg_base + GIO_LEVEL(bank->id),
+                       ilevel | level);
+
+       spin_unlock_irqrestore(&bank->bgc.lock, flags);
+       return 0;
+}
+
+static int brcmstb_gpio_priv_set_wake(struct brcmstb_gpio_priv *priv,
+               unsigned int enable)
+{
+       int ret = 0;
+
+       /*
+        * Only enable wake IRQ once for however many hwirqs can wake
+        * since they all use the same wake IRQ.  Mask will be set
+        * up appropriately thanks to IRQCHIP_MASK_ON_SUSPEND flag.
+        */
+       if (enable)
+               ret = enable_irq_wake(priv->parent_wake_irq);
+       else
+               ret = disable_irq_wake(priv->parent_wake_irq);
+       if (ret)
+               dev_err(&priv->pdev->dev, "failed to %s wake-up interrupt\n",
+                               enable ? "enable" : "disable");
+       return ret;
+}
+
+static int brcmstb_gpio_irq_set_wake(struct irq_data *d, unsigned int enable)
+{
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct brcmstb_gpio_priv *priv = brcmstb_gpio_gc_to_priv(gc);
+
+       return brcmstb_gpio_priv_set_wake(priv, enable);
+}
+
+static irqreturn_t brcmstb_gpio_wake_irq_handler(int irq, void *data)
+{
+       struct brcmstb_gpio_priv *priv = data;
+
+       if (!priv || irq != priv->parent_wake_irq)
+               return IRQ_NONE;
+       pm_wakeup_event(&priv->pdev->dev, 0);
+       return IRQ_HANDLED;
+}
+
+static void brcmstb_gpio_irq_bank_handler(struct brcmstb_gpio_bank *bank)
+{
+       struct brcmstb_gpio_priv *priv = bank->parent_priv;
+       struct irq_domain *irq_domain = bank->bgc.gc.irqdomain;
+       void __iomem *reg_base = priv->reg_base;
+       unsigned long status;
+       unsigned long flags;
+
+       spin_lock_irqsave(&bank->bgc.lock, flags);
+       while ((status = bank->bgc.read_reg(reg_base + GIO_STAT(bank->id)) &
+                        bank->bgc.read_reg(reg_base + GIO_MASK(bank->id)))) {
+               int bit;
+
+               for_each_set_bit(bit, &status, 32) {
+                       u32 stat = bank->bgc.read_reg(reg_base +
+                                                     GIO_STAT(bank->id));
+                       if (bit >= bank->width)
+                               dev_warn(&priv->pdev->dev,
+                                        "IRQ for invalid GPIO (bank=%d, offset=%d)\n",
+                                        bank->id, bit);
+                       bank->bgc.write_reg(reg_base + GIO_STAT(bank->id),
+                                           stat | BIT(bit));
+                       generic_handle_irq(irq_find_mapping(irq_domain, bit));
+               }
+       }
+       spin_unlock_irqrestore(&bank->bgc.lock, flags);
+}
+
+/* Each UPG GIO block has one IRQ for all banks */
+static void brcmstb_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+       struct gpio_chip *gc = irq_desc_get_handler_data(desc);
+       struct brcmstb_gpio_priv *priv = brcmstb_gpio_gc_to_priv(gc);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+       struct list_head *pos;
+
+       /* Interrupts weren't properly cleared during probe */
+       BUG_ON(!priv || !chip);
+
+       chained_irq_enter(chip, desc);
+       list_for_each(pos, &priv->bank_list) {
+               struct brcmstb_gpio_bank *bank =
+                       list_entry(pos, struct brcmstb_gpio_bank, node);
+               brcmstb_gpio_irq_bank_handler(bank);
+       }
+       chained_irq_exit(chip, desc);
+}
+
+static int brcmstb_gpio_reboot(struct notifier_block *nb,
+               unsigned long action, void *data)
+{
+       struct brcmstb_gpio_priv *priv =
+               container_of(nb, struct brcmstb_gpio_priv, reboot_notifier);
+
+       /* Enable GPIO for S5 cold boot */
+       if (action == SYS_POWER_OFF)
+               brcmstb_gpio_priv_set_wake(priv, 1);
+
+       return NOTIFY_DONE;
+}
+
 /* Make sure that the number of banks matches up between properties */
 static int brcmstb_gpio_sanity_check_banks(struct device *dev,
                struct device_node *np, struct resource *res)
@@ -100,7 +305,13 @@ static int brcmstb_gpio_remove(struct platform_device *pdev)
                bank = list_entry(pos, struct brcmstb_gpio_bank, node);
                ret = bgpio_remove(&bank->bgc);
                if (ret)
-                       dev_err(&pdev->dev, "gpiochip_remove fail in cleanup");
+                       dev_err(&pdev->dev, "gpiochip_remove fail in cleanup\n");
+       }
+       if (priv->reboot_notifier.notifier_call) {
+               ret = unregister_reboot_notifier(&priv->reboot_notifier);
+               if (ret)
+                       dev_err(&pdev->dev,
+                               "failed to unregister reboot notifier\n");
        }
        return ret;
 }
@@ -121,7 +332,7 @@ static int brcmstb_gpio_of_xlate(struct gpio_chip *gc,
                return -EINVAL;
 
        offset = gpiospec->args[0] - (gc->base - priv->gpio_base);
-       if (offset >= gc->ngpio)
+       if (offset >= gc->ngpio || offset < 0)
                return -EINVAL;
 
        if (unlikely(offset >= bank->width)) {
@@ -136,6 +347,65 @@ static int brcmstb_gpio_of_xlate(struct gpio_chip *gc,
        return offset;
 }
 
+/* Before calling, must have bank->parent_irq set and gpiochip registered */
+static int brcmstb_gpio_irq_setup(struct platform_device *pdev,
+               struct brcmstb_gpio_bank *bank)
+{
+       struct brcmstb_gpio_priv *priv = bank->parent_priv;
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+
+       bank->irq_chip.name = dev_name(dev);
+       bank->irq_chip.irq_mask = brcmstb_gpio_irq_mask;
+       bank->irq_chip.irq_unmask = brcmstb_gpio_irq_unmask;
+       bank->irq_chip.irq_set_type = brcmstb_gpio_irq_set_type;
+
+       /* Ensures that all non-wakeup IRQs are disabled at suspend */
+       bank->irq_chip.flags = IRQCHIP_MASK_ON_SUSPEND;
+
+       if (IS_ENABLED(CONFIG_PM_SLEEP) && !priv->can_wake &&
+                       of_property_read_bool(np, "wakeup-source")) {
+               priv->parent_wake_irq = platform_get_irq(pdev, 1);
+               if (priv->parent_wake_irq < 0) {
+                       dev_warn(dev,
+                               "Couldn't get wake IRQ - GPIOs will not be able to wake from sleep");
+               } else {
+                       int err;
+
+                       /*
+                        * Set wakeup capability before requesting wakeup
+                        * interrupt, so we can process boot-time "wakeups"
+                        * (e.g., from S5 cold boot)
+                        */
+                       device_set_wakeup_capable(dev, true);
+                       device_wakeup_enable(dev);
+                       err = devm_request_irq(dev, priv->parent_wake_irq,
+                                       brcmstb_gpio_wake_irq_handler, 0,
+                                       "brcmstb-gpio-wake", priv);
+
+                       if (err < 0) {
+                               dev_err(dev, "Couldn't request wake IRQ");
+                               return err;
+                       }
+
+                       priv->reboot_notifier.notifier_call =
+                               brcmstb_gpio_reboot;
+                       register_reboot_notifier(&priv->reboot_notifier);
+                       priv->can_wake = true;
+               }
+       }
+
+       if (priv->can_wake)
+               bank->irq_chip.irq_set_wake = brcmstb_gpio_irq_set_wake;
+
+       gpiochip_irqchip_add(&bank->bgc.gc, &bank->irq_chip, 0,
+                       handle_simple_irq, IRQ_TYPE_NONE);
+       gpiochip_set_chained_irqchip(&bank->bgc.gc, &bank->irq_chip,
+                       priv->parent_irq, brcmstb_gpio_irq_handler);
+
+       return 0;
+}
+
 static int brcmstb_gpio_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
@@ -146,6 +416,7 @@ static int brcmstb_gpio_probe(struct platform_device *pdev)
        struct property *prop;
        const __be32 *p;
        u32 bank_width;
+       int num_banks = 0;
        int err;
        static int gpio_base;
 
@@ -164,6 +435,16 @@ static int brcmstb_gpio_probe(struct platform_device *pdev)
        priv->reg_base = reg_base;
        priv->pdev = pdev;
 
+       if (of_property_read_bool(np, "interrupt-controller")) {
+               priv->parent_irq = platform_get_irq(pdev, 0);
+               if (priv->parent_irq <= 0) {
+                       dev_err(dev, "Couldn't get IRQ");
+                       return -ENOENT;
+               }
+       } else {
+               priv->parent_irq = -ENOENT;
+       }
+
        if (brcmstb_gpio_sanity_check_banks(dev, np, res))
                return -EINVAL;
 
@@ -180,7 +461,7 @@ static int brcmstb_gpio_probe(struct platform_device *pdev)
                }
 
                bank->parent_priv = priv;
-               bank->id = priv->num_banks;
+               bank->id = num_banks;
                if (bank_width <= 0 || bank_width > MAX_GPIO_PER_BANK) {
                        dev_err(dev, "Invalid bank width %d\n", bank_width);
                        goto fail;
@@ -212,6 +493,12 @@ static int brcmstb_gpio_probe(struct platform_device *pdev)
                /* not all ngpio lines are valid, will use bank width later */
                gc->ngpio = MAX_GPIO_PER_BANK;
 
+               /*
+                * Mask all interrupts by default, since wakeup interrupts may
+                * be retained from S5 cold boot
+                */
+               bank->bgc.write_reg(reg_base + GIO_MASK(bank->id), 0);
+
                err = gpiochip_add(gc);
                if (err) {
                        dev_err(dev, "Could not add gpiochip for bank %d\n",
@@ -219,17 +506,24 @@ static int brcmstb_gpio_probe(struct platform_device *pdev)
                        goto fail;
                }
                gpio_base += gc->ngpio;
+
+               if (priv->parent_irq > 0) {
+                       err = brcmstb_gpio_irq_setup(pdev, bank);
+                       if (err)
+                               goto fail;
+               }
+
                dev_dbg(dev, "bank=%d, base=%d, ngpio=%d, width=%d\n", bank->id,
                        gc->base, gc->ngpio, bank->width);
 
                /* Everything looks good, so add bank to list */
                list_add(&bank->node, &priv->bank_list);
 
-               priv->num_banks++;
+               num_banks++;
        }
 
        dev_info(dev, "Registered %d banks (GPIO(s): %d-%d)\n",
-                       priv->num_banks, priv->gpio_base, gpio_base - 1);
+                       num_banks, priv->gpio_base, gpio_base - 1);
 
        return 0;
 
index c246ac3dda7ca2ba0cfa443b8e0175dc176d8da9..94b0ab7097216560c5b867663425bd1f5ad04d92 100644 (file)
@@ -65,11 +65,11 @@ static struct davinci_gpio_regs __iomem *gpio2regs(unsigned gpio)
        return ptr;
 }
 
-static inline struct davinci_gpio_regs __iomem *irq2regs(int irq)
+static inline struct davinci_gpio_regs __iomem *irq2regs(struct irq_data *d)
 {
        struct davinci_gpio_regs __iomem *g;
 
-       g = (__force struct davinci_gpio_regs __iomem *)irq_get_chip_data(irq);
+       g = (__force struct davinci_gpio_regs __iomem *)irq_data_get_irq_chip_data(d);
 
        return g;
 }
@@ -287,7 +287,7 @@ static int davinci_gpio_probe(struct platform_device *pdev)
 
 static void gpio_irq_disable(struct irq_data *d)
 {
-       struct davinci_gpio_regs __iomem *g = irq2regs(d->irq);
+       struct davinci_gpio_regs __iomem *g = irq2regs(d);
        u32 mask = (u32) irq_data_get_irq_handler_data(d);
 
        writel_relaxed(mask, &g->clr_falling);
@@ -296,7 +296,7 @@ static void gpio_irq_disable(struct irq_data *d)
 
 static void gpio_irq_enable(struct irq_data *d)
 {
-       struct davinci_gpio_regs __iomem *g = irq2regs(d->irq);
+       struct davinci_gpio_regs __iomem *g = irq2regs(d);
        u32 mask = (u32) irq_data_get_irq_handler_data(d);
        unsigned status = irqd_get_trigger_type(d);
 
@@ -327,8 +327,9 @@ static struct irq_chip gpio_irqchip = {
 };
 
 static void
-gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+gpio_irq_handler(unsigned __irq, struct irq_desc *desc)
 {
+       unsigned int irq = irq_desc_get_irq(desc);
        struct davinci_gpio_regs __iomem *g;
        u32 mask = 0xffff;
        struct davinci_gpio_controller *d;
@@ -396,7 +397,7 @@ static int gpio_irq_type_unbanked(struct irq_data *data, unsigned trigger)
        struct davinci_gpio_regs __iomem *g;
        u32 mask;
 
-       d = (struct davinci_gpio_controller *)data->handler_data;
+       d = (struct davinci_gpio_controller *)irq_data_get_irq_handler_data(data);
        g = (struct davinci_gpio_regs __iomem *)d->regs;
        mask = __gpio_mask(data->irq - d->gpio_irq);
 
@@ -422,7 +423,6 @@ davinci_gpio_irq_map(struct irq_domain *d, unsigned int irq,
        irq_set_irq_type(irq, IRQ_TYPE_NONE);
        irq_set_chip_data(irq, (__force void *)g);
        irq_set_handler_data(irq, (void *)__gpio_mask(hw));
-       set_irq_flags(irq, IRQF_VALID);
 
        return 0;
 }
@@ -545,7 +545,7 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
                chips[0].chip.to_irq = gpio_to_irq_unbanked;
                chips[0].gpio_irq = bank_irq;
                chips[0].gpio_unbanked = pdata->gpio_unbanked;
-               binten = BIT(0);
+               binten = GENMASK(pdata->gpio_unbanked / 16, 0);
 
                /* AINTC handles mask/unmask; GPIO handles triggering */
                irq = bank_irq;
index 55fa9853a7f2207984c0e99d3e1cee2c49ad788d..c5be4b9b8baf7330ba8a87c99332b23e534fe135 100644 (file)
@@ -149,7 +149,7 @@ static u32 dwapb_do_irq(struct dwapb_gpio *gpio)
 
 static void dwapb_irq_handler(u32 irq, struct irq_desc *desc)
 {
-       struct dwapb_gpio *gpio = irq_get_handler_data(irq);
+       struct dwapb_gpio *gpio = irq_desc_get_handler_data(desc);
        struct irq_chip *chip = irq_desc_get_chip(desc);
 
        dwapb_do_irq(gpio);
index fbf287307c4cc736c5032fdbf1ddbc3a77dec45d..6bca1e125e1234b8e38f069f7e5b1ef6395b3cff 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/pinctrl/consumer.h>
-#include <linux/platform_data/gpio-em.h>
 
 struct em_gio_priv {
        void __iomem *base0;
@@ -262,7 +261,6 @@ static int em_gio_irq_domain_map(struct irq_domain *h, unsigned int irq,
 
        irq_set_chip_data(irq, h->host_data);
        irq_set_chip_and_handler(irq, &p->irq_chip, handle_level_irq);
-       set_irq_flags(irq, IRQF_VALID); /* kill me now */
        return 0;
 }
 
@@ -273,13 +271,12 @@ static const struct irq_domain_ops em_gio_irq_domain_ops = {
 
 static int em_gio_probe(struct platform_device *pdev)
 {
-       struct gpio_em_config pdata_dt;
-       struct gpio_em_config *pdata = dev_get_platdata(&pdev->dev);
        struct em_gio_priv *p;
        struct resource *io[2], *irq[2];
        struct gpio_chip *gpio_chip;
        struct irq_chip *irq_chip;
        const char *name = dev_name(&pdev->dev);
+       unsigned int ngpios;
        int ret;
 
        p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
@@ -319,18 +316,10 @@ static int em_gio_probe(struct platform_device *pdev)
                goto err0;
        }
 
-       if (!pdata) {
-               memset(&pdata_dt, 0, sizeof(pdata_dt));
-               pdata = &pdata_dt;
-
-               if (of_property_read_u32(pdev->dev.of_node, "ngpios",
-                                        &pdata->number_of_pins)) {
-                       dev_err(&pdev->dev, "Missing ngpios OF property\n");
-                       ret = -EINVAL;
-                       goto err0;
-               }
-
-               pdata->gpio_base = -1;
+       if (of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios)) {
+               dev_err(&pdev->dev, "Missing ngpios OF property\n");
+               ret = -EINVAL;
+               goto err0;
        }
 
        gpio_chip = &p->gpio_chip;
@@ -345,8 +334,8 @@ static int em_gio_probe(struct platform_device *pdev)
        gpio_chip->label = name;
        gpio_chip->dev = &pdev->dev;
        gpio_chip->owner = THIS_MODULE;
-       gpio_chip->base = pdata->gpio_base;
-       gpio_chip->ngpio = pdata->number_of_pins;
+       gpio_chip->base = -1;
+       gpio_chip->ngpio = ngpios;
 
        irq_chip = &p->irq_chip;
        irq_chip->name = name;
@@ -357,9 +346,7 @@ static int em_gio_probe(struct platform_device *pdev)
        irq_chip->irq_release_resources = em_gio_irq_relres;
        irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND;
 
-       p->irq_domain = irq_domain_add_simple(pdev->dev.of_node,
-                                             pdata->number_of_pins,
-                                             pdata->irq_base,
+       p->irq_domain = irq_domain_add_simple(pdev->dev.of_node, ngpios, 0,
                                              &em_gio_irq_domain_ops, p);
        if (!p->irq_domain) {
                ret = -ENXIO;
@@ -387,12 +374,6 @@ static int em_gio_probe(struct platform_device *pdev)
                goto err1;
        }
 
-       if (pdata->pctl_name) {
-               ret = gpiochip_add_pin_range(gpio_chip, pdata->pctl_name, 0,
-                                            gpio_chip->base, gpio_chip->ngpio);
-               if (ret < 0)
-                       dev_warn(&pdev->dev, "failed to add pin range\n");
-       }
        return 0;
 
 err1:
index 45684f36ddb15d54f57db64cc64f38f0ec34acde..9d90366ea2599920f64556caa38cc225b3296b83 100644 (file)
@@ -100,13 +100,15 @@ static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc)
        }
 }
 
-static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void ep93xx_gpio_f_irq_handler(unsigned int __irq,
+                                     struct irq_desc *desc)
 {
        /*
         * map discontiguous hw irq range to continuous sw irq range:
         *
         *  IRQ_EP93XX_GPIO{0..7}MUX -> gpio_to_irq(EP93XX_GPIO_LINE_F({0..7})
         */
+       unsigned int irq = irq_desc_get_irq(desc);
        int port_f_idx = ((irq + 1) & 7) ^ 4; /* {19..22,47..50} -> {0..7} */
        int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_F(0)) + port_f_idx;
 
@@ -208,7 +210,7 @@ static int ep93xx_gpio_irq_type(struct irq_data *d, unsigned int type)
                return -EINVAL;
        }
 
-       __irq_set_handler_locked(d->irq, handler);
+       irq_set_handler_locked(d, handler);
 
        gpio_int_enabled[port] |= port_mask;
 
@@ -234,7 +236,7 @@ static void ep93xx_gpio_init_irq(void)
             gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) {
                irq_set_chip_and_handler(gpio_irq, &ep93xx_gpio_irq_chip,
                                         handle_level_irq);
-               set_irq_flags(gpio_irq, IRQF_VALID);
+               irq_clear_status_flags(gpio_irq, IRQ_NOREQUEST);
        }
 
        irq_set_chained_handler(IRQ_EP93XX_GPIO_AB,
index 28071f4a56724b94d15d5c418e8189b7cef697eb..2ffcd9fdd1f2f7d3df917aa0324a07e3f23b17c8 100644 (file)
@@ -1,8 +1,10 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/gpio.h>
+#include <linux/gpio/driver.h>
 #include <linux/of_gpio.h>
 #include <linux/io.h>
+#include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/basic_mmio_gpio.h>
 
@@ -13,6 +15,7 @@
 #define ETRAX_FS_rw_intr_mask  16
 #define ETRAX_FS_rw_ack_intr   20
 #define ETRAX_FS_r_intr                24
+#define ETRAX_FS_r_masked_intr 28
 #define ETRAX_FS_rw_pb_dout    32
 #define ETRAX_FS_r_pb_din      36
 #define ETRAX_FS_rw_pb_oe      40
 #define ETRAX_FS_r_pe_din      84
 #define ETRAX_FS_rw_pe_oe      88
 
+#define ARTPEC3_r_pa_din       0
+#define ARTPEC3_rw_pa_dout     4
+#define ARTPEC3_rw_pa_oe       8
+#define ARTPEC3_r_pb_din       44
+#define ARTPEC3_rw_pb_dout     48
+#define ARTPEC3_rw_pb_oe       52
+#define ARTPEC3_r_pc_din       88
+#define ARTPEC3_rw_pc_dout     92
+#define ARTPEC3_rw_pc_oe       96
+#define ARTPEC3_r_pd_din       116
+#define ARTPEC3_rw_intr_cfg    120
+#define ARTPEC3_rw_intr_pins   124
+#define ARTPEC3_rw_intr_mask   128
+#define ARTPEC3_rw_ack_intr    132
+#define ARTPEC3_r_masked_intr  140
+
+#define GIO_CFG_OFF            0
+#define GIO_CFG_HI             1
+#define GIO_CFG_LO             2
+#define GIO_CFG_SET            3
+#define GIO_CFG_POSEDGE                5
+#define GIO_CFG_NEGEDGE                6
+#define GIO_CFG_ANYEDGE                7
+
+struct etraxfs_gpio_info;
+
+struct etraxfs_gpio_block {
+       spinlock_t lock;
+       u32 mask;
+       u32 cfg;
+       u32 pins;
+       unsigned int group[8];
+
+       void __iomem *regs;
+       const struct etraxfs_gpio_info *info;
+};
+
+struct etraxfs_gpio_chip {
+       struct bgpio_chip bgc;
+       struct etraxfs_gpio_block *block;
+};
+
 struct etraxfs_gpio_port {
        const char *label;
        unsigned int oe;
@@ -37,6 +82,12 @@ struct etraxfs_gpio_port {
 struct etraxfs_gpio_info {
        unsigned int num_ports;
        const struct etraxfs_gpio_port *ports;
+
+       unsigned int rw_ack_intr;
+       unsigned int rw_intr_mask;
+       unsigned int rw_intr_cfg;
+       unsigned int rw_intr_pins;
+       unsigned int r_masked_intr;
 };
 
 static const struct etraxfs_gpio_port etraxfs_gpio_etraxfs_ports[] = {
@@ -80,8 +131,56 @@ static const struct etraxfs_gpio_port etraxfs_gpio_etraxfs_ports[] = {
 static const struct etraxfs_gpio_info etraxfs_gpio_etraxfs = {
        .num_ports = ARRAY_SIZE(etraxfs_gpio_etraxfs_ports),
        .ports = etraxfs_gpio_etraxfs_ports,
+       .rw_ack_intr    = ETRAX_FS_rw_ack_intr,
+       .rw_intr_mask   = ETRAX_FS_rw_intr_mask,
+       .rw_intr_cfg    = ETRAX_FS_rw_intr_cfg,
+       .r_masked_intr  = ETRAX_FS_r_masked_intr,
+};
+
+static const struct etraxfs_gpio_port etraxfs_gpio_artpec3_ports[] = {
+       {
+               .label  = "A",
+               .ngpio  = 32,
+               .oe     = ARTPEC3_rw_pa_oe,
+               .dout   = ARTPEC3_rw_pa_dout,
+               .din    = ARTPEC3_r_pa_din,
+       },
+       {
+               .label  = "B",
+               .ngpio  = 32,
+               .oe     = ARTPEC3_rw_pb_oe,
+               .dout   = ARTPEC3_rw_pb_dout,
+               .din    = ARTPEC3_r_pb_din,
+       },
+       {
+               .label  = "C",
+               .ngpio  = 16,
+               .oe     = ARTPEC3_rw_pc_oe,
+               .dout   = ARTPEC3_rw_pc_dout,
+               .din    = ARTPEC3_r_pc_din,
+       },
+       {
+               .label  = "D",
+               .ngpio  = 32,
+               .din    = ARTPEC3_r_pd_din,
+       },
+};
+
+static const struct etraxfs_gpio_info etraxfs_gpio_artpec3 = {
+       .num_ports = ARRAY_SIZE(etraxfs_gpio_artpec3_ports),
+       .ports = etraxfs_gpio_artpec3_ports,
+       .rw_ack_intr    = ARTPEC3_rw_ack_intr,
+       .rw_intr_mask   = ARTPEC3_rw_intr_mask,
+       .rw_intr_cfg    = ARTPEC3_rw_intr_cfg,
+       .r_masked_intr  = ARTPEC3_r_masked_intr,
+       .rw_intr_pins   = ARTPEC3_rw_intr_pins,
 };
 
+static unsigned int etraxfs_gpio_chip_to_port(struct gpio_chip *gc)
+{
+       return gc->label[0] - 'A';
+}
+
 static int etraxfs_gpio_of_xlate(struct gpio_chip *gc,
                               const struct of_phandle_args *gpiospec,
                               u32 *flags)
@@ -90,7 +189,7 @@ static int etraxfs_gpio_of_xlate(struct gpio_chip *gc,
         * Port numbers are A to E, and the properties are integers, so we
         * specify them as 0xA - 0xE.
         */
-       if (gc->label[0] - 'A' + 0xA != gpiospec->args[2])
+       if (etraxfs_gpio_chip_to_port(gc) + 0xA != gpiospec->args[2])
                return -EINVAL;
 
        return of_gpio_simple_xlate(gc, gpiospec, flags);
@@ -101,24 +200,174 @@ static const struct of_device_id etraxfs_gpio_of_table[] = {
                .compatible = "axis,etraxfs-gio",
                .data = &etraxfs_gpio_etraxfs,
        },
+       {
+               .compatible = "axis,artpec3-gio",
+               .data = &etraxfs_gpio_artpec3,
+       },
        {},
 };
 
+static unsigned int etraxfs_gpio_to_group_irq(unsigned int gpio)
+{
+       return gpio % 8;
+}
+
+static unsigned int etraxfs_gpio_to_group_pin(struct etraxfs_gpio_chip *chip,
+                                             unsigned int gpio)
+{
+       return 4 * etraxfs_gpio_chip_to_port(&chip->bgc.gc) + gpio / 8;
+}
+
+static void etraxfs_gpio_irq_ack(struct irq_data *d)
+{
+       struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d);
+       struct etraxfs_gpio_block *block = chip->block;
+       unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
+
+       writel(BIT(grpirq), block->regs + block->info->rw_ack_intr);
+}
+
+static void etraxfs_gpio_irq_mask(struct irq_data *d)
+{
+       struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d);
+       struct etraxfs_gpio_block *block = chip->block;
+       unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
+
+       spin_lock(&block->lock);
+       block->mask &= ~BIT(grpirq);
+       writel(block->mask, block->regs + block->info->rw_intr_mask);
+       spin_unlock(&block->lock);
+}
+
+static void etraxfs_gpio_irq_unmask(struct irq_data *d)
+{
+       struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d);
+       struct etraxfs_gpio_block *block = chip->block;
+       unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
+
+       spin_lock(&block->lock);
+       block->mask |= BIT(grpirq);
+       writel(block->mask, block->regs + block->info->rw_intr_mask);
+       spin_unlock(&block->lock);
+}
+
+static int etraxfs_gpio_irq_set_type(struct irq_data *d, u32 type)
+{
+       struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d);
+       struct etraxfs_gpio_block *block = chip->block;
+       unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
+       u32 cfg;
+
+       switch (type) {
+       case IRQ_TYPE_EDGE_RISING:
+               cfg = GIO_CFG_POSEDGE;
+               break;
+       case IRQ_TYPE_EDGE_FALLING:
+               cfg = GIO_CFG_NEGEDGE;
+               break;
+       case IRQ_TYPE_EDGE_BOTH:
+               cfg = GIO_CFG_ANYEDGE;
+               break;
+       case IRQ_TYPE_LEVEL_LOW:
+               cfg = GIO_CFG_LO;
+               break;
+       case IRQ_TYPE_LEVEL_HIGH:
+               cfg = GIO_CFG_HI;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       spin_lock(&block->lock);
+       block->cfg &= ~(0x7 << (grpirq * 3));
+       block->cfg |= (cfg << (grpirq * 3));
+       writel(block->cfg, block->regs + block->info->rw_intr_cfg);
+       spin_unlock(&block->lock);
+
+       return 0;
+}
+
+static int etraxfs_gpio_irq_request_resources(struct irq_data *d)
+{
+       struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d);
+       struct etraxfs_gpio_block *block = chip->block;
+       unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
+       int ret = -EBUSY;
+
+       spin_lock(&block->lock);
+       if (block->group[grpirq])
+               goto out;
+
+       ret = gpiochip_lock_as_irq(&chip->bgc.gc, d->hwirq);
+       if (ret)
+               goto out;
+
+       block->group[grpirq] = d->irq;
+       if (block->info->rw_intr_pins) {
+               unsigned int pin = etraxfs_gpio_to_group_pin(chip, d->hwirq);
+
+               block->pins &= ~(0xf << (grpirq * 4));
+               block->pins |= (pin << (grpirq * 4));
+
+               writel(block->pins, block->regs + block->info->rw_intr_pins);
+       }
+
+out:
+       spin_unlock(&block->lock);
+       return ret;
+}
+
+static void etraxfs_gpio_irq_release_resources(struct irq_data *d)
+{
+       struct etraxfs_gpio_chip *chip = irq_data_get_irq_chip_data(d);
+       struct etraxfs_gpio_block *block = chip->block;
+       unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq);
+
+       spin_lock(&block->lock);
+       block->group[grpirq] = 0;
+       gpiochip_unlock_as_irq(&chip->bgc.gc, d->hwirq);
+       spin_unlock(&block->lock);
+}
+
+static struct irq_chip etraxfs_gpio_irq_chip = {
+       .name           = "gpio-etraxfs",
+       .irq_ack        = etraxfs_gpio_irq_ack,
+       .irq_mask       = etraxfs_gpio_irq_mask,
+       .irq_unmask     = etraxfs_gpio_irq_unmask,
+       .irq_set_type   = etraxfs_gpio_irq_set_type,
+       .irq_request_resources = etraxfs_gpio_irq_request_resources,
+       .irq_release_resources = etraxfs_gpio_irq_release_resources,
+};
+
+static irqreturn_t etraxfs_gpio_interrupt(int irq, void *dev_id)
+{
+       struct etraxfs_gpio_block *block = dev_id;
+       unsigned long intr = readl(block->regs + block->info->r_masked_intr);
+       int bit;
+
+       for_each_set_bit(bit, &intr, 8)
+               generic_handle_irq(block->group[bit]);
+
+       return IRQ_RETVAL(intr & 0xff);
+}
+
 static int etraxfs_gpio_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        const struct etraxfs_gpio_info *info;
        const struct of_device_id *match;
-       struct bgpio_chip *chips;
-       struct resource *res;
+       struct etraxfs_gpio_block *block;
+       struct etraxfs_gpio_chip *chips;
+       struct resource *res, *irq;
+       bool allportsirq = false;
        void __iomem *regs;
        int ret;
        int i;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        regs = devm_ioremap_resource(dev, res);
-       if (!regs)
-               return -ENOMEM;
+       if (IS_ERR(regs))
+               return PTR_ERR(regs);
 
        match = of_match_node(etraxfs_gpio_of_table, dev->of_node);
        if (!match)
@@ -130,19 +379,57 @@ static int etraxfs_gpio_probe(struct platform_device *pdev)
        if (!chips)
                return -ENOMEM;
 
+       irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!irq)
+               return -EINVAL;
+
+       block = devm_kzalloc(dev, sizeof(*block), GFP_KERNEL);
+       if (!block)
+               return -ENOMEM;
+
+       spin_lock_init(&block->lock);
+
+       block->regs = regs;
+       block->info = info;
+
+       writel(0, block->regs + info->rw_intr_mask);
+       writel(0, block->regs + info->rw_intr_cfg);
+       if (info->rw_intr_pins) {
+               allportsirq = true;
+               writel(0, block->regs + info->rw_intr_pins);
+       }
+
+       ret = devm_request_irq(dev, irq->start, etraxfs_gpio_interrupt,
+                              IRQF_SHARED, dev_name(dev), block);
+       if (ret) {
+               dev_err(dev, "Unable to request irq %d\n", ret);
+               return ret;
+       }
+
        for (i = 0; i < info->num_ports; i++) {
-               struct bgpio_chip *bgc = &chips[i];
+               struct etraxfs_gpio_chip *chip = &chips[i];
+               struct bgpio_chip *bgc = &chip->bgc;
                const struct etraxfs_gpio_port *port = &info->ports[i];
+               unsigned long flags = BGPIOF_READ_OUTPUT_REG_SET;
+               void __iomem *dat = regs + port->din;
+               void __iomem *set = regs + port->dout;
+               void __iomem *dirout = regs + port->oe;
+
+               chip->block = block;
+
+               if (dirout == set) {
+                       dirout = set = NULL;
+                       flags = BGPIOF_NO_OUTPUT;
+               }
 
                ret = bgpio_init(bgc, dev, 4,
-                                regs + port->din,      /* dat */
-                                regs + port->dout,     /* set */
-                                NULL,                  /* clr */
-                                regs + port->oe,       /* dirout */
-                                NULL,                  /* dirin */
-                                BGPIOF_UNREADABLE_REG_SET);
-               if (ret)
-                       return ret;
+                                dat, set, NULL, dirout, NULL,
+                                flags);
+               if (ret) {
+                       dev_err(dev, "Unable to init port %s\n",
+                               port->label);
+                       continue;
+               }
 
                bgc->gc.ngpio = port->ngpio;
                bgc->gc.label = port->label;
@@ -152,9 +439,21 @@ static int etraxfs_gpio_probe(struct platform_device *pdev)
                bgc->gc.of_xlate = etraxfs_gpio_of_xlate;
 
                ret = gpiochip_add(&bgc->gc);
-               if (ret)
+               if (ret) {
                        dev_err(dev, "Unable to register port %s\n",
                                bgc->gc.label);
+                       continue;
+               }
+
+               if (i > 0 && !allportsirq)
+                       continue;
+
+               ret = gpiochip_irqchip_add(&bgc->gc, &etraxfs_gpio_irq_chip, 0,
+                                          handle_level_irq, IRQ_TYPE_NONE);
+               if (ret) {
+                       dev_err(dev, "Unable to add irqchip to port %s\n",
+                               bgc->gc.label);
+               }
        }
 
        return 0;
index 9bda3727fac12df7480f451057ed2513fcae2618..a3f07537fe6250864e7e829b97821555e79bf426 100644 (file)
@@ -153,6 +153,10 @@ static int bgpio_get(struct gpio_chip *gc, unsigned int gpio)
        return !!(bgc->read_reg(bgc->reg_dat) & bgc->pin2mask(bgc, gpio));
 }
 
+static void bgpio_set_none(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+}
+
 static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
 {
        struct bgpio_chip *bgc = to_bgpio_chip(gc);
@@ -279,6 +283,12 @@ static int bgpio_simple_dir_in(struct gpio_chip *gc, unsigned int gpio)
        return 0;
 }
 
+static int bgpio_dir_out_err(struct gpio_chip *gc, unsigned int gpio,
+                               int val)
+{
+       return -EINVAL;
+}
+
 static int bgpio_simple_dir_out(struct gpio_chip *gc, unsigned int gpio,
                                int val)
 {
@@ -302,6 +312,14 @@ static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
        return 0;
 }
 
+static int bgpio_get_dir(struct gpio_chip *gc, unsigned int gpio)
+{
+       struct bgpio_chip *bgc = to_bgpio_chip(gc);
+
+       return (bgc->read_reg(bgc->reg_dir) & bgc->pin2mask(bgc, gpio)) ?
+              GPIOF_DIR_OUT : GPIOF_DIR_IN;
+}
+
 static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
 {
        struct bgpio_chip *bgc = to_bgpio_chip(gc);
@@ -351,6 +369,14 @@ static int bgpio_dir_out_inv(struct gpio_chip *gc, unsigned int gpio, int val)
        return 0;
 }
 
+static int bgpio_get_dir_inv(struct gpio_chip *gc, unsigned int gpio)
+{
+       struct bgpio_chip *bgc = to_bgpio_chip(gc);
+
+       return (bgc->read_reg(bgc->reg_dir) & bgc->pin2mask(bgc, gpio)) ?
+              GPIOF_DIR_IN : GPIOF_DIR_OUT;
+}
+
 static int bgpio_setup_accessors(struct device *dev,
                                 struct bgpio_chip *bgc,
                                 bool bit_be,
@@ -444,6 +470,9 @@ static int bgpio_setup_io(struct bgpio_chip *bgc,
                bgc->reg_set = set;
                bgc->gc.set = bgpio_set_set;
                bgc->gc.set_multiple = bgpio_set_multiple_set;
+       } else if (flags & BGPIOF_NO_OUTPUT) {
+               bgc->gc.set = bgpio_set_none;
+               bgc->gc.set_multiple = NULL;
        } else {
                bgc->gc.set = bgpio_set;
                bgc->gc.set_multiple = bgpio_set_multiple;
@@ -460,7 +489,8 @@ static int bgpio_setup_io(struct bgpio_chip *bgc,
 
 static int bgpio_setup_direction(struct bgpio_chip *bgc,
                                 void __iomem *dirout,
-                                void __iomem *dirin)
+                                void __iomem *dirin,
+                                unsigned long flags)
 {
        if (dirout && dirin) {
                return -EINVAL;
@@ -468,12 +498,17 @@ static int bgpio_setup_direction(struct bgpio_chip *bgc,
                bgc->reg_dir = dirout;
                bgc->gc.direction_output = bgpio_dir_out;
                bgc->gc.direction_input = bgpio_dir_in;
+               bgc->gc.get_direction = bgpio_get_dir;
        } else if (dirin) {
                bgc->reg_dir = dirin;
                bgc->gc.direction_output = bgpio_dir_out_inv;
                bgc->gc.direction_input = bgpio_dir_in_inv;
+               bgc->gc.get_direction = bgpio_get_dir_inv;
        } else {
-               bgc->gc.direction_output = bgpio_simple_dir_out;
+               if (flags & BGPIOF_NO_OUTPUT)
+                       bgc->gc.direction_output = bgpio_dir_out_err;
+               else
+                       bgc->gc.direction_output = bgpio_simple_dir_out;
                bgc->gc.direction_input = bgpio_simple_dir_in;
        }
 
@@ -525,7 +560,7 @@ int bgpio_init(struct bgpio_chip *bgc, struct device *dev,
        if (ret)
                return ret;
 
-       ret = bgpio_setup_direction(bgc, dirout, dirin);
+       ret = bgpio_setup_direction(bgc, dirout, dirin, flags);
        if (ret)
                return ret;
 
index 0a8f7617e72e99d413439c072e8a185cecae83e4..801423fe8143d23dbcffb40cd8215fda999b5f2d 100644 (file)
@@ -104,17 +104,12 @@ static void grgpio_set_imask(struct grgpio_priv *priv, unsigned int offset,
 {
        struct bgpio_chip *bgc = &priv->bgc;
        unsigned long mask = bgc->pin2mask(bgc, offset);
-       unsigned long flags;
-
-       spin_lock_irqsave(&bgc->lock, flags);
 
        if (val)
                priv->imask |= mask;
        else
                priv->imask &= ~mask;
        bgc->write_reg(priv->regs + GRGPIO_IMASK, priv->imask);
-
-       spin_unlock_irqrestore(&bgc->lock, flags);
 }
 
 static int grgpio_to_irq(struct gpio_chip *gc, unsigned offset)
@@ -180,16 +175,26 @@ static void grgpio_irq_mask(struct irq_data *d)
 {
        struct grgpio_priv *priv = irq_data_get_irq_chip_data(d);
        int offset = d->hwirq;
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->bgc.lock, flags);
 
        grgpio_set_imask(priv, offset, 0);
+
+       spin_unlock_irqrestore(&priv->bgc.lock, flags);
 }
 
 static void grgpio_irq_unmask(struct irq_data *d)
 {
        struct grgpio_priv *priv = irq_data_get_irq_chip_data(d);
        int offset = d->hwirq;
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->bgc.lock, flags);
 
        grgpio_set_imask(priv, offset, 1);
+
+       spin_unlock_irqrestore(&priv->bgc.lock, flags);
 }
 
 static struct irq_chip grgpio_irq_chip = {
@@ -281,12 +286,7 @@ static int grgpio_irq_map(struct irq_domain *d, unsigned int irq,
        irq_set_chip_data(irq, priv);
        irq_set_chip_and_handler(irq, &grgpio_irq_chip,
                                 handle_simple_irq);
-       irq_clear_status_flags(irq, IRQ_NOREQUEST);
-#ifdef CONFIG_ARM
-       set_irq_flags(irq, IRQF_VALID);
-#else
        irq_set_noprobe(irq);
-#endif
 
        return ret;
 }
@@ -301,9 +301,6 @@ static void grgpio_irq_unmap(struct irq_domain *d, unsigned int irq)
        int ngpio = priv->bgc.gc.ngpio;
        int i;
 
-#ifdef CONFIG_ARM
-       set_irq_flags(irq, 0);
-#endif
        irq_set_chip_and_handler(irq, NULL, NULL);
        irq_set_chip_data(irq, NULL);
 
index 7d3c90e9da71a313fcbac511097f159c80b15132..8c5252c6c327764cb6fc4ae99f321e2cdf830537 100644 (file)
@@ -685,9 +685,14 @@ static int max732x_probe(struct i2c_client *client,
 
        mutex_init(&chip->lock);
 
-       max732x_readb(chip, is_group_a(chip, 0), &chip->reg_out[0]);
-       if (nr_port > 8)
-               max732x_readb(chip, is_group_a(chip, 8), &chip->reg_out[1]);
+       ret = max732x_readb(chip, is_group_a(chip, 0), &chip->reg_out[0]);
+       if (ret)
+               goto out_failed;
+       if (nr_port > 8) {
+               ret = max732x_readb(chip, is_group_a(chip, 8), &chip->reg_out[1]);
+               if (ret)
+                       goto out_failed;
+       }
 
        ret = gpiochip_add(&chip->gpio_chip);
        if (ret)
index 2fc7ff852d1676d728e150d9a27e37e02403f72f..73db7ecd7ffd9c2e44bc0a98af639884ee6fb9ad 100644 (file)
@@ -507,11 +507,7 @@ static int mcp23s08_irq_setup(struct mcp23s08 *mcp)
                irq_set_chip_data(irq, mcp);
                irq_set_chip(irq, &mcp23s08_irq_chip);
                irq_set_nested_thread(irq, true);
-#ifdef CONFIG_ARM
-               set_irq_flags(irq, IRQF_VALID);
-#else
                irq_set_noprobe(irq);
-#endif
        }
        return 0;
 }
index 20aa66f34f6e04b26c26b02346ff6b5d040d155c..8ef7a12de98375e1dcb285799a6213b93a78551f 100644 (file)
@@ -32,7 +32,7 @@
 
 struct mpc8xxx_gpio_chip {
        struct of_mm_gpio_chip mm_gc;
-       spinlock_t lock;
+       raw_spinlock_t lock;
 
        /*
         * shadowed data register to be able to clear/set output pins in
@@ -95,7 +95,7 @@ static void mpc8xxx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
        struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
        unsigned long flags;
 
-       spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
+       raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
 
        if (val)
                mpc8xxx_gc->data |= mpc8xxx_gpio2mask(gpio);
@@ -104,7 +104,7 @@ static void mpc8xxx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
 
        out_be32(mm->regs + GPIO_DAT, mpc8xxx_gc->data);
 
-       spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
+       raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
 }
 
 static void mpc8xxx_gpio_set_multiple(struct gpio_chip *gc,
@@ -115,7 +115,7 @@ static void mpc8xxx_gpio_set_multiple(struct gpio_chip *gc,
        unsigned long flags;
        int i;
 
-       spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
+       raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
 
        for (i = 0; i < gc->ngpio; i++) {
                if (*mask == 0)
@@ -130,7 +130,7 @@ static void mpc8xxx_gpio_set_multiple(struct gpio_chip *gc,
 
        out_be32(mm->regs + GPIO_DAT, mpc8xxx_gc->data);
 
-       spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
+       raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
 }
 
 static int mpc8xxx_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
@@ -139,11 +139,11 @@ static int mpc8xxx_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
        struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
        unsigned long flags;
 
-       spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
+       raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
 
        clrbits32(mm->regs + GPIO_DIR, mpc8xxx_gpio2mask(gpio));
 
-       spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
+       raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
 
        return 0;
 }
@@ -156,11 +156,11 @@ static int mpc8xxx_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val
 
        mpc8xxx_gpio_set(gc, gpio, val);
 
-       spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
+       raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
 
        setbits32(mm->regs + GPIO_DIR, mpc8xxx_gpio2mask(gpio));
 
-       spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
+       raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
 
        return 0;
 }
@@ -174,6 +174,15 @@ static int mpc5121_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val
        return mpc8xxx_gpio_dir_out(gc, gpio, val);
 }
 
+static int mpc5125_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+       /* GPIO 0..3 are input only on MPC5125 */
+       if (gpio <= 3)
+               return -EINVAL;
+
+       return mpc8xxx_gpio_dir_out(gc, gpio, val);
+}
+
 static int mpc8xxx_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
 {
        struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
@@ -206,11 +215,11 @@ static void mpc8xxx_irq_unmask(struct irq_data *d)
        struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
        unsigned long flags;
 
-       spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
+       raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
 
        setbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(irqd_to_hwirq(d)));
 
-       spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
+       raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
 }
 
 static void mpc8xxx_irq_mask(struct irq_data *d)
@@ -219,11 +228,11 @@ static void mpc8xxx_irq_mask(struct irq_data *d)
        struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
        unsigned long flags;
 
-       spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
+       raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
 
        clrbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(irqd_to_hwirq(d)));
 
-       spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
+       raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
 }
 
 static void mpc8xxx_irq_ack(struct irq_data *d)
@@ -242,17 +251,17 @@ static int mpc8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
 
        switch (flow_type) {
        case IRQ_TYPE_EDGE_FALLING:
-               spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
+               raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
                setbits32(mm->regs + GPIO_ICR,
                          mpc8xxx_gpio2mask(irqd_to_hwirq(d)));
-               spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
+               raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
                break;
 
        case IRQ_TYPE_EDGE_BOTH:
-               spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
+               raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
                clrbits32(mm->regs + GPIO_ICR,
                          mpc8xxx_gpio2mask(irqd_to_hwirq(d)));
-               spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
+               raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
                break;
 
        default:
@@ -282,22 +291,22 @@ static int mpc512x_irq_set_type(struct irq_data *d, unsigned int flow_type)
        switch (flow_type) {
        case IRQ_TYPE_EDGE_FALLING:
        case IRQ_TYPE_LEVEL_LOW:
-               spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
+               raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
                clrsetbits_be32(reg, 3 << shift, 2 << shift);
-               spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
+               raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
                break;
 
        case IRQ_TYPE_EDGE_RISING:
        case IRQ_TYPE_LEVEL_HIGH:
-               spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
+               raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
                clrsetbits_be32(reg, 3 << shift, 1 << shift);
-               spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
+               raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
                break;
 
        case IRQ_TYPE_EDGE_BOTH:
-               spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
+               raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
                clrbits32(reg, 3 << shift);
-               spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
+               raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
                break;
 
        default:
@@ -312,17 +321,13 @@ static struct irq_chip mpc8xxx_irq_chip = {
        .irq_unmask     = mpc8xxx_irq_unmask,
        .irq_mask       = mpc8xxx_irq_mask,
        .irq_ack        = mpc8xxx_irq_ack,
+       /* this might get overwritten in mpc8xxx_probe() */
        .irq_set_type   = mpc8xxx_irq_set_type,
 };
 
 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(irq, h->host_data);
        irq_set_chip_and_handler(irq, &mpc8xxx_irq_chip, handle_level_irq);
 
@@ -334,11 +339,38 @@ static const struct irq_domain_ops mpc8xxx_gpio_irq_ops = {
        .xlate  = irq_domain_xlate_twocell,
 };
 
-static struct of_device_id mpc8xxx_gpio_ids[] = {
+struct mpc8xxx_gpio_devtype {
+       int (*gpio_dir_out)(struct gpio_chip *, unsigned int, int);
+       int (*gpio_get)(struct gpio_chip *, unsigned int);
+       int (*irq_set_type)(struct irq_data *, unsigned int);
+};
+
+static const struct mpc8xxx_gpio_devtype mpc512x_gpio_devtype = {
+       .gpio_dir_out = mpc5121_gpio_dir_out,
+       .irq_set_type = mpc512x_irq_set_type,
+};
+
+static const struct mpc8xxx_gpio_devtype mpc5125_gpio_devtype = {
+       .gpio_dir_out = mpc5125_gpio_dir_out,
+       .irq_set_type = mpc512x_irq_set_type,
+};
+
+static const struct mpc8xxx_gpio_devtype mpc8572_gpio_devtype = {
+       .gpio_get = mpc8572_gpio_get,
+};
+
+static const struct mpc8xxx_gpio_devtype mpc8xxx_gpio_devtype_default = {
+       .gpio_dir_out = mpc8xxx_gpio_dir_out,
+       .gpio_get = mpc8xxx_gpio_get,
+       .irq_set_type = mpc8xxx_irq_set_type,
+};
+
+static const struct of_device_id mpc8xxx_gpio_ids[] = {
        { .compatible = "fsl,mpc8349-gpio", },
-       { .compatible = "fsl,mpc8572-gpio", },
+       { .compatible = "fsl,mpc8572-gpio", .data = &mpc8572_gpio_devtype, },
        { .compatible = "fsl,mpc8610-gpio", },
-       { .compatible = "fsl,mpc5121-gpio", .data = mpc512x_irq_set_type, },
+       { .compatible = "fsl,mpc5121-gpio", .data = &mpc512x_gpio_devtype, },
+       { .compatible = "fsl,mpc5125-gpio", .data = &mpc5125_gpio_devtype, },
        { .compatible = "fsl,pq3-gpio",     },
        { .compatible = "fsl,qoriq-gpio",   },
        {}
@@ -351,6 +383,8 @@ static int mpc8xxx_probe(struct platform_device *pdev)
        struct of_mm_gpio_chip *mm_gc;
        struct gpio_chip *gc;
        const struct of_device_id *id;
+       const struct mpc8xxx_gpio_devtype *devtype =
+               of_device_get_match_data(&pdev->dev);
        int ret;
 
        mpc8xxx_gc = devm_kzalloc(&pdev->dev, sizeof(*mpc8xxx_gc), GFP_KERNEL);
@@ -359,7 +393,7 @@ static int mpc8xxx_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, mpc8xxx_gc);
 
-       spin_lock_init(&mpc8xxx_gc->lock);
+       raw_spin_lock_init(&mpc8xxx_gc->lock);
 
        mm_gc = &mpc8xxx_gc->mm_gc;
        gc = &mm_gc->gc;
@@ -367,10 +401,18 @@ static int mpc8xxx_probe(struct platform_device *pdev)
        mm_gc->save_regs = mpc8xxx_gpio_save_regs;
        gc->ngpio = MPC8XXX_GPIO_PINS;
        gc->direction_input = mpc8xxx_gpio_dir_in;
-       gc->direction_output = of_device_is_compatible(np, "fsl,mpc5121-gpio") ?
-               mpc5121_gpio_dir_out : mpc8xxx_gpio_dir_out;
-       gc->get = of_device_is_compatible(np, "fsl,mpc8572-gpio") ?
-               mpc8572_gpio_get : mpc8xxx_gpio_get;
+
+       if (!devtype)
+               devtype = &mpc8xxx_gpio_devtype_default;
+
+       /*
+        * It's assumed that only a single type of gpio controller is available
+        * on the current machine, so overwriting global data is fine.
+        */
+       mpc8xxx_irq_chip.irq_set_type = devtype->irq_set_type;
+
+       gc->direction_output = devtype->gpio_dir_out ?: mpc8xxx_gpio_dir_out;
+       gc->get = devtype->gpio_get ?: mpc8xxx_gpio_get;
        gc->set = mpc8xxx_gpio_set;
        gc->set_multiple = mpc8xxx_gpio_set_multiple;
        gc->to_irq = mpc8xxx_gpio_to_irq;
@@ -396,8 +438,8 @@ static int mpc8xxx_probe(struct platform_device *pdev)
        out_be32(mm_gc->regs + GPIO_IER, 0xffffffff);
        out_be32(mm_gc->regs + GPIO_IMR, 0);
 
-       irq_set_handler_data(mpc8xxx_gc->irqn, mpc8xxx_gc);
-       irq_set_chained_handler(mpc8xxx_gc->irqn, mpc8xxx_gpio_irq_cascade);
+       irq_set_chained_handler_and_data(mpc8xxx_gc->irqn,
+                                        mpc8xxx_gpio_irq_cascade, mpc8xxx_gc);
 
        return 0;
 }
@@ -407,8 +449,7 @@ static int mpc8xxx_remove(struct platform_device *pdev)
        struct mpc8xxx_gpio_chip *mpc8xxx_gc = platform_get_drvdata(pdev);
 
        if (mpc8xxx_gc->irq) {
-               irq_set_handler_data(mpc8xxx_gc->irqn, NULL);
-               irq_set_chained_handler(mpc8xxx_gc->irqn, NULL);
+               irq_set_chained_handler_and_data(mpc8xxx_gc->irqn, NULL, NULL);
                irq_domain_remove(mpc8xxx_gc->irq);
        }
 
index 52ff18229fdc874a36bc2e96a45f62bf8861901a..d2012cfb5571819f6b6e4526c40625e9e94d8076 100644 (file)
@@ -187,14 +187,6 @@ static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
        return irq_create_mapping(domain, offset);
 }
 
-static inline int msm_irq_to_gpio(struct gpio_chip *chip, unsigned irq)
-{
-       struct irq_data *irq_data = irq_get_irq_data(irq);
-
-       return irq_data->hwirq;
-}
-
-
 /* For dual-edge interrupts in software, since the hardware has no
  * such support:
  *
@@ -238,7 +230,7 @@ static void msm_gpio_update_dual_edge_pos(unsigned gpio)
 
 static void msm_gpio_irq_ack(struct irq_data *d)
 {
-       int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
+       int gpio = d->hwirq;
 
        writel(BIT(INTR_STATUS), GPIO_INTR_STATUS(gpio));
        if (test_bit(gpio, msm_gpio.dual_edge_irqs))
@@ -247,8 +239,8 @@ static void msm_gpio_irq_ack(struct irq_data *d)
 
 static void msm_gpio_irq_mask(struct irq_data *d)
 {
-       int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
        unsigned long irq_flags;
+       int gpio = d->hwirq;
 
        spin_lock_irqsave(&tlmm_lock, irq_flags);
        writel(TARGET_PROC_NONE, GPIO_INTR_CFG_SU(gpio));
@@ -259,8 +251,8 @@ static void msm_gpio_irq_mask(struct irq_data *d)
 
 static void msm_gpio_irq_unmask(struct irq_data *d)
 {
-       int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
        unsigned long irq_flags;
+       int gpio = d->hwirq;
 
        spin_lock_irqsave(&tlmm_lock, irq_flags);
        __set_bit(gpio, msm_gpio.enabled_irqs);
@@ -271,8 +263,8 @@ static void msm_gpio_irq_unmask(struct irq_data *d)
 
 static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type)
 {
-       int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
        unsigned long irq_flags;
+       int gpio = d->hwirq;
        uint32_t bits;
 
        spin_lock_irqsave(&tlmm_lock, irq_flags);
@@ -281,14 +273,14 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type)
 
        if (flow_type & IRQ_TYPE_EDGE_BOTH) {
                bits |= BIT(INTR_DECT_CTL);
-               __irq_set_handler_locked(d->irq, handle_edge_irq);
+               irq_set_handler_locked(d, handle_edge_irq);
                if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
                        __set_bit(gpio, msm_gpio.dual_edge_irqs);
                else
                        __clear_bit(gpio, msm_gpio.dual_edge_irqs);
        } else {
                bits &= ~BIT(INTR_DECT_CTL);
-               __irq_set_handler_locked(d->irq, handle_level_irq);
+               irq_set_handler_locked(d, handle_level_irq);
                __clear_bit(gpio, msm_gpio.dual_edge_irqs);
        }
 
@@ -331,7 +323,7 @@ static void msm_summary_irq_handler(unsigned int irq, struct irq_desc *desc)
 
 static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
 {
-       int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
+       int gpio = d->hwirq;
 
        if (on) {
                if (bitmap_empty(msm_gpio.wake_irqs, MAX_NR_GPIO))
@@ -363,7 +355,6 @@ static int msm_gpio_irq_domain_map(struct irq_domain *d, unsigned int irq,
        irq_set_lockdep_class(irq, &msm_gpio_lock_class);
        irq_set_chip_and_handler(irq, &msm_gpio_irq_chip,
                        handle_level_irq);
-       set_irq_flags(irq, IRQF_VALID);
 
        return 0;
 }
index 1a54205860f590c97812da14d331f56a8f5e04af..b396bf3bf29464c210e5ab0add53d95a9f134eb4 100644 (file)
@@ -458,9 +458,9 @@ static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type)
        return 0;
 }
 
-static void mvebu_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void mvebu_gpio_irq_handler(unsigned int __irq, struct irq_desc *desc)
 {
-       struct mvebu_gpio_chip *mvchip = irq_get_handler_data(irq);
+       struct mvebu_gpio_chip *mvchip = irq_desc_get_handler_data(desc);
        struct irq_chip *chip = irq_desc_get_chip(desc);
        u32 cause, type;
        int i;
@@ -787,8 +787,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
 
                if (irq < 0)
                        continue;
-               irq_set_handler_data(irq, mvchip);
-               irq_set_chained_handler(irq, mvebu_gpio_irq_handler);
+               irq_set_chained_handler_and_data(irq, mvebu_gpio_irq_handler,
+                                                mvchip);
        }
 
        mvchip->irqbase = irq_alloc_descs(-1, 0, ngpios, -1);
index ec1eb1b7250ff145f5459f50b4c874154f1e23dc..b752b560126e71c0066fd66f659641155b39ad71 100644 (file)
@@ -275,8 +275,8 @@ static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat)
 static void mx3_gpio_irq_handler(u32 irq, struct irq_desc *desc)
 {
        u32 irq_stat;
-       struct mxc_gpio_port *port = irq_get_handler_data(irq);
-       struct irq_chip *chip = irq_get_chip(irq);
+       struct mxc_gpio_port *port = irq_desc_get_handler_data(desc);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
 
        chained_irq_enter(chip, desc);
 
@@ -292,7 +292,7 @@ static void mx2_gpio_irq_handler(u32 irq, struct irq_desc *desc)
 {
        u32 irq_msk, irq_stat;
        struct mxc_gpio_port *port;
-       struct irq_chip *chip = irq_get_chip(irq);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
 
        chained_irq_enter(chip, desc);
 
@@ -339,7 +339,7 @@ static int gpio_set_wake_irq(struct irq_data *d, u32 enable)
        return 0;
 }
 
-static void __init mxc_gpio_init_gc(struct mxc_gpio_port *port, int irq_base)
+static void mxc_gpio_init_gc(struct mxc_gpio_port *port, int irq_base)
 {
        struct irq_chip_generic *gc;
        struct irq_chip_type *ct;
@@ -354,6 +354,7 @@ static void __init mxc_gpio_init_gc(struct mxc_gpio_port *port, int irq_base)
        ct->chip.irq_unmask = irq_gc_mask_set_bit;
        ct->chip.irq_set_type = gpio_set_irq_type;
        ct->chip.irq_set_wake = gpio_set_wake_irq;
+       ct->chip.flags = IRQCHIP_MASK_ON_SUSPEND;
        ct->regs.ack = GPIO_ISR;
        ct->regs.mask = GPIO_IMR;
 
index 551d15d7c369cc12b94496a020ccdaabd494cb3c..b7f383eb18d91e2f82831e4813b987d74d18d77b 100644 (file)
@@ -157,7 +157,7 @@ static void mxs_flip_edge(struct mxs_gpio_port *port, u32 gpio)
 static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc)
 {
        u32 irq_stat;
-       struct mxs_gpio_port *port = irq_get_handler_data(irq);
+       struct mxs_gpio_port *port = irq_desc_get_handler_data(desc);
 
        desc->irq_data.chip->irq_ack(&desc->irq_data);
 
index 61a731ff9a076fccd0c9b2bdc15d3ca10ce5e21c..2ae0d47e955443f7f1aec2f51c522466aa54ce30 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/platform_data/gpio-omap.h>
 
 #define OFF_MODE       1
+#define OMAP4_GPIO_DEBOUNCINGTIME_MASK 0xFF
 
 static LIST_HEAD(omap_gpio_list);
 
@@ -57,7 +58,7 @@ struct gpio_bank {
        u32 saved_datain;
        u32 level_mask;
        u32 toggle_mask;
-       spinlock_t lock;
+       raw_spinlock_t lock;
        struct gpio_chip chip;
        struct clk *dbck;
        u32 mod_usage;
@@ -175,7 +176,7 @@ static inline void omap_gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set
 static inline void omap_gpio_dbck_enable(struct gpio_bank *bank)
 {
        if (bank->dbck_enable_mask && !bank->dbck_enabled) {
-               clk_prepare_enable(bank->dbck);
+               clk_enable(bank->dbck);
                bank->dbck_enabled = true;
 
                writel_relaxed(bank->dbck_enable_mask,
@@ -193,7 +194,7 @@ static inline void omap_gpio_dbck_disable(struct gpio_bank *bank)
                 */
                writel_relaxed(0, bank->base + bank->regs->debounce_en);
 
-               clk_disable_unprepare(bank->dbck);
+               clk_disable(bank->dbck);
                bank->dbck_enabled = false;
        }
 }
@@ -204,8 +205,9 @@ static inline void omap_gpio_dbck_disable(struct gpio_bank *bank)
  * @offset: the gpio number on this @bank
  * @debounce: debounce time to use
  *
- * OMAP's debounce time is in 31us steps so we need
- * to convert and round up to the closest unit.
+ * OMAP's debounce time is in 31us steps
+ *   <debounce time> = (GPIO_DEBOUNCINGTIME[7:0].DEBOUNCETIME + 1) x 31
+ * so we need to convert and round up to the closest unit.
  */
 static void omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset,
                                    unsigned debounce)
@@ -213,34 +215,33 @@ static void omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset,
        void __iomem            *reg;
        u32                     val;
        u32                     l;
+       bool                    enable = !!debounce;
 
        if (!bank->dbck_flag)
                return;
 
-       if (debounce < 32)
-               debounce = 0x01;
-       else if (debounce > 7936)
-               debounce = 0xff;
-       else
-               debounce = (debounce / 0x1f) - 1;
+       if (enable) {
+               debounce = DIV_ROUND_UP(debounce, 31) - 1;
+               debounce &= OMAP4_GPIO_DEBOUNCINGTIME_MASK;
+       }
 
        l = BIT(offset);
 
-       clk_prepare_enable(bank->dbck);
+       clk_enable(bank->dbck);
        reg = bank->base + bank->regs->debounce;
        writel_relaxed(debounce, reg);
 
        reg = bank->base + bank->regs->debounce_en;
        val = readl_relaxed(reg);
 
-       if (debounce)
+       if (enable)
                val |= l;
        else
                val &= ~l;
        bank->dbck_enable_mask = val;
 
        writel_relaxed(val, reg);
-       clk_disable_unprepare(bank->dbck);
+       clk_disable(bank->dbck);
        /*
         * Enable debounce clock per module.
         * This call is mandatory because in omap_gpio_request() when
@@ -285,7 +286,7 @@ static void omap_clear_gpio_debounce(struct gpio_bank *bank, unsigned offset)
                bank->context.debounce = 0;
                writel_relaxed(bank->context.debounce, bank->base +
                             bank->regs->debounce);
-               clk_disable_unprepare(bank->dbck);
+               clk_disable(bank->dbck);
                bank->dbck_enabled = false;
        }
 }
@@ -498,24 +499,24 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned type)
        if (!BANK_USED(bank))
                pm_runtime_get_sync(bank->dev);
 
-       spin_lock_irqsave(&bank->lock, flags);
+       raw_spin_lock_irqsave(&bank->lock, flags);
        retval = omap_set_gpio_triggering(bank, offset, type);
        if (retval) {
-               spin_unlock_irqrestore(&bank->lock, flags);
+               raw_spin_unlock_irqrestore(&bank->lock, flags);
                goto error;
        }
        omap_gpio_init_irq(bank, offset);
        if (!omap_gpio_is_input(bank, offset)) {
-               spin_unlock_irqrestore(&bank->lock, flags);
+               raw_spin_unlock_irqrestore(&bank->lock, flags);
                retval = -EINVAL;
                goto error;
        }
-       spin_unlock_irqrestore(&bank->lock, flags);
+       raw_spin_unlock_irqrestore(&bank->lock, flags);
 
        if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
-               __irq_set_handler_locked(d->irq, handle_level_irq);
+               irq_set_handler_locked(d, handle_level_irq);
        else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
-               __irq_set_handler_locked(d->irq, handle_edge_irq);
+               irq_set_handler_locked(d, handle_edge_irq);
 
        return 0;
 
@@ -636,14 +637,14 @@ static int omap_set_gpio_wakeup(struct gpio_bank *bank, unsigned offset,
                return -EINVAL;
        }
 
-       spin_lock_irqsave(&bank->lock, flags);
+       raw_spin_lock_irqsave(&bank->lock, flags);
        if (enable)
                bank->context.wake_en |= gpio_bit;
        else
                bank->context.wake_en &= ~gpio_bit;
 
        writel_relaxed(bank->context.wake_en, bank->base + bank->regs->wkup_en);
-       spin_unlock_irqrestore(&bank->lock, flags);
+       raw_spin_unlock_irqrestore(&bank->lock, flags);
 
        return 0;
 }
@@ -669,10 +670,10 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
        if (!BANK_USED(bank))
                pm_runtime_get_sync(bank->dev);
 
-       spin_lock_irqsave(&bank->lock, flags);
+       raw_spin_lock_irqsave(&bank->lock, flags);
        omap_enable_gpio_module(bank, offset);
        bank->mod_usage |= BIT(offset);
-       spin_unlock_irqrestore(&bank->lock, flags);
+       raw_spin_unlock_irqrestore(&bank->lock, flags);
 
        return 0;
 }
@@ -682,14 +683,14 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)
        struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip);
        unsigned long flags;
 
-       spin_lock_irqsave(&bank->lock, flags);
+       raw_spin_lock_irqsave(&bank->lock, flags);
        bank->mod_usage &= ~(BIT(offset));
        if (!LINE_USED(bank->irq_usage, offset)) {
                omap_set_gpio_direction(bank, offset, 1);
                omap_clear_gpio_debounce(bank, offset);
        }
        omap_disable_gpio_module(bank, offset);
-       spin_unlock_irqrestore(&bank->lock, flags);
+       raw_spin_unlock_irqrestore(&bank->lock, flags);
 
        /*
         * If this is the last gpio to be freed in the bank,
@@ -716,7 +717,8 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
        struct gpio_bank *bank;
        int unmasked = 0;
        struct irq_chip *irqchip = irq_desc_get_chip(desc);
-       struct gpio_chip *chip = irq_get_handler_data(irq);
+       struct gpio_chip *chip = irq_desc_get_handler_data(desc);
+       unsigned long lock_flags;
 
        chained_irq_enter(irqchip, desc);
 
@@ -731,6 +733,8 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
                u32 isr_saved, level_mask = 0;
                u32 enabled;
 
+               raw_spin_lock_irqsave(&bank->lock, lock_flags);
+
                enabled = omap_get_gpio_irqbank_mask(bank);
                isr_saved = isr = readl_relaxed(isr_reg) & enabled;
 
@@ -744,6 +748,8 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
                omap_clear_gpio_irqbank(bank, isr_saved & ~level_mask);
                omap_enable_gpio_irqbank(bank, isr_saved & ~level_mask);
 
+               raw_spin_unlock_irqrestore(&bank->lock, lock_flags);
+
                /* if there is only edge sensitive GPIO pin interrupts
                configured, we could unmask GPIO bank interrupt immediately */
                if (!level_mask && !unmasked) {
@@ -758,6 +764,7 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
                        bit = __ffs(isr);
                        isr &= ~(BIT(bit));
 
+                       raw_spin_lock_irqsave(&bank->lock, lock_flags);
                        /*
                         * Some chips can't respond to both rising and falling
                         * at the same time.  If this irq was requested with
@@ -768,6 +775,8 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
                        if (bank->toggle_mask & (BIT(bit)))
                                omap_toggle_gpio_edge_triggering(bank, bit);
 
+                       raw_spin_unlock_irqrestore(&bank->lock, lock_flags);
+
                        generic_handle_irq(irq_find_mapping(bank->chip.irqdomain,
                                                            bit));
                }
@@ -791,7 +800,7 @@ static unsigned int omap_gpio_irq_startup(struct irq_data *d)
        if (!BANK_USED(bank))
                pm_runtime_get_sync(bank->dev);
 
-       spin_lock_irqsave(&bank->lock, flags);
+       raw_spin_lock_irqsave(&bank->lock, flags);
 
        if (!LINE_USED(bank->mod_usage, offset))
                omap_set_gpio_direction(bank, offset, 1);
@@ -800,12 +809,12 @@ static unsigned int omap_gpio_irq_startup(struct irq_data *d)
        omap_enable_gpio_module(bank, offset);
        bank->irq_usage |= BIT(offset);
 
-       spin_unlock_irqrestore(&bank->lock, flags);
+       raw_spin_unlock_irqrestore(&bank->lock, flags);
        omap_gpio_unmask_irq(d);
 
        return 0;
 err:
-       spin_unlock_irqrestore(&bank->lock, flags);
+       raw_spin_unlock_irqrestore(&bank->lock, flags);
        if (!BANK_USED(bank))
                pm_runtime_put(bank->dev);
        return -EINVAL;
@@ -817,7 +826,7 @@ static void omap_gpio_irq_shutdown(struct irq_data *d)
        unsigned long flags;
        unsigned offset = d->hwirq;
 
-       spin_lock_irqsave(&bank->lock, flags);
+       raw_spin_lock_irqsave(&bank->lock, flags);
        bank->irq_usage &= ~(BIT(offset));
        omap_set_gpio_irqenable(bank, offset, 0);
        omap_clear_gpio_irqstatus(bank, offset);
@@ -825,7 +834,7 @@ static void omap_gpio_irq_shutdown(struct irq_data *d)
        if (!LINE_USED(bank->mod_usage, offset))
                omap_clear_gpio_debounce(bank, offset);
        omap_disable_gpio_module(bank, offset);
-       spin_unlock_irqrestore(&bank->lock, flags);
+       raw_spin_unlock_irqrestore(&bank->lock, flags);
 
        /*
         * If this is the last IRQ to be freed in the bank,
@@ -849,10 +858,10 @@ static void omap_gpio_mask_irq(struct irq_data *d)
        unsigned offset = d->hwirq;
        unsigned long flags;
 
-       spin_lock_irqsave(&bank->lock, flags);
+       raw_spin_lock_irqsave(&bank->lock, flags);
        omap_set_gpio_irqenable(bank, offset, 0);
        omap_set_gpio_triggering(bank, offset, IRQ_TYPE_NONE);
-       spin_unlock_irqrestore(&bank->lock, flags);
+       raw_spin_unlock_irqrestore(&bank->lock, flags);
 }
 
 static void omap_gpio_unmask_irq(struct irq_data *d)
@@ -862,7 +871,7 @@ static void omap_gpio_unmask_irq(struct irq_data *d)
        u32 trigger = irqd_get_trigger_type(d);
        unsigned long flags;
 
-       spin_lock_irqsave(&bank->lock, flags);
+       raw_spin_lock_irqsave(&bank->lock, flags);
        if (trigger)
                omap_set_gpio_triggering(bank, offset, trigger);
 
@@ -874,7 +883,7 @@ static void omap_gpio_unmask_irq(struct irq_data *d)
        }
 
        omap_set_gpio_irqenable(bank, offset, 1);
-       spin_unlock_irqrestore(&bank->lock, flags);
+       raw_spin_unlock_irqrestore(&bank->lock, flags);
 }
 
 /*---------------------------------------------------------------------*/
@@ -887,9 +896,9 @@ static int omap_mpuio_suspend_noirq(struct device *dev)
                                        OMAP_MPUIO_GPIO_MASKIT / bank->stride;
        unsigned long           flags;
 
-       spin_lock_irqsave(&bank->lock, flags);
+       raw_spin_lock_irqsave(&bank->lock, flags);
        writel_relaxed(0xffff & ~bank->context.wake_en, mask_reg);
-       spin_unlock_irqrestore(&bank->lock, flags);
+       raw_spin_unlock_irqrestore(&bank->lock, flags);
 
        return 0;
 }
@@ -902,9 +911,9 @@ static int omap_mpuio_resume_noirq(struct device *dev)
                                        OMAP_MPUIO_GPIO_MASKIT / bank->stride;
        unsigned long           flags;
 
-       spin_lock_irqsave(&bank->lock, flags);
+       raw_spin_lock_irqsave(&bank->lock, flags);
        writel_relaxed(bank->context.wake_en, mask_reg);
-       spin_unlock_irqrestore(&bank->lock, flags);
+       raw_spin_unlock_irqrestore(&bank->lock, flags);
 
        return 0;
 }
@@ -950,9 +959,9 @@ static int omap_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
 
        bank = container_of(chip, struct gpio_bank, chip);
        reg = bank->base + bank->regs->direction;
-       spin_lock_irqsave(&bank->lock, flags);
+       raw_spin_lock_irqsave(&bank->lock, flags);
        dir = !!(readl_relaxed(reg) & BIT(offset));
-       spin_unlock_irqrestore(&bank->lock, flags);
+       raw_spin_unlock_irqrestore(&bank->lock, flags);
        return dir;
 }
 
@@ -962,9 +971,9 @@ static int omap_gpio_input(struct gpio_chip *chip, unsigned offset)
        unsigned long flags;
 
        bank = container_of(chip, struct gpio_bank, chip);
-       spin_lock_irqsave(&bank->lock, flags);
+       raw_spin_lock_irqsave(&bank->lock, flags);
        omap_set_gpio_direction(bank, offset, 1);
-       spin_unlock_irqrestore(&bank->lock, flags);
+       raw_spin_unlock_irqrestore(&bank->lock, flags);
        return 0;
 }
 
@@ -986,10 +995,10 @@ static int omap_gpio_output(struct gpio_chip *chip, unsigned offset, int value)
        unsigned long flags;
 
        bank = container_of(chip, struct gpio_bank, chip);
-       spin_lock_irqsave(&bank->lock, flags);
+       raw_spin_lock_irqsave(&bank->lock, flags);
        bank->set_dataout(bank, offset, value);
        omap_set_gpio_direction(bank, offset, 0);
-       spin_unlock_irqrestore(&bank->lock, flags);
+       raw_spin_unlock_irqrestore(&bank->lock, flags);
        return 0;
 }
 
@@ -1001,9 +1010,9 @@ static int omap_gpio_debounce(struct gpio_chip *chip, unsigned offset,
 
        bank = container_of(chip, struct gpio_bank, chip);
 
-       spin_lock_irqsave(&bank->lock, flags);
+       raw_spin_lock_irqsave(&bank->lock, flags);
        omap2_set_gpio_debounce(bank, offset, debounce);
-       spin_unlock_irqrestore(&bank->lock, flags);
+       raw_spin_unlock_irqrestore(&bank->lock, flags);
 
        return 0;
 }
@@ -1014,9 +1023,9 @@ static void omap_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
        unsigned long flags;
 
        bank = container_of(chip, struct gpio_bank, chip);
-       spin_lock_irqsave(&bank->lock, flags);
+       raw_spin_lock_irqsave(&bank->lock, flags);
        bank->set_dataout(bank, offset, value);
-       spin_unlock_irqrestore(&bank->lock, flags);
+       raw_spin_unlock_irqrestore(&bank->lock, flags);
 }
 
 /*---------------------------------------------------------------------*/
@@ -1061,10 +1070,6 @@ static void omap_gpio_mod_init(struct gpio_bank *bank)
         /* Initialize interface clk ungated, module enabled */
        if (bank->regs->ctrl)
                writel_relaxed(0, base + bank->regs->ctrl);
-
-       bank->dbck = clk_get(bank->dev, "dbclk");
-       if (IS_ERR(bank->dbck))
-               dev_err(bank->dev, "Could not get gpio dbck\n");
 }
 
 static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
@@ -1178,13 +1183,16 @@ static int omap_gpio_probe(struct platform_device *pdev)
        irqc->irq_set_wake = omap_gpio_wake_enable,
        irqc->name = dev_name(&pdev->dev);
 
-       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (unlikely(!res)) {
-               dev_err(dev, "Invalid IRQ resource\n");
-               return -ENODEV;
+       bank->irq = platform_get_irq(pdev, 0);
+       if (bank->irq <= 0) {
+               if (!bank->irq)
+                       bank->irq = -ENXIO;
+               if (bank->irq != -EPROBE_DEFER)
+                       dev_err(dev,
+                               "can't get irq resource ret=%d\n", bank->irq);
+               return bank->irq;
        }
 
-       bank->irq = res->start;
        bank->dev = dev;
        bank->chip.dev = dev;
        bank->chip.owner = THIS_MODULE;
@@ -1213,16 +1221,26 @@ static int omap_gpio_probe(struct platform_device *pdev)
        else
                bank->set_dataout = omap_set_gpio_dataout_mask;
 
-       spin_lock_init(&bank->lock);
+       raw_spin_lock_init(&bank->lock);
 
        /* Static mapping, never released */
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        bank->base = devm_ioremap_resource(dev, res);
        if (IS_ERR(bank->base)) {
-               irq_domain_remove(bank->chip.irqdomain);
                return PTR_ERR(bank->base);
        }
 
+       if (bank->dbck_flag) {
+               bank->dbck = devm_clk_get(bank->dev, "dbclk");
+               if (IS_ERR(bank->dbck)) {
+                       dev_err(bank->dev,
+                               "Could not get gpio dbck. Disable debounce\n");
+                       bank->dbck_flag = false;
+               } else {
+                       clk_prepare(bank->dbck);
+               }
+       }
+
        platform_set_drvdata(pdev, bank);
 
        pm_runtime_enable(bank->dev);
@@ -1254,6 +1272,8 @@ static int omap_gpio_remove(struct platform_device *pdev)
        list_del(&bank->node);
        gpiochip_remove(&bank->chip);
        pm_runtime_disable(bank->dev);
+       if (bank->dbck_flag)
+               clk_unprepare(bank->dbck);
 
        return 0;
 }
@@ -1271,7 +1291,7 @@ static int omap_gpio_runtime_suspend(struct device *dev)
        unsigned long flags;
        u32 wake_low, wake_hi;
 
-       spin_lock_irqsave(&bank->lock, flags);
+       raw_spin_lock_irqsave(&bank->lock, flags);
 
        /*
         * Only edges can generate a wakeup event to the PRCM.
@@ -1324,7 +1344,7 @@ update_gpio_context_count:
                                bank->get_context_loss_count(bank->dev);
 
        omap_gpio_dbck_disable(bank);
-       spin_unlock_irqrestore(&bank->lock, flags);
+       raw_spin_unlock_irqrestore(&bank->lock, flags);
 
        return 0;
 }
@@ -1339,7 +1359,7 @@ static int omap_gpio_runtime_resume(struct device *dev)
        unsigned long flags;
        int c;
 
-       spin_lock_irqsave(&bank->lock, flags);
+       raw_spin_lock_irqsave(&bank->lock, flags);
 
        /*
         * On the first resume during the probe, the context has not
@@ -1375,14 +1395,14 @@ static int omap_gpio_runtime_resume(struct device *dev)
                        if (c != bank->context_loss_count) {
                                omap_gpio_restore_context(bank);
                        } else {
-                               spin_unlock_irqrestore(&bank->lock, flags);
+                               raw_spin_unlock_irqrestore(&bank->lock, flags);
                                return 0;
                        }
                }
        }
 
        if (!bank->workaround_enabled) {
-               spin_unlock_irqrestore(&bank->lock, flags);
+               raw_spin_unlock_irqrestore(&bank->lock, flags);
                return 0;
        }
 
@@ -1437,7 +1457,7 @@ static int omap_gpio_runtime_resume(struct device *dev)
        }
 
        bank->workaround_enabled = false;
-       spin_unlock_irqrestore(&bank->lock, flags);
+       raw_spin_unlock_irqrestore(&bank->lock, flags);
 
        return 0;
 }
index 404f3c61ef9b19f43243d61eef656e8d81a899c9..1d4d9bc8b69db5cbacd1280fb5ff8c58fe25eea0 100644 (file)
@@ -88,7 +88,6 @@ struct pcf857x {
        struct gpio_chip        chip;
        struct i2c_client       *client;
        struct mutex            lock;           /* protect 'out' */
-       spinlock_t              slock;          /* protect irq demux */
        unsigned                out;            /* software latch */
        unsigned                status;         /* current status */
        unsigned int            irq_parent;
@@ -185,23 +184,21 @@ static void pcf857x_set(struct gpio_chip *chip, unsigned offset, int value)
 static irqreturn_t pcf857x_irq(int irq, void *data)
 {
        struct pcf857x  *gpio = data;
-       unsigned long change, i, status, flags;
+       unsigned long change, i, status;
 
        status = gpio->read(gpio->client);
 
-       spin_lock_irqsave(&gpio->slock, flags);
-
        /*
         * call the interrupt handler iff gpio is used as
         * interrupt source, just to avoid bad irqs
         */
-
+       mutex_lock(&gpio->lock);
        change = (gpio->status ^ status) & gpio->irq_enabled;
-       for_each_set_bit(i, &change, gpio->chip.ngpio)
-               handle_nested_irq(irq_find_mapping(gpio->chip.irqdomain, i));
        gpio->status = status;
+       mutex_unlock(&gpio->lock);
 
-       spin_unlock_irqrestore(&gpio->slock, flags);
+       for_each_set_bit(i, &change, gpio->chip.ngpio)
+               handle_nested_irq(irq_find_mapping(gpio->chip.irqdomain, i));
 
        return IRQ_HANDLED;
 }
@@ -293,7 +290,6 @@ static int pcf857x_probe(struct i2c_client *client,
                return -ENOMEM;
 
        mutex_init(&gpio->lock);
-       spin_lock_init(&gpio->slock);
 
        gpio->chip.base                 = pdata ? pdata->gpio_base : -1;
        gpio->chip.can_sleep            = true;
index 2d9a950ca2d46d1b65f26e7c85ac6861b1892ae0..34ed176df15a9be7ac009bfbc7e6028bb681ae15 100644 (file)
@@ -281,9 +281,9 @@ static int pch_irq_type(struct irq_data *d, unsigned int type)
 
        /* And the handler */
        if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
-               __irq_set_handler_locked(d->irq, handle_level_irq);
+               irq_set_handler_locked(d, handle_level_irq);
        else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
-               __irq_set_handler_locked(d->irq, handle_edge_irq);
+               irq_set_handler_locked(d, handle_edge_irq);
 
 unlock:
        spin_unlock_irqrestore(&chip->spinlock, flags);
index cdbbcf0faf9da4a263504f7a7b0cc3d8aabc8cdb..55a11de3d5b741f1038fd4b50fb9300cc8be7813 100644 (file)
@@ -524,7 +524,7 @@ static int pxa_irq_domain_map(struct irq_domain *d, unsigned int irq,
 {
        irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
                                 handle_edge_irq);
-       set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+       irq_set_noprobe(irq);
        return 0;
 }
 
@@ -643,20 +643,20 @@ static int pxa_gpio_probe(struct platform_device *pdev)
                        irq = gpio_to_irq(0);
                        irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
                                                 handle_edge_irq);
-                       set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+                       irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
                }
                if (irq1 > 0) {
                        irq = gpio_to_irq(1);
                        irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
                                                 handle_edge_irq);
-                       set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+                       irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
                }
 
                for (irq  = gpio_to_irq(gpio_offset);
                        irq <= gpio_to_irq(pxa_last_gpio); irq++) {
                        irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
                                                 handle_edge_irq);
-                       set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+                       irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
                }
        }
 
index 1e14a6c74ed139413564417339fc8e4399c55341..2a81224446145d62dcbd5befa1ad9e4f82ce66a7 100644 (file)
@@ -251,17 +251,32 @@ static void gpio_rcar_config_general_input_output_mode(struct gpio_chip *chip,
 
 static int gpio_rcar_request(struct gpio_chip *chip, unsigned offset)
 {
-       return pinctrl_request_gpio(chip->base + offset);
+       struct gpio_rcar_priv *p = gpio_to_priv(chip);
+       int error;
+
+       error = pm_runtime_get_sync(&p->pdev->dev);
+       if (error < 0)
+               return error;
+
+       error = pinctrl_request_gpio(chip->base + offset);
+       if (error)
+               pm_runtime_put(&p->pdev->dev);
+
+       return error;
 }
 
 static void gpio_rcar_free(struct gpio_chip *chip, unsigned offset)
 {
+       struct gpio_rcar_priv *p = gpio_to_priv(chip);
+
        pinctrl_free_gpio(chip->base + offset);
 
        /* Set the GPIO as an input to ensure that the next GPIO request won't
         * drive the GPIO pin as an output.
         */
        gpio_rcar_config_general_input_output_mode(chip, offset, false);
+
+       pm_runtime_put(&p->pdev->dev);
 }
 
 static int gpio_rcar_direction_input(struct gpio_chip *chip, unsigned offset)
@@ -326,6 +341,10 @@ static const struct of_device_id gpio_rcar_of_table[] = {
        }, {
                .compatible = "renesas,gpio-r8a7794",
                .data = &gpio_rcar_info_gen2,
+       }, {
+               .compatible = "renesas,gpio-r8a7795",
+               /* Gen3 GPIO is identical to Gen2. */
+               .data = &gpio_rcar_info_gen2,
        }, {
                .compatible = "renesas,gpio-rcar",
                .data = &gpio_rcar_info_gen1,
@@ -405,7 +424,6 @@ static int gpio_rcar_probe(struct platform_device *pdev)
        }
 
        pm_runtime_enable(dev);
-       pm_runtime_get_sync(dev);
 
        io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
@@ -487,7 +505,6 @@ static int gpio_rcar_probe(struct platform_device *pdev)
 err1:
        gpiochip_remove(gpio_chip);
 err0:
-       pm_runtime_put(dev);
        pm_runtime_disable(dev);
        return ret;
 }
@@ -498,7 +515,6 @@ static int gpio_rcar_remove(struct platform_device *pdev)
 
        gpiochip_remove(&p->gpio_chip);
 
-       pm_runtime_put(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
        return 0;
 }
index 3fa22dade243e14ec635493743a748263c2ae44c..67bd2f5d89e8f3d67efab99b8f3799351c263987 100644 (file)
@@ -155,7 +155,7 @@ static int sa1100_gpio_irqdomain_map(struct irq_domain *d,
 {
        irq_set_chip_and_handler(irq, &sa1100_gpio_irq_chip,
                                 handle_edge_irq);
-       set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+       irq_set_noprobe(irq);
 
        return 0;
 }
@@ -173,9 +173,9 @@ static struct irq_domain *sa1100_gpio_irqdomain;
  * and call the handler.
  */
 static void
-sa1100_gpio_handler(unsigned int irq, struct irq_desc *desc)
+sa1100_gpio_handler(unsigned int __irq, struct irq_desc *desc)
 {
-       unsigned int mask;
+       unsigned int irq, mask;
 
        mask = GEDR;
        do {
index 18579ac65b2b04fa09df3da436aff848e98e50e9..55e47828ddfcb66f2a4ad00ae049c8576ed03698 100644 (file)
@@ -346,7 +346,7 @@ static void gsta_alloc_irq_chip(struct gsta_gpio *chip)
                        i = chip->irq_base + j;
                        irq_set_chip_and_handler(i, &ct->chip, ct->handler);
                        irq_set_chip_data(i, gc);
-                       irq_modify_status(i, IRQ_NOREQUEST | IRQ_NOPROBE, 0);
+                       irq_clear_status_flags(i, IRQ_NOREQUEST | IRQ_NOPROBE);
                }
                gc->irq_cnt = i - gc->irq_base;
        }
index 31b244cffabb2ff9f862e479061e8bcd7e140d7e..d1d585ddb9ab786b2813993de448a3f3b50ab0c5 100644 (file)
@@ -102,7 +102,7 @@ static struct gpio_chip template_chip = {
 static int tc3589x_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 {
        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-       struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);
+       struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(gc);
        int offset = d->hwirq;
        int regoffset = offset / 8;
        int mask = 1 << (offset % 8);
@@ -130,7 +130,7 @@ static int tc3589x_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 static void tc3589x_gpio_irq_lock(struct irq_data *d)
 {
        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-       struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);
+       struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(gc);
 
        mutex_lock(&tc3589x_gpio->irq_lock);
 }
@@ -138,7 +138,7 @@ static void tc3589x_gpio_irq_lock(struct irq_data *d)
 static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d)
 {
        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-       struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);
+       struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(gc);
        struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
        static const u8 regmap[] = {
                [REG_IBE]       = TC3589x_GPIOIBE0,
@@ -167,7 +167,7 @@ static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d)
 static void tc3589x_gpio_irq_mask(struct irq_data *d)
 {
        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-       struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);
+       struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(gc);
        int offset = d->hwirq;
        int regoffset = offset / 8;
        int mask = 1 << (offset % 8);
@@ -178,7 +178,7 @@ static void tc3589x_gpio_irq_mask(struct irq_data *d)
 static void tc3589x_gpio_irq_unmask(struct irq_data *d)
 {
        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-       struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);
+       struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(gc);
        int offset = d->hwirq;
        int regoffset = offset / 8;
        int mask = 1 << (offset % 8);
index 9b25c90f725c21138f955dbc1a4745749114a9b4..9b14aafb576da8dc664cd75679379fe04ff4ace7 100644 (file)
@@ -252,9 +252,9 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)
        tegra_gpio_enable(gpio);
 
        if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
-               __irq_set_handler_locked(d->irq, handle_level_irq);
+               irq_set_handler_locked(d, handle_level_irq);
        else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
-               __irq_set_handler_locked(d->irq, handle_edge_irq);
+               irq_set_handler_locked(d, handle_edge_irq);
 
        return 0;
 }
@@ -268,16 +268,14 @@ static void tegra_gpio_irq_shutdown(struct irq_data *d)
 
 static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
-       struct tegra_gpio_bank *bank;
        int port;
        int pin;
        int unmasked = 0;
        struct irq_chip *chip = irq_desc_get_chip(desc);
+       struct tegra_gpio_bank *bank = irq_desc_get_handler_data(desc);
 
        chained_irq_enter(chip, desc);
 
-       bank = irq_get_handler_data(irq);
-
        for (port = 0; port < 4; port++) {
                int gpio = tegra_gpio_compose(bank->bank, port, 0);
                unsigned long sta = tegra_gpio_readl(GPIO_INT_STA(gpio)) &
@@ -509,7 +507,6 @@ static int tegra_gpio_probe(struct platform_device *pdev)
                irq_set_chip_data(irq, bank);
                irq_set_chip_and_handler(irq, &tegra_gpio_irq_chip,
                                         handle_simple_irq);
-               set_irq_flags(irq, IRQF_VALID);
        }
 
        for (i = 0; i < tegra_gpio_bank_count; i++) {
index e8f97e03c9bb6a61478a2c99f693f067c5b49ce7..5a492054589fa472c41f4f7ae7fc8b33b38843ce 100644 (file)
@@ -194,11 +194,12 @@ out:
 
 static void timbgpio_irq(unsigned int irq, struct irq_desc *desc)
 {
-       struct timbgpio *tgpio = irq_get_handler_data(irq);
+       struct timbgpio *tgpio = irq_desc_get_handler_data(desc);
+       struct irq_data *data = irq_desc_get_irq_data(desc);
        unsigned long ipr;
        int offset;
 
-       desc->irq_data.chip->irq_ack(irq_get_irq_data(irq));
+       data->chip->irq_ack(data);
        ipr = ioread32(tgpio->membase + TGPIO_IPR);
        iowrite32(ipr, tgpio->membase + TGPIO_ICR);
 
@@ -294,13 +295,10 @@ static int timbgpio_probe(struct platform_device *pdev)
                irq_set_chip_and_handler(tgpio->irq_base + i,
                        &timbgpio_irqchip, handle_simple_irq);
                irq_set_chip_data(tgpio->irq_base + i, tgpio);
-#ifdef CONFIG_ARM
-               set_irq_flags(tgpio->irq_base + i, IRQF_VALID | IRQF_PROBE);
-#endif
+               irq_clear_status_flags(tgpio->irq_base + i, IRQ_NOREQUEST | IRQ_NOPROBE);
        }
 
-       irq_set_handler_data(irq, tgpio);
-       irq_set_chained_handler(irq, timbgpio_irq);
+       irq_set_chained_handler_and_data(irq, timbgpio_irq, tgpio);
 
        return 0;
 }
index 445660adc898918d8c32cb9b09816762157dfc2c..bbac92ae4c328ab96eef76785e4189e7b3de08a5 100644 (file)
@@ -510,8 +510,8 @@ static int tz1090_gpio_bank_probe(struct tz1090_gpio_bank_info *info)
        gc->chip_types[1].chip.flags            = IRQCHIP_MASK_ON_SUSPEND;
 
        /* Setup chained handler for this GPIO bank */
-       irq_set_handler_data(bank->irq, bank);
-       irq_set_chained_handler(bank->irq, tz1090_gpio_irq_handler);
+       irq_set_chained_handler_and_data(bank->irq, tz1090_gpio_irq_handler,
+                                        bank);
 
        return 0;
 }
index 7bd9f209ffa81a1b00141d4345f4fe3becc7f317..3d5714d4f405dd50731da6a11d8f24398d7c36d8 100644 (file)
@@ -60,6 +60,8 @@ struct vf610_gpio_port {
 #define PORT_INT_EITHER_EDGE   0xb
 #define PORT_INT_LOGIC_ONE     0xc
 
+static struct irq_chip vf610_gpio_irq_chip;
+
 static const struct of_device_id vf610_gpio_dt_ids[] = {
        { .compatible = "fsl,vf610-gpio" },
        { /* sentinel */ }
@@ -120,7 +122,7 @@ static int vf610_gpio_direction_output(struct gpio_chip *chip, unsigned gpio,
 
 static void vf610_gpio_irq_handler(u32 irq, struct irq_desc *desc)
 {
-       struct vf610_gpio_port *port = irq_get_handler_data(irq);
+       struct vf610_gpio_port *port = irq_desc_get_handler_data(desc);
        struct irq_chip *chip = irq_desc_get_chip(desc);
        int pin;
        unsigned long irq_isfr;
@@ -173,6 +175,11 @@ static int vf610_gpio_irq_set_type(struct irq_data *d, u32 type)
 
        port->irqc[d->hwirq] = irqc;
 
+       if (type & IRQ_TYPE_LEVEL_MASK)
+               __irq_set_handler_locked(d->irq, handle_level_irq);
+       else
+               __irq_set_handler_locked(d->irq, handle_edge_irq);
+
        return 0;
 }
 
@@ -263,7 +270,7 @@ static int vf610_gpio_probe(struct platform_device *pdev)
        vf610_gpio_writel(~0, port->base + PORT_ISFR);
 
        ret = gpiochip_irqchip_add(gc, &vf610_gpio_irq_chip, 0,
-                                  handle_simple_irq, IRQ_TYPE_NONE);
+                                  handle_edge_irq, IRQ_TYPE_NONE);
        if (ret) {
                dev_err(dev, "failed to add irqchip\n");
                gpiochip_remove(gc);
index 9bdab7203d6515b84717170bbf3edb1c8d9b70f9..e02499a15e72263846e813ee1f990916113923b3 100644 (file)
@@ -387,7 +387,7 @@ static int xlp_gpio_probe(struct platform_device *pdev)
        irq_base = irq_alloc_descs(-1, XLP_GPIO_IRQ_BASE, gc->ngpio, 0);
        if (irq_base < 0) {
                dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n");
-               return err;
+               return -ENODEV;
        }
 
        err = gpiochip_add(gc);
diff --git a/drivers/gpio/gpio-zx.c b/drivers/gpio/gpio-zx.c
new file mode 100644 (file)
index 0000000..12ee196
--- /dev/null
@@ -0,0 +1,324 @@
+/*
+ * Copyright (C) 2015 Linaro Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/gpio/driver.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#define ZX_GPIO_DIR    0x00
+#define ZX_GPIO_IVE    0x04
+#define ZX_GPIO_IV     0x08
+#define ZX_GPIO_IEP    0x0C
+#define ZX_GPIO_IEN    0x10
+#define ZX_GPIO_DI     0x14
+#define ZX_GPIO_DO1    0x18
+#define ZX_GPIO_DO0    0x1C
+#define ZX_GPIO_DO     0x20
+
+#define ZX_GPIO_IM     0x28
+#define ZX_GPIO_IE     0x2C
+
+#define ZX_GPIO_MIS    0x30
+#define ZX_GPIO_IC     0x34
+
+#define ZX_GPIO_NR     16
+
+struct zx_gpio {
+       spinlock_t              lock;
+
+       void __iomem            *base;
+       struct gpio_chip        gc;
+       bool                    uses_pinctrl;
+};
+
+static inline struct zx_gpio *to_zx(struct gpio_chip *gc)
+{
+       return container_of(gc, struct zx_gpio, gc);
+}
+
+static int zx_gpio_request(struct gpio_chip *gc, unsigned offset)
+{
+       struct zx_gpio *chip = to_zx(gc);
+       int gpio = gc->base + offset;
+
+       if (chip->uses_pinctrl)
+               return pinctrl_request_gpio(gpio);
+       return 0;
+}
+
+static void zx_gpio_free(struct gpio_chip *gc, unsigned offset)
+{
+       struct zx_gpio *chip = to_zx(gc);
+       int gpio = gc->base + offset;
+
+       if (chip->uses_pinctrl)
+               pinctrl_free_gpio(gpio);
+}
+
+static int zx_direction_input(struct gpio_chip *gc, unsigned offset)
+{
+       struct zx_gpio *chip = to_zx(gc);
+       unsigned long flags;
+       u16 gpiodir;
+
+       if (offset >= gc->ngpio)
+               return -EINVAL;
+
+       spin_lock_irqsave(&chip->lock, flags);
+       gpiodir = readw_relaxed(chip->base + ZX_GPIO_DIR);
+       gpiodir &= ~BIT(offset);
+       writew_relaxed(gpiodir, chip->base + ZX_GPIO_DIR);
+       spin_unlock_irqrestore(&chip->lock, flags);
+
+       return 0;
+}
+
+static int zx_direction_output(struct gpio_chip *gc, unsigned offset,
+               int value)
+{
+       struct zx_gpio *chip = to_zx(gc);
+       unsigned long flags;
+       u16 gpiodir;
+
+       if (offset >= gc->ngpio)
+               return -EINVAL;
+
+       spin_lock_irqsave(&chip->lock, flags);
+       gpiodir = readw_relaxed(chip->base + ZX_GPIO_DIR);
+       gpiodir |= BIT(offset);
+       writew_relaxed(gpiodir, chip->base + ZX_GPIO_DIR);
+
+       if (value)
+               writew_relaxed(BIT(offset), chip->base + ZX_GPIO_DO1);
+       else
+               writew_relaxed(BIT(offset), chip->base + ZX_GPIO_DO0);
+       spin_unlock_irqrestore(&chip->lock, flags);
+
+       return 0;
+}
+
+static int zx_get_value(struct gpio_chip *gc, unsigned offset)
+{
+       struct zx_gpio *chip = to_zx(gc);
+
+       return !!(readw_relaxed(chip->base + ZX_GPIO_DI) & BIT(offset));
+}
+
+static void zx_set_value(struct gpio_chip *gc, unsigned offset, int value)
+{
+       struct zx_gpio *chip = to_zx(gc);
+
+       if (value)
+               writew_relaxed(BIT(offset), chip->base + ZX_GPIO_DO1);
+       else
+               writew_relaxed(BIT(offset), chip->base + ZX_GPIO_DO0);
+}
+
+static int zx_irq_type(struct irq_data *d, unsigned trigger)
+{
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct zx_gpio *chip = to_zx(gc);
+       int offset = irqd_to_hwirq(d);
+       unsigned long flags;
+       u16 gpiois, gpioi_epos, gpioi_eneg, gpioiev;
+       u16 bit = BIT(offset);
+
+       if (offset < 0 || offset >= ZX_GPIO_NR)
+               return -EINVAL;
+
+       spin_lock_irqsave(&chip->lock, flags);
+
+       gpioiev = readw_relaxed(chip->base + ZX_GPIO_IV);
+       gpiois = readw_relaxed(chip->base + ZX_GPIO_IVE);
+       gpioi_epos = readw_relaxed(chip->base + ZX_GPIO_IEP);
+       gpioi_eneg = readw_relaxed(chip->base + ZX_GPIO_IEN);
+
+       if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
+               gpiois |= bit;
+               if (trigger & IRQ_TYPE_LEVEL_HIGH)
+                       gpioiev |= bit;
+               else
+                       gpioiev &= ~bit;
+       } else
+               gpiois &= ~bit;
+
+       if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
+               gpioi_epos |= bit;
+               gpioi_eneg |= bit;
+       } else {
+               if (trigger & IRQ_TYPE_EDGE_RISING) {
+                       gpioi_epos |= bit;
+                       gpioi_eneg &= ~bit;
+               } else if (trigger & IRQ_TYPE_EDGE_FALLING) {
+                       gpioi_eneg |= bit;
+                       gpioi_epos &= ~bit;
+               }
+       }
+
+       writew_relaxed(gpiois, chip->base + ZX_GPIO_IVE);
+       writew_relaxed(gpioi_epos, chip->base + ZX_GPIO_IEP);
+       writew_relaxed(gpioi_eneg, chip->base + ZX_GPIO_IEN);
+       writew_relaxed(gpioiev, chip->base + ZX_GPIO_IV);
+       spin_unlock_irqrestore(&chip->lock, flags);
+
+       return 0;
+}
+
+static void zx_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+       unsigned long pending;
+       int offset;
+       struct gpio_chip *gc = irq_desc_get_handler_data(desc);
+       struct zx_gpio *chip = to_zx(gc);
+       struct irq_chip *irqchip = irq_desc_get_chip(desc);
+
+       chained_irq_enter(irqchip, desc);
+
+       pending = readw_relaxed(chip->base + ZX_GPIO_MIS);
+       writew_relaxed(pending, chip->base + ZX_GPIO_IC);
+       if (pending) {
+               for_each_set_bit(offset, &pending, ZX_GPIO_NR)
+                       generic_handle_irq(irq_find_mapping(gc->irqdomain,
+                                                           offset));
+       }
+
+       chained_irq_exit(irqchip, desc);
+}
+
+static void zx_irq_mask(struct irq_data *d)
+{
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct zx_gpio *chip = to_zx(gc);
+       u16 mask = BIT(irqd_to_hwirq(d) % ZX_GPIO_NR);
+       u16 gpioie;
+
+       spin_lock(&chip->lock);
+       gpioie = readw_relaxed(chip->base + ZX_GPIO_IM) | mask;
+       writew_relaxed(gpioie, chip->base + ZX_GPIO_IM);
+       gpioie = readw_relaxed(chip->base + ZX_GPIO_IE) & ~mask;
+       writew_relaxed(gpioie, chip->base + ZX_GPIO_IE);
+       spin_unlock(&chip->lock);
+}
+
+static void zx_irq_unmask(struct irq_data *d)
+{
+       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+       struct zx_gpio *chip = to_zx(gc);
+       u16 mask = BIT(irqd_to_hwirq(d) % ZX_GPIO_NR);
+       u16 gpioie;
+
+       spin_lock(&chip->lock);
+       gpioie = readw_relaxed(chip->base + ZX_GPIO_IM) & ~mask;
+       writew_relaxed(gpioie, chip->base + ZX_GPIO_IM);
+       gpioie = readw_relaxed(chip->base + ZX_GPIO_IE) | mask;
+       writew_relaxed(gpioie, chip->base + ZX_GPIO_IE);
+       spin_unlock(&chip->lock);
+}
+
+static struct irq_chip zx_irqchip = {
+       .name           = "zx-gpio",
+       .irq_mask       = zx_irq_mask,
+       .irq_unmask     = zx_irq_unmask,
+       .irq_set_type   = zx_irq_type,
+};
+
+static int zx_gpio_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct zx_gpio *chip;
+       struct resource *res;
+       int irq, id, ret;
+
+       chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
+       if (!chip)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       chip->base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(chip->base))
+               return PTR_ERR(chip->base);
+
+       spin_lock_init(&chip->lock);
+       if (of_property_read_bool(dev->of_node, "gpio-ranges"))
+               chip->uses_pinctrl = true;
+
+       id = of_alias_get_id(dev->of_node, "gpio");
+       chip->gc.request = zx_gpio_request;
+       chip->gc.free = zx_gpio_free;
+       chip->gc.direction_input = zx_direction_input;
+       chip->gc.direction_output = zx_direction_output;
+       chip->gc.get = zx_get_value;
+       chip->gc.set = zx_set_value;
+       chip->gc.base = ZX_GPIO_NR * id;
+       chip->gc.ngpio = ZX_GPIO_NR;
+       chip->gc.label = dev_name(dev);
+       chip->gc.dev = dev;
+       chip->gc.owner = THIS_MODULE;
+
+       ret = gpiochip_add(&chip->gc);
+       if (ret)
+               return ret;
+
+       /*
+        * irq_chip support
+        */
+       writew_relaxed(0xffff, chip->base + ZX_GPIO_IM);
+       writew_relaxed(0, chip->base + ZX_GPIO_IE);
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_err(dev, "invalid IRQ\n");
+               gpiochip_remove(&chip->gc);
+               return -ENODEV;
+       }
+
+       ret = gpiochip_irqchip_add(&chip->gc, &zx_irqchip,
+                                  0, handle_simple_irq,
+                                  IRQ_TYPE_NONE);
+       if (ret) {
+               dev_err(dev, "could not add irqchip\n");
+               gpiochip_remove(&chip->gc);
+               return ret;
+       }
+       gpiochip_set_chained_irqchip(&chip->gc, &zx_irqchip,
+                                    irq, zx_irq_handler);
+
+       platform_set_drvdata(pdev, chip);
+       dev_info(dev, "ZX GPIO chip registered\n");
+
+       return 0;
+}
+
+static const struct of_device_id zx_gpio_match[] = {
+       {
+               .compatible = "zte,zx296702-gpio",
+       },
+       { },
+};
+MODULE_DEVICE_TABLE(of, zx_gpio_match);
+
+static struct platform_driver zx_gpio_driver = {
+       .probe          = zx_gpio_probe,
+       .driver = {
+               .name   = "zx_gpio",
+               .of_match_table = of_match_ptr(zx_gpio_match),
+       },
+};
+
+module_platform_driver(zx_gpio_driver)
+
+MODULE_AUTHOR("Jun Nie <jun.nie@linaro.org>");
+MODULE_DESCRIPTION("ZTE ZX296702 GPIO driver");
+MODULE_LICENSE("GPL");
index a78882389836071510bbcd5548ce426e894868ab..27348e7cb705909adafa01b4490b2866e125caae 100644 (file)
@@ -441,10 +441,10 @@ static int zynq_gpio_set_irq_type(struct irq_data *irq_data, unsigned int type)
                       gpio->base_addr + ZYNQ_GPIO_INTANY_OFFSET(bank_num));
 
        if (type & IRQ_TYPE_LEVEL_MASK) {
-               __irq_set_chip_handler_name_locked(irq_data->irq,
+               irq_set_chip_handler_name_locked(irq_data,
                        &zynq_gpio_level_irqchip, handle_fasteoi_irq, NULL);
        } else {
-               __irq_set_chip_handler_name_locked(irq_data->irq,
+               irq_set_chip_handler_name_locked(irq_data,
                        &zynq_gpio_edge_irqchip, handle_level_irq, NULL);
        }
 
@@ -518,7 +518,7 @@ static void zynq_gpio_irqhandler(unsigned int irq, struct irq_desc *desc)
 {
        u32 int_sts, int_enb;
        unsigned int bank_num;
-       struct zynq_gpio *gpio = irq_get_handler_data(irq);
+       struct zynq_gpio *gpio = irq_desc_get_handler_data(desc);
        struct irq_chip *irqchip = irq_desc_get_chip(desc);
 
        chained_irq_enter(irqchip, desc);
@@ -782,6 +782,12 @@ static int __init zynq_gpio_init(void)
 }
 postcore_initcall(zynq_gpio_init);
 
+static void __exit zynq_gpio_exit(void)
+{
+       platform_driver_unregister(&zynq_gpio_driver);
+}
+module_exit(zynq_gpio_exit);
+
 MODULE_AUTHOR("Xilinx Inc.");
 MODULE_DESCRIPTION("Zynq GPIO driver");
 MODULE_LICENSE("GPL");
index 9a0ec48a47375d18d4d6d17f98e379f30f8e9ec8..fa6e3c8823d614dba89167e9eca1ad2dd74577b8 100644 (file)
@@ -136,7 +136,6 @@ static struct gpio_desc *of_get_gpio_hog(struct device_node *np,
 {
        struct device_node *chip_np;
        enum of_gpio_flags xlate_flags;
-       struct gpio_desc *desc;
        struct gg_data gg_data = {
                .flags = &xlate_flags,
        };
@@ -193,9 +192,7 @@ static struct gpio_desc *of_get_gpio_hog(struct device_node *np,
        if (name && of_property_read_string(np, "line-name", name))
                *name = np->name;
 
-       desc = gg_data.out_gpio;
-
-       return desc;
+       return gg_data.out_gpio;
 }
 
 /**
@@ -338,7 +335,7 @@ void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc)
 EXPORT_SYMBOL(of_mm_gpiochip_remove);
 
 #ifdef CONFIG_PINCTRL
-static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
+static int of_gpiochip_add_pin_range(struct gpio_chip *chip)
 {
        struct device_node *np = chip->of_node;
        struct of_phandle_args pinspec;
@@ -349,7 +346,7 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
        struct property *group_names;
 
        if (!np)
-               return;
+               return 0;
 
        group_names = of_find_property(np, group_names_propname, NULL);
 
@@ -361,11 +358,11 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
 
                pctldev = of_pinctrl_get(pinspec.np);
                if (!pctldev)
-                       break;
+                       return -EPROBE_DEFER;
 
                if (pinspec.args[2]) {
                        if (group_names) {
-                               ret = of_property_read_string_index(np,
+                               of_property_read_string_index(np,
                                                group_names_propname,
                                                index, &name);
                                if (strlen(name)) {
@@ -381,7 +378,7 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
                                        pinspec.args[1],
                                        pinspec.args[2]);
                        if (ret)
-                               break;
+                               return ret;
                } else {
                        /* npins == 0: special range */
                        if (pinspec.args[1]) {
@@ -411,32 +408,41 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
                        ret = gpiochip_add_pingroup_range(chip, pctldev,
                                                pinspec.args[0], name);
                        if (ret)
-                               break;
+                               return ret;
                }
        }
+
+       return 0;
 }
 
 #else
-static void of_gpiochip_add_pin_range(struct gpio_chip *chip) {}
+static int of_gpiochip_add_pin_range(struct gpio_chip *chip) { return 0; }
 #endif
 
-void of_gpiochip_add(struct gpio_chip *chip)
+int of_gpiochip_add(struct gpio_chip *chip)
 {
+       int status;
+
        if ((!chip->of_node) && (chip->dev))
                chip->of_node = chip->dev->of_node;
 
        if (!chip->of_node)
-               return;
+               return 0;
 
        if (!chip->of_xlate) {
                chip->of_gpio_n_cells = 2;
                chip->of_xlate = of_gpio_simple_xlate;
        }
 
-       of_gpiochip_add_pin_range(chip);
+       status = of_gpiochip_add_pin_range(chip);
+       if (status)
+               return status;
+
        of_node_get(chip->of_node);
 
        of_gpiochip_scan_hogs(chip);
+
+       return 0;
 }
 
 void of_gpiochip_remove(struct gpio_chip *chip)
index bf4bd1d120c38a94fb997521c1712224a7712f8d..b562dd36c4af1923ddae75416454785fc852ae1b 100644 (file)
@@ -190,7 +190,7 @@ EXPORT_SYMBOL_GPL(gpiod_get_direction);
  */
 static int gpiochip_add_to_list(struct gpio_chip *chip)
 {
-       struct list_head *pos = &gpio_chips;
+       struct list_head *pos;
        struct gpio_chip *_chip;
        int err = 0;
 
@@ -287,7 +287,13 @@ int gpiochip_add(struct gpio_chip *chip)
        INIT_LIST_HEAD(&chip->pin_ranges);
 #endif
 
-       of_gpiochip_add(chip);
+       if (!chip->owner && chip->dev && chip->dev->driver)
+               chip->owner = chip->dev->driver->owner;
+
+       status = of_gpiochip_add(chip);
+       if (status)
+               goto err_remove_chip;
+
        acpi_gpiochip_add(chip);
 
        status = gpiochip_sysfs_register(chip);
@@ -443,8 +449,8 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
                 * The parent irqchip is already using the chip_data for this
                 * irqchip, so our callbacks simply use the handler_data.
                 */
-               irq_set_handler_data(parent_irq, gpiochip);
-               irq_set_chained_handler(parent_irq, parent_handler);
+               irq_set_chained_handler_and_data(parent_irq, parent_handler,
+                                                gpiochip);
 
                gpiochip->irq_parent = parent_irq;
        }
@@ -456,12 +462,6 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
 }
 EXPORT_SYMBOL_GPL(gpiochip_set_chained_irqchip);
 
-/*
- * This lock class tells lockdep that GPIO irqs are in a different
- * category than their parents, so it won't report false recursion.
- */
-static struct lock_class_key gpiochip_irq_lock_class;
-
 /**
  * gpiochip_irq_map() - maps an IRQ into a GPIO irqchip
  * @d: the irqdomain used by this irqchip
@@ -478,16 +478,17 @@ static int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,
        struct gpio_chip *chip = d->host_data;
 
        irq_set_chip_data(irq, chip);
-       irq_set_lockdep_class(irq, &gpiochip_irq_lock_class);
+       /*
+        * This lock class tells lockdep that GPIO irqs are in a different
+        * category than their parents, so it won't report false recursion.
+        */
+       irq_set_lockdep_class(irq, chip->lock_key);
        irq_set_chip_and_handler(irq, chip->irqchip, chip->irq_handler);
        /* Chips that can sleep need nested thread handlers */
        if (chip->can_sleep && !chip->irq_not_threaded)
                irq_set_nested_thread(irq, 1);
-#ifdef CONFIG_ARM
-       set_irq_flags(irq, IRQF_VALID);
-#else
        irq_set_noprobe(irq);
-#endif
+
        /*
         * No set-up of the hardware will happen if IRQ_TYPE_NONE
         * is passed as default type.
@@ -502,9 +503,6 @@ static void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq)
 {
        struct gpio_chip *chip = d->host_data;
 
-#ifdef CONFIG_ARM
-       set_irq_flags(irq, 0);
-#endif
        if (chip->can_sleep)
                irq_set_nested_thread(irq, 0);
        irq_set_chip_and_handler(irq, NULL, NULL);
@@ -522,10 +520,14 @@ static int gpiochip_irq_reqres(struct irq_data *d)
 {
        struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
 
+       if (!try_module_get(chip->owner))
+               return -ENODEV;
+
        if (gpiochip_lock_as_irq(chip, d->hwirq)) {
                chip_err(chip,
                        "unable to lock HW IRQ %lu for IRQ\n",
                        d->hwirq);
+               module_put(chip->owner);
                return -EINVAL;
        }
        return 0;
@@ -536,6 +538,7 @@ static void gpiochip_irq_relres(struct irq_data *d)
        struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
 
        gpiochip_unlock_as_irq(chip, d->hwirq);
+       module_put(chip->owner);
 }
 
 static int gpiochip_to_irq(struct gpio_chip *chip, unsigned offset)
@@ -584,6 +587,7 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)
  * @handler: the irq handler to use (often a predefined irq core function)
  * @type: the default type for IRQs on this irqchip, pass IRQ_TYPE_NONE
  * to have the core avoid setting up any default type in the hardware.
+ * @lock_key: lockdep class
  *
  * This function closely associates a certain irqchip with a certain
  * gpiochip, providing an irq domain to translate the local IRQs to
@@ -599,11 +603,12 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)
  * the pins on the gpiochip can generate a unique IRQ. Everything else
  * need to be open coded.
  */
-int gpiochip_irqchip_add(struct gpio_chip *gpiochip,
-                        struct irq_chip *irqchip,
-                        unsigned int first_irq,
-                        irq_flow_handler_t handler,
-                        unsigned int type)
+int _gpiochip_irqchip_add(struct gpio_chip *gpiochip,
+                         struct irq_chip *irqchip,
+                         unsigned int first_irq,
+                         irq_flow_handler_t handler,
+                         unsigned int type,
+                         struct lock_class_key *lock_key)
 {
        struct device_node *of_node;
        unsigned int offset;
@@ -629,6 +634,7 @@ int gpiochip_irqchip_add(struct gpio_chip *gpiochip,
        gpiochip->irq_handler = handler;
        gpiochip->irq_default_type = type;
        gpiochip->to_irq = gpiochip_to_irq;
+       gpiochip->lock_key = lock_key;
        gpiochip->irqdomain = irq_domain_add_simple(of_node,
                                        gpiochip->ngpio, first_irq,
                                        &gpiochip_domain_ops, gpiochip);
@@ -636,8 +642,16 @@ int gpiochip_irqchip_add(struct gpio_chip *gpiochip,
                gpiochip->irqchip = NULL;
                return -EINVAL;
        }
-       irqchip->irq_request_resources = gpiochip_irq_reqres;
-       irqchip->irq_release_resources = gpiochip_irq_relres;
+
+       /*
+        * It is possible for a driver to override this, but only if the
+        * alternative functions are both implemented.
+        */
+       if (!irqchip->irq_request_resources &&
+           !irqchip->irq_release_resources) {
+               irqchip->irq_request_resources = gpiochip_irq_reqres;
+               irqchip->irq_release_resources = gpiochip_irq_relres;
+       }
 
        /*
         * Prepare the mapping since the irqchip shall be orthogonal to
@@ -658,7 +672,7 @@ int gpiochip_irqchip_add(struct gpio_chip *gpiochip,
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(gpiochip_irqchip_add);
+EXPORT_SYMBOL_GPL(_gpiochip_irqchip_add);
 
 #else /* CONFIG_GPIOLIB_IRQCHIP */
 
@@ -671,7 +685,7 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) {}
 /**
  * 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
+ * @pctldev: 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
  */
@@ -1894,12 +1908,12 @@ EXPORT_SYMBOL_GPL(gpiod_count);
  * dev, -ENOENT if no GPIO has been assigned to the requested function, or
  * another IS_ERR() code if an error occurred while trying to acquire the GPIO.
  */
-struct gpio_desc *__must_check __gpiod_get(struct device *dev, const char *con_id,
+struct gpio_desc *__must_check gpiod_get(struct device *dev, const char *con_id,
                                         enum gpiod_flags flags)
 {
        return gpiod_get_index(dev, con_id, 0, flags);
 }
-EXPORT_SYMBOL_GPL(__gpiod_get);
+EXPORT_SYMBOL_GPL(gpiod_get);
 
 /**
  * gpiod_get_optional - obtain an optional GPIO for a given GPIO function
@@ -1911,13 +1925,13 @@ EXPORT_SYMBOL_GPL(__gpiod_get);
  * the requested function it will return NULL. This is convenient for drivers
  * that need to handle optional GPIOs.
  */
-struct gpio_desc *__must_check __gpiod_get_optional(struct device *dev,
+struct gpio_desc *__must_check gpiod_get_optional(struct device *dev,
                                                  const char *con_id,
                                                  enum gpiod_flags flags)
 {
        return gpiod_get_index_optional(dev, con_id, 0, flags);
 }
-EXPORT_SYMBOL_GPL(__gpiod_get_optional);
+EXPORT_SYMBOL_GPL(gpiod_get_optional);
 
 
 /**
@@ -1974,7 +1988,7 @@ static int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
  * requested function and/or index, or another IS_ERR() code if an error
  * occurred while trying to acquire the GPIO.
  */
-struct gpio_desc *__must_check __gpiod_get_index(struct device *dev,
+struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
                                               const char *con_id,
                                               unsigned int idx,
                                               enum gpiod_flags flags)
@@ -2023,7 +2037,7 @@ struct gpio_desc *__must_check __gpiod_get_index(struct device *dev,
 
        return desc;
 }
-EXPORT_SYMBOL_GPL(__gpiod_get_index);
+EXPORT_SYMBOL_GPL(gpiod_get_index);
 
 /**
  * fwnode_get_named_gpiod - obtain a GPIO from firmware node
@@ -2092,7 +2106,7 @@ EXPORT_SYMBOL_GPL(fwnode_get_named_gpiod);
  * specified index was assigned to the requested function it will return NULL.
  * This is convenient for drivers that need to handle optional GPIOs.
  */
-struct gpio_desc *__must_check __gpiod_get_index_optional(struct device *dev,
+struct gpio_desc *__must_check gpiod_get_index_optional(struct device *dev,
                                                        const char *con_id,
                                                        unsigned int index,
                                                        enum gpiod_flags flags)
@@ -2107,7 +2121,7 @@ struct gpio_desc *__must_check __gpiod_get_index_optional(struct device *dev,
 
        return desc;
 }
-EXPORT_SYMBOL_GPL(__gpiod_get_index_optional);
+EXPORT_SYMBOL_GPL(gpiod_get_index_optional);
 
 /**
  * gpiod_hog - Hog the specified GPIO desc given the provided flags
index 7991069dd492ada6ce2eb5ef0df979fe9c1cd431..81200e9be3821c9c87db1a26d46318d133378ba8 100644 (file)
@@ -373,7 +373,7 @@ static int edp_gpio_config(struct edp_ctrl *ctrl)
        struct device *dev = &ctrl->pdev->dev;
        int ret;
 
-       ctrl->panel_hpd_gpio = devm_gpiod_get(dev, "panel-hpd");
+       ctrl->panel_hpd_gpio = devm_gpiod_get(dev, "panel-hpd", GPIOD_IN);
        if (IS_ERR(ctrl->panel_hpd_gpio)) {
                ret = PTR_ERR(ctrl->panel_hpd_gpio);
                ctrl->panel_hpd_gpio = NULL;
@@ -381,13 +381,7 @@ static int edp_gpio_config(struct edp_ctrl *ctrl)
                return ret;
        }
 
-       ret = gpiod_direction_input(ctrl->panel_hpd_gpio);
-       if (ret) {
-               pr_err("%s: Set direction for hpd failed, %d\n", __func__, ret);
-               return ret;
-       }
-
-       ctrl->panel_en_gpio = devm_gpiod_get(dev, "panel-en");
+       ctrl->panel_en_gpio = devm_gpiod_get(dev, "panel-en", GPIOD_OUT_LOW);
        if (IS_ERR(ctrl->panel_en_gpio)) {
                ret = PTR_ERR(ctrl->panel_en_gpio);
                ctrl->panel_en_gpio = NULL;
@@ -395,13 +389,6 @@ static int edp_gpio_config(struct edp_ctrl *ctrl)
                return ret;
        }
 
-       ret = gpiod_direction_output(ctrl->panel_en_gpio, 0);
-       if (ret) {
-               pr_err("%s: Set direction for panel_en failed, %d\n",
-                               __func__, ret);
-               return ret;
-       }
-
        DBG("gpio on");
 
        return 0;
index 7a0315855e90130d5eaa2f00e76750e59a68853f..0af8bed7ce1ee7238dadb6328ac9a73ba38a567d 100644 (file)
@@ -375,25 +375,17 @@ static int panel_probe(struct platform_device *pdev)
                dev_info(&pdev->dev, "found backlight\n");
        }
 
-       panel_mod->enable_gpio = devm_gpiod_get(&pdev->dev, "enable");
+       panel_mod->enable_gpio = devm_gpiod_get_optional(&pdev->dev, "enable",
+                                                        GPIOD_OUT_LOW);
        if (IS_ERR(panel_mod->enable_gpio)) {
                ret = PTR_ERR(panel_mod->enable_gpio);
-               if (ret != -ENOENT) {
-                       dev_err(&pdev->dev, "failed to request enable GPIO\n");
-                       goto fail_backlight;
-               }
-
-               /* Optional GPIO is not here, continue silently. */
-               panel_mod->enable_gpio = NULL;
-       } else {
-               ret = gpiod_direction_output(panel_mod->enable_gpio, 0);
-               if (ret < 0) {
-                       dev_err(&pdev->dev, "failed to setup GPIO\n");
-                       goto fail_backlight;
-               }
-               dev_info(&pdev->dev, "found enable GPIO\n");
+               dev_err(&pdev->dev, "failed to request enable GPIO\n");
+               goto fail_backlight;
        }
 
+       if (panel_mod->enable_gpio)
+               dev_info(&pdev->dev, "found enable GPIO\n");
+
        mod = &panel_mod->base;
        pdev->dev.platform_data = mod;
 
index f101bb5bddc7d710c6412dc2d982a6785953b47d..993eb201148e081f1e9092c780fc17ed61c11f0b 100644 (file)
@@ -469,16 +469,12 @@ static int stk3310_gpio_probe(struct i2c_client *client)
        dev = &client->dev;
 
        /* gpio interrupt pin */
-       gpio = devm_gpiod_get_index(dev, STK3310_GPIO, 0);
+       gpio = devm_gpiod_get_index(dev, STK3310_GPIO, 0, GPIOD_IN);
        if (IS_ERR(gpio)) {
                dev_err(dev, "acpi gpio get index failed\n");
                return PTR_ERR(gpio);
        }
 
-       ret = gpiod_direction_input(gpio);
-       if (ret)
-               return ret;
-
        ret = gpiod_to_irq(gpio);
        dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret);
 
index e330205f81947589a06d5a83232696a0613bbd1f..d8e614ca069fe7e3d55da67464be889a64e8af64 100644 (file)
@@ -845,16 +845,12 @@ static int bmc150_magn_gpio_probe(struct i2c_client *client)
        dev = &client->dev;
 
        /* data ready GPIO interrupt pin */
-       gpio = devm_gpiod_get_index(dev, BMC150_MAGN_GPIO_INT, 0);
+       gpio = devm_gpiod_get_index(dev, BMC150_MAGN_GPIO_INT, 0, GPIOD_IN);
        if (IS_ERR(gpio)) {
                dev_err(dev, "ACPI GPIO get index failed\n");
                return PTR_ERR(gpio);
        }
 
-       ret = gpiod_direction_input(gpio);
-       if (ret)
-               return ret;
-
        ret = gpiod_to_irq(gpio);
 
        dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret);
index c70ababce954d1d7ea2965dfe121996b4c0fe161..5dd39775d6ca5c449c1b496c90a275ba6ba9118a 100644 (file)
@@ -465,7 +465,7 @@ static int adp1653_of_init(struct i2c_client *client,
 
        of_node_put(child);
 
-       pd->enable_gpio = devm_gpiod_get(&client->dev, "enable");
+       pd->enable_gpio = devm_gpiod_get(&client->dev, "enable", GPIOD_OUT_LOW);
        if (!pd->enable_gpio) {
                dev_err(&client->dev, "Error getting GPIO\n");
                return -EINVAL;
index 2f77f1d03638504e8234c0a95e28b9e79cb8dead..fac80c691914b6625a9eab504b8baca75833c0dc 100644 (file)
@@ -318,19 +318,15 @@ static int nxp_nci_i2c_acpi_config(struct nxp_nci_i2c_phy *phy)
        struct i2c_client *client = phy->i2c_dev;
        struct gpio_desc *gpiod_en, *gpiod_fw, *gpiod_irq;
 
-       gpiod_en = devm_gpiod_get_index(&client->dev, NULL, 2);
-       gpiod_fw = devm_gpiod_get_index(&client->dev, NULL, 1);
-       gpiod_irq = devm_gpiod_get_index(&client->dev, NULL, 0);
+       gpiod_en = devm_gpiod_get_index(&client->dev, NULL, 2, GPIOD_OUT_LOW);
+       gpiod_fw = devm_gpiod_get_index(&client->dev, NULL, 1, GPIOD_OUT_LOW);
+       gpiod_irq = devm_gpiod_get_index(&client->dev, NULL, 0, GPIOD_IN);
 
        if (IS_ERR(gpiod_en) || IS_ERR(gpiod_fw) || IS_ERR(gpiod_irq)) {
                nfc_err(&client->dev, "No GPIOs\n");
                return -EINVAL;
        }
 
-       gpiod_direction_output(gpiod_en, 0);
-       gpiod_direction_output(gpiod_fw, 0);
-       gpiod_direction_input(gpiod_irq);
-
        client->irq = gpiod_to_irq(gpiod_irq);
        if (client->irq < 0) {
                nfc_err(&client->dev, "No IRQ\n");
index 2535d792d57af69277460ed4bc51beb39065d1d5..4f6d5e71507d1c5989326fbeece2597593b39f2f 100644 (file)
@@ -61,32 +61,26 @@ static const struct phy_ops phy_ops = {
 
 static int tusb1210_probe(struct ulpi *ulpi)
 {
-       struct gpio_desc *gpio;
        struct tusb1210 *tusb;
        u8 val, reg;
-       int ret;
 
        tusb = devm_kzalloc(&ulpi->dev, sizeof(*tusb), GFP_KERNEL);
        if (!tusb)
                return -ENOMEM;
 
-       gpio = devm_gpiod_get(&ulpi->dev, "reset");
-       if (!IS_ERR(gpio)) {
-               ret = gpiod_direction_output(gpio, 0);
-               if (ret)
-                       return ret;
-               gpiod_set_value_cansleep(gpio, 1);
-               tusb->gpio_reset = gpio;
-       }
+       tusb->gpio_reset = devm_gpiod_get_optional(&ulpi->dev, "reset",
+                                                  GPIOD_OUT_LOW);
+       if (IS_ERR(tusb->gpio_reset))
+               return PTR_ERR(tusb->gpio_reset);
 
-       gpio = devm_gpiod_get(&ulpi->dev, "cs");
-       if (!IS_ERR(gpio)) {
-               ret = gpiod_direction_output(gpio, 0);
-               if (ret)
-                       return ret;
-               gpiod_set_value_cansleep(gpio, 1);
-               tusb->gpio_cs = gpio;
-       }
+       gpiod_set_value_cansleep(tusb->gpio_reset, 1);
+
+       tusb->gpio_cs = devm_gpiod_get_optional(&ulpi->dev, "cs",
+                                               GPIOD_OUT_LOW);
+       if (IS_ERR(tusb->gpio_cs))
+               return PTR_ERR(tusb->gpio_cs);
+
+       gpiod_set_value_cansleep(tusb->gpio_cs, 1);
 
        /*
         * VENDOR_SPECIFIC2 register in TUSB1210 can be used for configuring eye
index 14eea946e6401cde3880cafc4e7c11e1264d918a..ed3768f4ecc70f7554ed4eeee53fb79615e0a05f 100644 (file)
@@ -75,5 +75,6 @@ int bgpio_init(struct bgpio_chip *bgc, struct device *dev,
 #define BGPIOF_UNREADABLE_REG_DIR      BIT(2) /* reg_dir is unreadable */
 #define BGPIOF_BIG_ENDIAN_BYTE_ORDER   BIT(3)
 #define BGPIOF_READ_OUTPUT_REG_SET     BIT(4) /* reg_set stores output value */
+#define BGPIOF_NO_OUTPUT               BIT(5) /* only input */
 
 #endif /* __BASIC_MMIO_GPIO_H */
index adac255aee86e359fb83085ba2c41edfc6f1991d..14cac67c2012b6883d03445331337d139aba0307 100644 (file)
@@ -47,17 +47,17 @@ enum gpiod_flags {
 int gpiod_count(struct device *dev, const char *con_id);
 
 /* Acquire and dispose GPIOs */
-struct gpio_desc *__must_check __gpiod_get(struct device *dev,
+struct gpio_desc *__must_check gpiod_get(struct device *dev,
                                         const char *con_id,
                                         enum gpiod_flags flags);
-struct gpio_desc *__must_check __gpiod_get_index(struct device *dev,
+struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
                                               const char *con_id,
                                               unsigned int idx,
                                               enum gpiod_flags flags);
-struct gpio_desc *__must_check __gpiod_get_optional(struct device *dev,
+struct gpio_desc *__must_check gpiod_get_optional(struct device *dev,
                                                  const char *con_id,
                                                  enum gpiod_flags flags);
-struct gpio_desc *__must_check __gpiod_get_index_optional(struct device *dev,
+struct gpio_desc *__must_check gpiod_get_index_optional(struct device *dev,
                                                        const char *con_id,
                                                        unsigned int index,
                                                        enum gpiod_flags flags);
@@ -70,18 +70,18 @@ struct gpio_descs *__must_check gpiod_get_array_optional(struct device *dev,
 void gpiod_put(struct gpio_desc *desc);
 void gpiod_put_array(struct gpio_descs *descs);
 
-struct gpio_desc *__must_check __devm_gpiod_get(struct device *dev,
+struct gpio_desc *__must_check devm_gpiod_get(struct device *dev,
                                              const char *con_id,
                                              enum gpiod_flags flags);
-struct gpio_desc *__must_check __devm_gpiod_get_index(struct device *dev,
+struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
                                                    const char *con_id,
                                                    unsigned int idx,
                                                    enum gpiod_flags flags);
-struct gpio_desc *__must_check __devm_gpiod_get_optional(struct device *dev,
+struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev,
                                                       const char *con_id,
                                                       enum gpiod_flags flags);
 struct gpio_desc *__must_check
-__devm_gpiod_get_index_optional(struct device *dev, const char *con_id,
+devm_gpiod_get_index_optional(struct device *dev, const char *con_id,
                              unsigned int index, enum gpiod_flags flags);
 struct gpio_descs *__must_check devm_gpiod_get_array(struct device *dev,
                                                     const char *con_id,
@@ -146,31 +146,31 @@ static inline int gpiod_count(struct device *dev, const char *con_id)
        return 0;
 }
 
-static inline struct gpio_desc *__must_check __gpiod_get(struct device *dev,
-                                               const char *con_id,
-                                               enum gpiod_flags flags)
+static inline struct gpio_desc *__must_check gpiod_get(struct device *dev,
+                                                      const char *con_id,
+                                                      enum gpiod_flags flags)
 {
        return ERR_PTR(-ENOSYS);
 }
 static inline struct gpio_desc *__must_check
-__gpiod_get_index(struct device *dev,
-                 const char *con_id,
-                 unsigned int idx,
-                 enum gpiod_flags flags)
+gpiod_get_index(struct device *dev,
+               const char *con_id,
+               unsigned int idx,
+               enum gpiod_flags flags)
 {
        return ERR_PTR(-ENOSYS);
 }
 
 static inline struct gpio_desc *__must_check
-__gpiod_get_optional(struct device *dev, const char *con_id,
-                    enum gpiod_flags flags)
+gpiod_get_optional(struct device *dev, const char *con_id,
+                  enum gpiod_flags flags)
 {
        return ERR_PTR(-ENOSYS);
 }
 
 static inline struct gpio_desc *__must_check
-__gpiod_get_index_optional(struct device *dev, const char *con_id,
-                          unsigned int index, enum gpiod_flags flags)
+gpiod_get_index_optional(struct device *dev, const char *con_id,
+                        unsigned int index, enum gpiod_flags flags)
 {
        return ERR_PTR(-ENOSYS);
 }
@@ -206,7 +206,7 @@ static inline void gpiod_put_array(struct gpio_descs *descs)
 }
 
 static inline struct gpio_desc *__must_check
-__devm_gpiod_get(struct device *dev,
+devm_gpiod_get(struct device *dev,
                 const char *con_id,
                 enum gpiod_flags flags)
 {
@@ -214,7 +214,7 @@ __devm_gpiod_get(struct device *dev,
 }
 static inline
 struct gpio_desc *__must_check
-__devm_gpiod_get_index(struct device *dev,
+devm_gpiod_get_index(struct device *dev,
                       const char *con_id,
                       unsigned int idx,
                       enum gpiod_flags flags)
@@ -223,14 +223,14 @@ __devm_gpiod_get_index(struct device *dev,
 }
 
 static inline struct gpio_desc *__must_check
-__devm_gpiod_get_optional(struct device *dev, const char *con_id,
+devm_gpiod_get_optional(struct device *dev, const char *con_id,
                          enum gpiod_flags flags)
 {
        return ERR_PTR(-ENOSYS);
 }
 
 static inline struct gpio_desc *__must_check
-__devm_gpiod_get_index_optional(struct device *dev, const char *con_id,
+devm_gpiod_get_index_optional(struct device *dev, const char *con_id,
                                unsigned int index, enum gpiod_flags flags)
 {
        return ERR_PTR(-ENOSYS);
@@ -424,42 +424,6 @@ static inline struct gpio_desc *devm_get_gpiod_from_child(
 
 #endif /* CONFIG_GPIOLIB */
 
-/*
- * Vararg-hacks! This is done to transition the kernel to always pass
- * the options flags argument to the below functions. During a transition
- * phase these vararg macros make both old-and-newstyle code compile,
- * but when all calls to the elder API are removed, these should go away
- * and the __gpiod_get() etc functions above be renamed just gpiod_get()
- * etc.
- */
-#define __gpiod_get(dev, con_id, flags, ...) __gpiod_get(dev, con_id, flags)
-#define gpiod_get(varargs...) __gpiod_get(varargs, GPIOD_ASIS)
-#define __gpiod_get_index(dev, con_id, index, flags, ...)              \
-       __gpiod_get_index(dev, con_id, index, flags)
-#define gpiod_get_index(varargs...) __gpiod_get_index(varargs, GPIOD_ASIS)
-#define __gpiod_get_optional(dev, con_id, flags, ...)                  \
-       __gpiod_get_optional(dev, con_id, flags)
-#define gpiod_get_optional(varargs...) __gpiod_get_optional(varargs, GPIOD_ASIS)
-#define __gpiod_get_index_optional(dev, con_id, index, flags, ...)     \
-       __gpiod_get_index_optional(dev, con_id, index, flags)
-#define gpiod_get_index_optional(varargs...)                           \
-       __gpiod_get_index_optional(varargs, GPIOD_ASIS)
-#define __devm_gpiod_get(dev, con_id, flags, ...)                      \
-       __devm_gpiod_get(dev, con_id, flags)
-#define devm_gpiod_get(varargs...) __devm_gpiod_get(varargs, GPIOD_ASIS)
-#define __devm_gpiod_get_index(dev, con_id, index, flags, ...)         \
-       __devm_gpiod_get_index(dev, con_id, index, flags)
-#define devm_gpiod_get_index(varargs...)                               \
-       __devm_gpiod_get_index(varargs, GPIOD_ASIS)
-#define __devm_gpiod_get_optional(dev, con_id, flags, ...)             \
-       __devm_gpiod_get_optional(dev, con_id, flags)
-#define devm_gpiod_get_optional(varargs...)                            \
-       __devm_gpiod_get_optional(varargs, GPIOD_ASIS)
-#define __devm_gpiod_get_index_optional(dev, con_id, index, flags, ...)        \
-       __devm_gpiod_get_index_optional(dev, con_id, index, flags)
-#define devm_gpiod_get_index_optional(varargs...)                      \
-       __devm_gpiod_get_index_optional(varargs, GPIOD_ASIS)
-
 #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS)
 
 int gpiod_export(struct gpio_desc *desc, bool direction_may_change);
index c8393cd4d44f2d871bdf962c3dad55505e362b32..1aed31c5ffba33c3a122779b9feb151f24953168 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/irq.h>
 #include <linux/irqchip/chained_irq.h>
 #include <linux/irqdomain.h>
+#include <linux/lockdep.h>
 #include <linux/pinctrl/pinctrl.h>
 
 struct device;
@@ -64,6 +65,17 @@ struct seq_file;
  *     registers.
  * @irq_not_threaded: flag must be set if @can_sleep is set but the
  *     IRQs don't need to be threaded
+ * @irqchip: GPIO IRQ chip impl, provided by GPIO driver
+ * @irqdomain: Interrupt translation domain; responsible for mapping
+ *     between GPIO hwirq number and linux irq number
+ * @irq_base: first linux IRQ number assigned to GPIO IRQ chip (deprecated)
+ * @irq_handler: the irq handler to use (often a predefined irq core function)
+ *     for GPIO IRQs, provided by GPIO driver
+ * @irq_default_type: default IRQ triggering type applied during GPIO driver
+ *     initialization, provided by GPIO driver
+ * @irq_parent: GPIO IRQ chip parent/bank linux irq number,
+ *     provided by GPIO driver
+ * @lock_key: per GPIO IRQ chip lockdep class
  *
  * A gpio_chip can help platforms abstract various sources of GPIOs so
  * they can all be accessed through a common programing interface.
@@ -126,6 +138,7 @@ struct gpio_chip {
        irq_flow_handler_t      irq_handler;
        unsigned int            irq_default_type;
        int                     irq_parent;
+       struct lock_class_key   *lock_key;
 #endif
 
 #if defined(CONFIG_OF_GPIO)
@@ -171,11 +184,25 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
                int parent_irq,
                irq_flow_handler_t parent_handler);
 
-int gpiochip_irqchip_add(struct gpio_chip *gpiochip,
-               struct irq_chip *irqchip,
-               unsigned int first_irq,
-               irq_flow_handler_t handler,
-               unsigned int type);
+int _gpiochip_irqchip_add(struct gpio_chip *gpiochip,
+                         struct irq_chip *irqchip,
+                         unsigned int first_irq,
+                         irq_flow_handler_t handler,
+                         unsigned int type,
+                         struct lock_class_key *lock_key);
+
+#ifdef CONFIG_LOCKDEP
+#define gpiochip_irqchip_add(...)                              \
+(                                                              \
+       ({                                                      \
+               static struct lock_class_key _key;              \
+               _gpiochip_irqchip_add(__VA_ARGS__, &_key);      \
+       })                                                      \
+)
+#else
+#define gpiochip_irqchip_add(...)                              \
+       _gpiochip_irqchip_add(__VA_ARGS__, NULL)
+#endif
 
 #endif /* CONFIG_GPIOLIB_IRQCHIP */
 
index 69dbe312b11b23f6f33f56c91e7d618b238758ff..f3191828f037368a28b3fc1affc2c5d919b74001 100644 (file)
@@ -54,7 +54,7 @@ extern int of_mm_gpiochip_add(struct device_node *np,
                              struct of_mm_gpio_chip *mm_gc);
 extern void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc);
 
-extern void of_gpiochip_add(struct gpio_chip *gc);
+extern int of_gpiochip_add(struct gpio_chip *gc);
 extern void of_gpiochip_remove(struct gpio_chip *gc);
 extern int of_gpio_simple_xlate(struct gpio_chip *gc,
                                const struct of_phandle_args *gpiospec,
@@ -76,7 +76,7 @@ static inline int of_gpio_simple_xlate(struct gpio_chip *gc,
        return -ENOSYS;
 }
 
-static inline void of_gpiochip_add(struct gpio_chip *gc) { }
+static inline int of_gpiochip_add(struct gpio_chip *gc) { return 0; }
 static inline void of_gpiochip_remove(struct gpio_chip *gc) { }
 
 #endif /* CONFIG_OF_GPIO */
diff --git a/include/linux/platform_data/gpio-em.h b/include/linux/platform_data/gpio-em.h
deleted file mode 100644 (file)
index 7c5a519..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef __GPIO_EM_H__
-#define __GPIO_EM_H__
-
-struct gpio_em_config {
-       unsigned int gpio_base;
-       unsigned int irq_base;
-       unsigned int number_of_pins;
-       const char *pctl_name;
-};
-
-#endif /* __GPIO_EM_H__ */