summaryrefslogtreecommitdiff
path: root/recipes-kernel/linux/linux-at91-4.9.87/linux-4.9-at91_gpio_set_single_ended.patch
blob: 7e7c6c3bce110532030e67c650fac33bae533d36 (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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
diff -Naru linux-4.9.orig/drivers/gpio/gpiolib.c linux-4.9/drivers/gpio/gpiolib.c
--- linux-4.9.orig/drivers/gpio/gpiolib.c	2018-12-11 10:11:06.000000000 -0600
+++ linux-4.9/drivers/gpio/gpiolib.c	2018-12-12 18:33:20.445762213 -0600
@@ -478,6 +478,8 @@
 			set_bit(FLAG_OPEN_DRAIN, &desc->flags);
 		if (lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE)
 			set_bit(FLAG_OPEN_SOURCE, &desc->flags);
+		if (lflags & GPIOHANDLE_REQUEST_PULLUP)
+			set_bit(FLAG_PULLUP, &desc->flags);
 
 		/*
 		 * Lines have to be requested explicitly for input
@@ -804,6 +806,8 @@
 		set_bit(FLAG_OPEN_DRAIN, &desc->flags);
 	if (lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE)
 		set_bit(FLAG_OPEN_SOURCE, &desc->flags);
+	if (lflags & GPIOHANDLE_REQUEST_PULLUP)
+		set_bit(FLAG_PULLUP, &desc->flags);
 
 	ret = gpiod_direction_input(desc);
 	if (ret)
@@ -953,6 +957,8 @@
 			lineinfo.flags |= GPIOLINE_FLAG_OPEN_DRAIN;
 		if (test_bit(FLAG_OPEN_SOURCE, &desc->flags))
 			lineinfo.flags |= GPIOLINE_FLAG_OPEN_SOURCE;
+		if (test_bit(FLAG_PULLUP, &desc->flags))
+			lineinfo.flags |= GPIOLINE_FLAG_PULLUP;
 
 		if (copy_to_user(ip, &lineinfo, sizeof(lineinfo)))
 			return -EFAULT;
@@ -2090,6 +2096,7 @@
 		clear_bit(FLAG_REQUESTED, &desc->flags);
 		clear_bit(FLAG_OPEN_DRAIN, &desc->flags);
 		clear_bit(FLAG_OPEN_SOURCE, &desc->flags);
+                clear_bit(FLAG_PULLUP, &desc->flags);
 		clear_bit(FLAG_IS_HOGGED, &desc->flags);
 		ret = true;
 	}
@@ -2259,6 +2266,17 @@
 		/* Emulate open source by not actively driving the line low */
 		if (!value)
 			return gpiod_direction_input(desc);
+	}
+	else if (test_bit(FLAG_PULLUP, &desc->flags)) {
+		if (gc->set_single_ended) {
+			ret = gc->set_single_ended(gc, gpio_chip_hwgpio(desc),
+						   LINE_MODE_PULLUP);
+			if (!ret)
+				goto set_output_value;
+		}
+		/* Emulate open source by not actively driving the line low */
+		if (!value)
+			return gpiod_direction_input(desc);
 	} else {
 		/* Make sure to disable open drain/source hardware, if any */
 		if (gc->set_single_ended)
@@ -3164,6 +3182,8 @@
 		set_bit(FLAG_OPEN_DRAIN, &desc->flags);
 	if (lflags & GPIO_OPEN_SOURCE)
 		set_bit(FLAG_OPEN_SOURCE, &desc->flags);
+	if (lflags & GPIO_PULLUP)
+		set_bit(FLAG_PULLUP, &desc->flags);
 
 	/* No particular flag request, return here... */
 	if (!(dflags & GPIOD_FLAGS_BIT_DIR_SET)) {
@@ -3266,6 +3286,7 @@
 	struct gpio_desc *desc = ERR_PTR(-ENODEV);
 	bool active_low = false;
 	bool single_ended = false;
+        bool pullup = false;
 	int ret;
 
 	if (!fwnode)
@@ -3279,6 +3300,7 @@
 		if (!IS_ERR(desc)) {
 			active_low = flags & OF_GPIO_ACTIVE_LOW;
 			single_ended = flags & OF_GPIO_SINGLE_ENDED;
+                        pullup = flags & OF_GPIO_PULLUP;
 		}
 	} else if (is_acpi_node(fwnode)) {
 		struct acpi_gpio_info info;
@@ -3304,7 +3326,8 @@
 		else
 			set_bit(FLAG_OPEN_SOURCE, &desc->flags);
 	}
-
+        if(pullup)
+                set_bit(FLAG_PULLUP, &desc->flags);
 	return desc;
 }
 EXPORT_SYMBOL_GPL(fwnode_get_named_gpiod);
diff -Naru linux-4.9.orig/drivers/gpio/gpiolib.h linux-4.9/drivers/gpio/gpiolib.h
--- linux-4.9.orig/drivers/gpio/gpiolib.h	2018-12-11 12:10:06.937000782 -0600
+++ linux-4.9/drivers/gpio/gpiolib.h	2018-12-11 12:11:30.324998313 -0600
@@ -189,6 +189,7 @@
 #define FLAG_OPEN_SOURCE 8	/* Gpio is open source type */
 #define FLAG_USED_AS_IRQ 9	/* GPIO is connected to an IRQ */
 #define FLAG_IS_HOGGED	11	/* GPIO is hogged */
+#define FLAG_PULLUP	12	/* GPIO is pulled up */
 
 	/* Connection label */
 	const char		*label;
diff -Naru linux-4.9.orig/drivers/gpio/gpiolib-of.c linux-4.9/drivers/gpio/gpiolib-of.c
--- linux-4.9.orig/drivers/gpio/gpiolib-of.c	2018-12-12 18:52:33.000000000 -0600
+++ linux-4.9/drivers/gpio/gpiolib-of.c	2018-12-12 19:10:16.669696602 -0600
@@ -152,6 +152,8 @@
 		else
 			*flags |= GPIO_OPEN_SOURCE;
 	}
+	if (of_flags & OF_GPIO_PULLUP)
+		*flags |= GPIO_PULLUP;
 
 	return desc;
 }
diff -Naru linux-4.9.orig/drivers/pinctrl/pinctrl-at91.c linux-4.9/drivers/pinctrl/pinctrl-at91.c
--- linux-4.9.orig/drivers/pinctrl/pinctrl-at91.c	2018-12-11 10:11:15.000000000 -0600
+++ linux-4.9/drivers/pinctrl/pinctrl-at91.c	2018-12-12 10:25:46.154628279 -0600
@@ -1671,6 +1671,33 @@
 	return -EINVAL;
 }
 
+static int at91_gpio_set_single_ended(struct gpio_chip *chip, unsigned offset, enum single_ended_mode mode)
+{
+ 	struct at91_gpio_chip *at91_gpio = gpiochip_get_data(chip);
+	void __iomem *pio = at91_gpio->regbase;
+	unsigned mask = 1 << offset;
+ 
+	/* Other possibilities:
+	 *    PIO_IFSCDR, PIO_IFSCER (Input Filter Slow Clock disable/enable register)
+	 *    PIO_SCDR (Slow Clock Divider Debouncing register)
+	 */
+        switch(mode) {
+            case LINE_MODE_PULLUP:
+                    at91_mux_set_pullup(pio, mask, true);
+                    return 0;
+            case LINE_MODE_OPEN_DRAIN:
+                    /* Open Drain is Multi Drive */
+                    at91_mux_set_multidrive(pio, mask, true);
+                    return 0;
+            case LINE_MODE_PUSH_PULL:
+                    /* Not pull up or open drain */
+                    at91_mux_set_pullup(pio, mask, false);
+                    at91_mux_set_multidrive(pio, mask, false);
+                    return 0;
+            default: return -EINVAL;
+        }
+}
+
 /* This structure is replicated for each GPIO block allocated at probe time */
 static const struct gpio_chip at91_gpio_template = {
 	.request		= gpiochip_generic_request,
@@ -1681,6 +1708,7 @@
 	.direction_output	= at91_gpio_direction_output,
 	.set			= at91_gpio_set,
 	.set_multiple		= at91_gpio_set_multiple,
+        .set_single_ended       = at91_gpio_set_single_ended,
 	.dbg_show		= at91_gpio_dbg_show,
 	.can_sleep		= false,
 	.ngpio			= MAX_NB_GPIO_PER_BANK,
diff -Naru linux-4.9.orig/include/dt-bindings/gpio/gpio.h linux-4.9/include/dt-bindings/gpio/gpio.h
--- linux-4.9.orig/include/dt-bindings/gpio/gpio.h	2018-12-12 10:50:50.000000000 -0600
+++ linux-4.9/include/dt-bindings/gpio/gpio.h	2018-12-13 14:00:29.459689020 -0600
@@ -17,6 +17,7 @@
 #define GPIO_PUSH_PULL 0
 #define GPIO_SINGLE_ENDED 2
 
+#define GPIO_PULLUP 4
 /*
  * Open Drain/Collector is the combination of single-ended active low,
  * Open Source/Emitter is the combination of single-ended active high.
diff -Naru linux-4.9.orig/include/linux/gpio/driver.h linux-4.9/include/linux/gpio/driver.h
--- linux-4.9.orig/include/linux/gpio/driver.h	2018-12-11 10:11:20.000000000 -0600
+++ linux-4.9/include/linux/gpio/driver.h	2018-12-11 17:47:56.188400715 -0600
@@ -23,11 +23,13 @@
  * @LINE_MODE_PUSH_PULL: normal mode for a GPIO line, drive actively high/low
  * @LINE_MODE_OPEN_DRAIN: set line to be open drain
  * @LINE_MODE_OPEN_SOURCE: set line to be open source
+ * @LINE_MODE_PULLUP: set line to be pullup
  */
 enum single_ended_mode {
 	LINE_MODE_PUSH_PULL,
 	LINE_MODE_OPEN_DRAIN,
 	LINE_MODE_OPEN_SOURCE,
+        LINE_MODE_PULLUP,
 };
 
 /**
diff -Naru linux-4.9.orig/include/linux/gpio/machine.h linux-4.9/include/linux/gpio/machine.h
--- linux-4.9.orig/include/linux/gpio/machine.h	2018-12-12 10:50:50.000000000 -0600
+++ linux-4.9/include/linux/gpio/machine.h	2018-12-12 18:25:12.265776665 -0600
@@ -9,6 +9,7 @@
 	GPIO_ACTIVE_LOW = (1 << 0),
 	GPIO_OPEN_DRAIN = (1 << 1),
 	GPIO_OPEN_SOURCE = (1 << 2),
+	GPIO_PULLUP = (1 << 3),
 };
 
 /**
diff -Naru linux-4.9.orig/include/linux/of_gpio.h linux-4.9/include/linux/of_gpio.h
--- linux-4.9.orig/include/linux/of_gpio.h	2018-12-12 18:40:24.109749670 -0600
+++ linux-4.9/include/linux/of_gpio.h	2018-12-12 18:35:55.000000000 -0600
@@ -30,6 +30,7 @@
 enum of_gpio_flags {
 	OF_GPIO_ACTIVE_LOW = 0x1,
 	OF_GPIO_SINGLE_ENDED = 0x2,
+	OF_GPIO_PULLUP = 0x2,
 };
 
 #ifdef CONFIG_OF_GPIO
diff -Naru linux-4.9.orig/include/uapi/linux/gpio.h linux-4.9/include/uapi/linux/gpio.h
--- linux-4.9.orig/include/uapi/linux/gpio.h	2018-12-11 10:11:21.000000000 -0600
+++ linux-4.9/include/uapi/linux/gpio.h	2018-12-11 12:21:03.884981333 -0600
@@ -32,6 +32,7 @@
 #define GPIOLINE_FLAG_ACTIVE_LOW	(1UL << 2)
 #define GPIOLINE_FLAG_OPEN_DRAIN	(1UL << 3)
 #define GPIOLINE_FLAG_OPEN_SOURCE	(1UL << 4)
+#define GPIOLINE_FLAG_PULLUP    	(1UL << 5)
 
 /**
  * struct gpioline_info - Information about a certain GPIO line
@@ -61,6 +62,7 @@
 #define GPIOHANDLE_REQUEST_ACTIVE_LOW	(1UL << 2)
 #define GPIOHANDLE_REQUEST_OPEN_DRAIN	(1UL << 3)
 #define GPIOHANDLE_REQUEST_OPEN_SOURCE	(1UL << 4)
+#define GPIOHANDLE_REQUEST_PULLUP	(1UL << 5)
 
 /**
  * struct gpiohandle_request - Information about a GPIO handle request