Skip to content

Commit

Permalink
gpiolib: Pass array info to get/set array functions
Browse files Browse the repository at this point in the history
In order to make use of array info obtained from gpiod_get_array() and
speed up processing of arrays matching single GPIO chip layout, that
information must be passed to get/set array functions.  Extend the
functions' API with that additional parameter and update all users.
Pass NULL if a user builds an array itself from single GPIOs.

Cc: Jonathan Corbet <[email protected]>
Cc: Miguel Ojeda Sandonis <[email protected]>
Cc: Geert Uytterhoeven <[email protected]>
Cc: Sebastien Bourdelin <[email protected]>
Cc: Lukas Wunner <[email protected]>
Cc: Peter Korsgaard <[email protected]>
Cc: Peter Rosin <[email protected]>
Cc: Andrew Lunn <[email protected]>
Cc: Florian Fainelli <[email protected]>
Cc: "David S. Miller" <[email protected]>
Cc: Rojhalat Ibrahim <[email protected]>
Cc: Dominik Brodowski <[email protected]>
Cc: Russell King <[email protected]>
Cc: Kishon Vijay Abraham I <[email protected]>
Cc: Tony Lindgren <[email protected]>
Cc: Lars-Peter Clausen <[email protected]>
Cc: Michael Hennerich <[email protected]>
Cc: Jonathan Cameron <[email protected]>
Cc: Hartmut Knaack <[email protected]>
Cc: Peter Meerwald-Stadler <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: Jiri Slaby <[email protected]>
Cc: Yegor Yefremov <[email protected]>
Cc: Uwe Kleine-König <[email protected]>
Signed-off-by: Janusz Krzysztofik <[email protected]>
Acked-by: Ulf Hansson <[email protected]>
Signed-off-by: Linus Walleij <[email protected]>
  • Loading branch information
jkrzyszt authored and linusw committed Sep 13, 2018
1 parent bf9346f commit 77588c1
Show file tree
Hide file tree
Showing 15 changed files with 86 additions and 26 deletions.
14 changes: 12 additions & 2 deletions Documentation/driver-api/gpio/consumer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -325,28 +325,36 @@ 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,
struct gpio_array *array_info,
unsigned long *value_bitmap);
int gpiod_get_raw_array_value(unsigned int array_size,
struct gpio_desc **desc_array,
struct gpio_array *array_info,
unsigned long *value_bitmap);
int gpiod_get_array_value_cansleep(unsigned int array_size,
struct gpio_desc **desc_array,
struct gpio_array *array_info,
unsigned long *value_bitmap);
int gpiod_get_raw_array_value_cansleep(unsigned int array_size,
struct gpio_desc **desc_array,
struct gpio_array *array_info,
unsigned long *value_bitmap);

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

The array can be an arbitrary set of GPIOs. The functions will try to access
Expand All @@ -358,6 +366,7 @@ accessed sequentially.
The functions take three arguments:
* array_size - the number of array elements
* desc_array - an array of GPIO descriptors
* array_info - optional information obtained from gpiod_array_get()
* value_bitmap - a bitmap to store the GPIOs' values (get) or
a bitmap of values to assign to the GPIOs (set)

Expand All @@ -368,12 +377,13 @@ 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_value_bitmap);
my_gpio_descs->info, 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
gpiod_get_array(). Afterwards the array of descriptors has to be setup
manually before it can be passed to one of the above functions.
manually before it can be passed to one of the above functions. In that case,
array_info should be set to NULL.

Note that for optimal performance GPIOs belonging to the same chip should be
contiguous within the array of descriptors.
Expand Down
8 changes: 4 additions & 4 deletions drivers/auxdisplay/hd44780.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ static void hd44780_write_gpio8(struct hd44780 *hd, u8 val, unsigned int 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);
gpiod_set_array_value_cansleep(n, &hd->pins[PIN_DATA0], NULL, values);

hd44780_strobe_gpio(hd);
}
Expand All @@ -87,7 +87,7 @@ static void hd44780_write_gpio4(struct hd44780 *hd, u8 val, unsigned int 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);
gpiod_set_array_value_cansleep(n, &hd->pins[PIN_DATA4], NULL, values);

hd44780_strobe_gpio(hd);

Expand All @@ -96,7 +96,7 @@ static void hd44780_write_gpio4(struct hd44780 *hd, u8 val, unsigned int rs)
values[0] |= val & 0x0f;

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

hd44780_strobe_gpio(hd);
}
Expand Down Expand Up @@ -152,7 +152,7 @@ static void hd44780_write_cmd_raw_gpio4(struct charlcd *lcd, int cmd)
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);
gpiod_set_array_value_cansleep(n, &hd->pins[PIN_DATA4], NULL, values);

hd44780_strobe_gpio(hd);
}
Expand Down
5 changes: 3 additions & 2 deletions drivers/bus/ts-nbus.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,8 @@ static void ts_nbus_reset_bus(struct ts_nbus *ts_nbus)

values[0] = 0;

gpiod_set_array_value_cansleep(8, ts_nbus->data->desc, values);
gpiod_set_array_value_cansleep(8, ts_nbus->data->desc,
ts_nbus->data->info, values);
gpiod_set_value_cansleep(ts_nbus->csn, 0);
gpiod_set_value_cansleep(ts_nbus->strobe, 0);
gpiod_set_value_cansleep(ts_nbus->ale, 0);
Expand Down Expand Up @@ -159,7 +160,7 @@ static void ts_nbus_write_byte(struct ts_nbus *ts_nbus, u8 byte)

values[0] = byte;

gpiod_set_array_value_cansleep(8, gpios->desc, values);
gpiod_set_array_value_cansleep(8, gpios->desc, gpios->info, values);
}

/*
Expand Down
6 changes: 4 additions & 2 deletions drivers/gpio/gpio-max3191x.c
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ static int max3191x_set_config(struct gpio_chip *gpio, unsigned int offset,

static void gpiod_set_array_single_value_cansleep(unsigned int ndescs,
struct gpio_desc **desc,
struct gpio_array *info,
int value)
{
unsigned long *values;
Expand All @@ -326,7 +327,7 @@ static void gpiod_set_array_single_value_cansleep(unsigned int ndescs,
else
bitmap_zero(values, ndescs);

gpiod_set_array_value_cansleep(ndescs, desc, values);
gpiod_set_array_value_cansleep(ndescs, desc, info, values);
kfree(values);
}

Expand Down Expand Up @@ -399,7 +400,8 @@ static int max3191x_probe(struct spi_device *spi)
if (max3191x->modesel_pins)
gpiod_set_array_single_value_cansleep(
max3191x->modesel_pins->ndescs,
max3191x->modesel_pins->desc, max3191x->mode);
max3191x->modesel_pins->desc,
max3191x->modesel_pins->info, max3191x->mode);

max3191x->ignore_uv = device_property_read_bool(dev,
"maxim,ignore-undervoltage");
Expand Down
40 changes: 32 additions & 8 deletions drivers/gpio/gpiolib.c
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,7 @@ static long linehandle_ioctl(struct file *filep, unsigned int cmd,
true,
lh->numdescs,
lh->descs,
NULL,
vals);
if (ret)
return ret;
Expand Down Expand Up @@ -468,6 +469,7 @@ static long linehandle_ioctl(struct file *filep, unsigned int cmd,
true,
lh->numdescs,
lh->descs,
NULL,
vals);
}
return -EINVAL;
Expand Down Expand Up @@ -2784,6 +2786,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,
struct gpio_array *array_info,
unsigned long *value_bitmap)
{
int i = 0;
Expand Down Expand Up @@ -2897,6 +2900,7 @@ 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 array / value bitmap
* @desc_array: array of GPIO descriptors whose values will be read
* @array_info: information on applicability of fast bitmap processing path
* @value_bitmap: bitmap to store the read values
*
* Read the raw values of the GPIOs, i.e. the values of the physical lines
Expand All @@ -2908,19 +2912,22 @@ EXPORT_SYMBOL_GPL(gpiod_get_value);
*/
int gpiod_get_raw_array_value(unsigned int array_size,
struct gpio_desc **desc_array,
struct gpio_array *array_info,
unsigned long *value_bitmap)
{
if (!desc_array)
return -EINVAL;
return gpiod_get_array_value_complex(true, false, array_size,
desc_array, value_bitmap);
desc_array, array_info,
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 array / value bitmap
* @desc_array: array of GPIO descriptors whose values will be read
* @array_info: information on applicability of fast bitmap processing path
* @value_bitmap: bitmap to store the read values
*
* Read the logical values of the GPIOs, i.e. taking their ACTIVE_LOW status
Expand All @@ -2931,12 +2938,14 @@ EXPORT_SYMBOL_GPL(gpiod_get_raw_array_value);
*/
int gpiod_get_array_value(unsigned int array_size,
struct gpio_desc **desc_array,
struct gpio_array *array_info,
unsigned long *value_bitmap)
{
if (!desc_array)
return -EINVAL;
return gpiod_get_array_value_complex(false, false, array_size,
desc_array, value_bitmap);
desc_array, array_info,
value_bitmap);
}
EXPORT_SYMBOL_GPL(gpiod_get_array_value);

Expand Down Expand Up @@ -3029,6 +3038,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,
struct gpio_array *array_info,
unsigned long *value_bitmap)
{
int i = 0;
Expand Down Expand Up @@ -3156,6 +3166,7 @@ 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 array / value bitmap
* @desc_array: array of GPIO descriptors whose values will be assigned
* @array_info: information on applicability of fast bitmap processing path
* @value_bitmap: bitmap of values to assign
*
* Set the raw values of the GPIOs, i.e. the values of the physical lines
Expand All @@ -3166,19 +3177,21 @@ EXPORT_SYMBOL_GPL(gpiod_set_value);
*/
int gpiod_set_raw_array_value(unsigned int array_size,
struct gpio_desc **desc_array,
struct gpio_array *array_info,
unsigned long *value_bitmap)
{
if (!desc_array)
return -EINVAL;
return gpiod_set_array_value_complex(true, false, array_size,
desc_array, value_bitmap);
desc_array, array_info, 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 array / value bitmap
* @desc_array: array of GPIO descriptors whose values will be assigned
* @array_info: information on applicability of fast bitmap processing path
* @value_bitmap: bitmap of values to assign
*
* Set the logical values of the GPIOs, i.e. taking their ACTIVE_LOW status
Expand All @@ -3189,12 +3202,13 @@ EXPORT_SYMBOL_GPL(gpiod_set_raw_array_value);
*/
void gpiod_set_array_value(unsigned int array_size,
struct gpio_desc **desc_array,
struct gpio_array *array_info,
unsigned long *value_bitmap)
{
if (!desc_array)
return;
gpiod_set_array_value_complex(false, false, array_size, desc_array,
value_bitmap);
array_info, value_bitmap);
}
EXPORT_SYMBOL_GPL(gpiod_set_array_value);

Expand Down Expand Up @@ -3416,6 +3430,7 @@ 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 array / value bitmap
* @desc_array: array of GPIO descriptors whose values will be read
* @array_info: information on applicability of fast bitmap processing path
* @value_bitmap: bitmap to store the read values
*
* Read the raw values of the GPIOs, i.e. the values of the physical lines
Expand All @@ -3426,20 +3441,23 @@ EXPORT_SYMBOL_GPL(gpiod_get_value_cansleep);
*/
int gpiod_get_raw_array_value_cansleep(unsigned int array_size,
struct gpio_desc **desc_array,
struct gpio_array *array_info,
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_bitmap);
desc_array, array_info,
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 array / value bitmap
* @desc_array: array of GPIO descriptors whose values will be read
* @array_info: information on applicability of fast bitmap processing path
* @value_bitmap: bitmap to store the read values
*
* Read the logical values of the GPIOs, i.e. taking their ACTIVE_LOW status
Expand All @@ -3449,13 +3467,15 @@ EXPORT_SYMBOL_GPL(gpiod_get_raw_array_value_cansleep);
*/
int gpiod_get_array_value_cansleep(unsigned int array_size,
struct gpio_desc **desc_array,
struct gpio_array *array_info,
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_bitmap);
desc_array, array_info,
value_bitmap);
}
EXPORT_SYMBOL_GPL(gpiod_get_array_value_cansleep);

Expand Down Expand Up @@ -3499,6 +3519,7 @@ 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 array / value bitmap
* @desc_array: array of GPIO descriptors whose values will be assigned
* @array_info: information on applicability of fast bitmap processing path
* @value_bitmap: bitmap of values to assign
*
* Set the raw values of the GPIOs, i.e. the values of the physical lines
Expand All @@ -3508,13 +3529,14 @@ EXPORT_SYMBOL_GPL(gpiod_set_value_cansleep);
*/
int gpiod_set_raw_array_value_cansleep(unsigned int array_size,
struct gpio_desc **desc_array,
struct gpio_array *array_info,
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_bitmap);
array_info, value_bitmap);
}
EXPORT_SYMBOL_GPL(gpiod_set_raw_array_value_cansleep);

Expand All @@ -3539,6 +3561,7 @@ 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 array / value bitmap
* @desc_array: array of GPIO descriptors whose values will be assigned
* @array_info: information on applicability of fast bitmap processing path
* @value_bitmap: bitmap of values to assign
*
* Set the logical values of the GPIOs, i.e. taking their ACTIVE_LOW status
Expand All @@ -3548,13 +3571,14 @@ 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,
struct gpio_array *array_info,
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_bitmap);
array_info, value_bitmap);
}
EXPORT_SYMBOL_GPL(gpiod_set_array_value_cansleep);

Expand Down
2 changes: 2 additions & 0 deletions drivers/gpio/gpiolib.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,10 +196,12 @@ struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip, u16 hwnum);
int gpiod_get_array_value_complex(bool raw, bool can_sleep,
unsigned int array_size,
struct gpio_desc **desc_array,
struct gpio_array *array_info,
unsigned long *value_bitmap);
int gpiod_set_array_value_complex(bool raw, bool can_sleep,
unsigned int array_size,
struct gpio_desc **desc_array,
struct gpio_array *array_info,
unsigned long *value_bitmap);

/* This is just passed between gpiolib and devres */
Expand Down
3 changes: 2 additions & 1 deletion drivers/i2c/muxes/i2c-mux-gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ static void i2c_mux_gpio_set(const struct gpiomux *mux, unsigned val)

values[0] = val;

gpiod_set_array_value_cansleep(mux->data.n_gpios, mux->gpios, values);
gpiod_set_array_value_cansleep(mux->data.n_gpios, mux->gpios, NULL,
values);
}

static int i2c_mux_gpio_select(struct i2c_mux_core *muxc, u32 chan)
Expand Down
2 changes: 1 addition & 1 deletion drivers/mmc/core/pwrseq_simple.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ static void mmc_pwrseq_simple_set_gpios_value(struct mmc_pwrseq_simple *pwrseq,
values[0] = value;

gpiod_set_array_value_cansleep(nvalues, reset_gpios->desc,
values);
reset_gpios->info, values);
}
}

Expand Down
Loading

0 comments on commit 77588c1

Please sign in to comment.