[PATCH 1/2] [GPIOLib] GPIO Interrupt counter support
Federico Fuga
fuga at studiofuga.com
Tue May 27 11:47:28 PDT 2014
Interrupt counter support inside GPIOLib
Signed-off-by: Federico Fuga <fuga at studiofuga.com>
---
drivers/gpio/Kconfig | 3 ++
drivers/gpio/gpiolib.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++
include/asm-generic/gpio.h | 6 ++++
3 files changed, 99 insertions(+)
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index b2450ba..d371e3c 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -81,6 +81,9 @@ config GPIO_SYSFS
Kernel drivers may also request that a particular GPIO be
exported to userspace; this can be useful when debugging.
+config GPIO_COUNTER
+ bool "GPIO Interrupt counter (where available)"
+
config GPIO_GENERIC
tristate
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index ff0fd65..c052cba 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -69,6 +69,10 @@ struct gpio_desc {
#ifdef CONFIG_DEBUG_FS
const char *label;
#endif
+
+#ifdef CONFIG_GPIO_COUNTER
+ unsigned long counter; /* IRQ Events counter */
+#endif
};
static struct gpio_desc gpio_desc[ARCH_NR_GPIOS];
@@ -583,9 +587,55 @@ static ssize_t gpio_active_low_store(struct device *dev,
static const DEVICE_ATTR(active_low, 0644,
gpio_active_low_show, gpio_active_low_store);
+
+static ssize_t counter_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct gpio_desc *desc = dev_get_drvdata(dev);
+ ssize_t status;
+
+ mutex_lock(&sysfs_lock);
+
+ if (!test_bit(FLAG_EXPORT, &desc->flags)) {
+ status = -EIO;
+ } else {
+ long value;
+
+ status = strict_strtol(buf, 0, &value);
+ if (status == 0)
+ desc->counter = value;
+ }
+
+ mutex_unlock(&sysfs_lock);
+
+ return status ? : size;
+
+}
+
+static ssize_t counter_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ const struct gpio_desc *desc = dev_get_drvdata(dev);
+ ssize_t status;
+
+ mutex_lock(&sysfs_lock);
+
+ if (!test_bit(FLAG_EXPORT, &desc->flags))
+ status = -EIO;
+ else
+ status = sprintf(buf, "%ld\n", desc->counter);
+
+ mutex_unlock(&sysfs_lock);
+
+ return status;
+}
+static DEVICE_ATTR(counter, 0666, counter_show, counter_store);
+
+
static const struct attribute *gpio_attrs[] = {
&dev_attr_value.attr,
&dev_attr_active_low.attr,
+ &dev_attr_counter.attr,
NULL,
};
@@ -1114,6 +1164,46 @@ static inline void gpiod_unexport(struct gpio_desc *desc)
#endif /* CONFIG_GPIO_SYSFS */
+#ifdef CONFIG_GPIO_COUNTER
+int gpio_counter_inc (unsigned gpio)
+{
+ struct gpio_desc *desc = gpio_to_desc(gpio);
+
+ mutex_lock(&sysfs_lock);
+ desc->counter++;
+ mutex_unlock(&sysfs_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(gpio_counter_inc);
+
+long gpio_counter_get (unsigned gpio)
+{
+ long ret;
+ struct gpio_desc *desc = gpio_to_desc(gpio);
+
+ mutex_lock(&sysfs_lock);
+ ret = desc->counter;
+ mutex_unlock(&sysfs_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(gpio_counter_get);
+
+int gpio_counter_set (unsigned gpio, long value)
+{
+ struct gpio_desc *desc = gpio_to_desc(gpio);
+
+ mutex_lock(&sysfs_lock);
+ desc->counter = value;
+ mutex_unlock(&sysfs_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(gpio_counter_set);
+#endif
+
+
/*
* Add a new chip to the global chips list, keeping the list of chips sorted
* by base order.
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index bde6469..2d40187 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -210,6 +210,12 @@ extern void gpio_unexport(unsigned gpio);
#endif /* CONFIG_GPIO_SYSFS */
+#ifdef CONFIG_GPIO_COUNTER
+extern int gpio_counter_inc (unsigned gpio);
+extern long gpio_counter_get (unsigned gpio);
+extern int gpio_counter_set (unsigned gpio, long value);
+#endif
+
#ifdef CONFIG_PINCTRL
/**
--
1.9.1
More information about the linux-rpi-kernel
mailing list