summaryrefslogtreecommitdiff
path: root/recipes-kernel/linux/linux-3.12.70/linux-3.12-gpio-expose-deglitch.patch
blob: b868a3664033a96221d8795c69e2eeb72132fe8b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
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)