Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b9762beb authored by Janusz Krzysztofik's avatar Janusz Krzysztofik Committed by Linus Walleij
Browse files

gpiolib: Pass bitmaps, not integer arrays, to get/set array



Most users of get/set array functions iterate consecutive bits of data,
usually a single integer, while processing array of results obtained
from, or building an array of values to be passed to those functions.
Save time wasted on those iterations by changing the functions' API to
accept bitmaps.

All current users are updated as well.

More benefits from the change are expected as soon as planned support
for accepting/passing those bitmaps directly from/to respective GPIO
chip callbacks if applicable is implemented.

Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Miguel Ojeda Sandonis <miguel.ojeda.sandonis@gmail.com>
Cc: Sebastien Bourdelin <sebastien.bourdelin@savoirfairelinux.com>
Cc: Lukas Wunner <lukas@wunner.de>
Cc: Peter Korsgaard <peter.korsgaard@barco.com>
Cc: Peter Rosin <peda@axentia.se>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Rojhalat Ibrahim <imr@rtschenk.de>
Cc: Dominik Brodowski <linux@dominikbrodowski.net>
Cc: Russell King <rmk+kernel@armlinux.org.uk>
Cc: Kishon Vijay Abraham I <kishon@ti.com>
Cc: Tony Lindgren <tony@atomide.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Michael Hennerich <Michael.Hennerich@analog.com>
Cc: Jonathan Cameron <jic23@kernel.org>
Cc: Hartmut Knaack <knaack.h@gmx.de>
Cc: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Cc: Yegor Yefremov <yegorslists@googlemail.com>
Cc: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: default avatarJanusz Krzysztofik <jmkrzyszt@gmail.com>
Acked-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
Reviewed-by: default avatarGeert Uytterhoeven <geert+renesas@glider.be>
Tested-by: default avatarGeert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent 5b394b2d
Loading
Loading
Loading
Loading
+11 −11
Original line number Diff line number Diff line
@@ -323,29 +323,29 @@ The following functions get or set the values of an array of GPIOs::

	int gpiod_get_array_value(unsigned int array_size,
				  struct gpio_desc **desc_array,
				  int *value_array);
				  unsigned long *value_bitmap);
	int gpiod_get_raw_array_value(unsigned int array_size,
				      struct gpio_desc **desc_array,
				      int *value_array);
				      unsigned long *value_bitmap);
	int gpiod_get_array_value_cansleep(unsigned int array_size,
					   struct gpio_desc **desc_array,
					   int *value_array);
					   unsigned long *value_bitmap);
	int gpiod_get_raw_array_value_cansleep(unsigned int array_size,
					   struct gpio_desc **desc_array,
					   int *value_array);
					   unsigned long *value_bitmap);

	void gpiod_set_array_value(unsigned int array_size,
				   struct gpio_desc **desc_array,
				   int *value_array)
				   unsigned long *value_bitmap)
	void gpiod_set_raw_array_value(unsigned int array_size,
				       struct gpio_desc **desc_array,
				       int *value_array)
				       unsigned long *value_bitmap)
	void gpiod_set_array_value_cansleep(unsigned int array_size,
					    struct gpio_desc **desc_array,
					    int *value_array)
					    unsigned long *value_bitmap)
	void gpiod_set_raw_array_value_cansleep(unsigned int array_size,
						struct gpio_desc **desc_array,
						int *value_array)
						unsigned long *value_bitmap)

The array can be an arbitrary set of GPIOs. The functions will try to access
GPIOs belonging to the same bank or chip simultaneously if supported by the
@@ -356,8 +356,8 @@ accessed sequentially.
The functions take three arguments:
	* array_size	- the number of array elements
	* desc_array	- an array of GPIO descriptors
	* value_array	- an array to store the GPIOs' values (get) or
			  an array of values to assign to the GPIOs (set)
	* value_bitmap	- a bitmap to store the GPIOs' values (get) or
			  a bitmap of values to assign to the GPIOs (set)

The descriptor array can be obtained using the gpiod_get_array() function
or one of its variants. If the group of descriptors returned by that function
@@ -366,7 +366,7 @@ the struct gpio_descs returned by gpiod_get_array()::

	struct gpio_descs *my_gpio_descs = gpiod_get_array(...);
	gpiod_set_array_value(my_gpio_descs->ndescs, my_gpio_descs->desc,
			      my_gpio_values);
			      my_gpio_value_bitmap);

It is also possible to access a completely arbitrary array of descriptors. The
descriptors may be obtained using any combination of gpiod_get() and
+20 −39
Original line number Diff line number Diff line
@@ -62,17 +62,12 @@ static void hd44780_strobe_gpio(struct hd44780 *hd)
/* write to an LCD panel register in 8 bit GPIO mode */
static void hd44780_write_gpio8(struct hd44780 *hd, u8 val, unsigned int rs)
{
	int values[10];	/* for DATA[0-7], RS, RW */
	unsigned int i, n;

	for (i = 0; i < 8; i++)
		values[PIN_DATA0 + i] = !!(val & BIT(i));
	values[PIN_CTRL_RS] = rs;
	n = 9;
	if (hd->pins[PIN_CTRL_RW]) {
		values[PIN_CTRL_RW] = 0;
		n++;
	}
	DECLARE_BITMAP(values, 10); /* for DATA[0-7], RS, RW */
	unsigned int n;

	values[0] = val;
	__assign_bit(8, values, rs);
	n = hd->pins[PIN_CTRL_RW] ? 10 : 9;

	/* Present the data to the port */
	gpiod_set_array_value_cansleep(n, &hd->pins[PIN_DATA0], values);
@@ -83,32 +78,25 @@ static void hd44780_write_gpio8(struct hd44780 *hd, u8 val, unsigned int rs)
/* write to an LCD panel register in 4 bit GPIO mode */
static void hd44780_write_gpio4(struct hd44780 *hd, u8 val, unsigned int rs)
{
	int values[10];	/* for DATA[0-7], RS, RW, but DATA[0-3] is unused */
	unsigned int i, n;
	DECLARE_BITMAP(values, 6); /* for DATA[4-7], RS, RW */
	unsigned int n;

	/* High nibble + RS, RW */
	for (i = 4; i < 8; i++)
		values[PIN_DATA0 + i] = !!(val & BIT(i));
	values[PIN_CTRL_RS] = rs;
	n = 5;
	if (hd->pins[PIN_CTRL_RW]) {
		values[PIN_CTRL_RW] = 0;
		n++;
	}
	values[0] = val >> 4;
	__assign_bit(4, values, rs);
	n = hd->pins[PIN_CTRL_RW] ? 6 : 5;

	/* Present the data to the port */
	gpiod_set_array_value_cansleep(n, &hd->pins[PIN_DATA4],
				       &values[PIN_DATA4]);
	gpiod_set_array_value_cansleep(n, &hd->pins[PIN_DATA4], values);

	hd44780_strobe_gpio(hd);

	/* Low nibble */
	for (i = 0; i < 4; i++)
		values[PIN_DATA4 + i] = !!(val & BIT(i));
	values[0] &= ~0x0fUL;
	values[0] |= val & 0x0f;

	/* Present the data to the port */
	gpiod_set_array_value_cansleep(n, &hd->pins[PIN_DATA4],
				       &values[PIN_DATA4]);
	gpiod_set_array_value_cansleep(n, &hd->pins[PIN_DATA4], values);

	hd44780_strobe_gpio(hd);
}
@@ -155,23 +143,16 @@ static void hd44780_write_cmd_gpio4(struct charlcd *lcd, int cmd)
/* Send 4-bits of a command to the LCD panel in raw 4 bit GPIO mode */
static void hd44780_write_cmd_raw_gpio4(struct charlcd *lcd, int cmd)
{
	int values[10];	/* for DATA[0-7], RS, RW, but DATA[0-3] is unused */
	DECLARE_BITMAP(values, 6); /* for DATA[4-7], RS, RW */
	struct hd44780 *hd = lcd->drvdata;
	unsigned int i, n;
	unsigned int n;

	/* Command nibble + RS, RW */
	for (i = 0; i < 4; i++)
		values[PIN_DATA4 + i] = !!(cmd & BIT(i));
	values[PIN_CTRL_RS] = 0;
	n = 5;
	if (hd->pins[PIN_CTRL_RW]) {
		values[PIN_CTRL_RW] = 0;
		n++;
	}
	values[0] = cmd & 0x0f;
	n = hd->pins[PIN_CTRL_RW] ? 6 : 5;

	/* Present the data to the port */
	gpiod_set_array_value_cansleep(n, &hd->pins[PIN_DATA4],
				       &values[PIN_DATA4]);
	gpiod_set_array_value_cansleep(n, &hd->pins[PIN_DATA4], values);

	hd44780_strobe_gpio(hd);
}
+4 −11
Original line number Diff line number Diff line
@@ -110,11 +110,9 @@ static void ts_nbus_set_direction(struct ts_nbus *ts_nbus, int direction)
 */
static void ts_nbus_reset_bus(struct ts_nbus *ts_nbus)
{
	int i;
	int values[8];
	DECLARE_BITMAP(values, 8);

	for (i = 0; i < 8; i++)
		values[i] = 0;
	values[0] = 0;

	gpiod_set_array_value_cansleep(8, ts_nbus->data->desc, values);
	gpiod_set_value_cansleep(ts_nbus->csn, 0);
@@ -157,14 +155,9 @@ static int ts_nbus_read_byte(struct ts_nbus *ts_nbus, u8 *val)
static void ts_nbus_write_byte(struct ts_nbus *ts_nbus, u8 byte)
{
	struct gpio_descs *gpios = ts_nbus->data;
	int i;
	int values[8];
	DECLARE_BITMAP(values, 8);

	for (i = 0; i < 8; i++)
		if (byte & BIT(i))
			values[i] = 1;
		else
			values[i] = 0;
	values[0] = byte;

	gpiod_set_array_value_cansleep(8, gpios->desc, values);
}
+6 −4
Original line number Diff line number Diff line
@@ -315,14 +315,16 @@ static void gpiod_set_array_single_value_cansleep(unsigned int ndescs,
						  struct gpio_desc **desc,
						  int value)
{
	int i, *values;
	unsigned long *values;

	values = kmalloc_array(ndescs, sizeof(*values), GFP_KERNEL);
	values = bitmap_alloc(ndescs, GFP_KERNEL);
	if (!values)
		return;

	for (i = 0; i < ndescs; i++)
		values[i] = value;
	if (value)
		bitmap_fill(values, ndescs);
	else
		bitmap_zero(values, ndescs);

	gpiod_set_array_value_cansleep(ndescs, desc, values);
	kfree(values);
+43 −39
Original line number Diff line number Diff line
@@ -427,7 +427,7 @@ static long linehandle_ioctl(struct file *filep, unsigned int cmd,
	struct linehandle_state *lh = filep->private_data;
	void __user *ip = (void __user *)arg;
	struct gpiohandle_data ghd;
	int vals[GPIOHANDLES_MAX];
	DECLARE_BITMAP(vals, GPIOHANDLES_MAX);
	int i;

	if (cmd == GPIOHANDLE_GET_LINE_VALUES_IOCTL) {
@@ -442,7 +442,7 @@ static long linehandle_ioctl(struct file *filep, unsigned int cmd,

		memset(&ghd, 0, sizeof(ghd));
		for (i = 0; i < lh->numdescs; i++)
			ghd.values[i] = vals[i];
			ghd.values[i] = test_bit(i, vals);

		if (copy_to_user(ip, &ghd, sizeof(ghd)))
			return -EFAULT;
@@ -461,7 +461,7 @@ static long linehandle_ioctl(struct file *filep, unsigned int cmd,

		/* Clamp all values to [0,1] */
		for (i = 0; i < lh->numdescs; i++)
			vals[i] = !!ghd.values[i];
			__assign_bit(i, vals, ghd.values[i]);

		/* Reuse the array setting function */
		return gpiod_set_array_value_complex(false,
@@ -2784,7 +2784,7 @@ static int gpio_chip_get_multiple(struct gpio_chip *chip,
int gpiod_get_array_value_complex(bool raw, bool can_sleep,
				  unsigned int array_size,
				  struct gpio_desc **desc_array,
				  int *value_array)
				  unsigned long *value_bitmap)
{
	int i = 0;

@@ -2835,7 +2835,7 @@ int gpiod_get_array_value_complex(bool raw, bool can_sleep,

			if (!raw && test_bit(FLAG_ACTIVE_LOW, &desc->flags))
				value = !value;
			value_array[j] = value;
			__assign_bit(j, value_bitmap, value);
			trace_gpio_value(desc_to_gpio(desc), 1, value);
		}

@@ -2895,9 +2895,9 @@ EXPORT_SYMBOL_GPL(gpiod_get_value);

/**
 * gpiod_get_raw_array_value() - read raw values from an array of GPIOs
 * @array_size: number of elements in the descriptor / value arrays
 * @array_size: number of elements in the descriptor array / value bitmap
 * @desc_array: array of GPIO descriptors whose values will be read
 * @value_array: array to store the read values
 * @value_bitmap: bitmap to store the read values
 *
 * Read the raw values of the GPIOs, i.e. the values of the physical lines
 * without regard for their ACTIVE_LOW status.  Return 0 in case of success,
@@ -2907,20 +2907,21 @@ EXPORT_SYMBOL_GPL(gpiod_get_value);
 * and it will complain if the GPIO chip functions potentially sleep.
 */
int gpiod_get_raw_array_value(unsigned int array_size,
			      struct gpio_desc **desc_array, int *value_array)
			      struct gpio_desc **desc_array,
			      unsigned long *value_bitmap)
{
	if (!desc_array)
		return -EINVAL;
	return gpiod_get_array_value_complex(true, false, array_size,
					     desc_array, value_array);
					     desc_array, value_bitmap);
}
EXPORT_SYMBOL_GPL(gpiod_get_raw_array_value);

/**
 * gpiod_get_array_value() - read values from an array of GPIOs
 * @array_size: number of elements in the descriptor / value arrays
 * @array_size: number of elements in the descriptor array / value bitmap
 * @desc_array: array of GPIO descriptors whose values will be read
 * @value_array: array to store the read values
 * @value_bitmap: bitmap to store the read values
 *
 * Read the logical values of the GPIOs, i.e. taking their ACTIVE_LOW status
 * into account.  Return 0 in case of success, else an error code.
@@ -2929,12 +2930,13 @@ EXPORT_SYMBOL_GPL(gpiod_get_raw_array_value);
 * and it will complain if the GPIO chip functions potentially sleep.
 */
int gpiod_get_array_value(unsigned int array_size,
			  struct gpio_desc **desc_array, int *value_array)
			  struct gpio_desc **desc_array,
			  unsigned long *value_bitmap)
{
	if (!desc_array)
		return -EINVAL;
	return gpiod_get_array_value_complex(false, false, array_size,
					     desc_array, value_array);
					     desc_array, value_bitmap);
}
EXPORT_SYMBOL_GPL(gpiod_get_array_value);

@@ -3027,7 +3029,7 @@ static void gpio_chip_set_multiple(struct gpio_chip *chip,
int gpiod_set_array_value_complex(bool raw, bool can_sleep,
				   unsigned int array_size,
				   struct gpio_desc **desc_array,
				   int *value_array)
				   unsigned long *value_bitmap)
{
	int i = 0;

@@ -3056,7 +3058,7 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep,
		do {
			struct gpio_desc *desc = desc_array[i];
			int hwgpio = gpio_chip_hwgpio(desc);
			int value = value_array[i];
			int value = test_bit(i, value_bitmap);

			if (!raw && test_bit(FLAG_ACTIVE_LOW, &desc->flags))
				value = !value;
@@ -3152,9 +3154,9 @@ EXPORT_SYMBOL_GPL(gpiod_set_value);

/**
 * gpiod_set_raw_array_value() - assign values to an array of GPIOs
 * @array_size: number of elements in the descriptor / value arrays
 * @array_size: number of elements in the descriptor array / value bitmap
 * @desc_array: array of GPIO descriptors whose values will be assigned
 * @value_array: array of values to assign
 * @value_bitmap: bitmap of values to assign
 *
 * Set the raw values of the GPIOs, i.e. the values of the physical lines
 * without regard for their ACTIVE_LOW status.
@@ -3163,20 +3165,21 @@ EXPORT_SYMBOL_GPL(gpiod_set_value);
 * complain if the GPIO chip functions potentially sleep.
 */
int gpiod_set_raw_array_value(unsigned int array_size,
			 struct gpio_desc **desc_array, int *value_array)
			 struct gpio_desc **desc_array,
			 unsigned long *value_bitmap)
{
	if (!desc_array)
		return -EINVAL;
	return gpiod_set_array_value_complex(true, false, array_size,
					desc_array, value_array);
					desc_array, value_bitmap);
}
EXPORT_SYMBOL_GPL(gpiod_set_raw_array_value);

/**
 * gpiod_set_array_value() - assign values to an array of GPIOs
 * @array_size: number of elements in the descriptor / value arrays
 * @array_size: number of elements in the descriptor array / value bitmap
 * @desc_array: array of GPIO descriptors whose values will be assigned
 * @value_array: array of values to assign
 * @value_bitmap: bitmap of values to assign
 *
 * Set the logical values of the GPIOs, i.e. taking their ACTIVE_LOW status
 * into account.
@@ -3185,12 +3188,13 @@ EXPORT_SYMBOL_GPL(gpiod_set_raw_array_value);
 * complain if the GPIO chip functions potentially sleep.
 */
void gpiod_set_array_value(unsigned int array_size,
			   struct gpio_desc **desc_array, int *value_array)
			   struct gpio_desc **desc_array,
			   unsigned long *value_bitmap)
{
	if (!desc_array)
		return;
	gpiod_set_array_value_complex(false, false, array_size, desc_array,
				      value_array);
				      value_bitmap);
}
EXPORT_SYMBOL_GPL(gpiod_set_array_value);

@@ -3410,9 +3414,9 @@ EXPORT_SYMBOL_GPL(gpiod_get_value_cansleep);

/**
 * gpiod_get_raw_array_value_cansleep() - read raw values from an array of GPIOs
 * @array_size: number of elements in the descriptor / value arrays
 * @array_size: number of elements in the descriptor array / value bitmap
 * @desc_array: array of GPIO descriptors whose values will be read
 * @value_array: array to store the read values
 * @value_bitmap: bitmap to store the read values
 *
 * Read the raw values of the GPIOs, i.e. the values of the physical lines
 * without regard for their ACTIVE_LOW status.  Return 0 in case of success,
@@ -3422,21 +3426,21 @@ EXPORT_SYMBOL_GPL(gpiod_get_value_cansleep);
 */
int gpiod_get_raw_array_value_cansleep(unsigned int array_size,
				       struct gpio_desc **desc_array,
				       int *value_array)
				       unsigned long *value_bitmap)
{
	might_sleep_if(extra_checks);
	if (!desc_array)
		return -EINVAL;
	return gpiod_get_array_value_complex(true, true, array_size,
					     desc_array, value_array);
					     desc_array, value_bitmap);
}
EXPORT_SYMBOL_GPL(gpiod_get_raw_array_value_cansleep);

/**
 * gpiod_get_array_value_cansleep() - read values from an array of GPIOs
 * @array_size: number of elements in the descriptor / value arrays
 * @array_size: number of elements in the descriptor array / value bitmap
 * @desc_array: array of GPIO descriptors whose values will be read
 * @value_array: array to store the read values
 * @value_bitmap: bitmap to store the read values
 *
 * Read the logical values of the GPIOs, i.e. taking their ACTIVE_LOW status
 * into account.  Return 0 in case of success, else an error code.
@@ -3445,13 +3449,13 @@ EXPORT_SYMBOL_GPL(gpiod_get_raw_array_value_cansleep);
 */
int gpiod_get_array_value_cansleep(unsigned int array_size,
				   struct gpio_desc **desc_array,
				   int *value_array)
				   unsigned long *value_bitmap)
{
	might_sleep_if(extra_checks);
	if (!desc_array)
		return -EINVAL;
	return gpiod_get_array_value_complex(false, true, array_size,
					     desc_array, value_array);
					     desc_array, value_bitmap);
}
EXPORT_SYMBOL_GPL(gpiod_get_array_value_cansleep);

@@ -3493,9 +3497,9 @@ EXPORT_SYMBOL_GPL(gpiod_set_value_cansleep);

/**
 * gpiod_set_raw_array_value_cansleep() - assign values to an array of GPIOs
 * @array_size: number of elements in the descriptor / value arrays
 * @array_size: number of elements in the descriptor array / value bitmap
 * @desc_array: array of GPIO descriptors whose values will be assigned
 * @value_array: array of values to assign
 * @value_bitmap: bitmap of values to assign
 *
 * Set the raw values of the GPIOs, i.e. the values of the physical lines
 * without regard for their ACTIVE_LOW status.
@@ -3504,13 +3508,13 @@ EXPORT_SYMBOL_GPL(gpiod_set_value_cansleep);
 */
int gpiod_set_raw_array_value_cansleep(unsigned int array_size,
					struct gpio_desc **desc_array,
					int *value_array)
					unsigned long *value_bitmap)
{
	might_sleep_if(extra_checks);
	if (!desc_array)
		return -EINVAL;
	return gpiod_set_array_value_complex(true, true, array_size, desc_array,
				      value_array);
				      value_bitmap);
}
EXPORT_SYMBOL_GPL(gpiod_set_raw_array_value_cansleep);

@@ -3533,9 +3537,9 @@ void gpiod_add_lookup_tables(struct gpiod_lookup_table **tables, size_t n)

/**
 * gpiod_set_array_value_cansleep() - assign values to an array of GPIOs
 * @array_size: number of elements in the descriptor / value arrays
 * @array_size: number of elements in the descriptor array / value bitmap
 * @desc_array: array of GPIO descriptors whose values will be assigned
 * @value_array: array of values to assign
 * @value_bitmap: bitmap of values to assign
 *
 * Set the logical values of the GPIOs, i.e. taking their ACTIVE_LOW status
 * into account.
@@ -3544,13 +3548,13 @@ void gpiod_add_lookup_tables(struct gpiod_lookup_table **tables, size_t n)
 */
void gpiod_set_array_value_cansleep(unsigned int array_size,
				    struct gpio_desc **desc_array,
				    int *value_array)
				    unsigned long *value_bitmap)
{
	might_sleep_if(extra_checks);
	if (!desc_array)
		return;
	gpiod_set_array_value_complex(false, true, array_size, desc_array,
				      value_array);
				      value_bitmap);
}
EXPORT_SYMBOL_GPL(gpiod_set_array_value_cansleep);

Loading