Commit 8d2faea6 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'gpio-v4.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio

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
  ...
parents 02cf1da2 01e2dae9
...@@ -16,7 +16,8 @@ Description: ...@@ -16,7 +16,8 @@ Description:
/sys/class/gpio /sys/class/gpio
/export ... asks the kernel to export a GPIO to userspace /export ... asks the kernel to export a GPIO to userspace
/unexport ... to return a GPIO to the kernel /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 /value ... always readable, writes fail for input GPIOs
/direction ... r/w as: in, out (default low); write: high, low /direction ... r/w as: in, out (default low); write: high, low
/edge ... r/w as: none, falling, rising, both /edge ... r/w as: none, falling, rising, both
......
...@@ -33,6 +33,13 @@ Optional properties: ...@@ -33,6 +33,13 @@ Optional properties:
- interrupt-parent: - interrupt-parent:
phandle of the parent interrupt controller 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: - #interrupt-cells:
Should be <2>. The first cell is the GPIO number, the second should specify Should be <2>. The first cell is the GPIO number, the second should specify
flags. The following subset of flags is supported: flags. The following subset of flags is supported:
...@@ -47,19 +54,33 @@ Optional properties: ...@@ -47,19 +54,33 @@ Optional properties:
- interrupt-controller: - interrupt-controller:
Marks the device node as an interrupt controller Marks the device node as an interrupt controller
- interrupt-names: - wakeup-source:
The name of the IRQ resource used by this controller GPIOs for this controller can be used as a wakeup source
Example: Example:
upg_gio: gpio@f040a700 { upg_gio: gpio@f040a700 {
#gpio-cells = <0x2>; #gpio-cells = <2>;
#interrupt-cells = <0x2>; #interrupt-cells = <2>;
compatible = "brcm,bcm7445-gpio", "brcm,brcmstb-gpio"; compatible = "brcm,bcm7445-gpio", "brcm,brcmstb-gpio";
gpio-controller; gpio-controller;
interrupt-controller; interrupt-controller;
reg = <0xf040a700 0x80>; 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>; interrupts = <0x6>;
interrupt-names = "upg_gio"; interrupts-extended = <&irq0_aon_intc 0x6>,
brcm,gpio-bank-widths = <0x20 0x20 0x20 0x18>; <&aon_pm_l2_intc 0x5>;
wakeup-source;
brcm,gpio-bank-widths = <18 4>;
}; };
...@@ -2,8 +2,9 @@ Axis ETRAX FS General I/O controller bindings ...@@ -2,8 +2,9 @@ Axis ETRAX FS General I/O controller bindings
Required properties: Required properties:
- compatible: - compatible: one of:
- "axis,etraxfs-gio" - "axis,etraxfs-gio"
- "axis,artpec3-gio"
- reg: Physical base address and length of the controller's registers. - reg: Physical base address and length of the controller's registers.
- #gpio-cells: Should be 3 - #gpio-cells: Should be 3
- The first cell is the gpio offset number. - The first cell is the gpio offset number.
......
* 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";
};
...@@ -9,6 +9,7 @@ Required Properties: ...@@ -9,6 +9,7 @@ Required Properties:
- "renesas,gpio-r8a7791": for R8A7791 (R-Car M2-W) compatible GPIO controller. - "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-r8a7793": for R8A7793 (R-Car M2-N) compatible GPIO controller.
- "renesas,gpio-r8a7794": for R8A7794 (R-Car E2) 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. - "renesas,gpio-rcar": for generic R-Car GPIO controller.
- reg: Base address and length of each memory resource used by the GPIO - reg: Base address and length of each memory resource used by the GPIO
......
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>;
};
...@@ -6,6 +6,9 @@ consumer.txt ...@@ -6,6 +6,9 @@ consumer.txt
- How to obtain and use GPIOs in a driver - How to obtain and use GPIOs in a driver
driver.txt driver.txt
- How to write a GPIO driver - 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 board.txt
- How to assign GPIOs to a consumer device and a function - How to assign GPIOs to a consumer device and a function
sysfs.txt sysfs.txt
......
...@@ -237,6 +237,39 @@ Note that these functions should only be used with great moderation ; a driver ...@@ -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. 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 Set multiple GPIO outputs with a single function call
----------------------------------------------------- -----------------------------------------------------
The following functions set the output values of an array of GPIOs: The following functions set the output values of an array of GPIOs:
......
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.
...@@ -20,11 +20,10 @@ userspace GPIO can be used to determine system configuration data that ...@@ -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 standard kernels won't know about. And for some tasks, simple userspace
GPIO drivers could be all that the system really needs. GPIO drivers could be all that the system really needs.
Note that standard kernel drivers exist for common "LEDs and Buttons" DO NOT ABUSE SYFS TO CONTROL HARDWARE THAT HAS PROPER KERNEL DRIVERS.
GPIO tasks: "leds-gpio" and "gpio_keys", respectively. Use those PLEASE READ THE DOCUMENT NAMED "drivers-on-gpio.txt" IN THIS DOCUMENTATION
instead of talking directly to the GPIOs; they integrate with kernel DIRECTORY TO AVOID REINVENTING KERNEL WHEELS IN USERSPACE. I MEAN IT.
frameworks better than your userspace code could. REALLY.
Paths in Sysfs Paths in Sysfs
-------------- --------------
......
...@@ -113,7 +113,6 @@ config GPIO_74XX_MMIO ...@@ -113,7 +113,6 @@ config GPIO_74XX_MMIO
config GPIO_ALTERA config GPIO_ALTERA
tristate "Altera GPIO" tristate "Altera GPIO"
depends on OF_GPIO depends on OF_GPIO
select GPIO_GENERIC
select GPIOLIB_IRQCHIP select GPIOLIB_IRQCHIP
help help
Say Y or M here to build support for the Altera PIO device. Say Y or M here to build support for the Altera PIO device.
...@@ -131,6 +130,7 @@ config GPIO_BRCMSTB ...@@ -131,6 +130,7 @@ config GPIO_BRCMSTB
default y if ARCH_BRCMSTB default y if ARCH_BRCMSTB
depends on OF_GPIO && (ARCH_BRCMSTB || COMPILE_TEST) depends on OF_GPIO && (ARCH_BRCMSTB || COMPILE_TEST)
select GPIO_GENERIC select GPIO_GENERIC
select GPIOLIB_IRQCHIP
help help
Say yes here to enable GPIO support for Broadcom STB (BCM7XXX) SoCs. Say yes here to enable GPIO support for Broadcom STB (BCM7XXX) SoCs.
...@@ -172,6 +172,7 @@ config GPIO_ETRAXFS ...@@ -172,6 +172,7 @@ config GPIO_ETRAXFS
depends on CRIS || COMPILE_TEST depends on CRIS || COMPILE_TEST
depends on OF depends on OF
select GPIO_GENERIC select GPIO_GENERIC
select GPIOLIB_IRQCHIP
help help
Say yes here to support the GPIO controller on Axis ETRAX FS SoCs. Say yes here to support the GPIO controller on Axis ETRAX FS SoCs.
...@@ -308,7 +309,6 @@ config GPIO_MVEBU ...@@ -308,7 +309,6 @@ config GPIO_MVEBU
def_bool y def_bool y
depends on PLAT_ORION depends on PLAT_ORION
depends on OF depends on OF
select GPIO_GENERIC
select GENERIC_IRQ_CHIP select GENERIC_IRQ_CHIP
config GPIO_MXC config GPIO_MXC
...@@ -1005,6 +1005,12 @@ config GPIO_MC33880 ...@@ -1005,6 +1005,12 @@ config GPIO_MC33880
SPI driver for Freescale MC33880 high-side/low-side switch. SPI driver for Freescale MC33880 high-side/low-side switch.
This provides GPIO interface supporting inputs and outputs. 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 endmenu
menu "USB GPIO expanders" menu "USB GPIO expanders"
......
...@@ -117,3 +117,4 @@ obj-$(CONFIG_GPIO_XLP) += gpio-xlp.o ...@@ -117,3 +117,4 @@ obj-$(CONFIG_GPIO_XLP) += gpio-xlp.o
obj-$(CONFIG_GPIO_XTENSA) += gpio-xtensa.o obj-$(CONFIG_GPIO_XTENSA) += gpio-xtensa.o
obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o
obj-$(CONFIG_GPIO_ZYNQ) += gpio-zynq.o obj-$(CONFIG_GPIO_ZYNQ) += gpio-zynq.o
obj-$(CONFIG_GPIO_ZX) += gpio-zx.o
...@@ -59,13 +59,13 @@ static int devm_gpiod_match_array(struct device *dev, void *res, void *data) ...@@ -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 * automatically disposed on driver detach. See gpiod_get() for detailed
* information about behavior and return values. * 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, const char *con_id,
enum gpiod_flags flags) enum gpiod_flags flags)
{ {
return devm_gpiod_get_index(dev, con_id, 0, 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() * devm_gpiod_get_optional - Resource-managed gpiod_get_optional()
...@@ -77,13 +77,13 @@ EXPORT_SYMBOL(__devm_gpiod_get); ...@@ -77,13 +77,13 @@ EXPORT_SYMBOL(__devm_gpiod_get);
* are automatically disposed on driver detach. See gpiod_get_optional() for * are automatically disposed on driver detach. See gpiod_get_optional() for
* detailed information about behavior and return values. * 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, const char *con_id,
enum gpiod_flags flags) enum gpiod_flags flags)
{ {
return devm_gpiod_get_index_optional(dev, con_id, 0, 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() * devm_gpiod_get_index - Resource-managed gpiod_get_index()
...@@ -96,7 +96,7 @@ EXPORT_SYMBOL(__devm_gpiod_get_optional); ...@@ -96,7 +96,7 @@ EXPORT_SYMBOL(__devm_gpiod_get_optional);
* automatically disposed on driver detach. See gpiod_get_index() for detailed * automatically disposed on driver detach. See gpiod_get_index() for detailed
* information about behavior and return values. * 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, const char *con_id,
unsigned int idx, unsigned int idx,
enum gpiod_flags flags) enum gpiod_flags flags)
...@@ -120,7 +120,7 @@ struct gpio_desc *__must_check __devm_gpiod_get_index(struct device *dev, ...@@ -120,7 +120,7 @@ struct gpio_desc *__must_check __devm_gpiod_get_index(struct device *dev,
return desc; 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 * devm_get_gpiod_from_child - get a GPIO descriptor from a device's child node
...@@ -182,7 +182,7 @@ EXPORT_SYMBOL(devm_get_gpiod_from_child); ...@@ -182,7 +182,7 @@ EXPORT_SYMBOL(devm_get_gpiod_from_child);
* gpiod_get_index_optional() for detailed information about behavior and * gpiod_get_index_optional() for detailed information about behavior and
* return values. * 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, const char *con_id,
unsigned int index, unsigned int index,
enum gpiod_flags flags) enum gpiod_flags flags)
...@@ -197,7 +197,7 @@ struct gpio_desc *__must_check __devm_gpiod_get_index_optional(struct device *de ...@@ -197,7 +197,7 @@ struct gpio_desc *__must_check __devm_gpiod_get_index_optional(struct device *de
return desc; 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() * devm_gpiod_get_array - Resource-managed gpiod_get_array()
......
...@@ -129,7 +129,7 @@ static int mmio_74xx_gpio_probe(struct platform_device *pdev) ...@@ -129,7 +129,7 @@ static int mmio_74xx_gpio_probe(struct platform_device *pdev)
if (IS_ERR(dat)) if (IS_ERR(dat))
return PTR_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, err = bgpio_init(&priv->bgc, &pdev->dev,
DIV_ROUND_UP(MMIO_74XX_BIT_CNT(priv->flags), 8), DIV_ROUND_UP(MMIO_74XX_BIT_CNT(priv->flags), 8),
......
...@@ -305,15 +305,7 @@ static int adp5588_irq_setup(struct adp5588_gpio *dev) ...@@ -305,15 +305,7 @@ static int adp5588_irq_setup(struct adp5588_gpio *dev)
irq_set_chip_and_handler(irq, &adp5588_irq_chip, irq_set_chip_and_handler(irq, &adp5588_irq_chip,
handle_level_irq); handle_level_irq);
irq_set_nested_thread(irq, 1); irq_set_nested_thread(irq, 1);
#ifdef CONFIG_ARM irq_modify_status(irq, IRQ_NOREQUEST, IRQ_NOPROBE);
/*
* 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
} }
ret = request_threaded_irq(client->irq, ret = request_threaded_irq(client->irq,
......
...@@ -338,9 +338,9 @@ static int altera_gpio_remove(struct platform_device *pdev) ...@@ -338,9 +338,9 @@ static int altera_gpio_remove(struct platform_device *pdev)
{ {
struct altera_gpio_chip *altera_gc = platform_get_drvdata(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[] = { static const struct of_device_id altera_gpio_of_match[] = {
......
...@@ -438,7 +438,7 @@ static void bcm_kona_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) ...@@ -438,7 +438,7 @@ static void bcm_kona_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
void __iomem *reg_base; void __iomem *reg_base;
int bit, bank_id; int bit, bank_id;
unsigned long sta; 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); struct irq_chip *chip = irq_desc_get_chip(desc);
chained_irq_enter(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, ...@@ -525,11 +525,7 @@ static int bcm_kona_gpio_irq_map(struct irq_domain *d, unsigned int irq,
return ret; return ret;
irq_set_lockdep_class(irq, &gpio_lock_class); irq_set_lockdep_class(irq, &gpio_lock_class);
irq_set_chip_and_handler(irq, &bcm_gpio_irq_chip, handle_simple_irq); 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); irq_set_noprobe(irq);
#endif
return 0; return 0;
} }
...@@ -644,17 +640,6 @@ static int bcm_kona_gpio_probe(struct platform_device *pdev) ...@@ -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); dev_err(dev, "Couldn't add GPIO chip -- %d\n", ret);
goto err_irq_domain; 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++) { for (i = 0; i < kona_gpio->num_bank; i++) {
bank = &kona_gpio->banks[i]; bank = &kona_gpio->banks[i];
irq_set_chained_handler_and_data(bank->irq, irq_set_chained_handler_and_data(bank->irq,
......
...@@ -17,6 +17,10 @@ ...@@ -17,6 +17,10 @@
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/basic_mmio_gpio.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_BANK_SIZE 0x20
#define GIO_ODEN(bank) (((bank) * GIO_BANK_SIZE) + 0x00) #define GIO_ODEN(bank) (((bank) * GIO_BANK_SIZE) + 0x00)
...@@ -34,14 +38,18 @@ struct brcmstb_gpio_bank { ...@@ -34,14 +38,18 @@ struct brcmstb_gpio_bank {
struct bgpio_chip bgc; struct bgpio_chip bgc;
struct brcmstb_gpio_priv *parent_priv; struct brcmstb_gpio_priv *parent_priv;
u32 width; u32 width;
struct irq_chip irq_chip;
}; };
struct brcmstb_gpio_priv { struct brcmstb_gpio_priv {
struct list_head bank_list; struct list_head bank_list;
void __iomem *reg_base; void __iomem *reg_base;
int num_banks;
struct platform_device *pdev; struct platform_device *pdev;
int parent_irq;
int gpio_base; int gpio_base;
bool can_wake;
int parent_wake_irq;
struct notifier_block reboot_notifier;
}; };
#define MAX_GPIO_PER_BANK 32 #define MAX_GPIO_PER_BANK 32
...@@ -63,6 +71,203 @@ brcmstb_gpio_gc_to_priv(struct gpio_chip *gc) ...@@ -63,6 +71,203 @@ brcmstb_gpio_gc_to_priv(struct gpio_chip *gc)
return bank->parent_priv; 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 */ /* Make sure that the number of banks matches up between properties */
static int brcmstb_gpio_sanity_check_banks(struct device *dev, static int brcmstb_gpio_sanity_check_banks(struct device *dev,
struct device_node *np, struct resource *res) struct device_node *np, struct resource *res)
...@@ -100,7 +305,13 @@ static int brcmstb_gpio_remove(struct platform_device *pdev) ...@@ -100,7 +305,13 @@ static int brcmstb_gpio_remove(struct platform_device *pdev)
bank = list_entry(pos, struct brcmstb_gpio_bank, node); bank = list_entry(pos, struct brcmstb_gpio_bank, node);
ret = bgpio_remove(&bank->bgc); ret = bgpio_remove(&bank->bgc);
if (ret) 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; return ret;
} }
...@@ -121,7 +332,7 @@ static int brcmstb_gpio_of_xlate(struct gpio_chip *gc, ...@@ -121,7 +332,7 @@ static int brcmstb_gpio_of_xlate(struct gpio_chip *gc,
return -EINVAL; return -EINVAL;
offset = gpiospec->args[0] - (gc->base - priv->gpio_base); offset = gpiospec->args[0] - (gc->base - priv->gpio_base);
if (offset >= gc->ngpio) if (offset >= gc->ngpio || offset < 0)
return -EINVAL; return -EINVAL;
if (unlikely(offset >= bank->width)) { if (unlikely(offset >= bank->width)) {
...@@ -136,6 +347,65 @@ static int brcmstb_gpio_of_xlate(struct gpio_chip *gc, ...@@ -136,6 +347,65 @@ static int brcmstb_gpio_of_xlate(struct gpio_chip *gc,
return offset; 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) static int brcmstb_gpio_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
...@@ -146,6 +416,7 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) ...@@ -146,6 +416,7 @@ static int brcmstb_gpio_probe(struct platform_device *pdev)
struct property *prop; struct property *prop;
const __be32 *p; const __be32 *p;
u32 bank_width; u32 bank_width;
int num_banks = 0;
int err; int err;
static int gpio_base; static int gpio_base;
...@@ -164,6 +435,16 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) ...@@ -164,6 +435,16 @@ static int brcmstb_gpio_probe(struct platform_device *pdev)
priv->reg_base = reg_base; priv->reg_base = reg_base;
priv->pdev = pdev; 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)) if (brcmstb_gpio_sanity_check_banks(dev, np, res))
return -EINVAL; return -EINVAL;
...@@ -180,7 +461,7 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) ...@@ -180,7 +461,7 @@ static int brcmstb_gpio_probe(struct platform_device *pdev)
} }
bank->parent_priv = priv; bank->parent_priv = priv;
bank->id = priv->num_banks; bank->id = num_banks;
if (bank_width <= 0 || bank_width > MAX_GPIO_PER_BANK) { if (bank_width <= 0 || bank_width > MAX_GPIO_PER_BANK) {
dev_err(dev, "Invalid bank width %d\n", bank_width); dev_err(dev, "Invalid bank width %d\n", bank_width);
goto fail; goto fail;
...@@ -212,6 +493,12 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) ...@@ -212,6 +493,12 @@ static int brcmstb_gpio_probe(struct platform_device *pdev)
/* not all ngpio lines are valid, will use bank width later */ /* not all ngpio lines are valid, will use bank width later */
gc->ngpio = MAX_GPIO_PER_BANK; 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); err = gpiochip_add(gc);
if (err) { if (err) {
dev_err(dev, "Could not add gpiochip for bank %d\n", dev_err(dev, "Could not add gpiochip for bank %d\n",
...@@ -219,17 +506,24 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) ...@@ -219,17 +506,24 @@ static int brcmstb_gpio_probe(struct platform_device *pdev)
goto fail; goto fail;
} }
gpio_base += gc->ngpio; 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, dev_dbg(dev, "bank=%d, base=%d, ngpio=%d, width=%d\n", bank->id,
gc->base, gc->ngpio, bank->width); gc->base, gc->ngpio, bank->width);
/* Everything looks good, so add bank to list */ /* Everything looks good, so add bank to list */
list_add(&bank->node, &priv->bank_list); list_add(&bank->node, &priv->bank_list);
priv->num_banks++; num_banks++;
} }
dev_info(dev, "Registered %d banks (GPIO(s): %d-%d)\n", 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; return 0;
......
...@@ -65,11 +65,11 @@ static struct davinci_gpio_regs __iomem *gpio2regs(unsigned gpio) ...@@ -65,11 +65,11 @@ static struct davinci_gpio_regs __iomem *gpio2regs(unsigned gpio)
return ptr; 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; 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; return g;
} }
...@@ -287,7 +287,7 @@ static int davinci_gpio_probe(struct platform_device *pdev) ...@@ -287,7 +287,7 @@ static int davinci_gpio_probe(struct platform_device *pdev)
static void gpio_irq_disable(struct irq_data *d) 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); u32 mask = (u32) irq_data_get_irq_handler_data(d);
writel_relaxed(mask, &g->clr_falling); writel_relaxed(mask, &g->clr_falling);
...@@ -296,7 +296,7 @@ static void gpio_irq_disable(struct irq_data *d) ...@@ -296,7 +296,7 @@ static void gpio_irq_disable(struct irq_data *d)
static void gpio_irq_enable(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); u32 mask = (u32) irq_data_get_irq_handler_data(d);
unsigned status = irqd_get_trigger_type(d); unsigned status = irqd_get_trigger_type(d);
...@@ -327,8 +327,9 @@ static struct irq_chip gpio_irqchip = { ...@@ -327,8 +327,9 @@ static struct irq_chip gpio_irqchip = {
}; };
static void 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; struct davinci_gpio_regs __iomem *g;
u32 mask = 0xffff; u32 mask = 0xffff;
struct davinci_gpio_controller *d; struct davinci_gpio_controller *d;
...@@ -396,7 +397,7 @@ static int gpio_irq_type_unbanked(struct irq_data *data, unsigned trigger) ...@@ -396,7 +397,7 @@ static int gpio_irq_type_unbanked(struct irq_data *data, unsigned trigger)
struct davinci_gpio_regs __iomem *g; struct davinci_gpio_regs __iomem *g;
u32 mask; 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; g = (struct davinci_gpio_regs __iomem *)d->regs;
mask = __gpio_mask(data->irq - d->gpio_irq); mask = __gpio_mask(data->irq - d->gpio_irq);
...@@ -422,7 +423,6 @@ davinci_gpio_irq_map(struct irq_domain *d, unsigned int 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_irq_type(irq, IRQ_TYPE_NONE);
irq_set_chip_data(irq, (__force void *)g); irq_set_chip_data(irq, (__force void *)g);
irq_set_handler_data(irq, (void *)__gpio_mask(hw)); irq_set_handler_data(irq, (void *)__gpio_mask(hw));
set_irq_flags(irq, IRQF_VALID);
return 0; return 0;
} }
...@@ -545,7 +545,7 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) ...@@ -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].chip.to_irq = gpio_to_irq_unbanked;
chips[0].gpio_irq = bank_irq; chips[0].gpio_irq = bank_irq;
chips[0].gpio_unbanked = pdata->gpio_unbanked; chips[0].gpio_unbanked = pdata->gpio_unbanked;
binten = BIT(0); binten = GENMASK(pdata->gpio_unbanked / 16, 0);
/* AINTC handles mask/unmask; GPIO handles triggering */ /* AINTC handles mask/unmask; GPIO handles triggering */
irq = bank_irq; irq = bank_irq;
......
...@@ -149,7 +149,7 @@ static u32 dwapb_do_irq(struct dwapb_gpio *gpio) ...@@ -149,7 +149,7 @@ static u32 dwapb_do_irq(struct dwapb_gpio *gpio)
static void dwapb_irq_handler(u32 irq, struct irq_desc *desc) 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); struct irq_chip *chip = irq_desc_get_chip(desc);
dwapb_do_irq(gpio); dwapb_do_irq(gpio);
......
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pinctrl/consumer.h> #include <linux/pinctrl/consumer.h>
#include <linux/platform_data/gpio-em.h>
struct em_gio_priv { struct em_gio_priv {
void __iomem *base0; void __iomem *base0;
...@@ -262,7 +261,6 @@ static int em_gio_irq_domain_map(struct irq_domain *h, unsigned int irq, ...@@ -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_data(irq, h->host_data);
irq_set_chip_and_handler(irq, &p->irq_chip, handle_level_irq); irq_set_chip_and_handler(irq, &p->irq_chip, handle_level_irq);
set_irq_flags(irq, IRQF_VALID); /* kill me now */
return 0; return 0;
} }
...@@ -273,13 +271,12 @@ static const struct irq_domain_ops em_gio_irq_domain_ops = { ...@@ -273,13 +271,12 @@ static const struct irq_domain_ops em_gio_irq_domain_ops = {
static int em_gio_probe(struct platform_device *pdev) 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 em_gio_priv *p;
struct resource *io[2], *irq[2]; struct resource *io[2], *irq[2];
struct gpio_chip *gpio_chip; struct gpio_chip *gpio_chip;
struct irq_chip *irq_chip; struct irq_chip *irq_chip;
const char *name = dev_name(&pdev->dev); const char *name = dev_name(&pdev->dev);
unsigned int ngpios;
int ret; int ret;
p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL); p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
...@@ -319,20 +316,12 @@ static int em_gio_probe(struct platform_device *pdev) ...@@ -319,20 +316,12 @@ static int em_gio_probe(struct platform_device *pdev)
goto err0; goto err0;
} }
if (!pdata) { if (of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios)) {
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"); dev_err(&pdev->dev, "Missing ngpios OF property\n");
ret = -EINVAL; ret = -EINVAL;
goto err0; goto err0;
} }
pdata->gpio_base = -1;
}
gpio_chip = &p->gpio_chip; gpio_chip = &p->gpio_chip;
gpio_chip->of_node = pdev->dev.of_node; gpio_chip->of_node = pdev->dev.of_node;
gpio_chip->direction_input = em_gio_direction_input; gpio_chip->direction_input = em_gio_direction_input;
...@@ -345,8 +334,8 @@ static int em_gio_probe(struct platform_device *pdev) ...@@ -345,8 +334,8 @@ static int em_gio_probe(struct platform_device *pdev)
gpio_chip->label = name; gpio_chip->label = name;
gpio_chip->dev = &pdev->dev; gpio_chip->dev = &pdev->dev;
gpio_chip->owner = THIS_MODULE; gpio_chip->owner = THIS_MODULE;
gpio_chip->base = pdata->gpio_base; gpio_chip->base = -1;
gpio_chip->ngpio = pdata->number_of_pins; gpio_chip->ngpio = ngpios;
irq_chip = &p->irq_chip; irq_chip = &p->irq_chip;
irq_chip->name = name; irq_chip->name = name;
...@@ -357,9 +346,7 @@ static int em_gio_probe(struct platform_device *pdev) ...@@ -357,9 +346,7 @@ static int em_gio_probe(struct platform_device *pdev)
irq_chip->irq_release_resources = em_gio_irq_relres; irq_chip->irq_release_resources = em_gio_irq_relres;
irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND; irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND;
p->irq_domain = irq_domain_add_simple(pdev->dev.of_node, p->irq_domain = irq_domain_add_simple(pdev->dev.of_node, ngpios, 0,
pdata->number_of_pins,
pdata->irq_base,
&em_gio_irq_domain_ops, p); &em_gio_irq_domain_ops, p);
if (!p->irq_domain) { if (!p->irq_domain) {
ret = -ENXIO; ret = -ENXIO;
...@@ -387,12 +374,6 @@ static int em_gio_probe(struct platform_device *pdev) ...@@ -387,12 +374,6 @@ static int em_gio_probe(struct platform_device *pdev)
goto err1; 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; return 0;
err1: err1:
......
...@@ -100,13 +100,15 @@ static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc) ...@@ -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: * 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}) * 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 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; 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) ...@@ -208,7 +210,7 @@ static int ep93xx_gpio_irq_type(struct irq_data *d, unsigned int type)
return -EINVAL; return -EINVAL;
} }
__irq_set_handler_locked(d->irq, handler); irq_set_handler_locked(d, handler);
gpio_int_enabled[port] |= port_mask; gpio_int_enabled[port] |= port_mask;
...@@ -234,7 +236,7 @@ static void ep93xx_gpio_init_irq(void) ...@@ -234,7 +236,7 @@ static void ep93xx_gpio_init_irq(void)
gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) { gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) {
irq_set_chip_and_handler(gpio_irq, &ep93xx_gpio_irq_chip, irq_set_chip_and_handler(gpio_irq, &ep93xx_gpio_irq_chip,
handle_level_irq); 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, irq_set_chained_handler(IRQ_EP93XX_GPIO_AB,
......
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/gpio/driver.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/basic_mmio_gpio.h> #include <linux/basic_mmio_gpio.h>
...@@ -13,6 +15,7 @@ ...@@ -13,6 +15,7 @@
#define ETRAX_FS_rw_intr_mask 16 #define ETRAX_FS_rw_intr_mask 16
#define ETRAX_FS_rw_ack_intr 20 #define ETRAX_FS_rw_ack_intr 20
#define ETRAX_FS_r_intr 24 #define ETRAX_FS_r_intr 24
#define ETRAX_FS_r_masked_intr 28
#define ETRAX_FS_rw_pb_dout 32 #define ETRAX_FS_rw_pb_dout 32
#define ETRAX_FS_r_pb_din 36 #define ETRAX_FS_r_pb_din 36
#define ETRAX_FS_rw_pb_oe 40 #define ETRAX_FS_rw_pb_oe 40
...@@ -26,6 +29,48 @@ ...@@ -26,6 +29,48 @@
#define ETRAX_FS_r_pe_din 84 #define ETRAX_FS_r_pe_din 84
#define ETRAX_FS_rw_pe_oe 88 #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 { struct etraxfs_gpio_port {
const char *label; const char *label;
unsigned int oe; unsigned int oe;
...@@ -37,6 +82,12 @@ struct etraxfs_gpio_port { ...@@ -37,6 +82,12 @@ struct etraxfs_gpio_port {
struct etraxfs_gpio_info { struct etraxfs_gpio_info {
unsigned int num_ports; unsigned int num_ports;
const struct etraxfs_gpio_port *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[] = { static const struct etraxfs_gpio_port etraxfs_gpio_etraxfs_ports[] = {
...@@ -80,8 +131,56 @@ 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 = { static const struct etraxfs_gpio_info etraxfs_gpio_etraxfs = {
.num_ports = ARRAY_SIZE(etraxfs_gpio_etraxfs_ports), .num_ports = ARRAY_SIZE(etraxfs_gpio_etraxfs_ports),
.ports = 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, static int etraxfs_gpio_of_xlate(struct gpio_chip *gc,
const struct of_phandle_args *gpiospec, const struct of_phandle_args *gpiospec,
u32 *flags) u32 *flags)
...@@ -90,7 +189,7 @@ static int etraxfs_gpio_of_xlate(struct gpio_chip *gc, ...@@ -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 * Port numbers are A to E, and the properties are integers, so we
* specify them as 0xA - 0xE. * 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 -EINVAL;
return of_gpio_simple_xlate(gc, gpiospec, flags); return of_gpio_simple_xlate(gc, gpiospec, flags);
...@@ -101,24 +200,174 @@ static const struct of_device_id etraxfs_gpio_of_table[] = { ...@@ -101,24 +200,174 @@ static const struct of_device_id etraxfs_gpio_of_table[] = {
.compatible = "axis,etraxfs-gio", .compatible = "axis,etraxfs-gio",
.data = &etraxfs_gpio_etraxfs, .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) static int etraxfs_gpio_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
const struct etraxfs_gpio_info *info; const struct etraxfs_gpio_info *info;
const struct of_device_id *match; const struct of_device_id *match;
struct bgpio_chip *chips; struct etraxfs_gpio_block *block;
struct resource *res; struct etraxfs_gpio_chip *chips;
struct resource *res, *irq;
bool allportsirq = false;
void __iomem *regs; void __iomem *regs;
int ret; int ret;
int i; int i;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
regs = devm_ioremap_resource(dev, res); regs = devm_ioremap_resource(dev, res);
if (!regs) if (IS_ERR(regs))
return -ENOMEM; return PTR_ERR(regs);
match = of_match_node(etraxfs_gpio_of_table, dev->of_node); match = of_match_node(etraxfs_gpio_of_table, dev->of_node);
if (!match) if (!match)
...@@ -130,19 +379,57 @@ static int etraxfs_gpio_probe(struct platform_device *pdev) ...@@ -130,19 +379,57 @@ static int etraxfs_gpio_probe(struct platform_device *pdev)
if (!chips) if (!chips)
return -ENOMEM; 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++) { 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]; 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, ret = bgpio_init(bgc, dev, 4,
regs + port->din, /* dat */ dat, set, NULL, dirout, NULL,
regs + port->dout, /* set */ flags);
NULL, /* clr */ if (ret) {
regs + port->oe, /* dirout */ dev_err(dev, "Unable to init port %s\n",
NULL, /* dirin */ port->label);
BGPIOF_UNREADABLE_REG_SET); continue;
if (ret) }
return ret;
bgc->gc.ngpio = port->ngpio; bgc->gc.ngpio = port->ngpio;
bgc->gc.label = port->label; bgc->gc.label = port->label;
...@@ -152,9 +439,21 @@ static int etraxfs_gpio_probe(struct platform_device *pdev) ...@@ -152,9 +439,21 @@ static int etraxfs_gpio_probe(struct platform_device *pdev)
bgc->gc.of_xlate = etraxfs_gpio_of_xlate; bgc->gc.of_xlate = etraxfs_gpio_of_xlate;
ret = gpiochip_add(&bgc->gc); ret = gpiochip_add(&bgc->gc);
if (ret) if (ret) {
dev_err(dev, "Unable to register port %s\n", dev_err(dev, "Unable to register port %s\n",
bgc->gc.label); 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; return 0;
......
...@@ -153,6 +153,10 @@ static int bgpio_get(struct gpio_chip *gc, unsigned int gpio) ...@@ -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)); 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) static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
{ {
struct bgpio_chip *bgc = to_bgpio_chip(gc); 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) ...@@ -279,6 +283,12 @@ static int bgpio_simple_dir_in(struct gpio_chip *gc, unsigned int gpio)
return 0; 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, static int bgpio_simple_dir_out(struct gpio_chip *gc, unsigned int gpio,
int val) int val)
{ {
...@@ -302,6 +312,14 @@ static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) ...@@ -302,6 +312,14 @@ static int bgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
return 0; 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) static int bgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
{ {
struct bgpio_chip *bgc = to_bgpio_chip(gc); 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) ...@@ -351,6 +369,14 @@ static int bgpio_dir_out_inv(struct gpio_chip *gc, unsigned int gpio, int val)
return 0; 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, static int bgpio_setup_accessors(struct device *dev,
struct bgpio_chip *bgc, struct bgpio_chip *bgc,
bool bit_be, bool bit_be,
...@@ -444,6 +470,9 @@ static int bgpio_setup_io(struct bgpio_chip *bgc, ...@@ -444,6 +470,9 @@ static int bgpio_setup_io(struct bgpio_chip *bgc,
bgc->reg_set = set; bgc->reg_set = set;
bgc->gc.set = bgpio_set_set; bgc->gc.set = bgpio_set_set;
bgc->gc.set_multiple = bgpio_set_multiple_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 { } else {
bgc->gc.set = bgpio_set; bgc->gc.set = bgpio_set;
bgc->gc.set_multiple = bgpio_set_multiple; bgc->gc.set_multiple = bgpio_set_multiple;
...@@ -460,7 +489,8 @@ static int bgpio_setup_io(struct bgpio_chip *bgc, ...@@ -460,7 +489,8 @@ static int bgpio_setup_io(struct bgpio_chip *bgc,
static int bgpio_setup_direction(struct bgpio_chip *bgc, static int bgpio_setup_direction(struct bgpio_chip *bgc,
void __iomem *dirout, void __iomem *dirout,
void __iomem *dirin) void __iomem *dirin,
unsigned long flags)
{ {
if (dirout && dirin) { if (dirout && dirin) {
return -EINVAL; return -EINVAL;
...@@ -468,11 +498,16 @@ static int bgpio_setup_direction(struct bgpio_chip *bgc, ...@@ -468,11 +498,16 @@ static int bgpio_setup_direction(struct bgpio_chip *bgc,
bgc->reg_dir = dirout; bgc->reg_dir = dirout;
bgc->gc.direction_output = bgpio_dir_out; bgc->gc.direction_output = bgpio_dir_out;
bgc->gc.direction_input = bgpio_dir_in; bgc->gc.direction_input = bgpio_dir_in;
bgc->gc.get_direction = bgpio_get_dir;
} else if (dirin) { } else if (dirin) {
bgc->reg_dir = dirin; bgc->reg_dir = dirin;
bgc->gc.direction_output = bgpio_dir_out_inv; bgc->gc.direction_output = bgpio_dir_out_inv;
bgc->gc.direction_input = bgpio_dir_in_inv; bgc->gc.direction_input = bgpio_dir_in_inv;
bgc->gc.get_direction = bgpio_get_dir_inv;
} else { } else {
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_output = bgpio_simple_dir_out;
bgc->gc.direction_input = bgpio_simple_dir_in; bgc->gc.direction_input = bgpio_simple_dir_in;
} }
...@@ -525,7 +560,7 @@ int bgpio_init(struct bgpio_chip *bgc, struct device *dev, ...@@ -525,7 +560,7 @@ int bgpio_init(struct bgpio_chip *bgc, struct device *dev,
if (ret) if (ret)
return ret; return ret;
ret = bgpio_setup_direction(bgc, dirout, dirin); ret = bgpio_setup_direction(bgc, dirout, dirin, flags);
if (ret) if (ret)
return ret; return ret;
......
...@@ -104,17 +104,12 @@ static void grgpio_set_imask(struct grgpio_priv *priv, unsigned int offset, ...@@ -104,17 +104,12 @@ static void grgpio_set_imask(struct grgpio_priv *priv, unsigned int offset,
{ {
struct bgpio_chip *bgc = &priv->bgc; struct bgpio_chip *bgc = &priv->bgc;
unsigned long mask = bgc->pin2mask(bgc, offset); unsigned long mask = bgc->pin2mask(bgc, offset);
unsigned long flags;
spin_lock_irqsave(&bgc->lock, flags);
if (val) if (val)
priv->imask |= mask; priv->imask |= mask;
else else
priv->imask &= ~mask; priv->imask &= ~mask;
bgc->write_reg(priv->regs + GRGPIO_IMASK, priv->imask); 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) static int grgpio_to_irq(struct gpio_chip *gc, unsigned offset)
...@@ -180,16 +175,26 @@ static void grgpio_irq_mask(struct irq_data *d) ...@@ -180,16 +175,26 @@ static void grgpio_irq_mask(struct irq_data *d)
{ {
struct grgpio_priv *priv = irq_data_get_irq_chip_data(d); struct grgpio_priv *priv = irq_data_get_irq_chip_data(d);
int offset = d->hwirq; int offset = d->hwirq;
unsigned long flags;
spin_lock_irqsave(&priv->bgc.lock, flags);
grgpio_set_imask(priv, offset, 0); grgpio_set_imask(priv, offset, 0);
spin_unlock_irqrestore(&priv->bgc.lock, flags);
} }
static void grgpio_irq_unmask(struct irq_data *d) static void grgpio_irq_unmask(struct irq_data *d)
{ {
struct grgpio_priv *priv = irq_data_get_irq_chip_data(d); struct grgpio_priv *priv = irq_data_get_irq_chip_data(d);
int offset = d->hwirq; int offset = d->hwirq;
unsigned long flags;
spin_lock_irqsave(&priv->bgc.lock, flags);
grgpio_set_imask(priv, offset, 1); grgpio_set_imask(priv, offset, 1);
spin_unlock_irqrestore(&priv->bgc.lock, flags);
} }
static struct irq_chip grgpio_irq_chip = { static struct irq_chip grgpio_irq_chip = {
...@@ -281,12 +286,7 @@ static int grgpio_irq_map(struct irq_domain *d, unsigned int irq, ...@@ -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_data(irq, priv);
irq_set_chip_and_handler(irq, &grgpio_irq_chip, irq_set_chip_and_handler(irq, &grgpio_irq_chip,
handle_simple_irq); handle_simple_irq);
irq_clear_status_flags(irq, IRQ_NOREQUEST);
#ifdef CONFIG_ARM
set_irq_flags(irq, IRQF_VALID);
#else
irq_set_noprobe(irq); irq_set_noprobe(irq);
#endif
return ret; return ret;
} }
...@@ -301,9 +301,6 @@ static void grgpio_irq_unmap(struct irq_domain *d, unsigned int irq) ...@@ -301,9 +301,6 @@ static void grgpio_irq_unmap(struct irq_domain *d, unsigned int irq)
int ngpio = priv->bgc.gc.ngpio; int ngpio = priv->bgc.gc.ngpio;
int i; int i;
#ifdef CONFIG_ARM
set_irq_flags(irq, 0);
#endif
irq_set_chip_and_handler(irq, NULL, NULL); irq_set_chip_and_handler(irq, NULL, NULL);
irq_set_chip_data(irq, NULL); irq_set_chip_data(irq, NULL);
......
...@@ -685,9 +685,14 @@ static int max732x_probe(struct i2c_client *client, ...@@ -685,9 +685,14 @@ static int max732x_probe(struct i2c_client *client,
mutex_init(&chip->lock); mutex_init(&chip->lock);
max732x_readb(chip, is_group_a(chip, 0), &chip->reg_out[0]); ret = max732x_readb(chip, is_group_a(chip, 0), &chip->reg_out[0]);
if (nr_port > 8) if (ret)
max732x_readb(chip, is_group_a(chip, 8), &chip->reg_out[1]); 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); ret = gpiochip_add(&chip->gpio_chip);
if (ret) if (ret)
......
...@@ -507,11 +507,7 @@ static int mcp23s08_irq_setup(struct mcp23s08 *mcp) ...@@ -507,11 +507,7 @@ static int mcp23s08_irq_setup(struct mcp23s08 *mcp)
irq_set_chip_data(irq, mcp); irq_set_chip_data(irq, mcp);
irq_set_chip(irq, &mcp23s08_irq_chip); irq_set_chip(irq, &mcp23s08_irq_chip);
irq_set_nested_thread(irq, true); irq_set_nested_thread(irq, true);
#ifdef CONFIG_ARM
set_irq_flags(irq, IRQF_VALID);
#else
irq_set_noprobe(irq); irq_set_noprobe(irq);
#endif
} }
return 0; return 0;
} }
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
struct mpc8xxx_gpio_chip { struct mpc8xxx_gpio_chip {
struct of_mm_gpio_chip mm_gc; 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 * 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) ...@@ -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); struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&mpc8xxx_gc->lock, flags); raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
if (val) if (val)
mpc8xxx_gc->data |= mpc8xxx_gpio2mask(gpio); mpc8xxx_gc->data |= mpc8xxx_gpio2mask(gpio);
...@@ -104,7 +104,7 @@ static void mpc8xxx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) ...@@ -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); 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, static void mpc8xxx_gpio_set_multiple(struct gpio_chip *gc,
...@@ -115,7 +115,7 @@ 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; unsigned long flags;
int i; int i;
spin_lock_irqsave(&mpc8xxx_gc->lock, flags); raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
for (i = 0; i < gc->ngpio; i++) { for (i = 0; i < gc->ngpio; i++) {
if (*mask == 0) if (*mask == 0)
...@@ -130,7 +130,7 @@ static void mpc8xxx_gpio_set_multiple(struct gpio_chip *gc, ...@@ -130,7 +130,7 @@ static void mpc8xxx_gpio_set_multiple(struct gpio_chip *gc,
out_be32(mm->regs + GPIO_DAT, mpc8xxx_gc->data); 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) 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) ...@@ -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); struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
unsigned long flags; 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)); 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; return 0;
} }
...@@ -156,11 +156,11 @@ static int mpc8xxx_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val ...@@ -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); 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)); 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; return 0;
} }
...@@ -174,6 +174,15 @@ static int mpc5121_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val ...@@ -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); 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) static int mpc8xxx_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
{ {
struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); 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) ...@@ -206,11 +215,11 @@ static void mpc8xxx_irq_unmask(struct irq_data *d)
struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc; struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
unsigned long flags; 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))); 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) static void mpc8xxx_irq_mask(struct irq_data *d)
...@@ -219,11 +228,11 @@ 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; struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
unsigned long flags; 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))); 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) 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) ...@@ -242,17 +251,17 @@ static int mpc8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
switch (flow_type) { switch (flow_type) {
case IRQ_TYPE_EDGE_FALLING: 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, setbits32(mm->regs + GPIO_ICR,
mpc8xxx_gpio2mask(irqd_to_hwirq(d))); mpc8xxx_gpio2mask(irqd_to_hwirq(d)));
spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
break; break;
case IRQ_TYPE_EDGE_BOTH: 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, clrbits32(mm->regs + GPIO_ICR,
mpc8xxx_gpio2mask(irqd_to_hwirq(d))); mpc8xxx_gpio2mask(irqd_to_hwirq(d)));
spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
break; break;
default: default:
...@@ -282,22 +291,22 @@ static int mpc512x_irq_set_type(struct irq_data *d, unsigned int flow_type) ...@@ -282,22 +291,22 @@ static int mpc512x_irq_set_type(struct irq_data *d, unsigned int flow_type)
switch (flow_type) { switch (flow_type) {
case IRQ_TYPE_EDGE_FALLING: case IRQ_TYPE_EDGE_FALLING:
case IRQ_TYPE_LEVEL_LOW: 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); clrsetbits_be32(reg, 3 << shift, 2 << shift);
spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
break; break;
case IRQ_TYPE_EDGE_RISING: case IRQ_TYPE_EDGE_RISING:
case IRQ_TYPE_LEVEL_HIGH: 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); clrsetbits_be32(reg, 3 << shift, 1 << shift);
spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
break; break;
case IRQ_TYPE_EDGE_BOTH: case IRQ_TYPE_EDGE_BOTH:
spin_lock_irqsave(&mpc8xxx_gc->lock, flags); raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
clrbits32(reg, 3 << shift); clrbits32(reg, 3 << shift);
spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); raw_spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
break; break;
default: default:
...@@ -312,17 +321,13 @@ static struct irq_chip mpc8xxx_irq_chip = { ...@@ -312,17 +321,13 @@ static struct irq_chip mpc8xxx_irq_chip = {
.irq_unmask = mpc8xxx_irq_unmask, .irq_unmask = mpc8xxx_irq_unmask,
.irq_mask = mpc8xxx_irq_mask, .irq_mask = mpc8xxx_irq_mask,
.irq_ack = mpc8xxx_irq_ack, .irq_ack = mpc8xxx_irq_ack,
/* this might get overwritten in mpc8xxx_probe() */
.irq_set_type = mpc8xxx_irq_set_type, .irq_set_type = mpc8xxx_irq_set_type,
}; };
static int mpc8xxx_gpio_irq_map(struct irq_domain *h, unsigned int irq, static int mpc8xxx_gpio_irq_map(struct irq_domain *h, unsigned int irq,
irq_hw_number_t hwirq) 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_data(irq, h->host_data);
irq_set_chip_and_handler(irq, &mpc8xxx_irq_chip, handle_level_irq); 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 = { ...@@ -334,11 +339,38 @@ static const struct irq_domain_ops mpc8xxx_gpio_irq_ops = {
.xlate = irq_domain_xlate_twocell, .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,mpc8349-gpio", },
{ .compatible = "fsl,mpc8572-gpio", }, { .compatible = "fsl,mpc8572-gpio", .data = &mpc8572_gpio_devtype, },
{ .compatible = "fsl,mpc8610-gpio", }, { .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,pq3-gpio", },
{ .compatible = "fsl,qoriq-gpio", }, { .compatible = "fsl,qoriq-gpio", },
{} {}
...@@ -351,6 +383,8 @@ static int mpc8xxx_probe(struct platform_device *pdev) ...@@ -351,6 +383,8 @@ static int mpc8xxx_probe(struct platform_device *pdev)
struct of_mm_gpio_chip *mm_gc; struct of_mm_gpio_chip *mm_gc;
struct gpio_chip *gc; struct gpio_chip *gc;
const struct of_device_id *id; const struct of_device_id *id;
const struct mpc8xxx_gpio_devtype *devtype =
of_device_get_match_data(&pdev->dev);
int ret; int ret;
mpc8xxx_gc = devm_kzalloc(&pdev->dev, sizeof(*mpc8xxx_gc), GFP_KERNEL); mpc8xxx_gc = devm_kzalloc(&pdev->dev, sizeof(*mpc8xxx_gc), GFP_KERNEL);
...@@ -359,7 +393,7 @@ static int mpc8xxx_probe(struct platform_device *pdev) ...@@ -359,7 +393,7 @@ static int mpc8xxx_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, mpc8xxx_gc); 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; mm_gc = &mpc8xxx_gc->mm_gc;
gc = &mm_gc->gc; gc = &mm_gc->gc;
...@@ -367,10 +401,18 @@ static int mpc8xxx_probe(struct platform_device *pdev) ...@@ -367,10 +401,18 @@ static int mpc8xxx_probe(struct platform_device *pdev)
mm_gc->save_regs = mpc8xxx_gpio_save_regs; mm_gc->save_regs = mpc8xxx_gpio_save_regs;
gc->ngpio = MPC8XXX_GPIO_PINS; gc->ngpio = MPC8XXX_GPIO_PINS;
gc->direction_input = mpc8xxx_gpio_dir_in; 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; if (!devtype)
gc->get = of_device_is_compatible(np, "fsl,mpc8572-gpio") ? devtype = &mpc8xxx_gpio_devtype_default;
mpc8572_gpio_get : mpc8xxx_gpio_get;
/*
* 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 = mpc8xxx_gpio_set;
gc->set_multiple = mpc8xxx_gpio_set_multiple; gc->set_multiple = mpc8xxx_gpio_set_multiple;
gc->to_irq = mpc8xxx_gpio_to_irq; gc->to_irq = mpc8xxx_gpio_to_irq;
...@@ -396,8 +438,8 @@ static int mpc8xxx_probe(struct platform_device *pdev) ...@@ -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_IER, 0xffffffff);
out_be32(mm_gc->regs + GPIO_IMR, 0); out_be32(mm_gc->regs + GPIO_IMR, 0);
irq_set_handler_data(mpc8xxx_gc->irqn, mpc8xxx_gc); irq_set_chained_handler_and_data(mpc8xxx_gc->irqn,
irq_set_chained_handler(mpc8xxx_gc->irqn, mpc8xxx_gpio_irq_cascade); mpc8xxx_gpio_irq_cascade, mpc8xxx_gc);
return 0; return 0;
} }
...@@ -407,8 +449,7 @@ static int mpc8xxx_remove(struct platform_device *pdev) ...@@ -407,8 +449,7 @@ static int mpc8xxx_remove(struct platform_device *pdev)
struct mpc8xxx_gpio_chip *mpc8xxx_gc = platform_get_drvdata(pdev); struct mpc8xxx_gpio_chip *mpc8xxx_gc = platform_get_drvdata(pdev);
if (mpc8xxx_gc->irq) { if (mpc8xxx_gc->irq) {
irq_set_handler_data(mpc8xxx_gc->irqn, NULL); irq_set_chained_handler_and_data(mpc8xxx_gc->irqn, NULL, NULL);
irq_set_chained_handler(mpc8xxx_gc->irqn, NULL);
irq_domain_remove(mpc8xxx_gc->irq); irq_domain_remove(mpc8xxx_gc->irq);
} }
......
...@@ -187,14 +187,6 @@ static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset) ...@@ -187,14 +187,6 @@ static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
return irq_create_mapping(domain, 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 /* For dual-edge interrupts in software, since the hardware has no
* such support: * such support:
* *
...@@ -238,7 +230,7 @@ static void msm_gpio_update_dual_edge_pos(unsigned gpio) ...@@ -238,7 +230,7 @@ static void msm_gpio_update_dual_edge_pos(unsigned gpio)
static void msm_gpio_irq_ack(struct irq_data *d) 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)); writel(BIT(INTR_STATUS), GPIO_INTR_STATUS(gpio));
if (test_bit(gpio, msm_gpio.dual_edge_irqs)) if (test_bit(gpio, msm_gpio.dual_edge_irqs))
...@@ -247,8 +239,8 @@ static void msm_gpio_irq_ack(struct irq_data *d) ...@@ -247,8 +239,8 @@ static void msm_gpio_irq_ack(struct irq_data *d)
static void msm_gpio_irq_mask(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; unsigned long irq_flags;
int gpio = d->hwirq;
spin_lock_irqsave(&tlmm_lock, irq_flags); spin_lock_irqsave(&tlmm_lock, irq_flags);
writel(TARGET_PROC_NONE, GPIO_INTR_CFG_SU(gpio)); writel(TARGET_PROC_NONE, GPIO_INTR_CFG_SU(gpio));
...@@ -259,8 +251,8 @@ static void msm_gpio_irq_mask(struct irq_data *d) ...@@ -259,8 +251,8 @@ static void msm_gpio_irq_mask(struct irq_data *d)
static void msm_gpio_irq_unmask(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; unsigned long irq_flags;
int gpio = d->hwirq;
spin_lock_irqsave(&tlmm_lock, irq_flags); spin_lock_irqsave(&tlmm_lock, irq_flags);
__set_bit(gpio, msm_gpio.enabled_irqs); __set_bit(gpio, msm_gpio.enabled_irqs);
...@@ -271,8 +263,8 @@ static void msm_gpio_irq_unmask(struct irq_data *d) ...@@ -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) 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; unsigned long irq_flags;
int gpio = d->hwirq;
uint32_t bits; uint32_t bits;
spin_lock_irqsave(&tlmm_lock, irq_flags); 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) ...@@ -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) { if (flow_type & IRQ_TYPE_EDGE_BOTH) {
bits |= BIT(INTR_DECT_CTL); 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) if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
__set_bit(gpio, msm_gpio.dual_edge_irqs); __set_bit(gpio, msm_gpio.dual_edge_irqs);
else else
__clear_bit(gpio, msm_gpio.dual_edge_irqs); __clear_bit(gpio, msm_gpio.dual_edge_irqs);
} else { } else {
bits &= ~BIT(INTR_DECT_CTL); 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); __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) ...@@ -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) 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 (on) {
if (bitmap_empty(msm_gpio.wake_irqs, MAX_NR_GPIO)) 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, ...@@ -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_lockdep_class(irq, &msm_gpio_lock_class);
irq_set_chip_and_handler(irq, &msm_gpio_irq_chip, irq_set_chip_and_handler(irq, &msm_gpio_irq_chip,
handle_level_irq); handle_level_irq);
set_irq_flags(irq, IRQF_VALID);
return 0; return 0;
} }
......
...@@ -458,9 +458,9 @@ static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type) ...@@ -458,9 +458,9 @@ static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type)
return 0; 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); struct irq_chip *chip = irq_desc_get_chip(desc);
u32 cause, type; u32 cause, type;
int i; int i;
...@@ -787,8 +787,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev) ...@@ -787,8 +787,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
if (irq < 0) if (irq < 0)
continue; continue;
irq_set_handler_data(irq, mvchip); irq_set_chained_handler_and_data(irq, mvebu_gpio_irq_handler,
irq_set_chained_handler(irq, mvebu_gpio_irq_handler); mvchip);
} }
mvchip->irqbase = irq_alloc_descs(-1, 0, ngpios, -1); mvchip->irqbase = irq_alloc_descs(-1, 0, ngpios, -1);
......
...@@ -275,8 +275,8 @@ static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat) ...@@ -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) static void mx3_gpio_irq_handler(u32 irq, struct irq_desc *desc)
{ {
u32 irq_stat; u32 irq_stat;
struct mxc_gpio_port *port = irq_get_handler_data(irq); struct mxc_gpio_port *port = irq_desc_get_handler_data(desc);
struct irq_chip *chip = irq_get_chip(irq); struct irq_chip *chip = irq_desc_get_chip(desc);
chained_irq_enter(chip, desc); chained_irq_enter(chip, desc);
...@@ -292,7 +292,7 @@ static void mx2_gpio_irq_handler(u32 irq, struct irq_desc *desc) ...@@ -292,7 +292,7 @@ static void mx2_gpio_irq_handler(u32 irq, struct irq_desc *desc)
{ {
u32 irq_msk, irq_stat; u32 irq_msk, irq_stat;
struct mxc_gpio_port *port; 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); chained_irq_enter(chip, desc);
...@@ -339,7 +339,7 @@ static int gpio_set_wake_irq(struct irq_data *d, u32 enable) ...@@ -339,7 +339,7 @@ static int gpio_set_wake_irq(struct irq_data *d, u32 enable)
return 0; 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_generic *gc;
struct irq_chip_type *ct; struct irq_chip_type *ct;
...@@ -354,6 +354,7 @@ static void __init mxc_gpio_init_gc(struct mxc_gpio_port *port, int irq_base) ...@@ -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_unmask = irq_gc_mask_set_bit;
ct->chip.irq_set_type = gpio_set_irq_type; ct->chip.irq_set_type = gpio_set_irq_type;
ct->chip.irq_set_wake = gpio_set_wake_irq; ct->chip.irq_set_wake = gpio_set_wake_irq;
ct->chip.flags = IRQCHIP_MASK_ON_SUSPEND;
ct->regs.ack = GPIO_ISR; ct->regs.ack = GPIO_ISR;
ct->regs.mask = GPIO_IMR; ct->regs.mask = GPIO_IMR;
......
...@@ -157,7 +157,7 @@ static void mxs_flip_edge(struct mxs_gpio_port *port, u32 gpio) ...@@ -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) static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc)
{ {
u32 irq_stat; 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); desc->irq_data.chip->irq_ack(&desc->irq_data);
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <linux/platform_data/gpio-omap.h> #include <linux/platform_data/gpio-omap.h>
#define OFF_MODE 1 #define OFF_MODE 1
#define OMAP4_GPIO_DEBOUNCINGTIME_MASK 0xFF
static LIST_HEAD(omap_gpio_list); static LIST_HEAD(omap_gpio_list);
...@@ -57,7 +58,7 @@ struct gpio_bank { ...@@ -57,7 +58,7 @@ struct gpio_bank {
u32 saved_datain; u32 saved_datain;
u32 level_mask; u32 level_mask;
u32 toggle_mask; u32 toggle_mask;
spinlock_t lock; raw_spinlock_t lock;
struct gpio_chip chip; struct gpio_chip chip;
struct clk *dbck; struct clk *dbck;
u32 mod_usage; u32 mod_usage;
...@@ -175,7 +176,7 @@ static inline void omap_gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set ...@@ -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) static inline void omap_gpio_dbck_enable(struct gpio_bank *bank)
{ {
if (bank->dbck_enable_mask && !bank->dbck_enabled) { if (bank->dbck_enable_mask && !bank->dbck_enabled) {
clk_prepare_enable(bank->dbck); clk_enable(bank->dbck);
bank->dbck_enabled = true; bank->dbck_enabled = true;
writel_relaxed(bank->dbck_enable_mask, writel_relaxed(bank->dbck_enable_mask,
...@@ -193,7 +194,7 @@ static inline void omap_gpio_dbck_disable(struct gpio_bank *bank) ...@@ -193,7 +194,7 @@ static inline void omap_gpio_dbck_disable(struct gpio_bank *bank)
*/ */
writel_relaxed(0, bank->base + bank->regs->debounce_en); writel_relaxed(0, bank->base + bank->regs->debounce_en);
clk_disable_unprepare(bank->dbck); clk_disable(bank->dbck);
bank->dbck_enabled = false; bank->dbck_enabled = false;
} }
} }
...@@ -204,8 +205,9 @@ static inline void omap_gpio_dbck_disable(struct gpio_bank *bank) ...@@ -204,8 +205,9 @@ static inline void omap_gpio_dbck_disable(struct gpio_bank *bank)
* @offset: the gpio number on this @bank * @offset: the gpio number on this @bank
* @debounce: debounce time to use * @debounce: debounce time to use
* *
* OMAP's debounce time is in 31us steps so we need * OMAP's debounce time is in 31us steps
* to convert and round up to the closest unit. * <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, static void omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset,
unsigned debounce) unsigned debounce)
...@@ -213,34 +215,33 @@ static void omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset, ...@@ -213,34 +215,33 @@ static void omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset,
void __iomem *reg; void __iomem *reg;
u32 val; u32 val;
u32 l; u32 l;
bool enable = !!debounce;
if (!bank->dbck_flag) if (!bank->dbck_flag)
return; return;
if (debounce < 32) if (enable) {
debounce = 0x01; debounce = DIV_ROUND_UP(debounce, 31) - 1;
else if (debounce > 7936) debounce &= OMAP4_GPIO_DEBOUNCINGTIME_MASK;
debounce = 0xff; }
else
debounce = (debounce / 0x1f) - 1;
l = BIT(offset); l = BIT(offset);
clk_prepare_enable(bank->dbck); clk_enable(bank->dbck);
reg = bank->base + bank->regs->debounce; reg = bank->base + bank->regs->debounce;
writel_relaxed(debounce, reg); writel_relaxed(debounce, reg);
reg = bank->base + bank->regs->debounce_en; reg = bank->base + bank->regs->debounce_en;
val = readl_relaxed(reg); val = readl_relaxed(reg);
if (debounce) if (enable)
val |= l; val |= l;
else else
val &= ~l; val &= ~l;
bank->dbck_enable_mask = val; bank->dbck_enable_mask = val;
writel_relaxed(val, reg); writel_relaxed(val, reg);
clk_disable_unprepare(bank->dbck); clk_disable(bank->dbck);
/* /*
* Enable debounce clock per module. * Enable debounce clock per module.
* This call is mandatory because in omap_gpio_request() when * 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) ...@@ -285,7 +286,7 @@ static void omap_clear_gpio_debounce(struct gpio_bank *bank, unsigned offset)
bank->context.debounce = 0; bank->context.debounce = 0;
writel_relaxed(bank->context.debounce, bank->base + writel_relaxed(bank->context.debounce, bank->base +
bank->regs->debounce); bank->regs->debounce);
clk_disable_unprepare(bank->dbck); clk_disable(bank->dbck);
bank->dbck_enabled = false; bank->dbck_enabled = false;
} }
} }
...@@ -498,24 +499,24 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned type) ...@@ -498,24 +499,24 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned type)
if (!BANK_USED(bank)) if (!BANK_USED(bank))
pm_runtime_get_sync(bank->dev); 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); retval = omap_set_gpio_triggering(bank, offset, type);
if (retval) { if (retval) {
spin_unlock_irqrestore(&bank->lock, flags); raw_spin_unlock_irqrestore(&bank->lock, flags);
goto error; goto error;
} }
omap_gpio_init_irq(bank, offset); omap_gpio_init_irq(bank, offset);
if (!omap_gpio_is_input(bank, offset)) { if (!omap_gpio_is_input(bank, offset)) {
spin_unlock_irqrestore(&bank->lock, flags); raw_spin_unlock_irqrestore(&bank->lock, flags);
retval = -EINVAL; retval = -EINVAL;
goto error; 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)) 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)) 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; return 0;
...@@ -636,14 +637,14 @@ static int omap_set_gpio_wakeup(struct gpio_bank *bank, unsigned offset, ...@@ -636,14 +637,14 @@ static int omap_set_gpio_wakeup(struct gpio_bank *bank, unsigned offset,
return -EINVAL; return -EINVAL;
} }
spin_lock_irqsave(&bank->lock, flags); raw_spin_lock_irqsave(&bank->lock, flags);
if (enable) if (enable)
bank->context.wake_en |= gpio_bit; bank->context.wake_en |= gpio_bit;
else else
bank->context.wake_en &= ~gpio_bit; bank->context.wake_en &= ~gpio_bit;
writel_relaxed(bank->context.wake_en, bank->base + bank->regs->wkup_en); 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; return 0;
} }
...@@ -669,10 +670,10 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset) ...@@ -669,10 +670,10 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
if (!BANK_USED(bank)) if (!BANK_USED(bank))
pm_runtime_get_sync(bank->dev); 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); omap_enable_gpio_module(bank, offset);
bank->mod_usage |= BIT(offset); bank->mod_usage |= BIT(offset);
spin_unlock_irqrestore(&bank->lock, flags); raw_spin_unlock_irqrestore(&bank->lock, flags);
return 0; return 0;
} }
...@@ -682,14 +683,14 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset) ...@@ -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); struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip);
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&bank->lock, flags); raw_spin_lock_irqsave(&bank->lock, flags);
bank->mod_usage &= ~(BIT(offset)); bank->mod_usage &= ~(BIT(offset));
if (!LINE_USED(bank->irq_usage, offset)) { if (!LINE_USED(bank->irq_usage, offset)) {
omap_set_gpio_direction(bank, offset, 1); omap_set_gpio_direction(bank, offset, 1);
omap_clear_gpio_debounce(bank, offset); omap_clear_gpio_debounce(bank, offset);
} }
omap_disable_gpio_module(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, * 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) ...@@ -716,7 +717,8 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
struct gpio_bank *bank; struct gpio_bank *bank;
int unmasked = 0; int unmasked = 0;
struct irq_chip *irqchip = irq_desc_get_chip(desc); 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); chained_irq_enter(irqchip, desc);
...@@ -731,6 +733,8 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *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 isr_saved, level_mask = 0;
u32 enabled; u32 enabled;
raw_spin_lock_irqsave(&bank->lock, lock_flags);
enabled = omap_get_gpio_irqbank_mask(bank); enabled = omap_get_gpio_irqbank_mask(bank);
isr_saved = isr = readl_relaxed(isr_reg) & enabled; 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) ...@@ -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_clear_gpio_irqbank(bank, isr_saved & ~level_mask);
omap_enable_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 /* if there is only edge sensitive GPIO pin interrupts
configured, we could unmask GPIO bank interrupt immediately */ configured, we could unmask GPIO bank interrupt immediately */
if (!level_mask && !unmasked) { if (!level_mask && !unmasked) {
...@@ -758,6 +764,7 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) ...@@ -758,6 +764,7 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
bit = __ffs(isr); bit = __ffs(isr);
isr &= ~(BIT(bit)); isr &= ~(BIT(bit));
raw_spin_lock_irqsave(&bank->lock, lock_flags);
/* /*
* Some chips can't respond to both rising and falling * Some chips can't respond to both rising and falling
* at the same time. If this irq was requested with * 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) ...@@ -768,6 +775,8 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
if (bank->toggle_mask & (BIT(bit))) if (bank->toggle_mask & (BIT(bit)))
omap_toggle_gpio_edge_triggering(bank, 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, generic_handle_irq(irq_find_mapping(bank->chip.irqdomain,
bit)); bit));
} }
...@@ -791,7 +800,7 @@ static unsigned int omap_gpio_irq_startup(struct irq_data *d) ...@@ -791,7 +800,7 @@ static unsigned int omap_gpio_irq_startup(struct irq_data *d)
if (!BANK_USED(bank)) if (!BANK_USED(bank))
pm_runtime_get_sync(bank->dev); 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)) if (!LINE_USED(bank->mod_usage, offset))
omap_set_gpio_direction(bank, offset, 1); omap_set_gpio_direction(bank, offset, 1);
...@@ -800,12 +809,12 @@ static unsigned int omap_gpio_irq_startup(struct irq_data *d) ...@@ -800,12 +809,12 @@ static unsigned int omap_gpio_irq_startup(struct irq_data *d)
omap_enable_gpio_module(bank, offset); omap_enable_gpio_module(bank, offset);
bank->irq_usage |= BIT(offset); bank->irq_usage |= BIT(offset);
spin_unlock_irqrestore(&bank->lock, flags); raw_spin_unlock_irqrestore(&bank->lock, flags);
omap_gpio_unmask_irq(d); omap_gpio_unmask_irq(d);
return 0; return 0;
err: err:
spin_unlock_irqrestore(&bank->lock, flags); raw_spin_unlock_irqrestore(&bank->lock, flags);
if (!BANK_USED(bank)) if (!BANK_USED(bank))
pm_runtime_put(bank->dev); pm_runtime_put(bank->dev);
return -EINVAL; return -EINVAL;
...@@ -817,7 +826,7 @@ static void omap_gpio_irq_shutdown(struct irq_data *d) ...@@ -817,7 +826,7 @@ static void omap_gpio_irq_shutdown(struct irq_data *d)
unsigned long flags; unsigned long flags;
unsigned offset = d->hwirq; unsigned offset = d->hwirq;
spin_lock_irqsave(&bank->lock, flags); raw_spin_lock_irqsave(&bank->lock, flags);
bank->irq_usage &= ~(BIT(offset)); bank->irq_usage &= ~(BIT(offset));
omap_set_gpio_irqenable(bank, offset, 0); omap_set_gpio_irqenable(bank, offset, 0);
omap_clear_gpio_irqstatus(bank, offset); omap_clear_gpio_irqstatus(bank, offset);
...@@ -825,7 +834,7 @@ static void omap_gpio_irq_shutdown(struct irq_data *d) ...@@ -825,7 +834,7 @@ static void omap_gpio_irq_shutdown(struct irq_data *d)
if (!LINE_USED(bank->mod_usage, offset)) if (!LINE_USED(bank->mod_usage, offset))
omap_clear_gpio_debounce(bank, offset); omap_clear_gpio_debounce(bank, offset);
omap_disable_gpio_module(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, * 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) ...@@ -849,10 +858,10 @@ static void omap_gpio_mask_irq(struct irq_data *d)
unsigned offset = d->hwirq; unsigned offset = d->hwirq;
unsigned long flags; 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_irqenable(bank, offset, 0);
omap_set_gpio_triggering(bank, offset, IRQ_TYPE_NONE); 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) static void omap_gpio_unmask_irq(struct irq_data *d)
...@@ -862,7 +871,7 @@ 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); u32 trigger = irqd_get_trigger_type(d);
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&bank->lock, flags); raw_spin_lock_irqsave(&bank->lock, flags);
if (trigger) if (trigger)
omap_set_gpio_triggering(bank, offset, trigger); omap_set_gpio_triggering(bank, offset, trigger);
...@@ -874,7 +883,7 @@ static void omap_gpio_unmask_irq(struct irq_data *d) ...@@ -874,7 +883,7 @@ static void omap_gpio_unmask_irq(struct irq_data *d)
} }
omap_set_gpio_irqenable(bank, offset, 1); 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) ...@@ -887,9 +896,9 @@ static int omap_mpuio_suspend_noirq(struct device *dev)
OMAP_MPUIO_GPIO_MASKIT / bank->stride; OMAP_MPUIO_GPIO_MASKIT / bank->stride;
unsigned long flags; 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); writel_relaxed(0xffff & ~bank->context.wake_en, mask_reg);
spin_unlock_irqrestore(&bank->lock, flags); raw_spin_unlock_irqrestore(&bank->lock, flags);
return 0; return 0;
} }
...@@ -902,9 +911,9 @@ static int omap_mpuio_resume_noirq(struct device *dev) ...@@ -902,9 +911,9 @@ static int omap_mpuio_resume_noirq(struct device *dev)
OMAP_MPUIO_GPIO_MASKIT / bank->stride; OMAP_MPUIO_GPIO_MASKIT / bank->stride;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&bank->lock, flags); raw_spin_lock_irqsave(&bank->lock, flags);
writel_relaxed(bank->context.wake_en, mask_reg); writel_relaxed(bank->context.wake_en, mask_reg);
spin_unlock_irqrestore(&bank->lock, flags); raw_spin_unlock_irqrestore(&bank->lock, flags);
return 0; return 0;
} }
...@@ -950,9 +959,9 @@ static int omap_gpio_get_direction(struct gpio_chip *chip, unsigned offset) ...@@ -950,9 +959,9 @@ static int omap_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
bank = container_of(chip, struct gpio_bank, chip); bank = container_of(chip, struct gpio_bank, chip);
reg = bank->base + bank->regs->direction; 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)); dir = !!(readl_relaxed(reg) & BIT(offset));
spin_unlock_irqrestore(&bank->lock, flags); raw_spin_unlock_irqrestore(&bank->lock, flags);
return dir; return dir;
} }
...@@ -962,9 +971,9 @@ static int omap_gpio_input(struct gpio_chip *chip, unsigned offset) ...@@ -962,9 +971,9 @@ static int omap_gpio_input(struct gpio_chip *chip, unsigned offset)
unsigned long flags; unsigned long flags;
bank = container_of(chip, struct gpio_bank, chip); 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); omap_set_gpio_direction(bank, offset, 1);
spin_unlock_irqrestore(&bank->lock, flags); raw_spin_unlock_irqrestore(&bank->lock, flags);
return 0; return 0;
} }
...@@ -986,10 +995,10 @@ static int omap_gpio_output(struct gpio_chip *chip, unsigned offset, int value) ...@@ -986,10 +995,10 @@ static int omap_gpio_output(struct gpio_chip *chip, unsigned offset, int value)
unsigned long flags; unsigned long flags;
bank = container_of(chip, struct gpio_bank, chip); 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); bank->set_dataout(bank, offset, value);
omap_set_gpio_direction(bank, offset, 0); omap_set_gpio_direction(bank, offset, 0);
spin_unlock_irqrestore(&bank->lock, flags); raw_spin_unlock_irqrestore(&bank->lock, flags);
return 0; return 0;
} }
...@@ -1001,9 +1010,9 @@ static int omap_gpio_debounce(struct gpio_chip *chip, unsigned offset, ...@@ -1001,9 +1010,9 @@ static int omap_gpio_debounce(struct gpio_chip *chip, unsigned offset,
bank = container_of(chip, struct gpio_bank, chip); 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); omap2_set_gpio_debounce(bank, offset, debounce);
spin_unlock_irqrestore(&bank->lock, flags); raw_spin_unlock_irqrestore(&bank->lock, flags);
return 0; return 0;
} }
...@@ -1014,9 +1023,9 @@ static void omap_gpio_set(struct gpio_chip *chip, unsigned offset, int value) ...@@ -1014,9 +1023,9 @@ static void omap_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
unsigned long flags; unsigned long flags;
bank = container_of(chip, struct gpio_bank, chip); 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); 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) ...@@ -1061,10 +1070,6 @@ static void omap_gpio_mod_init(struct gpio_bank *bank)
/* Initialize interface clk ungated, module enabled */ /* Initialize interface clk ungated, module enabled */
if (bank->regs->ctrl) if (bank->regs->ctrl)
writel_relaxed(0, base + 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) 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) ...@@ -1178,13 +1183,16 @@ static int omap_gpio_probe(struct platform_device *pdev)
irqc->irq_set_wake = omap_gpio_wake_enable, irqc->irq_set_wake = omap_gpio_wake_enable,
irqc->name = dev_name(&pdev->dev); irqc->name = dev_name(&pdev->dev);
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); bank->irq = platform_get_irq(pdev, 0);
if (unlikely(!res)) { if (bank->irq <= 0) {
dev_err(dev, "Invalid IRQ resource\n"); if (!bank->irq)
return -ENODEV; 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->dev = dev;
bank->chip.dev = dev; bank->chip.dev = dev;
bank->chip.owner = THIS_MODULE; bank->chip.owner = THIS_MODULE;
...@@ -1213,16 +1221,26 @@ static int omap_gpio_probe(struct platform_device *pdev) ...@@ -1213,16 +1221,26 @@ static int omap_gpio_probe(struct platform_device *pdev)
else else
bank->set_dataout = omap_set_gpio_dataout_mask; bank->set_dataout = omap_set_gpio_dataout_mask;
spin_lock_init(&bank->lock); raw_spin_lock_init(&bank->lock);
/* Static mapping, never released */ /* Static mapping, never released */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
bank->base = devm_ioremap_resource(dev, res); bank->base = devm_ioremap_resource(dev, res);
if (IS_ERR(bank->base)) { if (IS_ERR(bank->base)) {
irq_domain_remove(bank->chip.irqdomain);
return PTR_ERR(bank->base); 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); platform_set_drvdata(pdev, bank);
pm_runtime_enable(bank->dev); pm_runtime_enable(bank->dev);
...@@ -1254,6 +1272,8 @@ static int omap_gpio_remove(struct platform_device *pdev) ...@@ -1254,6 +1272,8 @@ static int omap_gpio_remove(struct platform_device *pdev)
list_del(&bank->node); list_del(&bank->node);
gpiochip_remove(&bank->chip); gpiochip_remove(&bank->chip);
pm_runtime_disable(bank->dev); pm_runtime_disable(bank->dev);
if (bank->dbck_flag)
clk_unprepare(bank->dbck);
return 0; return 0;
} }
...@@ -1271,7 +1291,7 @@ static int omap_gpio_runtime_suspend(struct device *dev) ...@@ -1271,7 +1291,7 @@ static int omap_gpio_runtime_suspend(struct device *dev)
unsigned long flags; unsigned long flags;
u32 wake_low, wake_hi; 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. * Only edges can generate a wakeup event to the PRCM.
...@@ -1324,7 +1344,7 @@ static int omap_gpio_runtime_suspend(struct device *dev) ...@@ -1324,7 +1344,7 @@ static int omap_gpio_runtime_suspend(struct device *dev)
bank->get_context_loss_count(bank->dev); bank->get_context_loss_count(bank->dev);
omap_gpio_dbck_disable(bank); omap_gpio_dbck_disable(bank);
spin_unlock_irqrestore(&bank->lock, flags); raw_spin_unlock_irqrestore(&bank->lock, flags);
return 0; return 0;
} }
...@@ -1339,7 +1359,7 @@ static int omap_gpio_runtime_resume(struct device *dev) ...@@ -1339,7 +1359,7 @@ static int omap_gpio_runtime_resume(struct device *dev)
unsigned long flags; unsigned long flags;
int c; 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 * On the first resume during the probe, the context has not
...@@ -1375,14 +1395,14 @@ static int omap_gpio_runtime_resume(struct device *dev) ...@@ -1375,14 +1395,14 @@ static int omap_gpio_runtime_resume(struct device *dev)
if (c != bank->context_loss_count) { if (c != bank->context_loss_count) {
omap_gpio_restore_context(bank); omap_gpio_restore_context(bank);
} else { } else {
spin_unlock_irqrestore(&bank->lock, flags); raw_spin_unlock_irqrestore(&bank->lock, flags);
return 0; return 0;
} }
} }
} }
if (!bank->workaround_enabled) { if (!bank->workaround_enabled) {
spin_unlock_irqrestore(&bank->lock, flags); raw_spin_unlock_irqrestore(&bank->lock, flags);
return 0; return 0;
} }
...@@ -1437,7 +1457,7 @@ static int omap_gpio_runtime_resume(struct device *dev) ...@@ -1437,7 +1457,7 @@ static int omap_gpio_runtime_resume(struct device *dev)
} }
bank->workaround_enabled = false; bank->workaround_enabled = false;
spin_unlock_irqrestore(&bank->lock, flags); raw_spin_unlock_irqrestore(&bank->lock, flags);
return 0; return 0;
} }
......
...@@ -88,7 +88,6 @@ struct pcf857x { ...@@ -88,7 +88,6 @@ struct pcf857x {
struct gpio_chip chip; struct gpio_chip chip;
struct i2c_client *client; struct i2c_client *client;
struct mutex lock; /* protect 'out' */ struct mutex lock; /* protect 'out' */
spinlock_t slock; /* protect irq demux */
unsigned out; /* software latch */ unsigned out; /* software latch */
unsigned status; /* current status */ unsigned status; /* current status */
unsigned int irq_parent; unsigned int irq_parent;
...@@ -185,23 +184,21 @@ static void pcf857x_set(struct gpio_chip *chip, unsigned offset, int value) ...@@ -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) static irqreturn_t pcf857x_irq(int irq, void *data)
{ {
struct pcf857x *gpio = data; struct pcf857x *gpio = data;
unsigned long change, i, status, flags; unsigned long change, i, status;
status = gpio->read(gpio->client); status = gpio->read(gpio->client);
spin_lock_irqsave(&gpio->slock, flags);
/* /*
* call the interrupt handler iff gpio is used as * call the interrupt handler iff gpio is used as
* interrupt source, just to avoid bad irqs * interrupt source, just to avoid bad irqs
*/ */
mutex_lock(&gpio->lock);
change = (gpio->status ^ status) & gpio->irq_enabled; 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; 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; return IRQ_HANDLED;
} }
...@@ -293,7 +290,6 @@ static int pcf857x_probe(struct i2c_client *client, ...@@ -293,7 +290,6 @@ static int pcf857x_probe(struct i2c_client *client,
return -ENOMEM; return -ENOMEM;
mutex_init(&gpio->lock); mutex_init(&gpio->lock);
spin_lock_init(&gpio->slock);
gpio->chip.base = pdata ? pdata->gpio_base : -1; gpio->chip.base = pdata ? pdata->gpio_base : -1;
gpio->chip.can_sleep = true; gpio->chip.can_sleep = true;
......
...@@ -281,9 +281,9 @@ static int pch_irq_type(struct irq_data *d, unsigned int type) ...@@ -281,9 +281,9 @@ static int pch_irq_type(struct irq_data *d, unsigned int type)
/* And the handler */ /* And the handler */
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) 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)) 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: unlock:
spin_unlock_irqrestore(&chip->spinlock, flags); spin_unlock_irqrestore(&chip->spinlock, flags);
......
...@@ -524,7 +524,7 @@ static int pxa_irq_domain_map(struct irq_domain *d, unsigned int irq, ...@@ -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, irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
handle_edge_irq); handle_edge_irq);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); irq_set_noprobe(irq);
return 0; return 0;
} }
...@@ -643,20 +643,20 @@ static int pxa_gpio_probe(struct platform_device *pdev) ...@@ -643,20 +643,20 @@ static int pxa_gpio_probe(struct platform_device *pdev)
irq = gpio_to_irq(0); irq = gpio_to_irq(0);
irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
handle_edge_irq); handle_edge_irq);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
} }
if (irq1 > 0) { if (irq1 > 0) {
irq = gpio_to_irq(1); irq = gpio_to_irq(1);
irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
handle_edge_irq); 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); for (irq = gpio_to_irq(gpio_offset);
irq <= gpio_to_irq(pxa_last_gpio); irq++) { irq <= gpio_to_irq(pxa_last_gpio); irq++) {
irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
handle_edge_irq); handle_edge_irq);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
} }
} }
......
...@@ -251,17 +251,32 @@ static void gpio_rcar_config_general_input_output_mode(struct gpio_chip *chip, ...@@ -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) 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) 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); pinctrl_free_gpio(chip->base + offset);
/* Set the GPIO as an input to ensure that the next GPIO request won't /* Set the GPIO as an input to ensure that the next GPIO request won't
* drive the GPIO pin as an output. * drive the GPIO pin as an output.
*/ */
gpio_rcar_config_general_input_output_mode(chip, offset, false); 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) 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[] = { ...@@ -326,6 +341,10 @@ static const struct of_device_id gpio_rcar_of_table[] = {
}, { }, {
.compatible = "renesas,gpio-r8a7794", .compatible = "renesas,gpio-r8a7794",
.data = &gpio_rcar_info_gen2, .data = &gpio_rcar_info_gen2,
}, {
.compatible = "renesas,gpio-r8a7795",
/* Gen3 GPIO is identical to Gen2. */
.data = &gpio_rcar_info_gen2,
}, { }, {
.compatible = "renesas,gpio-rcar", .compatible = "renesas,gpio-rcar",
.data = &gpio_rcar_info_gen1, .data = &gpio_rcar_info_gen1,
...@@ -405,7 +424,6 @@ static int gpio_rcar_probe(struct platform_device *pdev) ...@@ -405,7 +424,6 @@ static int gpio_rcar_probe(struct platform_device *pdev)
} }
pm_runtime_enable(dev); pm_runtime_enable(dev);
pm_runtime_get_sync(dev);
io = platform_get_resource(pdev, IORESOURCE_MEM, 0); io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
...@@ -487,7 +505,6 @@ static int gpio_rcar_probe(struct platform_device *pdev) ...@@ -487,7 +505,6 @@ static int gpio_rcar_probe(struct platform_device *pdev)
err1: err1:
gpiochip_remove(gpio_chip); gpiochip_remove(gpio_chip);
err0: err0:
pm_runtime_put(dev);
pm_runtime_disable(dev); pm_runtime_disable(dev);
return ret; return ret;
} }
...@@ -498,7 +515,6 @@ static int gpio_rcar_remove(struct platform_device *pdev) ...@@ -498,7 +515,6 @@ static int gpio_rcar_remove(struct platform_device *pdev)
gpiochip_remove(&p->gpio_chip); gpiochip_remove(&p->gpio_chip);
pm_runtime_put(&pdev->dev);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
return 0; return 0;
} }
......
...@@ -155,7 +155,7 @@ static int sa1100_gpio_irqdomain_map(struct irq_domain *d, ...@@ -155,7 +155,7 @@ static int sa1100_gpio_irqdomain_map(struct irq_domain *d,
{ {
irq_set_chip_and_handler(irq, &sa1100_gpio_irq_chip, irq_set_chip_and_handler(irq, &sa1100_gpio_irq_chip,
handle_edge_irq); handle_edge_irq);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); irq_set_noprobe(irq);
return 0; return 0;
} }
...@@ -173,9 +173,9 @@ static struct irq_domain *sa1100_gpio_irqdomain; ...@@ -173,9 +173,9 @@ static struct irq_domain *sa1100_gpio_irqdomain;
* and call the handler. * and call the handler.
*/ */
static void 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; mask = GEDR;
do { do {
......
...@@ -346,7 +346,7 @@ static void gsta_alloc_irq_chip(struct gsta_gpio *chip) ...@@ -346,7 +346,7 @@ static void gsta_alloc_irq_chip(struct gsta_gpio *chip)
i = chip->irq_base + j; i = chip->irq_base + j;
irq_set_chip_and_handler(i, &ct->chip, ct->handler); irq_set_chip_and_handler(i, &ct->chip, ct->handler);
irq_set_chip_data(i, gc); 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; gc->irq_cnt = i - gc->irq_base;
} }
......
...@@ -102,7 +102,7 @@ static struct gpio_chip template_chip = { ...@@ -102,7 +102,7 @@ static struct gpio_chip template_chip = {
static int tc3589x_gpio_irq_set_type(struct irq_data *d, unsigned int type) 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 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 offset = d->hwirq;
int regoffset = offset / 8; int regoffset = offset / 8;
int mask = 1 << (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) ...@@ -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) static void tc3589x_gpio_irq_lock(struct irq_data *d)
{ {
struct gpio_chip *gc = irq_data_get_irq_chip_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); mutex_lock(&tc3589x_gpio->irq_lock);
} }
...@@ -138,7 +138,7 @@ static void tc3589x_gpio_irq_lock(struct irq_data *d) ...@@ -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) static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d)
{ {
struct gpio_chip *gc = irq_data_get_irq_chip_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; struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
static const u8 regmap[] = { static const u8 regmap[] = {
[REG_IBE] = TC3589x_GPIOIBE0, [REG_IBE] = TC3589x_GPIOIBE0,
...@@ -167,7 +167,7 @@ static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d) ...@@ -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) static void tc3589x_gpio_irq_mask(struct irq_data *d)
{ {
struct gpio_chip *gc = irq_data_get_irq_chip_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 offset = d->hwirq;
int regoffset = offset / 8; int regoffset = offset / 8;
int mask = 1 << (offset % 8); int mask = 1 << (offset % 8);
...@@ -178,7 +178,7 @@ static void tc3589x_gpio_irq_mask(struct irq_data *d) ...@@ -178,7 +178,7 @@ static void tc3589x_gpio_irq_mask(struct irq_data *d)
static void tc3589x_gpio_irq_unmask(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 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 offset = d->hwirq;
int regoffset = offset / 8; int regoffset = offset / 8;
int mask = 1 << (offset % 8); int mask = 1 << (offset % 8);
......
...@@ -252,9 +252,9 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type) ...@@ -252,9 +252,9 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)
tegra_gpio_enable(gpio); tegra_gpio_enable(gpio);
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) 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)) 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; return 0;
} }
...@@ -268,16 +268,14 @@ static void tegra_gpio_irq_shutdown(struct irq_data *d) ...@@ -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) static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
{ {
struct tegra_gpio_bank *bank;
int port; int port;
int pin; int pin;
int unmasked = 0; int unmasked = 0;
struct irq_chip *chip = irq_desc_get_chip(desc); 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); chained_irq_enter(chip, desc);
bank = irq_get_handler_data(irq);
for (port = 0; port < 4; port++) { for (port = 0; port < 4; port++) {
int gpio = tegra_gpio_compose(bank->bank, port, 0); int gpio = tegra_gpio_compose(bank->bank, port, 0);
unsigned long sta = tegra_gpio_readl(GPIO_INT_STA(gpio)) & unsigned long sta = tegra_gpio_readl(GPIO_INT_STA(gpio)) &
...@@ -509,7 +507,6 @@ static int tegra_gpio_probe(struct platform_device *pdev) ...@@ -509,7 +507,6 @@ static int tegra_gpio_probe(struct platform_device *pdev)
irq_set_chip_data(irq, bank); irq_set_chip_data(irq, bank);
irq_set_chip_and_handler(irq, &tegra_gpio_irq_chip, irq_set_chip_and_handler(irq, &tegra_gpio_irq_chip,
handle_simple_irq); handle_simple_irq);
set_irq_flags(irq, IRQF_VALID);
} }
for (i = 0; i < tegra_gpio_bank_count; i++) { for (i = 0; i < tegra_gpio_bank_count; i++) {
......
...@@ -194,11 +194,12 @@ static int timbgpio_irq_type(struct irq_data *d, unsigned trigger) ...@@ -194,11 +194,12 @@ static int timbgpio_irq_type(struct irq_data *d, unsigned trigger)
static void timbgpio_irq(unsigned int irq, struct irq_desc *desc) 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; unsigned long ipr;
int offset; int offset;
desc->irq_data.chip->irq_ack(irq_get_irq_data(irq)); data->chip->irq_ack(data);
ipr = ioread32(tgpio->membase + TGPIO_IPR); ipr = ioread32(tgpio->membase + TGPIO_IPR);
iowrite32(ipr, tgpio->membase + TGPIO_ICR); iowrite32(ipr, tgpio->membase + TGPIO_ICR);
...@@ -294,13 +295,10 @@ static int timbgpio_probe(struct platform_device *pdev) ...@@ -294,13 +295,10 @@ static int timbgpio_probe(struct platform_device *pdev)
irq_set_chip_and_handler(tgpio->irq_base + i, irq_set_chip_and_handler(tgpio->irq_base + i,
&timbgpio_irqchip, handle_simple_irq); &timbgpio_irqchip, handle_simple_irq);
irq_set_chip_data(tgpio->irq_base + i, tgpio); irq_set_chip_data(tgpio->irq_base + i, tgpio);
#ifdef CONFIG_ARM irq_clear_status_flags(tgpio->irq_base + i, IRQ_NOREQUEST | IRQ_NOPROBE);
set_irq_flags(tgpio->irq_base + i, IRQF_VALID | IRQF_PROBE);
#endif
} }
irq_set_handler_data(irq, tgpio); irq_set_chained_handler_and_data(irq, timbgpio_irq, tgpio);
irq_set_chained_handler(irq, timbgpio_irq);
return 0; return 0;
} }
......
...@@ -510,8 +510,8 @@ static int tz1090_gpio_bank_probe(struct tz1090_gpio_bank_info *info) ...@@ -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; gc->chip_types[1].chip.flags = IRQCHIP_MASK_ON_SUSPEND;
/* Setup chained handler for this GPIO bank */ /* Setup chained handler for this GPIO bank */
irq_set_handler_data(bank->irq, bank); irq_set_chained_handler_and_data(bank->irq, tz1090_gpio_irq_handler,
irq_set_chained_handler(bank->irq, tz1090_gpio_irq_handler); bank);
return 0; return 0;
} }
......
...@@ -60,6 +60,8 @@ struct vf610_gpio_port { ...@@ -60,6 +60,8 @@ struct vf610_gpio_port {
#define PORT_INT_EITHER_EDGE 0xb #define PORT_INT_EITHER_EDGE 0xb
#define PORT_INT_LOGIC_ONE 0xc #define PORT_INT_LOGIC_ONE 0xc
static struct irq_chip vf610_gpio_irq_chip;
static const struct of_device_id vf610_gpio_dt_ids[] = { static const struct of_device_id vf610_gpio_dt_ids[] = {
{ .compatible = "fsl,vf610-gpio" }, { .compatible = "fsl,vf610-gpio" },
{ /* sentinel */ } { /* sentinel */ }
...@@ -120,7 +122,7 @@ static int vf610_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, ...@@ -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) 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); struct irq_chip *chip = irq_desc_get_chip(desc);
int pin; int pin;
unsigned long irq_isfr; unsigned long irq_isfr;
...@@ -173,6 +175,11 @@ static int vf610_gpio_irq_set_type(struct irq_data *d, u32 type) ...@@ -173,6 +175,11 @@ static int vf610_gpio_irq_set_type(struct irq_data *d, u32 type)
port->irqc[d->hwirq] = irqc; 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; return 0;
} }
...@@ -263,7 +270,7 @@ static int vf610_gpio_probe(struct platform_device *pdev) ...@@ -263,7 +270,7 @@ static int vf610_gpio_probe(struct platform_device *pdev)
vf610_gpio_writel(~0, port->base + PORT_ISFR); vf610_gpio_writel(~0, port->base + PORT_ISFR);
ret = gpiochip_irqchip_add(gc, &vf610_gpio_irq_chip, 0, ret = gpiochip_irqchip_add(gc, &vf610_gpio_irq_chip, 0,
handle_simple_irq, IRQ_TYPE_NONE); handle_edge_irq, IRQ_TYPE_NONE);
if (ret) { if (ret) {
dev_err(dev, "failed to add irqchip\n"); dev_err(dev, "failed to add irqchip\n");
gpiochip_remove(gc); gpiochip_remove(gc);
......
...@@ -387,7 +387,7 @@ static int xlp_gpio_probe(struct platform_device *pdev) ...@@ -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); irq_base = irq_alloc_descs(-1, XLP_GPIO_IRQ_BASE, gc->ngpio, 0);
if (irq_base < 0) { if (irq_base < 0) {
dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n"); dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n");
return err; return -ENODEV;
} }
err = gpiochip_add(gc); err = gpiochip_add(gc);
......
/*
* 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");
...@@ -441,10 +441,10 @@ static int zynq_gpio_set_irq_type(struct irq_data *irq_data, unsigned int type) ...@@ -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)); gpio->base_addr + ZYNQ_GPIO_INTANY_OFFSET(bank_num));
if (type & IRQ_TYPE_LEVEL_MASK) { 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); &zynq_gpio_level_irqchip, handle_fasteoi_irq, NULL);
} else { } 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); &zynq_gpio_edge_irqchip, handle_level_irq, NULL);
} }
...@@ -518,7 +518,7 @@ static void zynq_gpio_irqhandler(unsigned int irq, struct irq_desc *desc) ...@@ -518,7 +518,7 @@ static void zynq_gpio_irqhandler(unsigned int irq, struct irq_desc *desc)
{ {
u32 int_sts, int_enb; u32 int_sts, int_enb;
unsigned int bank_num; 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); struct irq_chip *irqchip = irq_desc_get_chip(desc);
chained_irq_enter(irqchip, desc); chained_irq_enter(irqchip, desc);
...@@ -782,6 +782,12 @@ static int __init zynq_gpio_init(void) ...@@ -782,6 +782,12 @@ static int __init zynq_gpio_init(void)
} }
postcore_initcall(zynq_gpio_init); 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_AUTHOR("Xilinx Inc.");
MODULE_DESCRIPTION("Zynq GPIO driver"); MODULE_DESCRIPTION("Zynq GPIO driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -136,7 +136,6 @@ static struct gpio_desc *of_get_gpio_hog(struct device_node *np, ...@@ -136,7 +136,6 @@ static struct gpio_desc *of_get_gpio_hog(struct device_node *np,
{ {
struct device_node *chip_np; struct device_node *chip_np;
enum of_gpio_flags xlate_flags; enum of_gpio_flags xlate_flags;
struct gpio_desc *desc;
struct gg_data gg_data = { struct gg_data gg_data = {
.flags = &xlate_flags, .flags = &xlate_flags,
}; };
...@@ -193,9 +192,7 @@ static struct gpio_desc *of_get_gpio_hog(struct device_node *np, ...@@ -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)) if (name && of_property_read_string(np, "line-name", name))
*name = np->name; *name = np->name;
desc = gg_data.out_gpio; return gg_data.out_gpio;
return desc;
} }
/** /**
...@@ -338,7 +335,7 @@ void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc) ...@@ -338,7 +335,7 @@ void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc)
EXPORT_SYMBOL(of_mm_gpiochip_remove); EXPORT_SYMBOL(of_mm_gpiochip_remove);
#ifdef CONFIG_PINCTRL #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 device_node *np = chip->of_node;
struct of_phandle_args pinspec; struct of_phandle_args pinspec;
...@@ -349,7 +346,7 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip) ...@@ -349,7 +346,7 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
struct property *group_names; struct property *group_names;
if (!np) if (!np)
return; return 0;
group_names = of_find_property(np, group_names_propname, NULL); 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) ...@@ -361,11 +358,11 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
pctldev = of_pinctrl_get(pinspec.np); pctldev = of_pinctrl_get(pinspec.np);
if (!pctldev) if (!pctldev)
break; return -EPROBE_DEFER;
if (pinspec.args[2]) { if (pinspec.args[2]) {
if (group_names) { if (group_names) {
ret = of_property_read_string_index(np, of_property_read_string_index(np,
group_names_propname, group_names_propname,
index, &name); index, &name);
if (strlen(name)) { if (strlen(name)) {
...@@ -381,7 +378,7 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip) ...@@ -381,7 +378,7 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
pinspec.args[1], pinspec.args[1],
pinspec.args[2]); pinspec.args[2]);
if (ret) if (ret)
break; return ret;
} else { } else {
/* npins == 0: special range */ /* npins == 0: special range */
if (pinspec.args[1]) { if (pinspec.args[1]) {
...@@ -411,32 +408,41 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip) ...@@ -411,32 +408,41 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
ret = gpiochip_add_pingroup_range(chip, pctldev, ret = gpiochip_add_pingroup_range(chip, pctldev,
pinspec.args[0], name); pinspec.args[0], name);
if (ret) if (ret)
break; return ret;
} }
} }
return 0;
} }
#else #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 #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)) if ((!chip->of_node) && (chip->dev))
chip->of_node = chip->dev->of_node; chip->of_node = chip->dev->of_node;
if (!chip->of_node) if (!chip->of_node)
return; return 0;
if (!chip->of_xlate) { if (!chip->of_xlate) {
chip->of_gpio_n_cells = 2; chip->of_gpio_n_cells = 2;
chip->of_xlate = of_gpio_simple_xlate; 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_node_get(chip->of_node);
of_gpiochip_scan_hogs(chip); of_gpiochip_scan_hogs(chip);
return 0;
} }
void of_gpiochip_remove(struct gpio_chip *chip) void of_gpiochip_remove(struct gpio_chip *chip)
......
...@@ -190,7 +190,7 @@ EXPORT_SYMBOL_GPL(gpiod_get_direction); ...@@ -190,7 +190,7 @@ EXPORT_SYMBOL_GPL(gpiod_get_direction);
*/ */
static int gpiochip_add_to_list(struct gpio_chip *chip) static int gpiochip_add_to_list(struct gpio_chip *chip)
{ {
struct list_head *pos = &gpio_chips; struct list_head *pos;
struct gpio_chip *_chip; struct gpio_chip *_chip;
int err = 0; int err = 0;
...@@ -287,7 +287,13 @@ int gpiochip_add(struct gpio_chip *chip) ...@@ -287,7 +287,13 @@ int gpiochip_add(struct gpio_chip *chip)
INIT_LIST_HEAD(&chip->pin_ranges); INIT_LIST_HEAD(&chip->pin_ranges);
#endif #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); acpi_gpiochip_add(chip);
status = gpiochip_sysfs_register(chip); status = gpiochip_sysfs_register(chip);
...@@ -443,8 +449,8 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip, ...@@ -443,8 +449,8 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
* The parent irqchip is already using the chip_data for this * The parent irqchip is already using the chip_data for this
* irqchip, so our callbacks simply use the handler_data. * irqchip, so our callbacks simply use the handler_data.
*/ */
irq_set_handler_data(parent_irq, gpiochip); irq_set_chained_handler_and_data(parent_irq, parent_handler,
irq_set_chained_handler(parent_irq, parent_handler); gpiochip);
gpiochip->irq_parent = parent_irq; gpiochip->irq_parent = parent_irq;
} }
...@@ -456,12 +462,6 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip, ...@@ -456,12 +462,6 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
} }
EXPORT_SYMBOL_GPL(gpiochip_set_chained_irqchip); 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 * gpiochip_irq_map() - maps an IRQ into a GPIO irqchip
* @d: the irqdomain used by this irqchip * @d: the irqdomain used by this irqchip
...@@ -478,16 +478,17 @@ static int gpiochip_irq_map(struct irq_domain *d, unsigned int irq, ...@@ -478,16 +478,17 @@ static int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,
struct gpio_chip *chip = d->host_data; struct gpio_chip *chip = d->host_data;
irq_set_chip_data(irq, chip); 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); irq_set_chip_and_handler(irq, chip->irqchip, chip->irq_handler);
/* Chips that can sleep need nested thread handlers */ /* Chips that can sleep need nested thread handlers */
if (chip->can_sleep && !chip->irq_not_threaded) if (chip->can_sleep && !chip->irq_not_threaded)
irq_set_nested_thread(irq, 1); irq_set_nested_thread(irq, 1);
#ifdef CONFIG_ARM
set_irq_flags(irq, IRQF_VALID);
#else
irq_set_noprobe(irq); irq_set_noprobe(irq);
#endif
/* /*
* No set-up of the hardware will happen if IRQ_TYPE_NONE * No set-up of the hardware will happen if IRQ_TYPE_NONE
* is passed as default type. * is passed as default type.
...@@ -502,9 +503,6 @@ static void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq) ...@@ -502,9 +503,6 @@ static void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq)
{ {
struct gpio_chip *chip = d->host_data; struct gpio_chip *chip = d->host_data;
#ifdef CONFIG_ARM
set_irq_flags(irq, 0);
#endif
if (chip->can_sleep) if (chip->can_sleep)
irq_set_nested_thread(irq, 0); irq_set_nested_thread(irq, 0);
irq_set_chip_and_handler(irq, NULL, NULL); irq_set_chip_and_handler(irq, NULL, NULL);
...@@ -522,10 +520,14 @@ static int gpiochip_irq_reqres(struct irq_data *d) ...@@ -522,10 +520,14 @@ static int gpiochip_irq_reqres(struct irq_data *d)
{ {
struct gpio_chip *chip = irq_data_get_irq_chip_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)) { if (gpiochip_lock_as_irq(chip, d->hwirq)) {
chip_err(chip, chip_err(chip,
"unable to lock HW IRQ %lu for IRQ\n", "unable to lock HW IRQ %lu for IRQ\n",
d->hwirq); d->hwirq);
module_put(chip->owner);
return -EINVAL; return -EINVAL;
} }
return 0; return 0;
...@@ -536,6 +538,7 @@ static void gpiochip_irq_relres(struct irq_data *d) ...@@ -536,6 +538,7 @@ static void gpiochip_irq_relres(struct irq_data *d)
struct gpio_chip *chip = irq_data_get_irq_chip_data(d); struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
gpiochip_unlock_as_irq(chip, d->hwirq); gpiochip_unlock_as_irq(chip, d->hwirq);
module_put(chip->owner);
} }
static int gpiochip_to_irq(struct gpio_chip *chip, unsigned offset) static int gpiochip_to_irq(struct gpio_chip *chip, unsigned offset)
...@@ -584,6 +587,7 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) ...@@ -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) * @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 * @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. * 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 * This function closely associates a certain irqchip with a certain
* gpiochip, providing an irq domain to translate the local IRQs to * gpiochip, providing an irq domain to translate the local IRQs to
...@@ -599,11 +603,12 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) ...@@ -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 * the pins on the gpiochip can generate a unique IRQ. Everything else
* need to be open coded. * need to be open coded.
*/ */
int gpiochip_irqchip_add(struct gpio_chip *gpiochip, int _gpiochip_irqchip_add(struct gpio_chip *gpiochip,
struct irq_chip *irqchip, struct irq_chip *irqchip,
unsigned int first_irq, unsigned int first_irq,
irq_flow_handler_t handler, irq_flow_handler_t handler,
unsigned int type) unsigned int type,
struct lock_class_key *lock_key)
{ {
struct device_node *of_node; struct device_node *of_node;
unsigned int offset; unsigned int offset;
...@@ -629,6 +634,7 @@ int gpiochip_irqchip_add(struct gpio_chip *gpiochip, ...@@ -629,6 +634,7 @@ int gpiochip_irqchip_add(struct gpio_chip *gpiochip,
gpiochip->irq_handler = handler; gpiochip->irq_handler = handler;
gpiochip->irq_default_type = type; gpiochip->irq_default_type = type;
gpiochip->to_irq = gpiochip_to_irq; gpiochip->to_irq = gpiochip_to_irq;
gpiochip->lock_key = lock_key;
gpiochip->irqdomain = irq_domain_add_simple(of_node, gpiochip->irqdomain = irq_domain_add_simple(of_node,
gpiochip->ngpio, first_irq, gpiochip->ngpio, first_irq,
&gpiochip_domain_ops, gpiochip); &gpiochip_domain_ops, gpiochip);
...@@ -636,8 +642,16 @@ int gpiochip_irqchip_add(struct gpio_chip *gpiochip, ...@@ -636,8 +642,16 @@ int gpiochip_irqchip_add(struct gpio_chip *gpiochip,
gpiochip->irqchip = NULL; gpiochip->irqchip = NULL;
return -EINVAL; return -EINVAL;
} }
/*
* 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_request_resources = gpiochip_irq_reqres;
irqchip->irq_release_resources = gpiochip_irq_relres; irqchip->irq_release_resources = gpiochip_irq_relres;
}
/* /*
* Prepare the mapping since the irqchip shall be orthogonal to * Prepare the mapping since the irqchip shall be orthogonal to
...@@ -658,7 +672,7 @@ int gpiochip_irqchip_add(struct gpio_chip *gpiochip, ...@@ -658,7 +672,7 @@ int gpiochip_irqchip_add(struct gpio_chip *gpiochip,
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(gpiochip_irqchip_add); EXPORT_SYMBOL_GPL(_gpiochip_irqchip_add);
#else /* CONFIG_GPIOLIB_IRQCHIP */ #else /* CONFIG_GPIOLIB_IRQCHIP */
...@@ -671,7 +685,7 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) {} ...@@ -671,7 +685,7 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) {}
/** /**
* gpiochip_add_pingroup_range() - add a range for GPIO <-> pin mapping * gpiochip_add_pingroup_range() - add a range for GPIO <-> pin mapping
* @chip: the gpiochip to add the range for * @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 * @gpio_offset: the start offset in the current gpio_chip number space
* @pin_group: name of the pin group inside the pin controller * @pin_group: name of the pin group inside the pin controller
*/ */
...@@ -1894,12 +1908,12 @@ EXPORT_SYMBOL_GPL(gpiod_count); ...@@ -1894,12 +1908,12 @@ EXPORT_SYMBOL_GPL(gpiod_count);
* dev, -ENOENT if no GPIO has been assigned to the requested function, or * 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. * 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) enum gpiod_flags flags)
{ {
return gpiod_get_index(dev, con_id, 0, 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 * gpiod_get_optional - obtain an optional GPIO for a given GPIO function
...@@ -1911,13 +1925,13 @@ EXPORT_SYMBOL_GPL(__gpiod_get); ...@@ -1911,13 +1925,13 @@ EXPORT_SYMBOL_GPL(__gpiod_get);
* the requested function it will return NULL. This is convenient for drivers * the requested function it will return NULL. This is convenient for drivers
* that need to handle optional GPIOs. * 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, const char *con_id,
enum gpiod_flags flags) enum gpiod_flags flags)
{ {
return gpiod_get_index_optional(dev, con_id, 0, 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, ...@@ -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 * requested function and/or index, or another IS_ERR() code if an error
* occurred while trying to acquire the GPIO. * 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, const char *con_id,
unsigned int idx, unsigned int idx,
enum gpiod_flags flags) enum gpiod_flags flags)
...@@ -2023,7 +2037,7 @@ struct gpio_desc *__must_check __gpiod_get_index(struct device *dev, ...@@ -2023,7 +2037,7 @@ struct gpio_desc *__must_check __gpiod_get_index(struct device *dev,
return desc; return desc;
} }
EXPORT_SYMBOL_GPL(__gpiod_get_index); EXPORT_SYMBOL_GPL(gpiod_get_index);
/** /**
* fwnode_get_named_gpiod - obtain a GPIO from firmware node * fwnode_get_named_gpiod - obtain a GPIO from firmware node
...@@ -2092,7 +2106,7 @@ EXPORT_SYMBOL_GPL(fwnode_get_named_gpiod); ...@@ -2092,7 +2106,7 @@ EXPORT_SYMBOL_GPL(fwnode_get_named_gpiod);
* specified index was assigned to the requested function it will return NULL. * specified index was assigned to the requested function it will return NULL.
* This is convenient for drivers that need to handle optional GPIOs. * 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, const char *con_id,
unsigned int index, unsigned int index,
enum gpiod_flags flags) enum gpiod_flags flags)
...@@ -2107,7 +2121,7 @@ struct gpio_desc *__must_check __gpiod_get_index_optional(struct device *dev, ...@@ -2107,7 +2121,7 @@ struct gpio_desc *__must_check __gpiod_get_index_optional(struct device *dev,
return desc; 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 * gpiod_hog - Hog the specified GPIO desc given the provided flags
......
...@@ -373,7 +373,7 @@ static int edp_gpio_config(struct edp_ctrl *ctrl) ...@@ -373,7 +373,7 @@ static int edp_gpio_config(struct edp_ctrl *ctrl)
struct device *dev = &ctrl->pdev->dev; struct device *dev = &ctrl->pdev->dev;
int ret; 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)) { if (IS_ERR(ctrl->panel_hpd_gpio)) {
ret = PTR_ERR(ctrl->panel_hpd_gpio); ret = PTR_ERR(ctrl->panel_hpd_gpio);
ctrl->panel_hpd_gpio = NULL; ctrl->panel_hpd_gpio = NULL;
...@@ -381,13 +381,7 @@ static int edp_gpio_config(struct edp_ctrl *ctrl) ...@@ -381,13 +381,7 @@ static int edp_gpio_config(struct edp_ctrl *ctrl)
return ret; return ret;
} }
ret = gpiod_direction_input(ctrl->panel_hpd_gpio); ctrl->panel_en_gpio = devm_gpiod_get(dev, "panel-en", GPIOD_OUT_LOW);
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");
if (IS_ERR(ctrl->panel_en_gpio)) { if (IS_ERR(ctrl->panel_en_gpio)) {
ret = PTR_ERR(ctrl->panel_en_gpio); ret = PTR_ERR(ctrl->panel_en_gpio);
ctrl->panel_en_gpio = NULL; ctrl->panel_en_gpio = NULL;
...@@ -395,13 +389,6 @@ static int edp_gpio_config(struct edp_ctrl *ctrl) ...@@ -395,13 +389,6 @@ static int edp_gpio_config(struct edp_ctrl *ctrl)
return ret; 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"); DBG("gpio on");
return 0; return 0;
......
...@@ -375,24 +375,16 @@ static int panel_probe(struct platform_device *pdev) ...@@ -375,24 +375,16 @@ static int panel_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "found backlight\n"); 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)) { if (IS_ERR(panel_mod->enable_gpio)) {
ret = PTR_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"); dev_err(&pdev->dev, "failed to request enable GPIO\n");
goto fail_backlight; goto fail_backlight;
} }
/* Optional GPIO is not here, continue silently. */ if (panel_mod->enable_gpio)
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_info(&pdev->dev, "found enable GPIO\n");
}
mod = &panel_mod->base; mod = &panel_mod->base;
pdev->dev.platform_data = mod; pdev->dev.platform_data = mod;
......
...@@ -469,16 +469,12 @@ static int stk3310_gpio_probe(struct i2c_client *client) ...@@ -469,16 +469,12 @@ static int stk3310_gpio_probe(struct i2c_client *client)
dev = &client->dev; dev = &client->dev;
/* gpio interrupt pin */ /* 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)) { if (IS_ERR(gpio)) {
dev_err(dev, "acpi gpio get index failed\n"); dev_err(dev, "acpi gpio get index failed\n");
return PTR_ERR(gpio); return PTR_ERR(gpio);
} }
ret = gpiod_direction_input(gpio);
if (ret)
return ret;
ret = gpiod_to_irq(gpio); ret = gpiod_to_irq(gpio);
dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret); dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret);
......
...@@ -845,16 +845,12 @@ static int bmc150_magn_gpio_probe(struct i2c_client *client) ...@@ -845,16 +845,12 @@ static int bmc150_magn_gpio_probe(struct i2c_client *client)
dev = &client->dev; dev = &client->dev;
/* data ready GPIO interrupt pin */ /* 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)) { if (IS_ERR(gpio)) {
dev_err(dev, "ACPI GPIO get index failed\n"); dev_err(dev, "ACPI GPIO get index failed\n");
return PTR_ERR(gpio); return PTR_ERR(gpio);
} }
ret = gpiod_direction_input(gpio);
if (ret)
return ret;
ret = gpiod_to_irq(gpio); ret = gpiod_to_irq(gpio);
dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret); dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret);
......
...@@ -465,7 +465,7 @@ static int adp1653_of_init(struct i2c_client *client, ...@@ -465,7 +465,7 @@ static int adp1653_of_init(struct i2c_client *client,
of_node_put(child); 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) { if (!pd->enable_gpio) {
dev_err(&client->dev, "Error getting GPIO\n"); dev_err(&client->dev, "Error getting GPIO\n");
return -EINVAL; return -EINVAL;
......
...@@ -318,19 +318,15 @@ static int nxp_nci_i2c_acpi_config(struct nxp_nci_i2c_phy *phy) ...@@ -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 i2c_client *client = phy->i2c_dev;
struct gpio_desc *gpiod_en, *gpiod_fw, *gpiod_irq; struct gpio_desc *gpiod_en, *gpiod_fw, *gpiod_irq;
gpiod_en = devm_gpiod_get_index(&client->dev, NULL, 2); gpiod_en = devm_gpiod_get_index(&client->dev, NULL, 2, GPIOD_OUT_LOW);
gpiod_fw = devm_gpiod_get_index(&client->dev, NULL, 1); gpiod_fw = devm_gpiod_get_index(&client->dev, NULL, 1, GPIOD_OUT_LOW);
gpiod_irq = devm_gpiod_get_index(&client->dev, NULL, 0); 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)) { if (IS_ERR(gpiod_en) || IS_ERR(gpiod_fw) || IS_ERR(gpiod_irq)) {
nfc_err(&client->dev, "No GPIOs\n"); nfc_err(&client->dev, "No GPIOs\n");
return -EINVAL; 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); client->irq = gpiod_to_irq(gpiod_irq);
if (client->irq < 0) { if (client->irq < 0) {
nfc_err(&client->dev, "No IRQ\n"); nfc_err(&client->dev, "No IRQ\n");
......
...@@ -61,32 +61,26 @@ static const struct phy_ops phy_ops = { ...@@ -61,32 +61,26 @@ static const struct phy_ops phy_ops = {
static int tusb1210_probe(struct ulpi *ulpi) static int tusb1210_probe(struct ulpi *ulpi)
{ {
struct gpio_desc *gpio;
struct tusb1210 *tusb; struct tusb1210 *tusb;
u8 val, reg; u8 val, reg;
int ret;
tusb = devm_kzalloc(&ulpi->dev, sizeof(*tusb), GFP_KERNEL); tusb = devm_kzalloc(&ulpi->dev, sizeof(*tusb), GFP_KERNEL);
if (!tusb) if (!tusb)
return -ENOMEM; return -ENOMEM;
gpio = devm_gpiod_get(&ulpi->dev, "reset"); tusb->gpio_reset = devm_gpiod_get_optional(&ulpi->dev, "reset",
if (!IS_ERR(gpio)) { GPIOD_OUT_LOW);
ret = gpiod_direction_output(gpio, 0); if (IS_ERR(tusb->gpio_reset))
if (ret) return PTR_ERR(tusb->gpio_reset);
return ret;
gpiod_set_value_cansleep(gpio, 1);
tusb->gpio_reset = gpio;
}
gpio = devm_gpiod_get(&ulpi->dev, "cs"); gpiod_set_value_cansleep(tusb->gpio_reset, 1);
if (!IS_ERR(gpio)) {
ret = gpiod_direction_output(gpio, 0); tusb->gpio_cs = devm_gpiod_get_optional(&ulpi->dev, "cs",
if (ret) GPIOD_OUT_LOW);
return ret; if (IS_ERR(tusb->gpio_cs))
gpiod_set_value_cansleep(gpio, 1); return PTR_ERR(tusb->gpio_cs);
tusb->gpio_cs = gpio;
} gpiod_set_value_cansleep(tusb->gpio_cs, 1);
/* /*
* VENDOR_SPECIFIC2 register in TUSB1210 can be used for configuring eye * VENDOR_SPECIFIC2 register in TUSB1210 can be used for configuring eye
......
...@@ -75,5 +75,6 @@ int bgpio_init(struct bgpio_chip *bgc, struct device *dev, ...@@ -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_UNREADABLE_REG_DIR BIT(2) /* reg_dir is unreadable */
#define BGPIOF_BIG_ENDIAN_BYTE_ORDER BIT(3) #define BGPIOF_BIG_ENDIAN_BYTE_ORDER BIT(3)
#define BGPIOF_READ_OUTPUT_REG_SET BIT(4) /* reg_set stores output value */ #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 */ #endif /* __BASIC_MMIO_GPIO_H */
...@@ -47,17 +47,17 @@ enum gpiod_flags { ...@@ -47,17 +47,17 @@ enum gpiod_flags {
int gpiod_count(struct device *dev, const char *con_id); int gpiod_count(struct device *dev, const char *con_id);
/* Acquire and dispose GPIOs */ /* 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, const char *con_id,
enum gpiod_flags flags); 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, const char *con_id,
unsigned int idx, unsigned int idx,
enum gpiod_flags flags); 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, const char *con_id,
enum gpiod_flags flags); 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, const char *con_id,
unsigned int index, unsigned int index,
enum gpiod_flags flags); enum gpiod_flags flags);
...@@ -70,18 +70,18 @@ struct gpio_descs *__must_check gpiod_get_array_optional(struct device *dev, ...@@ -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(struct gpio_desc *desc);
void gpiod_put_array(struct gpio_descs *descs); 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, const char *con_id,
enum gpiod_flags flags); 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, const char *con_id,
unsigned int idx, unsigned int idx,
enum gpiod_flags flags); 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, const char *con_id,
enum gpiod_flags flags); enum gpiod_flags flags);
struct gpio_desc *__must_check 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); unsigned int index, enum gpiod_flags flags);
struct gpio_descs *__must_check devm_gpiod_get_array(struct device *dev, struct gpio_descs *__must_check devm_gpiod_get_array(struct device *dev,
const char *con_id, const char *con_id,
...@@ -146,14 +146,14 @@ static inline int gpiod_count(struct device *dev, const char *con_id) ...@@ -146,14 +146,14 @@ static inline int gpiod_count(struct device *dev, const char *con_id)
return 0; return 0;
} }
static inline struct gpio_desc *__must_check __gpiod_get(struct device *dev, static inline struct gpio_desc *__must_check gpiod_get(struct device *dev,
const char *con_id, const char *con_id,
enum gpiod_flags flags) enum gpiod_flags flags)
{ {
return ERR_PTR(-ENOSYS); return ERR_PTR(-ENOSYS);
} }
static inline struct gpio_desc *__must_check static inline struct gpio_desc *__must_check
__gpiod_get_index(struct device *dev, gpiod_get_index(struct device *dev,
const char *con_id, const char *con_id,
unsigned int idx, unsigned int idx,
enum gpiod_flags flags) enum gpiod_flags flags)
...@@ -162,14 +162,14 @@ __gpiod_get_index(struct device *dev, ...@@ -162,14 +162,14 @@ __gpiod_get_index(struct device *dev,
} }
static inline struct gpio_desc *__must_check static inline struct gpio_desc *__must_check
__gpiod_get_optional(struct device *dev, const char *con_id, gpiod_get_optional(struct device *dev, const char *con_id,
enum gpiod_flags flags) enum gpiod_flags flags)
{ {
return ERR_PTR(-ENOSYS); return ERR_PTR(-ENOSYS);
} }
static inline struct gpio_desc *__must_check static inline struct gpio_desc *__must_check
__gpiod_get_index_optional(struct device *dev, const char *con_id, gpiod_get_index_optional(struct device *dev, const char *con_id,
unsigned int index, enum gpiod_flags flags) unsigned int index, enum gpiod_flags flags)
{ {
return ERR_PTR(-ENOSYS); return ERR_PTR(-ENOSYS);
...@@ -206,7 +206,7 @@ static inline void gpiod_put_array(struct gpio_descs *descs) ...@@ -206,7 +206,7 @@ static inline void gpiod_put_array(struct gpio_descs *descs)
} }
static inline struct gpio_desc *__must_check static inline struct gpio_desc *__must_check
__devm_gpiod_get(struct device *dev, devm_gpiod_get(struct device *dev,
const char *con_id, const char *con_id,
enum gpiod_flags flags) enum gpiod_flags flags)
{ {
...@@ -214,7 +214,7 @@ __devm_gpiod_get(struct device *dev, ...@@ -214,7 +214,7 @@ __devm_gpiod_get(struct device *dev,
} }
static inline static inline
struct gpio_desc *__must_check struct gpio_desc *__must_check
__devm_gpiod_get_index(struct device *dev, devm_gpiod_get_index(struct device *dev,
const char *con_id, const char *con_id,
unsigned int idx, unsigned int idx,
enum gpiod_flags flags) enum gpiod_flags flags)
...@@ -223,14 +223,14 @@ __devm_gpiod_get_index(struct device *dev, ...@@ -223,14 +223,14 @@ __devm_gpiod_get_index(struct device *dev,
} }
static inline struct gpio_desc *__must_check 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) enum gpiod_flags flags)
{ {
return ERR_PTR(-ENOSYS); return ERR_PTR(-ENOSYS);
} }
static inline struct gpio_desc *__must_check 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) unsigned int index, enum gpiod_flags flags)
{ {
return ERR_PTR(-ENOSYS); return ERR_PTR(-ENOSYS);
...@@ -424,42 +424,6 @@ static inline struct gpio_desc *devm_get_gpiod_from_child( ...@@ -424,42 +424,6 @@ static inline struct gpio_desc *devm_get_gpiod_from_child(
#endif /* CONFIG_GPIOLIB */ #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) #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS)
int gpiod_export(struct gpio_desc *desc, bool direction_may_change); int gpiod_export(struct gpio_desc *desc, bool direction_may_change);
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/irqchip/chained_irq.h> #include <linux/irqchip/chained_irq.h>
#include <linux/irqdomain.h> #include <linux/irqdomain.h>
#include <linux/lockdep.h>
#include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinctrl.h>
struct device; struct device;
...@@ -64,6 +65,17 @@ struct seq_file; ...@@ -64,6 +65,17 @@ struct seq_file;
* registers. * registers.
* @irq_not_threaded: flag must be set if @can_sleep is set but the * @irq_not_threaded: flag must be set if @can_sleep is set but the
* IRQs don't need to be threaded * 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 * A gpio_chip can help platforms abstract various sources of GPIOs so
* they can all be accessed through a common programing interface. * they can all be accessed through a common programing interface.
...@@ -126,6 +138,7 @@ struct gpio_chip { ...@@ -126,6 +138,7 @@ struct gpio_chip {
irq_flow_handler_t irq_handler; irq_flow_handler_t irq_handler;
unsigned int irq_default_type; unsigned int irq_default_type;
int irq_parent; int irq_parent;
struct lock_class_key *lock_key;
#endif #endif
#if defined(CONFIG_OF_GPIO) #if defined(CONFIG_OF_GPIO)
...@@ -171,11 +184,25 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip, ...@@ -171,11 +184,25 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
int parent_irq, int parent_irq,
irq_flow_handler_t parent_handler); irq_flow_handler_t parent_handler);
int gpiochip_irqchip_add(struct gpio_chip *gpiochip, int _gpiochip_irqchip_add(struct gpio_chip *gpiochip,
struct irq_chip *irqchip, struct irq_chip *irqchip,
unsigned int first_irq, unsigned int first_irq,
irq_flow_handler_t handler, irq_flow_handler_t handler,
unsigned int type); 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 */ #endif /* CONFIG_GPIOLIB_IRQCHIP */
......
...@@ -54,7 +54,7 @@ extern int of_mm_gpiochip_add(struct device_node *np, ...@@ -54,7 +54,7 @@ extern int of_mm_gpiochip_add(struct device_node *np,
struct of_mm_gpio_chip *mm_gc); struct of_mm_gpio_chip *mm_gc);
extern void of_mm_gpiochip_remove(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 void of_gpiochip_remove(struct gpio_chip *gc);
extern int of_gpio_simple_xlate(struct gpio_chip *gc, extern int of_gpio_simple_xlate(struct gpio_chip *gc,
const struct of_phandle_args *gpiospec, const struct of_phandle_args *gpiospec,
...@@ -76,7 +76,7 @@ static inline int of_gpio_simple_xlate(struct gpio_chip *gc, ...@@ -76,7 +76,7 @@ static inline int of_gpio_simple_xlate(struct gpio_chip *gc,
return -ENOSYS; 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) { } static inline void of_gpiochip_remove(struct gpio_chip *gc) { }
#endif /* CONFIG_OF_GPIO */ #endif /* CONFIG_OF_GPIO */
......
#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__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment