summaryrefslogtreecommitdiff
path: root/drivers/gpio/gpiolib-sysfs.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2022-03-25 22:28:23 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2022-03-25 22:28:23 +0300
commitebcb577aee1448fd60904fc4126cbf7ec012bd0b (patch)
tree144ea30487c4bc1451ed1eb3d2cafa3e777abe01 /drivers/gpio/gpiolib-sysfs.c
parent5e206459f670b579da9b7861a0f3ce3b989a68b6 (diff)
parent87ba5badc541a79bab2fa3243ee0008c0880c64a (diff)
downloadlinux-ebcb577aee1448fd60904fc4126cbf7ec012bd0b.tar.xz
Merge tag 'gpio-updates-for-v5.18' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux
Pull gpio updates from Bartosz Golaszewski: "Relatively few updates for this release cycle. We have a single new driver and some minor changes in drivers, more work on limiting the usage of of_node in drivers and DT updates: - new driver: gpio-en7523 - dt-bindings: convertion of faraday,ftgpio010 to YAML, new compatible string in gpio-vf610 and a bugfix in an example - gpiolib core: several improvements and some code shrink - documentation: convert all public docs into kerneldoc format - set IRQ bus token in gpio-crystalcove (addresses a debugfs issue) - add a missing return value check for kstrdup() in gpio-merrifield - allow gpio-tps68470 to be built as module - more work on limiting usage of of_node in GPIO drivers - several sysfs interface improvements - use SDPX in gpio-ts4900" * tag 'gpio-updates-for-v5.18' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux: gpio: ts4900: Use SPDX header gpiolib: Use list_first_entry()/list_last_entry() gpiolib: sysfs: Simplify edge handling in the code gpiolib: sysfs: Move kstrtox() calls outside of the mutex lock gpiolib: sysfs: Move sysfs_emit() calls outside of the mutex lock gpiolib: make struct comments into real kernel docs dt-bindings: gpio: convert faraday,ftgpio01 to yaml dt-bindings: gpio: gpio-vf610: Add imx93 compatible string gpiolib: Simplify error path in gpiod_get_index() when requesting GPIO gpiolib: Use short form of ternary operator in gpiod_get_index() gpiolib: Introduce for_each_gpio_desc_with_flag() macro gpio: Add support for Airoha EN7523 GPIO controller dt-bindings: arm: airoha: Add binding for Airoha GPIO controller dt-bindings: gpio: fix gpio-hog example gpio: tps68470: Allow building as module gpio: tegra: Get rid of duplicate of_node assignment gpio: altera-a10sr: Switch to use fwnode instead of of_node gpio: merrifield: check the return value of devm_kstrdup() gpio: crystalcove: Set IRQ domain bus token to DOMAIN_BUS_WIRED
Diffstat (limited to 'drivers/gpio/gpiolib-sysfs.c')
-rw-r--r--drivers/gpio/gpiolib-sysfs.c100
1 files changed, 40 insertions, 60 deletions
diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c
index 44c1ad51b3fe..d44ffea038f5 100644
--- a/drivers/gpio/gpiolib-sysfs.c
+++ b/drivers/gpio/gpiolib-sysfs.c
@@ -13,6 +13,7 @@
#include "gpiolib.h"
#include "gpiolib-sysfs.h"
+#define GPIO_IRQF_TRIGGER_NONE 0
#define GPIO_IRQF_TRIGGER_FALLING BIT(0)
#define GPIO_IRQF_TRIGGER_RISING BIT(1)
#define GPIO_IRQF_TRIGGER_BOTH (GPIO_IRQF_TRIGGER_FALLING | \
@@ -61,17 +62,16 @@ static ssize_t direction_show(struct device *dev,
{
struct gpiod_data *data = dev_get_drvdata(dev);
struct gpio_desc *desc = data->desc;
- ssize_t status;
+ int value;
mutex_lock(&data->mutex);
gpiod_get_direction(desc);
- status = sysfs_emit(buf, "%s\n",
- test_bit(FLAG_IS_OUT, &desc->flags) ? "out" : "in");
+ value = !!test_bit(FLAG_IS_OUT, &desc->flags);
mutex_unlock(&data->mutex);
- return status;
+ return sysfs_emit(buf, "%s\n", value ? "out" : "in");
}
static ssize_t direction_store(struct device *dev,
@@ -108,12 +108,13 @@ static ssize_t value_show(struct device *dev,
mutex_lock(&data->mutex);
status = gpiod_get_value_cansleep(desc);
- if (status >= 0)
- status = sysfs_emit(buf, "%zd\n", status);
mutex_unlock(&data->mutex);
- return status;
+ if (status < 0)
+ return status;
+
+ return sysfs_emit(buf, "%zd\n", status);
}
static ssize_t value_store(struct device *dev,
@@ -121,24 +122,18 @@ static ssize_t value_store(struct device *dev,
{
struct gpiod_data *data = dev_get_drvdata(dev);
struct gpio_desc *desc = data->desc;
- ssize_t status = 0;
+ ssize_t status;
+ long value;
+
+ status = kstrtol(buf, 0, &value);
mutex_lock(&data->mutex);
if (!test_bit(FLAG_IS_OUT, &desc->flags)) {
status = -EPERM;
- } else {
- long value;
-
- if (size <= 2 && isdigit(buf[0]) &&
- (size == 1 || buf[1] == '\n'))
- value = buf[0] - '0';
- else
- status = kstrtol(buf, 0, &value);
- if (status == 0) {
- gpiod_set_value_cansleep(desc, value);
- status = size;
- }
+ } else if (status == 0) {
+ gpiod_set_value_cansleep(desc, value);
+ status = size;
}
mutex_unlock(&data->mutex);
@@ -224,54 +219,41 @@ static void gpio_sysfs_free_irq(struct device *dev)
sysfs_put(data->value_kn);
}
-static const struct {
- const char *name;
- unsigned char flags;
-} trigger_types[] = {
- { "none", 0 },
- { "falling", GPIO_IRQF_TRIGGER_FALLING },
- { "rising", GPIO_IRQF_TRIGGER_RISING },
- { "both", GPIO_IRQF_TRIGGER_BOTH },
+static const char * const trigger_names[] = {
+ [GPIO_IRQF_TRIGGER_NONE] = "none",
+ [GPIO_IRQF_TRIGGER_FALLING] = "falling",
+ [GPIO_IRQF_TRIGGER_RISING] = "rising",
+ [GPIO_IRQF_TRIGGER_BOTH] = "both",
};
static ssize_t edge_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct gpiod_data *data = dev_get_drvdata(dev);
- ssize_t status = 0;
- int i;
+ int flags;
mutex_lock(&data->mutex);
- for (i = 0; i < ARRAY_SIZE(trigger_types); i++) {
- if (data->irq_flags == trigger_types[i].flags)
- break;
- }
- if (i < ARRAY_SIZE(trigger_types))
- status = sysfs_emit(buf, "%s\n", trigger_types[i].name);
+ flags = data->irq_flags;
mutex_unlock(&data->mutex);
- return status;
+ if (flags >= ARRAY_SIZE(trigger_names))
+ return 0;
+
+ return sysfs_emit(buf, "%s\n", trigger_names[flags]);
}
static ssize_t edge_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct gpiod_data *data = dev_get_drvdata(dev);
- unsigned char flags;
ssize_t status = size;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(trigger_types); i++) {
- if (sysfs_streq(trigger_types[i].name, buf))
- break;
- }
-
- if (i == ARRAY_SIZE(trigger_types))
- return -EINVAL;
+ int flags;
- flags = trigger_types[i].flags;
+ flags = sysfs_match_string(trigger_names, buf);
+ if (flags < 0)
+ return flags;
mutex_lock(&data->mutex);
@@ -324,16 +306,15 @@ static ssize_t active_low_show(struct device *dev,
{
struct gpiod_data *data = dev_get_drvdata(dev);
struct gpio_desc *desc = data->desc;
- ssize_t status;
+ int value;
mutex_lock(&data->mutex);
- status = sysfs_emit(buf, "%d\n",
- !!test_bit(FLAG_ACTIVE_LOW, &desc->flags));
+ value = !!test_bit(FLAG_ACTIVE_LOW, &desc->flags);
mutex_unlock(&data->mutex);
- return status;
+ return sysfs_emit(buf, "%d\n", value);
}
static ssize_t active_low_store(struct device *dev,
@@ -343,11 +324,13 @@ static ssize_t active_low_store(struct device *dev,
ssize_t status;
long value;
+ status = kstrtol(buf, 0, &value);
+ if (status)
+ return status;
+
mutex_lock(&data->mutex);
- status = kstrtol(buf, 0, &value);
- if (status == 0)
- status = gpio_sysfs_set_active_low(dev, value);
+ status = gpio_sysfs_set_active_low(dev, value);
mutex_unlock(&data->mutex);
@@ -790,11 +773,8 @@ void gpiochip_sysfs_unregister(struct gpio_device *gdev)
mutex_unlock(&sysfs_lock);
/* unregister gpiod class devices owned by sysfs */
- for (i = 0; i < chip->ngpio; i++) {
- desc = &gdev->descs[i];
- if (test_and_clear_bit(FLAG_SYSFS, &desc->flags))
- gpiod_free(desc);
- }
+ for_each_gpio_desc_with_flag(i, chip, desc, FLAG_SYSFS)
+ gpiod_free(desc);
}
static int __init gpiolib_sysfs_init(void)