diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-09 14:58:15 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-09 14:58:15 -0400 |
commit | ea584595fc85e65796335033dfca25ed655cd0ed (patch) | |
tree | 79d444c507472f6c66d887ad332e7c1784eeb4de /drivers/gpio/gpiolib.c | |
parent | 782d59c5dfc5ac39ac8cfb4c6dd40597938dde9c (diff) | |
parent | a092e19b688be88f7329bd05f90cb92ebe1a4f5b (diff) |
Merge tag 'gpio-v3.18-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio
Pull GPIO changes from Linus Walleij:
"This is the bulk of GPIO changes for the v3.18 development cycle:
- Increase the default ARCH_NR_GPIO from 256 to 512. This was done
to avoid having a custom <asm/gpio.h> header for the x86
architecture - GPIO is custom and complicated enough as it is
already! We want to move to a radix to store the descriptors going
forward, and finally get rid of this fixed array size altogether.
- Endgame patching of the gpio_remove() semantics initiated by
Abdoulaye Berthe. It is not accepted by the system that the
removal of a GPIO chip fails during eg reboot or shutdown, and
therefore the return value has now painfully been refactored away.
For special cases like GPIO expanders on a hot-pluggable bus like
USB, we may later add some gpiochip_try_remove() call, but for the
cases we have now, return values are moot.
- Some incremental refactoring of the gpiolib core and ACPI GPIO
library for more descriptor usage.
- Refactor the chained IRQ handler set-up method to handle also
threaded, nested interrupts and set up the parent IRQ correctly.
Switch STMPE and TC3589x drivers to use this registration method.
- Add a .irq_not_threaded flag to the struct gpio_chip, so that also
GPIO expanders that block but are still not using threaded IRQ
handlers.
- New drivers for the ARM64 X-Gene SoC GPIO controller.
- The syscon GPIO driver has been improved to handle the "DSP GPIO"
found on the TI Keystone 2 SoC:s.
- ADNP driver switched to use gpiolib irqchip helpers.
- Refactor the DWAPB driver to support being instantiated from and
MFD cell (platform device).
- Incremental feature improvement in the Zynq, MCP23S08, DWAPB, OMAP,
Xilinx and Crystalcove drivers.
- Various minor fixes"
* tag 'gpio-v3.18-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (52 commits)
gpio: pch: Build context save/restore only for PM
pinctrl: abx500: get rid of unused variable
gpio: ks8695: fix 'else should follow close brace '}''
gpio: stmpe: add verbose debug code
gpio: stmpe: fix up interrupt enable logic
gpio: staticize xway_stp_init()
gpio: handle also nested irqchips in the chained handler set-up
gpio: set parent irq on chained handlers
gpiolib: irqchip: use irq_find_mapping while removing irqchip
gpio: crystalcove: support virtual GPIO
pinctrl: bcm281xx: make Kconfig dependency more strict
gpio: kona: enable only on BCM_MOBILE or for compile testing
gpio, bcm-kona, LLVMLinux: Remove use of __initconst
gpio: Fix ngpio in gpio-xilinx driver
gpio: dwapb: fix pointer to integer cast
gpio: xgene: Remove unneeded #ifdef CONFIG_OF guard
gpio: xgene: Remove unneeded forward declation for struct xgene_gpio
gpio: xgene: Fix missing spin_lock_init()
gpio: ks8695: fix switch case indentation
gpiolib: add irq_not_threaded flag to gpio_chip
...
Diffstat (limited to 'drivers/gpio/gpiolib.c')
-rw-r--r-- | drivers/gpio/gpiolib.c | 90 |
1 files changed, 54 insertions, 36 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index c68d037de656..e8e98ca25ec7 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
@@ -308,10 +308,9 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip); | |||
308 | * | 308 | * |
309 | * A gpio_chip with any GPIOs still requested may not be removed. | 309 | * A gpio_chip with any GPIOs still requested may not be removed. |
310 | */ | 310 | */ |
311 | int gpiochip_remove(struct gpio_chip *chip) | 311 | void gpiochip_remove(struct gpio_chip *chip) |
312 | { | 312 | { |
313 | unsigned long flags; | 313 | unsigned long flags; |
314 | int status = 0; | ||
315 | unsigned id; | 314 | unsigned id; |
316 | 315 | ||
317 | acpi_gpiochip_remove(chip); | 316 | acpi_gpiochip_remove(chip); |
@@ -323,24 +322,15 @@ int gpiochip_remove(struct gpio_chip *chip) | |||
323 | of_gpiochip_remove(chip); | 322 | of_gpiochip_remove(chip); |
324 | 323 | ||
325 | for (id = 0; id < chip->ngpio; id++) { | 324 | for (id = 0; id < chip->ngpio; id++) { |
326 | if (test_bit(FLAG_REQUESTED, &chip->desc[id].flags)) { | 325 | if (test_bit(FLAG_REQUESTED, &chip->desc[id].flags)) |
327 | status = -EBUSY; | 326 | dev_crit(chip->dev, "REMOVING GPIOCHIP WITH GPIOS STILL REQUESTED\n"); |
328 | break; | ||
329 | } | ||
330 | } | ||
331 | if (status == 0) { | ||
332 | for (id = 0; id < chip->ngpio; id++) | ||
333 | chip->desc[id].chip = NULL; | ||
334 | |||
335 | list_del(&chip->list); | ||
336 | } | 327 | } |
328 | for (id = 0; id < chip->ngpio; id++) | ||
329 | chip->desc[id].chip = NULL; | ||
337 | 330 | ||
331 | list_del(&chip->list); | ||
338 | spin_unlock_irqrestore(&gpio_lock, flags); | 332 | spin_unlock_irqrestore(&gpio_lock, flags); |
339 | 333 | gpiochip_unexport(chip); | |
340 | if (status == 0) | ||
341 | gpiochip_unexport(chip); | ||
342 | |||
343 | return status; | ||
344 | } | 334 | } |
345 | EXPORT_SYMBOL_GPL(gpiochip_remove); | 335 | EXPORT_SYMBOL_GPL(gpiochip_remove); |
346 | 336 | ||
@@ -395,30 +385,47 @@ static struct gpio_chip *find_chip_by_name(const char *name) | |||
395 | */ | 385 | */ |
396 | 386 | ||
397 | /** | 387 | /** |
398 | * gpiochip_add_chained_irqchip() - adds a chained irqchip to a gpiochip | 388 | * gpiochip_set_chained_irqchip() - sets a chained irqchip to a gpiochip |
399 | * @gpiochip: the gpiochip to add the irqchip to | 389 | * @gpiochip: the gpiochip to set the irqchip chain to |
400 | * @irqchip: the irqchip to add to the gpiochip | 390 | * @irqchip: the irqchip to chain to the gpiochip |
401 | * @parent_irq: the irq number corresponding to the parent IRQ for this | 391 | * @parent_irq: the irq number corresponding to the parent IRQ for this |
402 | * chained irqchip | 392 | * chained irqchip |
403 | * @parent_handler: the parent interrupt handler for the accumulated IRQ | 393 | * @parent_handler: the parent interrupt handler for the accumulated IRQ |
404 | * coming out of the gpiochip | 394 | * coming out of the gpiochip. If the interrupt is nested rather than |
395 | * cascaded, pass NULL in this handler argument | ||
405 | */ | 396 | */ |
406 | void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip, | 397 | void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip, |
407 | struct irq_chip *irqchip, | 398 | struct irq_chip *irqchip, |
408 | int parent_irq, | 399 | int parent_irq, |
409 | irq_flow_handler_t parent_handler) | 400 | irq_flow_handler_t parent_handler) |
410 | { | 401 | { |
411 | if (gpiochip->can_sleep) { | 402 | unsigned int offset; |
412 | chip_err(gpiochip, "you cannot have chained interrupts on a chip that may sleep\n"); | 403 | |
404 | if (!gpiochip->irqdomain) { | ||
405 | chip_err(gpiochip, "called %s before setting up irqchip\n", | ||
406 | __func__); | ||
413 | return; | 407 | return; |
414 | } | 408 | } |
415 | 409 | ||
416 | /* | 410 | if (parent_handler) { |
417 | * The parent irqchip is already using the chip_data for this | 411 | if (gpiochip->can_sleep) { |
418 | * irqchip, so our callbacks simply use the handler_data. | 412 | chip_err(gpiochip, |
419 | */ | 413 | "you cannot have chained interrupts on a " |
420 | irq_set_handler_data(parent_irq, gpiochip); | 414 | "chip that may sleep\n"); |
421 | irq_set_chained_handler(parent_irq, parent_handler); | 415 | return; |
416 | } | ||
417 | /* | ||
418 | * The parent irqchip is already using the chip_data for this | ||
419 | * irqchip, so our callbacks simply use the handler_data. | ||
420 | */ | ||
421 | irq_set_handler_data(parent_irq, gpiochip); | ||
422 | irq_set_chained_handler(parent_irq, parent_handler); | ||
423 | } | ||
424 | |||
425 | /* Set the parent IRQ for all affected IRQs */ | ||
426 | for (offset = 0; offset < gpiochip->ngpio; offset++) | ||
427 | irq_set_parent(irq_find_mapping(gpiochip->irqdomain, offset), | ||
428 | parent_irq); | ||
422 | } | 429 | } |
423 | EXPORT_SYMBOL_GPL(gpiochip_set_chained_irqchip); | 430 | EXPORT_SYMBOL_GPL(gpiochip_set_chained_irqchip); |
424 | 431 | ||
@@ -447,7 +454,7 @@ static int gpiochip_irq_map(struct irq_domain *d, unsigned int irq, | |||
447 | irq_set_lockdep_class(irq, &gpiochip_irq_lock_class); | 454 | irq_set_lockdep_class(irq, &gpiochip_irq_lock_class); |
448 | irq_set_chip_and_handler(irq, chip->irqchip, chip->irq_handler); | 455 | irq_set_chip_and_handler(irq, chip->irqchip, chip->irq_handler); |
449 | /* Chips that can sleep need nested thread handlers */ | 456 | /* Chips that can sleep need nested thread handlers */ |
450 | if (chip->can_sleep) | 457 | if (chip->can_sleep && !chip->irq_not_threaded) |
451 | irq_set_nested_thread(irq, 1); | 458 | irq_set_nested_thread(irq, 1); |
452 | #ifdef CONFIG_ARM | 459 | #ifdef CONFIG_ARM |
453 | set_irq_flags(irq, IRQF_VALID); | 460 | set_irq_flags(irq, IRQF_VALID); |
@@ -524,7 +531,8 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) | |||
524 | /* Remove all IRQ mappings and delete the domain */ | 531 | /* Remove all IRQ mappings and delete the domain */ |
525 | if (gpiochip->irqdomain) { | 532 | if (gpiochip->irqdomain) { |
526 | for (offset = 0; offset < gpiochip->ngpio; offset++) | 533 | for (offset = 0; offset < gpiochip->ngpio; offset++) |
527 | irq_dispose_mapping(gpiochip->irq_base + offset); | 534 | irq_dispose_mapping( |
535 | irq_find_mapping(gpiochip->irqdomain, offset)); | ||
528 | irq_domain_remove(gpiochip->irqdomain); | 536 | irq_domain_remove(gpiochip->irqdomain); |
529 | } | 537 | } |
530 | 538 | ||
@@ -895,12 +903,22 @@ EXPORT_SYMBOL_GPL(gpiochip_is_requested); | |||
895 | * allows the GPIO chip module to be unloaded as needed (we assume that the | 903 | * allows the GPIO chip module to be unloaded as needed (we assume that the |
896 | * GPIO chip driver handles freeing the GPIOs it has requested). | 904 | * GPIO chip driver handles freeing the GPIOs it has requested). |
897 | */ | 905 | */ |
898 | int gpiochip_request_own_desc(struct gpio_desc *desc, const char *label) | 906 | struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *chip, u16 hwnum, |
907 | const char *label) | ||
899 | { | 908 | { |
900 | if (!desc || !desc->chip) | 909 | struct gpio_desc *desc = gpiochip_get_desc(chip, hwnum); |
901 | return -EINVAL; | 910 | int err; |
902 | 911 | ||
903 | return __gpiod_request(desc, label); | 912 | if (IS_ERR(desc)) { |
913 | chip_err(chip, "failed to get GPIO descriptor\n"); | ||
914 | return desc; | ||
915 | } | ||
916 | |||
917 | err = __gpiod_request(desc, label); | ||
918 | if (err < 0) | ||
919 | return ERR_PTR(err); | ||
920 | |||
921 | return desc; | ||
904 | } | 922 | } |
905 | EXPORT_SYMBOL_GPL(gpiochip_request_own_desc); | 923 | EXPORT_SYMBOL_GPL(gpiochip_request_own_desc); |
906 | 924 | ||
@@ -1652,7 +1670,7 @@ struct gpio_desc *__must_check __gpiod_get_index(struct device *dev, | |||
1652 | * a result. In that case, use platform lookup as a fallback. | 1670 | * a result. In that case, use platform lookup as a fallback. |
1653 | */ | 1671 | */ |
1654 | if (!desc || desc == ERR_PTR(-ENOENT)) { | 1672 | if (!desc || desc == ERR_PTR(-ENOENT)) { |
1655 | dev_dbg(dev, "using lookup tables for GPIO lookup"); | 1673 | dev_dbg(dev, "using lookup tables for GPIO lookup\n"); |
1656 | desc = gpiod_find(dev, con_id, idx, &lookupflags); | 1674 | desc = gpiod_find(dev, con_id, idx, &lookupflags); |
1657 | } | 1675 | } |
1658 | 1676 | ||