Commit bbfe0d6b authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'gpio-v5.4-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 changes in the GPIO subsystem for the v5.4 kernel
  cycle.

  Core changes:

   - Support hierarchical GPIO irqchips.

     We now have three consumers that can use this: Intel IXP4xx,
     ThunderX and Qualcomm SPMI GPIO (in the pinctrl subsystem).

     The support code has been long in the making and hashed out so it
     should be easily adaptable for all hierarchical irqchip parents.
     The code only gets compiled in if hierarchical irqchip is used at
     the topmost irq controller at least, as the hierarchical irqchip
     requires strict hierarchy all the way up in the system.

   - Determine the need for a "valid_mask" for GPIO lines on the
     gpio_chip and conversely for the "valid_mask" for the GPIO
     interrupt chip interrupt lines by looking for a .init_valid_mask()
     callback in the main chip or GPIO interrupt chip respectively.
     Allocate it with bitmap_alloc().

   - Isolate the device tree/open firmware GPIO description code out in
     its own file properly.

   - Isolate the ACPI GPIO description code out in its own file
     properly.

   - Drop a whole lot of #ifdef:s in the main includes: it does not hurt
     to keep the include items around, and we get quicker and clearer
     compile failures if the appropriate kernel symbols are not selected
     for drivers.

  New/deleted drivers:

   - New driver for Aspeed SGPIO.

   - The KS8695 driver is deleted as the platform gets deleted from
     arch/arm in this kernel cycle.

   - The Cirrus Logic Madera driver now supports CS47L92 and CS47L15.

   - The Freescale MPC8xxx now supports LS1028A and LS1088A.

  Driver improvements:

   - We pass the GPIO irqchip intialization by directly filling in the
     struct instead of using set-up functions (the new way) for Intel
     MID, Lynxpoint, Merrifield, XLP, HLWD, Aspeed, ZX, VF610, TQMX86,
     MT7621, Zynq and EP93xx.

  Out-of-band changes:

   - Fix a GPIO header inclusion in Unicore - no response from
     maintainer.

   - Drop FMC subsystem from MAINTAINERS - was deleted in the GPIO tree
     last cycle so let's mop up the shards"

* tag 'gpio-v5.4-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (82 commits)
  gpiolib: of: add a fallback for wlf,reset GPIO name
  gpio: htc-egpio: Remove unused exported htc_egpio_get_wakeup_irq()
  gpio: remove explicit comparison with 0
  gpio: creg-snps: use devm_platform_ioremap_resource() to simplify code
  gpio: devres: Switch to EXPORT_SYMBOL_GPL()
  gpio: of: Switch to EXPORT_SYMBOL_GPL()
  gpio: of: Make of_gpio_simple_xlate() private
  gpio: of: Make of_get_named_gpiod_flags() private
  gpio: aspeed: Add in ast2600 details to Aspeed driver
  gpio: aspeed: Use ngpio property from device tree if available
  gpio: aspeed: Setup irqchip dynamically
  gpio/aspeed: Fix incorrect number of banks
  gpio: aspeed: Update documentation with ast2600 controllers
  gpio: Initialize the irqchip valid_mask with a callback
  gpiolib: acpi: make acpi_can_fallback_to_crs() static
  gpio: Fix further merge errors
  gpio: Fix up merge collision in include file
  gpio: of: Normalize return code variable name
  gpio: gpiolib: Normalize return code variable name
  gpio: ep93xx: Pass irqchip when adding gpiochip
  ...
parents 31dda85e 11c43bb0
...@@ -2,7 +2,8 @@ Aspeed GPIO controller Device Tree Bindings ...@@ -2,7 +2,8 @@ Aspeed GPIO controller Device Tree Bindings
------------------------------------------- -------------------------------------------
Required properties: Required properties:
- compatible : Either "aspeed,ast2400-gpio" or "aspeed,ast2500-gpio" - compatible : Either "aspeed,ast2400-gpio", "aspeed,ast2500-gpio",
or "aspeed,ast2600-gpio".
- #gpio-cells : Should be two - #gpio-cells : Should be two
- First cell is the GPIO line number - First cell is the GPIO line number
...@@ -18,6 +19,8 @@ Required properties: ...@@ -18,6 +19,8 @@ Required properties:
Optional properties: Optional properties:
- clocks : A phandle to the clock to use for debounce timings - clocks : A phandle to the clock to use for debounce timings
- ngpios : Number of GPIOs controlled by this controller. Should be set
when there are multiple GPIO controllers on a SoC (ast2600).
The gpio and interrupt properties are further described in their respective The gpio and interrupt properties are further described in their respective
bindings documentation: bindings documentation:
......
...@@ -6,6 +6,7 @@ Required Properties: ...@@ -6,6 +6,7 @@ Required Properties:
66AK2E SoCs 66AK2E SoCs
"ti,k2g-gpio", "ti,keystone-gpio": for 66AK2G "ti,k2g-gpio", "ti,keystone-gpio": for 66AK2G
"ti,am654-gpio", "ti,keystone-gpio": for TI K3 AM654 "ti,am654-gpio", "ti,keystone-gpio": for TI K3 AM654
"ti,j721e-gpio", "ti,keystone-gpio": for J721E SoCs
- reg: Physical base address of the controller and the size of memory mapped - reg: Physical base address of the controller and the size of memory mapped
registers. registers.
......
...@@ -4,7 +4,7 @@ Required properties: ...@@ -4,7 +4,7 @@ Required properties:
- compatible : Should be "fsl,<soc>-gpio" - compatible : Should be "fsl,<soc>-gpio"
The following <soc>s are known to be supported: The following <soc>s are known to be supported:
mpc5121, mpc5125, mpc8349, mpc8572, mpc8610, pq3, qoriq, mpc5121, mpc5125, mpc8349, mpc8572, mpc8610, pq3, qoriq,
ls1021a, ls1043a, ls2080a. ls1021a, ls1043a, ls2080a, ls1028a, ls1088a.
- reg : Address and length of the register set for the device - reg : Address and length of the register set for the device
- interrupts : Should be the port interrupt shared by all 32 pins. - interrupts : Should be the port interrupt shared by all 32 pins.
- #gpio-cells : Should be two. The first cell is the pin number and - #gpio-cells : Should be two. The first cell is the pin number and
...@@ -37,3 +37,17 @@ gpio0: gpio@2300000 { ...@@ -37,3 +37,17 @@ gpio0: gpio@2300000 {
interrupt-controller; interrupt-controller;
#interrupt-cells = <2>; #interrupt-cells = <2>;
}; };
Example of gpio-controller node for a ls1028a/ls1088a SoC:
gpio1: gpio@2300000 {
compatible = "fsl,ls1028a-gpio", "fsl,ls1088a-gpio", "fsl,qoriq-gpio";
reg = <0x0 0x2300000 0x0 0x10000>;
interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
little-endian;
};
Aspeed SGPIO controller Device Tree Bindings
--------------------------------------------
This SGPIO controller is for ASPEED AST2500 SoC, it supports up to 80 full
featured Serial GPIOs. Each of the Serial GPIO pins can be programmed to
support the following options:
- Support interrupt option for each input port and various interrupt
sensitivity option (level-high, level-low, edge-high, edge-low)
- Support reset tolerance option for each output port
- Directly connected to APB bus and its shift clock is from APB bus clock
divided by a programmable value.
- Co-work with external signal-chained TTL components (74LV165/74LV595)
Required properties:
- compatible : Should be one of
"aspeed,ast2400-sgpio", "aspeed,ast2500-sgpio"
- #gpio-cells : Should be 2, see gpio.txt
- reg : Address and length of the register set for the device
- gpio-controller : Marks the device node as a GPIO controller
- interrupts : Interrupt specifier, see interrupt-controller/interrupts.txt
- interrupt-controller : Mark the GPIO controller as an interrupt-controller
- ngpios : number of GPIO lines, see gpio.txt
(should be multiple of 8, up to 80 pins)
- clocks : A phandle to the APB clock for SGPM clock division
- bus-frequency : SGPM CLK frequency
The sgpio and interrupt properties are further described in their respective
bindings documentation:
- Documentation/devicetree/bindings/gpio/gpio.txt
- Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
Example:
sgpio: sgpio@1e780200 {
#gpio-cells = <2>;
compatible = "aspeed,ast2500-sgpio";
gpio-controller;
interrupts = <40>;
reg = <0x1e780200 0x0100>;
clocks = <&syscon ASPEED_CLK_APB>;
interrupt-controller;
ngpios = <8>;
bus-frequency = <12000000>;
};
...@@ -69,9 +69,9 @@ driver code: ...@@ -69,9 +69,9 @@ driver code:
The code implementing a gpio_chip should support multiple instances of the The code implementing a gpio_chip should support multiple instances of the
controller, preferably using the driver model. That code will configure each controller, preferably using the driver model. That code will configure each
gpio_chip and issue ``gpiochip_add[_data]()`` or ``devm_gpiochip_add_data()``. gpio_chip and issue gpiochip_add(), gpiochip_add_data(), or
Removing a GPIO controller should be rare; use ``[devm_]gpiochip_remove()`` devm_gpiochip_add_data(). Removing a GPIO controller should be rare; use
when it is unavoidable. gpiochip_remove() when it is unavoidable.
Often a gpio_chip is part of an instance-specific structure with states not Often a gpio_chip is part of an instance-specific structure with states not
exposed by the GPIO interfaces, such as addressing, power management, and more. exposed by the GPIO interfaces, such as addressing, power management, and more.
...@@ -259,7 +259,7 @@ most often cascaded off a parent interrupt controller, and in some special ...@@ -259,7 +259,7 @@ most often cascaded off a parent interrupt controller, and in some special
cases the GPIO logic is melded with a SoC's primary interrupt controller. cases the GPIO logic is melded with a SoC's primary interrupt controller.
The IRQ portions of the GPIO block are implemented using an irq_chip, using The IRQ portions of the GPIO block are implemented using an irq_chip, using
the header <linux/irq.h>. So basically such a driver is utilizing two sub- the header <linux/irq.h>. So this combined driver is utilizing two sub-
systems simultaneously: gpio and irq. systems simultaneously: gpio and irq.
It is legal for any IRQ consumer to request an IRQ from any irqchip even if it It is legal for any IRQ consumer to request an IRQ from any irqchip even if it
...@@ -391,25 +391,119 @@ Infrastructure helpers for GPIO irqchips ...@@ -391,25 +391,119 @@ Infrastructure helpers for GPIO irqchips
---------------------------------------- ----------------------------------------
To help out in handling the set-up and management of GPIO irqchips and the To help out in handling the set-up and management of GPIO irqchips and the
associated irqdomain and resource allocation callbacks, the gpiolib has associated irqdomain and resource allocation callbacks. These are activated
some helpers that can be enabled by selecting the GPIOLIB_IRQCHIP Kconfig by selecting the Kconfig symbol GPIOLIB_IRQCHIP. If the symbol
symbol: IRQ_DOMAIN_HIERARCHY is also selected, hierarchical helpers will also be
provided. A big portion of overhead code will be managed by gpiolib,
- gpiochip_irqchip_add(): adds a chained cascaded irqchip to a gpiochip. It under the assumption that your interrupts are 1-to-1-mapped to the
will pass the struct gpio_chip* for the chip to all IRQ callbacks, so the GPIO line index:
callbacks need to embed the gpio_chip in its state container and obtain a
pointer to the container using container_of(). GPIO line offset Hardware IRQ
(See Documentation/driver-api/driver-model/design-patterns.rst) 0 0
1 1
2 2
... ...
ngpio-1 ngpio-1
If some GPIO lines do not have corresponding IRQs, the bitmask valid_mask
and the flag need_valid_mask in gpio_irq_chip can be used to mask off some
lines as invalid for associating with IRQs.
The preferred way to set up the helpers is to fill in the
struct gpio_irq_chip inside struct gpio_chip before adding the gpio_chip.
If you do this, the additional irq_chip will be set up by gpiolib at the
same time as setting up the rest of the GPIO functionality. The following
is a typical example of a cascaded interrupt handler using gpio_irq_chip:
/* Typical state container with dynamic irqchip */
struct my_gpio {
struct gpio_chip gc;
struct irq_chip irq;
};
int irq; /* from platform etc */
struct my_gpio *g;
struct gpio_irq_chip *girq;
/* Set up the irqchip dynamically */
g->irq.name = "my_gpio_irq";
g->irq.irq_ack = my_gpio_ack_irq;
g->irq.irq_mask = my_gpio_mask_irq;
g->irq.irq_unmask = my_gpio_unmask_irq;
g->irq.irq_set_type = my_gpio_set_irq_type;
/* Get a pointer to the gpio_irq_chip */
girq = &g->gc.irq;
girq->chip = &g->irq;
girq->parent_handler = ftgpio_gpio_irq_handler;
girq->num_parents = 1;
girq->parents = devm_kcalloc(dev, 1, sizeof(*girq->parents),
GFP_KERNEL);
if (!girq->parents)
return -ENOMEM;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_bad_irq;
girq->parents[0] = irq;
return devm_gpiochip_add_data(dev, &g->gc, g);
The helper support using hierarchical interrupt controllers as well.
In this case the typical set-up will look like this:
/* Typical state container with dynamic irqchip */
struct my_gpio {
struct gpio_chip gc;
struct irq_chip irq;
struct fwnode_handle *fwnode;
};
int irq; /* from platform etc */
struct my_gpio *g;
struct gpio_irq_chip *girq;
/* Set up the irqchip dynamically */
g->irq.name = "my_gpio_irq";
g->irq.irq_ack = my_gpio_ack_irq;
g->irq.irq_mask = my_gpio_mask_irq;
g->irq.irq_unmask = my_gpio_unmask_irq;
g->irq.irq_set_type = my_gpio_set_irq_type;
/* Get a pointer to the gpio_irq_chip */
girq = &g->gc.irq;
girq->chip = &g->irq;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_bad_irq;
girq->fwnode = g->fwnode;
girq->parent_domain = parent;
girq->child_to_parent_hwirq = my_gpio_child_to_parent_hwirq;
return devm_gpiochip_add_data(dev, &g->gc, g);
As you can see pretty similar, but you do not supply a parent handler for
the IRQ, instead a parent irqdomain, an fwnode for the hardware and
a funcion .child_to_parent_hwirq() that has the purpose of looking up
the parent hardware irq from a child (i.e. this gpio chip) hardware irq.
As always it is good to look at examples in the kernel tree for advice
on how to find the required pieces.
The old way of adding irqchips to gpiochips after registration is also still
available but we try to move away from this:
- DEPRECATED: gpiochip_irqchip_add(): adds a chained cascaded irqchip to a
gpiochip. It will pass the struct gpio_chip* for the chip to all IRQ
callbacks, so the callbacks need to embed the gpio_chip in its state
container and obtain a pointer to the container using container_of().
(See Documentation/driver-model/design-patterns.txt)
- gpiochip_irqchip_add_nested(): adds a nested cascaded irqchip to a gpiochip, - gpiochip_irqchip_add_nested(): adds a nested cascaded irqchip to a gpiochip,
as discussed above regarding different types of cascaded irqchips. The as discussed above regarding different types of cascaded irqchips. The
cascaded irq has to be handled by a threaded interrupt handler. cascaded irq has to be handled by a threaded interrupt handler.
Apart from that it works exactly like the chained irqchip. Apart from that it works exactly like the chained irqchip.
- gpiochip_set_chained_irqchip(): sets up a chained cascaded irq handler for a - DEPRECATED: gpiochip_set_chained_irqchip(): sets up a chained cascaded irq
gpio_chip from a parent IRQ and passes the struct gpio_chip* as handler handler for a gpio_chip from a parent IRQ and passes the struct gpio_chip*
data. Notice that we pass is as the handler data, since the irqchip data is as handler data. Notice that we pass is as the handler data, since the
likely used by the parent irqchip. irqchip data is likely used by the parent irqchip.
- gpiochip_set_nested_irqchip(): sets up a nested cascaded irq handler for a - gpiochip_set_nested_irqchip(): sets up a nested cascaded irq handler for a
gpio_chip from a parent IRQ. As the parent IRQ has usually been gpio_chip from a parent IRQ. As the parent IRQ has usually been
...@@ -418,11 +512,11 @@ symbol: ...@@ -418,11 +512,11 @@ symbol:
If there is a need to exclude certain GPIO lines from the IRQ domain handled by If there is a need to exclude certain GPIO lines from the IRQ domain handled by
these helpers, we can set .irq.need_valid_mask of the gpiochip before these helpers, we can set .irq.need_valid_mask of the gpiochip before
``[devm_]gpiochip_add_data()`` is called. This allocates an .irq.valid_mask with as devm_gpiochip_add_data() or gpiochip_add_data() is called. This allocates an
many bits set as there are GPIO lines in the chip, each bit representing line .irq.valid_mask with as many bits set as there are GPIO lines in the chip, each
0..n-1. Drivers can exclude GPIO lines by clearing bits from this mask. The mask bit representing line 0..n-1. Drivers can exclude GPIO lines by clearing bits
must be filled in before gpiochip_irqchip_add() or gpiochip_irqchip_add_nested() from this mask. The mask must be filled in before gpiochip_irqchip_add() or
is called. gpiochip_irqchip_add_nested() is called.
To use the helpers please keep the following in mind: To use the helpers please keep the following in mind:
......
...@@ -6329,15 +6329,6 @@ S: Odd Fixes ...@@ -6329,15 +6329,6 @@ S: Odd Fixes
L: linux-block@vger.kernel.org L: linux-block@vger.kernel.org
F: drivers/block/floppy.c F: drivers/block/floppy.c
FMC SUBSYSTEM
M: Alessandro Rubini <rubini@gnudd.com>
W: http://www.ohwr.org/projects/fmc-bus
S: Supported
F: drivers/fmc/
F: include/linux/fmc*.h
F: include/linux/ipmi-fru.h
K: fmc_d.*register
FPGA MANAGER FRAMEWORK FPGA MANAGER FRAMEWORK
M: Moritz Fischer <mdf@kernel.org> M: Moritz Fischer <mdf@kernel.org>
L: linux-fpga@vger.kernel.org L: linux-fpga@vger.kernel.org
...@@ -8383,12 +8374,6 @@ F: Documentation/x86/intel_txt.rst ...@@ -8383,12 +8374,6 @@ F: Documentation/x86/intel_txt.rst
F: include/linux/tboot.h F: include/linux/tboot.h
F: arch/x86/kernel/tboot.c F: arch/x86/kernel/tboot.c
INTEL-MID GPIO DRIVER
M: David Cohen <david.a.cohen@linux.intel.com>
L: linux-gpio@vger.kernel.org
S: Maintained
F: drivers/gpio/gpio-intel-mid.c
INTERCONNECT API INTERCONNECT API
M: Georgi Djakov <georgi.djakov@linaro.org> M: Georgi Djakov <georgi.djakov@linaro.org>
L: linux-pm@vger.kernel.org L: linux-pm@vger.kernel.org
......
...@@ -93,6 +93,7 @@ CONFIG_SERIAL_HS_LPC32XX_CONSOLE=y ...@@ -93,6 +93,7 @@ CONFIG_SERIAL_HS_LPC32XX_CONSOLE=y
# CONFIG_HW_RANDOM is not set # CONFIG_HW_RANDOM is not set
CONFIG_I2C_CHARDEV=y CONFIG_I2C_CHARDEV=y
CONFIG_I2C_PNX=y CONFIG_I2C_PNX=y
CONFIG_GPIO_LPC32XX=y
CONFIG_SPI=y CONFIG_SPI=y
CONFIG_SPI_PL022=y CONFIG_SPI_PL022=y
CONFIG_GPIO_SYSFS=y CONFIG_GPIO_SYSFS=y
......
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#include <linux/kallsyms.h> #include <linux/kallsyms.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/syscore_ops.h> #include <linux/syscore_ops.h>
#include <linux/gpio.h>
#include <mach/hardware.h> #include <mach/hardware.h>
......
...@@ -288,7 +288,7 @@ config GPIO_IXP4XX ...@@ -288,7 +288,7 @@ config GPIO_IXP4XX
depends on ARM # For <asm/mach-types.h> depends on ARM # For <asm/mach-types.h>
depends on ARCH_IXP4XX depends on ARCH_IXP4XX
select GPIO_GENERIC select GPIO_GENERIC
select IRQ_DOMAIN select GPIOLIB_IRQCHIP
select IRQ_DOMAIN_HIERARCHY select IRQ_DOMAIN_HIERARCHY
help help
Say yes here to support the GPIO functionality of a number of Intel Say yes here to support the GPIO functionality of a number of Intel
...@@ -311,6 +311,13 @@ config GPIO_LPC18XX ...@@ -311,6 +311,13 @@ config GPIO_LPC18XX
Select this option to enable GPIO driver for Select this option to enable GPIO driver for
NXP LPC18XX/43XX devices. NXP LPC18XX/43XX devices.
config GPIO_LPC32XX
tristate "NXP LPC32XX GPIO support"
depends on OF_GPIO && (ARCH_LPC32XX || COMPILE_TEST)
help
Select this option to enable GPIO driver for
NXP LPC32XX devices.
config GPIO_LYNXPOINT config GPIO_LYNXPOINT
tristate "Intel Lynxpoint GPIO support" tristate "Intel Lynxpoint GPIO support"
depends on ACPI && X86 depends on ACPI && X86
...@@ -539,6 +546,7 @@ config GPIO_THUNDERX ...@@ -539,6 +546,7 @@ config GPIO_THUNDERX
tristate "Cavium ThunderX/OCTEON-TX GPIO" tristate "Cavium ThunderX/OCTEON-TX GPIO"
depends on ARCH_THUNDER || (64BIT && COMPILE_TEST) depends on ARCH_THUNDER || (64BIT && COMPILE_TEST)
depends on PCI_MSI depends on PCI_MSI
select GPIOLIB_IRQCHIP
select IRQ_DOMAIN_HIERARCHY select IRQ_DOMAIN_HIERARCHY
select IRQ_FASTEOI_HIERARCHY_HANDLERS select IRQ_FASTEOI_HIERARCHY_HANDLERS
help help
...@@ -1465,7 +1473,6 @@ endmenu ...@@ -1465,7 +1473,6 @@ endmenu
config GPIO_MOCKUP config GPIO_MOCKUP
tristate "GPIO Testing Driver" tristate "GPIO Testing Driver"
depends on GPIOLIB
select IRQ_SIM select IRQ_SIM
help help
This enables GPIO Testing driver, which provides a way to test GPIO This enables GPIO Testing driver, which provides a way to test GPIO
......
...@@ -67,14 +67,13 @@ obj-$(CONFIG_GPIO_IT87) += gpio-it87.o ...@@ -67,14 +67,13 @@ obj-$(CONFIG_GPIO_IT87) += gpio-it87.o
obj-$(CONFIG_GPIO_IXP4XX) += gpio-ixp4xx.o obj-$(CONFIG_GPIO_IXP4XX) += gpio-ixp4xx.o
obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o
obj-$(CONFIG_GPIO_KEMPLD) += gpio-kempld.o obj-$(CONFIG_GPIO_KEMPLD) += gpio-kempld.o
obj-$(CONFIG_ARCH_KS8695) += gpio-ks8695.o
obj-$(CONFIG_GPIO_LOONGSON1) += gpio-loongson1.o obj-$(CONFIG_GPIO_LOONGSON1) += gpio-loongson1.o
obj-$(CONFIG_GPIO_LOONGSON) += gpio-loongson.o obj-$(CONFIG_GPIO_LOONGSON) += gpio-loongson.o
obj-$(CONFIG_GPIO_LP3943) += gpio-lp3943.o obj-$(CONFIG_GPIO_LP3943) += gpio-lp3943.o
obj-$(CONFIG_GPIO_LP873X) += gpio-lp873x.o obj-$(CONFIG_GPIO_LP873X) += gpio-lp873x.o
obj-$(CONFIG_GPIO_LP87565) += gpio-lp87565.o obj-$(CONFIG_GPIO_LP87565) += gpio-lp87565.o
obj-$(CONFIG_GPIO_LPC18XX) += gpio-lpc18xx.o obj-$(CONFIG_GPIO_LPC18XX) += gpio-lpc18xx.o
obj-$(CONFIG_ARCH_LPC32XX) += gpio-lpc32xx.o obj-$(CONFIG_GPIO_LPC32XX) += gpio-lpc32xx.o
obj-$(CONFIG_GPIO_LYNXPOINT) += gpio-lynxpoint.o obj-$(CONFIG_GPIO_LYNXPOINT) += gpio-lynxpoint.o
obj-$(CONFIG_GPIO_MADERA) += gpio-madera.o obj-$(CONFIG_GPIO_MADERA) += gpio-madera.o
obj-$(CONFIG_GPIO_MAX3191X) += gpio-max3191x.o obj-$(CONFIG_GPIO_MAX3191X) += gpio-max3191x.o
......
...@@ -142,7 +142,7 @@ static const struct gpio_chip template_chip = { ...@@ -142,7 +142,7 @@ static const struct gpio_chip template_chip = {
static int arizona_gpio_probe(struct platform_device *pdev) static int arizona_gpio_probe(struct platform_device *pdev)
{ {
struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
struct arizona_pdata *pdata = dev_get_platdata(arizona->dev); struct arizona_pdata *pdata = &arizona->pdata;
struct arizona_gpio *arizona_gpio; struct arizona_gpio *arizona_gpio;
int ret; int ret;
...@@ -177,7 +177,7 @@ static int arizona_gpio_probe(struct platform_device *pdev) ...@@ -177,7 +177,7 @@ static int arizona_gpio_probe(struct platform_device *pdev)
return -EINVAL; return -EINVAL;
} }
if (pdata && pdata->gpio_base) if (pdata->gpio_base)
arizona_gpio->gpio_chip.base = pdata->gpio_base; arizona_gpio->gpio_chip.base = pdata->gpio_base;
else else
arizona_gpio->gpio_chip.base = -1; arizona_gpio->gpio_chip.base = -1;
......
...@@ -52,6 +52,7 @@ struct aspeed_gpio_config { ...@@ -52,6 +52,7 @@ struct aspeed_gpio_config {
*/ */
struct aspeed_gpio { struct aspeed_gpio {
struct gpio_chip chip; struct gpio_chip chip;
struct irq_chip irqc;
spinlock_t lock; spinlock_t lock;
void __iomem *base; void __iomem *base;
int irq; int irq;
...@@ -661,12 +662,14 @@ static void aspeed_gpio_irq_handler(struct irq_desc *desc) ...@@ -661,12 +662,14 @@ static void aspeed_gpio_irq_handler(struct irq_desc *desc)
struct gpio_chip *gc = irq_desc_get_handler_data(desc); struct gpio_chip *gc = irq_desc_get_handler_data(desc);
struct irq_chip *ic = irq_desc_get_chip(desc); struct irq_chip *ic = irq_desc_get_chip(desc);
struct aspeed_gpio *data = gpiochip_get_data(gc); struct aspeed_gpio *data = gpiochip_get_data(gc);
unsigned int i, p, girq; unsigned int i, p, girq, banks;
unsigned long reg; unsigned long reg;
struct aspeed_gpio *gpio = gpiochip_get_data(gc);
chained_irq_enter(ic, desc); chained_irq_enter(ic, desc);
for (i = 0; i < ARRAY_SIZE(aspeed_gpio_banks); i++) { banks = DIV_ROUND_UP(gpio->chip.ngpio, 32);
for (i = 0; i < banks; i++) {
const struct aspeed_gpio_bank *bank = &aspeed_gpio_banks[i]; const struct aspeed_gpio_bank *bank = &aspeed_gpio_banks[i];
reg = ioread32(bank_reg(data, bank, reg_irq_status)); reg = ioread32(bank_reg(data, bank, reg_irq_status));
...@@ -681,16 +684,11 @@ static void aspeed_gpio_irq_handler(struct irq_desc *desc) ...@@ -681,16 +684,11 @@ static void aspeed_gpio_irq_handler(struct irq_desc *desc)
chained_irq_exit(ic, desc); chained_irq_exit(ic, desc);
} }
static struct irq_chip aspeed_gpio_irqchip = { static void aspeed_init_irq_valid_mask(struct gpio_chip *gc,
.name = "aspeed-gpio", unsigned long *valid_mask,
.irq_ack = aspeed_gpio_irq_ack, unsigned int ngpios)
.irq_mask = aspeed_gpio_irq_mask,
.irq_unmask = aspeed_gpio_irq_unmask,
.irq_set_type = aspeed_gpio_set_type,
};
static void set_irq_valid_mask(struct aspeed_gpio *gpio)
{ {
struct aspeed_gpio *gpio = gpiochip_get_data(gc);
const struct aspeed_bank_props *props = gpio->config->props; const struct aspeed_bank_props *props = gpio->config->props;
while (!is_bank_props_sentinel(props)) { while (!is_bank_props_sentinel(props)) {
...@@ -701,42 +699,16 @@ static void set_irq_valid_mask(struct aspeed_gpio *gpio) ...@@ -701,42 +699,16 @@ static void set_irq_valid_mask(struct aspeed_gpio *gpio)
for_each_clear_bit(offset, &input, 32) { for_each_clear_bit(offset, &input, 32) {
unsigned int i = props->bank * 32 + offset; unsigned int i = props->bank * 32 + offset;
if (i >= gpio->config->nr_gpios) if (i >= gpio->chip.ngpio)
break; break;
clear_bit(i, gpio->chip.irq.valid_mask); clear_bit(i, valid_mask);
} }
props++; props++;
} }
} }
static int aspeed_gpio_setup_irqs(struct aspeed_gpio *gpio,
struct platform_device *pdev)
{
int rc;
rc = platform_get_irq(pdev, 0);
if (rc < 0)
return rc;
gpio->irq = rc;
set_irq_valid_mask(gpio);
rc = gpiochip_irqchip_add(&gpio->chip, &aspeed_gpio_irqchip,
0, handle_bad_irq, IRQ_TYPE_NONE);
if (rc) {
dev_info(&pdev->dev, "Could not add irqchip\n");
return rc;
}
gpiochip_set_chained_irqchip(&gpio->chip, &aspeed_gpio_irqchip,
gpio->irq, aspeed_gpio_irq_handler);
return 0;
}
static int aspeed_gpio_reset_tolerance(struct gpio_chip *chip, static int aspeed_gpio_reset_tolerance(struct gpio_chip *chip,
unsigned int offset, bool enable) unsigned int offset, bool enable)
{ {
...@@ -1040,10 +1012,10 @@ int aspeed_gpio_copro_grab_gpio(struct gpio_desc *desc, ...@@ -1040,10 +1012,10 @@ int aspeed_gpio_copro_grab_gpio(struct gpio_desc *desc,
unsigned long flags; unsigned long flags;
if (!gpio->cf_copro_bankmap) if (!gpio->cf_copro_bankmap)
gpio->cf_copro_bankmap = kzalloc(gpio->config->nr_gpios >> 3, GFP_KERNEL); gpio->cf_copro_bankmap = kzalloc(gpio->chip.ngpio >> 3, GFP_KERNEL);
if (!gpio->cf_copro_bankmap) if (!gpio->cf_copro_bankmap)
return -ENOMEM; return -ENOMEM;
if (offset < 0 || offset > gpio->config->nr_gpios) if (offset < 0 || offset > gpio->chip.ngpio)
return -EINVAL; return -EINVAL;
bindex = offset >> 3; bindex = offset >> 3;
...@@ -1088,7 +1060,7 @@ int aspeed_gpio_copro_release_gpio(struct gpio_desc *desc) ...@@ -1088,7 +1060,7 @@ int aspeed_gpio_copro_release_gpio(struct gpio_desc *desc)
if (!gpio->cf_copro_bankmap) if (!gpio->cf_copro_bankmap)
return -ENXIO; return -ENXIO;
if (offset < 0 || offset > gpio->config->nr_gpios) if (offset < 0 || offset > gpio->chip.ngpio)
return -EINVAL; return -EINVAL;
bindex = offset >> 3; bindex = offset >> 3;
...@@ -1141,9 +1113,25 @@ static const struct aspeed_gpio_config ast2500_config = ...@@ -1141,9 +1113,25 @@ static const struct aspeed_gpio_config ast2500_config =
/* 232 for simplicity, actual number is 228 (4-GPIO hole in GPIOAB) */ /* 232 for simplicity, actual number is 228 (4-GPIO hole in GPIOAB) */
{ .nr_gpios = 232, .props = ast2500_bank_props, }; { .nr_gpios = 232, .props = ast2500_bank_props, };
static const struct aspeed_bank_props ast2600_bank_props[] = {
/* input output */
{5, 0xffffffff, 0x0000ffff}, /* U/V/W/X */
{6, 0xffff0000, 0x0fff0000}, /* Y/Z */
{ },
};
static const struct aspeed_gpio_config ast2600_config =
/*
* ast2600 has two controllers one with 208 GPIOs and one with 36 GPIOs.
* We expect ngpio being set in the device tree and this is a fallback
* option.
*/
{ .nr_gpios = 208, .props = ast2600_bank_props, };
static const struct of_device_id aspeed_gpio_of_table[] = { static const struct of_device_id aspeed_gpio_of_table[] = {
{ .compatible = "aspeed,ast2400-gpio", .data = &ast2400_config, }, { .compatible = "aspeed,ast2400-gpio", .data = &ast2400_config, },
{ .compatible = "aspeed,ast2500-gpio", .data = &ast2500_config, }, { .compatible = "aspeed,ast2500-gpio", .data = &ast2500_config, },
{ .compatible = "aspeed,ast2600-gpio", .data = &ast2600_config, },
{} {}
}; };
MODULE_DEVICE_TABLE(of, aspeed_gpio_of_table); MODULE_DEVICE_TABLE(of, aspeed_gpio_of_table);
...@@ -1152,7 +1140,8 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev) ...@@ -1152,7 +1140,8 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
{ {
const struct of_device_id *gpio_id; const struct of_device_id *gpio_id;
struct aspeed_gpio *gpio; struct aspeed_gpio *gpio;
int rc, i, banks; int rc, i, banks, err;
u32 ngpio;
gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
if (!gpio) if (!gpio)
...@@ -1178,6 +1167,9 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev) ...@@ -1178,6 +1167,9 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
gpio->config = gpio_id->data; gpio->config = gpio_id->data;
gpio->chip.parent = &pdev->dev; gpio->chip.parent = &pdev->dev;
err = of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpio);
gpio->chip.ngpio = (u16) ngpio;
if (err)
gpio->chip.ngpio = gpio->config->nr_gpios; gpio->chip.ngpio = gpio->config->nr_gpios;
gpio->chip.direction_input = aspeed_gpio_dir_in; gpio->chip.direction_input = aspeed_gpio_dir_in;
gpio->chip.direction_output = aspeed_gpio_dir_out; gpio->chip.direction_output = aspeed_gpio_dir_out;
...@@ -1189,10 +1181,9 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev) ...@@ -1189,10 +1181,9 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
gpio->chip.set_config = aspeed_gpio_set_config; gpio->chip.set_config = aspeed_gpio_set_config;
gpio->chip.label = dev_name(&pdev->dev); gpio->chip.label = dev_name(&pdev->dev);
gpio->chip.base = -1; gpio->chip.base = -1;
gpio->chip.irq.need_valid_mask = true;
/* Allocate a cache of the output registers */ /* Allocate a cache of the output registers */
banks = gpio->config->nr_gpios >> 5; banks = DIV_ROUND_UP(gpio->chip.ngpio, 32);
gpio->dcache = devm_kcalloc(&pdev->dev, gpio->dcache = devm_kcalloc(&pdev->dev,
banks, sizeof(u32), GFP_KERNEL); banks, sizeof(u32), GFP_KERNEL);
if (!gpio->dcache) if (!gpio->dcache)
...@@ -1212,16 +1203,42 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev) ...@@ -1212,16 +1203,42 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
aspeed_gpio_change_cmd_source(gpio, bank, 3, GPIO_CMDSRC_ARM); aspeed_gpio_change_cmd_source(gpio, bank, 3, GPIO_CMDSRC_ARM);
} }
rc = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio); /* Optionally set up an irqchip if there is an IRQ */
if (rc < 0) rc = platform_get_irq(pdev, 0);
return rc; if (rc > 0) {
struct gpio_irq_chip *girq;
gpio->irq = rc;
girq = &gpio->chip.irq;
girq->chip = &gpio->irqc;
girq->chip->name = dev_name(&pdev->dev);
girq->chip->irq_ack = aspeed_gpio_irq_ack;
girq->chip->irq_mask = aspeed_gpio_irq_mask;
girq->chip->irq_unmask = aspeed_gpio_irq_unmask;
girq->chip->irq_set_type = aspeed_gpio_set_type;
girq->parent_handler = aspeed_gpio_irq_handler;
girq->num_parents = 1;
girq->parents = devm_kcalloc(&pdev->dev, 1,
sizeof(*girq->parents),
GFP_KERNEL);
if (!girq->parents)
return -ENOMEM;
girq->parents[0] = gpio->irq;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_bad_irq;
girq->init_valid_mask = aspeed_init_irq_valid_mask;
}
gpio->offset_timer = gpio->offset_timer =
devm_kzalloc(&pdev->dev, gpio->chip.ngpio, GFP_KERNEL); devm_kzalloc(&pdev->dev, gpio->chip.ngpio, GFP_KERNEL);
if (!gpio->offset_timer) if (!gpio->offset_timer)
return -ENOMEM; return -ENOMEM;
return aspeed_gpio_setup_irqs(gpio, pdev); rc = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio);
if (rc < 0)
return rc;
return 0;
} }
static struct platform_driver aspeed_gpio_driver = { static struct platform_driver aspeed_gpio_driver = {
......
...@@ -36,7 +36,7 @@ static int bd70528_set_debounce(struct bd70528_gpio *bdgpio, ...@@ -36,7 +36,7 @@ static int bd70528_set_debounce(struct bd70528_gpio *bdgpio,
break; break;
default: default:
dev_err(bdgpio->chip.dev, dev_err(bdgpio->chip.dev,
"Invalid debouce value %u\n", debounce); "Invalid debounce value %u\n", debounce);
return -EINVAL; return -EINVAL;
} }
return regmap_update_bits(bdgpio->chip.regmap, GPIO_IN_REG(offset), return regmap_update_bits(bdgpio->chip.regmap, GPIO_IN_REG(offset),
...@@ -153,7 +153,7 @@ static int bd70528_gpio_get_i(struct bd70528_gpio *bdgpio, unsigned int offset) ...@@ -153,7 +153,7 @@ static int bd70528_gpio_get_i(struct bd70528_gpio *bdgpio, unsigned int offset)
static int bd70528_gpio_get(struct gpio_chip *chip, unsigned int offset) static int bd70528_gpio_get(struct gpio_chip *chip, unsigned int offset)
{ {
int ret = -EINVAL; int ret;
struct bd70528_gpio *bdgpio = gpiochip_get_data(chip); struct bd70528_gpio *bdgpio = gpiochip_get_data(chip);
/* /*
......
...@@ -636,10 +636,8 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) ...@@ -636,10 +636,8 @@ static int brcmstb_gpio_probe(struct platform_device *pdev)
if (of_property_read_bool(np, "interrupt-controller")) { if (of_property_read_bool(np, "interrupt-controller")) {
priv->parent_irq = platform_get_irq(pdev, 0); priv->parent_irq = platform_get_irq(pdev, 0);
if (priv->parent_irq <= 0) { if (priv->parent_irq <= 0)
dev_err(dev, "Couldn't get IRQ");
return -ENOENT; return -ENOENT;
}
} else { } else {
priv->parent_irq = -ENOENT; priv->parent_irq = -ENOENT;
} }
......
...@@ -214,27 +214,33 @@ static int cdns_gpio_probe(struct platform_device *pdev) ...@@ -214,27 +214,33 @@ static int cdns_gpio_probe(struct platform_device *pdev)
goto err_revert_dir; goto err_revert_dir;
} }
ret = devm_gpiochip_add_data(&pdev->dev, &cgpio->gc, cgpio);
if (ret < 0) {
dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
goto err_disable_clk;
}
/* /*
* irq_chip support * Optional irq_chip support
*/ */
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq >= 0) { if (irq >= 0) {
ret = gpiochip_irqchip_add(&cgpio->gc, &cdns_gpio_irqchip, struct gpio_irq_chip *girq;
0, handle_level_irq,
IRQ_TYPE_NONE); girq = &cgpio->gc.irq;
if (ret) { girq->chip = &cdns_gpio_irqchip;
dev_err(&pdev->dev, "Could not add irqchip, %d\n", girq->parent_handler = cdns_gpio_irq_handler;
ret); girq->num_parents = 1;
girq->parents = devm_kcalloc(&pdev->dev, 1,
sizeof(*girq->parents),
GFP_KERNEL);
if (!girq->parents) {
ret = -ENOMEM;
goto err_disable_clk; goto err_disable_clk;
} }
gpiochip_set_chained_irqchip(&cgpio->gc, &cdns_gpio_irqchip, girq->parents[0] = irq;
irq, cdns_gpio_irq_handler); girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_level_irq;
}
ret = devm_gpiochip_add_data(&pdev->dev, &cgpio->gc, cgpio);
if (ret < 0) {
dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
goto err_disable_clk;
} }
cgpio->bypass_orig = ioread32(cgpio->regs + CDNS_GPIO_BYPASS_MODE); cgpio->bypass_orig = ioread32(cgpio->regs + CDNS_GPIO_BYPASS_MODE);
......
...@@ -137,7 +137,6 @@ static int creg_gpio_probe(struct platform_device *pdev) ...@@ -137,7 +137,6 @@ static int creg_gpio_probe(struct platform_device *pdev)
const struct of_device_id *match; const struct of_device_id *match;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct creg_gpio *hcg; struct creg_gpio *hcg;
struct resource *mem;
u32 ngpios; u32 ngpios;
int ret; int ret;
...@@ -145,8 +144,7 @@ static int creg_gpio_probe(struct platform_device *pdev) ...@@ -145,8 +144,7 @@ static int creg_gpio_probe(struct platform_device *pdev)
if (!hcg) if (!hcg)
return -ENOMEM; return -ENOMEM;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); hcg->regs = devm_platform_ioremap_resource(pdev, 0);
hcg->regs = devm_ioremap_resource(dev, mem);
if (IS_ERR(hcg->regs)) if (IS_ERR(hcg->regs))
return PTR_ERR(hcg->regs); return PTR_ERR(hcg->regs);
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include "gpiolib.h" #include "gpiolib.h"
#include "gpiolib-acpi.h"
#define GPIO_SWPORTA_DR 0x00 #define GPIO_SWPORTA_DR 0x00
#define GPIO_SWPORTA_DDR 0x04 #define GPIO_SWPORTA_DDR 0x04
......
...@@ -584,10 +584,8 @@ static int sprd_eic_probe(struct platform_device *pdev) ...@@ -584,10 +584,8 @@ static int sprd_eic_probe(struct platform_device *pdev)
sprd_eic->type = pdata->type; sprd_eic->type = pdata->type;
sprd_eic->irq = platform_get_irq(pdev, 0); sprd_eic->irq = platform_get_irq(pdev, 0);
if (sprd_eic->irq < 0) { if (sprd_eic->irq < 0)
dev_err(&pdev->dev, "Failed to get EIC interrupt.\n");
return sprd_eic->irq; return sprd_eic->irq;
}
for (i = 0; i < SPRD_EIC_MAX_BANK; i++) { for (i = 0; i < SPRD_EIC_MAX_BANK; i++) {
/* /*
......
...@@ -272,11 +272,12 @@ static int em_gio_probe(struct platform_device *pdev) ...@@ -272,11 +272,12 @@ static int em_gio_probe(struct platform_device *pdev)
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); struct device *dev = &pdev->dev;
const char *name = dev_name(dev);
unsigned int ngpios; unsigned int ngpios;
int ret; int ret;
p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL); p = devm_kzalloc(dev, sizeof(*p), GFP_KERNEL);
if (!p) if (!p)
return -ENOMEM; return -ENOMEM;
...@@ -290,27 +291,27 @@ static int em_gio_probe(struct platform_device *pdev) ...@@ -290,27 +291,27 @@ static int em_gio_probe(struct platform_device *pdev)
irq[1] = platform_get_resource(pdev, IORESOURCE_IRQ, 1); irq[1] = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
if (!io[0] || !io[1] || !irq[0] || !irq[1]) { if (!io[0] || !io[1] || !irq[0] || !irq[1]) {
dev_err(&pdev->dev, "missing IRQ or IOMEM\n"); dev_err(dev, "missing IRQ or IOMEM\n");
return -EINVAL; return -EINVAL;
} }
p->base0 = devm_ioremap_nocache(&pdev->dev, io[0]->start, p->base0 = devm_ioremap_nocache(dev, io[0]->start,
resource_size(io[0])); resource_size(io[0]));
if (!p->base0) if (!p->base0)
return -ENOMEM; return -ENOMEM;
p->base1 = devm_ioremap_nocache(&pdev->dev, io[1]->start, p->base1 = devm_ioremap_nocache(dev, io[1]->start,
resource_size(io[1])); resource_size(io[1]));
if (!p->base1) if (!p->base1)
return -ENOMEM; return -ENOMEM;
if (of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios)) { if (of_property_read_u32(dev->of_node, "ngpios", &ngpios)) {
dev_err(&pdev->dev, "Missing ngpios OF property\n"); dev_err(dev, "Missing ngpios OF property\n");
return -EINVAL; return -EINVAL;
} }
gpio_chip = &p->gpio_chip; gpio_chip = &p->gpio_chip;
gpio_chip->of_node = pdev->dev.of_node; gpio_chip->of_node = dev->of_node;
gpio_chip->direction_input = em_gio_direction_input; gpio_chip->direction_input = em_gio_direction_input;
gpio_chip->get = em_gio_get; gpio_chip->get = em_gio_get;
gpio_chip->direction_output = em_gio_direction_output; gpio_chip->direction_output = em_gio_direction_output;
...@@ -319,7 +320,7 @@ static int em_gio_probe(struct platform_device *pdev) ...@@ -319,7 +320,7 @@ static int em_gio_probe(struct platform_device *pdev)
gpio_chip->request = em_gio_request; gpio_chip->request = em_gio_request;
gpio_chip->free = em_gio_free; gpio_chip->free = em_gio_free;
gpio_chip->label = name; gpio_chip->label = name;
gpio_chip->parent = &pdev->dev; gpio_chip->parent = dev;
gpio_chip->owner = THIS_MODULE; gpio_chip->owner = THIS_MODULE;
gpio_chip->base = -1; gpio_chip->base = -1;
gpio_chip->ngpio = ngpios; gpio_chip->ngpio = ngpios;
...@@ -333,33 +334,33 @@ static int em_gio_probe(struct platform_device *pdev) ...@@ -333,33 +334,33 @@ 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, ngpios, 0, p->irq_domain = irq_domain_add_simple(dev->of_node, ngpios, 0,
&em_gio_irq_domain_ops, p); &em_gio_irq_domain_ops, p);
if (!p->irq_domain) { if (!p->irq_domain) {
dev_err(&pdev->dev, "cannot initialize irq domain\n"); dev_err(dev, "cannot initialize irq domain\n");
return -ENXIO; return -ENXIO;
} }
ret = devm_add_action_or_reset(&pdev->dev, em_gio_irq_domain_remove, ret = devm_add_action_or_reset(dev, em_gio_irq_domain_remove,
p->irq_domain); p->irq_domain);
if (ret) if (ret)
return ret; return ret;
if (devm_request_irq(&pdev->dev, irq[0]->start, if (devm_request_irq(dev, irq[0]->start,
em_gio_irq_handler, 0, name, p)) { em_gio_irq_handler, 0, name, p)) {
dev_err(&pdev->dev, "failed to request low IRQ\n"); dev_err(dev, "failed to request low IRQ\n");
return -ENOENT; return -ENOENT;
} }
if (devm_request_irq(&pdev->dev, irq[1]->start, if (devm_request_irq(dev, irq[1]->start,
em_gio_irq_handler, 0, name, p)) { em_gio_irq_handler, 0, name, p)) {
dev_err(&pdev->dev, "failed to request high IRQ\n"); dev_err(dev, "failed to request high IRQ\n");
return -ENOENT; return -ENOENT;
} }
ret = devm_gpiochip_add_data(&pdev->dev, gpio_chip, p); ret = devm_gpiochip_add_data(dev, gpio_chip, p);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to add GPIO controller\n"); dev_err(dev, "failed to add GPIO controller\n");
return ret; return ret;
} }
......
...@@ -269,56 +269,6 @@ static struct irq_chip ep93xx_gpio_irq_chip = { ...@@ -269,56 +269,6 @@ static struct irq_chip ep93xx_gpio_irq_chip = {
.irq_set_type = ep93xx_gpio_irq_type, .irq_set_type = ep93xx_gpio_irq_type,
}; };
static int ep93xx_gpio_init_irq(struct platform_device *pdev,
struct ep93xx_gpio *epg)
{
int ab_parent_irq = platform_get_irq(pdev, 0);
struct device *dev = &pdev->dev;
int gpio_irq;
int ret;
int i;
/* The A bank */
ret = gpiochip_irqchip_add(&epg->gc[0], &ep93xx_gpio_irq_chip,
64, handle_level_irq,
IRQ_TYPE_NONE);
if (ret) {
dev_err(dev, "Could not add irqchip 0\n");
return ret;
}
gpiochip_set_chained_irqchip(&epg->gc[0], &ep93xx_gpio_irq_chip,
ab_parent_irq,
ep93xx_gpio_ab_irq_handler);
/* The B bank */
ret = gpiochip_irqchip_add(&epg->gc[1], &ep93xx_gpio_irq_chip,
72, handle_level_irq,
IRQ_TYPE_NONE);
if (ret) {
dev_err(dev, "Could not add irqchip 1\n");
return ret;
}
gpiochip_set_chained_irqchip(&epg->gc[1], &ep93xx_gpio_irq_chip,
ab_parent_irq,
ep93xx_gpio_ab_irq_handler);
/* The F bank */
for (i = 0; i < 8; i++) {
gpio_irq = EP93XX_GPIO_F_IRQ_BASE + i;
irq_set_chip_data(gpio_irq, &epg->gc[5]);
irq_set_chip_and_handler(gpio_irq, &ep93xx_gpio_irq_chip,
handle_level_irq);
irq_clear_status_flags(gpio_irq, IRQ_NOREQUEST);
}
for (i = 1; i <= 8; i++)
irq_set_chained_handler_and_data(platform_get_irq(pdev, i),
ep93xx_gpio_f_irq_handler,
&epg->gc[i]);
return 0;
}
/************************************************************************* /*************************************************************************
* gpiolib interface for EP93xx on-chip GPIOs * gpiolib interface for EP93xx on-chip GPIOs
*************************************************************************/ *************************************************************************/
...@@ -328,26 +278,33 @@ struct ep93xx_gpio_bank { ...@@ -328,26 +278,33 @@ struct ep93xx_gpio_bank {
int dir; int dir;
int base; int base;
bool has_irq; bool has_irq;
bool has_hierarchical_irq;
unsigned int irq_base;
}; };
#define EP93XX_GPIO_BANK(_label, _data, _dir, _base, _has_irq) \ #define EP93XX_GPIO_BANK(_label, _data, _dir, _base, _has_irq, _has_hier, _irq_base) \
{ \ { \
.label = _label, \ .label = _label, \
.data = _data, \ .data = _data, \
.dir = _dir, \ .dir = _dir, \
.base = _base, \ .base = _base, \
.has_irq = _has_irq, \ .has_irq = _has_irq, \
.has_hierarchical_irq = _has_hier, \
.irq_base = _irq_base, \
} }
static struct ep93xx_gpio_bank ep93xx_gpio_banks[] = { static struct ep93xx_gpio_bank ep93xx_gpio_banks[] = {
EP93XX_GPIO_BANK("A", 0x00, 0x10, 0, true), /* Bank A has 8 IRQs */ /* Bank A has 8 IRQs */
EP93XX_GPIO_BANK("B", 0x04, 0x14, 8, true), /* Bank B has 8 IRQs */ EP93XX_GPIO_BANK("A", 0x00, 0x10, 0, true, false, 64),
EP93XX_GPIO_BANK("C", 0x08, 0x18, 40, false), /* Bank B has 8 IRQs */
EP93XX_GPIO_BANK("D", 0x0c, 0x1c, 24, false), EP93XX_GPIO_BANK("B", 0x04, 0x14, 8, true, false, 72),
EP93XX_GPIO_BANK("E", 0x20, 0x24, 32, false), EP93XX_GPIO_BANK("C", 0x08, 0x18, 40, false, false, 0),
EP93XX_GPIO_BANK("F", 0x30, 0x34, 16, true), /* Bank F has 8 IRQs */ EP93XX_GPIO_BANK("D", 0x0c, 0x1c, 24, false, false, 0),
EP93XX_GPIO_BANK("G", 0x38, 0x3c, 48, false), EP93XX_GPIO_BANK("E", 0x20, 0x24, 32, false, false, 0),
EP93XX_GPIO_BANK("H", 0x40, 0x44, 56, false), /* Bank F has 8 IRQs */
EP93XX_GPIO_BANK("F", 0x30, 0x34, 16, false, true, 0),
EP93XX_GPIO_BANK("G", 0x38, 0x3c, 48, false, false, 0),
EP93XX_GPIO_BANK("H", 0x40, 0x44, 56, false, false, 0),
}; };
static int ep93xx_gpio_set_config(struct gpio_chip *gc, unsigned offset, static int ep93xx_gpio_set_config(struct gpio_chip *gc, unsigned offset,
...@@ -369,12 +326,15 @@ static int ep93xx_gpio_f_to_irq(struct gpio_chip *gc, unsigned offset) ...@@ -369,12 +326,15 @@ static int ep93xx_gpio_f_to_irq(struct gpio_chip *gc, unsigned offset)
return EP93XX_GPIO_F_IRQ_BASE + offset; return EP93XX_GPIO_F_IRQ_BASE + offset;
} }
static int ep93xx_gpio_add_bank(struct gpio_chip *gc, struct device *dev, static int ep93xx_gpio_add_bank(struct gpio_chip *gc,
struct platform_device *pdev,
struct ep93xx_gpio *epg, struct ep93xx_gpio *epg,
struct ep93xx_gpio_bank *bank) struct ep93xx_gpio_bank *bank)
{ {
void __iomem *data = epg->base + bank->data; void __iomem *data = epg->base + bank->data;
void __iomem *dir = epg->base + bank->dir; void __iomem *dir = epg->base + bank->dir;
struct device *dev = &pdev->dev;
struct gpio_irq_chip *girq;
int err; int err;
err = bgpio_init(gc, dev, 1, data, NULL, NULL, dir, NULL, 0); err = bgpio_init(gc, dev, 1, data, NULL, NULL, dir, NULL, 0);
...@@ -384,8 +344,59 @@ static int ep93xx_gpio_add_bank(struct gpio_chip *gc, struct device *dev, ...@@ -384,8 +344,59 @@ static int ep93xx_gpio_add_bank(struct gpio_chip *gc, struct device *dev,
gc->label = bank->label; gc->label = bank->label;
gc->base = bank->base; gc->base = bank->base;
if (bank->has_irq) girq = &gc->irq;
if (bank->has_irq || bank->has_hierarchical_irq) {
gc->set_config = ep93xx_gpio_set_config; gc->set_config = ep93xx_gpio_set_config;
girq->chip = &ep93xx_gpio_irq_chip;
}
if (bank->has_irq) {
int ab_parent_irq = platform_get_irq(pdev, 0);
girq->parent_handler = ep93xx_gpio_ab_irq_handler;
girq->num_parents = 1;
girq->parents = devm_kcalloc(dev, 1,
sizeof(*girq->parents),
GFP_KERNEL);
if (!girq->parents)
return -ENOMEM;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_level_irq;
girq->parents[0] = ab_parent_irq;
girq->first = bank->irq_base;
}
/* Only bank F has especially funky IRQ handling */
if (bank->has_hierarchical_irq) {
int gpio_irq;
int i;
/*
* FIXME: convert this to use hierarchical IRQ support!
* this requires fixing the root irqchip to be hierarchial.
*/
girq->parent_handler = ep93xx_gpio_f_irq_handler;
girq->num_parents = 8;
girq->parents = devm_kcalloc(dev, 8,
sizeof(*girq->parents),
GFP_KERNEL);
if (!girq->parents)
return -ENOMEM;
/* Pick resources 1..8 for these IRQs */
for (i = 1; i <= 8; i++)
girq->parents[i - 1] = platform_get_irq(pdev, i);
for (i = 0; i < 8; i++) {
gpio_irq = EP93XX_GPIO_F_IRQ_BASE + i;
irq_set_chip_data(gpio_irq, &epg->gc[5]);
irq_set_chip_and_handler(gpio_irq,
&ep93xx_gpio_irq_chip,
handle_level_irq);
irq_clear_status_flags(gpio_irq, IRQ_NOREQUEST);
}
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_level_irq;
gc->to_irq = ep93xx_gpio_f_to_irq;
}
return devm_gpiochip_add_data(dev, gc, epg); return devm_gpiochip_add_data(dev, gc, epg);
} }
...@@ -407,16 +418,11 @@ static int ep93xx_gpio_probe(struct platform_device *pdev) ...@@ -407,16 +418,11 @@ static int ep93xx_gpio_probe(struct platform_device *pdev)
struct gpio_chip *gc = &epg->gc[i]; struct gpio_chip *gc = &epg->gc[i];
struct ep93xx_gpio_bank *bank = &ep93xx_gpio_banks[i]; struct ep93xx_gpio_bank *bank = &ep93xx_gpio_banks[i];
if (ep93xx_gpio_add_bank(gc, &pdev->dev, epg, bank)) if (ep93xx_gpio_add_bank(gc, pdev, epg, bank))
dev_warn(&pdev->dev, "Unable to add gpio bank %s\n", dev_warn(&pdev->dev, "Unable to add gpio bank %s\n",
bank->label); bank->label);
/* Only bank F has especially funky IRQ handling */
if (i == 5)
gc->to_irq = ep93xx_gpio_f_to_irq;
} }
ep93xx_gpio_init_irq(pdev, epg);
return 0; return 0;
} }
......
...@@ -290,16 +290,14 @@ static int ftgpio_gpio_probe(struct platform_device *pdev) ...@@ -290,16 +290,14 @@ static int ftgpio_gpio_probe(struct platform_device *pdev)
girq->num_parents = 1; girq->num_parents = 1;
girq->parents = devm_kcalloc(dev, 1, sizeof(*girq->parents), girq->parents = devm_kcalloc(dev, 1, sizeof(*girq->parents),
GFP_KERNEL); GFP_KERNEL);
if (!girq->parents) if (!girq->parents) {
return -ENOMEM; ret = -ENOMEM;
goto dis_clk;
}
girq->default_type = IRQ_TYPE_NONE; girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_bad_irq; girq->handler = handle_bad_irq;
girq->parents[0] = irq; girq->parents[0] = irq;
ret = devm_gpiochip_add_data(dev, &g->gc, g);
if (ret)
goto dis_clk;
/* Disable, unmask and clear all interrupts */ /* Disable, unmask and clear all interrupts */
writel(0x0, g->base + GPIO_INT_EN); writel(0x0, g->base + GPIO_INT_EN);
writel(0x0, g->base + GPIO_INT_MASK); writel(0x0, g->base + GPIO_INT_MASK);
...@@ -308,6 +306,10 @@ static int ftgpio_gpio_probe(struct platform_device *pdev) ...@@ -308,6 +306,10 @@ static int ftgpio_gpio_probe(struct platform_device *pdev)
/* Clear any use of debounce */ /* Clear any use of debounce */
writel(0x0, g->base + GPIO_DEBOUNCE_EN); writel(0x0, g->base + GPIO_DEBOUNCE_EN);
ret = devm_gpiochip_add_data(dev, &g->gc, g);
if (ret)
goto dis_clk;
platform_set_drvdata(pdev, g); platform_set_drvdata(pdev, g);
dev_info(dev, "FTGPIO010 @%p registered\n", g->base); dev_info(dev, "FTGPIO010 @%p registered\n", g->base);
......
...@@ -408,8 +408,6 @@ static int grgpio_probe(struct platform_device *ofdev) ...@@ -408,8 +408,6 @@ static int grgpio_probe(struct platform_device *ofdev)
* Continue without irq functionality for that * Continue without irq functionality for that
* gpio line * gpio line
*/ */
dev_err(priv->dev,
"Failed to get irq for offset %d\n", i);
continue; continue;
} }
priv->uirqs[lirq->index].uirq = ret; priv->uirqs[lirq->index].uirq = ret;
......
...@@ -244,20 +244,16 @@ static int hlwd_gpio_probe(struct platform_device *pdev) ...@@ -244,20 +244,16 @@ static int hlwd_gpio_probe(struct platform_device *pdev)
ngpios = 32; ngpios = 32;
hlwd->gpioc.ngpio = ngpios; hlwd->gpioc.ngpio = ngpios;
res = devm_gpiochip_add_data(&pdev->dev, &hlwd->gpioc, hlwd);
if (res)
return res;
/* Mask and ack all interrupts */ /* Mask and ack all interrupts */
iowrite32be(0, hlwd->regs + HW_GPIOB_INTMASK); iowrite32be(0, hlwd->regs + HW_GPIOB_INTMASK);
iowrite32be(0xffffffff, hlwd->regs + HW_GPIOB_INTFLAG); iowrite32be(0xffffffff, hlwd->regs + HW_GPIOB_INTFLAG);
/* /*
* If this GPIO controller is not marked as an interrupt controller in * If this GPIO controller is not marked as an interrupt controller in
* the DT, return. * the DT, skip interrupt support.
*/ */
if (!of_property_read_bool(pdev->dev.of_node, "interrupt-controller")) if (of_property_read_bool(pdev->dev.of_node, "interrupt-controller")) {
return 0; struct gpio_irq_chip *girq;
hlwd->irq = platform_get_irq(pdev, 0); hlwd->irq = platform_get_irq(pdev, 0);
if (hlwd->irq < 0) { if (hlwd->irq < 0) {
...@@ -272,15 +268,21 @@ static int hlwd_gpio_probe(struct platform_device *pdev) ...@@ -272,15 +268,21 @@ static int hlwd_gpio_probe(struct platform_device *pdev)
hlwd->irqc.irq_enable = hlwd_gpio_irq_enable; hlwd->irqc.irq_enable = hlwd_gpio_irq_enable;
hlwd->irqc.irq_set_type = hlwd_gpio_irq_set_type; hlwd->irqc.irq_set_type = hlwd_gpio_irq_set_type;
res = gpiochip_irqchip_add(&hlwd->gpioc, &hlwd->irqc, 0, girq = &hlwd->gpioc.irq;
handle_level_irq, IRQ_TYPE_NONE); girq->chip = &hlwd->irqc;
if (res) girq->parent_handler = hlwd_gpio_irqhandler;
return res; girq->num_parents = 1;
girq->parents = devm_kcalloc(&pdev->dev, 1,
gpiochip_set_chained_irqchip(&hlwd->gpioc, &hlwd->irqc, sizeof(*girq->parents),
hlwd->irq, hlwd_gpio_irqhandler); GFP_KERNEL);
if (!girq->parents)
return -ENOMEM;
girq->parents[0] = hlwd->irq;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_level_irq;
}
return 0; return devm_gpiochip_add_data(&pdev->dev, &hlwd->gpioc, hlwd);
} }
static const struct of_device_id hlwd_gpio_match[] = { static const struct of_device_id hlwd_gpio_match[] = {
......
...@@ -118,20 +118,6 @@ static void egpio_handler(struct irq_desc *desc) ...@@ -118,20 +118,6 @@ static void egpio_handler(struct irq_desc *desc)
} }
} }
int htc_egpio_get_wakeup_irq(struct device *dev)
{
struct egpio_info *ei = dev_get_drvdata(dev);
/* Read current pins. */
u16 readval = egpio_readw(ei, ei->ack_register);
/* Ack/unmask interrupts. */
ack_irqs(ei);
/* Return first set pin. */
readval &= ei->irqs_enabled;
return ei->irq_start + ffs(readval) - 1;
}
EXPORT_SYMBOL(htc_egpio_get_wakeup_irq);
static inline int egpio_pos(struct egpio_info *ei, int bit) static inline int egpio_pos(struct egpio_info *ei, int bit)
{ {
return bit >> ei->reg_shift; return bit >> ei->reg_shift;
......
...@@ -329,6 +329,7 @@ static int intel_gpio_probe(struct pci_dev *pdev, ...@@ -329,6 +329,7 @@ static int intel_gpio_probe(struct pci_dev *pdev,
u32 gpio_base; u32 gpio_base;
u32 irq_base; u32 irq_base;
int retval; int retval;
struct gpio_irq_chip *girq;
struct intel_mid_gpio_ddata *ddata = struct intel_mid_gpio_ddata *ddata =
(struct intel_mid_gpio_ddata *)id->driver_data; (struct intel_mid_gpio_ddata *)id->driver_data;
...@@ -369,6 +370,22 @@ static int intel_gpio_probe(struct pci_dev *pdev, ...@@ -369,6 +370,22 @@ static int intel_gpio_probe(struct pci_dev *pdev,
spin_lock_init(&priv->lock); spin_lock_init(&priv->lock);
girq = &priv->chip.irq;
girq->chip = &intel_mid_irqchip;
girq->parent_handler = intel_mid_irq_handler;
girq->num_parents = 1;
girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents,
sizeof(*girq->parents),
GFP_KERNEL);
if (!girq->parents)
return -ENOMEM;
girq->parents[0] = pdev->irq;
girq->first = irq_base;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_simple_irq;
intel_mid_irq_init_hw(priv);
pci_set_drvdata(pdev, priv); pci_set_drvdata(pdev, priv);
retval = devm_gpiochip_add_data(&pdev->dev, &priv->chip, priv); retval = devm_gpiochip_add_data(&pdev->dev, &priv->chip, priv);
if (retval) { if (retval) {
...@@ -376,24 +393,6 @@ static int intel_gpio_probe(struct pci_dev *pdev, ...@@ -376,24 +393,6 @@ static int intel_gpio_probe(struct pci_dev *pdev,
return retval; return retval;
} }
retval = gpiochip_irqchip_add(&priv->chip,
&intel_mid_irqchip,
irq_base,
handle_simple_irq,
IRQ_TYPE_NONE);
if (retval) {
dev_err(&pdev->dev,
"could not connect irqchip to gpiochip\n");
return retval;
}
intel_mid_irq_init_hw(priv);
gpiochip_set_chained_irqchip(&priv->chip,
&intel_mid_irqchip,
pdev->irq,
intel_mid_irq_handler);
pm_runtime_put_noidle(&pdev->dev); pm_runtime_put_noidle(&pdev->dev);
pm_runtime_allow(&pdev->dev); pm_runtime_allow(&pdev->dev);
......
This diff is collapsed.
// SPDX-License-Identifier: GPL-2.0-only
/*
* arch/arm/mach-ks8695/gpio.c
*
* Copyright (C) 2006 Andrew Victor
* Updated to GPIOLIB, Copyright 2008 Simtec Electronics
* Daniel Silverstone <dsilvers@simtec.co.uk>
*/
#include <linux/gpio/driver.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/module.h>
#include <linux/io.h>
#include <mach/hardware.h>
#include <asm/mach/irq.h>
#include <mach/regs-gpio.h>
#include <mach/gpio-ks8695.h>
/*
* Configure a GPIO line for either GPIO function, or its internal
* function (Interrupt, Timer, etc).
*/
static void ks8695_gpio_mode(unsigned int pin, short gpio)
{
unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN };
unsigned long x, flags;
if (pin > KS8695_GPIO_5) /* only GPIO 0..5 have internal functions */
return;
local_irq_save(flags);
x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
if (gpio) /* GPIO: set bit to 0 */
x &= ~enable[pin];
else /* Internal function: set bit to 1 */
x |= enable[pin];
__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPC);
local_irq_restore(flags);
}
static unsigned short gpio_irq[] = { KS8695_IRQ_EXTERN0, KS8695_IRQ_EXTERN1, KS8695_IRQ_EXTERN2, KS8695_IRQ_EXTERN3 };
/*
* Configure GPIO pin as external interrupt source.
*/
int ks8695_gpio_interrupt(unsigned int pin, unsigned int type)
{
unsigned long x, flags;
if (pin > KS8695_GPIO_3) /* only GPIO 0..3 can generate IRQ */
return -EINVAL;
local_irq_save(flags);
/* set pin as input */
x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
x &= ~IOPM(pin);
__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
local_irq_restore(flags);
/* Set IRQ triggering type */
irq_set_irq_type(gpio_irq[pin], type);
/* enable interrupt mode */
ks8695_gpio_mode(pin, 0);
return 0;
}
EXPORT_SYMBOL(ks8695_gpio_interrupt);
/* .... Generic GPIO interface .............................................. */
/*
* Configure the GPIO line as an input.
*/
static int ks8695_gpio_direction_input(struct gpio_chip *gc, unsigned int pin)
{
unsigned long x, flags;
if (pin > KS8695_GPIO_15)
return -EINVAL;
/* set pin to GPIO mode */
ks8695_gpio_mode(pin, 1);
local_irq_save(flags);
/* set pin as input */
x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
x &= ~IOPM(pin);
__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
local_irq_restore(flags);
return 0;
}
/*
* Configure the GPIO line as an output, with default state.
*/
static int ks8695_gpio_direction_output(struct gpio_chip *gc,
unsigned int pin, int state)
{
unsigned long x, flags;
if (pin > KS8695_GPIO_15)
return -EINVAL;
/* set pin to GPIO mode */
ks8695_gpio_mode(pin, 1);
local_irq_save(flags);
/* set line state */
x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
if (state)
x |= IOPD(pin);
else
x &= ~IOPD(pin);
__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD);
/* set pin as output */
x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
x |= IOPM(pin);
__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM);
local_irq_restore(flags);
return 0;
}
/*
* Set the state of an output GPIO line.
*/
static void ks8695_gpio_set_value(struct gpio_chip *gc,
unsigned int pin, int state)
{
unsigned long x, flags;
if (pin > KS8695_GPIO_15)
return;
local_irq_save(flags);
/* set output line state */
x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
if (state)
x |= IOPD(pin);
else
x &= ~IOPD(pin);
__raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD);
local_irq_restore(flags);
}
/*
* Read the state of a GPIO line.
*/
static int ks8695_gpio_get_value(struct gpio_chip *gc, unsigned int pin)
{
unsigned long x;
if (pin > KS8695_GPIO_15)
return -EINVAL;
x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
return (x & IOPD(pin)) != 0;
}
/*
* Map GPIO line to IRQ number.
*/
static int ks8695_gpio_to_irq(struct gpio_chip *gc, unsigned int pin)
{
if (pin > KS8695_GPIO_3) /* only GPIO 0..3 can generate IRQ */
return -EINVAL;
return gpio_irq[pin];
}
/* GPIOLIB interface */
static struct gpio_chip ks8695_gpio_chip = {
.label = "KS8695",
.direction_input = ks8695_gpio_direction_input,
.direction_output = ks8695_gpio_direction_output,
.get = ks8695_gpio_get_value,
.set = ks8695_gpio_set_value,
.to_irq = ks8695_gpio_to_irq,
.base = 0,
.ngpio = 16,
.can_sleep = false,
};
/* Register the GPIOs */
void ks8695_register_gpios(void)
{
if (gpiochip_add_data(&ks8695_gpio_chip, NULL))
printk(KERN_ERR "Unable to register core GPIOs\n");
}
/* .... Debug interface ..................................................... */
#ifdef CONFIG_DEBUG_FS
static int ks8695_gpio_show(struct seq_file *s, void *unused)
{
unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN };
unsigned int intmask[] = { IOPC_IOEINT0TM, IOPC_IOEINT1TM, IOPC_IOEINT2TM, IOPC_IOEINT3TM };
unsigned long mode, ctrl, data;
int i;
mode = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
ctrl = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
data = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
seq_printf(s, "Pin\tI/O\tFunction\tState\n\n");
for (i = KS8695_GPIO_0; i <= KS8695_GPIO_15 ; i++) {
seq_printf(s, "%i:\t", i);
seq_printf(s, "%s\t", (mode & IOPM(i)) ? "Output" : "Input");
if (i <= KS8695_GPIO_3) {
if (ctrl & enable[i]) {
seq_printf(s, "EXT%i ", i);
switch ((ctrl & intmask[i]) >> (4 * i)) {
case IOPC_TM_LOW:
seq_printf(s, "(Low)"); break;
case IOPC_TM_HIGH:
seq_printf(s, "(High)"); break;
case IOPC_TM_RISING:
seq_printf(s, "(Rising)"); break;
case IOPC_TM_FALLING:
seq_printf(s, "(Falling)"); break;
case IOPC_TM_EDGE:
seq_printf(s, "(Edges)"); break;
}
} else
seq_printf(s, "GPIO\t");
} else if (i <= KS8695_GPIO_5) {
if (ctrl & enable[i])
seq_printf(s, "TOUT%i\t", i - KS8695_GPIO_4);
else
seq_printf(s, "GPIO\t");
} else {
seq_printf(s, "GPIO\t");
}
seq_printf(s, "\t");
seq_printf(s, "%i\n", (data & IOPD(i)) ? 1 : 0);
}
return 0;
}
DEFINE_SHOW_ATTRIBUTE(ks8695_gpio);
static int __init ks8695_gpio_debugfs_init(void)
{
/* /sys/kernel/debug/ks8695_gpio */
debugfs_create_file("ks8695_gpio", S_IFREG | S_IRUGO, NULL, NULL,
&ks8695_gpio_fops);
return 0;
}
postcore_initcall(ks8695_gpio_debugfs_init);
#endif
...@@ -16,36 +16,33 @@ ...@@ -16,36 +16,33 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/module.h> #include <linux/module.h>
#include <mach/hardware.h> #define LPC32XX_GPIO_P3_INP_STATE (0x000)
#include <mach/platform.h> #define LPC32XX_GPIO_P3_OUTP_SET (0x004)
#define LPC32XX_GPIO_P3_OUTP_CLR (0x008)
#define LPC32XX_GPIO_P3_INP_STATE _GPREG(0x000) #define LPC32XX_GPIO_P3_OUTP_STATE (0x00C)
#define LPC32XX_GPIO_P3_OUTP_SET _GPREG(0x004) #define LPC32XX_GPIO_P2_DIR_SET (0x010)
#define LPC32XX_GPIO_P3_OUTP_CLR _GPREG(0x008) #define LPC32XX_GPIO_P2_DIR_CLR (0x014)
#define LPC32XX_GPIO_P3_OUTP_STATE _GPREG(0x00C) #define LPC32XX_GPIO_P2_DIR_STATE (0x018)
#define LPC32XX_GPIO_P2_DIR_SET _GPREG(0x010) #define LPC32XX_GPIO_P2_INP_STATE (0x01C)
#define LPC32XX_GPIO_P2_DIR_CLR _GPREG(0x014) #define LPC32XX_GPIO_P2_OUTP_SET (0x020)
#define LPC32XX_GPIO_P2_DIR_STATE _GPREG(0x018) #define LPC32XX_GPIO_P2_OUTP_CLR (0x024)
#define LPC32XX_GPIO_P2_INP_STATE _GPREG(0x01C) #define LPC32XX_GPIO_P2_MUX_SET (0x028)
#define LPC32XX_GPIO_P2_OUTP_SET _GPREG(0x020) #define LPC32XX_GPIO_P2_MUX_CLR (0x02C)
#define LPC32XX_GPIO_P2_OUTP_CLR _GPREG(0x024) #define LPC32XX_GPIO_P2_MUX_STATE (0x030)
#define LPC32XX_GPIO_P2_MUX_SET _GPREG(0x028) #define LPC32XX_GPIO_P0_INP_STATE (0x040)
#define LPC32XX_GPIO_P2_MUX_CLR _GPREG(0x02C) #define LPC32XX_GPIO_P0_OUTP_SET (0x044)
#define LPC32XX_GPIO_P2_MUX_STATE _GPREG(0x030) #define LPC32XX_GPIO_P0_OUTP_CLR (0x048)
#define LPC32XX_GPIO_P0_INP_STATE _GPREG(0x040) #define LPC32XX_GPIO_P0_OUTP_STATE (0x04C)
#define LPC32XX_GPIO_P0_OUTP_SET _GPREG(0x044) #define LPC32XX_GPIO_P0_DIR_SET (0x050)
#define LPC32XX_GPIO_P0_OUTP_CLR _GPREG(0x048) #define LPC32XX_GPIO_P0_DIR_CLR (0x054)
#define LPC32XX_GPIO_P0_OUTP_STATE _GPREG(0x04C) #define LPC32XX_GPIO_P0_DIR_STATE (0x058)
#define LPC32XX_GPIO_P0_DIR_SET _GPREG(0x050) #define LPC32XX_GPIO_P1_INP_STATE (0x060)
#define LPC32XX_GPIO_P0_DIR_CLR _GPREG(0x054) #define LPC32XX_GPIO_P1_OUTP_SET (0x064)
#define LPC32XX_GPIO_P0_DIR_STATE _GPREG(0x058) #define LPC32XX_GPIO_P1_OUTP_CLR (0x068)
#define LPC32XX_GPIO_P1_INP_STATE _GPREG(0x060) #define LPC32XX_GPIO_P1_OUTP_STATE (0x06C)
#define LPC32XX_GPIO_P1_OUTP_SET _GPREG(0x064) #define LPC32XX_GPIO_P1_DIR_SET (0x070)
#define LPC32XX_GPIO_P1_OUTP_CLR _GPREG(0x068) #define LPC32XX_GPIO_P1_DIR_CLR (0x074)
#define LPC32XX_GPIO_P1_OUTP_STATE _GPREG(0x06C) #define LPC32XX_GPIO_P1_DIR_STATE (0x078)
#define LPC32XX_GPIO_P1_DIR_SET _GPREG(0x070)
#define LPC32XX_GPIO_P1_DIR_CLR _GPREG(0x074)
#define LPC32XX_GPIO_P1_DIR_STATE _GPREG(0x078)
#define GPIO012_PIN_TO_BIT(x) (1 << (x)) #define GPIO012_PIN_TO_BIT(x) (1 << (x))
#define GPIO3_PIN_TO_BIT(x) (1 << ((x) + 25)) #define GPIO3_PIN_TO_BIT(x) (1 << ((x) + 25))
...@@ -72,12 +69,12 @@ ...@@ -72,12 +69,12 @@
#define LPC32XX_GPO_P3_GRP (LPC32XX_GPI_P3_GRP + LPC32XX_GPI_P3_MAX) #define LPC32XX_GPO_P3_GRP (LPC32XX_GPI_P3_GRP + LPC32XX_GPI_P3_MAX)
struct gpio_regs { struct gpio_regs {
void __iomem *inp_state; unsigned long inp_state;
void __iomem *outp_state; unsigned long outp_state;
void __iomem *outp_set; unsigned long outp_set;
void __iomem *outp_clr; unsigned long outp_clr;
void __iomem *dir_set; unsigned long dir_set;
void __iomem *dir_clr; unsigned long dir_clr;
}; };
/* /*
...@@ -165,16 +162,27 @@ static struct gpio_regs gpio_grp_regs_p3 = { ...@@ -165,16 +162,27 @@ static struct gpio_regs gpio_grp_regs_p3 = {
struct lpc32xx_gpio_chip { struct lpc32xx_gpio_chip {
struct gpio_chip chip; struct gpio_chip chip;
struct gpio_regs *gpio_grp; struct gpio_regs *gpio_grp;
void __iomem *reg_base;
}; };
static inline u32 gpreg_read(struct lpc32xx_gpio_chip *group, unsigned long offset)
{
return __raw_readl(group->reg_base + offset);
}
static inline void gpreg_write(struct lpc32xx_gpio_chip *group, u32 val, unsigned long offset)
{
__raw_writel(val, group->reg_base + offset);
}
static void __set_gpio_dir_p012(struct lpc32xx_gpio_chip *group, static void __set_gpio_dir_p012(struct lpc32xx_gpio_chip *group,
unsigned pin, int input) unsigned pin, int input)
{ {
if (input) if (input)
__raw_writel(GPIO012_PIN_TO_BIT(pin), gpreg_write(group, GPIO012_PIN_TO_BIT(pin),
group->gpio_grp->dir_clr); group->gpio_grp->dir_clr);
else else
__raw_writel(GPIO012_PIN_TO_BIT(pin), gpreg_write(group, GPIO012_PIN_TO_BIT(pin),
group->gpio_grp->dir_set); group->gpio_grp->dir_set);
} }
...@@ -184,19 +192,19 @@ static void __set_gpio_dir_p3(struct lpc32xx_gpio_chip *group, ...@@ -184,19 +192,19 @@ static void __set_gpio_dir_p3(struct lpc32xx_gpio_chip *group,
u32 u = GPIO3_PIN_TO_BIT(pin); u32 u = GPIO3_PIN_TO_BIT(pin);
if (input) if (input)
__raw_writel(u, group->gpio_grp->dir_clr); gpreg_write(group, u, group->gpio_grp->dir_clr);
else else
__raw_writel(u, group->gpio_grp->dir_set); gpreg_write(group, u, group->gpio_grp->dir_set);
} }
static void __set_gpio_level_p012(struct lpc32xx_gpio_chip *group, static void __set_gpio_level_p012(struct lpc32xx_gpio_chip *group,
unsigned pin, int high) unsigned pin, int high)
{ {
if (high) if (high)
__raw_writel(GPIO012_PIN_TO_BIT(pin), gpreg_write(group, GPIO012_PIN_TO_BIT(pin),
group->gpio_grp->outp_set); group->gpio_grp->outp_set);
else else
__raw_writel(GPIO012_PIN_TO_BIT(pin), gpreg_write(group, GPIO012_PIN_TO_BIT(pin),
group->gpio_grp->outp_clr); group->gpio_grp->outp_clr);
} }
...@@ -206,31 +214,31 @@ static void __set_gpio_level_p3(struct lpc32xx_gpio_chip *group, ...@@ -206,31 +214,31 @@ static void __set_gpio_level_p3(struct lpc32xx_gpio_chip *group,
u32 u = GPIO3_PIN_TO_BIT(pin); u32 u = GPIO3_PIN_TO_BIT(pin);
if (high) if (high)
__raw_writel(u, group->gpio_grp->outp_set); gpreg_write(group, u, group->gpio_grp->outp_set);
else else
__raw_writel(u, group->gpio_grp->outp_clr); gpreg_write(group, u, group->gpio_grp->outp_clr);
} }
static void __set_gpo_level_p3(struct lpc32xx_gpio_chip *group, static void __set_gpo_level_p3(struct lpc32xx_gpio_chip *group,
unsigned pin, int high) unsigned pin, int high)
{ {
if (high) if (high)
__raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_set); gpreg_write(group, GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_set);
else else
__raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_clr); gpreg_write(group, GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_clr);
} }
static int __get_gpio_state_p012(struct lpc32xx_gpio_chip *group, static int __get_gpio_state_p012(struct lpc32xx_gpio_chip *group,
unsigned pin) unsigned pin)
{ {
return GPIO012_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state), return GPIO012_PIN_IN_SEL(gpreg_read(group, group->gpio_grp->inp_state),
pin); pin);
} }
static int __get_gpio_state_p3(struct lpc32xx_gpio_chip *group, static int __get_gpio_state_p3(struct lpc32xx_gpio_chip *group,
unsigned pin) unsigned pin)
{ {
int state = __raw_readl(group->gpio_grp->inp_state); int state = gpreg_read(group, group->gpio_grp->inp_state);
/* /*
* P3 GPIO pin input mapping is not contiguous, GPIOP3-0..4 is mapped * P3 GPIO pin input mapping is not contiguous, GPIOP3-0..4 is mapped
...@@ -242,13 +250,13 @@ static int __get_gpio_state_p3(struct lpc32xx_gpio_chip *group, ...@@ -242,13 +250,13 @@ static int __get_gpio_state_p3(struct lpc32xx_gpio_chip *group,
static int __get_gpi_state_p3(struct lpc32xx_gpio_chip *group, static int __get_gpi_state_p3(struct lpc32xx_gpio_chip *group,
unsigned pin) unsigned pin)
{ {
return GPI3_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state), pin); return GPI3_PIN_IN_SEL(gpreg_read(group, group->gpio_grp->inp_state), pin);
} }
static int __get_gpo_state_p3(struct lpc32xx_gpio_chip *group, static int __get_gpo_state_p3(struct lpc32xx_gpio_chip *group,
unsigned pin) unsigned pin)
{ {
return GPO3_PIN_IN_SEL(__raw_readl(group->gpio_grp->outp_state), pin); return GPO3_PIN_IN_SEL(gpreg_read(group, group->gpio_grp->outp_state), pin);
} }
/* /*
...@@ -497,12 +505,18 @@ static int lpc32xx_of_xlate(struct gpio_chip *gc, ...@@ -497,12 +505,18 @@ static int lpc32xx_of_xlate(struct gpio_chip *gc,
static int lpc32xx_gpio_probe(struct platform_device *pdev) static int lpc32xx_gpio_probe(struct platform_device *pdev)
{ {
int i; int i;
void __iomem *reg_base;
reg_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(reg_base))
return PTR_ERR(reg_base);
for (i = 0; i < ARRAY_SIZE(lpc32xx_gpiochip); i++) { for (i = 0; i < ARRAY_SIZE(lpc32xx_gpiochip); i++) {
if (pdev->dev.of_node) { if (pdev->dev.of_node) {
lpc32xx_gpiochip[i].chip.of_xlate = lpc32xx_of_xlate; lpc32xx_gpiochip[i].chip.of_xlate = lpc32xx_of_xlate;
lpc32xx_gpiochip[i].chip.of_gpio_n_cells = 3; lpc32xx_gpiochip[i].chip.of_gpio_n_cells = 3;
lpc32xx_gpiochip[i].chip.of_node = pdev->dev.of_node; lpc32xx_gpiochip[i].chip.of_node = pdev->dev.of_node;
lpc32xx_gpiochip[i].reg_base = reg_base;
} }
devm_gpiochip_add_data(&pdev->dev, &lpc32xx_gpiochip[i].chip, devm_gpiochip_add_data(&pdev->dev, &lpc32xx_gpiochip[i].chip,
&lpc32xx_gpiochip[i]); &lpc32xx_gpiochip[i]);
...@@ -527,3 +541,7 @@ static struct platform_driver lpc32xx_gpio_driver = { ...@@ -527,3 +541,7 @@ static struct platform_driver lpc32xx_gpio_driver = {
}; };
module_platform_driver(lpc32xx_gpio_driver); module_platform_driver(lpc32xx_gpio_driver);
MODULE_AUTHOR("Kevin Wells <kevin.wells@nxp.com>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("GPIO driver for LPC32xx SoC");
...@@ -358,25 +358,30 @@ static int lp_gpio_probe(struct platform_device *pdev) ...@@ -358,25 +358,30 @@ static int lp_gpio_probe(struct platform_device *pdev)
gc->can_sleep = false; gc->can_sleep = false;
gc->parent = dev; gc->parent = dev;
ret = devm_gpiochip_add_data(dev, gc, lg);
if (ret) {
dev_err(dev, "failed adding lp-gpio chip\n");
return ret;
}
/* set up interrupts */ /* set up interrupts */
if (irq_rc && irq_rc->start) { if (irq_rc && irq_rc->start) {
struct gpio_irq_chip *girq;
girq = &gc->irq;
girq->chip = &lp_irqchip;
girq->parent_handler = lp_gpio_irq_handler;
girq->num_parents = 1;
girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents,
sizeof(*girq->parents),
GFP_KERNEL);
if (!girq->parents)
return -ENOMEM;
girq->parents[0] = (unsigned)irq_rc->start;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_simple_irq;
lp_gpio_irq_init_hw(lg); lp_gpio_irq_init_hw(lg);
ret = gpiochip_irqchip_add(gc, &lp_irqchip, 0,
handle_simple_irq, IRQ_TYPE_NONE);
if (ret) {
dev_err(dev, "failed to add irqchip\n");
return ret;
} }
gpiochip_set_chained_irqchip(gc, &lp_irqchip, ret = devm_gpiochip_add_data(dev, gc, lg);
(unsigned)irq_rc->start, if (ret) {
lp_gpio_irq_handler); dev_err(dev, "failed adding lp-gpio chip\n");
return ret;
} }
pm_runtime_enable(dev); pm_runtime_enable(dev);
......
...@@ -120,7 +120,7 @@ static const struct gpio_chip madera_gpio_chip = { ...@@ -120,7 +120,7 @@ static const struct gpio_chip madera_gpio_chip = {
static int madera_gpio_probe(struct platform_device *pdev) static int madera_gpio_probe(struct platform_device *pdev)
{ {
struct madera *madera = dev_get_drvdata(pdev->dev.parent); struct madera *madera = dev_get_drvdata(pdev->dev.parent);
struct madera_pdata *pdata = dev_get_platdata(madera->dev); struct madera_pdata *pdata = &madera->pdata;
struct madera_gpio *madera_gpio; struct madera_gpio *madera_gpio;
int ret; int ret;
...@@ -136,6 +136,9 @@ static int madera_gpio_probe(struct platform_device *pdev) ...@@ -136,6 +136,9 @@ static int madera_gpio_probe(struct platform_device *pdev)
madera_gpio->gpio_chip.parent = pdev->dev.parent; madera_gpio->gpio_chip.parent = pdev->dev.parent;
switch (madera->type) { switch (madera->type) {
case CS47L15:
madera_gpio->gpio_chip.ngpio = CS47L15_NUM_GPIOS;
break;
case CS47L35: case CS47L35:
madera_gpio->gpio_chip.ngpio = CS47L35_NUM_GPIOS; madera_gpio->gpio_chip.ngpio = CS47L35_NUM_GPIOS;
break; break;
...@@ -147,13 +150,18 @@ static int madera_gpio_probe(struct platform_device *pdev) ...@@ -147,13 +150,18 @@ static int madera_gpio_probe(struct platform_device *pdev)
case CS47L91: case CS47L91:
madera_gpio->gpio_chip.ngpio = CS47L90_NUM_GPIOS; madera_gpio->gpio_chip.ngpio = CS47L90_NUM_GPIOS;
break; break;
case CS42L92:
case CS47L92:
case CS47L93:
madera_gpio->gpio_chip.ngpio = CS47L92_NUM_GPIOS;
break;
default: default:
dev_err(&pdev->dev, "Unknown chip variant %d\n", madera->type); dev_err(&pdev->dev, "Unknown chip variant %d\n", madera->type);
return -EINVAL; return -EINVAL;
} }
/* We want to be usable on systems that don't use devicetree or acpi */ /* We want to be usable on systems that don't use devicetree or acpi */
if (pdata && pdata->gpio_base) if (pdata->gpio_base)
madera_gpio->gpio_chip.base = pdata->gpio_base; madera_gpio->gpio_chip.base = pdata->gpio_base;
else else
madera_gpio->gpio_chip.base = -1; madera_gpio->gpio_chip.base = -1;
......
...@@ -270,10 +270,8 @@ static int max77620_gpio_probe(struct platform_device *pdev) ...@@ -270,10 +270,8 @@ static int max77620_gpio_probe(struct platform_device *pdev)
int ret; int ret;
gpio_irq = platform_get_irq(pdev, 0); gpio_irq = platform_get_irq(pdev, 0);
if (gpio_irq <= 0) { if (gpio_irq <= 0)
dev_err(&pdev->dev, "GPIO irq not available %d\n", gpio_irq);
return -ENODEV; return -ENODEV;
}
mgpio = devm_kzalloc(&pdev->dev, sizeof(*mgpio), GFP_KERNEL); mgpio = devm_kzalloc(&pdev->dev, sizeof(*mgpio), GFP_KERNEL);
if (!mgpio) if (!mgpio)
......
...@@ -188,3 +188,4 @@ module_platform_driver(max77650_gpio_driver); ...@@ -188,3 +188,4 @@ module_platform_driver(max77650_gpio_driver);
MODULE_DESCRIPTION("MAXIM 77650/77651 GPIO driver"); MODULE_DESCRIPTION("MAXIM 77650/77651 GPIO driver");
MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>"); MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:max77650-gpio");
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include "gpiolib.h" #include "gpiolib.h"
#include "gpiolib-acpi.h"
/* /*
* Only first 8bits of a register correspond to each pin, * Only first 8bits of a register correspond to each pin,
......
...@@ -397,6 +397,7 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id ...@@ -397,6 +397,7 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id
{ {
const struct mrfld_gpio_pinrange *range; const struct mrfld_gpio_pinrange *range;
const char *pinctrl_dev_name; const char *pinctrl_dev_name;
struct gpio_irq_chip *girq;
struct mrfld_gpio *priv; struct mrfld_gpio *priv;
u32 gpio_base, irq_base; u32 gpio_base, irq_base;
void __iomem *base; void __iomem *base;
...@@ -444,6 +445,21 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id ...@@ -444,6 +445,21 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id
raw_spin_lock_init(&priv->lock); raw_spin_lock_init(&priv->lock);
girq = &priv->chip.irq;
girq->chip = &mrfld_irqchip;
girq->parent_handler = mrfld_irq_handler;
girq->num_parents = 1;
girq->parents = devm_kcalloc(&pdev->dev, girq->num_parents,
sizeof(*girq->parents),
GFP_KERNEL);
if (!girq->parents)
return -ENOMEM;
girq->parents[0] = pdev->irq;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_bad_irq;
mrfld_irq_init_hw(priv);
pci_set_drvdata(pdev, priv); pci_set_drvdata(pdev, priv);
retval = devm_gpiochip_add_data(&pdev->dev, &priv->chip, priv); retval = devm_gpiochip_add_data(&pdev->dev, &priv->chip, priv);
if (retval) { if (retval) {
...@@ -465,18 +481,6 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id ...@@ -465,18 +481,6 @@ static int mrfld_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id
} }
} }
retval = gpiochip_irqchip_add(&priv->chip, &mrfld_irqchip, irq_base,
handle_bad_irq, IRQ_TYPE_NONE);
if (retval) {
dev_err(&pdev->dev, "could not connect irqchip to gpiochip\n");
return retval;
}
mrfld_irq_init_hw(priv);
gpiochip_set_chained_irqchip(&priv->chip, &mrfld_irqchip, pdev->irq,
mrfld_irq_handler);
return 0; return 0;
} }
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#define GPIO_IMR 0x10 #define GPIO_IMR 0x10
#define GPIO_ICR 0x14 #define GPIO_ICR 0x14
#define GPIO_ICR2 0x18 #define GPIO_ICR2 0x18
#define GPIO_IBE 0x18
struct mpc8xxx_gpio_chip { struct mpc8xxx_gpio_chip {
struct gpio_chip gc; struct gpio_chip gc;
...@@ -45,6 +46,27 @@ struct mpc8xxx_gpio_chip { ...@@ -45,6 +46,27 @@ struct mpc8xxx_gpio_chip {
unsigned int irqn; unsigned int irqn;
}; };
/* The GPIO Input Buffer Enable register(GPIO_IBE) is used to
* control the input enable of each individual GPIO port.
* When an individual GPIO port’s direction is set to
* input (GPIO_GPDIR[DRn=0]), the associated input enable must be
* set (GPIOxGPIE[IEn]=1) to propagate the port value to the GPIO
* Data Register.
*/
static int ls1028a_gpio_dir_in_init(struct gpio_chip *gc)
{
unsigned long flags;
struct mpc8xxx_gpio_chip *mpc8xxx_gc = gpiochip_get_data(gc);
spin_lock_irqsave(&gc->bgpio_lock, flags);
gc->write_reg(mpc8xxx_gc->regs + GPIO_IBE, 0xffffffff);
spin_unlock_irqrestore(&gc->bgpio_lock, flags);
return 0;
}
/* /*
* This hardware has a big endian bit assignment such that GPIO line 0 is * This hardware has a big endian bit assignment such that GPIO line 0 is
* connected to bit 31, line 1 to bit 30 ... line 31 to bit 0. * connected to bit 31, line 1 to bit 30 ... line 31 to bit 0.
...@@ -261,6 +283,7 @@ static const struct irq_domain_ops mpc8xxx_gpio_irq_ops = { ...@@ -261,6 +283,7 @@ static const struct irq_domain_ops mpc8xxx_gpio_irq_ops = {
}; };
struct mpc8xxx_gpio_devtype { struct mpc8xxx_gpio_devtype {
int (*gpio_dir_in_init)(struct gpio_chip *chip);
int (*gpio_dir_out)(struct gpio_chip *, unsigned int, int); int (*gpio_dir_out)(struct gpio_chip *, unsigned int, int);
int (*gpio_get)(struct gpio_chip *, unsigned int); int (*gpio_get)(struct gpio_chip *, unsigned int);
int (*irq_set_type)(struct irq_data *, unsigned int); int (*irq_set_type)(struct irq_data *, unsigned int);
...@@ -271,6 +294,10 @@ static const struct mpc8xxx_gpio_devtype mpc512x_gpio_devtype = { ...@@ -271,6 +294,10 @@ static const struct mpc8xxx_gpio_devtype mpc512x_gpio_devtype = {
.irq_set_type = mpc512x_irq_set_type, .irq_set_type = mpc512x_irq_set_type,
}; };
static const struct mpc8xxx_gpio_devtype ls1028a_gpio_devtype = {
.gpio_dir_in_init = ls1028a_gpio_dir_in_init,
};
static const struct mpc8xxx_gpio_devtype mpc5125_gpio_devtype = { static const struct mpc8xxx_gpio_devtype mpc5125_gpio_devtype = {
.gpio_dir_out = mpc5125_gpio_dir_out, .gpio_dir_out = mpc5125_gpio_dir_out,
.irq_set_type = mpc512x_irq_set_type, .irq_set_type = mpc512x_irq_set_type,
...@@ -291,6 +318,8 @@ static const struct of_device_id mpc8xxx_gpio_ids[] = { ...@@ -291,6 +318,8 @@ static const struct of_device_id mpc8xxx_gpio_ids[] = {
{ .compatible = "fsl,mpc5121-gpio", .data = &mpc512x_gpio_devtype, }, { .compatible = "fsl,mpc5121-gpio", .data = &mpc512x_gpio_devtype, },
{ .compatible = "fsl,mpc5125-gpio", .data = &mpc5125_gpio_devtype, }, { .compatible = "fsl,mpc5125-gpio", .data = &mpc5125_gpio_devtype, },
{ .compatible = "fsl,pq3-gpio", }, { .compatible = "fsl,pq3-gpio", },
{ .compatible = "fsl,ls1028a-gpio", .data = &ls1028a_gpio_devtype, },
{ .compatible = "fsl,ls1088a-gpio", .data = &ls1028a_gpio_devtype, },
{ .compatible = "fsl,qoriq-gpio", }, { .compatible = "fsl,qoriq-gpio", },
{} {}
}; };
...@@ -376,6 +405,9 @@ static int mpc8xxx_probe(struct platform_device *pdev) ...@@ -376,6 +405,9 @@ static int mpc8xxx_probe(struct platform_device *pdev)
/* ack and mask all irqs */ /* ack and mask all irqs */
gc->write_reg(mpc8xxx_gc->regs + GPIO_IER, 0xffffffff); gc->write_reg(mpc8xxx_gc->regs + GPIO_IER, 0xffffffff);
gc->write_reg(mpc8xxx_gc->regs + GPIO_IMR, 0); gc->write_reg(mpc8xxx_gc->regs + GPIO_IMR, 0);
/* enable input buffer */
if (devtype->gpio_dir_in_init)
devtype->gpio_dir_in_init(gc);
irq_set_chained_handler_and_data(mpc8xxx_gc->irqn, irq_set_chained_handler_and_data(mpc8xxx_gc->irqn,
mpc8xxx_gpio_irq_cascade, mpc8xxx_gc); mpc8xxx_gpio_irq_cascade, mpc8xxx_gc);
......
...@@ -241,13 +241,6 @@ mediatek_gpio_bank_probe(struct device *dev, ...@@ -241,13 +241,6 @@ mediatek_gpio_bank_probe(struct device *dev,
if (!rg->chip.label) if (!rg->chip.label)
return -ENOMEM; return -ENOMEM;
ret = devm_gpiochip_add_data(dev, &rg->chip, mtk);
if (ret < 0) {
dev_err(dev, "Could not register gpio %d, ret=%d\n",
rg->chip.ngpio, ret);
return ret;
}
rg->irq_chip.name = dev_name(dev); rg->irq_chip.name = dev_name(dev);
rg->irq_chip.parent_device = dev; rg->irq_chip.parent_device = dev;
rg->irq_chip.irq_unmask = mediatek_gpio_irq_unmask; rg->irq_chip.irq_unmask = mediatek_gpio_irq_unmask;
...@@ -256,8 +249,10 @@ mediatek_gpio_bank_probe(struct device *dev, ...@@ -256,8 +249,10 @@ mediatek_gpio_bank_probe(struct device *dev,
rg->irq_chip.irq_set_type = mediatek_gpio_irq_type; rg->irq_chip.irq_set_type = mediatek_gpio_irq_type;
if (mtk->gpio_irq) { if (mtk->gpio_irq) {
struct gpio_irq_chip *girq;
/* /*
* Manually request the irq here instead of passing * Directly request the irq here instead of passing
* a flow-handler to gpiochip_set_chained_irqchip, * a flow-handler to gpiochip_set_chained_irqchip,
* because the irq is shared. * because the irq is shared.
*/ */
...@@ -271,15 +266,21 @@ mediatek_gpio_bank_probe(struct device *dev, ...@@ -271,15 +266,21 @@ mediatek_gpio_bank_probe(struct device *dev,
return ret; return ret;
} }
ret = gpiochip_irqchip_add(&rg->chip, &rg->irq_chip, girq = &rg->chip.irq;
0, handle_simple_irq, IRQ_TYPE_NONE); girq->chip = &rg->irq_chip;
if (ret) { /* This will let us handle the parent IRQ in the driver */
dev_err(dev, "failed to add gpiochip_irqchip\n"); girq->parent_handler = NULL;
return ret; girq->num_parents = 0;
girq->parents = NULL;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_simple_irq;
} }
gpiochip_set_chained_irqchip(&rg->chip, &rg->irq_chip, ret = devm_gpiochip_add_data(dev, &rg->chip, mtk);
mtk->gpio_irq, NULL); if (ret < 0) {
dev_err(dev, "Could not register gpio %d, ret=%d\n",
rg->chip.ngpio, ret);
return ret;
} }
/* set polarity to low for all gpios */ /* set polarity to low for all gpios */
......
...@@ -435,12 +435,9 @@ static int mxc_gpio_probe(struct platform_device *pdev) ...@@ -435,12 +435,9 @@ static int mxc_gpio_probe(struct platform_device *pdev)
return port->irq; return port->irq;
/* the controller clock is optional */ /* the controller clock is optional */
port->clk = devm_clk_get(&pdev->dev, NULL); port->clk = devm_clk_get_optional(&pdev->dev, NULL);
if (IS_ERR(port->clk)) { if (IS_ERR(port->clk))
if (PTR_ERR(port->clk) == -EPROBE_DEFER) return PTR_ERR(port->clk);
return -EPROBE_DEFER;
port->clk = NULL;
}
err = clk_prepare_enable(port->clk); err = clk_prepare_enable(port->clk);
if (err) { if (err) {
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
*/ */
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/bits.h>
#include <linux/gpio/driver.h> #include <linux/gpio/driver.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/i2c.h> #include <linux/i2c.h>
...@@ -28,9 +29,9 @@ ...@@ -28,9 +29,9 @@
#define PCA953X_INVERT 0x02 #define PCA953X_INVERT 0x02
#define PCA953X_DIRECTION 0x03 #define PCA953X_DIRECTION 0x03
#define REG_ADDR_MASK 0x3f #define REG_ADDR_MASK GENMASK(5, 0)
#define REG_ADDR_EXT 0x40 #define REG_ADDR_EXT BIT(6)
#define REG_ADDR_AI 0x80 #define REG_ADDR_AI BIT(7)
#define PCA957X_IN 0x00 #define PCA957X_IN 0x00
#define PCA957X_INVRT 0x01 #define PCA957X_INVRT 0x01
...@@ -55,17 +56,17 @@ ...@@ -55,17 +56,17 @@
#define PCAL6524_OUT_INDCONF 0x2c #define PCAL6524_OUT_INDCONF 0x2c
#define PCAL6524_DEBOUNCE 0x2d #define PCAL6524_DEBOUNCE 0x2d
#define PCA_GPIO_MASK 0x00FF #define PCA_GPIO_MASK GENMASK(7, 0)
#define PCAL_GPIO_MASK 0x1f #define PCAL_GPIO_MASK GENMASK(4, 0)
#define PCAL_PINCTRL_MASK 0x60 #define PCAL_PINCTRL_MASK GENMASK(6, 5)
#define PCA_INT 0x0100 #define PCA_INT BIT(8)
#define PCA_PCAL 0x0200 #define PCA_PCAL BIT(9)
#define PCA_LATCH_INT (PCA_PCAL | PCA_INT) #define PCA_LATCH_INT (PCA_PCAL | PCA_INT)
#define PCA953X_TYPE 0x1000 #define PCA953X_TYPE BIT(12)
#define PCA957X_TYPE 0x2000 #define PCA957X_TYPE BIT(13)
#define PCA_TYPE_MASK 0xF000 #define PCA_TYPE_MASK GENMASK(15, 12)
#define PCA_CHIP_TYPE(x) ((x) & PCA_TYPE_MASK) #define PCA_CHIP_TYPE(x) ((x) & PCA_TYPE_MASK)
...@@ -565,7 +566,7 @@ static void pca953x_irq_mask(struct irq_data *d) ...@@ -565,7 +566,7 @@ static void pca953x_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 pca953x_chip *chip = gpiochip_get_data(gc); struct pca953x_chip *chip = gpiochip_get_data(gc);
chip->irq_mask[d->hwirq / BANK_SZ] &= ~(1 << (d->hwirq % BANK_SZ)); chip->irq_mask[d->hwirq / BANK_SZ] &= ~BIT(d->hwirq % BANK_SZ);
} }
static void pca953x_irq_unmask(struct irq_data *d) static void pca953x_irq_unmask(struct irq_data *d)
...@@ -573,7 +574,7 @@ static void pca953x_irq_unmask(struct irq_data *d) ...@@ -573,7 +574,7 @@ static void pca953x_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 pca953x_chip *chip = gpiochip_get_data(gc); struct pca953x_chip *chip = gpiochip_get_data(gc);
chip->irq_mask[d->hwirq / BANK_SZ] |= 1 << (d->hwirq % BANK_SZ); chip->irq_mask[d->hwirq / BANK_SZ] |= BIT(d->hwirq % BANK_SZ);
} }
static int pca953x_irq_set_wake(struct irq_data *d, unsigned int on) static int pca953x_irq_set_wake(struct irq_data *d, unsigned int on)
...@@ -640,7 +641,7 @@ static int pca953x_irq_set_type(struct irq_data *d, unsigned int type) ...@@ -640,7 +641,7 @@ static int pca953x_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 pca953x_chip *chip = gpiochip_get_data(gc); struct pca953x_chip *chip = gpiochip_get_data(gc);
int bank_nb = d->hwirq / BANK_SZ; int bank_nb = d->hwirq / BANK_SZ;
u8 mask = 1 << (d->hwirq % BANK_SZ); u8 mask = BIT(d->hwirq % BANK_SZ);
if (!(type & IRQ_TYPE_EDGE_BOTH)) { if (!(type & IRQ_TYPE_EDGE_BOTH)) {
dev_err(&chip->client->dev, "irq %d: unsupported type %d\n", dev_err(&chip->client->dev, "irq %d: unsupported type %d\n",
...@@ -665,7 +666,7 @@ static void pca953x_irq_shutdown(struct irq_data *d) ...@@ -665,7 +666,7 @@ static void pca953x_irq_shutdown(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 pca953x_chip *chip = gpiochip_get_data(gc); struct pca953x_chip *chip = gpiochip_get_data(gc);
u8 mask = 1 << (d->hwirq % BANK_SZ); u8 mask = BIT(d->hwirq % BANK_SZ);
chip->irq_trig_raise[d->hwirq / BANK_SZ] &= ~mask; chip->irq_trig_raise[d->hwirq / BANK_SZ] &= ~mask;
chip->irq_trig_fall[d->hwirq / BANK_SZ] &= ~mask; chip->irq_trig_fall[d->hwirq / BANK_SZ] &= ~mask;
...@@ -846,12 +847,12 @@ static int device_pca95xx_init(struct pca953x_chip *chip, u32 invert) ...@@ -846,12 +847,12 @@ static int device_pca95xx_init(struct pca953x_chip *chip, u32 invert)
ret = regcache_sync_region(chip->regmap, chip->regs->output, ret = regcache_sync_region(chip->regmap, chip->regs->output,
chip->regs->output + NBANK(chip)); chip->regs->output + NBANK(chip));
if (ret != 0) if (ret)
goto out; goto out;
ret = regcache_sync_region(chip->regmap, chip->regs->direction, ret = regcache_sync_region(chip->regmap, chip->regs->direction,
chip->regs->direction + NBANK(chip)); chip->regs->direction + NBANK(chip));
if (ret != 0) if (ret)
goto out; goto out;
/* set platform specific polarity inversion */ /* set platform specific polarity inversion */
...@@ -946,19 +947,15 @@ static int pca953x_probe(struct i2c_client *client, ...@@ -946,19 +947,15 @@ static int pca953x_probe(struct i2c_client *client,
if (i2c_id) { if (i2c_id) {
chip->driver_data = i2c_id->driver_data; chip->driver_data = i2c_id->driver_data;
} else { } else {
const struct acpi_device_id *acpi_id; const void *match;
struct device *dev = &client->dev;
chip->driver_data = (uintptr_t)of_device_get_match_data(dev); match = device_get_match_data(&client->dev);
if (!chip->driver_data) { if (!match) {
acpi_id = acpi_match_device(pca953x_acpi_ids, dev);
if (!acpi_id) {
ret = -ENODEV; ret = -ENODEV;
goto err_exit; goto err_exit;
} }
chip->driver_data = acpi_id->driver_data; chip->driver_data = (uintptr_t)match;
}
} }
i2c_set_clientdata(client, chip); i2c_set_clientdata(client, chip);
...@@ -1038,8 +1035,7 @@ static int pca953x_remove(struct i2c_client *client) ...@@ -1038,8 +1035,7 @@ static int pca953x_remove(struct i2c_client *client)
ret = pdata->teardown(client, chip->gpio_chip.base, ret = pdata->teardown(client, chip->gpio_chip.base,
chip->gpio_chip.ngpio, pdata->context); chip->gpio_chip.ngpio, pdata->context);
if (ret < 0) if (ret < 0)
dev_err(&client->dev, "%s failed, %d\n", dev_err(&client->dev, "teardown failed, %d\n", ret);
"teardown", ret);
} else { } else {
ret = 0; ret = 0;
} }
...@@ -1061,14 +1057,14 @@ static int pca953x_regcache_sync(struct device *dev) ...@@ -1061,14 +1057,14 @@ static int pca953x_regcache_sync(struct device *dev)
*/ */
ret = regcache_sync_region(chip->regmap, chip->regs->direction, ret = regcache_sync_region(chip->regmap, chip->regs->direction,
chip->regs->direction + NBANK(chip)); chip->regs->direction + NBANK(chip));
if (ret != 0) { if (ret) {
dev_err(dev, "Failed to sync GPIO dir registers: %d\n", ret); dev_err(dev, "Failed to sync GPIO dir registers: %d\n", ret);
return ret; return ret;
} }
ret = regcache_sync_region(chip->regmap, chip->regs->output, ret = regcache_sync_region(chip->regmap, chip->regs->output,
chip->regs->output + NBANK(chip)); chip->regs->output + NBANK(chip));
if (ret != 0) { if (ret) {
dev_err(dev, "Failed to sync GPIO out registers: %d\n", ret); dev_err(dev, "Failed to sync GPIO out registers: %d\n", ret);
return ret; return ret;
} }
...@@ -1077,7 +1073,7 @@ static int pca953x_regcache_sync(struct device *dev) ...@@ -1077,7 +1073,7 @@ static int pca953x_regcache_sync(struct device *dev)
if (chip->driver_data & PCA_PCAL) { if (chip->driver_data & PCA_PCAL) {
ret = regcache_sync_region(chip->regmap, PCAL953X_IN_LATCH, ret = regcache_sync_region(chip->regmap, PCAL953X_IN_LATCH,
PCAL953X_IN_LATCH + NBANK(chip)); PCAL953X_IN_LATCH + NBANK(chip));
if (ret != 0) { if (ret) {
dev_err(dev, "Failed to sync INT latch registers: %d\n", dev_err(dev, "Failed to sync INT latch registers: %d\n",
ret); ret);
return ret; return ret;
...@@ -1085,7 +1081,7 @@ static int pca953x_regcache_sync(struct device *dev) ...@@ -1085,7 +1081,7 @@ static int pca953x_regcache_sync(struct device *dev)
ret = regcache_sync_region(chip->regmap, PCAL953X_INT_MASK, ret = regcache_sync_region(chip->regmap, PCAL953X_INT_MASK,
PCAL953X_INT_MASK + NBANK(chip)); PCAL953X_INT_MASK + NBANK(chip));
if (ret != 0) { if (ret) {
dev_err(dev, "Failed to sync INT mask registers: %d\n", dev_err(dev, "Failed to sync INT mask registers: %d\n",
ret); ret);
return ret; return ret;
...@@ -1117,7 +1113,7 @@ static int pca953x_resume(struct device *dev) ...@@ -1117,7 +1113,7 @@ static int pca953x_resume(struct device *dev)
if (!atomic_read(&chip->wakeup_path)) { if (!atomic_read(&chip->wakeup_path)) {
ret = regulator_enable(chip->regulator); ret = regulator_enable(chip->regulator);
if (ret != 0) { if (ret) {
dev_err(dev, "Failed to enable regulator: %d\n", ret); dev_err(dev, "Failed to enable regulator: %d\n", ret);
return 0; return 0;
} }
...@@ -1130,7 +1126,7 @@ static int pca953x_resume(struct device *dev) ...@@ -1130,7 +1126,7 @@ static int pca953x_resume(struct device *dev)
return ret; return ret;
ret = regcache_sync(chip->regmap); ret = regcache_sync(chip->regmap);
if (ret != 0) { if (ret) {
dev_err(dev, "Failed to restore register map: %d\n", ret); dev_err(dev, "Failed to restore register map: %d\n", ret);
return ret; return ret;
} }
......
...@@ -409,8 +409,7 @@ static int pch_gpio_probe(struct pci_dev *pdev, ...@@ -409,8 +409,7 @@ static int pch_gpio_probe(struct pci_dev *pdev,
static int __maybe_unused pch_gpio_suspend(struct device *dev) static int __maybe_unused pch_gpio_suspend(struct device *dev)
{ {
struct pci_dev *pdev = to_pci_dev(dev); struct pch_gpio *chip = dev_get_drvdata(dev);
struct pch_gpio *chip = pci_get_drvdata(pdev);
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&chip->spinlock, flags); spin_lock_irqsave(&chip->spinlock, flags);
...@@ -422,8 +421,7 @@ static int __maybe_unused pch_gpio_suspend(struct device *dev) ...@@ -422,8 +421,7 @@ static int __maybe_unused pch_gpio_suspend(struct device *dev)
static int __maybe_unused pch_gpio_resume(struct device *dev) static int __maybe_unused pch_gpio_resume(struct device *dev)
{ {
struct pci_dev *pdev = to_pci_dev(dev); struct pch_gpio *chip = dev_get_drvdata(dev);
struct pch_gpio *chip = pci_get_drvdata(pdev);
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&chip->spinlock, flags); spin_lock_irqsave(&chip->spinlock, flags);
......
...@@ -305,10 +305,8 @@ static int sprd_pmic_eic_probe(struct platform_device *pdev) ...@@ -305,10 +305,8 @@ static int sprd_pmic_eic_probe(struct platform_device *pdev)
mutex_init(&pmic_eic->buslock); mutex_init(&pmic_eic->buslock);
pmic_eic->irq = platform_get_irq(pdev, 0); pmic_eic->irq = platform_get_irq(pdev, 0);
if (pmic_eic->irq < 0) { if (pmic_eic->irq < 0)
dev_err(&pdev->dev, "Failed to get PMIC EIC interrupt.\n");
return pmic_eic->irq; return pmic_eic->irq;
}
pmic_eic->map = dev_get_regmap(pdev->dev.parent, NULL); pmic_eic->map = dev_get_regmap(pdev->dev.parent, NULL);
if (!pmic_eic->map) if (!pmic_eic->map)
......
...@@ -226,10 +226,8 @@ static int sprd_gpio_probe(struct platform_device *pdev) ...@@ -226,10 +226,8 @@ static int sprd_gpio_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
sprd_gpio->irq = platform_get_irq(pdev, 0); sprd_gpio->irq = platform_get_irq(pdev, 0);
if (sprd_gpio->irq < 0) { if (sprd_gpio->irq < 0)
dev_err(&pdev->dev, "Failed to get GPIO interrupt.\n");
return sprd_gpio->irq; return sprd_gpio->irq;
}
sprd_gpio->base = devm_platform_ioremap_resource(pdev, 0); sprd_gpio->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(sprd_gpio->base)) if (IS_ERR(sprd_gpio->base))
......
...@@ -429,6 +429,23 @@ static irqreturn_t stmpe_gpio_irq(int irq, void *dev) ...@@ -429,6 +429,23 @@ static irqreturn_t stmpe_gpio_irq(int irq, void *dev)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static void stmpe_init_irq_valid_mask(struct gpio_chip *gc,
unsigned long *valid_mask,
unsigned int ngpios)
{
struct stmpe_gpio *stmpe_gpio = gpiochip_get_data(gc);
int i;
if (!stmpe_gpio->norequest_mask)
return;
/* Forbid unused lines to be mapped as IRQs */
for (i = 0; i < sizeof(u32); i++) {
if (stmpe_gpio->norequest_mask & BIT(i))
clear_bit(i, valid_mask);
}
}
static int stmpe_gpio_probe(struct platform_device *pdev) static int stmpe_gpio_probe(struct platform_device *pdev)
{ {
struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
...@@ -454,14 +471,21 @@ static int stmpe_gpio_probe(struct platform_device *pdev) ...@@ -454,14 +471,21 @@ static int stmpe_gpio_probe(struct platform_device *pdev)
stmpe_gpio->chip.parent = &pdev->dev; stmpe_gpio->chip.parent = &pdev->dev;
stmpe_gpio->chip.of_node = np; stmpe_gpio->chip.of_node = np;
stmpe_gpio->chip.base = -1; stmpe_gpio->chip.base = -1;
/*
* REVISIT: this makes sure the valid mask gets allocated and
* filled in when adding the gpio_chip, but the rest of the
* gpio_irqchip is still filled in using the old method
* in gpiochip_irqchip_add_nested() so clean this up once we
* get the gpio_irqchip to initialize while adding the
* gpio_chip also for threaded irqchips.
*/
stmpe_gpio->chip.irq.init_valid_mask = stmpe_init_irq_valid_mask;
if (IS_ENABLED(CONFIG_DEBUG_FS)) if (IS_ENABLED(CONFIG_DEBUG_FS))
stmpe_gpio->chip.dbg_show = stmpe_dbg_show; stmpe_gpio->chip.dbg_show = stmpe_dbg_show;
of_property_read_u32(np, "st,norequest-mask", of_property_read_u32(np, "st,norequest-mask",
&stmpe_gpio->norequest_mask); &stmpe_gpio->norequest_mask);
if (stmpe_gpio->norequest_mask)
stmpe_gpio->chip.irq.need_valid_mask = true;
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq < 0) if (irq < 0)
...@@ -487,14 +511,6 @@ static int stmpe_gpio_probe(struct platform_device *pdev) ...@@ -487,14 +511,6 @@ static int stmpe_gpio_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "unable to get irq: %d\n", ret); dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
goto out_disable; goto out_disable;
} }
if (stmpe_gpio->norequest_mask) {
int i;
/* Forbid unused lines to be mapped as IRQs */
for (i = 0; i < sizeof(u32); i++)
if (stmpe_gpio->norequest_mask & BIT(i))
clear_bit(i, stmpe_gpio->chip.irq.valid_mask);
}
ret = gpiochip_irqchip_add_nested(&stmpe_gpio->chip, ret = gpiochip_irqchip_add_nested(&stmpe_gpio->chip,
&stmpe_gpio_irq_chip, &stmpe_gpio_irq_chip,
0, 0,
......
...@@ -171,10 +171,8 @@ static int tb10x_gpio_probe(struct platform_device *pdev) ...@@ -171,10 +171,8 @@ static int tb10x_gpio_probe(struct platform_device *pdev)
struct irq_chip_generic *gc; struct irq_chip_generic *gc;
ret = platform_get_irq(pdev, 0); ret = platform_get_irq(pdev, 0);
if (ret < 0) { if (ret < 0)
dev_err(dev, "No interrupt specified.\n");
return ret; return ret;
}
tb10x_gpio->gc.to_irq = tb10x_gpio_to_irq; tb10x_gpio->gc.to_irq = tb10x_gpio_to_irq;
tb10x_gpio->irq = ret; tb10x_gpio->irq = ret;
......
...@@ -624,10 +624,8 @@ static int tegra_gpio_probe(struct platform_device *pdev) ...@@ -624,10 +624,8 @@ static int tegra_gpio_probe(struct platform_device *pdev)
for (i = 0; i < tgi->bank_count; i++) { for (i = 0; i < tgi->bank_count; i++) {
ret = platform_get_irq(pdev, i); ret = platform_get_irq(pdev, i);
if (ret < 0) { if (ret < 0)
dev_err(&pdev->dev, "Missing IRQ resource: %d\n", ret);
return ret; return ret;
}
bank = &tgi->bank_info[i]; bank = &tgi->bank_info[i];
bank->bank = i; bank->bank = i;
......
...@@ -53,7 +53,6 @@ struct thunderx_line { ...@@ -53,7 +53,6 @@ struct thunderx_line {
struct thunderx_gpio { struct thunderx_gpio {
struct gpio_chip chip; struct gpio_chip chip;
u8 __iomem *register_base; u8 __iomem *register_base;
struct irq_domain *irqd;
struct msix_entry *msix_entries; /* per line MSI-X */ struct msix_entry *msix_entries; /* per line MSI-X */
struct thunderx_line *line_entries; /* per line irq info */ struct thunderx_line *line_entries; /* per line irq info */
raw_spinlock_t lock; raw_spinlock_t lock;
...@@ -283,54 +282,60 @@ static void thunderx_gpio_set_multiple(struct gpio_chip *chip, ...@@ -283,54 +282,60 @@ static void thunderx_gpio_set_multiple(struct gpio_chip *chip,
} }
} }
static void thunderx_gpio_irq_ack(struct irq_data *data) static void thunderx_gpio_irq_ack(struct irq_data *d)
{ {
struct thunderx_line *txline = irq_data_get_irq_chip_data(data); struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
writeq(GPIO_INTR_INTR, writeq(GPIO_INTR_INTR,
txline->txgpio->register_base + intr_reg(txline->line)); txgpio->register_base + intr_reg(irqd_to_hwirq(d)));
} }
static void thunderx_gpio_irq_mask(struct irq_data *data) static void thunderx_gpio_irq_mask(struct irq_data *d)
{ {
struct thunderx_line *txline = irq_data_get_irq_chip_data(data); struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
writeq(GPIO_INTR_ENA_W1C, writeq(GPIO_INTR_ENA_W1C,
txline->txgpio->register_base + intr_reg(txline->line)); txgpio->register_base + intr_reg(irqd_to_hwirq(d)));
} }
static void thunderx_gpio_irq_mask_ack(struct irq_data *data) static void thunderx_gpio_irq_mask_ack(struct irq_data *d)
{ {
struct thunderx_line *txline = irq_data_get_irq_chip_data(data); struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
writeq(GPIO_INTR_ENA_W1C | GPIO_INTR_INTR, writeq(GPIO_INTR_ENA_W1C | GPIO_INTR_INTR,
txline->txgpio->register_base + intr_reg(txline->line)); txgpio->register_base + intr_reg(irqd_to_hwirq(d)));
} }
static void thunderx_gpio_irq_unmask(struct irq_data *data) static void thunderx_gpio_irq_unmask(struct irq_data *d)
{ {
struct thunderx_line *txline = irq_data_get_irq_chip_data(data); struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
writeq(GPIO_INTR_ENA_W1S, writeq(GPIO_INTR_ENA_W1S,
txline->txgpio->register_base + intr_reg(txline->line)); txgpio->register_base + intr_reg(irqd_to_hwirq(d)));
} }
static int thunderx_gpio_irq_set_type(struct irq_data *data, static int thunderx_gpio_irq_set_type(struct irq_data *d,
unsigned int flow_type) unsigned int flow_type)
{ {
struct thunderx_line *txline = irq_data_get_irq_chip_data(data); struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct thunderx_gpio *txgpio = txline->txgpio; struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
struct thunderx_line *txline =
&txgpio->line_entries[irqd_to_hwirq(d)];
u64 bit_cfg; u64 bit_cfg;
irqd_set_trigger_type(data, flow_type); irqd_set_trigger_type(d, flow_type);
bit_cfg = txline->fil_bits | GPIO_BIT_CFG_INT_EN; bit_cfg = txline->fil_bits | GPIO_BIT_CFG_INT_EN;
if (flow_type & IRQ_TYPE_EDGE_BOTH) { if (flow_type & IRQ_TYPE_EDGE_BOTH) {
irq_set_handler_locked(data, handle_fasteoi_ack_irq); irq_set_handler_locked(d, handle_fasteoi_ack_irq);
bit_cfg |= GPIO_BIT_CFG_INT_TYPE; bit_cfg |= GPIO_BIT_CFG_INT_TYPE;
} else { } else {
irq_set_handler_locked(data, handle_fasteoi_mask_irq); irq_set_handler_locked(d, handle_fasteoi_mask_irq);
} }
raw_spin_lock(&txgpio->lock); raw_spin_lock(&txgpio->lock);
...@@ -359,33 +364,6 @@ static void thunderx_gpio_irq_disable(struct irq_data *data) ...@@ -359,33 +364,6 @@ static void thunderx_gpio_irq_disable(struct irq_data *data)
irq_chip_disable_parent(data); irq_chip_disable_parent(data);
} }
static int thunderx_gpio_irq_request_resources(struct irq_data *data)
{
struct thunderx_line *txline = irq_data_get_irq_chip_data(data);
struct thunderx_gpio *txgpio = txline->txgpio;
int r;
r = gpiochip_lock_as_irq(&txgpio->chip, txline->line);
if (r)
return r;
r = irq_chip_request_resources_parent(data);
if (r)
gpiochip_unlock_as_irq(&txgpio->chip, txline->line);
return r;
}
static void thunderx_gpio_irq_release_resources(struct irq_data *data)
{
struct thunderx_line *txline = irq_data_get_irq_chip_data(data);
struct thunderx_gpio *txgpio = txline->txgpio;
irq_chip_release_resources_parent(data);
gpiochip_unlock_as_irq(&txgpio->chip, txline->line);
}
/* /*
* Interrupts are chained from underlying MSI-X vectors. We have * Interrupts are chained from underlying MSI-X vectors. We have
* these irq_chip functions to be able to handle level triggering * these irq_chip functions to be able to handle level triggering
...@@ -402,48 +380,22 @@ static struct irq_chip thunderx_gpio_irq_chip = { ...@@ -402,48 +380,22 @@ static struct irq_chip thunderx_gpio_irq_chip = {
.irq_unmask = thunderx_gpio_irq_unmask, .irq_unmask = thunderx_gpio_irq_unmask,
.irq_eoi = irq_chip_eoi_parent, .irq_eoi = irq_chip_eoi_parent,
.irq_set_affinity = irq_chip_set_affinity_parent, .irq_set_affinity = irq_chip_set_affinity_parent,
.irq_request_resources = thunderx_gpio_irq_request_resources,
.irq_release_resources = thunderx_gpio_irq_release_resources,
.irq_set_type = thunderx_gpio_irq_set_type, .irq_set_type = thunderx_gpio_irq_set_type,
.flags = IRQCHIP_SET_TYPE_MASKED .flags = IRQCHIP_SET_TYPE_MASKED
}; };
static int thunderx_gpio_irq_translate(struct irq_domain *d, static int thunderx_gpio_child_to_parent_hwirq(struct gpio_chip *gc,
struct irq_fwspec *fwspec, unsigned int child,
irq_hw_number_t *hwirq, unsigned int child_type,
unsigned int *type) unsigned int *parent,
unsigned int *parent_type)
{ {
struct thunderx_gpio *txgpio = d->host_data; struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
if (WARN_ON(fwspec->param_count < 2))
return -EINVAL;
if (fwspec->param[0] >= txgpio->chip.ngpio)
return -EINVAL;
*hwirq = fwspec->param[0];
*type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
return 0;
}
static int thunderx_gpio_irq_alloc(struct irq_domain *d, unsigned int virq,
unsigned int nr_irqs, void *arg)
{
struct thunderx_line *txline = arg;
return irq_domain_set_hwirq_and_chip(d, virq, txline->line,
&thunderx_gpio_irq_chip, txline);
}
static const struct irq_domain_ops thunderx_gpio_irqd_ops = {
.alloc = thunderx_gpio_irq_alloc,
.translate = thunderx_gpio_irq_translate
};
static int thunderx_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
{
struct thunderx_gpio *txgpio = gpiochip_get_data(chip);
return irq_find_mapping(txgpio->irqd, offset); *parent = txgpio->base_msi + (2 * child);
*parent_type = IRQ_TYPE_LEVEL_HIGH;
return 0;
} }
static int thunderx_gpio_probe(struct pci_dev *pdev, static int thunderx_gpio_probe(struct pci_dev *pdev,
...@@ -453,6 +405,7 @@ static int thunderx_gpio_probe(struct pci_dev *pdev, ...@@ -453,6 +405,7 @@ static int thunderx_gpio_probe(struct pci_dev *pdev,
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct thunderx_gpio *txgpio; struct thunderx_gpio *txgpio;
struct gpio_chip *chip; struct gpio_chip *chip;
struct gpio_irq_chip *girq;
int ngpio, i; int ngpio, i;
int err = 0; int err = 0;
...@@ -539,27 +492,6 @@ static int thunderx_gpio_probe(struct pci_dev *pdev, ...@@ -539,27 +492,6 @@ static int thunderx_gpio_probe(struct pci_dev *pdev,
if (err < 0) if (err < 0)
goto out; goto out;
/*
* Push GPIO specific irqdomain on hierarchy created as a side
* effect of the pci_enable_msix()
*/
txgpio->irqd = irq_domain_create_hierarchy(irq_get_irq_data(txgpio->msix_entries[0].vector)->domain,
0, 0, of_node_to_fwnode(dev->of_node),
&thunderx_gpio_irqd_ops, txgpio);
if (!txgpio->irqd) {
err = -ENOMEM;
goto out;
}
/* Push on irq_data and the domain for each line. */
for (i = 0; i < ngpio; i++) {
err = irq_domain_push_irq(txgpio->irqd,
txgpio->msix_entries[i].vector,
&txgpio->line_entries[i]);
if (err < 0)
dev_err(dev, "irq_domain_push_irq: %d\n", err);
}
chip->label = KBUILD_MODNAME; chip->label = KBUILD_MODNAME;
chip->parent = dev; chip->parent = dev;
chip->owner = THIS_MODULE; chip->owner = THIS_MODULE;
...@@ -574,11 +506,28 @@ static int thunderx_gpio_probe(struct pci_dev *pdev, ...@@ -574,11 +506,28 @@ static int thunderx_gpio_probe(struct pci_dev *pdev,
chip->set = thunderx_gpio_set; chip->set = thunderx_gpio_set;
chip->set_multiple = thunderx_gpio_set_multiple; chip->set_multiple = thunderx_gpio_set_multiple;
chip->set_config = thunderx_gpio_set_config; chip->set_config = thunderx_gpio_set_config;
chip->to_irq = thunderx_gpio_to_irq; girq = &chip->irq;
girq->chip = &thunderx_gpio_irq_chip;
girq->fwnode = of_node_to_fwnode(dev->of_node);
girq->parent_domain =
irq_get_irq_data(txgpio->msix_entries[0].vector)->domain;
girq->child_to_parent_hwirq = thunderx_gpio_child_to_parent_hwirq;
girq->handler = handle_bad_irq;
girq->default_type = IRQ_TYPE_NONE;
err = devm_gpiochip_add_data(dev, chip, txgpio); err = devm_gpiochip_add_data(dev, chip, txgpio);
if (err) if (err)
goto out; goto out;
/* Push on irq_data and the domain for each line. */
for (i = 0; i < ngpio; i++) {
err = irq_domain_push_irq(chip->irq.domain,
txgpio->msix_entries[i].vector,
chip);
if (err < 0)
dev_err(dev, "irq_domain_push_irq: %d\n", err);
}
dev_info(dev, "ThunderX GPIO: %d lines with base %d.\n", dev_info(dev, "ThunderX GPIO: %d lines with base %d.\n",
ngpio, chip->base); ngpio, chip->base);
return 0; return 0;
...@@ -593,10 +542,10 @@ static void thunderx_gpio_remove(struct pci_dev *pdev) ...@@ -593,10 +542,10 @@ static void thunderx_gpio_remove(struct pci_dev *pdev)
struct thunderx_gpio *txgpio = pci_get_drvdata(pdev); struct thunderx_gpio *txgpio = pci_get_drvdata(pdev);
for (i = 0; i < txgpio->chip.ngpio; i++) for (i = 0; i < txgpio->chip.ngpio; i++)
irq_domain_pop_irq(txgpio->irqd, irq_domain_pop_irq(txgpio->chip.irq.domain,
txgpio->msix_entries[i].vector); txgpio->msix_entries[i].vector);
irq_domain_remove(txgpio->irqd); irq_domain_remove(txgpio->chip.irq.domain);
pci_set_drvdata(pdev, NULL); pci_set_drvdata(pdev, NULL);
} }
......
...@@ -214,11 +214,23 @@ static const struct dev_pm_ops tqmx86_gpio_dev_pm_ops = { ...@@ -214,11 +214,23 @@ static const struct dev_pm_ops tqmx86_gpio_dev_pm_ops = {
tqmx86_gpio_runtime_resume, NULL) tqmx86_gpio_runtime_resume, NULL)
}; };
static void tqmx86_init_irq_valid_mask(struct gpio_chip *chip,
unsigned long *valid_mask,
unsigned int ngpios)
{
/* Only GPIOs 4-7 are valid for interrupts. Clear the others */
clear_bit(0, valid_mask);
clear_bit(1, valid_mask);
clear_bit(2, valid_mask);
clear_bit(3, valid_mask);
}
static int tqmx86_gpio_probe(struct platform_device *pdev) static int tqmx86_gpio_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct tqmx86_gpio_data *gpio; struct tqmx86_gpio_data *gpio;
struct gpio_chip *chip; struct gpio_chip *chip;
struct gpio_irq_chip *girq;
void __iomem *io_base; void __iomem *io_base;
struct resource *res; struct resource *res;
int ret, irq; int ret, irq;
...@@ -259,17 +271,10 @@ static int tqmx86_gpio_probe(struct platform_device *pdev) ...@@ -259,17 +271,10 @@ static int tqmx86_gpio_probe(struct platform_device *pdev)
chip->get = tqmx86_gpio_get; chip->get = tqmx86_gpio_get;
chip->set = tqmx86_gpio_set; chip->set = tqmx86_gpio_set;
chip->ngpio = TQMX86_NGPIO; chip->ngpio = TQMX86_NGPIO;
chip->irq.need_valid_mask = true;
chip->parent = pdev->dev.parent; chip->parent = pdev->dev.parent;
pm_runtime_enable(&pdev->dev); pm_runtime_enable(&pdev->dev);
ret = devm_gpiochip_add_data(dev, chip, gpio);
if (ret) {
dev_err(dev, "Could not register GPIO chip\n");
goto out_pm_dis;
}
if (irq) { if (irq) {
struct irq_chip *irq_chip = &gpio->irq_chip; struct irq_chip *irq_chip = &gpio->irq_chip;
u8 irq_status; u8 irq_status;
...@@ -287,23 +292,28 @@ static int tqmx86_gpio_probe(struct platform_device *pdev) ...@@ -287,23 +292,28 @@ static int tqmx86_gpio_probe(struct platform_device *pdev)
irq_status = tqmx86_gpio_read(gpio, TQMX86_GPIIS); irq_status = tqmx86_gpio_read(gpio, TQMX86_GPIIS);
tqmx86_gpio_write(gpio, irq_status, TQMX86_GPIIS); tqmx86_gpio_write(gpio, irq_status, TQMX86_GPIIS);
ret = gpiochip_irqchip_add(chip, irq_chip, girq = &chip->irq;
0, handle_simple_irq, girq->chip = irq_chip;
IRQ_TYPE_EDGE_BOTH); girq->parent_handler = tqmx86_gpio_irq_handler;
if (ret) { girq->num_parents = 1;
dev_err(dev, "Could not add irq chip\n"); girq->parents = devm_kcalloc(&pdev->dev, 1,
sizeof(*girq->parents),
GFP_KERNEL);
if (!girq->parents) {
ret = -ENOMEM;
goto out_pm_dis; goto out_pm_dis;
} }
girq->parents[0] = irq;
gpiochip_set_chained_irqchip(chip, irq_chip, girq->default_type = IRQ_TYPE_NONE;
irq, tqmx86_gpio_irq_handler); girq->handler = handle_simple_irq;
girq->init_valid_mask = tqmx86_init_irq_valid_mask;
} }
/* Only GPIOs 4-7 are valid for interrupts. Clear the others */ ret = devm_gpiochip_add_data(dev, chip, gpio);
clear_bit(0, chip->irq.valid_mask); if (ret) {
clear_bit(1, chip->irq.valid_mask); dev_err(dev, "Could not register GPIO chip\n");
clear_bit(2, chip->irq.valid_mask); goto out_pm_dis;
clear_bit(3, chip->irq.valid_mask); }
dev_info(dev, "GPIO functionality initialized with %d pins\n", dev_info(dev, "GPIO functionality initialized with %d pins\n",
chip->ngpio); chip->ngpio);
......
...@@ -243,6 +243,7 @@ static int vf610_gpio_probe(struct platform_device *pdev) ...@@ -243,6 +243,7 @@ static int vf610_gpio_probe(struct platform_device *pdev)
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
struct vf610_gpio_port *port; struct vf610_gpio_port *port;
struct gpio_chip *gc; struct gpio_chip *gc;
struct gpio_irq_chip *girq;
struct irq_chip *ic; struct irq_chip *ic;
int i; int i;
int ret; int ret;
...@@ -318,10 +319,6 @@ static int vf610_gpio_probe(struct platform_device *pdev) ...@@ -318,10 +319,6 @@ static int vf610_gpio_probe(struct platform_device *pdev)
ic->irq_set_type = vf610_gpio_irq_set_type; ic->irq_set_type = vf610_gpio_irq_set_type;
ic->irq_set_wake = vf610_gpio_irq_set_wake; ic->irq_set_wake = vf610_gpio_irq_set_wake;
ret = devm_gpiochip_add_data(dev, gc, port);
if (ret < 0)
return ret;
/* Mask all GPIO interrupts */ /* Mask all GPIO interrupts */
for (i = 0; i < gc->ngpio; i++) for (i = 0; i < gc->ngpio; i++)
vf610_gpio_writel(0, port->base + PORT_PCR(i)); vf610_gpio_writel(0, port->base + PORT_PCR(i));
...@@ -329,15 +326,20 @@ static int vf610_gpio_probe(struct platform_device *pdev) ...@@ -329,15 +326,20 @@ static int vf610_gpio_probe(struct platform_device *pdev)
/* Clear the interrupt status register for all GPIO's */ /* Clear the interrupt status register for all GPIO's */
vf610_gpio_writel(~0, port->base + PORT_ISFR); vf610_gpio_writel(~0, port->base + PORT_ISFR);
ret = gpiochip_irqchip_add(gc, ic, 0, handle_edge_irq, IRQ_TYPE_NONE); girq = &gc->irq;
if (ret) { girq->chip = ic;
dev_err(dev, "failed to add irqchip\n"); girq->parent_handler = vf610_gpio_irq_handler;
return ret; girq->num_parents = 1;
} girq->parents = devm_kcalloc(&pdev->dev, 1,
gpiochip_set_chained_irqchip(gc, ic, port->irq, sizeof(*girq->parents),
vf610_gpio_irq_handler); GFP_KERNEL);
if (!girq->parents)
return -ENOMEM;
girq->parents[0] = port->irq;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_edge_irq;
return 0; return devm_gpiochip_add_data(dev, gc, port);
} }
static struct platform_driver vf610_gpio_driver = { static struct platform_driver vf610_gpio_driver = {
......
...@@ -79,7 +79,7 @@ MODULE_PARM_DESC(gpioa_freq, ...@@ -79,7 +79,7 @@ MODULE_PARM_DESC(gpioa_freq,
/* ----- begin of gipo a chip -------------------------------------------- */ /* ----- begin of gipo a chip -------------------------------------------- */
static int vprbrd_gpioa_get(struct gpio_chip *chip, static int vprbrd_gpioa_get(struct gpio_chip *chip,
unsigned offset) unsigned int offset)
{ {
int ret, answer, error = 0; int ret, answer, error = 0;
struct vprbrd_gpio *gpio = gpiochip_get_data(chip); struct vprbrd_gpio *gpio = gpiochip_get_data(chip);
...@@ -129,7 +129,7 @@ static int vprbrd_gpioa_get(struct gpio_chip *chip, ...@@ -129,7 +129,7 @@ static int vprbrd_gpioa_get(struct gpio_chip *chip,
} }
static void vprbrd_gpioa_set(struct gpio_chip *chip, static void vprbrd_gpioa_set(struct gpio_chip *chip,
unsigned offset, int value) unsigned int offset, int value)
{ {
int ret; int ret;
struct vprbrd_gpio *gpio = gpiochip_get_data(chip); struct vprbrd_gpio *gpio = gpiochip_get_data(chip);
...@@ -170,7 +170,7 @@ static void vprbrd_gpioa_set(struct gpio_chip *chip, ...@@ -170,7 +170,7 @@ static void vprbrd_gpioa_set(struct gpio_chip *chip,
} }
static int vprbrd_gpioa_direction_input(struct gpio_chip *chip, static int vprbrd_gpioa_direction_input(struct gpio_chip *chip,
unsigned offset) unsigned int offset)
{ {
int ret; int ret;
struct vprbrd_gpio *gpio = gpiochip_get_data(chip); struct vprbrd_gpio *gpio = gpiochip_get_data(chip);
...@@ -207,7 +207,7 @@ static int vprbrd_gpioa_direction_input(struct gpio_chip *chip, ...@@ -207,7 +207,7 @@ static int vprbrd_gpioa_direction_input(struct gpio_chip *chip,
} }
static int vprbrd_gpioa_direction_output(struct gpio_chip *chip, static int vprbrd_gpioa_direction_output(struct gpio_chip *chip,
unsigned offset, int value) unsigned int offset, int value)
{ {
int ret; int ret;
struct vprbrd_gpio *gpio = gpiochip_get_data(chip); struct vprbrd_gpio *gpio = gpiochip_get_data(chip);
...@@ -251,8 +251,8 @@ static int vprbrd_gpioa_direction_output(struct gpio_chip *chip, ...@@ -251,8 +251,8 @@ static int vprbrd_gpioa_direction_output(struct gpio_chip *chip,
/* ----- begin of gipo b chip -------------------------------------------- */ /* ----- begin of gipo b chip -------------------------------------------- */
static int vprbrd_gpiob_setdir(struct vprbrd *vb, unsigned offset, static int vprbrd_gpiob_setdir(struct vprbrd *vb, unsigned int offset,
unsigned dir) unsigned int dir)
{ {
struct vprbrd_gpiob_msg *gbmsg = (struct vprbrd_gpiob_msg *)vb->buf; struct vprbrd_gpiob_msg *gbmsg = (struct vprbrd_gpiob_msg *)vb->buf;
int ret; int ret;
...@@ -273,7 +273,7 @@ static int vprbrd_gpiob_setdir(struct vprbrd *vb, unsigned offset, ...@@ -273,7 +273,7 @@ static int vprbrd_gpiob_setdir(struct vprbrd *vb, unsigned offset,
} }
static int vprbrd_gpiob_get(struct gpio_chip *chip, static int vprbrd_gpiob_get(struct gpio_chip *chip,
unsigned offset) unsigned int offset)
{ {
int ret; int ret;
u16 val; u16 val;
...@@ -305,7 +305,7 @@ static int vprbrd_gpiob_get(struct gpio_chip *chip, ...@@ -305,7 +305,7 @@ static int vprbrd_gpiob_get(struct gpio_chip *chip,
} }
static void vprbrd_gpiob_set(struct gpio_chip *chip, static void vprbrd_gpiob_set(struct gpio_chip *chip,
unsigned offset, int value) unsigned int offset, int value)
{ {
int ret; int ret;
struct vprbrd_gpio *gpio = gpiochip_get_data(chip); struct vprbrd_gpio *gpio = gpiochip_get_data(chip);
...@@ -338,7 +338,7 @@ static void vprbrd_gpiob_set(struct gpio_chip *chip, ...@@ -338,7 +338,7 @@ static void vprbrd_gpiob_set(struct gpio_chip *chip,
} }
static int vprbrd_gpiob_direction_input(struct gpio_chip *chip, static int vprbrd_gpiob_direction_input(struct gpio_chip *chip,
unsigned offset) unsigned int offset)
{ {
int ret; int ret;
struct vprbrd_gpio *gpio = gpiochip_get_data(chip); struct vprbrd_gpio *gpio = gpiochip_get_data(chip);
...@@ -359,7 +359,7 @@ static int vprbrd_gpiob_direction_input(struct gpio_chip *chip, ...@@ -359,7 +359,7 @@ static int vprbrd_gpiob_direction_input(struct gpio_chip *chip,
} }
static int vprbrd_gpiob_direction_output(struct gpio_chip *chip, static int vprbrd_gpiob_direction_output(struct gpio_chip *chip,
unsigned offset, int value) unsigned int offset, int value)
{ {
int ret; int ret;
struct vprbrd_gpio *gpio = gpiochip_get_data(chip); struct vprbrd_gpio *gpio = gpiochip_get_data(chip);
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/acpi.h> #include <linux/acpi.h>
#include "gpiolib.h" #include "gpiolib.h"
#include "gpiolib-acpi.h"
/* Common property names */ /* Common property names */
#define XGENE_NIRQ_PROPERTY "apm,nr-irqs" #define XGENE_NIRQ_PROPERTY "apm,nr-irqs"
......
...@@ -290,6 +290,7 @@ MODULE_DEVICE_TABLE(of, xlp_gpio_of_ids); ...@@ -290,6 +290,7 @@ MODULE_DEVICE_TABLE(of, xlp_gpio_of_ids);
static int xlp_gpio_probe(struct platform_device *pdev) static int xlp_gpio_probe(struct platform_device *pdev)
{ {
struct gpio_chip *gc; struct gpio_chip *gc;
struct gpio_irq_chip *girq;
struct xlp_gpio_priv *priv; struct xlp_gpio_priv *priv;
void __iomem *gpio_base; void __iomem *gpio_base;
int irq_base, irq, err; int irq_base, irq, err;
...@@ -395,27 +396,27 @@ static int xlp_gpio_probe(struct platform_device *pdev) ...@@ -395,27 +396,27 @@ static int xlp_gpio_probe(struct platform_device *pdev)
irq_base = 0; irq_base = 0;
} }
girq = &gc->irq;
girq->chip = &xlp_gpio_irq_chip;
girq->parent_handler = xlp_gpio_generic_handler;
girq->num_parents = 1;
girq->parents = devm_kcalloc(&pdev->dev, 1,
sizeof(*girq->parents),
GFP_KERNEL);
if (!girq->parents)
return -ENOMEM;
girq->parents[0] = irq;
girq->first = irq_base;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_level_irq;
err = gpiochip_add_data(gc, priv); err = gpiochip_add_data(gc, priv);
if (err < 0) if (err < 0)
return err; return err;
err = gpiochip_irqchip_add(gc, &xlp_gpio_irq_chip, irq_base,
handle_level_irq, IRQ_TYPE_NONE);
if (err) {
dev_err(&pdev->dev, "Could not connect irqchip to gpiochip!\n");
goto out_gpio_remove;
}
gpiochip_set_chained_irqchip(gc, &xlp_gpio_irq_chip, irq,
xlp_gpio_generic_handler);
dev_info(&pdev->dev, "registered %d GPIOs\n", gc->ngpio); dev_info(&pdev->dev, "registered %d GPIOs\n", gc->ngpio);
return 0; return 0;
out_gpio_remove:
gpiochip_remove(gc);
return err;
} }
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
......
...@@ -215,6 +215,7 @@ static int zx_gpio_probe(struct platform_device *pdev) ...@@ -215,6 +215,7 @@ static int zx_gpio_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct zx_gpio *chip; struct zx_gpio *chip;
struct gpio_irq_chip *girq;
int irq, id, ret; int irq, id, ret;
chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
...@@ -242,32 +243,30 @@ static int zx_gpio_probe(struct platform_device *pdev) ...@@ -242,32 +243,30 @@ static int zx_gpio_probe(struct platform_device *pdev)
chip->gc.parent = dev; chip->gc.parent = dev;
chip->gc.owner = THIS_MODULE; chip->gc.owner = THIS_MODULE;
ret = gpiochip_add_data(&chip->gc, chip);
if (ret)
return ret;
/* /*
* irq_chip support * irq_chip support
*/ */
writew_relaxed(0xffff, chip->base + ZX_GPIO_IM); writew_relaxed(0xffff, chip->base + ZX_GPIO_IM);
writew_relaxed(0, chip->base + ZX_GPIO_IE); writew_relaxed(0, chip->base + ZX_GPIO_IE);
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq < 0) { if (irq < 0)
dev_err(dev, "invalid IRQ\n"); return irq;
gpiochip_remove(&chip->gc); girq = &chip->gc.irq;
return -ENODEV; girq->chip = &zx_irqchip;
} girq->parent_handler = zx_irq_handler;
girq->num_parents = 1;
girq->parents = devm_kcalloc(&pdev->dev, 1,
sizeof(*girq->parents),
GFP_KERNEL);
if (!girq->parents)
return -ENOMEM;
girq->parents[0] = irq;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_simple_irq;
ret = gpiochip_irqchip_add(&chip->gc, &zx_irqchip, ret = gpiochip_add_data(&chip->gc, chip);
0, handle_simple_irq, if (ret)
IRQ_TYPE_NONE);
if (ret) {
dev_err(dev, "could not add irqchip\n");
gpiochip_remove(&chip->gc);
return ret; return ret;
}
gpiochip_set_chained_irqchip(&chip->gc, &zx_irqchip,
irq, zx_irq_handler);
platform_set_drvdata(pdev, chip); platform_set_drvdata(pdev, chip);
dev_info(dev, "ZX GPIO chip registered\n"); dev_info(dev, "ZX GPIO chip registered\n");
......
...@@ -830,6 +830,7 @@ static int zynq_gpio_probe(struct platform_device *pdev) ...@@ -830,6 +830,7 @@ static int zynq_gpio_probe(struct platform_device *pdev)
int ret, bank_num; int ret, bank_num;
struct zynq_gpio *gpio; struct zynq_gpio *gpio;
struct gpio_chip *chip; struct gpio_chip *chip;
struct gpio_irq_chip *girq;
const struct of_device_id *match; const struct of_device_id *match;
gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
...@@ -849,10 +850,8 @@ static int zynq_gpio_probe(struct platform_device *pdev) ...@@ -849,10 +850,8 @@ static int zynq_gpio_probe(struct platform_device *pdev)
return PTR_ERR(gpio->base_addr); return PTR_ERR(gpio->base_addr);
gpio->irq = platform_get_irq(pdev, 0); gpio->irq = platform_get_irq(pdev, 0);
if (gpio->irq < 0) { if (gpio->irq < 0)
dev_err(&pdev->dev, "invalid IRQ\n");
return gpio->irq; return gpio->irq;
}
/* configure the gpio chip */ /* configure the gpio chip */
chip = &gpio->chip; chip = &gpio->chip;
...@@ -887,34 +886,38 @@ static int zynq_gpio_probe(struct platform_device *pdev) ...@@ -887,34 +886,38 @@ static int zynq_gpio_probe(struct platform_device *pdev)
if (ret < 0) if (ret < 0)
goto err_pm_dis; goto err_pm_dis;
/* report a bug if gpio chip registration fails */
ret = gpiochip_add_data(chip, gpio);
if (ret) {
dev_err(&pdev->dev, "Failed to add gpio chip\n");
goto err_pm_put;
}
/* disable interrupts for all banks */ /* disable interrupts for all banks */
for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++) for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++)
writel_relaxed(ZYNQ_GPIO_IXR_DISABLE_ALL, gpio->base_addr + writel_relaxed(ZYNQ_GPIO_IXR_DISABLE_ALL, gpio->base_addr +
ZYNQ_GPIO_INTDIS_OFFSET(bank_num)); ZYNQ_GPIO_INTDIS_OFFSET(bank_num));
ret = gpiochip_irqchip_add(chip, &zynq_gpio_edge_irqchip, 0, /* Set up the GPIO irqchip */
handle_level_irq, IRQ_TYPE_NONE); girq = &chip->irq;
if (ret) { girq->chip = &zynq_gpio_edge_irqchip;
dev_err(&pdev->dev, "Failed to add irq chip\n"); girq->parent_handler = zynq_gpio_irqhandler;
goto err_rm_gpiochip; girq->num_parents = 1;
girq->parents = devm_kcalloc(&pdev->dev, 1,
sizeof(*girq->parents),
GFP_KERNEL);
if (!girq->parents) {
ret = -ENOMEM;
goto err_pm_put;
} }
girq->parents[0] = gpio->irq;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_level_irq;
gpiochip_set_chained_irqchip(chip, &zynq_gpio_edge_irqchip, gpio->irq, /* report a bug if gpio chip registration fails */
zynq_gpio_irqhandler); ret = gpiochip_add_data(chip, gpio);
if (ret) {
dev_err(&pdev->dev, "Failed to add gpio chip\n");
goto err_pm_put;
}
pm_runtime_put(&pdev->dev); pm_runtime_put(&pdev->dev);
return 0; return 0;
err_rm_gpiochip:
gpiochip_remove(chip);
err_pm_put: err_pm_put:
pm_runtime_put(&pdev->dev); pm_runtime_put(&pdev->dev);
err_pm_dis: err_pm_dis:
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinctrl.h>
#include "gpiolib.h" #include "gpiolib.h"
#include "gpiolib-acpi.h"
static int run_edge_events_on_boot = -1; static int run_edge_events_on_boot = -1;
module_param(run_edge_events_on_boot, int, 0444); module_param(run_edge_events_on_boot, int, 0444);
...@@ -391,6 +392,13 @@ int acpi_dev_add_driver_gpios(struct acpi_device *adev, ...@@ -391,6 +392,13 @@ int acpi_dev_add_driver_gpios(struct acpi_device *adev,
} }
EXPORT_SYMBOL_GPL(acpi_dev_add_driver_gpios); EXPORT_SYMBOL_GPL(acpi_dev_add_driver_gpios);
void acpi_dev_remove_driver_gpios(struct acpi_device *adev)
{
if (adev)
adev->driver_gpios = NULL;
}
EXPORT_SYMBOL_GPL(acpi_dev_remove_driver_gpios);
static void devm_acpi_dev_release_driver_gpios(struct device *dev, void *res) static void devm_acpi_dev_release_driver_gpios(struct device *dev, void *res)
{ {
acpi_dev_remove_driver_gpios(ACPI_COMPANION(dev)); acpi_dev_remove_driver_gpios(ACPI_COMPANION(dev));
...@@ -729,6 +737,16 @@ static struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev, ...@@ -729,6 +737,16 @@ static struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
return ret ? ERR_PTR(ret) : lookup.desc; return ret ? ERR_PTR(ret) : lookup.desc;
} }
static bool acpi_can_fallback_to_crs(struct acpi_device *adev,
const char *con_id)
{
/* Never allow fallback if the device has properties */
if (acpi_dev_has_props(adev) || adev->driver_gpios)
return false;
return con_id == NULL;
}
struct gpio_desc *acpi_find_gpio(struct device *dev, struct gpio_desc *acpi_find_gpio(struct device *dev,
const char *con_id, const char *con_id,
unsigned int idx, unsigned int idx,
...@@ -1265,15 +1283,6 @@ int acpi_gpio_count(struct device *dev, const char *con_id) ...@@ -1265,15 +1283,6 @@ int acpi_gpio_count(struct device *dev, const char *con_id)
return count ? count : -ENOENT; return count ? count : -ENOENT;
} }
bool acpi_can_fallback_to_crs(struct acpi_device *adev, const char *con_id)
{
/* Never allow fallback if the device has properties */
if (acpi_dev_has_props(adev) || adev->driver_gpios)
return false;
return con_id == NULL;
}
/* Run deferred acpi_gpiochip_request_irqs() */ /* Run deferred acpi_gpiochip_request_irqs() */
static int acpi_gpio_handle_deferred_request_irqs(void) static int acpi_gpio_handle_deferred_request_irqs(void)
{ {
......
/* SPDX-License-Identifier: GPL-2.0 */
/*
* ACPI helpers for GPIO API
*
* Copyright (C) 2012,2019 Intel Corporation
*/
#ifndef GPIOLIB_ACPI_H
#define GPIOLIB_ACPI_H
struct acpi_device;
/**
* struct acpi_gpio_info - ACPI GPIO specific information
* @adev: reference to ACPI device which consumes GPIO resource
* @flags: GPIO initialization flags
* @gpioint: if %true this GPIO is of type GpioInt otherwise type is GpioIo
* @pin_config: pin bias as provided by ACPI
* @polarity: interrupt polarity as provided by ACPI
* @triggering: triggering type as provided by ACPI
* @quirks: Linux specific quirks as provided by struct acpi_gpio_mapping
*/
struct acpi_gpio_info {
struct acpi_device *adev;
enum gpiod_flags flags;
bool gpioint;
int pin_config;
int polarity;
int triggering;
unsigned int quirks;
};
#ifdef CONFIG_ACPI
void acpi_gpiochip_add(struct gpio_chip *chip);
void acpi_gpiochip_remove(struct gpio_chip *chip);
void acpi_gpiochip_request_interrupts(struct gpio_chip *chip);
void acpi_gpiochip_free_interrupts(struct gpio_chip *chip);
int acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags,
struct acpi_gpio_info *info);
int acpi_gpio_update_gpiod_lookup_flags(unsigned long *lookupflags,
struct acpi_gpio_info *info);
struct gpio_desc *acpi_find_gpio(struct device *dev,
const char *con_id,
unsigned int idx,
enum gpiod_flags *dflags,
unsigned long *lookupflags);
struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode,
const char *propname, int index,
struct acpi_gpio_info *info);
int acpi_gpio_count(struct device *dev, const char *con_id);
#else
static inline void acpi_gpiochip_add(struct gpio_chip *chip) { }
static inline void acpi_gpiochip_remove(struct gpio_chip *chip) { }
static inline void
acpi_gpiochip_request_interrupts(struct gpio_chip *chip) { }
static inline void
acpi_gpiochip_free_interrupts(struct gpio_chip *chip) { }
static inline int
acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, struct acpi_gpio_info *info)
{
return 0;
}
static inline int
acpi_gpio_update_gpiod_lookup_flags(unsigned long *lookupflags,
struct acpi_gpio_info *info)
{
return 0;
}
static inline struct gpio_desc *
acpi_find_gpio(struct device *dev, const char *con_id,
unsigned int idx, enum gpiod_flags *dflags,
unsigned long *lookupflags)
{
return ERR_PTR(-ENOENT);
}
static inline struct gpio_desc *
acpi_node_get_gpiod(struct fwnode_handle *fwnode, const char *propname,
int index, struct acpi_gpio_info *info)
{
return ERR_PTR(-ENXIO);
}
static inline int acpi_gpio_count(struct device *dev, const char *con_id)
{
return -ENODEV;
}
#endif
#endif /* GPIOLIB_ACPI_H */
...@@ -59,7 +59,7 @@ struct gpio_desc *__must_check devm_gpiod_get(struct device *dev, ...@@ -59,7 +59,7 @@ struct gpio_desc *__must_check devm_gpiod_get(struct device *dev,
{ {
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_GPL(devm_gpiod_get);
/** /**
* devm_gpiod_get_optional - Resource-managed gpiod_get_optional() * devm_gpiod_get_optional - Resource-managed gpiod_get_optional()
...@@ -77,7 +77,7 @@ struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev, ...@@ -77,7 +77,7 @@ struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev,
{ {
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_GPL(devm_gpiod_get_optional);
/** /**
* devm_gpiod_get_index - Resource-managed gpiod_get_index() * devm_gpiod_get_index - Resource-managed gpiod_get_index()
...@@ -127,7 +127,7 @@ struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev, ...@@ -127,7 +127,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_GPL(devm_gpiod_get_index);
/** /**
* devm_gpiod_get_from_of_node() - obtain a GPIO from an OF node * devm_gpiod_get_from_of_node() - obtain a GPIO from an OF node
...@@ -182,7 +182,7 @@ struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev, ...@@ -182,7 +182,7 @@ struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev,
return desc; return desc;
} }
EXPORT_SYMBOL(devm_gpiod_get_from_of_node); EXPORT_SYMBOL_GPL(devm_gpiod_get_from_of_node);
/** /**
* devm_fwnode_get_index_gpiod_from_child - get a GPIO descriptor from a * devm_fwnode_get_index_gpiod_from_child - get a GPIO descriptor from a
...@@ -239,7 +239,7 @@ struct gpio_desc *devm_fwnode_get_index_gpiod_from_child(struct device *dev, ...@@ -239,7 +239,7 @@ struct gpio_desc *devm_fwnode_get_index_gpiod_from_child(struct device *dev,
return desc; return desc;
} }
EXPORT_SYMBOL(devm_fwnode_get_index_gpiod_from_child); EXPORT_SYMBOL_GPL(devm_fwnode_get_index_gpiod_from_child);
/** /**
* devm_gpiod_get_index_optional - Resource-managed gpiod_get_index_optional() * devm_gpiod_get_index_optional - Resource-managed gpiod_get_index_optional()
...@@ -268,7 +268,7 @@ struct gpio_desc *__must_check devm_gpiod_get_index_optional(struct device *dev, ...@@ -268,7 +268,7 @@ struct gpio_desc *__must_check devm_gpiod_get_index_optional(struct device *dev,
return desc; return desc;
} }
EXPORT_SYMBOL(devm_gpiod_get_index_optional); EXPORT_SYMBOL_GPL(devm_gpiod_get_index_optional);
/** /**
* devm_gpiod_get_array - Resource-managed gpiod_get_array() * devm_gpiod_get_array - Resource-managed gpiod_get_array()
...@@ -303,7 +303,7 @@ struct gpio_descs *__must_check devm_gpiod_get_array(struct device *dev, ...@@ -303,7 +303,7 @@ struct gpio_descs *__must_check devm_gpiod_get_array(struct device *dev,
return descs; return descs;
} }
EXPORT_SYMBOL(devm_gpiod_get_array); EXPORT_SYMBOL_GPL(devm_gpiod_get_array);
/** /**
* devm_gpiod_get_array_optional - Resource-managed gpiod_get_array_optional() * devm_gpiod_get_array_optional - Resource-managed gpiod_get_array_optional()
...@@ -328,7 +328,7 @@ devm_gpiod_get_array_optional(struct device *dev, const char *con_id, ...@@ -328,7 +328,7 @@ devm_gpiod_get_array_optional(struct device *dev, const char *con_id,
return descs; return descs;
} }
EXPORT_SYMBOL(devm_gpiod_get_array_optional); EXPORT_SYMBOL_GPL(devm_gpiod_get_array_optional);
/** /**
* devm_gpiod_put - Resource-managed gpiod_put() * devm_gpiod_put - Resource-managed gpiod_put()
...@@ -344,7 +344,7 @@ void devm_gpiod_put(struct device *dev, struct gpio_desc *desc) ...@@ -344,7 +344,7 @@ void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
WARN_ON(devres_release(dev, devm_gpiod_release, devm_gpiod_match, WARN_ON(devres_release(dev, devm_gpiod_release, devm_gpiod_match,
&desc)); &desc));
} }
EXPORT_SYMBOL(devm_gpiod_put); EXPORT_SYMBOL_GPL(devm_gpiod_put);
/** /**
* devm_gpiod_unhinge - Remove resource management from a gpio descriptor * devm_gpiod_unhinge - Remove resource management from a gpio descriptor
...@@ -374,7 +374,7 @@ void devm_gpiod_unhinge(struct device *dev, struct gpio_desc *desc) ...@@ -374,7 +374,7 @@ void devm_gpiod_unhinge(struct device *dev, struct gpio_desc *desc)
/* Anything else we should warn about */ /* Anything else we should warn about */
WARN_ON(ret); WARN_ON(ret);
} }
EXPORT_SYMBOL(devm_gpiod_unhinge); EXPORT_SYMBOL_GPL(devm_gpiod_unhinge);
/** /**
* devm_gpiod_put_array - Resource-managed gpiod_put_array() * devm_gpiod_put_array - Resource-managed gpiod_put_array()
...@@ -390,7 +390,7 @@ void devm_gpiod_put_array(struct device *dev, struct gpio_descs *descs) ...@@ -390,7 +390,7 @@ void devm_gpiod_put_array(struct device *dev, struct gpio_descs *descs)
WARN_ON(devres_release(dev, devm_gpiod_release_array, WARN_ON(devres_release(dev, devm_gpiod_release_array,
devm_gpiod_match_array, &descs)); devm_gpiod_match_array, &descs));
} }
EXPORT_SYMBOL(devm_gpiod_put_array); EXPORT_SYMBOL_GPL(devm_gpiod_put_array);
...@@ -444,7 +444,7 @@ int devm_gpio_request(struct device *dev, unsigned gpio, const char *label) ...@@ -444,7 +444,7 @@ int devm_gpio_request(struct device *dev, unsigned gpio, const char *label)
return 0; return 0;
} }
EXPORT_SYMBOL(devm_gpio_request); EXPORT_SYMBOL_GPL(devm_gpio_request);
/** /**
* devm_gpio_request_one - request a single GPIO with initial setup * devm_gpio_request_one - request a single GPIO with initial setup
...@@ -474,7 +474,7 @@ int devm_gpio_request_one(struct device *dev, unsigned gpio, ...@@ -474,7 +474,7 @@ int devm_gpio_request_one(struct device *dev, unsigned gpio,
return 0; return 0;
} }
EXPORT_SYMBOL(devm_gpio_request_one); EXPORT_SYMBOL_GPL(devm_gpio_request_one);
/** /**
* devm_gpio_free - free a GPIO * devm_gpio_free - free a GPIO
...@@ -492,4 +492,4 @@ void devm_gpio_free(struct device *dev, unsigned int gpio) ...@@ -492,4 +492,4 @@ void devm_gpio_free(struct device *dev, unsigned int gpio)
WARN_ON(devres_release(dev, devm_gpio_release, devm_gpio_match, WARN_ON(devres_release(dev, devm_gpio_release, devm_gpio_match,
&gpio)); &gpio));
} }
EXPORT_SYMBOL(devm_gpio_free); EXPORT_SYMBOL_GPL(devm_gpio_free);
...@@ -21,6 +21,34 @@ ...@@ -21,6 +21,34 @@
#include <linux/gpio/machine.h> #include <linux/gpio/machine.h>
#include "gpiolib.h" #include "gpiolib.h"
#include "gpiolib-of.h"
/*
* This is used by external users of of_gpio_count() from <linux/of_gpio.h>
*
* FIXME: get rid of those external users by converting them to GPIO
* descriptors and let them all use gpiod_get_count()
*/
int of_gpio_get_count(struct device *dev, const char *con_id)
{
int ret;
char propname[32];
unsigned int i;
for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) {
if (con_id)
snprintf(propname, sizeof(propname), "%s-%s",
con_id, gpio_suffixes[i]);
else
snprintf(propname, sizeof(propname), "%s",
gpio_suffixes[i]);
ret = of_gpio_named_count(dev->of_node, propname);
if (ret > 0)
break;
}
return ret ? ret : -ENOENT;
}
static int of_gpiochip_match_node_and_xlate(struct gpio_chip *chip, void *data) static int of_gpiochip_match_node_and_xlate(struct gpio_chip *chip, void *data)
{ {
...@@ -53,6 +81,23 @@ static struct gpio_desc *of_xlate_and_get_gpiod_flags(struct gpio_chip *chip, ...@@ -53,6 +81,23 @@ static struct gpio_desc *of_xlate_and_get_gpiod_flags(struct gpio_chip *chip,
return gpiochip_get_desc(chip, ret); return gpiochip_get_desc(chip, ret);
} }
/**
* of_gpio_need_valid_mask() - figure out if the OF GPIO driver needs
* to set the .valid_mask
* @dev: the device for the GPIO provider
* @return: true if the valid mask needs to be set
*/
bool of_gpio_need_valid_mask(const struct gpio_chip *gc)
{
int size;
struct device_node *np = gc->of_node;
size = of_property_count_u32_elems(np, "gpio-reserved-ranges");
if (size > 0 && size % 2 == 0)
return true;
return false;
}
static void of_gpio_flags_quirks(struct device_node *np, static void of_gpio_flags_quirks(struct device_node *np,
const char *propname, const char *propname,
enum of_gpio_flags *flags, enum of_gpio_flags *flags,
...@@ -178,7 +223,7 @@ static void of_gpio_flags_quirks(struct device_node *np, ...@@ -178,7 +223,7 @@ static void of_gpio_flags_quirks(struct device_node *np,
* value on the error condition. If @flags is not NULL the function also fills * value on the error condition. If @flags is not NULL the function also fills
* in flags for the GPIO. * in flags for the GPIO.
*/ */
struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, static struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
const char *propname, int index, enum of_gpio_flags *flags) const char *propname, int index, enum of_gpio_flags *flags)
{ {
struct of_phandle_args gpiospec; struct of_phandle_args gpiospec;
...@@ -229,7 +274,76 @@ int of_get_named_gpio_flags(struct device_node *np, const char *list_name, ...@@ -229,7 +274,76 @@ int of_get_named_gpio_flags(struct device_node *np, const char *list_name,
else else
return desc_to_gpio(desc); return desc_to_gpio(desc);
} }
EXPORT_SYMBOL(of_get_named_gpio_flags); EXPORT_SYMBOL_GPL(of_get_named_gpio_flags);
/**
* gpiod_get_from_of_node() - obtain a GPIO from an OF node
* @node: handle of the OF node
* @propname: name of the DT property representing the GPIO
* @index: index of the GPIO to obtain for the consumer
* @dflags: GPIO initialization flags
* @label: label to attach to the requested GPIO
*
* Returns:
* On successful request the GPIO pin is configured in accordance with
* provided @dflags.
*
* In case of error an ERR_PTR() is returned.
*/
struct gpio_desc *gpiod_get_from_of_node(struct device_node *node,
const char *propname, int index,
enum gpiod_flags dflags,
const char *label)
{
unsigned long lflags = GPIO_LOOKUP_FLAGS_DEFAULT;
struct gpio_desc *desc;
enum of_gpio_flags flags;
bool active_low = false;
bool single_ended = false;
bool open_drain = false;
bool transitory = false;
int ret;
desc = of_get_named_gpiod_flags(node, propname,
index, &flags);
if (!desc || IS_ERR(desc)) {
return desc;
}
active_low = flags & OF_GPIO_ACTIVE_LOW;
single_ended = flags & OF_GPIO_SINGLE_ENDED;
open_drain = flags & OF_GPIO_OPEN_DRAIN;
transitory = flags & OF_GPIO_TRANSITORY;
ret = gpiod_request(desc, label);
if (ret == -EBUSY && (flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE))
return desc;
if (ret)
return ERR_PTR(ret);
if (active_low)
lflags |= GPIO_ACTIVE_LOW;
if (single_ended) {
if (open_drain)
lflags |= GPIO_OPEN_DRAIN;
else
lflags |= GPIO_OPEN_SOURCE;
}
if (transitory)
lflags |= GPIO_TRANSITORY;
ret = gpiod_configure_flags(desc, propname, lflags, dflags);
if (ret < 0) {
gpiod_put(desc);
return ERR_PTR(ret);
}
return desc;
}
EXPORT_SYMBOL_GPL(gpiod_get_from_of_node);
/* /*
* The SPI GPIO bindings happened before we managed to establish that GPIO * The SPI GPIO bindings happened before we managed to establish that GPIO
...@@ -324,6 +438,19 @@ static struct gpio_desc *of_find_regulator_gpio(struct device *dev, const char * ...@@ -324,6 +438,19 @@ static struct gpio_desc *of_find_regulator_gpio(struct device *dev, const char *
return desc; return desc;
} }
static struct gpio_desc *of_find_arizona_gpio(struct device *dev,
const char *con_id,
enum of_gpio_flags *of_flags)
{
if (!IS_ENABLED(CONFIG_MFD_ARIZONA))
return ERR_PTR(-ENOENT);
if (!con_id || strcmp(con_id, "wlf,reset"))
return ERR_PTR(-ENOENT);
return of_get_named_gpiod_flags(dev->of_node, con_id, 0, of_flags);
}
struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
unsigned int idx, unsigned long *flags) unsigned int idx, unsigned long *flags)
{ {
...@@ -365,6 +492,9 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, ...@@ -365,6 +492,9 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
desc = of_find_regulator_gpio(dev, con_id, &of_flags); desc = of_find_regulator_gpio(dev, con_id, &of_flags);
} }
if (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT)
desc = of_find_arizona_gpio(dev, con_id, &of_flags);
if (IS_ERR(desc)) if (IS_ERR(desc))
return desc; return desc;
...@@ -514,8 +644,9 @@ static int of_gpiochip_scan_gpios(struct gpio_chip *chip) ...@@ -514,8 +644,9 @@ static int of_gpiochip_scan_gpios(struct gpio_chip *chip)
* GPIO chips. This function performs only one sanity check: whether GPIO * GPIO chips. This function performs only one sanity check: whether GPIO
* is less than ngpios (that is specified in the gpio_chip). * is less than ngpios (that is specified in the gpio_chip).
*/ */
int of_gpio_simple_xlate(struct gpio_chip *gc, static int of_gpio_simple_xlate(struct gpio_chip *gc,
const struct of_phandle_args *gpiospec, u32 *flags) const struct of_phandle_args *gpiospec,
u32 *flags)
{ {
/* /*
* We're discouraging gpio_cells < 2, since that way you'll have to * We're discouraging gpio_cells < 2, since that way you'll have to
...@@ -539,7 +670,6 @@ int of_gpio_simple_xlate(struct gpio_chip *gc, ...@@ -539,7 +670,6 @@ int of_gpio_simple_xlate(struct gpio_chip *gc,
return gpiospec->args[0]; return gpiospec->args[0];
} }
EXPORT_SYMBOL(of_gpio_simple_xlate);
/** /**
* of_mm_gpiochip_add_data - Add memory mapped GPIO chip (bank) * of_mm_gpiochip_add_data - Add memory mapped GPIO chip (bank)
...@@ -596,7 +726,7 @@ int of_mm_gpiochip_add_data(struct device_node *np, ...@@ -596,7 +726,7 @@ int of_mm_gpiochip_add_data(struct device_node *np,
pr_err("%pOF: GPIO chip registration failed with status %d\n", np, ret); pr_err("%pOF: GPIO chip registration failed with status %d\n", np, ret);
return ret; return ret;
} }
EXPORT_SYMBOL(of_mm_gpiochip_add_data); EXPORT_SYMBOL_GPL(of_mm_gpiochip_add_data);
/** /**
* of_mm_gpiochip_remove - Remove memory mapped GPIO chip (bank) * of_mm_gpiochip_remove - Remove memory mapped GPIO chip (bank)
...@@ -613,7 +743,7 @@ void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc) ...@@ -613,7 +743,7 @@ void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc)
iounmap(mm_gc->regs); iounmap(mm_gc->regs);
kfree(gc->label); kfree(gc->label);
} }
EXPORT_SYMBOL(of_mm_gpiochip_remove); EXPORT_SYMBOL_GPL(of_mm_gpiochip_remove);
static void of_gpiochip_init_valid_mask(struct gpio_chip *chip) static void of_gpiochip_init_valid_mask(struct gpio_chip *chip)
{ {
...@@ -725,7 +855,7 @@ static int of_gpiochip_add_pin_range(struct gpio_chip *chip) { return 0; } ...@@ -725,7 +855,7 @@ static int of_gpiochip_add_pin_range(struct gpio_chip *chip) { return 0; }
int of_gpiochip_add(struct gpio_chip *chip) int of_gpiochip_add(struct gpio_chip *chip)
{ {
int status; int ret;
if (!chip->of_node) if (!chip->of_node)
return 0; return 0;
...@@ -740,9 +870,9 @@ int of_gpiochip_add(struct gpio_chip *chip) ...@@ -740,9 +870,9 @@ int of_gpiochip_add(struct gpio_chip *chip)
of_gpiochip_init_valid_mask(chip); of_gpiochip_init_valid_mask(chip);
status = of_gpiochip_add_pin_range(chip); ret = of_gpiochip_add_pin_range(chip);
if (status) if (ret)
return status; return ret;
/* If the chip defines names itself, these take precedence */ /* If the chip defines names itself, these take precedence */
if (!chip->names) if (!chip->names)
...@@ -751,13 +881,13 @@ int of_gpiochip_add(struct gpio_chip *chip) ...@@ -751,13 +881,13 @@ int of_gpiochip_add(struct gpio_chip *chip)
of_node_get(chip->of_node); of_node_get(chip->of_node);
status = of_gpiochip_scan_gpios(chip); ret = of_gpiochip_scan_gpios(chip);
if (status) { if (ret) {
of_node_put(chip->of_node); of_node_put(chip->of_node);
gpiochip_remove_pin_ranges(chip); gpiochip_remove_pin_ranges(chip);
} }
return status; return ret;
} }
void of_gpiochip_remove(struct gpio_chip *chip) void of_gpiochip_remove(struct gpio_chip *chip)
......
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef GPIOLIB_OF_H
#define GPIOLIB_OF_H
struct gpio_chip;
enum of_gpio_flags;
#ifdef CONFIG_OF_GPIO
struct gpio_desc *of_find_gpio(struct device *dev,
const char *con_id,
unsigned int idx,
unsigned long *lookupflags);
int of_gpiochip_add(struct gpio_chip *gc);
void of_gpiochip_remove(struct gpio_chip *gc);
int of_gpio_get_count(struct device *dev, const char *con_id);
bool of_gpio_need_valid_mask(const struct gpio_chip *gc);
#else
static inline struct gpio_desc *of_find_gpio(struct device *dev,
const char *con_id,
unsigned int idx,
unsigned long *lookupflags)
{
return ERR_PTR(-ENOENT);
}
static inline int of_gpiochip_add(struct gpio_chip *gc) { return 0; }
static inline void of_gpiochip_remove(struct gpio_chip *gc) { }
static inline int of_gpio_get_count(struct device *dev, const char *con_id)
{
return 0;
}
static inline bool of_gpio_need_valid_mask(const struct gpio_chip *gc)
{
return false;
}
#endif /* CONFIG_OF_GPIO */
#endif /* GPIOLIB_OF_H */
This diff is collapsed.
...@@ -16,9 +16,6 @@ ...@@ -16,9 +16,6 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/cdev.h> #include <linux/cdev.h>
enum of_gpio_flags;
struct acpi_device;
/** /**
* struct gpio_device - internal state container for GPIO devices * struct gpio_device - internal state container for GPIO devices
* @id: numerical ID number for the GPIO chip * @id: numerical ID number for the GPIO chip
...@@ -69,126 +66,9 @@ struct gpio_device { ...@@ -69,126 +66,9 @@ struct gpio_device {
#endif #endif
}; };
/**
* struct acpi_gpio_info - ACPI GPIO specific information
* @adev: reference to ACPI device which consumes GPIO resource
* @flags: GPIO initialization flags
* @gpioint: if %true this GPIO is of type GpioInt otherwise type is GpioIo
* @pin_config: pin bias as provided by ACPI
* @polarity: interrupt polarity as provided by ACPI
* @triggering: triggering type as provided by ACPI
* @quirks: Linux specific quirks as provided by struct acpi_gpio_mapping
*/
struct acpi_gpio_info {
struct acpi_device *adev;
enum gpiod_flags flags;
bool gpioint;
int pin_config;
int polarity;
int triggering;
unsigned int quirks;
};
/* gpio suffixes used for ACPI and device tree lookup */ /* gpio suffixes used for ACPI and device tree lookup */
static __maybe_unused const char * const gpio_suffixes[] = { "gpios", "gpio" }; static __maybe_unused const char * const gpio_suffixes[] = { "gpios", "gpio" };
#ifdef CONFIG_OF_GPIO
struct gpio_desc *of_find_gpio(struct device *dev,
const char *con_id,
unsigned int idx,
unsigned long *lookupflags);
struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
const char *list_name, int index, enum of_gpio_flags *flags);
int of_gpiochip_add(struct gpio_chip *gc);
void of_gpiochip_remove(struct gpio_chip *gc);
#else
static inline struct gpio_desc *of_find_gpio(struct device *dev,
const char *con_id,
unsigned int idx,
unsigned long *lookupflags)
{
return ERR_PTR(-ENOENT);
}
static inline struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
const char *list_name, int index, enum of_gpio_flags *flags)
{
return ERR_PTR(-ENOENT);
}
static inline int of_gpiochip_add(struct gpio_chip *gc) { return 0; }
static inline void of_gpiochip_remove(struct gpio_chip *gc) { }
#endif /* CONFIG_OF_GPIO */
#ifdef CONFIG_ACPI
void acpi_gpiochip_add(struct gpio_chip *chip);
void acpi_gpiochip_remove(struct gpio_chip *chip);
void acpi_gpiochip_request_interrupts(struct gpio_chip *chip);
void acpi_gpiochip_free_interrupts(struct gpio_chip *chip);
int acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags,
struct acpi_gpio_info *info);
int acpi_gpio_update_gpiod_lookup_flags(unsigned long *lookupflags,
struct acpi_gpio_info *info);
struct gpio_desc *acpi_find_gpio(struct device *dev,
const char *con_id,
unsigned int idx,
enum gpiod_flags *dflags,
unsigned long *lookupflags);
struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode,
const char *propname, int index,
struct acpi_gpio_info *info);
int acpi_gpio_count(struct device *dev, const char *con_id);
bool acpi_can_fallback_to_crs(struct acpi_device *adev, const char *con_id);
#else
static inline void acpi_gpiochip_add(struct gpio_chip *chip) { }
static inline void acpi_gpiochip_remove(struct gpio_chip *chip) { }
static inline void
acpi_gpiochip_request_interrupts(struct gpio_chip *chip) { }
static inline void
acpi_gpiochip_free_interrupts(struct gpio_chip *chip) { }
static inline int
acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, struct acpi_gpio_info *info)
{
return 0;
}
static inline int
acpi_gpio_update_gpiod_lookup_flags(unsigned long *lookupflags,
struct acpi_gpio_info *info)
{
return 0;
}
static inline struct gpio_desc *
acpi_find_gpio(struct device *dev, const char *con_id,
unsigned int idx, enum gpiod_flags *dflags,
unsigned long *lookupflags)
{
return ERR_PTR(-ENOENT);
}
static inline struct gpio_desc *
acpi_node_get_gpiod(struct fwnode_handle *fwnode, const char *propname,
int index, struct acpi_gpio_info *info)
{
return ERR_PTR(-ENXIO);
}
static inline int acpi_gpio_count(struct device *dev, const char *con_id)
{
return -ENODEV;
}
static inline bool acpi_can_fallback_to_crs(struct acpi_device *adev,
const char *con_id)
{
return false;
}
#endif
struct gpio_array { struct gpio_array {
struct gpio_desc **desc; struct gpio_desc **desc;
unsigned int size; unsigned int size;
......
This diff is collapsed.
...@@ -1455,6 +1455,20 @@ static void byt_gpio_irq_handler(struct irq_desc *desc) ...@@ -1455,6 +1455,20 @@ static void byt_gpio_irq_handler(struct irq_desc *desc)
chip->irq_eoi(data); chip->irq_eoi(data);
} }
static void byt_init_irq_valid_mask(struct gpio_chip *chip,
unsigned long *valid_mask,
unsigned int ngpios)
{
/*
* FIXME: currently the valid_mask is filled in as part of
* initializing the irq_chip below in byt_gpio_irq_init_hw().
* when converting this driver to the new way of passing the
* gpio_irq_chip along when adding the gpio_chip, move the
* mask initialization into this callback instead. Right now
* this callback is here to make sure the mask gets allocated.
*/
}
static void byt_gpio_irq_init_hw(struct byt_gpio *vg) static void byt_gpio_irq_init_hw(struct byt_gpio *vg)
{ {
struct gpio_chip *gc = &vg->chip; struct gpio_chip *gc = &vg->chip;
...@@ -1525,7 +1539,7 @@ static int byt_gpio_probe(struct byt_gpio *vg) ...@@ -1525,7 +1539,7 @@ static int byt_gpio_probe(struct byt_gpio *vg)
gc->can_sleep = false; gc->can_sleep = false;
gc->parent = &vg->pdev->dev; gc->parent = &vg->pdev->dev;
gc->ngpio = vg->soc_data->npins; gc->ngpio = vg->soc_data->npins;
gc->irq.need_valid_mask = true; gc->irq.init_valid_mask = byt_init_irq_valid_mask;
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
vg->saved_context = devm_kcalloc(&vg->pdev->dev, gc->ngpio, vg->saved_context = devm_kcalloc(&vg->pdev->dev, gc->ngpio,
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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