Message ID | 1413244255-3880-1-git-send-email-soren.brinkmann@xilinx.com |
---|---|
State | Accepted |
Headers | show |
On Tue, Oct 14, 2014 at 1:50 AM, Soren Brinkmann <soren.brinkmann@xilinx.com> wrote: > Add an attribute 'wakeup' to the GPIO sysfs interface which allows > marking/unmarking a GPIO as wake IRQ. > The file 'wakeup' is created in each exported GPIOs directory, if an IRQ > is associated with that GPIO and the irqchip implements set_wake(). > Writing 'enabled' to that file will enable wake for that GPIO, while > writing 'disabled' will disable wake. > Reading that file will return either 'disabled' or 'enabled' depening on > the currently set flag for the GPIO's IRQ. > > Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com> > Reviewed-by: Alexandre Courbot <acourbot@nvidia.com> > --- > v2: > - fix error path to unlock mutex before return As you're adding an ABI, you should be patching Documentation/ABI/testing/sysfs-gpio and Documentation/gpio/sysfs.txt in this patch. While I *HATE* the idea of adding IRQ support to userspace for GPIOs, this "just" adds the wakeup capacity, so I guess I'm OK with it. Provided you add it to the ABI doc... Yours, Linus Walleij -- To unsubscribe from this list: send the line "unsubscribe linux-gpio" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Mon, 2014-10-27 at 05:52PM +0100, Linus Walleij wrote: > On Tue, Oct 14, 2014 at 1:50 AM, Soren Brinkmann > <soren.brinkmann@xilinx.com> wrote: > > > Add an attribute 'wakeup' to the GPIO sysfs interface which allows > > marking/unmarking a GPIO as wake IRQ. > > The file 'wakeup' is created in each exported GPIOs directory, if an IRQ > > is associated with that GPIO and the irqchip implements set_wake(). > > Writing 'enabled' to that file will enable wake for that GPIO, while > > writing 'disabled' will disable wake. > > Reading that file will return either 'disabled' or 'enabled' depening on > > the currently set flag for the GPIO's IRQ. > > > > Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com> > > Reviewed-by: Alexandre Courbot <acourbot@nvidia.com> > > --- > > v2: > > - fix error path to unlock mutex before return > > As you're adding an ABI, you should be patching > Documentation/ABI/testing/sysfs-gpio and > Documentation/gpio/sysfs.txt in this patch. > > While I *HATE* the idea of adding IRQ support to userspace > for GPIOs, this "just" adds the wakeup capacity, so I guess I'm > OK with it. > > Provided you add it to the ABI doc... Thanks. I will add some documentation and sent a new patch. Thanks, Sören -- To unsubscribe from this list: send the line "unsubscribe linux-gpio" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c index 5f2150b619a7..7588b6d5ba94 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -286,6 +286,58 @@ found: static DEVICE_ATTR(edge, 0644, gpio_edge_show, gpio_edge_store); +static ssize_t gpio_wakeup_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + ssize_t status; + const struct gpio_desc *desc = dev_get_drvdata(dev); + int irq = gpiod_to_irq(desc); + struct irq_desc *irq_desc = irq_to_desc(irq); + + mutex_lock(&sysfs_lock); + + if (irqd_is_wakeup_set(&irq_desc->irq_data)) + status = sprintf(buf, "enabled\n"); + else + status = sprintf(buf, "disabled\n"); + + mutex_unlock(&sysfs_lock); + + return status; +} + +static ssize_t gpio_wakeup_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + int ret; + unsigned int on; + struct gpio_desc *desc = dev_get_drvdata(dev); + int irq = gpiod_to_irq(desc); + + mutex_lock(&sysfs_lock); + + if (sysfs_streq("enabled", buf)) { + on = true; + } else if (sysfs_streq("disabled", buf)) { + on = false; + } else { + mutex_unlock(&sysfs_lock); + return -EINVAL; + } + + ret = irq_set_irq_wake(irq, on); + + mutex_unlock(&sysfs_lock); + + if (ret) + pr_warn("%s: failed to %s wake\n", __func__, + on ? "enable" : "disable"); + + return size; +} + +static DEVICE_ATTR(wakeup, 0644, gpio_wakeup_show, gpio_wakeup_store); + static int sysfs_set_active_low(struct gpio_desc *desc, struct device *dev, int value) { @@ -526,7 +578,7 @@ static struct class gpio_class = { int gpiod_export(struct gpio_desc *desc, bool direction_may_change) { unsigned long flags; - int status; + int status, irq; const char *ioname = NULL; struct device *dev; int offset; @@ -582,11 +634,24 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change) goto fail_unregister_device; } - if (gpiod_to_irq(desc) >= 0 && (direction_may_change || - !test_bit(FLAG_IS_OUT, &desc->flags))) { - status = device_create_file(dev, &dev_attr_edge); - if (status) - goto fail_unregister_device; + irq = gpiod_to_irq(desc); + if (irq >= 0) { + struct irq_desc *irq_desc = irq_to_desc(irq); + struct irq_chip *irqchip = irq_desc_get_chip(irq_desc); + + if (direction_may_change || + !test_bit(FLAG_IS_OUT, &desc->flags)) { + status = device_create_file(dev, &dev_attr_edge); + if (status) + goto fail_unregister_device; + } + + if (irqchip->flags & IRQCHIP_SKIP_SET_WAKE || + irqchip->irq_set_wake) { + status = device_create_file(dev, &dev_attr_wakeup); + if (status) + goto fail_unregister_device; + } } set_bit(FLAG_EXPORT, &desc->flags);