This is the bulk of GPIO changes for the v3.16 series:
- We are finalizing and fixing up the gpiochip irqchip helpers bringing a helpful irqchip implementation into the gpiolib core and avoiding duplicate code and, more importantly, duplicate bug fixes: - Support for using the helpers with threaded interrupt handlers as used on sleeping GPIO-irqchips - Do not set up hardware triggers for edges or levels if the default IRQ type is IRQ_TYPE_NONE - some drivers would exploit the fact that you could get default initialization of the IRQ type from the core at probe() but if no default type is set up from the helper, we should not call the driver to configure anything. Wait until a consumer requests the interrupt instead. - Make the irqchip helpers put the GPIO irqs into their own lock class. The GPIO irqchips can often emit (harmless, but annoying) lockdep warnings about recursions when they are in fact just cascaded IRQs. By putting them into their own lock class we help the lockdep core to keep track of things. - Switch the tc3589x GPIO expanders to use the irqchip helpers - Switch the OMAP GPIO driver to use the irqchip helpers - Add some documentation for the irqchip helpers - select IRQ_DOMAIN when using the helpers since some platforms may not be using this by default and it's a strict dependency. - Continued GPIO descriptor refactoring: - Remove the one instance of gpio_to_desc() from the device tree code, making the OF GPIO code use GPIO descriptors only. - Introduce gpiod_get_optional() and gpiod_get_optional_index() akin to the similar regulator functions for cases where the use of GPIO is optional and not strictly required. - Make of_get_named_gpiod_flags() private - we do not want to unnecessarily expose APIs to drivers that make the gpiolib harder than necessary to maintain and refactor. Privatize this function. - Support "-gpio" suffix for the OF GPIO retrieveal path. We used to look for "foo-gpios" or just "gpios" in device tree nodes, but it turns out that some drivers with a single GPIO line will just state "foo-gpio" (singularis). Sigh. Support this with a fallback looking for it, as this simplifies driver code and handles it in core code. - Switch the ACPI GPIO core to fetch GPIOs with the *_cansleep function variants as the GPIO operation region handler can sleep, and shall be able to handle gpiochips that sleep. - Tons of cleanups and janitorial work from Jingoo Han, Axel Lin, Javier Martinez Canillas and Abdoulaye Berthe. Notably Jingoo cut off a ton of pointless OOM messages. - Incremental development and fixes for various drivers, nothing really special here. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJTjDSbAAoJEEEQszewGV1zcwcQAI/fwAw2B8kelDMaB1ggQeAU cyXrr9vVXYMztOoYkYcbZq0stuvZT+CDCVJPqPqntYYssAJf/2m3xWEhz4XFcGui THTNIaFLc9f7JvTFfWS0VzwPzqPp/XkUiAyDzYMK0Wso6AP853IB4LlHDMvC9jpM brMo+zdhnASayhumAL8kp0XVal7d/3IAy/v7Q6ebpqoP5AnhC8NT8ysh2raGdVLa 4+W9hMtflq8u+gllxul71Mf1L3CD0x3UybMbsx4k0Z+60uYjiIhhbHdGxRVH3YAU DZ40RW6ARU1mXuUlSjBIbgN1fzxCKNQFR7MsDruiSR0ohHEa8dc3o1AktdRKGoQl +sUMSQI3G4tlLOhVYIOx+kOF4DJWNNFYNdvT/ut0NwKohma2nZt9LDyqp92XZKt9 gVufvJzFe94re/bAMAz41PRm3wnzmuUSAq649r0RIQ4Yp74f5n5EO9WnnI/CIVlw pAFsLJZZhh47I6IxMmIPBjiy8QWVdvRwsBIrV0pDoZGQjjm2S1MHi+5pLghHRROq qtrRG1SIAptoaEDWM0WdVPT4Jcx+3QzU9YjlCiXxd8qQl4lRHAJRCYbxGYsK0a8b eXQ5N4CHy2jOUTKhmT2ISLmC6EWurabSh9eWwmk2R2gBmwG6AKoI60MKFtcx53tz 3fQN3Oy8zaNyIL6/2aoN =M59o -----END PGP SIGNATURE----- Merge tag 'gpio-v3.16-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio into next Pull GPIO updates from Linus Walleij: "This is the bulk of GPIO changes for the v3.16 series. There is a lot of action in the GPIO subsystem doing refactorings and cleanups, almost as many deletions as insertions and minor feature growth and no new drivers this time. Which is actually pretty nice. Some GPIO-related stuff will come in through the pin control tree as well. Details: - We are finalizing and fixing up the gpiochip irqchip helpers bringing a helpful irqchip implementation into the gpiolib core and avoiding duplicate code and, more importantly, duplicate bug fixes: * Support for using the helpers with threaded interrupt handlers as used on sleeping GPIO-irqchips * Do not set up hardware triggers for edges or levels if the default IRQ type is IRQ_TYPE_NONE - some drivers would exploit the fact that you could get default initialization of the IRQ type from the core at probe() but if no default type is set up from the helper, we should not call the driver to configure anything. Wait until a consumer requests the interrupt instead. * Make the irqchip helpers put the GPIO irqs into their own lock class. The GPIO irqchips can often emit (harmless, but annoying) lockdep warnings about recursions when they are in fact just cascaded IRQs. By putting them into their own lock class we help the lockdep core to keep track of things. * Switch the tc3589x GPIO expanders to use the irqchip helpers * Switch the OMAP GPIO driver to use the irqchip helpers * Add some documentation for the irqchip helpers * select IRQ_DOMAIN when using the helpers since some platforms may not be using this by default and it's a strict dependency. - Continued GPIO descriptor refactoring: * Remove the one instance of gpio_to_desc() from the device tree code, making the OF GPIO code use GPIO descriptors only. * Introduce gpiod_get_optional() and gpiod_get_optional_index() akin to the similar regulator functions for cases where the use of GPIO is optional and not strictly required. * Make of_get_named_gpiod_flags() private - we do not want to unnecessarily expose APIs to drivers that make the gpiolib harder than necessary to maintain and refactor. Privatize this function. - Support "-gpio" suffix for the OF GPIO retrieveal path. We used to look for "foo-gpios" or just "gpios" in device tree nodes, but it turns out that some drivers with a single GPIO line will just state "foo-gpio" (singularis). Sigh. Support this with a fallback looking for it, as this simplifies driver code and handles it in core code. - Switch the ACPI GPIO core to fetch GPIOs with the *_cansleep function variants as the GPIO operation region handler can sleep, and shall be able to handle gpiochips that sleep. - Tons of cleanups and janitorial work from Jingoo Han, Axel Lin, Javier Martinez Canillas and Abdoulaye Berthe. Notably Jingoo cut off a ton of pointless OOM messages. - Incremental development and fixes for various drivers, nothing really special here" * tag 'gpio-v3.16-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (85 commits) gpio: select IRQ_DOMAIN for gpiolib irqchip helpers gpio: pca953x: use gpiolib irqchip helpers gpio: pcf857x: Add IRQF_SHARED when request irq gpio: pcf857x: Avoid calling irq_domain_cleanup twice gpio: mcp23s08: switch chip count to int gpio: dwapb: use a second irq chip gpio: ep93xx: Use devm_ioremap_resource() gpio: mcp23s08: fixed count variable for devicetree probing gpio: Add run-time dependencies to R-Car driver gpio: pch: add slab include Documentation / ACPI: Fix location of GPIO documentation gpio / ACPI: use *_cansleep version of gpiod_get/set APIs gpio: generic: add request function pointer gpio-pch: Fix Kconfig dependencies gpio: make of_get_named_gpiod_flags() private gpio: gpioep93xx: use devm functions gpio: janzttl: use devm function gpio: timberdale: use devm functions gpio: bt8xx: use devm function for memory allocation gpio: include linux/bug.h in interface header ...
This commit is contained in:
Коммит
80fb974798
|
@ -296,7 +296,7 @@ specifies the path to the controller. In order to use these GPIOs in Linux
|
|||
we need to translate them to the corresponding Linux GPIO descriptors.
|
||||
|
||||
There is a standard GPIO API for that and is documented in
|
||||
Documentation/gpio.txt.
|
||||
Documentation/gpio/.
|
||||
|
||||
In the above example we can get the corresponding two GPIO descriptors with
|
||||
a code like this:
|
||||
|
|
|
@ -21,6 +21,12 @@ Required Properties:
|
|||
GPIO_ACTIVE_HIGH and GPIO_ACTIVE_LOW flags are supported.
|
||||
- gpio-ranges: Range of pins managed by the GPIO controller.
|
||||
|
||||
Optional properties:
|
||||
|
||||
- clocks: Must contain a reference to the functional clock. The property is
|
||||
mandatory if the hardware implements a controllable functional clock for
|
||||
the GPIO instance.
|
||||
|
||||
Please refer to gpio.txt in this directory for details of gpio-ranges property
|
||||
and the common GPIO bindings used by client devices.
|
||||
|
||||
|
|
|
@ -308,3 +308,10 @@ SLAVE DMA ENGINE
|
|||
|
||||
SPI
|
||||
devm_spi_register_master()
|
||||
|
||||
GPIO
|
||||
devm_gpiod_get()
|
||||
devm_gpiod_get_index()
|
||||
devm_gpiod_get_optional()
|
||||
devm_gpiod_get_index_optional()
|
||||
devm_gpiod_put()
|
||||
|
|
|
@ -73,6 +73,65 @@ The IRQ portions of the GPIO block are implemented using an irqchip, using
|
|||
the header <linux/irq.h>. So basically such a driver is utilizing two sub-
|
||||
systems simultaneously: gpio and irq.
|
||||
|
||||
GPIO irqchips usually fall in one of two categories:
|
||||
|
||||
* CHAINED GPIO irqchips: these are usually the type that is embedded on
|
||||
an SoC. This means that there is a fast IRQ handler for the GPIOs that
|
||||
gets called in a chain from the parent IRQ handler, most typically the
|
||||
system interrupt controller. This means the GPIO irqchip is registered
|
||||
using irq_set_chained_handler() or the corresponding
|
||||
gpiochip_set_chained_irqchip() helper function, and the GPIO irqchip
|
||||
handler will be called immediately from the parent irqchip, while
|
||||
holding the IRQs disabled. The GPIO irqchip will then end up calling
|
||||
something like this sequence in its interrupt handler:
|
||||
|
||||
static irqreturn_t tc3589x_gpio_irq(int irq, void *data)
|
||||
chained_irq_enter(...);
|
||||
generic_handle_irq(...);
|
||||
chained_irq_exit(...);
|
||||
|
||||
Chained GPIO irqchips typically can NOT set the .can_sleep flag on
|
||||
struct gpio_chip, as everything happens directly in the callbacks.
|
||||
|
||||
* NESTED THREADED GPIO irqchips: these are off-chip GPIO expanders and any
|
||||
other GPIO irqchip residing on the other side of a sleeping bus. Of course
|
||||
such drivers that need slow bus traffic to read out IRQ status and similar,
|
||||
traffic which may in turn incur other IRQs to happen, cannot be handled
|
||||
in a quick IRQ handler with IRQs disabled. Instead they need to spawn a
|
||||
thread and then mask the parent IRQ line until the interrupt is handled
|
||||
by the driver. The hallmark of this driver is to call something like
|
||||
this in its interrupt handler:
|
||||
|
||||
static irqreturn_t tc3589x_gpio_irq(int irq, void *data)
|
||||
...
|
||||
handle_nested_irq(irq);
|
||||
|
||||
The hallmark of threaded GPIO irqchips is that they set the .can_sleep
|
||||
flag on struct gpio_chip to true, indicating that this chip may sleep
|
||||
when accessing the GPIOs.
|
||||
|
||||
To help out in handling the set-up and management of GPIO irqchips and the
|
||||
associated irqdomain and resource allocation callbacks, the gpiolib has
|
||||
some helpers that can be enabled by selecting the GPIOLIB_IRQCHIP Kconfig
|
||||
symbol:
|
||||
|
||||
* gpiochip_irqchip_add(): adds an 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_set_chained_irqchip(): sets up a chained irq handler for a
|
||||
gpio_chip from a parent IRQ and passes the struct gpio_chip* as handler
|
||||
data. (Notice handler data, since the irqchip data is likely used by the
|
||||
parent irqchip!) This is for the chained type of chip.
|
||||
|
||||
To use the helpers please keep the following in mind:
|
||||
|
||||
- Make sure to assign all relevant members of the struct gpio_chip so that
|
||||
the irqchip can initialize. E.g. .dev and .can_sleep shall be set up
|
||||
properly.
|
||||
|
||||
It is legal for any IRQ consumer to request an IRQ from any irqchip no matter
|
||||
if that is a combined GPIO+IRQ driver. The basic premise is that gpio_chip and
|
||||
irq_chip are orthogonal, and offering their services independent of each
|
||||
|
|
|
@ -6418,6 +6418,7 @@ F: drivers/usb/*/*omap*
|
|||
F: arch/arm/*omap*/usb*
|
||||
|
||||
OMAP GPIO DRIVER
|
||||
M: Javier Martinez Canillas <javier@dowhile0.org>
|
||||
M: Santosh Shilimkar <santosh.shilimkar@ti.com>
|
||||
M: Kevin Hilman <khilman@deeprootsystems.com>
|
||||
L: linux-omap@vger.kernel.org
|
||||
|
|
|
@ -56,6 +56,7 @@ config GPIO_ACPI
|
|||
depends on ACPI
|
||||
|
||||
config GPIOLIB_IRQCHIP
|
||||
select IRQ_DOMAIN
|
||||
bool
|
||||
|
||||
config DEBUG_GPIO
|
||||
|
@ -243,6 +244,15 @@ config GPIO_OCTEON
|
|||
Say yes here to support the on-chip GPIO lines on the OCTEON
|
||||
family of SOCs.
|
||||
|
||||
config GPIO_OMAP
|
||||
bool "TI OMAP GPIO support" if COMPILE_TEST && !ARCH_OMAP2PLUS
|
||||
default y if ARCH_OMAP
|
||||
depends on ARM
|
||||
select GENERIC_IRQ_CHIP
|
||||
select GPIOLIB_IRQCHIP
|
||||
help
|
||||
Say yes here to enable GPIO support for TI OMAP SoCs.
|
||||
|
||||
config GPIO_PL061
|
||||
bool "PrimeCell PL061 GPIO support"
|
||||
depends on ARM_AMBA
|
||||
|
@ -259,7 +269,7 @@ config GPIO_PXA
|
|||
|
||||
config GPIO_RCAR
|
||||
tristate "Renesas R-Car GPIO"
|
||||
depends on ARM
|
||||
depends on ARM && (ARCH_SHMOBILE || COMPILE_TEST)
|
||||
help
|
||||
Say yes here to support GPIO on Renesas R-Car SoCs.
|
||||
|
||||
|
@ -510,6 +520,7 @@ config GPIO_PCA953X
|
|||
config GPIO_PCA953X_IRQ
|
||||
bool "Interrupt controller support for PCA953x"
|
||||
depends on GPIO_PCA953X=y
|
||||
select GPIOLIB_IRQCHIP
|
||||
help
|
||||
Say yes here to enable the pca953x to be used as an interrupt
|
||||
controller. It requires the driver to be built in the kernel.
|
||||
|
@ -579,6 +590,7 @@ config GPIO_STP_XWAY
|
|||
config GPIO_TC3589X
|
||||
bool "TC3589X GPIOs"
|
||||
depends on MFD_TC3589X
|
||||
select GPIOLIB_IRQCHIP
|
||||
help
|
||||
This enables support for the GPIOs found on the TC3589X
|
||||
I/O Expander.
|
||||
|
@ -699,13 +711,13 @@ config GPIO_AMD8111
|
|||
config GPIO_INTEL_MID
|
||||
bool "Intel Mid GPIO support"
|
||||
depends on PCI && X86
|
||||
select IRQ_DOMAIN
|
||||
select GPIOLIB_IRQCHIP
|
||||
help
|
||||
Say Y here to support Intel Mid GPIO.
|
||||
|
||||
config GPIO_PCH
|
||||
tristate "Intel EG20T PCH/LAPIS Semiconductor IOH(ML7223/ML7831) GPIO"
|
||||
depends on PCI && X86
|
||||
depends on PCI && (X86_32 || COMPILE_TEST)
|
||||
select GENERIC_IRQ_CHIP
|
||||
help
|
||||
This driver is for PCH(Platform controller Hub) GPIO of Intel Topcliff
|
||||
|
@ -739,7 +751,7 @@ config GPIO_SODAVILLE
|
|||
|
||||
config GPIO_TIMBERDALE
|
||||
bool "Support for timberdale GPIO IP"
|
||||
depends on MFD_TIMBERDALE && HAS_IOMEM
|
||||
depends on MFD_TIMBERDALE
|
||||
---help---
|
||||
Add support for the GPIO IP in the timberdale FPGA.
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ obj-$(CONFIG_GPIO_MVEBU) += gpio-mvebu.o
|
|||
obj-$(CONFIG_GPIO_MXC) += gpio-mxc.o
|
||||
obj-$(CONFIG_GPIO_MXS) += gpio-mxs.o
|
||||
obj-$(CONFIG_GPIO_OCTEON) += gpio-octeon.o
|
||||
obj-$(CONFIG_ARCH_OMAP) += gpio-omap.o
|
||||
obj-$(CONFIG_GPIO_OMAP) += gpio-omap.o
|
||||
obj-$(CONFIG_GPIO_PCA953X) += gpio-pca953x.o
|
||||
obj-$(CONFIG_GPIO_PCF857X) += gpio-pcf857x.o
|
||||
obj-$(CONFIG_GPIO_PCH) += gpio-pch.o
|
||||
|
|
|
@ -51,6 +51,22 @@ struct gpio_desc *__must_check devm_gpiod_get(struct device *dev,
|
|||
}
|
||||
EXPORT_SYMBOL(devm_gpiod_get);
|
||||
|
||||
/**
|
||||
* devm_gpiod_get_optional - Resource-managed gpiod_get_optional()
|
||||
* @dev: GPIO consumer
|
||||
* @con_id: function within the GPIO consumer
|
||||
*
|
||||
* Managed gpiod_get_optional(). GPIO descriptors returned from this function
|
||||
* are automatically disposed on driver detach. See gpiod_get_optional() for
|
||||
* detailed information about behavior and return values.
|
||||
*/
|
||||
struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev,
|
||||
const char *con_id)
|
||||
{
|
||||
return devm_gpiod_get_index_optional(dev, con_id, 0);
|
||||
}
|
||||
EXPORT_SYMBOL(devm_gpiod_get_optional);
|
||||
|
||||
/**
|
||||
* devm_gpiod_get_index - Resource-managed gpiod_get_index()
|
||||
* @dev: GPIO consumer
|
||||
|
@ -86,6 +102,33 @@ struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
|
|||
}
|
||||
EXPORT_SYMBOL(devm_gpiod_get_index);
|
||||
|
||||
/**
|
||||
* devm_gpiod_get_index_optional - Resource-managed gpiod_get_index_optional()
|
||||
* @dev: GPIO consumer
|
||||
* @con_id: function within the GPIO consumer
|
||||
* @index: index of the GPIO to obtain in the consumer
|
||||
*
|
||||
* Managed gpiod_get_index_optional(). GPIO descriptors returned from this
|
||||
* function are automatically disposed on driver detach. See
|
||||
* gpiod_get_index_optional() for detailed information about behavior and
|
||||
* return values.
|
||||
*/
|
||||
struct gpio_desc *__must_check devm_gpiod_get_index_optional(struct device *dev,
|
||||
const char *con_id,
|
||||
unsigned int index)
|
||||
{
|
||||
struct gpio_desc *desc;
|
||||
|
||||
desc = devm_gpiod_get_index(dev, con_id, index);
|
||||
if (IS_ERR(desc)) {
|
||||
if (PTR_ERR(desc) == -ENOENT)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return desc;
|
||||
}
|
||||
EXPORT_SYMBOL(devm_gpiod_get_index_optional);
|
||||
|
||||
/**
|
||||
* devm_gpiod_put - Resource-managed gpiod_put()
|
||||
* @desc: GPIO descriptor to dispose of
|
||||
|
|
|
@ -106,10 +106,8 @@ static int adp5520_gpio_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
|
||||
if (dev == NULL) {
|
||||
dev_err(&pdev->dev, "failed to alloc memory\n");
|
||||
if (dev == NULL)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dev->master = pdev->dev.parent;
|
||||
|
||||
|
|
|
@ -379,10 +379,8 @@ static int adp5588_gpio_probe(struct i2c_client *client,
|
|||
}
|
||||
|
||||
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
||||
if (dev == NULL) {
|
||||
dev_err(&client->dev, "failed to alloc memory\n");
|
||||
if (dev == NULL)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dev->client = client;
|
||||
|
||||
|
|
|
@ -178,7 +178,7 @@ static int bt8xxgpio_probe(struct pci_dev *dev,
|
|||
struct bt8xxgpio *bg;
|
||||
int err;
|
||||
|
||||
bg = kzalloc(sizeof(*bg), GFP_KERNEL);
|
||||
bg = devm_kzalloc(&dev->dev, sizeof(struct bt8xxgpio), GFP_KERNEL);
|
||||
if (!bg)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -188,9 +188,9 @@ static int bt8xxgpio_probe(struct pci_dev *dev,
|
|||
err = pci_enable_device(dev);
|
||||
if (err) {
|
||||
printk(KERN_ERR "bt8xxgpio: Can't enable device.\n");
|
||||
goto err_freebg;
|
||||
return err;
|
||||
}
|
||||
if (!request_mem_region(pci_resource_start(dev, 0),
|
||||
if (!devm_request_mem_region(&dev->dev, pci_resource_start(dev, 0),
|
||||
pci_resource_len(dev, 0),
|
||||
"bt8xxgpio")) {
|
||||
printk(KERN_WARNING "bt8xxgpio: Can't request iomem (0x%llx).\n",
|
||||
|
@ -201,11 +201,11 @@ static int bt8xxgpio_probe(struct pci_dev *dev,
|
|||
pci_set_master(dev);
|
||||
pci_set_drvdata(dev, bg);
|
||||
|
||||
bg->mmio = ioremap(pci_resource_start(dev, 0), 0x1000);
|
||||
bg->mmio = devm_ioremap(&dev->dev, pci_resource_start(dev, 0), 0x1000);
|
||||
if (!bg->mmio) {
|
||||
printk(KERN_ERR "bt8xxgpio: ioremap() failed\n");
|
||||
err = -EIO;
|
||||
goto err_release_mem;
|
||||
goto err_disable;
|
||||
}
|
||||
|
||||
/* Disable interrupts */
|
||||
|
@ -220,18 +220,13 @@ static int bt8xxgpio_probe(struct pci_dev *dev,
|
|||
err = gpiochip_add(&bg->gpio);
|
||||
if (err) {
|
||||
printk(KERN_ERR "bt8xxgpio: Failed to register GPIOs\n");
|
||||
goto err_release_mem;
|
||||
goto err_disable;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_release_mem:
|
||||
release_mem_region(pci_resource_start(dev, 0),
|
||||
pci_resource_len(dev, 0));
|
||||
err_disable:
|
||||
pci_disable_device(dev);
|
||||
err_freebg:
|
||||
kfree(bg);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -250,8 +245,6 @@ static void bt8xxgpio_remove(struct pci_dev *pdev)
|
|||
release_mem_region(pci_resource_start(pdev, 0),
|
||||
pci_resource_len(pdev, 0));
|
||||
pci_disable_device(pdev);
|
||||
|
||||
kfree(bg);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
|
|
@ -230,10 +230,8 @@ static int davinci_gpio_probe(struct platform_device *pdev)
|
|||
chips = devm_kzalloc(dev,
|
||||
ngpio * sizeof(struct davinci_gpio_controller),
|
||||
GFP_KERNEL);
|
||||
if (!chips) {
|
||||
dev_err(dev, "Memory allocation failed\n");
|
||||
if (!chips)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
|
|
|
@ -198,6 +198,8 @@ static int dwapb_irq_set_type(struct irq_data *d, u32 type)
|
|||
break;
|
||||
}
|
||||
|
||||
irq_setup_alt_chip(d, type);
|
||||
|
||||
writel(level, gpio->regs + GPIO_INTTYPE_LEVEL);
|
||||
writel(polarity, gpio->regs + GPIO_INT_POLARITY);
|
||||
spin_unlock_irqrestore(&bgc->lock, flags);
|
||||
|
@ -213,7 +215,7 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
|
|||
struct irq_chip_generic *irq_gc;
|
||||
unsigned int hwirq, ngpio = gc->ngpio;
|
||||
struct irq_chip_type *ct;
|
||||
int err, irq;
|
||||
int err, irq, i;
|
||||
|
||||
irq = irq_of_parse_and_map(node, 0);
|
||||
if (!irq) {
|
||||
|
@ -227,7 +229,7 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
|
|||
if (!gpio->domain)
|
||||
return;
|
||||
|
||||
err = irq_alloc_domain_generic_chips(gpio->domain, ngpio, 1,
|
||||
err = irq_alloc_domain_generic_chips(gpio->domain, ngpio, 2,
|
||||
"gpio-dwapb", handle_level_irq,
|
||||
IRQ_NOREQUEST, 0,
|
||||
IRQ_GC_INIT_NESTED_LOCK);
|
||||
|
@ -248,20 +250,24 @@ static void dwapb_configure_irqs(struct dwapb_gpio *gpio,
|
|||
irq_gc->reg_base = gpio->regs;
|
||||
irq_gc->private = gpio;
|
||||
|
||||
ct = irq_gc->chip_types;
|
||||
ct->chip.irq_ack = irq_gc_ack_set_bit;
|
||||
ct->chip.irq_mask = irq_gc_mask_set_bit;
|
||||
ct->chip.irq_unmask = irq_gc_mask_clr_bit;
|
||||
ct->chip.irq_set_type = dwapb_irq_set_type;
|
||||
ct->chip.irq_enable = dwapb_irq_enable;
|
||||
ct->chip.irq_disable = dwapb_irq_disable;
|
||||
ct->chip.irq_request_resources = dwapb_irq_reqres;
|
||||
ct->chip.irq_release_resources = dwapb_irq_relres;
|
||||
ct->regs.ack = GPIO_PORTA_EOI;
|
||||
ct->regs.mask = GPIO_INTMASK;
|
||||
for (i = 0; i < 2; i++) {
|
||||
ct = &irq_gc->chip_types[i];
|
||||
ct->chip.irq_ack = irq_gc_ack_set_bit;
|
||||
ct->chip.irq_mask = irq_gc_mask_set_bit;
|
||||
ct->chip.irq_unmask = irq_gc_mask_clr_bit;
|
||||
ct->chip.irq_set_type = dwapb_irq_set_type;
|
||||
ct->chip.irq_enable = dwapb_irq_enable;
|
||||
ct->chip.irq_disable = dwapb_irq_disable;
|
||||
ct->chip.irq_request_resources = dwapb_irq_reqres;
|
||||
ct->chip.irq_release_resources = dwapb_irq_relres;
|
||||
ct->regs.ack = GPIO_PORTA_EOI;
|
||||
ct->regs.mask = GPIO_INTMASK;
|
||||
ct->type = IRQ_TYPE_LEVEL_MASK;
|
||||
}
|
||||
|
||||
irq_setup_generic_chip(irq_gc, IRQ_MSK(port->bgc.gc.ngpio),
|
||||
IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0);
|
||||
irq_gc->chip_types[0].type = IRQ_TYPE_LEVEL_MASK;
|
||||
irq_gc->chip_types[1].type = IRQ_TYPE_EDGE_BOTH;
|
||||
irq_gc->chip_types[1].handler = handle_edge_irq;
|
||||
|
||||
irq_set_chained_handler(irq, dwapb_irq_handler);
|
||||
irq_set_handler_data(irq, gpio);
|
||||
|
|
|
@ -212,7 +212,7 @@ static void __em_gio_set(struct gpio_chip *chip, unsigned int reg,
|
|||
{
|
||||
/* upper 16 bits contains mask and lower 16 actual value */
|
||||
em_gio_write(gpio_to_priv(chip), reg,
|
||||
(1 << (shift + 16)) | (value << shift));
|
||||
(BIT(shift + 16)) | (value << shift));
|
||||
}
|
||||
|
||||
static void em_gio_set(struct gpio_chip *chip, unsigned offset, int value)
|
||||
|
@ -284,7 +284,6 @@ static int em_gio_probe(struct platform_device *pdev)
|
|||
|
||||
p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
|
||||
if (!p) {
|
||||
dev_err(&pdev->dev, "failed to allocate driver data\n");
|
||||
ret = -ENOMEM;
|
||||
goto err0;
|
||||
}
|
||||
|
|
|
@ -344,37 +344,24 @@ static int ep93xx_gpio_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct ep93xx_gpio *ep93xx_gpio;
|
||||
struct resource *res;
|
||||
void __iomem *mmio;
|
||||
int i;
|
||||
int ret;
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
ep93xx_gpio = kzalloc(sizeof(*ep93xx_gpio), GFP_KERNEL);
|
||||
ep93xx_gpio = devm_kzalloc(dev, sizeof(struct ep93xx_gpio), GFP_KERNEL);
|
||||
if (!ep93xx_gpio)
|
||||
return -ENOMEM;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
ret = -ENXIO;
|
||||
goto exit_free;
|
||||
}
|
||||
|
||||
if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
|
||||
ret = -EBUSY;
|
||||
goto exit_free;
|
||||
}
|
||||
|
||||
mmio = ioremap(res->start, resource_size(res));
|
||||
if (!mmio) {
|
||||
ret = -ENXIO;
|
||||
goto exit_release;
|
||||
}
|
||||
ep93xx_gpio->mmio_base = mmio;
|
||||
ep93xx_gpio->mmio_base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(ep93xx_gpio->mmio_base))
|
||||
return PTR_ERR(ep93xx_gpio->mmio_base);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ep93xx_gpio_banks); i++) {
|
||||
struct bgpio_chip *bgc = &ep93xx_gpio->bgc[i];
|
||||
struct ep93xx_gpio_bank *bank = &ep93xx_gpio_banks[i];
|
||||
|
||||
if (ep93xx_gpio_add_bank(bgc, &pdev->dev, mmio, bank))
|
||||
if (ep93xx_gpio_add_bank(bgc, &pdev->dev,
|
||||
ep93xx_gpio->mmio_base, bank))
|
||||
dev_warn(&pdev->dev, "Unable to add gpio bank %s\n",
|
||||
bank->label);
|
||||
}
|
||||
|
@ -382,13 +369,6 @@ static int ep93xx_gpio_probe(struct platform_device *pdev)
|
|||
ep93xx_gpio_init_irq();
|
||||
|
||||
return 0;
|
||||
|
||||
exit_release:
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
exit_free:
|
||||
kfree(ep93xx_gpio);
|
||||
dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct platform_driver ep93xx_gpio_driver = {
|
||||
|
|
|
@ -18,15 +18,9 @@
|
|||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#define GEF_GPIO_DIRECT 0x00
|
||||
|
@ -39,28 +33,26 @@
|
|||
#define GEF_GPIO_OVERRUN 0x1C
|
||||
#define GEF_GPIO_MODE 0x20
|
||||
|
||||
static void _gef_gpio_set(void __iomem *reg, unsigned int offset, int value)
|
||||
static void gef_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
||||
{
|
||||
struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
|
||||
unsigned int data;
|
||||
|
||||
data = ioread32be(reg);
|
||||
/* value: 0=low; 1=high */
|
||||
if (value & 0x1)
|
||||
data = data | (0x1 << offset);
|
||||
data = ioread32be(mmchip->regs + GEF_GPIO_OUT);
|
||||
if (value)
|
||||
data = data | BIT(offset);
|
||||
else
|
||||
data = data & ~(0x1 << offset);
|
||||
|
||||
iowrite32be(data, reg);
|
||||
data = data & ~BIT(offset);
|
||||
iowrite32be(data, mmchip->regs + GEF_GPIO_OUT);
|
||||
}
|
||||
|
||||
|
||||
static int gef_gpio_dir_in(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
unsigned int data;
|
||||
struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
|
||||
|
||||
data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT);
|
||||
data = data | (0x1 << offset);
|
||||
data = data | BIT(offset);
|
||||
iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT);
|
||||
|
||||
return 0;
|
||||
|
@ -71,11 +63,11 @@ static int gef_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int value)
|
|||
unsigned int data;
|
||||
struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
|
||||
|
||||
/* Set direction before switching to input */
|
||||
_gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);
|
||||
/* Set value before switching to output */
|
||||
gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);
|
||||
|
||||
data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT);
|
||||
data = data & ~(0x1 << offset);
|
||||
data = data & ~BIT(offset);
|
||||
iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT);
|
||||
|
||||
return 0;
|
||||
|
@ -83,116 +75,56 @@ static int gef_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int value)
|
|||
|
||||
static int gef_gpio_get(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
unsigned int data;
|
||||
int state = 0;
|
||||
struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
|
||||
|
||||
data = ioread32be(mmchip->regs + GEF_GPIO_IN);
|
||||
state = (int)((data >> offset) & 0x1);
|
||||
|
||||
return state;
|
||||
return !!(ioread32be(mmchip->regs + GEF_GPIO_IN) & BIT(offset));
|
||||
}
|
||||
|
||||
static void gef_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
||||
{
|
||||
struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
|
||||
|
||||
_gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);
|
||||
}
|
||||
|
||||
static int __init gef_gpio_init(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
int retval;
|
||||
struct of_mm_gpio_chip *gef_gpio_chip;
|
||||
|
||||
for_each_compatible_node(np, NULL, "gef,sbc610-gpio") {
|
||||
|
||||
pr_debug("%s: Initialising GEF GPIO\n", np->full_name);
|
||||
|
||||
/* Allocate chip structure */
|
||||
gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);
|
||||
if (!gef_gpio_chip) {
|
||||
pr_err("%s: Unable to allocate structure\n",
|
||||
np->full_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Setup pointers to chip functions */
|
||||
gef_gpio_chip->gc.of_gpio_n_cells = 2;
|
||||
gef_gpio_chip->gc.ngpio = 19;
|
||||
gef_gpio_chip->gc.direction_input = gef_gpio_dir_in;
|
||||
gef_gpio_chip->gc.direction_output = gef_gpio_dir_out;
|
||||
gef_gpio_chip->gc.get = gef_gpio_get;
|
||||
gef_gpio_chip->gc.set = gef_gpio_set;
|
||||
|
||||
/* This function adds a memory mapped GPIO chip */
|
||||
retval = of_mm_gpiochip_add(np, gef_gpio_chip);
|
||||
if (retval) {
|
||||
kfree(gef_gpio_chip);
|
||||
pr_err("%s: Unable to add GPIO\n", np->full_name);
|
||||
}
|
||||
}
|
||||
|
||||
for_each_compatible_node(np, NULL, "gef,sbc310-gpio") {
|
||||
|
||||
pr_debug("%s: Initialising GEF GPIO\n", np->full_name);
|
||||
|
||||
/* Allocate chip structure */
|
||||
gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);
|
||||
if (!gef_gpio_chip) {
|
||||
pr_err("%s: Unable to allocate structure\n",
|
||||
np->full_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Setup pointers to chip functions */
|
||||
gef_gpio_chip->gc.of_gpio_n_cells = 2;
|
||||
gef_gpio_chip->gc.ngpio = 6;
|
||||
gef_gpio_chip->gc.direction_input = gef_gpio_dir_in;
|
||||
gef_gpio_chip->gc.direction_output = gef_gpio_dir_out;
|
||||
gef_gpio_chip->gc.get = gef_gpio_get;
|
||||
gef_gpio_chip->gc.set = gef_gpio_set;
|
||||
|
||||
/* This function adds a memory mapped GPIO chip */
|
||||
retval = of_mm_gpiochip_add(np, gef_gpio_chip);
|
||||
if (retval) {
|
||||
kfree(gef_gpio_chip);
|
||||
pr_err("%s: Unable to add GPIO\n", np->full_name);
|
||||
}
|
||||
}
|
||||
|
||||
for_each_compatible_node(np, NULL, "ge,imp3a-gpio") {
|
||||
|
||||
pr_debug("%s: Initialising GE GPIO\n", np->full_name);
|
||||
|
||||
/* Allocate chip structure */
|
||||
gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);
|
||||
if (!gef_gpio_chip) {
|
||||
pr_err("%s: Unable to allocate structure\n",
|
||||
np->full_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Setup pointers to chip functions */
|
||||
gef_gpio_chip->gc.of_gpio_n_cells = 2;
|
||||
gef_gpio_chip->gc.ngpio = 16;
|
||||
gef_gpio_chip->gc.direction_input = gef_gpio_dir_in;
|
||||
gef_gpio_chip->gc.direction_output = gef_gpio_dir_out;
|
||||
gef_gpio_chip->gc.get = gef_gpio_get;
|
||||
gef_gpio_chip->gc.set = gef_gpio_set;
|
||||
|
||||
/* This function adds a memory mapped GPIO chip */
|
||||
retval = of_mm_gpiochip_add(np, gef_gpio_chip);
|
||||
if (retval) {
|
||||
kfree(gef_gpio_chip);
|
||||
pr_err("%s: Unable to add GPIO\n", np->full_name);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
static const struct of_device_id gef_gpio_ids[] = {
|
||||
{
|
||||
.compatible = "gef,sbc610-gpio",
|
||||
.data = (void *)19,
|
||||
}, {
|
||||
.compatible = "gef,sbc310-gpio",
|
||||
.data = (void *)6,
|
||||
}, {
|
||||
.compatible = "ge,imp3a-gpio",
|
||||
.data = (void *)16,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
arch_initcall(gef_gpio_init);
|
||||
MODULE_DEVICE_TABLE(of, gef_gpio_ids);
|
||||
|
||||
static int __init gef_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct of_device_id *of_id =
|
||||
of_match_device(gef_gpio_ids, &pdev->dev);
|
||||
struct of_mm_gpio_chip *mmchip;
|
||||
|
||||
mmchip = devm_kzalloc(&pdev->dev, sizeof(*mmchip), GFP_KERNEL);
|
||||
if (!mmchip)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Setup pointers to chip functions */
|
||||
mmchip->gc.ngpio = (u16)(uintptr_t)of_id->data;
|
||||
mmchip->gc.of_gpio_n_cells = 2;
|
||||
mmchip->gc.direction_input = gef_gpio_dir_in;
|
||||
mmchip->gc.direction_output = gef_gpio_dir_out;
|
||||
mmchip->gc.get = gef_gpio_get;
|
||||
mmchip->gc.set = gef_gpio_set;
|
||||
|
||||
/* This function adds a memory mapped GPIO chip */
|
||||
return of_mm_gpiochip_add(pdev->dev.of_node, mmchip);
|
||||
};
|
||||
|
||||
static struct platform_driver gef_gpio_driver = {
|
||||
.driver = {
|
||||
.name = "gef-gpio",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = gef_gpio_ids,
|
||||
},
|
||||
};
|
||||
module_platform_driver_probe(gef_gpio_driver, gef_gpio_probe);
|
||||
|
||||
MODULE_DESCRIPTION("GE I/O FPGA GPIO driver");
|
||||
MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com");
|
||||
|
|
|
@ -388,6 +388,14 @@ static int bgpio_setup_direction(struct bgpio_chip *bgc,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int bgpio_request(struct gpio_chip *chip, unsigned gpio_pin)
|
||||
{
|
||||
if (gpio_pin < chip->ngpio)
|
||||
return 0;
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int bgpio_remove(struct bgpio_chip *bgc)
|
||||
{
|
||||
return gpiochip_remove(&bgc->gc);
|
||||
|
@ -413,6 +421,7 @@ int bgpio_init(struct bgpio_chip *bgc, struct device *dev,
|
|||
bgc->gc.label = dev_name(dev);
|
||||
bgc->gc.base = -1;
|
||||
bgc->gc.ngpio = bgc->bits;
|
||||
bgc->gc.request = bgpio_request;
|
||||
|
||||
ret = bgpio_setup_io(bgc, dat, set, clr);
|
||||
if (ret)
|
||||
|
|
|
@ -481,7 +481,7 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static struct of_device_id grgpio_match[] = {
|
||||
static const struct of_device_id grgpio_match[] = {
|
||||
{.name = "GAISLER_GPIO"},
|
||||
{.name = "01_01a"},
|
||||
{},
|
||||
|
|
|
@ -152,34 +152,21 @@ static int ttl_probe(struct platform_device *pdev)
|
|||
pdata = dev_get_platdata(&pdev->dev);
|
||||
if (!pdata) {
|
||||
dev_err(dev, "no platform data\n");
|
||||
ret = -ENXIO;
|
||||
goto out_return;
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
mod = kzalloc(sizeof(*mod), GFP_KERNEL);
|
||||
if (!mod) {
|
||||
dev_err(dev, "unable to allocate private data\n");
|
||||
ret = -ENOMEM;
|
||||
goto out_return;
|
||||
}
|
||||
mod = devm_kzalloc(dev, sizeof(*mod), GFP_KERNEL);
|
||||
if (!mod)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(pdev, mod);
|
||||
spin_lock_init(&mod->lock);
|
||||
|
||||
/* get access to the MODULbus registers for this module */
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(dev, "MODULbus registers not found\n");
|
||||
ret = -ENODEV;
|
||||
goto out_free_mod;
|
||||
}
|
||||
|
||||
mod->regs = ioremap(res->start, resource_size(res));
|
||||
if (!mod->regs) {
|
||||
dev_err(dev, "MODULbus registers not ioremap\n");
|
||||
ret = -ENOMEM;
|
||||
goto out_free_mod;
|
||||
}
|
||||
mod->regs = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(mod->regs))
|
||||
return PTR_ERR(mod->regs);
|
||||
|
||||
ttl_setup_device(mod);
|
||||
|
||||
|
@ -198,17 +185,10 @@ static int ttl_probe(struct platform_device *pdev)
|
|||
ret = gpiochip_add(gpio);
|
||||
if (ret) {
|
||||
dev_err(dev, "unable to add GPIO chip\n");
|
||||
goto out_iounmap_regs;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_iounmap_regs:
|
||||
iounmap(mod->regs);
|
||||
out_free_mod:
|
||||
kfree(mod);
|
||||
out_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ttl_remove(struct platform_device *pdev)
|
||||
|
@ -223,8 +203,6 @@ static int ttl_remove(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
iounmap(mod->regs);
|
||||
kfree(mod);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include <linux/mfd/kempld.h>
|
||||
|
||||
#define KEMPLD_GPIO_MAX_NUM 16
|
||||
#define KEMPLD_GPIO_MASK(x) (1 << ((x) % 8))
|
||||
#define KEMPLD_GPIO_MASK(x) (BIT((x) % 8))
|
||||
#define KEMPLD_GPIO_DIR_NUM(x) (0x40 + (x) / 8)
|
||||
#define KEMPLD_GPIO_LVL_NUM(x) (0x42 + (x) / 8)
|
||||
#define KEMPLD_GPIO_EVT_LVL_EDGE 0x46
|
||||
|
@ -216,4 +216,4 @@ module_platform_driver(kempld_gpio_driver);
|
|||
MODULE_DESCRIPTION("KEM PLD GPIO Driver");
|
||||
MODULE_AUTHOR("Michael Brunner <michael.brunner@kontron.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:gpio-kempld");
|
||||
MODULE_ALIAS("platform:kempld-gpio");
|
||||
|
|
|
@ -375,10 +375,8 @@ static int lp_gpio_probe(struct platform_device *pdev)
|
|||
int ret = -ENODEV;
|
||||
|
||||
lg = devm_kzalloc(dev, sizeof(struct lp_gpio), GFP_KERNEL);
|
||||
if (!lg) {
|
||||
dev_err(dev, "can't allocate lp_gpio chip data\n");
|
||||
if (!lg)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
lg->pdev = pdev;
|
||||
platform_set_drvdata(pdev, lg);
|
||||
|
|
|
@ -237,10 +237,9 @@ int __max730x_remove(struct device *dev)
|
|||
ts->write(dev, 0x04, 0x00);
|
||||
|
||||
ret = gpiochip_remove(&ts->chip);
|
||||
if (!ret) {
|
||||
if (!ret)
|
||||
mutex_destroy(&ts->lock);
|
||||
kfree(ts);
|
||||
} else
|
||||
else
|
||||
dev_err(dev, "Failed to remove GPIO controller: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -714,7 +714,7 @@ fail:
|
|||
|
||||
#ifdef CONFIG_OF
|
||||
#ifdef CONFIG_SPI_MASTER
|
||||
static struct of_device_id mcp23s08_spi_of_match[] = {
|
||||
static const struct of_device_id mcp23s08_spi_of_match[] = {
|
||||
{
|
||||
.compatible = "microchip,mcp23s08",
|
||||
.data = (void *) MCP_TYPE_S08,
|
||||
|
@ -738,7 +738,7 @@ MODULE_DEVICE_TABLE(of, mcp23s08_spi_of_match);
|
|||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_I2C)
|
||||
static struct of_device_id mcp23s08_i2c_of_match[] = {
|
||||
static const struct of_device_id mcp23s08_i2c_of_match[] = {
|
||||
{
|
||||
.compatible = "microchip,mcp23008",
|
||||
.data = (void *) MCP_TYPE_008,
|
||||
|
@ -867,7 +867,7 @@ static int mcp23s08_probe(struct spi_device *spi)
|
|||
{
|
||||
struct mcp23s08_platform_data *pdata;
|
||||
unsigned addr;
|
||||
unsigned chips = 0;
|
||||
int chips = 0;
|
||||
struct mcp23s08_driver_data *data;
|
||||
int status, type;
|
||||
unsigned base = -1,
|
||||
|
@ -894,11 +894,14 @@ static int mcp23s08_probe(struct spi_device *spi)
|
|||
dev_err(&spi->dev, "invalid spi-present-mask\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) {
|
||||
if ((spi_present_mask & (1 << addr)))
|
||||
chips++;
|
||||
pullups[addr] = 0;
|
||||
if (spi_present_mask & (1 << addr))
|
||||
chips++;
|
||||
}
|
||||
if (!chips)
|
||||
return -ENODEV;
|
||||
} else {
|
||||
type = spi_get_device_id(spi)->driver_data;
|
||||
pdata = dev_get_platdata(&spi->dev);
|
||||
|
@ -937,6 +940,10 @@ static int mcp23s08_probe(struct spi_device *spi)
|
|||
if (!(spi_present_mask & (1 << addr)))
|
||||
continue;
|
||||
chips--;
|
||||
if (chips < 0) {
|
||||
dev_err(&spi->dev, "FATAL: invalid negative chip id\n");
|
||||
goto fail;
|
||||
}
|
||||
data->mcp[addr] = &data->chip[chips];
|
||||
status = mcp23s08_probe_one(data->mcp[addr], &spi->dev, spi,
|
||||
0x40 | (addr << 1), type, base,
|
||||
|
|
|
@ -113,10 +113,8 @@ static int moxart_gpio_probe(struct platform_device *pdev)
|
|||
int ret;
|
||||
|
||||
mgc = devm_kzalloc(dev, sizeof(*mgc), GFP_KERNEL);
|
||||
if (!mgc) {
|
||||
dev_err(dev, "can't allocate GPIO chip container\n");
|
||||
if (!mgc)
|
||||
return -ENOMEM;
|
||||
}
|
||||
mgc->gpio = moxart_template_chip;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
|
|
|
@ -535,7 +535,7 @@ static void mvebu_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
|
|||
#define mvebu_gpio_dbg_show NULL
|
||||
#endif
|
||||
|
||||
static struct of_device_id mvebu_gpio_of_match[] = {
|
||||
static const struct of_device_id mvebu_gpio_of_match[] = {
|
||||
{
|
||||
.compatible = "marvell,orion-gpio",
|
||||
.data = (void *) MVEBU_GPIO_SOC_VARIANT_ORION,
|
||||
|
@ -574,10 +574,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
|
|||
soc_variant = MVEBU_GPIO_SOC_VARIANT_ORION;
|
||||
|
||||
mvchip = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_gpio_chip), GFP_KERNEL);
|
||||
if (!mvchip) {
|
||||
dev_err(&pdev->dev, "Cannot allocate memory\n");
|
||||
if (!mvchip)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios)) {
|
||||
dev_err(&pdev->dev, "Missing ngpios OF property\n");
|
||||
|
@ -738,9 +736,4 @@ static struct platform_driver mvebu_gpio_driver = {
|
|||
},
|
||||
.probe = mvebu_gpio_probe,
|
||||
};
|
||||
|
||||
static int __init mvebu_gpio_init(void)
|
||||
{
|
||||
return platform_driver_register(&mvebu_gpio_driver);
|
||||
}
|
||||
postcore_initcall(mvebu_gpio_init);
|
||||
module_platform_driver(mvebu_gpio_driver);
|
||||
|
|
|
@ -24,9 +24,9 @@
|
|||
#include <linux/pm.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/irqchip/chained_irq.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/platform_data/gpio-omap.h>
|
||||
|
||||
#define OFF_MODE 1
|
||||
|
@ -52,7 +52,6 @@ struct gpio_bank {
|
|||
struct list_head node;
|
||||
void __iomem *base;
|
||||
u16 irq;
|
||||
struct irq_domain *domain;
|
||||
u32 non_wakeup_gpios;
|
||||
u32 enabled_non_wakeup_gpios;
|
||||
struct gpio_regs context;
|
||||
|
@ -84,22 +83,21 @@ struct gpio_bank {
|
|||
};
|
||||
|
||||
#define GPIO_INDEX(bank, gpio) (gpio % bank->width)
|
||||
#define GPIO_BIT(bank, gpio) (1 << GPIO_INDEX(bank, gpio))
|
||||
#define GPIO_BIT(bank, gpio) (BIT(GPIO_INDEX(bank, gpio)))
|
||||
#define GPIO_MOD_CTRL_BIT BIT(0)
|
||||
|
||||
#define BANK_USED(bank) (bank->mod_usage || bank->irq_usage)
|
||||
#define LINE_USED(line, offset) (line & (1 << offset))
|
||||
#define LINE_USED(line, offset) (line & (BIT(offset)))
|
||||
|
||||
static int irq_to_gpio(struct gpio_bank *bank, unsigned int gpio_irq)
|
||||
{
|
||||
return bank->chip.base + gpio_irq;
|
||||
}
|
||||
|
||||
static int omap_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
|
||||
static inline struct gpio_bank *_irq_data_get_bank(struct irq_data *d)
|
||||
{
|
||||
struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip);
|
||||
|
||||
return irq_find_mapping(bank->domain, offset);
|
||||
struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
|
||||
return container_of(chip, struct gpio_bank, chip);
|
||||
}
|
||||
|
||||
static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
|
||||
|
@ -110,9 +108,9 @@ static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input)
|
|||
reg += bank->regs->direction;
|
||||
l = readl_relaxed(reg);
|
||||
if (is_input)
|
||||
l |= 1 << gpio;
|
||||
l |= BIT(gpio);
|
||||
else
|
||||
l &= ~(1 << gpio);
|
||||
l &= ~(BIT(gpio));
|
||||
writel_relaxed(l, reg);
|
||||
bank->context.oe = l;
|
||||
}
|
||||
|
@ -155,14 +153,14 @@ static int _get_gpio_datain(struct gpio_bank *bank, int offset)
|
|||
{
|
||||
void __iomem *reg = bank->base + bank->regs->datain;
|
||||
|
||||
return (readl_relaxed(reg) & (1 << offset)) != 0;
|
||||
return (readl_relaxed(reg) & (BIT(offset))) != 0;
|
||||
}
|
||||
|
||||
static int _get_gpio_dataout(struct gpio_bank *bank, int offset)
|
||||
{
|
||||
void __iomem *reg = bank->base + bank->regs->dataout;
|
||||
|
||||
return (readl_relaxed(reg) & (1 << offset)) != 0;
|
||||
return (readl_relaxed(reg) & (BIT(offset))) != 0;
|
||||
}
|
||||
|
||||
static inline void _gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set)
|
||||
|
@ -180,7 +178,7 @@ static inline void _gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set)
|
|||
static inline void _gpio_dbck_enable(struct gpio_bank *bank)
|
||||
{
|
||||
if (bank->dbck_enable_mask && !bank->dbck_enabled) {
|
||||
clk_enable(bank->dbck);
|
||||
clk_prepare_enable(bank->dbck);
|
||||
bank->dbck_enabled = true;
|
||||
|
||||
writel_relaxed(bank->dbck_enable_mask,
|
||||
|
@ -198,7 +196,7 @@ static inline void _gpio_dbck_disable(struct gpio_bank *bank)
|
|||
*/
|
||||
writel_relaxed(0, bank->base + bank->regs->debounce_en);
|
||||
|
||||
clk_disable(bank->dbck);
|
||||
clk_disable_unprepare(bank->dbck);
|
||||
bank->dbck_enabled = false;
|
||||
}
|
||||
}
|
||||
|
@ -231,7 +229,7 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
|
|||
|
||||
l = GPIO_BIT(bank, gpio);
|
||||
|
||||
clk_enable(bank->dbck);
|
||||
clk_prepare_enable(bank->dbck);
|
||||
reg = bank->base + bank->regs->debounce;
|
||||
writel_relaxed(debounce, reg);
|
||||
|
||||
|
@ -245,7 +243,7 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
|
|||
bank->dbck_enable_mask = val;
|
||||
|
||||
writel_relaxed(val, reg);
|
||||
clk_disable(bank->dbck);
|
||||
clk_disable_unprepare(bank->dbck);
|
||||
/*
|
||||
* Enable debounce clock per module.
|
||||
* This call is mandatory because in omap_gpio_request() when
|
||||
|
@ -290,7 +288,7 @@ static void _clear_gpio_debounce(struct gpio_bank *bank, unsigned gpio)
|
|||
bank->context.debounce = 0;
|
||||
writel_relaxed(bank->context.debounce, bank->base +
|
||||
bank->regs->debounce);
|
||||
clk_disable(bank->dbck);
|
||||
clk_disable_unprepare(bank->dbck);
|
||||
bank->dbck_enabled = false;
|
||||
}
|
||||
}
|
||||
|
@ -299,7 +297,7 @@ static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio,
|
|||
unsigned trigger)
|
||||
{
|
||||
void __iomem *base = bank->base;
|
||||
u32 gpio_bit = 1 << gpio;
|
||||
u32 gpio_bit = BIT(gpio);
|
||||
|
||||
_gpio_rmw(base, bank->regs->leveldetect0, gpio_bit,
|
||||
trigger & IRQ_TYPE_LEVEL_LOW);
|
||||
|
@ -368,9 +366,9 @@ static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio)
|
|||
|
||||
l = readl_relaxed(reg);
|
||||
if ((l >> gpio) & 1)
|
||||
l &= ~(1 << gpio);
|
||||
l &= ~(BIT(gpio));
|
||||
else
|
||||
l |= 1 << gpio;
|
||||
l |= BIT(gpio);
|
||||
|
||||
writel_relaxed(l, reg);
|
||||
}
|
||||
|
@ -392,11 +390,11 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio,
|
|||
|
||||
l = readl_relaxed(reg);
|
||||
if ((trigger & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH)
|
||||
bank->toggle_mask |= 1 << gpio;
|
||||
bank->toggle_mask |= BIT(gpio);
|
||||
if (trigger & IRQ_TYPE_EDGE_RISING)
|
||||
l |= 1 << gpio;
|
||||
l |= BIT(gpio);
|
||||
else if (trigger & IRQ_TYPE_EDGE_FALLING)
|
||||
l &= ~(1 << gpio);
|
||||
l &= ~(BIT(gpio));
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -413,10 +411,10 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio,
|
|||
if (trigger & IRQ_TYPE_EDGE_RISING)
|
||||
l |= 2 << (gpio << 1);
|
||||
if (trigger & IRQ_TYPE_EDGE_FALLING)
|
||||
l |= 1 << (gpio << 1);
|
||||
l |= BIT(gpio << 1);
|
||||
|
||||
/* Enable wake-up during idle for dynamic tick */
|
||||
_gpio_rmw(base, bank->regs->wkup_en, 1 << gpio, trigger);
|
||||
_gpio_rmw(base, bank->regs->wkup_en, BIT(gpio), trigger);
|
||||
bank->context.wake_en =
|
||||
readl_relaxed(bank->base + bank->regs->wkup_en);
|
||||
writel_relaxed(l, reg);
|
||||
|
@ -430,7 +428,7 @@ static void _enable_gpio_module(struct gpio_bank *bank, unsigned offset)
|
|||
void __iomem *reg = bank->base + bank->regs->pinctrl;
|
||||
|
||||
/* Claim the pin for MPU */
|
||||
writel_relaxed(readl_relaxed(reg) | (1 << offset), reg);
|
||||
writel_relaxed(readl_relaxed(reg) | (BIT(offset)), reg);
|
||||
}
|
||||
|
||||
if (bank->regs->ctrl && !BANK_USED(bank)) {
|
||||
|
@ -453,7 +451,7 @@ static void _disable_gpio_module(struct gpio_bank *bank, unsigned offset)
|
|||
!LINE_USED(bank->mod_usage, offset) &&
|
||||
!LINE_USED(bank->irq_usage, offset)) {
|
||||
/* Disable wake-up during idle for dynamic tick */
|
||||
_gpio_rmw(base, bank->regs->wkup_en, 1 << offset, 0);
|
||||
_gpio_rmw(base, bank->regs->wkup_en, BIT(offset), 0);
|
||||
bank->context.wake_en =
|
||||
readl_relaxed(bank->base + bank->regs->wkup_en);
|
||||
}
|
||||
|
@ -479,7 +477,7 @@ static int gpio_is_input(struct gpio_bank *bank, int mask)
|
|||
|
||||
static int gpio_irq_type(struct irq_data *d, unsigned type)
|
||||
{
|
||||
struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
|
||||
struct gpio_bank *bank = _irq_data_get_bank(d);
|
||||
unsigned gpio = 0;
|
||||
int retval;
|
||||
unsigned long flags;
|
||||
|
@ -509,20 +507,12 @@ static int gpio_irq_type(struct irq_data *d, unsigned type)
|
|||
if (!LINE_USED(bank->mod_usage, offset)) {
|
||||
_enable_gpio_module(bank, offset);
|
||||
_set_gpio_direction(bank, offset, 1);
|
||||
} else if (!gpio_is_input(bank, 1 << offset)) {
|
||||
} else if (!gpio_is_input(bank, BIT(offset))) {
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
retval = gpio_lock_as_irq(&bank->chip, offset);
|
||||
if (retval) {
|
||||
dev_err(bank->dev, "unable to lock offset %d for IRQ\n",
|
||||
offset);
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
return retval;
|
||||
}
|
||||
|
||||
bank->irq_usage |= 1 << GPIO_INDEX(bank, gpio);
|
||||
bank->irq_usage |= BIT(GPIO_INDEX(bank, gpio));
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
|
||||
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
|
||||
|
@ -559,7 +549,7 @@ static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank)
|
|||
{
|
||||
void __iomem *reg = bank->base;
|
||||
u32 l;
|
||||
u32 mask = (1 << bank->width) - 1;
|
||||
u32 mask = (BIT(bank->width)) - 1;
|
||||
|
||||
reg += bank->regs->irqenable;
|
||||
l = readl_relaxed(reg);
|
||||
|
@ -664,7 +654,7 @@ static void _reset_gpio(struct gpio_bank *bank, int gpio)
|
|||
/* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
|
||||
static int gpio_wake_enable(struct irq_data *d, unsigned int enable)
|
||||
{
|
||||
struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
|
||||
struct gpio_bank *bank = _irq_data_get_bank(d);
|
||||
unsigned int gpio = irq_to_gpio(bank, d->hwirq);
|
||||
|
||||
return _set_gpio_wakeup(bank, gpio, enable);
|
||||
|
@ -691,7 +681,7 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
|
|||
_set_gpio_triggering(bank, offset, IRQ_TYPE_NONE);
|
||||
_enable_gpio_module(bank, offset);
|
||||
}
|
||||
bank->mod_usage |= 1 << offset;
|
||||
bank->mod_usage |= BIT(offset);
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
|
||||
return 0;
|
||||
|
@ -703,7 +693,7 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)
|
|||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
bank->mod_usage &= ~(1 << offset);
|
||||
bank->mod_usage &= ~(BIT(offset));
|
||||
_disable_gpio_module(bank, offset);
|
||||
_reset_gpio(bank, bank->chip.base + offset);
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
|
@ -732,11 +722,12 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
|
|||
unsigned int bit;
|
||||
struct gpio_bank *bank;
|
||||
int unmasked = 0;
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
struct irq_chip *irqchip = irq_desc_get_chip(desc);
|
||||
struct gpio_chip *chip = irq_get_handler_data(irq);
|
||||
|
||||
chained_irq_enter(chip, desc);
|
||||
chained_irq_enter(irqchip, desc);
|
||||
|
||||
bank = irq_get_handler_data(irq);
|
||||
bank = container_of(chip, struct gpio_bank, chip);
|
||||
isr_reg = bank->base + bank->regs->irqstatus;
|
||||
pm_runtime_get_sync(bank->dev);
|
||||
|
||||
|
@ -764,7 +755,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
|
|||
configured, we could unmask GPIO bank interrupt immediately */
|
||||
if (!level_mask && !unmasked) {
|
||||
unmasked = 1;
|
||||
chained_irq_exit(chip, desc);
|
||||
chained_irq_exit(irqchip, desc);
|
||||
}
|
||||
|
||||
if (!isr)
|
||||
|
@ -772,7 +763,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
|
|||
|
||||
while (isr) {
|
||||
bit = __ffs(isr);
|
||||
isr &= ~(1 << bit);
|
||||
isr &= ~(BIT(bit));
|
||||
|
||||
/*
|
||||
* Some chips can't respond to both rising and falling
|
||||
|
@ -781,10 +772,11 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
|
|||
* to respond to the IRQ for the opposite direction.
|
||||
* This will be indicated in the bank toggle_mask.
|
||||
*/
|
||||
if (bank->toggle_mask & (1 << bit))
|
||||
if (bank->toggle_mask & (BIT(bit)))
|
||||
_toggle_gpio_edge_triggering(bank, bit);
|
||||
|
||||
generic_handle_irq(irq_find_mapping(bank->domain, bit));
|
||||
generic_handle_irq(irq_find_mapping(bank->chip.irqdomain,
|
||||
bit));
|
||||
}
|
||||
}
|
||||
/* if bank has any level sensitive GPIO pin interrupt
|
||||
|
@ -793,20 +785,20 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
|
|||
interrupt */
|
||||
exit:
|
||||
if (!unmasked)
|
||||
chained_irq_exit(chip, desc);
|
||||
chained_irq_exit(irqchip, desc);
|
||||
pm_runtime_put(bank->dev);
|
||||
}
|
||||
|
||||
static void gpio_irq_shutdown(struct irq_data *d)
|
||||
{
|
||||
struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
|
||||
struct gpio_bank *bank = _irq_data_get_bank(d);
|
||||
unsigned int gpio = irq_to_gpio(bank, d->hwirq);
|
||||
unsigned long flags;
|
||||
unsigned offset = GPIO_INDEX(bank, gpio);
|
||||
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
gpio_unlock_as_irq(&bank->chip, offset);
|
||||
bank->irq_usage &= ~(1 << offset);
|
||||
bank->irq_usage &= ~(BIT(offset));
|
||||
_disable_gpio_module(bank, offset);
|
||||
_reset_gpio(bank, gpio);
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
|
@ -821,7 +813,7 @@ static void gpio_irq_shutdown(struct irq_data *d)
|
|||
|
||||
static void gpio_ack_irq(struct irq_data *d)
|
||||
{
|
||||
struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
|
||||
struct gpio_bank *bank = _irq_data_get_bank(d);
|
||||
unsigned int gpio = irq_to_gpio(bank, d->hwirq);
|
||||
|
||||
_clear_gpio_irqstatus(bank, gpio);
|
||||
|
@ -829,7 +821,7 @@ static void gpio_ack_irq(struct irq_data *d)
|
|||
|
||||
static void gpio_mask_irq(struct irq_data *d)
|
||||
{
|
||||
struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
|
||||
struct gpio_bank *bank = _irq_data_get_bank(d);
|
||||
unsigned int gpio = irq_to_gpio(bank, d->hwirq);
|
||||
unsigned long flags;
|
||||
|
||||
|
@ -841,7 +833,7 @@ static void gpio_mask_irq(struct irq_data *d)
|
|||
|
||||
static void gpio_unmask_irq(struct irq_data *d)
|
||||
{
|
||||
struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
|
||||
struct gpio_bank *bank = _irq_data_get_bank(d);
|
||||
unsigned int gpio = irq_to_gpio(bank, d->hwirq);
|
||||
unsigned int irq_mask = GPIO_BIT(bank, gpio);
|
||||
u32 trigger = irqd_get_trigger_type(d);
|
||||
|
@ -936,6 +928,21 @@ static inline void mpuio_init(struct gpio_bank *bank)
|
|||
|
||||
/*---------------------------------------------------------------------*/
|
||||
|
||||
static int gpio_get_direction(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct gpio_bank *bank;
|
||||
unsigned long flags;
|
||||
void __iomem *reg;
|
||||
int dir;
|
||||
|
||||
bank = container_of(chip, struct gpio_bank, chip);
|
||||
reg = bank->base + bank->regs->direction;
|
||||
spin_lock_irqsave(&bank->lock, flags);
|
||||
dir = !!(readl_relaxed(reg) & BIT(offset));
|
||||
spin_unlock_irqrestore(&bank->lock, flags);
|
||||
return dir;
|
||||
}
|
||||
|
||||
static int gpio_input(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct gpio_bank *bank;
|
||||
|
@ -954,7 +961,7 @@ static int gpio_get(struct gpio_chip *chip, unsigned offset)
|
|||
u32 mask;
|
||||
|
||||
bank = container_of(chip, struct gpio_bank, chip);
|
||||
mask = (1 << offset);
|
||||
mask = (BIT(offset));
|
||||
|
||||
if (gpio_is_input(bank, mask))
|
||||
return _get_gpio_datain(bank, offset);
|
||||
|
@ -1081,10 +1088,12 @@ omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start,
|
|||
IRQ_NOREQUEST | IRQ_NOPROBE, 0);
|
||||
}
|
||||
|
||||
static void omap_gpio_chip_init(struct gpio_bank *bank)
|
||||
static int omap_gpio_chip_init(struct gpio_bank *bank)
|
||||
{
|
||||
int j;
|
||||
static int gpio;
|
||||
int irq_base = 0;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* REVISIT eventually switch from OMAP-specific gpio structs
|
||||
|
@ -1092,12 +1101,12 @@ static void omap_gpio_chip_init(struct gpio_bank *bank)
|
|||
*/
|
||||
bank->chip.request = omap_gpio_request;
|
||||
bank->chip.free = omap_gpio_free;
|
||||
bank->chip.get_direction = gpio_get_direction;
|
||||
bank->chip.direction_input = gpio_input;
|
||||
bank->chip.get = gpio_get;
|
||||
bank->chip.direction_output = gpio_output;
|
||||
bank->chip.set_debounce = gpio_debounce;
|
||||
bank->chip.set = gpio_set;
|
||||
bank->chip.to_irq = omap_gpio_to_irq;
|
||||
if (bank->is_mpuio) {
|
||||
bank->chip.label = "mpuio";
|
||||
if (bank->regs->wkup_en)
|
||||
|
@ -1110,22 +1119,48 @@ static void omap_gpio_chip_init(struct gpio_bank *bank)
|
|||
}
|
||||
bank->chip.ngpio = bank->width;
|
||||
|
||||
gpiochip_add(&bank->chip);
|
||||
ret = gpiochip_add(&bank->chip);
|
||||
if (ret) {
|
||||
dev_err(bank->dev, "Could not register gpio chip %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARCH_OMAP1
|
||||
/*
|
||||
* REVISIT: Once we have OMAP1 supporting SPARSE_IRQ, we can drop
|
||||
* irq_alloc_descs() since a base IRQ offset will no longer be needed.
|
||||
*/
|
||||
irq_base = irq_alloc_descs(-1, 0, bank->width, 0);
|
||||
if (irq_base < 0) {
|
||||
dev_err(bank->dev, "Couldn't allocate IRQ numbers\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = gpiochip_irqchip_add(&bank->chip, &gpio_irq_chip,
|
||||
irq_base, gpio_irq_handler,
|
||||
IRQ_TYPE_NONE);
|
||||
|
||||
if (ret) {
|
||||
dev_err(bank->dev, "Couldn't add irqchip to gpiochip %d\n", ret);
|
||||
ret = gpiochip_remove(&bank->chip);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
gpiochip_set_chained_irqchip(&bank->chip, &gpio_irq_chip,
|
||||
bank->irq, gpio_irq_handler);
|
||||
|
||||
for (j = 0; j < bank->width; j++) {
|
||||
int irq = irq_create_mapping(bank->domain, j);
|
||||
int irq = irq_find_mapping(bank->chip.irqdomain, j);
|
||||
irq_set_lockdep_class(irq, &gpio_lock_class);
|
||||
irq_set_chip_data(irq, bank);
|
||||
if (bank->is_mpuio) {
|
||||
omap_mpuio_alloc_gc(bank, irq, bank->width);
|
||||
} else {
|
||||
irq_set_chip_and_handler(irq, &gpio_irq_chip,
|
||||
handle_simple_irq);
|
||||
set_irq_flags(irq, IRQF_VALID);
|
||||
irq_set_chip_and_handler(irq, NULL, NULL);
|
||||
set_irq_flags(irq, 0);
|
||||
}
|
||||
}
|
||||
irq_set_chained_handler(bank->irq, gpio_irq_handler);
|
||||
irq_set_handler_data(bank->irq, bank);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id omap_gpio_match[];
|
||||
|
@ -1138,9 +1173,7 @@ static int omap_gpio_probe(struct platform_device *pdev)
|
|||
const struct omap_gpio_platform_data *pdata;
|
||||
struct resource *res;
|
||||
struct gpio_bank *bank;
|
||||
#ifdef CONFIG_ARCH_OMAP1
|
||||
int irq_base;
|
||||
#endif
|
||||
int ret;
|
||||
|
||||
match = of_match_device(of_match_ptr(omap_gpio_match), dev);
|
||||
|
||||
|
@ -1162,6 +1195,7 @@ static int omap_gpio_probe(struct platform_device *pdev)
|
|||
|
||||
bank->irq = res->start;
|
||||
bank->dev = dev;
|
||||
bank->chip.dev = dev;
|
||||
bank->dbck_flag = pdata->dbck_flag;
|
||||
bank->stride = pdata->bank_stride;
|
||||
bank->width = pdata->bank_width;
|
||||
|
@ -1182,29 +1216,6 @@ static int omap_gpio_probe(struct platform_device *pdev)
|
|||
pdata->get_context_loss_count;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARCH_OMAP1
|
||||
/*
|
||||
* REVISIT: Once we have OMAP1 supporting SPARSE_IRQ, we can drop
|
||||
* irq_alloc_descs() and irq_domain_add_legacy() and just use a
|
||||
* linear IRQ domain mapping for all OMAP platforms.
|
||||
*/
|
||||
irq_base = irq_alloc_descs(-1, 0, bank->width, 0);
|
||||
if (irq_base < 0) {
|
||||
dev_err(dev, "Couldn't allocate IRQ numbers\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
bank->domain = irq_domain_add_legacy(node, bank->width, irq_base,
|
||||
0, &irq_domain_simple_ops, NULL);
|
||||
#else
|
||||
bank->domain = irq_domain_add_linear(node, bank->width,
|
||||
&irq_domain_simple_ops, NULL);
|
||||
#endif
|
||||
if (!bank->domain) {
|
||||
dev_err(dev, "Couldn't register an IRQ domain\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (bank->regs->set_dataout && bank->regs->clr_dataout)
|
||||
bank->set_dataout = _set_gpio_dataout_reg;
|
||||
else
|
||||
|
@ -1216,7 +1227,7 @@ static int omap_gpio_probe(struct platform_device *pdev)
|
|||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
bank->base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(bank->base)) {
|
||||
irq_domain_remove(bank->domain);
|
||||
irq_domain_remove(bank->chip.irqdomain);
|
||||
return PTR_ERR(bank->base);
|
||||
}
|
||||
|
||||
|
@ -1230,7 +1241,11 @@ static int omap_gpio_probe(struct platform_device *pdev)
|
|||
mpuio_init(bank);
|
||||
|
||||
omap_gpio_mod_init(bank);
|
||||
omap_gpio_chip_init(bank);
|
||||
|
||||
ret = omap_gpio_chip_init(bank);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
omap_gpio_show_rev(bank);
|
||||
|
||||
pm_runtime_put(bank->dev);
|
||||
|
|
|
@ -148,7 +148,7 @@ static const struct palmas_device_data tps80036_dev_data = {
|
|||
.ngpio = 16,
|
||||
};
|
||||
|
||||
static struct of_device_id of_palmas_gpio_match[] = {
|
||||
static const struct of_device_id of_palmas_gpio_match[] = {
|
||||
{ .compatible = "ti,palmas-gpio", .data = &palmas_dev_data,},
|
||||
{ .compatible = "ti,tps65913-gpio", .data = &palmas_dev_data,},
|
||||
{ .compatible = "ti,tps65914-gpio", .data = &palmas_dev_data,},
|
||||
|
@ -173,10 +173,8 @@ static int palmas_gpio_probe(struct platform_device *pdev)
|
|||
|
||||
palmas_gpio = devm_kzalloc(&pdev->dev,
|
||||
sizeof(*palmas_gpio), GFP_KERNEL);
|
||||
if (!palmas_gpio) {
|
||||
dev_err(&pdev->dev, "Could not allocate palmas_gpio\n");
|
||||
if (!palmas_gpio)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
palmas_gpio->palmas = palmas;
|
||||
palmas_gpio->gpio_chip.owner = THIS_MODULE;
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/platform_data/pca953x.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -91,7 +89,6 @@ struct pca953x_chip {
|
|||
u8 irq_stat[MAX_BANK];
|
||||
u8 irq_trig_raise[MAX_BANK];
|
||||
u8 irq_trig_fall[MAX_BANK];
|
||||
struct irq_domain *domain;
|
||||
#endif
|
||||
|
||||
struct i2c_client *client;
|
||||
|
@ -100,6 +97,11 @@ struct pca953x_chip {
|
|||
int chip_type;
|
||||
};
|
||||
|
||||
static inline struct pca953x_chip *to_pca(struct gpio_chip *gc)
|
||||
{
|
||||
return container_of(gc, struct pca953x_chip, gpio_chip);
|
||||
}
|
||||
|
||||
static int pca953x_read_single(struct pca953x_chip *chip, int reg, u32 *val,
|
||||
int off)
|
||||
{
|
||||
|
@ -202,12 +204,10 @@ static int pca953x_read_regs(struct pca953x_chip *chip, int reg, u8 *val)
|
|||
|
||||
static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
|
||||
{
|
||||
struct pca953x_chip *chip;
|
||||
struct pca953x_chip *chip = to_pca(gc);
|
||||
u8 reg_val;
|
||||
int ret, offset = 0;
|
||||
|
||||
chip = container_of(gc, struct pca953x_chip, gpio_chip);
|
||||
|
||||
mutex_lock(&chip->i2c_lock);
|
||||
reg_val = chip->reg_direction[off / BANK_SZ] | (1u << (off % BANK_SZ));
|
||||
|
||||
|
@ -233,12 +233,10 @@ exit:
|
|||
static int pca953x_gpio_direction_output(struct gpio_chip *gc,
|
||||
unsigned off, int val)
|
||||
{
|
||||
struct pca953x_chip *chip;
|
||||
struct pca953x_chip *chip = to_pca(gc);
|
||||
u8 reg_val;
|
||||
int ret, offset = 0;
|
||||
|
||||
chip = container_of(gc, struct pca953x_chip, gpio_chip);
|
||||
|
||||
mutex_lock(&chip->i2c_lock);
|
||||
/* set output level */
|
||||
if (val)
|
||||
|
@ -285,12 +283,10 @@ exit:
|
|||
|
||||
static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
|
||||
{
|
||||
struct pca953x_chip *chip;
|
||||
struct pca953x_chip *chip = to_pca(gc);
|
||||
u32 reg_val;
|
||||
int ret, offset = 0;
|
||||
|
||||
chip = container_of(gc, struct pca953x_chip, gpio_chip);
|
||||
|
||||
mutex_lock(&chip->i2c_lock);
|
||||
switch (chip->chip_type) {
|
||||
case PCA953X_TYPE:
|
||||
|
@ -315,12 +311,10 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
|
|||
|
||||
static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
|
||||
{
|
||||
struct pca953x_chip *chip;
|
||||
struct pca953x_chip *chip = to_pca(gc);
|
||||
u8 reg_val;
|
||||
int ret, offset = 0;
|
||||
|
||||
chip = container_of(gc, struct pca953x_chip, gpio_chip);
|
||||
|
||||
mutex_lock(&chip->i2c_lock);
|
||||
if (val)
|
||||
reg_val = chip->reg_output[off / BANK_SZ]
|
||||
|
@ -367,38 +361,34 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_GPIO_PCA953X_IRQ
|
||||
static int pca953x_gpio_to_irq(struct gpio_chip *gc, unsigned off)
|
||||
{
|
||||
struct pca953x_chip *chip;
|
||||
|
||||
chip = container_of(gc, struct pca953x_chip, gpio_chip);
|
||||
return irq_create_mapping(chip->domain, off);
|
||||
}
|
||||
|
||||
static void pca953x_irq_mask(struct irq_data *d)
|
||||
{
|
||||
struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct pca953x_chip *chip = to_pca(gc);
|
||||
|
||||
chip->irq_mask[d->hwirq / BANK_SZ] &= ~(1 << (d->hwirq % BANK_SZ));
|
||||
}
|
||||
|
||||
static void pca953x_irq_unmask(struct irq_data *d)
|
||||
{
|
||||
struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct pca953x_chip *chip = to_pca(gc);
|
||||
|
||||
chip->irq_mask[d->hwirq / BANK_SZ] |= 1 << (d->hwirq % BANK_SZ);
|
||||
}
|
||||
|
||||
static void pca953x_irq_bus_lock(struct irq_data *d)
|
||||
{
|
||||
struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct pca953x_chip *chip = to_pca(gc);
|
||||
|
||||
mutex_lock(&chip->irq_lock);
|
||||
}
|
||||
|
||||
static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
|
||||
{
|
||||
struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct pca953x_chip *chip = to_pca(gc);
|
||||
u8 new_irqs;
|
||||
int level, i;
|
||||
|
||||
|
@ -420,7 +410,8 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
|
|||
|
||||
static int pca953x_irq_set_type(struct irq_data *d, unsigned int type)
|
||||
{
|
||||
struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct pca953x_chip *chip = to_pca(gc);
|
||||
int bank_nb = d->hwirq / BANK_SZ;
|
||||
u8 mask = 1 << (d->hwirq % BANK_SZ);
|
||||
|
||||
|
@ -503,44 +494,25 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid)
|
|||
struct pca953x_chip *chip = devid;
|
||||
u8 pending[MAX_BANK];
|
||||
u8 level;
|
||||
unsigned nhandled = 0;
|
||||
int i;
|
||||
|
||||
if (!pca953x_irq_pending(chip, pending))
|
||||
return IRQ_HANDLED;
|
||||
return IRQ_NONE;
|
||||
|
||||
for (i = 0; i < NBANK(chip); i++) {
|
||||
while (pending[i]) {
|
||||
level = __ffs(pending[i]);
|
||||
handle_nested_irq(irq_find_mapping(chip->domain,
|
||||
handle_nested_irq(irq_find_mapping(chip->gpio_chip.irqdomain,
|
||||
level + (BANK_SZ * i)));
|
||||
pending[i] &= ~(1 << level);
|
||||
nhandled++;
|
||||
}
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
return (nhandled > 0) ? IRQ_HANDLED : IRQ_NONE;
|
||||
}
|
||||
|
||||
static int pca953x_gpio_irq_map(struct irq_domain *d, unsigned int irq,
|
||||
irq_hw_number_t hwirq)
|
||||
{
|
||||
irq_clear_status_flags(irq, IRQ_NOREQUEST);
|
||||
irq_set_chip_data(irq, d->host_data);
|
||||
irq_set_chip(irq, &pca953x_irq_chip);
|
||||
irq_set_nested_thread(irq, true);
|
||||
#ifdef CONFIG_ARM
|
||||
set_irq_flags(irq, IRQF_VALID);
|
||||
#else
|
||||
irq_set_noprobe(irq);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct irq_domain_ops pca953x_irq_simple_ops = {
|
||||
.map = pca953x_gpio_irq_map,
|
||||
.xlate = irq_domain_xlate_twocell,
|
||||
};
|
||||
|
||||
static int pca953x_irq_setup(struct pca953x_chip *chip,
|
||||
const struct i2c_device_id *id,
|
||||
int irq_base)
|
||||
|
@ -572,19 +544,12 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
|
|||
chip->irq_stat[i] &= chip->reg_direction[i];
|
||||
mutex_init(&chip->irq_lock);
|
||||
|
||||
chip->domain = irq_domain_add_simple(client->dev.of_node,
|
||||
chip->gpio_chip.ngpio,
|
||||
irq_base,
|
||||
&pca953x_irq_simple_ops,
|
||||
chip);
|
||||
if (!chip->domain)
|
||||
return -ENODEV;
|
||||
|
||||
ret = devm_request_threaded_irq(&client->dev,
|
||||
client->irq,
|
||||
NULL,
|
||||
pca953x_irq_handler,
|
||||
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
|
||||
IRQF_TRIGGER_LOW | IRQF_ONESHOT |
|
||||
IRQF_SHARED,
|
||||
dev_name(&client->dev), chip);
|
||||
if (ret) {
|
||||
dev_err(&client->dev, "failed to request irq %d\n",
|
||||
|
@ -592,7 +557,16 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
|
|||
return ret;
|
||||
}
|
||||
|
||||
chip->gpio_chip.to_irq = pca953x_gpio_to_irq;
|
||||
ret = gpiochip_irqchip_add(&chip->gpio_chip,
|
||||
&pca953x_irq_chip,
|
||||
irq_base,
|
||||
handle_simple_irq,
|
||||
IRQ_TYPE_NONE);
|
||||
if (ret) {
|
||||
dev_err(&client->dev,
|
||||
"could not connect irqchip to gpiochip\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -756,11 +730,11 @@ static int pca953x_probe(struct i2c_client *client,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = pca953x_irq_setup(chip, id, irq_base);
|
||||
ret = gpiochip_add(&chip->gpio_chip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = gpiochip_add(&chip->gpio_chip);
|
||||
ret = pca953x_irq_setup(chip, id, irq_base);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -262,7 +262,7 @@ static int pcf857x_irq_domain_init(struct pcf857x *gpio,
|
|||
/* enable real irq */
|
||||
status = devm_request_threaded_irq(&client->dev, client->irq,
|
||||
NULL, pcf857x_irq, IRQF_ONESHOT |
|
||||
IRQF_TRIGGER_FALLING,
|
||||
IRQF_TRIGGER_FALLING | IRQF_SHARED,
|
||||
dev_name(&client->dev), gpio);
|
||||
|
||||
if (status)
|
||||
|
@ -319,7 +319,7 @@ static int pcf857x_probe(struct i2c_client *client,
|
|||
status = pcf857x_irq_domain_init(gpio, client);
|
||||
if (status < 0) {
|
||||
dev_err(&client->dev, "irq_domain init failed\n");
|
||||
goto fail;
|
||||
goto fail_irq_domain;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -414,12 +414,13 @@ static int pcf857x_probe(struct i2c_client *client,
|
|||
return 0;
|
||||
|
||||
fail:
|
||||
dev_dbg(&client->dev, "probe error %d for '%s'\n",
|
||||
status, client->name);
|
||||
|
||||
if (client->irq)
|
||||
pcf857x_irq_domain_cleanup(gpio);
|
||||
|
||||
fail_irq_domain:
|
||||
dev_dbg(&client->dev, "probe error %d for '%s'\n",
|
||||
status, client->name);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <linux/gpio.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define PCH_EDGE_FALLING 0
|
||||
#define PCH_EDGE_RISING BIT(0)
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include <linux/irq.h>
|
||||
#include <linux/irqchip/chained_irq.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/amba/bus.h>
|
||||
|
@ -88,7 +87,7 @@ static int pl061_direction_input(struct gpio_chip *gc, unsigned offset)
|
|||
|
||||
spin_lock_irqsave(&chip->lock, flags);
|
||||
gpiodir = readb(chip->base + GPIODIR);
|
||||
gpiodir &= ~(1 << offset);
|
||||
gpiodir &= ~(BIT(offset));
|
||||
writeb(gpiodir, chip->base + GPIODIR);
|
||||
spin_unlock_irqrestore(&chip->lock, flags);
|
||||
|
||||
|
@ -106,16 +105,16 @@ static int pl061_direction_output(struct gpio_chip *gc, unsigned offset,
|
|||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&chip->lock, flags);
|
||||
writeb(!!value << offset, chip->base + (1 << (offset + 2)));
|
||||
writeb(!!value << offset, chip->base + (BIT(offset + 2)));
|
||||
gpiodir = readb(chip->base + GPIODIR);
|
||||
gpiodir |= 1 << offset;
|
||||
gpiodir |= BIT(offset);
|
||||
writeb(gpiodir, chip->base + GPIODIR);
|
||||
|
||||
/*
|
||||
* gpio value is set again, because pl061 doesn't allow to set value of
|
||||
* a gpio pin before configuring it in OUT mode.
|
||||
*/
|
||||
writeb(!!value << offset, chip->base + (1 << (offset + 2)));
|
||||
writeb(!!value << offset, chip->base + (BIT(offset + 2)));
|
||||
spin_unlock_irqrestore(&chip->lock, flags);
|
||||
|
||||
return 0;
|
||||
|
@ -125,14 +124,14 @@ static int pl061_get_value(struct gpio_chip *gc, unsigned offset)
|
|||
{
|
||||
struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
|
||||
|
||||
return !!readb(chip->base + (1 << (offset + 2)));
|
||||
return !!readb(chip->base + (BIT(offset + 2)));
|
||||
}
|
||||
|
||||
static void pl061_set_value(struct gpio_chip *gc, unsigned offset, int value)
|
||||
{
|
||||
struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
|
||||
|
||||
writeb(!!value << offset, chip->base + (1 << (offset + 2)));
|
||||
writeb(!!value << offset, chip->base + (BIT(offset + 2)));
|
||||
}
|
||||
|
||||
static int pl061_irq_type(struct irq_data *d, unsigned trigger)
|
||||
|
@ -207,7 +206,7 @@ static void pl061_irq_mask(struct irq_data *d)
|
|||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
|
||||
u8 mask = 1 << (irqd_to_hwirq(d) % PL061_GPIO_NR);
|
||||
u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR);
|
||||
u8 gpioie;
|
||||
|
||||
spin_lock(&chip->lock);
|
||||
|
@ -220,7 +219,7 @@ static void pl061_irq_unmask(struct irq_data *d)
|
|||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
|
||||
u8 mask = 1 << (irqd_to_hwirq(d) % PL061_GPIO_NR);
|
||||
u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR);
|
||||
u8 gpioie;
|
||||
|
||||
spin_lock(&chip->lock);
|
||||
|
@ -302,9 +301,9 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
|
||||
for (i = 0; i < PL061_GPIO_NR; i++) {
|
||||
if (pdata) {
|
||||
if (pdata->directions & (1 << i))
|
||||
if (pdata->directions & (BIT(i)))
|
||||
pl061_direction_output(&chip->gc, i,
|
||||
pdata->values & (1 << i));
|
||||
pdata->values & (BIT(i)));
|
||||
else
|
||||
pl061_direction_input(&chip->gc, i);
|
||||
}
|
||||
|
@ -331,7 +330,7 @@ static int pl061_suspend(struct device *dev)
|
|||
chip->csave_regs.gpio_ie = readb(chip->base + GPIOIE);
|
||||
|
||||
for (offset = 0; offset < PL061_GPIO_NR; offset++) {
|
||||
if (chip->csave_regs.gpio_dir & (1 << offset))
|
||||
if (chip->csave_regs.gpio_dir & (BIT(offset)))
|
||||
chip->csave_regs.gpio_data |=
|
||||
pl061_get_value(&chip->gc, offset) << offset;
|
||||
}
|
||||
|
@ -345,10 +344,10 @@ static int pl061_resume(struct device *dev)
|
|||
int offset;
|
||||
|
||||
for (offset = 0; offset < PL061_GPIO_NR; offset++) {
|
||||
if (chip->csave_regs.gpio_dir & (1 << offset))
|
||||
if (chip->csave_regs.gpio_dir & (BIT(offset)))
|
||||
pl061_direction_output(&chip->gc, offset,
|
||||
chip->csave_regs.gpio_data &
|
||||
(1 << offset));
|
||||
(BIT(offset)));
|
||||
else
|
||||
pl061_direction_input(&chip->gc, offset);
|
||||
}
|
||||
|
|
|
@ -119,10 +119,8 @@ static int rc5t583_gpio_probe(struct platform_device *pdev)
|
|||
|
||||
rc5t583_gpio = devm_kzalloc(&pdev->dev, sizeof(*rc5t583_gpio),
|
||||
GFP_KERNEL);
|
||||
if (!rc5t583_gpio) {
|
||||
dev_warn(&pdev->dev, "Mem allocation for rc5t583_gpio failed");
|
||||
if (!rc5t583_gpio)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
rc5t583_gpio->gpio_chip.label = "gpio-rc5t583",
|
||||
rc5t583_gpio->gpio_chip.owner = THIS_MODULE,
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/platform_data/gpio-rcar.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
|
@ -362,7 +363,6 @@ static int gpio_rcar_probe(struct platform_device *pdev)
|
|||
|
||||
p = devm_kzalloc(dev, sizeof(*p), GFP_KERNEL);
|
||||
if (!p) {
|
||||
dev_err(dev, "failed to allocate driver data\n");
|
||||
ret = -ENOMEM;
|
||||
goto err0;
|
||||
}
|
||||
|
@ -377,6 +377,9 @@ static int gpio_rcar_probe(struct platform_device *pdev)
|
|||
|
||||
platform_set_drvdata(pdev, p);
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
|
||||
|
@ -460,6 +463,8 @@ static int gpio_rcar_probe(struct platform_device *pdev)
|
|||
err1:
|
||||
irq_domain_remove(p->irq_domain);
|
||||
err0:
|
||||
pm_runtime_put(dev);
|
||||
pm_runtime_disable(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -473,6 +478,8 @@ static int gpio_rcar_remove(struct platform_device *pdev)
|
|||
return ret;
|
||||
|
||||
irq_domain_remove(p->irq_domain);
|
||||
pm_runtime_put(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -141,17 +141,15 @@ static int rdc321x_gpio_probe(struct platform_device *pdev)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
rdc321x_gpio_dev = kzalloc(sizeof(struct rdc321x_gpio), GFP_KERNEL);
|
||||
if (!rdc321x_gpio_dev) {
|
||||
dev_err(&pdev->dev, "failed to allocate private data\n");
|
||||
rdc321x_gpio_dev = devm_kzalloc(&pdev->dev, sizeof(struct rdc321x_gpio),
|
||||
GFP_KERNEL);
|
||||
if (!rdc321x_gpio_dev)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
r = platform_get_resource_byname(pdev, IORESOURCE_IO, "gpio-reg1");
|
||||
if (!r) {
|
||||
dev_err(&pdev->dev, "failed to get gpio-reg1 resource\n");
|
||||
err = -ENODEV;
|
||||
goto out_free;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
spin_lock_init(&rdc321x_gpio_dev->lock);
|
||||
|
@ -162,8 +160,7 @@ static int rdc321x_gpio_probe(struct platform_device *pdev)
|
|||
r = platform_get_resource_byname(pdev, IORESOURCE_IO, "gpio-reg2");
|
||||
if (!r) {
|
||||
dev_err(&pdev->dev, "failed to get gpio-reg2 resource\n");
|
||||
err = -ENODEV;
|
||||
goto out_free;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
rdc321x_gpio_dev->reg2_ctrl_base = r->start;
|
||||
|
@ -187,21 +184,17 @@ static int rdc321x_gpio_probe(struct platform_device *pdev)
|
|||
rdc321x_gpio_dev->reg1_data_base,
|
||||
&rdc321x_gpio_dev->data_reg[0]);
|
||||
if (err)
|
||||
goto out_free;
|
||||
return err;
|
||||
|
||||
err = pci_read_config_dword(rdc321x_gpio_dev->sb_pdev,
|
||||
rdc321x_gpio_dev->reg2_data_base,
|
||||
&rdc321x_gpio_dev->data_reg[1]);
|
||||
if (err)
|
||||
goto out_free;
|
||||
return err;
|
||||
|
||||
dev_info(&pdev->dev, "registering %d GPIOs\n",
|
||||
rdc321x_gpio_dev->chip.ngpio);
|
||||
return gpiochip_add(&rdc321x_gpio_dev->chip);
|
||||
|
||||
out_free:
|
||||
kfree(rdc321x_gpio_dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int rdc321x_gpio_remove(struct platform_device *pdev)
|
||||
|
@ -213,8 +206,6 @@ static int rdc321x_gpio_remove(struct platform_device *pdev)
|
|||
if (ret)
|
||||
dev_err(&pdev->dev, "failed to unregister chip\n");
|
||||
|
||||
kfree(rdc321x_gpio_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -97,8 +97,6 @@ static int sch_gpio_core_direction_out(struct gpio_chip *gc,
|
|||
u8 curr_dirs;
|
||||
unsigned short offset, bit;
|
||||
|
||||
sch_gpio_core_set(gc, gpio_num, val);
|
||||
|
||||
spin_lock(&gpio_lock);
|
||||
|
||||
offset = CGIO + gpio_num / 8;
|
||||
|
@ -109,6 +107,17 @@ static int sch_gpio_core_direction_out(struct gpio_chip *gc,
|
|||
outb(curr_dirs & ~(1 << bit), gpio_ba + offset);
|
||||
|
||||
spin_unlock(&gpio_lock);
|
||||
|
||||
/*
|
||||
* according to the datasheet, writing to the level register has no
|
||||
* effect when GPIO is programmed as input.
|
||||
* Actually the the level register is read-only when configured as input.
|
||||
* Thus presetting the output level before switching to output is _NOT_ possible.
|
||||
* Hence we set the level after configuring the GPIO as output.
|
||||
* But we cannot prevent a short low pulse if direction is set to high
|
||||
* and an external pull-up is connected.
|
||||
*/
|
||||
sch_gpio_core_set(gc, gpio_num, val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -178,8 +187,6 @@ static int sch_gpio_resume_direction_out(struct gpio_chip *gc,
|
|||
u8 curr_dirs;
|
||||
unsigned short offset, bit;
|
||||
|
||||
sch_gpio_resume_set(gc, gpio_num, val);
|
||||
|
||||
offset = RGIO + gpio_num / 8;
|
||||
bit = gpio_num % 8;
|
||||
|
||||
|
@ -190,6 +197,17 @@ static int sch_gpio_resume_direction_out(struct gpio_chip *gc,
|
|||
outb(curr_dirs & ~(1 << bit), gpio_ba + offset);
|
||||
|
||||
spin_unlock(&gpio_lock);
|
||||
|
||||
/*
|
||||
* according to the datasheet, writing to the level register has no
|
||||
* effect when GPIO is programmed as input.
|
||||
* Actually the the level register is read-only when configured as input.
|
||||
* Thus presetting the output level before switching to output is _NOT_ possible.
|
||||
* Hence we set the level after configuring the GPIO as output.
|
||||
* But we cannot prevent a short low pulse if direction is set to high
|
||||
* and an external pull-up is connected.
|
||||
*/
|
||||
sch_gpio_resume_set(gc, gpio_num, val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -327,14 +327,22 @@ static int __init sch311x_detect(int sio_config_port, unsigned short *addr)
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
/* Check device ID. We currently know about:
|
||||
* SCH3112 (0x7c), SCH3114 (0x7d), and SCH3116 (0x7f). */
|
||||
/* Check device ID. */
|
||||
reg = sch311x_sio_inb(sio_config_port, 0x20);
|
||||
if (!(reg == 0x7c || reg == 0x7d || reg == 0x7f)) {
|
||||
switch (reg) {
|
||||
case 0x7c: /* SCH3112 */
|
||||
dev_id = 2;
|
||||
break;
|
||||
case 0x7d: /* SCH3114 */
|
||||
dev_id = 4;
|
||||
break;
|
||||
case 0x7f: /* SCH3116 */
|
||||
dev_id = 6;
|
||||
break;
|
||||
default:
|
||||
err = -ENODEV;
|
||||
goto exit;
|
||||
}
|
||||
dev_id = reg == 0x7c ? 2 : reg == 0x7d ? 4 : 6;
|
||||
|
||||
/* Select logical device A (runtime registers) */
|
||||
sch311x_sio_outb(sio_config_port, 0x07, 0x0a);
|
||||
|
|
|
@ -129,10 +129,8 @@ static int spics_gpio_probe(struct platform_device *pdev)
|
|||
int ret;
|
||||
|
||||
spics = devm_kzalloc(&pdev->dev, sizeof(*spics), GFP_KERNEL);
|
||||
if (!spics) {
|
||||
dev_err(&pdev->dev, "memory allocation fail\n");
|
||||
if (!spics)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
spics->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/i2c/sx150x.h>
|
||||
|
||||
#define NO_UPDATE_PENDING -1
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mfd/tc3589x.h>
|
||||
|
||||
|
@ -31,10 +29,6 @@ struct tc3589x_gpio {
|
|||
struct tc3589x *tc3589x;
|
||||
struct device *dev;
|
||||
struct mutex irq_lock;
|
||||
struct irq_domain *domain;
|
||||
|
||||
int irq_base;
|
||||
|
||||
/* Caches of interrupt control registers for bus_lock */
|
||||
u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS];
|
||||
u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS];
|
||||
|
@ -95,30 +89,6 @@ static int tc3589x_gpio_direction_input(struct gpio_chip *chip,
|
|||
return tc3589x_set_bits(tc3589x, reg, 1 << pos, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* tc3589x_gpio_irq_get_irq(): Map a hardware IRQ on a chip to a Linux IRQ
|
||||
*
|
||||
* @tc3589x_gpio: tc3589x_gpio_irq controller to operate on.
|
||||
* @irq: index of the hardware interrupt requested in the chip IRQs
|
||||
*
|
||||
* Useful for drivers to request their own IRQs.
|
||||
*/
|
||||
static int tc3589x_gpio_irq_get_irq(struct tc3589x_gpio *tc3589x_gpio,
|
||||
int hwirq)
|
||||
{
|
||||
if (!tc3589x_gpio)
|
||||
return -EINVAL;
|
||||
|
||||
return irq_create_mapping(tc3589x_gpio->domain, hwirq);
|
||||
}
|
||||
|
||||
static int tc3589x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
|
||||
|
||||
return tc3589x_gpio_irq_get_irq(tc3589x_gpio, offset);
|
||||
}
|
||||
|
||||
static struct gpio_chip template_chip = {
|
||||
.label = "tc3589x",
|
||||
.owner = THIS_MODULE,
|
||||
|
@ -126,13 +96,13 @@ static struct gpio_chip template_chip = {
|
|||
.get = tc3589x_gpio_get,
|
||||
.direction_output = tc3589x_gpio_direction_output,
|
||||
.set = tc3589x_gpio_set,
|
||||
.to_irq = tc3589x_gpio_to_irq,
|
||||
.can_sleep = true,
|
||||
};
|
||||
|
||||
static int tc3589x_gpio_irq_set_type(struct irq_data *d, unsigned int type)
|
||||
{
|
||||
struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);
|
||||
int offset = d->hwirq;
|
||||
int regoffset = offset / 8;
|
||||
int mask = 1 << (offset % 8);
|
||||
|
@ -159,14 +129,16 @@ static int tc3589x_gpio_irq_set_type(struct irq_data *d, unsigned int type)
|
|||
|
||||
static void tc3589x_gpio_irq_lock(struct irq_data *d)
|
||||
{
|
||||
struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);
|
||||
|
||||
mutex_lock(&tc3589x_gpio->irq_lock);
|
||||
}
|
||||
|
||||
static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d)
|
||||
{
|
||||
struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);
|
||||
struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
|
||||
static const u8 regmap[] = {
|
||||
[REG_IBE] = TC3589x_GPIOIBE0,
|
||||
|
@ -194,7 +166,8 @@ static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d)
|
|||
|
||||
static void tc3589x_gpio_irq_mask(struct irq_data *d)
|
||||
{
|
||||
struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);
|
||||
int offset = d->hwirq;
|
||||
int regoffset = offset / 8;
|
||||
int mask = 1 << (offset % 8);
|
||||
|
@ -204,7 +177,8 @@ static void tc3589x_gpio_irq_mask(struct irq_data *d)
|
|||
|
||||
static void tc3589x_gpio_irq_unmask(struct irq_data *d)
|
||||
{
|
||||
struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct tc3589x_gpio *tc3589x_gpio = container_of(gc, struct tc3589x_gpio, chip);
|
||||
int offset = d->hwirq;
|
||||
int regoffset = offset / 8;
|
||||
int mask = 1 << (offset % 8);
|
||||
|
@ -242,7 +216,8 @@ static irqreturn_t tc3589x_gpio_irq(int irq, void *dev)
|
|||
while (stat) {
|
||||
int bit = __ffs(stat);
|
||||
int line = i * 8 + bit;
|
||||
int irq = tc3589x_gpio_irq_get_irq(tc3589x_gpio, line);
|
||||
int irq = irq_find_mapping(tc3589x_gpio->chip.irqdomain,
|
||||
line);
|
||||
|
||||
handle_nested_irq(irq);
|
||||
stat &= ~(1 << bit);
|
||||
|
@ -254,61 +229,6 @@ static irqreturn_t tc3589x_gpio_irq(int irq, void *dev)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int tc3589x_gpio_irq_map(struct irq_domain *d, unsigned int irq,
|
||||
irq_hw_number_t hwirq)
|
||||
{
|
||||
struct tc3589x *tc3589x_gpio = d->host_data;
|
||||
|
||||
irq_set_chip_data(irq, tc3589x_gpio);
|
||||
irq_set_chip_and_handler(irq, &tc3589x_gpio_irq_chip,
|
||||
handle_simple_irq);
|
||||
irq_set_nested_thread(irq, 1);
|
||||
#ifdef CONFIG_ARM
|
||||
set_irq_flags(irq, IRQF_VALID);
|
||||
#else
|
||||
irq_set_noprobe(irq);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tc3589x_gpio_irq_unmap(struct irq_domain *d, unsigned int irq)
|
||||
{
|
||||
#ifdef CONFIG_ARM
|
||||
set_irq_flags(irq, 0);
|
||||
#endif
|
||||
irq_set_chip_and_handler(irq, NULL, NULL);
|
||||
irq_set_chip_data(irq, NULL);
|
||||
}
|
||||
|
||||
static struct irq_domain_ops tc3589x_irq_ops = {
|
||||
.map = tc3589x_gpio_irq_map,
|
||||
.unmap = tc3589x_gpio_irq_unmap,
|
||||
.xlate = irq_domain_xlate_twocell,
|
||||
};
|
||||
|
||||
static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio,
|
||||
struct device_node *np)
|
||||
{
|
||||
int base = tc3589x_gpio->irq_base;
|
||||
|
||||
/*
|
||||
* If this results in a linear domain, irq_create_mapping() will
|
||||
* take care of allocating IRQ descriptors at runtime. When a base
|
||||
* is provided, the IRQ descriptors will be allocated when the
|
||||
* domain is instantiated.
|
||||
*/
|
||||
tc3589x_gpio->domain = irq_domain_add_simple(np,
|
||||
tc3589x_gpio->chip.ngpio, base, &tc3589x_irq_ops,
|
||||
tc3589x_gpio);
|
||||
if (!tc3589x_gpio->domain) {
|
||||
dev_err(tc3589x_gpio->dev, "Failed to create irqdomain\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tc3589x_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent);
|
||||
|
@ -329,7 +249,8 @@ static int tc3589x_gpio_probe(struct platform_device *pdev)
|
|||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
tc3589x_gpio = kzalloc(sizeof(struct tc3589x_gpio), GFP_KERNEL);
|
||||
tc3589x_gpio = devm_kzalloc(&pdev->dev, sizeof(struct tc3589x_gpio),
|
||||
GFP_KERNEL);
|
||||
if (!tc3589x_gpio)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -347,30 +268,36 @@ static int tc3589x_gpio_probe(struct platform_device *pdev)
|
|||
tc3589x_gpio->chip.of_node = np;
|
||||
#endif
|
||||
|
||||
tc3589x_gpio->irq_base = tc3589x->irq_base ?
|
||||
tc3589x->irq_base + TC3589x_INT_GPIO(0) : 0;
|
||||
|
||||
/* Bring the GPIO module out of reset */
|
||||
ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL,
|
||||
TC3589x_RSTCTRL_GPIRST, 0);
|
||||
if (ret < 0)
|
||||
goto out_free;
|
||||
return ret;
|
||||
|
||||
ret = tc3589x_gpio_irq_init(tc3589x_gpio, np);
|
||||
if (ret)
|
||||
goto out_free;
|
||||
|
||||
ret = request_threaded_irq(irq, NULL, tc3589x_gpio_irq, IRQF_ONESHOT,
|
||||
"tc3589x-gpio", tc3589x_gpio);
|
||||
ret = devm_request_threaded_irq(&pdev->dev,
|
||||
irq, NULL, tc3589x_gpio_irq,
|
||||
IRQF_ONESHOT, "tc3589x-gpio",
|
||||
tc3589x_gpio);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
|
||||
goto out_free;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = gpiochip_add(&tc3589x_gpio->chip);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret);
|
||||
goto out_freeirq;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = gpiochip_irqchip_add(&tc3589x_gpio->chip,
|
||||
&tc3589x_gpio_irq_chip,
|
||||
0,
|
||||
handle_simple_irq,
|
||||
IRQ_TYPE_NONE);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"could not connect irqchip to gpiochip\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (pdata && pdata->setup)
|
||||
|
@ -379,12 +306,6 @@ static int tc3589x_gpio_probe(struct platform_device *pdev)
|
|||
platform_set_drvdata(pdev, tc3589x_gpio);
|
||||
|
||||
return 0;
|
||||
|
||||
out_freeirq:
|
||||
free_irq(irq, tc3589x_gpio);
|
||||
out_free:
|
||||
kfree(tc3589x_gpio);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tc3589x_gpio_remove(struct platform_device *pdev)
|
||||
|
@ -392,7 +313,6 @@ static int tc3589x_gpio_remove(struct platform_device *pdev)
|
|||
struct tc3589x_gpio *tc3589x_gpio = platform_get_drvdata(pdev);
|
||||
struct tc3589x *tc3589x = tc3589x_gpio->tc3589x;
|
||||
struct tc3589x_gpio_platform_data *pdata = tc3589x->pdata->gpio;
|
||||
int irq = platform_get_irq(pdev, 0);
|
||||
int ret;
|
||||
|
||||
if (pdata && pdata->remove)
|
||||
|
@ -405,10 +325,6 @@ static int tc3589x_gpio_remove(struct platform_device *pdev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
free_irq(irq, tc3589x_gpio);
|
||||
|
||||
kfree(tc3589x_gpio);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -408,7 +408,7 @@ static struct tegra_gpio_soc_config tegra30_gpio_config = {
|
|||
.upper_offset = 0x80,
|
||||
};
|
||||
|
||||
static struct of_device_id tegra_gpio_of_match[] = {
|
||||
static const struct of_device_id tegra_gpio_of_match[] = {
|
||||
{ .compatible = "nvidia,tegra30-gpio", .data = &tegra30_gpio_config },
|
||||
{ .compatible = "nvidia,tegra20-gpio", .data = &tegra20_gpio_config },
|
||||
{ },
|
||||
|
@ -458,10 +458,8 @@ static int tegra_gpio_probe(struct platform_device *pdev)
|
|||
tegra_gpio_banks = devm_kzalloc(&pdev->dev,
|
||||
tegra_gpio_bank_count * sizeof(*tegra_gpio_banks),
|
||||
GFP_KERNEL);
|
||||
if (!tegra_gpio_banks) {
|
||||
dev_err(&pdev->dev, "Couldn't allocate bank structure\n");
|
||||
if (!tegra_gpio_banks)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
irq_domain = irq_domain_add_linear(pdev->dev.of_node,
|
||||
tegra_gpio_chip.ngpio,
|
||||
|
|
|
@ -224,6 +224,7 @@ static struct irq_chip timbgpio_irqchip = {
|
|||
static int timbgpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
int err, i;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct gpio_chip *gc;
|
||||
struct timbgpio *tgpio;
|
||||
struct resource *iomem;
|
||||
|
@ -231,35 +232,35 @@ static int timbgpio_probe(struct platform_device *pdev)
|
|||
int irq = platform_get_irq(pdev, 0);
|
||||
|
||||
if (!pdata || pdata->nr_pins > 32) {
|
||||
err = -EINVAL;
|
||||
goto err_mem;
|
||||
dev_err(dev, "Invalid platform data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!iomem) {
|
||||
err = -EINVAL;
|
||||
goto err_mem;
|
||||
dev_err(dev, "Unable to get resource\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tgpio = kzalloc(sizeof(*tgpio), GFP_KERNEL);
|
||||
tgpio = devm_kzalloc(dev, sizeof(struct timbgpio), GFP_KERNEL);
|
||||
if (!tgpio) {
|
||||
err = -EINVAL;
|
||||
goto err_mem;
|
||||
dev_err(dev, "Memory alloc failed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
tgpio->irq_base = pdata->irq_base;
|
||||
|
||||
spin_lock_init(&tgpio->lock);
|
||||
|
||||
if (!request_mem_region(iomem->start, resource_size(iomem),
|
||||
DRIVER_NAME)) {
|
||||
err = -EBUSY;
|
||||
goto err_request;
|
||||
if (!devm_request_mem_region(dev, iomem->start, resource_size(iomem),
|
||||
DRIVER_NAME)) {
|
||||
dev_err(dev, "Region already claimed\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
tgpio->membase = ioremap(iomem->start, resource_size(iomem));
|
||||
tgpio->membase = devm_ioremap(dev, iomem->start, resource_size(iomem));
|
||||
if (!tgpio->membase) {
|
||||
err = -ENOMEM;
|
||||
goto err_ioremap;
|
||||
dev_err(dev, "Cannot ioremap\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
gc = &tgpio->gpio;
|
||||
|
@ -279,7 +280,7 @@ static int timbgpio_probe(struct platform_device *pdev)
|
|||
|
||||
err = gpiochip_add(gc);
|
||||
if (err)
|
||||
goto err_chipadd;
|
||||
return err;
|
||||
|
||||
platform_set_drvdata(pdev, tgpio);
|
||||
|
||||
|
@ -302,17 +303,6 @@ static int timbgpio_probe(struct platform_device *pdev)
|
|||
irq_set_chained_handler(irq, timbgpio_irq);
|
||||
|
||||
return 0;
|
||||
|
||||
err_chipadd:
|
||||
iounmap(tgpio->membase);
|
||||
err_ioremap:
|
||||
release_mem_region(iomem->start, resource_size(iomem));
|
||||
err_request:
|
||||
kfree(tgpio);
|
||||
err_mem:
|
||||
printk(KERN_ERR DRIVER_NAME": Failed to register GPIOs: %d\n", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int timbgpio_remove(struct platform_device *pdev)
|
||||
|
@ -320,7 +310,6 @@ static int timbgpio_remove(struct platform_device *pdev)
|
|||
int err;
|
||||
struct timbgpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
|
||||
struct timbgpio *tgpio = platform_get_drvdata(pdev);
|
||||
struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
int irq = platform_get_irq(pdev, 0);
|
||||
|
||||
if (irq >= 0 && tgpio->irq_base > 0) {
|
||||
|
@ -338,10 +327,6 @@ static int timbgpio_remove(struct platform_device *pdev)
|
|||
if (err)
|
||||
printk(KERN_ERR DRIVER_NAME": failed to remove gpio_chip\n");
|
||||
|
||||
iounmap(tgpio->membase);
|
||||
release_mem_region(iomem->start, resource_size(iomem));
|
||||
kfree(tgpio);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -97,10 +97,8 @@ static int tps6586x_gpio_probe(struct platform_device *pdev)
|
|||
pdata = dev_get_platdata(pdev->dev.parent);
|
||||
tps6586x_gpio = devm_kzalloc(&pdev->dev,
|
||||
sizeof(*tps6586x_gpio), GFP_KERNEL);
|
||||
if (!tps6586x_gpio) {
|
||||
dev_err(&pdev->dev, "Could not allocate tps6586x_gpio\n");
|
||||
if (!tps6586x_gpio)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
tps6586x_gpio->parent = pdev->dev.parent;
|
||||
|
||||
|
|
|
@ -123,10 +123,8 @@ static int tps65910_gpio_probe(struct platform_device *pdev)
|
|||
|
||||
tps65910_gpio = devm_kzalloc(&pdev->dev,
|
||||
sizeof(*tps65910_gpio), GFP_KERNEL);
|
||||
if (!tps65910_gpio) {
|
||||
dev_err(&pdev->dev, "Could not allocate tps65910_gpio\n");
|
||||
if (!tps65910_gpio)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
tps65910_gpio->tps65910 = tps65910;
|
||||
|
||||
|
|
|
@ -289,7 +289,7 @@ static int xgpio_of_probe(struct device_node *np)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct of_device_id xgpio_of_match[] = {
|
||||
static const struct of_device_id xgpio_of_match[] = {
|
||||
{ .compatible = "xlnx,xps-gpio-1.00.a", },
|
||||
{ /* end of list */ },
|
||||
};
|
||||
|
|
|
@ -81,9 +81,15 @@ static inline void zevio_gpio_port_set(struct zevio_gpio *c, unsigned pin,
|
|||
static int zevio_gpio_get(struct gpio_chip *chip, unsigned pin)
|
||||
{
|
||||
struct zevio_gpio *controller = to_zevio_gpio(chip);
|
||||
u32 val, dir;
|
||||
|
||||
/* Only reading allowed, so no spinlock needed */
|
||||
u32 val = zevio_gpio_port_get(controller, pin, ZEVIO_GPIO_INPUT);
|
||||
spin_lock(&controller->lock);
|
||||
dir = zevio_gpio_port_get(controller, pin, ZEVIO_GPIO_DIRECTION);
|
||||
if (dir & BIT(ZEVIO_GPIO_BIT(pin)))
|
||||
val = zevio_gpio_port_get(controller, pin, ZEVIO_GPIO_INPUT);
|
||||
else
|
||||
val = zevio_gpio_port_get(controller, pin, ZEVIO_GPIO_OUTPUT);
|
||||
spin_unlock(&controller->lock);
|
||||
|
||||
return (val >> ZEVIO_GPIO_BIT(pin)) & 0x1;
|
||||
}
|
||||
|
@ -172,10 +178,8 @@ static int zevio_gpio_probe(struct platform_device *pdev)
|
|||
int status, i;
|
||||
|
||||
controller = devm_kzalloc(&pdev->dev, sizeof(*controller), GFP_KERNEL);
|
||||
if (!controller) {
|
||||
dev_err(&pdev->dev, "not enough free memory\n");
|
||||
if (!controller)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Copy our reference */
|
||||
controller->chip.gc = zevio_gpio_chip;
|
||||
|
@ -198,7 +202,7 @@ static int zevio_gpio_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct of_device_id zevio_gpio_of_match[] = {
|
||||
static const struct of_device_id zevio_gpio_of_match[] = {
|
||||
{ .compatible = "lsi,zevio-gpio", },
|
||||
{ },
|
||||
};
|
||||
|
@ -209,7 +213,7 @@ static struct platform_driver zevio_gpio_driver = {
|
|||
.driver = {
|
||||
.name = "gpio-zevio",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(zevio_gpio_of_match),
|
||||
.of_match_table = zevio_gpio_of_match,
|
||||
},
|
||||
.probe = zevio_gpio_probe,
|
||||
};
|
||||
|
|
|
@ -449,9 +449,10 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
|
|||
mutex_unlock(&achip->conn_lock);
|
||||
|
||||
if (function == ACPI_WRITE)
|
||||
gpiod_set_raw_value(desc, !!((1 << i) & *value));
|
||||
gpiod_set_raw_value_cansleep(desc,
|
||||
!!((1 << i) & *value));
|
||||
else
|
||||
*value |= (u64)gpiod_get_raw_value(desc) << i;
|
||||
*value |= (u64)gpiod_get_raw_value_cansleep(desc) << i;
|
||||
}
|
||||
|
||||
out:
|
||||
|
|
|
@ -48,7 +48,7 @@ static int of_gpiochip_find_and_xlate(struct gpio_chip *gc, void *data)
|
|||
if (ret < 0)
|
||||
return false;
|
||||
|
||||
gg_data->out_gpio = gpio_to_desc(ret + gc->base);
|
||||
gg_data->out_gpio = gpiochip_get_desc(gc, ret);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -96,6 +96,20 @@ struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
|
|||
}
|
||||
EXPORT_SYMBOL(of_get_named_gpiod_flags);
|
||||
|
||||
int of_get_named_gpio_flags(struct device_node *np, const char *list_name,
|
||||
int index, enum of_gpio_flags *flags)
|
||||
{
|
||||
struct gpio_desc *desc;
|
||||
|
||||
desc = of_get_named_gpiod_flags(np, list_name, index, flags);
|
||||
|
||||
if (IS_ERR(desc))
|
||||
return PTR_ERR(desc);
|
||||
else
|
||||
return desc_to_gpio(desc);
|
||||
}
|
||||
EXPORT_SYMBOL(of_get_named_gpio_flags);
|
||||
|
||||
/**
|
||||
* of_gpio_simple_xlate - translate gpio_spec to the GPIO number and flags
|
||||
* @gc: pointer to the gpio_chip structure
|
||||
|
|
|
@ -1363,6 +1363,11 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
|
|||
int parent_irq,
|
||||
irq_flow_handler_t parent_handler)
|
||||
{
|
||||
if (gpiochip->can_sleep) {
|
||||
chip_err(gpiochip, "you cannot have chained interrupts on a chip that may sleep\n");
|
||||
return;
|
||||
}
|
||||
|
||||
irq_set_chained_handler(parent_irq, parent_handler);
|
||||
/*
|
||||
* The parent irqchip is already using the chip_data for this
|
||||
|
@ -1372,6 +1377,12 @@ void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(gpiochip_set_chained_irqchip);
|
||||
|
||||
/*
|
||||
* This lock class tells lockdep that GPIO irqs are in a different
|
||||
* category than their parents, so it won't report false recursion.
|
||||
*/
|
||||
static struct lock_class_key gpiochip_irq_lock_class;
|
||||
|
||||
/**
|
||||
* gpiochip_irq_map() - maps an IRQ into a GPIO irqchip
|
||||
* @d: the irqdomain used by this irqchip
|
||||
|
@ -1388,22 +1399,35 @@ static int gpiochip_irq_map(struct irq_domain *d, unsigned int irq,
|
|||
struct gpio_chip *chip = d->host_data;
|
||||
|
||||
irq_set_chip_data(irq, chip);
|
||||
irq_set_lockdep_class(irq, &gpiochip_irq_lock_class);
|
||||
irq_set_chip_and_handler(irq, chip->irqchip, chip->irq_handler);
|
||||
/* Chips that can sleep need nested thread handlers */
|
||||
if (chip->can_sleep)
|
||||
irq_set_nested_thread(irq, 1);
|
||||
#ifdef CONFIG_ARM
|
||||
set_irq_flags(irq, IRQF_VALID);
|
||||
#else
|
||||
irq_set_noprobe(irq);
|
||||
#endif
|
||||
irq_set_irq_type(irq, chip->irq_default_type);
|
||||
/*
|
||||
* No set-up of the hardware will happen if IRQ_TYPE_NONE
|
||||
* is passed as default type.
|
||||
*/
|
||||
if (chip->irq_default_type != IRQ_TYPE_NONE)
|
||||
irq_set_irq_type(irq, chip->irq_default_type);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq)
|
||||
{
|
||||
struct gpio_chip *chip = d->host_data;
|
||||
|
||||
#ifdef CONFIG_ARM
|
||||
set_irq_flags(irq, 0);
|
||||
#endif
|
||||
if (chip->can_sleep)
|
||||
irq_set_nested_thread(irq, 0);
|
||||
irq_set_chip_and_handler(irq, NULL, NULL);
|
||||
irq_set_chip_data(irq, NULL);
|
||||
}
|
||||
|
@ -1471,7 +1495,8 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip)
|
|||
* @first_irq: if not dynamically assigned, the base (first) IRQ to
|
||||
* allocate gpiochip irqs from
|
||||
* @handler: the irq handler to use (often a predefined irq core function)
|
||||
* @type: the default type for IRQs on this irqchip
|
||||
* @type: the default type for IRQs on this irqchip, pass IRQ_TYPE_NONE
|
||||
* to have the core avoid setting up any default type in the hardware.
|
||||
*
|
||||
* This function closely associates a certain irqchip with a certain
|
||||
* gpiochip, providing an irq domain to translate the local IRQs to
|
||||
|
@ -2571,22 +2596,27 @@ void gpiod_add_lookup_table(struct gpiod_lookup_table *table)
|
|||
mutex_unlock(&gpio_lookup_lock);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
|
||||
unsigned int idx,
|
||||
enum gpio_lookup_flags *flags)
|
||||
{
|
||||
static const char *suffixes[] = { "gpios", "gpio" };
|
||||
char prop_name[32]; /* 32 is max size of property name */
|
||||
enum of_gpio_flags of_flags;
|
||||
struct gpio_desc *desc;
|
||||
unsigned int i;
|
||||
|
||||
if (con_id)
|
||||
snprintf(prop_name, 32, "%s-gpios", con_id);
|
||||
else
|
||||
snprintf(prop_name, 32, "gpios");
|
||||
for (i = 0; i < ARRAY_SIZE(suffixes); i++) {
|
||||
if (con_id)
|
||||
snprintf(prop_name, 32, "%s-%s", con_id, suffixes[i]);
|
||||
else
|
||||
snprintf(prop_name, 32, "%s", suffixes[i]);
|
||||
|
||||
desc = of_get_named_gpiod_flags(dev->of_node, prop_name, idx,
|
||||
&of_flags);
|
||||
desc = of_get_named_gpiod_flags(dev->of_node, prop_name, idx,
|
||||
&of_flags);
|
||||
if (!IS_ERR(desc))
|
||||
break;
|
||||
}
|
||||
|
||||
if (IS_ERR(desc))
|
||||
return desc;
|
||||
|
@ -2596,14 +2626,6 @@ static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
|
|||
|
||||
return desc;
|
||||
}
|
||||
#else
|
||||
static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
|
||||
unsigned int idx,
|
||||
enum gpio_lookup_flags *flags)
|
||||
{
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id,
|
||||
unsigned int idx,
|
||||
|
@ -2701,7 +2723,7 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id,
|
|||
}
|
||||
|
||||
/**
|
||||
* gpio_get - obtain a GPIO for a given GPIO function
|
||||
* gpiod_get - obtain a GPIO for a given GPIO function
|
||||
* @dev: GPIO consumer, can be NULL for system-global GPIOs
|
||||
* @con_id: function within the GPIO consumer
|
||||
*
|
||||
|
@ -2715,6 +2737,22 @@ struct gpio_desc *__must_check gpiod_get(struct device *dev, const char *con_id)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(gpiod_get);
|
||||
|
||||
/**
|
||||
* gpiod_get_optional - obtain an optional GPIO for a given GPIO function
|
||||
* @dev: GPIO consumer, can be NULL for system-global GPIOs
|
||||
* @con_id: function within the GPIO consumer
|
||||
*
|
||||
* This is equivalent to gpiod_get(), except that when no GPIO was assigned to
|
||||
* the requested function it will return NULL. This is convenient for drivers
|
||||
* that need to handle optional GPIOs.
|
||||
*/
|
||||
struct gpio_desc *__must_check gpiod_get_optional(struct device *dev,
|
||||
const char *con_id)
|
||||
{
|
||||
return gpiod_get_index_optional(dev, con_id, 0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gpiod_get_optional);
|
||||
|
||||
/**
|
||||
* gpiod_get_index - obtain a GPIO from a multi-index GPIO function
|
||||
* @dev: GPIO consumer, can be NULL for system-global GPIOs
|
||||
|
@ -2777,6 +2815,33 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(gpiod_get_index);
|
||||
|
||||
/**
|
||||
* gpiod_get_index_optional - obtain an optional GPIO from a multi-index GPIO
|
||||
* function
|
||||
* @dev: GPIO consumer, can be NULL for system-global GPIOs
|
||||
* @con_id: function within the GPIO consumer
|
||||
* @index: index of the GPIO to obtain in the consumer
|
||||
*
|
||||
* This is equivalent to gpiod_get_index(), except that when no GPIO with the
|
||||
* specified index was assigned to the requested function it will return NULL.
|
||||
* This is convenient for drivers that need to handle optional GPIOs.
|
||||
*/
|
||||
struct gpio_desc *__must_check gpiod_get_index_optional(struct device *dev,
|
||||
const char *con_id,
|
||||
unsigned int index)
|
||||
{
|
||||
struct gpio_desc *desc;
|
||||
|
||||
desc = gpiod_get_index(dev, con_id, index);
|
||||
if (IS_ERR(desc)) {
|
||||
if (PTR_ERR(desc) == -ENOENT)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return desc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gpiod_get_index_optional);
|
||||
|
||||
/**
|
||||
* gpiod_put - dispose of a GPIO descriptor
|
||||
* @desc: GPIO descriptor to dispose of
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
#include <linux/err.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
enum of_gpio_flags;
|
||||
|
||||
/**
|
||||
* struct acpi_gpio_info - ACPI GPIO specific information
|
||||
* @gpioint: if %true this GPIO is of type GpioInt otherwise type is GpioIo
|
||||
|
@ -46,4 +48,7 @@ acpi_get_gpiod_by_index(struct device *dev, int index,
|
|||
int gpiochip_request_own_desc(struct gpio_desc *desc, const char *label);
|
||||
void gpiochip_free_own_desc(struct gpio_desc *desc);
|
||||
|
||||
struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
|
||||
const char *list_name, int index, enum of_gpio_flags *flags);
|
||||
|
||||
#endif /* GPIOLIB_H */
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef __LINUX_GPIO_CONSUMER_H
|
||||
#define __LINUX_GPIO_CONSUMER_H
|
||||
|
||||
#include <linux/bug.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
|
@ -23,6 +24,12 @@ struct gpio_desc *__must_check gpiod_get(struct device *dev,
|
|||
struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
|
||||
const char *con_id,
|
||||
unsigned int idx);
|
||||
struct gpio_desc *__must_check gpiod_get_optional(struct device *dev,
|
||||
const char *con_id);
|
||||
struct gpio_desc *__must_check gpiod_get_index_optional(struct device *dev,
|
||||
const char *con_id,
|
||||
unsigned int index);
|
||||
|
||||
void gpiod_put(struct gpio_desc *desc);
|
||||
|
||||
struct gpio_desc *__must_check devm_gpiod_get(struct device *dev,
|
||||
|
@ -30,6 +37,12 @@ struct gpio_desc *__must_check devm_gpiod_get(struct device *dev,
|
|||
struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
|
||||
const char *con_id,
|
||||
unsigned int idx);
|
||||
struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev,
|
||||
const char *con_id);
|
||||
struct gpio_desc *__must_check
|
||||
devm_gpiod_get_index_optional(struct device *dev, const char *con_id,
|
||||
unsigned int index);
|
||||
|
||||
void devm_gpiod_put(struct device *dev, struct gpio_desc *desc);
|
||||
|
||||
int gpiod_get_direction(const struct gpio_desc *desc);
|
||||
|
@ -73,6 +86,20 @@ static inline struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
|
|||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
static inline struct gpio_desc *__must_check
|
||||
gpiod_get_optional(struct device *dev, const char *con_id)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
static inline struct gpio_desc *__must_check
|
||||
gpiod_get_index_optional(struct device *dev, const char *con_id,
|
||||
unsigned int index)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
static inline void gpiod_put(struct gpio_desc *desc)
|
||||
{
|
||||
might_sleep();
|
||||
|
@ -93,6 +120,20 @@ struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
|
|||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
static inline struct gpio_desc *__must_check
|
||||
devm_gpiod_get_optional(struct device *dev, const char *con_id)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
static inline struct gpio_desc *__must_check
|
||||
devm_gpiod_get_index_optional(struct device *dev, const char *con_id,
|
||||
unsigned int index)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
static inline void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
|
||||
{
|
||||
might_sleep();
|
||||
|
|
|
@ -51,7 +51,10 @@ struct seq_file;
|
|||
* format specifier for an unsigned int. It is substituted by the actual
|
||||
* number of the gpio.
|
||||
* @can_sleep: flag must be set iff get()/set() methods sleep, as they
|
||||
* must while accessing GPIO expander chips over I2C or SPI
|
||||
* must while accessing GPIO expander chips over I2C or SPI. This
|
||||
* implies that if the chip supports IRQs, these IRQs need to be threaded
|
||||
* as the chip access may sleep when e.g. reading out the IRQ status
|
||||
* registers.
|
||||
* @exported: flags if the gpiochip is exported for use from sysfs. Private.
|
||||
*
|
||||
* A gpio_chip can help platforms abstract various sources of GPIOs so
|
||||
|
|
|
@ -111,7 +111,6 @@ enum tx3589x_block {
|
|||
#define TC3589x_INT_PORIRQ 7
|
||||
|
||||
#define TC3589x_NR_INTERNAL_IRQS 8
|
||||
#define TC3589x_INT_GPIO(x) (TC3589x_NR_INTERNAL_IRQS + (x))
|
||||
|
||||
struct tc3589x {
|
||||
struct mutex lock;
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include <linux/errno.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
|
||||
struct device_node;
|
||||
|
||||
|
@ -48,7 +47,7 @@ static inline struct of_mm_gpio_chip *to_of_mm_gpio_chip(struct gpio_chip *gc)
|
|||
return container_of(gc, struct of_mm_gpio_chip, gc);
|
||||
}
|
||||
|
||||
extern struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
|
||||
extern int of_get_named_gpio_flags(struct device_node *np,
|
||||
const char *list_name, int index, enum of_gpio_flags *flags);
|
||||
|
||||
extern int of_mm_gpiochip_add(struct device_node *np,
|
||||
|
@ -63,10 +62,10 @@ extern int of_gpio_simple_xlate(struct gpio_chip *gc,
|
|||
#else /* CONFIG_OF_GPIO */
|
||||
|
||||
/* Drivers may not strictly depend on the GPIO support, so let them link. */
|
||||
static inline struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,
|
||||
static inline int of_get_named_gpio_flags(struct device_node *np,
|
||||
const char *list_name, int index, enum of_gpio_flags *flags)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int of_gpio_simple_xlate(struct gpio_chip *gc,
|
||||
|
@ -81,18 +80,6 @@ static inline void of_gpiochip_remove(struct gpio_chip *gc) { }
|
|||
|
||||
#endif /* CONFIG_OF_GPIO */
|
||||
|
||||
static inline int of_get_named_gpio_flags(struct device_node *np,
|
||||
const char *list_name, int index, enum of_gpio_flags *flags)
|
||||
{
|
||||
struct gpio_desc *desc;
|
||||
desc = of_get_named_gpiod_flags(np, list_name, index, flags);
|
||||
|
||||
if (IS_ERR(desc))
|
||||
return PTR_ERR(desc);
|
||||
else
|
||||
return desc_to_gpio(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* of_gpio_named_count() - Count GPIOs for a device
|
||||
* @np: device node to count GPIOs for
|
||||
|
@ -129,22 +116,6 @@ static inline int of_gpio_count(struct device_node *np)
|
|||
return of_gpio_named_count(np, "gpios");
|
||||
}
|
||||
|
||||
/**
|
||||
* of_get_gpiod_flags() - Get a GPIO descriptor and flags to use with GPIO API
|
||||
* @np: device node to get GPIO from
|
||||
* @index: index of the GPIO
|
||||
* @flags: a flags pointer to fill in
|
||||
*
|
||||
* Returns GPIO descriptor to use with Linux generic GPIO API, or a errno
|
||||
* value on the error condition. If @flags is not NULL the function also fills
|
||||
* in flags for the GPIO.
|
||||
*/
|
||||
static inline struct gpio_desc *of_get_gpiod_flags(struct device_node *np,
|
||||
int index, enum of_gpio_flags *flags)
|
||||
{
|
||||
return of_get_named_gpiod_flags(np, "gpios", index, flags);
|
||||
}
|
||||
|
||||
static inline int of_get_gpio_flags(struct device_node *np, int index,
|
||||
enum of_gpio_flags *flags)
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче