gpio: Introduce ->get_multiple callback
SPI-attached GPIO controllers typically read out all inputs in one go. If callers desire the values of multipe inputs, ideally a single readout should take place to return the desired values. However the current driver API only offers a ->get callback but no ->get_multiple (unlike ->set_multiple, which is present). Thus, to read multiple inputs, a full readout needs to be performed for every single value (barring driver-internal caching), which is inefficient. In fact, the lack of a ->get_multiple callback has been bemoaned repeatedly by the gpio subsystem maintainer: http://www.spinics.net/lists/linux-gpio/msg10571.html http://www.spinics.net/lists/devicetree/msg121734.html Introduce the missing callback. Add corresponding consumer functions such as gpiod_get_array_value(). Amend linehandle_ioctl() to take advantage of the newly added infrastructure. Update the documentation. Cc: Rojhalat Ibrahim <imr@rtschenk.de> Signed-off-by: Lukas Wunner <lukas@wunner.de> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:

committed by
Linus Walleij

parent
5307e2ad69
commit
eec1d566cd
@@ -365,28 +365,28 @@ 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];
|
||||
int i;
|
||||
|
||||
if (cmd == GPIOHANDLE_GET_LINE_VALUES_IOCTL) {
|
||||
int val;
|
||||
/* TODO: check if descriptors are really input */
|
||||
int ret = gpiod_get_array_value_complex(false,
|
||||
true,
|
||||
lh->numdescs,
|
||||
lh->descs,
|
||||
vals);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
memset(&ghd, 0, sizeof(ghd));
|
||||
|
||||
/* TODO: check if descriptors are really input */
|
||||
for (i = 0; i < lh->numdescs; i++) {
|
||||
val = gpiod_get_value_cansleep(lh->descs[i]);
|
||||
if (val < 0)
|
||||
return val;
|
||||
ghd.values[i] = val;
|
||||
}
|
||||
for (i = 0; i < lh->numdescs; i++)
|
||||
ghd.values[i] = vals[i];
|
||||
|
||||
if (copy_to_user(ip, &ghd, sizeof(ghd)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
} else if (cmd == GPIOHANDLE_SET_LINE_VALUES_IOCTL) {
|
||||
int vals[GPIOHANDLES_MAX];
|
||||
|
||||
/* TODO: check if descriptors are really output */
|
||||
if (copy_from_user(&ghd, ip, sizeof(ghd)))
|
||||
return -EFAULT;
|
||||
@@ -2466,6 +2466,71 @@ static int gpiod_get_raw_value_commit(const struct gpio_desc *desc)
|
||||
return value;
|
||||
}
|
||||
|
||||
static int gpio_chip_get_multiple(struct gpio_chip *chip,
|
||||
unsigned long *mask, unsigned long *bits)
|
||||
{
|
||||
if (chip->get_multiple) {
|
||||
return chip->get_multiple(chip, mask, bits);
|
||||
} else if (chip->get) {
|
||||
int i, value;
|
||||
|
||||
for_each_set_bit(i, mask, chip->ngpio) {
|
||||
value = chip->get(chip, i);
|
||||
if (value < 0)
|
||||
return value;
|
||||
__assign_bit(i, bits, value);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
int gpiod_get_array_value_complex(bool raw, bool can_sleep,
|
||||
unsigned int array_size,
|
||||
struct gpio_desc **desc_array,
|
||||
int *value_array)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (i < array_size) {
|
||||
struct gpio_chip *chip = desc_array[i]->gdev->chip;
|
||||
unsigned long mask[BITS_TO_LONGS(chip->ngpio)];
|
||||
unsigned long bits[BITS_TO_LONGS(chip->ngpio)];
|
||||
int first, j, ret;
|
||||
|
||||
if (!can_sleep)
|
||||
WARN_ON(chip->can_sleep);
|
||||
|
||||
/* collect all inputs belonging to the same chip */
|
||||
first = i;
|
||||
memset(mask, 0, sizeof(mask));
|
||||
do {
|
||||
const struct gpio_desc *desc = desc_array[i];
|
||||
int hwgpio = gpio_chip_hwgpio(desc);
|
||||
|
||||
__set_bit(hwgpio, mask);
|
||||
i++;
|
||||
} while ((i < array_size) &&
|
||||
(desc_array[i]->gdev->chip == chip));
|
||||
|
||||
ret = gpio_chip_get_multiple(chip, mask, bits);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (j = first; j < i; j++) {
|
||||
const struct gpio_desc *desc = desc_array[j];
|
||||
int hwgpio = gpio_chip_hwgpio(desc);
|
||||
int value = test_bit(hwgpio, bits);
|
||||
|
||||
if (!raw && test_bit(FLAG_ACTIVE_LOW, &desc->flags))
|
||||
value = !value;
|
||||
value_array[j] = value;
|
||||
trace_gpio_value(desc_to_gpio(desc), 1, value);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* gpiod_get_raw_value() - return a gpio's raw value
|
||||
* @desc: gpio whose value will be returned
|
||||
@@ -2514,6 +2579,51 @@ int gpiod_get_value(const struct gpio_desc *desc)
|
||||
}
|
||||
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
|
||||
* @desc_array: array of GPIO descriptors whose values will be read
|
||||
* @value_array: array 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,
|
||||
* else an error code.
|
||||
*
|
||||
* This function should be called from contexts where we cannot sleep,
|
||||
* 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)
|
||||
{
|
||||
if (!desc_array)
|
||||
return -EINVAL;
|
||||
return gpiod_get_array_value_complex(true, false, array_size,
|
||||
desc_array, value_array);
|
||||
}
|
||||
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
|
||||
* @desc_array: array of GPIO descriptors whose values will be read
|
||||
* @value_array: array 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.
|
||||
*
|
||||
* This function should be called from contexts where we cannot sleep,
|
||||
* 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)
|
||||
{
|
||||
if (!desc_array)
|
||||
return -EINVAL;
|
||||
return gpiod_get_array_value_complex(false, false, array_size,
|
||||
desc_array, value_array);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gpiod_get_array_value);
|
||||
|
||||
/*
|
||||
* gpio_set_open_drain_value_commit() - Set the open drain gpio's value.
|
||||
* @desc: gpio descriptor whose state need to be set.
|
||||
@@ -2942,6 +3052,53 @@ int gpiod_get_value_cansleep(const struct gpio_desc *desc)
|
||||
}
|
||||
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
|
||||
* @desc_array: array of GPIO descriptors whose values will be read
|
||||
* @value_array: array 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,
|
||||
* else an error code.
|
||||
*
|
||||
* This function is to be called from contexts that can sleep.
|
||||
*/
|
||||
int gpiod_get_raw_array_value_cansleep(unsigned int array_size,
|
||||
struct gpio_desc **desc_array,
|
||||
int *value_array)
|
||||
{
|
||||
might_sleep_if(extra_checks);
|
||||
if (!desc_array)
|
||||
return -EINVAL;
|
||||
return gpiod_get_array_value_complex(true, true, array_size,
|
||||
desc_array, value_array);
|
||||
}
|
||||
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
|
||||
* @desc_array: array of GPIO descriptors whose values will be read
|
||||
* @value_array: array 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.
|
||||
*
|
||||
* This function is to be called from contexts that can sleep.
|
||||
*/
|
||||
int gpiod_get_array_value_cansleep(unsigned int array_size,
|
||||
struct gpio_desc **desc_array,
|
||||
int *value_array)
|
||||
{
|
||||
might_sleep_if(extra_checks);
|
||||
if (!desc_array)
|
||||
return -EINVAL;
|
||||
return gpiod_get_array_value_complex(false, true, array_size,
|
||||
desc_array, value_array);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gpiod_get_array_value_cansleep);
|
||||
|
||||
/**
|
||||
* gpiod_set_raw_value_cansleep() - assign a gpio's raw value
|
||||
* @desc: gpio whose value will be assigned
|
||||
|
@@ -180,6 +180,10 @@ static inline bool acpi_can_fallback_to_crs(struct acpi_device *adev,
|
||||
#endif
|
||||
|
||||
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,
|
||||
int *value_array);
|
||||
void gpiod_set_array_value_complex(bool raw, bool can_sleep,
|
||||
unsigned int array_size,
|
||||
struct gpio_desc **desc_array,
|
||||
|
Reference in New Issue
Block a user