summaryrefslogtreecommitdiff
path: root/drivers/gpio/gpiolib.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-02-23 08:46:04 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2017-02-23 08:46:04 -0800
commit1ec5c1867af085897bb9e0f67bef3713334dbe7f (patch)
tree6d4fa09006a3a4a163fd357bc10da047207341cf /drivers/gpio/gpiolib.c
parentd5dee39b27201f9f5460eca55efcc91a663b738c (diff)
parent3498d8694d41af701c51289e7caf3ffefc7bfb6b (diff)
Merge tag 'gpio-v4.11-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.11 cycle Core changes: - Augment fwnode_get_named_gpiod() to configure the GPIO pin immediately after requesting it like all other APIs do. This is a treewide change also updating all users. - Pass a GPIO label down to gpiod_request() from fwnode_get_named_gpiod(). This makes debugfs and the userspace ABI correctly reflect the current in-kernel consumer of a pin taken using this abstraction. This is a treewide change also updating all users. - Rename devm_get_gpiod_from_child() to devm_fwnode_get_gpiod_from_child() to reflect the fact that this function is operating on a fwnode object. This is a treewide change also updating all users. - Make it possible to take multiple GPIOs in a single hog of device tree hogs. - The refactorings switching GPIO chips to use the .set_config() callback using standard pin control properties and providing a backend into the pin control subsystem that were also merged into the pin control tree naturally appear here too. Testing instrumentation: - A whole slew of cleanups and improvements to the mockup GPIO driver. We now have an extended userspace test exercising the subsystem, and we can inject interrupts etc from userspace to fully test the core GPIO functionality. New drivers: - New driver for the Cortina Systems Gemini GPIO controller. - New driver for the Exar XR17V352/354/358 chips. - New driver for the ACCES PCI-IDIO-16 PCI GPIO card. Driver changes: - RCAR: set the irqchip parent device, add fine-grained runtime PM support. - pca953x: support optional RESET control line on the chip. - DaVinci: cleanups and simplifications. Add support for multiple instances. - .set_multiple() and naming of lines on more or less all of the ISA/PCI GPIO controllers. - mcp23s08: refactored to use regmap as a first step to further rewrites and modernizations" * tag 'gpio-v4.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio: (61 commits) gpio: reintroduce devm_get_gpiod_from_child() gpio: pci-idio-16: Fix PCI BAR index gpio: pci-idio-16: Fix PCI device ID code gpio: mockup: implement event injecting over debugfs gpio: mockup: add a dummy irqchip gpio: mockup: implement naming the lines gpio: mockup: code shrink gpio: mockup: readability tweaks gpio: Add GPIO support for the ACCES PCI-IDIO-16 gpio: Add the devm_fwnode_get_index_gpiod_from_child() helper gpio: Rename devm_get_gpiod_from_child() gpio: mcp23s08: Select REGMAP/REGMAP_I2C to fix build error gpio: ws16c48: Add support for GPIO names gpio: gpio-mm: Add support for GPIO names gpio: 104-idio-16: Add support for GPIO names gpio: 104-idi-48: Add support for GPIO names gpio: 104-dio-48e: Add support for GPIO names gpio: ws16c48: Remove unnecessary driver_data set gpio: gpio-mm: Remove unnecessary driver_data set gpio: 104-idio-16: Remove unnecessary driver_data set ...
Diffstat (limited to 'drivers/gpio/gpiolib.c')
-rw-r--r--drivers/gpio/gpiolib.c55
1 files changed, 30 insertions, 25 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index d0478f1853db..8b4d721d6d63 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1,3 +1,4 @@
+#include <linux/bitops.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
@@ -982,7 +983,7 @@ static int gpio_chrdev_open(struct inode *inode, struct file *filp)
struct gpio_device, chrdev);
/* Fail on open if the backing gpiochip is gone */
- if (!gdev || !gdev->chip)
+ if (!gdev->chip)
return -ENODEV;
get_device(&gdev->dev);
filp->private_data = gdev;
@@ -1001,8 +1002,6 @@ static int gpio_chrdev_release(struct inode *inode, struct file *filp)
struct gpio_device *gdev = container_of(inode->i_cdev,
struct gpio_device, chrdev);
- if (!gdev)
- return -ENODEV;
put_device(&gdev->dev);
return 0;
}
@@ -1423,8 +1422,7 @@ void devm_gpiochip_remove(struct device *dev, struct gpio_chip *chip)
ret = devres_release(dev, devm_gpio_chip_release,
devm_gpio_chip_match, chip);
- if (!ret)
- WARN_ON(ret);
+ WARN_ON(ret);
}
EXPORT_SYMBOL_GPL(devm_gpiochip_remove);
@@ -2586,18 +2584,11 @@ static void gpio_chip_set_multiple(struct gpio_chip *chip,
if (chip->set_multiple) {
chip->set_multiple(chip, mask, bits);
} else {
- int i;
- for (i = 0; i < chip->ngpio; i++) {
- if (mask[BIT_WORD(i)] == 0) {
- /* no more set bits in this mask word;
- * skip ahead to the next word */
- i = (BIT_WORD(i) + 1) * BITS_PER_LONG - 1;
- continue;
- }
- /* set outputs if the corresponding mask bit is set */
- if (__test_and_clear_bit(i, mask))
- chip->set(chip, i, test_bit(i, bits));
- }
+ unsigned int i;
+
+ /* set outputs if the corresponding mask bit is set */
+ for_each_set_bit(i, mask, chip->ngpio)
+ chip->set(chip, i, test_bit(i, bits));
}
}
@@ -3325,6 +3316,8 @@ EXPORT_SYMBOL_GPL(gpiod_get_index);
* fwnode_get_named_gpiod - obtain a GPIO from firmware node
* @fwnode: handle of the firmware node
* @propname: name of the firmware property representing the GPIO
+ * @index: index of the GPIO to obtain in the consumer
+ * @dflags: GPIO initialization flags
*
* This function can be used for drivers that get their configuration
* from firmware.
@@ -3333,12 +3326,18 @@ EXPORT_SYMBOL_GPL(gpiod_get_index);
* underlying firmware interface and then makes sure that the GPIO
* descriptor is requested before it is returned to the caller.
*
+ * On successfull request the GPIO pin is configured in accordance with
+ * provided @dflags.
+ *
* In case of error an ERR_PTR() is returned.
*/
struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
- const char *propname)
+ const char *propname, int index,
+ enum gpiod_flags dflags,
+ const char *label)
{
struct gpio_desc *desc = ERR_PTR(-ENODEV);
+ unsigned long lflags = 0;
bool active_low = false;
bool single_ended = false;
int ret;
@@ -3349,8 +3348,8 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
if (is_of_node(fwnode)) {
enum of_gpio_flags flags;
- desc = of_get_named_gpiod_flags(to_of_node(fwnode), propname, 0,
- &flags);
+ desc = of_get_named_gpiod_flags(to_of_node(fwnode), propname,
+ index, &flags);
if (!IS_ERR(desc)) {
active_low = flags & OF_GPIO_ACTIVE_LOW;
single_ended = flags & OF_GPIO_SINGLE_ENDED;
@@ -3358,7 +3357,7 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
} else if (is_acpi_node(fwnode)) {
struct acpi_gpio_info info;
- desc = acpi_node_get_gpiod(fwnode, propname, 0, &info);
+ desc = acpi_node_get_gpiod(fwnode, propname, index, &info);
if (!IS_ERR(desc))
active_low = info.polarity == GPIO_ACTIVE_LOW;
}
@@ -3366,18 +3365,24 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
if (IS_ERR(desc))
return desc;
- ret = gpiod_request(desc, NULL);
+ ret = gpiod_request(desc, label);
if (ret)
return ERR_PTR(ret);
if (active_low)
- set_bit(FLAG_ACTIVE_LOW, &desc->flags);
+ lflags |= GPIO_ACTIVE_LOW;
if (single_ended) {
if (active_low)
- set_bit(FLAG_OPEN_DRAIN, &desc->flags);
+ lflags |= GPIO_OPEN_DRAIN;
else
- set_bit(FLAG_OPEN_SOURCE, &desc->flags);
+ lflags |= GPIO_OPEN_SOURCE;
+ }
+
+ ret = gpiod_configure_flags(desc, propname, lflags, dflags);
+ if (ret < 0) {
+ gpiod_put(desc);
+ return ERR_PTR(ret);
}
return desc;