summaryrefslogtreecommitdiff
path: root/recipes-kernel/linux/linux-3.12.70/linux-3.12-gpio-expose-deglitch.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes-kernel/linux/linux-3.12.70/linux-3.12-gpio-expose-deglitch.patch')
-rw-r--r--recipes-kernel/linux/linux-3.12.70/linux-3.12-gpio-expose-deglitch.patch165
1 files changed, 165 insertions, 0 deletions
diff --git a/recipes-kernel/linux/linux-3.12.70/linux-3.12-gpio-expose-deglitch.patch b/recipes-kernel/linux/linux-3.12.70/linux-3.12-gpio-expose-deglitch.patch
new file mode 100644
index 0000000..b868a36
--- /dev/null
+++ b/recipes-kernel/linux/linux-3.12.70/linux-3.12-gpio-expose-deglitch.patch
@@ -0,0 +1,165 @@
+Index: linux-3.12.13/drivers/gpio/gpiolib.c
+===================================================================
+--- linux-3.12.13.orig/drivers/gpio/gpiolib.c 2014-04-18 09:55:28.325372866 -0500
++++ linux-3.12.13/drivers/gpio/gpiolib.c 2014-04-18 10:01:46.221371869 -0500
+@@ -90,6 +90,7 @@
+ static int gpiod_direction_input_pullup(struct gpio_desc *desc, bool pullup);
+ static int gpiod_direction_output(struct gpio_desc *desc, int value);
+ static int gpiod_direction_output_pullup(struct gpio_desc *desc, int value, bool pullup);
++static int gpiod_deglitch(struct gpio_desc *desc, bool enable);
+ static int gpiod_get_direction(const struct gpio_desc *desc);
+ static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce);
+ static int gpiod_get_value_cansleep(const struct gpio_desc *desc);
+@@ -1539,6 +1540,9 @@
+ (flags & GPIOF_INIT_HIGH) ? 1 : 0);
+ }
+
++ if (flags & GPIOF_DEGLITCH)
++ err = gpiod_deglitch(desc, (flags & GPIOF_DEGLITCH) ? true : false);
++
+ if (err)
+ goto free_gpio;
+
+@@ -1909,6 +1913,67 @@
+ }
+ EXPORT_SYMBOL_GPL(gpio_direction_output);
+
++static int gpiod_deglitch(struct gpio_desc *desc, bool enable)
++{
++ unsigned long flags;
++ struct gpio_chip *chip;
++ int status = -EINVAL;
++ int offset;
++
++ if (!desc || !desc->chip) {
++ pr_warn("%s: invalid GPIO\n", __func__);
++ return -EINVAL;
++ }
++
++ chip = desc->chip;
++ if (!chip->deglitch) {
++ pr_warn("%s: missing deglitch() operation\n",
++ __func__);
++ return -EIO;
++ }
++
++ spin_lock_irqsave(&gpio_lock, flags);
++
++ status = gpio_ensure_requested(desc);
++ if (status < 0)
++ goto fail;
++
++ /* now we know the gpio is valid and chip won't vanish */
++
++ spin_unlock_irqrestore(&gpio_lock, flags);
++
++ might_sleep_if(chip->can_sleep);
++
++ offset = gpio_chip_hwgpio(desc);
++ if (status) {
++ status = chip->request(chip, offset);
++ if (status < 0) {
++ pr_debug("GPIO-%d: chip request fail, %d\n",
++ desc_to_gpio(desc), status);
++ /* and it's not available to anyone else ...
++ * gpio_request() is the fully clean solution.
++ */
++ goto lose;
++ }
++ }
++
++ status = chip->deglitch(chip, offset, enable);
++lose:
++ return status;
++fail:
++ spin_unlock_irqrestore(&gpio_lock, flags);
++ if (status)
++ pr_debug("%s: gpio-%d status %d\n", __func__,
++ desc_to_gpio(desc), status);
++ return status;
++}
++
++int gpio_deglitch(unsigned gpio, bool enable)
++{
++ return gpiod_deglitch(gpio_to_desc(gpio), enable);
++}
++EXPORT_SYMBOL_GPL(gpio_deglitch);
++
+ /**
+ * gpio_set_debounce - sets @debounce time for a @gpio
+ * @gpio: the gpio to set debounce time
+Index: linux-3.12.13/drivers/pinctrl/pinctrl-at91.c
+===================================================================
+--- linux-3.12.13.orig/drivers/pinctrl/pinctrl-at91.c 2014-04-18 09:55:28.325372866 -0500
++++ linux-3.12.13/drivers/pinctrl/pinctrl-at91.c 2014-04-18 10:02:45.041371714 -0500
+@@ -1171,6 +1171,17 @@
+ return 0;
+ }
+
++static int at91_gpio_set_deglitch(struct gpio_chip *chip, unsigned offset, bool enable)
++{
++ struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
++ void __iomem *pio = at91_gpio->regbase;
++ unsigned mask = 1 << offset;
++
++ at91_mux_pio3_set_deglitch(pio, mask, enable);
++
++ return 0;
++}
++
+ static int at91_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+ {
+ struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
+@@ -1542,6 +1553,7 @@
+ .get = at91_gpio_get,
+ .direction_output = at91_gpio_direction_output,
+ .direction_output_pullup = at91_gpio_direction_output_pullup,
++ .deglitch = at91_gpio_set_deglitch,
+ .set = at91_gpio_set,
+ .to_irq = at91_gpio_to_irq,
+ .dbg_show = at91_gpio_dbg_show,
+Index: linux-3.12.13/include/asm-generic/gpio.h
+===================================================================
+--- linux-3.12.13.orig/include/asm-generic/gpio.h 2014-04-18 09:55:28.325372866 -0500
++++ linux-3.12.13/include/asm-generic/gpio.h 2014-04-18 09:58:13.081372430 -0500
+@@ -67,6 +67,7 @@
+ * returns either the value actually sensed, or zero
+ * @direction_output: configures signal "offset" as output, or returns error
+ * @direction_output_pullup: configures signal "offset" as output with pullup enabled, or returns error
++ * @deglitch: enables deglitch on signal "offset"
+ * @set_debounce: optional hook for setting debounce time for specified gpio in
+ * interrupt triggered gpio chips
+ * @set: assigns output value for signal "offset"
+@@ -121,6 +122,8 @@
+ unsigned offset, int value);
+ int (*direction_output_pullup)(struct gpio_chip *chip,
+ unsigned offset, int value, bool pullup);
++ int (*deglitch)(struct gpio_chip *chip,
++ unsigned offset, bool enable);
+ int (*set_debounce)(struct gpio_chip *chip,
+ unsigned offset, unsigned debounce);
+
+@@ -182,6 +185,7 @@
+ extern int gpio_direction_input_pullup(unsigned gpio, bool pullup);
+ extern int gpio_direction_output(unsigned gpio, int value);
+ extern int gpio_direction_output_pullup(unsigned gpio, int value, bool pullup);
++extern int gpio_deglitch(unsigned gpio, bool enable);
+
+ extern int gpio_set_debounce(unsigned gpio, unsigned debounce);
+
+Index: linux-3.12.13/include/linux/gpio.h
+===================================================================
+--- linux-3.12.13.orig/include/linux/gpio.h 2014-04-18 09:55:28.325372866 -0500
++++ linux-3.12.13/include/linux/gpio.h 2014-04-18 09:57:56.305372474 -0500
+@@ -13,9 +13,11 @@
+ #define GPIOF_INIT_HIGH (1 << 1)
+
+ #define GPIOF_PULLUP (2 << 0)
++#define GPIOF_DEGLITCH (2 << 1)
+
+ #define GPIOF_IN (GPIOF_DIR_IN)
+ #define GPIOF_IN_PULLUP (GPIOF_DIR_IN | GPIOF_PULLUP)
++#define GPIOF_IN_DEGLITCH (GPIOF_DIR_IN | GPIOF_DEGLITCH)
+ #define GPIOF_OUT_INIT_LOW (GPIOF_DIR_OUT | GPIOF_INIT_LOW)
+ #define GPIOF_OUT_INIT_HIGH (GPIOF_DIR_OUT | GPIOF_INIT_HIGH)
+