Commit ec75039d authored by Geert Uytterhoeven's avatar Geert Uytterhoeven Committed by Linus Walleij
Browse files

gpio: aggregator: Use bitmap_parselist() for parsing GPIO offsets



Replace the custom code to parse GPIO offsets and/or GPIO offset ranges
by a call to bitmap_parselist(), and an iteration over the returned bit
mask.

This should have no impact on the format of the configuration parameters
written to the "new_device" virtual file in sysfs.

Suggested-by: default avatarAndy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: default avatarGeert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/20200701114212.8520-3-geert+renesas@glider.be


Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent 2073ea3a
Loading
Loading
Loading
Loading
+26 −33
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@
#include <linux/bitmap.h>
#include <linux/bitops.h>
#include <linux/ctype.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/gpio/driver.h>
#include <linux/gpio/machine.h>
@@ -111,55 +112,45 @@ static int aggr_add_gpio(struct gpio_aggregator *aggr, const char *key,

static int aggr_parse(struct gpio_aggregator *aggr)
{
	unsigned int first_index, last_index, i, n = 0;
	char *name, *offsets, *first, *last, *next;
	char *args = aggr->args;
	int error;
	unsigned long *bitmap;
	unsigned int i, n = 0;
	char *name, *offsets;
	int error = 0;

	bitmap = bitmap_alloc(ARCH_NR_GPIOS, GFP_KERNEL);
	if (!bitmap)
		return -ENOMEM;

	for (name = get_arg(&args), offsets = get_arg(&args); name;
	     offsets = get_arg(&args)) {
		if (IS_ERR(name)) {
			pr_err("Cannot get GPIO specifier: %pe\n", name);
			return PTR_ERR(name);
			error = PTR_ERR(name);
			goto free_bitmap;
		}

		if (!isrange(offsets)) {
			/* Named GPIO line */
			error = aggr_add_gpio(aggr, name, U16_MAX, &n);
			if (error)
				return error;
				goto free_bitmap;

			name = offsets;
			continue;
		}

		/* GPIO chip + offset(s) */
		for (first = offsets; *first; first = next) {
			next = strchrnul(first, ',');
			if (*next)
				*next++ = '\0';

			last = strchr(first, '-');
			if (last)
				*last++ = '\0';

			if (kstrtouint(first, 10, &first_index)) {
				pr_err("Cannot parse GPIO index %s\n", first);
				return -EINVAL;
		error = bitmap_parselist(offsets, bitmap, ARCH_NR_GPIOS);
		if (error) {
			pr_err("Cannot parse %s: %d\n", offsets, error);
			goto free_bitmap;
		}

			if (!last) {
				last_index = first_index;
			} else if (kstrtouint(last, 10, &last_index)) {
				pr_err("Cannot parse GPIO index %s\n", last);
				return -EINVAL;
			}

			for (i = first_index; i <= last_index; i++) {
		for_each_set_bit(i, bitmap, ARCH_NR_GPIOS) {
			error = aggr_add_gpio(aggr, name, i, &n);
			if (error)
					return error;
			}
				goto free_bitmap;
		}

		name = get_arg(&args);
@@ -167,10 +158,12 @@ static int aggr_parse(struct gpio_aggregator *aggr)

	if (!n) {
		pr_err("No GPIOs specified\n");
		return -EINVAL;
		error = -EINVAL;
	}

	return 0;
free_bitmap:
	bitmap_free(bitmap);
	return error;
}

static ssize_t new_device_store(struct device_driver *driver, const char *buf,