diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-05 09:51:41 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-05 09:51:41 -0700 |
commit | 1b2951dd99af3970c1c1a8385a12b90236b837de (patch) | |
tree | f0263fd6e22c23078b38360ea7495b1dd2d212dc /drivers/gpio/gpiolib.c | |
parent | 06dd3dfeea60e2a6457a6aedf97afc8e6d2ba497 (diff) | |
parent | 348f3cde84ab5b1f53cd3c0eaac1ca99a4dcb148 (diff) | |
download | linux-1b2951dd99af3970c1c1a8385a12b90236b837de.tar.bz2 |
Merge tag 'gpio-v4.17-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio
Pull GPIO updates from Linus Walleij:
"This is the bulk of GPIO changes for the v4.17 kernel cycle:
New drivers:
- Nintendo Wii GameCube GPIO, known as "Hollywood"
- Raspberry Pi mailbox service GPIO expander
- Spreadtrum main SC9860 SoC and IEC GPIO controllers.
Improvements:
- Implemented .get_multiple() callback for most of the
high-performance industrial GPIO cards for the ISA bus.
- ISA GPIO drivers now select the ISA_BUS_API instead of depending on
it. This is merged with the same pattern for all the ISA drivers
and some other Kconfig cleanups related to this.
Cleanup:
- Delete the TZ1090 GPIO drivers following the deletion of this SoC
from the ARM tree.
- Move the documentation over to driver-api to conform with the rest
of the kernel documentation build.
- Continue to make the GPIO drivers include only
<linux/gpio/driver.h> and not the too broad <linux/gpio.h> that we
want to get rid of.
- Managed to remove VLA allocation from two drivers pending more
fixes in this area for the next merge window.
- Misc janitorial fixes"
* tag 'gpio-v4.17-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (77 commits)
gpio: Add Spreadtrum PMIC EIC driver support
gpio: Add Spreadtrum EIC driver support
dt-bindings: gpio: Add Spreadtrum EIC controller documentation
gpio: ath79: Fix potential NULL dereference in ath79_gpio_probe()
pinctrl: qcom: Don't allow protected pins to be requested
gpiolib: Support 'gpio-reserved-ranges' property
gpiolib: Change bitmap allocation to kmalloc_array
gpiolib: Extract mask allocation into subroutine
dt-bindings: gpio: Add a gpio-reserved-ranges property
gpio: mockup: fix a potential crash when creating debugfs entries
gpio: pca953x: add compatibility for pcal6524 and pcal9555a
gpio: dwapb: Add support for a bus clock
gpio: Remove VLA from xra1403 driver
gpio: Remove VLA from MAX3191X driver
gpio: ws16c48: Implement get_multiple callback
gpio: gpio-mm: Implement get_multiple callback
gpio: 104-idi-48: Implement get_multiple callback
gpio: 104-dio-48e: Implement get_multiple callback
gpio: pcie-idio-24: Implement get_multiple/set_multiple callbacks
gpio: pci-idio-16: Implement get_multiple callback
...
Diffstat (limited to 'drivers/gpio/gpiolib.c')
-rw-r--r-- | drivers/gpio/gpiolib.c | 68 |
1 files changed, 62 insertions, 6 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index d66de67ef307..43aeb07343ec 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -337,6 +337,57 @@ static int gpiochip_set_desc_names(struct gpio_chip *gc) return 0; } +static unsigned long *gpiochip_allocate_mask(struct gpio_chip *chip) +{ + unsigned long *p; + + p = kmalloc_array(BITS_TO_LONGS(chip->ngpio), sizeof(*p), GFP_KERNEL); + if (!p) + return NULL; + + /* Assume by default all GPIOs are valid */ + bitmap_fill(p, chip->ngpio); + + return p; +} + +static int gpiochip_init_valid_mask(struct gpio_chip *gpiochip) +{ +#ifdef CONFIG_OF_GPIO + int size; + struct device_node *np = gpiochip->of_node; + + size = of_property_count_u32_elems(np, "gpio-reserved-ranges"); + if (size > 0 && size % 2 == 0) + gpiochip->need_valid_mask = true; +#endif + + if (!gpiochip->need_valid_mask) + return 0; + + gpiochip->valid_mask = gpiochip_allocate_mask(gpiochip); + if (!gpiochip->valid_mask) + return -ENOMEM; + + return 0; +} + +static void gpiochip_free_valid_mask(struct gpio_chip *gpiochip) +{ + kfree(gpiochip->valid_mask); + gpiochip->valid_mask = NULL; +} + +bool gpiochip_line_is_valid(const struct gpio_chip *gpiochip, + unsigned int offset) +{ + /* No mask means all valid */ + if (likely(!gpiochip->valid_mask)) + return true; + return test_bit(offset, gpiochip->valid_mask); +} +EXPORT_SYMBOL_GPL(gpiochip_line_is_valid); + /* * GPIO line handle management */ @@ -1261,6 +1312,10 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, if (status) goto err_remove_from_list; + status = gpiochip_init_valid_mask(chip); + if (status) + goto err_remove_irqchip_mask; + status = gpiochip_add_irqchip(chip, lock_key, request_key); if (status) goto err_remove_chip; @@ -1290,6 +1345,8 @@ err_remove_chip: acpi_gpiochip_remove(chip); gpiochip_free_hogs(chip); of_gpiochip_remove(chip); + gpiochip_free_valid_mask(chip); +err_remove_irqchip_mask: gpiochip_irqchip_free_valid_mask(chip); err_remove_from_list: spin_lock_irqsave(&gpio_lock, flags); @@ -1346,6 +1403,7 @@ void gpiochip_remove(struct gpio_chip *chip) acpi_gpiochip_remove(chip); gpiochip_remove_pin_ranges(chip); of_gpiochip_remove(chip); + gpiochip_free_valid_mask(chip); /* * We accept no more calls into the driver from this point, so * NULL the driver data pointer @@ -1506,14 +1564,10 @@ static int gpiochip_irqchip_init_valid_mask(struct gpio_chip *gpiochip) if (!gpiochip->irq.need_valid_mask) return 0; - gpiochip->irq.valid_mask = kcalloc(BITS_TO_LONGS(gpiochip->ngpio), - sizeof(long), GFP_KERNEL); + gpiochip->irq.valid_mask = gpiochip_allocate_mask(gpiochip); if (!gpiochip->irq.valid_mask) return -ENOMEM; - /* Assume by default all GPIOs are valid */ - bitmap_fill(gpiochip->irq.valid_mask, gpiochip->ngpio); - return 0; } @@ -1526,6 +1580,8 @@ static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gpiochip) bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gpiochip, unsigned int offset) { + if (!gpiochip_line_is_valid(gpiochip, offset)) + return false; /* No mask means all valid */ if (likely(!gpiochip->irq.valid_mask)) return true; @@ -3689,7 +3745,7 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, } if (IS_ERR(desc)) { - dev_dbg(dev, "lookup for GPIO %s failed\n", con_id); + dev_dbg(dev, "No GPIO consumer %s found\n", con_id); return desc; } |