Re: [RFC PATCH v2] gpiolib: add gpio get direction callback support
On Wed, Oct 24, 2012 at 4:25 PM, Mathias Nyman wrote: > Add .get_direction callback to gpio_chip. This allows gpiolib > to check the current direction of a gpio. > Used to show the correct gpio direction in sysfs and debug entries. > > If callback is not set then gpiolib will work as previously; > e.g. guessing everything is input until a direction is set. > > Signed-off-by: Mathias Nyman I buy into this concept. Patch applied. Unless Grant protests, it stays in. Thanks for working on this! Linus Walleij -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [RFC PATCH v2] gpiolib: add gpio get direction callback support
On Wed, Oct 24, 2012 at 4:25 PM, Mathias Nyman mathias.ny...@linux.intel.com wrote: Add .get_direction callback to gpio_chip. This allows gpiolib to check the current direction of a gpio. Used to show the correct gpio direction in sysfs and debug entries. If callback is not set then gpiolib will work as previously; e.g. guessing everything is input until a direction is set. Signed-off-by: Mathias Nyman mathias.ny...@linux.intel.com I buy into this concept. Patch applied. Unless Grant protests, it stays in. Thanks for working on this! Linus Walleij -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[RFC PATCH v2] gpiolib: add gpio get direction callback support
Add .get_direction callback to gpio_chip. This allows gpiolib to check the current direction of a gpio. Used to show the correct gpio direction in sysfs and debug entries. If callback is not set then gpiolib will work as previously; e.g. guessing everything is input until a direction is set. Signed-off-by: Mathias Nyman --- drivers/gpio/gpiolib.c | 38 +- include/asm-generic/gpio.h |5 - 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index de0213c..141f793 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -191,6 +191,32 @@ err: return ret; } +/* caller ensures gpio is valid and requested, chip->get_direction may sleep */ +static int gpio_get_direction(unsigned gpio) +{ + struct gpio_chip*chip; + struct gpio_desc*desc = _desc[gpio]; + int status = -EINVAL; + + chip = gpio_to_chip(gpio); + gpio -= chip->base; + + if (!chip->get_direction) + return status; + + status = chip->get_direction(chip, gpio); + if (status > 0) { + /* GPIOF_DIR_IN, or other positive */ + status = 1; + clear_bit(FLAG_IS_OUT, >flags); + } + if (status == 0) { + /* GPIOF_DIR_OUT */ + set_bit(FLAG_IS_OUT, >flags); + } + return status; +} + #ifdef CONFIG_GPIO_SYSFS /* lock protects against unexport_gpio() being called while @@ -223,6 +249,7 @@ static ssize_t gpio_direction_show(struct device *dev, struct device_attribute *attr, char *buf) { const struct gpio_desc *desc = dev_get_drvdata(dev); + unsignedgpio = desc - gpio_desc; ssize_t status; mutex_lock(_lock); @@ -230,6 +257,7 @@ static ssize_t gpio_direction_show(struct device *dev, if (!test_bit(FLAG_EXPORT, >flags)) status = -EIO; else + gpio_get_direction(gpio); status = sprintf(buf, "%s\n", test_bit(FLAG_IS_OUT, >flags) ? "out" : "in"); @@ -1073,6 +1101,7 @@ int gpiochip_add(struct gpio_chip *chip) * inputs (often with pullups enabled) so power * usage is minimized. Linux code should set the * gpio direction first thing; but until it does, +* and in case chip->get_direction is not set, * we may expose the wrong direction in sysfs. */ gpio_desc[id].flags = !chip->direction_input @@ -1224,9 +1253,15 @@ int gpio_request(unsigned gpio, const char *label) desc_set_label(desc, NULL); module_put(chip->owner); clear_bit(FLAG_REQUESTED, >flags); + goto done; } } - + if (chip->get_direction) { + /* chip->get_direction may sleep */ + spin_unlock_irqrestore(_lock, flags); + gpio_get_direction(gpio); + spin_lock_irqsave(_lock, flags); + } done: if (status) pr_debug("gpio_request: gpio-%d (%s) status %d\n", @@ -1762,6 +1797,7 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip) if (!test_bit(FLAG_REQUESTED, >flags)) continue; + gpio_get_direction(gpio); is_out = test_bit(FLAG_IS_OUT, >flags); seq_printf(s, " gpio-%-3d (%-20.20s) %s %s", gpio, gdesc->label, diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index 365ea09..d8e8c26 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -56,6 +56,8 @@ struct device_node; * enabling module power and clock; may sleep * @free: optional hook for chip-specific deactivation, such as * disabling module power and clock; may sleep + * @get_direction: returns direction for signal "offset", 0=out, 1=in, + * (same as GPIOF_DIR_XXX), or negative error * @direction_input: configures signal "offset" as input, or returns error * @get: returns value for signal "offset"; for output signals this * returns either the value actually sensed, or zero @@ -98,7 +100,8 @@ struct gpio_chip { unsigned offset); void(*free)(struct gpio_chip *chip, unsigned offset); - + int (*get_direction)(struct gpio_chip *chip, + unsigned offset); int (*direction_input)(struct gpio_chip *chip, unsigned offset);
[RFC PATCH v2] gpiolib: add gpio get direction callback support
Add .get_direction callback to gpio_chip. This allows gpiolib to check the current direction of a gpio. Used to show the correct gpio direction in sysfs and debug entries. If callback is not set then gpiolib will work as previously; e.g. guessing everything is input until a direction is set. Signed-off-by: Mathias Nyman mathias.ny...@linux.intel.com --- drivers/gpio/gpiolib.c | 38 +- include/asm-generic/gpio.h |5 - 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index de0213c..141f793 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -191,6 +191,32 @@ err: return ret; } +/* caller ensures gpio is valid and requested, chip-get_direction may sleep */ +static int gpio_get_direction(unsigned gpio) +{ + struct gpio_chip*chip; + struct gpio_desc*desc = gpio_desc[gpio]; + int status = -EINVAL; + + chip = gpio_to_chip(gpio); + gpio -= chip-base; + + if (!chip-get_direction) + return status; + + status = chip-get_direction(chip, gpio); + if (status 0) { + /* GPIOF_DIR_IN, or other positive */ + status = 1; + clear_bit(FLAG_IS_OUT, desc-flags); + } + if (status == 0) { + /* GPIOF_DIR_OUT */ + set_bit(FLAG_IS_OUT, desc-flags); + } + return status; +} + #ifdef CONFIG_GPIO_SYSFS /* lock protects against unexport_gpio() being called while @@ -223,6 +249,7 @@ static ssize_t gpio_direction_show(struct device *dev, struct device_attribute *attr, char *buf) { const struct gpio_desc *desc = dev_get_drvdata(dev); + unsignedgpio = desc - gpio_desc; ssize_t status; mutex_lock(sysfs_lock); @@ -230,6 +257,7 @@ static ssize_t gpio_direction_show(struct device *dev, if (!test_bit(FLAG_EXPORT, desc-flags)) status = -EIO; else + gpio_get_direction(gpio); status = sprintf(buf, %s\n, test_bit(FLAG_IS_OUT, desc-flags) ? out : in); @@ -1073,6 +1101,7 @@ int gpiochip_add(struct gpio_chip *chip) * inputs (often with pullups enabled) so power * usage is minimized. Linux code should set the * gpio direction first thing; but until it does, +* and in case chip-get_direction is not set, * we may expose the wrong direction in sysfs. */ gpio_desc[id].flags = !chip-direction_input @@ -1224,9 +1253,15 @@ int gpio_request(unsigned gpio, const char *label) desc_set_label(desc, NULL); module_put(chip-owner); clear_bit(FLAG_REQUESTED, desc-flags); + goto done; } } - + if (chip-get_direction) { + /* chip-get_direction may sleep */ + spin_unlock_irqrestore(gpio_lock, flags); + gpio_get_direction(gpio); + spin_lock_irqsave(gpio_lock, flags); + } done: if (status) pr_debug(gpio_request: gpio-%d (%s) status %d\n, @@ -1762,6 +1797,7 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip) if (!test_bit(FLAG_REQUESTED, gdesc-flags)) continue; + gpio_get_direction(gpio); is_out = test_bit(FLAG_IS_OUT, gdesc-flags); seq_printf(s, gpio-%-3d (%-20.20s) %s %s, gpio, gdesc-label, diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index 365ea09..d8e8c26 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -56,6 +56,8 @@ struct device_node; * enabling module power and clock; may sleep * @free: optional hook for chip-specific deactivation, such as * disabling module power and clock; may sleep + * @get_direction: returns direction for signal offset, 0=out, 1=in, + * (same as GPIOF_DIR_XXX), or negative error * @direction_input: configures signal offset as input, or returns error * @get: returns value for signal offset; for output signals this * returns either the value actually sensed, or zero @@ -98,7 +100,8 @@ struct gpio_chip { unsigned offset); void(*free)(struct gpio_chip *chip, unsigned offset); - + int (*get_direction)(struct gpio_chip *chip, + unsigned offset); int (*direction_input)(struct gpio_chip *chip,