aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDanilo Krummrich <danilokrummrich@dk-develop.de>2017-08-28 12:59:20 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2017-08-28 13:32:10 -0400
commit9ee0a0558819e63d189426c953668fe1ce7cb637 (patch)
tree3fa59eab6b045632a2cd119dbd206d9e2110ece5
parent0ca0681002587d56ebadc16a6c6653028c3c5cbf (diff)
Input: PS/2 gpio bit banging driver for serio bus
This driver provides PS/2 serio bus support by implementing bit banging with the GPIO API. The GPIO pins, data and clock, can be configured with a node in the device tree or by generic device properties (GDP). Writing to a device is supported as well, though it is possible timings can not be halt as they are tough and difficult to reach with bit banging. Therefore it can be configured (also in DT and GDP) whether the serio write function should be available for clients. This driver is for development purposes and not recommended for productive use. However, this driver can be useful e.g. when no USB port is available or using old peripherals is desired as PS/2 controller chips getting rare. This driver was tested on bcm2825 and on Kirin 960 and it worked well together with the atkbd and psmouse driver. Signed-off-by: Danilo Krummrich <danilokrummrich@dk-develop.de> Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Acked-by: Rob Herring <robh@kernel.org> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
-rw-r--r--Documentation/devicetree/bindings/serio/ps2-gpio.txt23
-rw-r--r--Documentation/gpio/drivers-on-gpio.txt5
-rw-r--r--drivers/input/serio/Kconfig11
-rw-r--r--drivers/input/serio/Makefile1
-rw-r--r--drivers/input/serio/ps2-gpio.c453
5 files changed, 493 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/serio/ps2-gpio.txt b/Documentation/devicetree/bindings/serio/ps2-gpio.txt
new file mode 100644
index 000000000000..7b7bc9cdf986
--- /dev/null
+++ b/Documentation/devicetree/bindings/serio/ps2-gpio.txt
@@ -0,0 +1,23 @@
1Device-Tree binding for ps/2 gpio device
2
3Required properties:
4 - compatible = "ps2-gpio"
5 - data-gpios: the data pin
6 - clk-gpios: the clock pin
7 - interrupts: Should trigger on the falling edge of the clock line.
8
9Optional properties:
10 - write-enable: Indicates whether write function is provided
11 to serio device. Possibly providing the write fn will not work, because
12 of the tough timing requirements.
13
14Example nodes:
15
16ps2@0 {
17 compatible = "ps2-gpio";
18 interrupt-parent = <&gpio>;
19 interrupts = <23 IRQ_TYPE_EDGE_FALLING>;
20 data-gpios = <&gpio 24 GPIO_ACTIVE_HIGH>;
21 clk-gpios = <&gpio 23 GPIO_ACTIVE_HIGH>;
22 write-enable;
23};
diff --git a/Documentation/gpio/drivers-on-gpio.txt b/Documentation/gpio/drivers-on-gpio.txt
index 306513251713..9a78d385b92e 100644
--- a/Documentation/gpio/drivers-on-gpio.txt
+++ b/Documentation/gpio/drivers-on-gpio.txt
@@ -84,6 +84,11 @@ hardware descriptions such as device tree or ACPI:
84 NAND flash MTD subsystem and provides chip access and partition parsing like 84 NAND flash MTD subsystem and provides chip access and partition parsing like
85 any other NAND driving hardware. 85 any other NAND driving hardware.
86 86
87- ps2-gpio: drivers/input/serio/ps2-gpio.c is used to drive a PS/2 (IBM) serio
88 bus, data and clock line, by bit banging two GPIO lines. It will appear as
89 any other serio bus to the system and makes it possible to connect drivers
90 for e.g. keyboards and other PS/2 protocol based devices.
91
87Apart from this there are special GPIO drivers in subsystems like MMC/SD to 92Apart from this there are special GPIO drivers in subsystems like MMC/SD to
88read card detect and write protect GPIO lines, and in the TTY serial subsystem 93read card detect and write protect GPIO lines, and in the TTY serial subsystem
89to emulate MCTRL (modem control) signals CTS/RTS by using two GPIO lines. The 94to emulate MCTRL (modem control) signals CTS/RTS by using two GPIO lines. The
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
index c3d05b4d3118..21488c048fa3 100644
--- a/drivers/input/serio/Kconfig
+++ b/drivers/input/serio/Kconfig
@@ -292,6 +292,17 @@ config SERIO_SUN4I_PS2
292 To compile this driver as a module, choose M here: the 292 To compile this driver as a module, choose M here: the
293 module will be called sun4i-ps2. 293 module will be called sun4i-ps2.
294 294
295config SERIO_GPIO_PS2
296 tristate "GPIO PS/2 bit banging driver"
297 depends on GPIOLIB
298 help
299 Say Y here if you want PS/2 bit banging support via GPIO.
300
301 To compile this driver as a module, choose M here: the
302 module will be called ps2-gpio.
303
304 If you are unsure, say N.
305
295config USERIO 306config USERIO
296 tristate "User space serio port driver support" 307 tristate "User space serio port driver support"
297 help 308 help
diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile
index 2374ef9b33d7..767bd9b6e1ed 100644
--- a/drivers/input/serio/Makefile
+++ b/drivers/input/serio/Makefile
@@ -30,4 +30,5 @@ obj-$(CONFIG_SERIO_APBPS2) += apbps2.o
30obj-$(CONFIG_SERIO_OLPC_APSP) += olpc_apsp.o 30obj-$(CONFIG_SERIO_OLPC_APSP) += olpc_apsp.o
31obj-$(CONFIG_HYPERV_KEYBOARD) += hyperv-keyboard.o 31obj-$(CONFIG_HYPERV_KEYBOARD) += hyperv-keyboard.o
32obj-$(CONFIG_SERIO_SUN4I_PS2) += sun4i-ps2.o 32obj-$(CONFIG_SERIO_SUN4I_PS2) += sun4i-ps2.o
33obj-$(CONFIG_SERIO_GPIO_PS2) += ps2-gpio.o
33obj-$(CONFIG_USERIO) += userio.o 34obj-$(CONFIG_USERIO) += userio.o
diff --git a/drivers/input/serio/ps2-gpio.c b/drivers/input/serio/ps2-gpio.c
new file mode 100644
index 000000000000..b50e3817f3c4
--- /dev/null
+++ b/drivers/input/serio/ps2-gpio.c
@@ -0,0 +1,453 @@
1/*
2 * GPIO based serio bus driver for bit banging the PS/2 protocol
3 *
4 * Author: Danilo Krummrich <danilokrummrich@dk-develop.de>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/gpio/consumer.h>
12#include <linux/interrupt.h>
13#include <linux/module.h>
14#include <linux/serio.h>
15#include <linux/slab.h>
16#include <linux/platform_device.h>
17#include <linux/workqueue.h>
18#include <linux/completion.h>
19#include <linux/mutex.h>
20#include <linux/preempt.h>
21#include <linux/property.h>
22#include <linux/of.h>
23#include <linux/jiffies.h>
24#include <linux/delay.h>
25
26#define DRIVER_NAME "ps2-gpio"
27
28#define PS2_MODE_RX 0
29#define PS2_MODE_TX 1
30
31#define PS2_START_BIT 0
32#define PS2_DATA_BIT0 1
33#define PS2_DATA_BIT1 2
34#define PS2_DATA_BIT2 3
35#define PS2_DATA_BIT3 4
36#define PS2_DATA_BIT4 5
37#define PS2_DATA_BIT5 6
38#define PS2_DATA_BIT6 7
39#define PS2_DATA_BIT7 8
40#define PS2_PARITY_BIT 9
41#define PS2_STOP_BIT 10
42#define PS2_TX_TIMEOUT 11
43#define PS2_ACK_BIT 12
44
45#define PS2_DEV_RET_ACK 0xfa
46#define PS2_DEV_RET_NACK 0xfe
47
48#define PS2_CMD_RESEND 0xfe
49
50struct ps2_gpio_data {
51 struct device *dev;
52 struct serio *serio;
53 unsigned char mode;
54 struct gpio_desc *gpio_clk;
55 struct gpio_desc *gpio_data;
56 bool write_enable;
57 int irq;
58 unsigned char rx_cnt;
59 unsigned char rx_byte;
60 unsigned char tx_cnt;
61 unsigned char tx_byte;
62 struct completion tx_done;
63 struct mutex tx_mutex;
64 struct delayed_work tx_work;
65};
66
67static int ps2_gpio_open(struct serio *serio)
68{
69 struct ps2_gpio_data *drvdata = serio->port_data;
70
71 enable_irq(drvdata->irq);
72 return 0;
73}
74
75static void ps2_gpio_close(struct serio *serio)
76{
77 struct ps2_gpio_data *drvdata = serio->port_data;
78
79 disable_irq(drvdata->irq);
80}
81
82static int __ps2_gpio_write(struct serio *serio, unsigned char val)
83{
84 struct ps2_gpio_data *drvdata = serio->port_data;
85
86 disable_irq_nosync(drvdata->irq);
87 gpiod_direction_output(drvdata->gpio_clk, 0);
88
89 drvdata->mode = PS2_MODE_TX;
90 drvdata->tx_byte = val;
91
92 schedule_delayed_work(&drvdata->tx_work, usecs_to_jiffies(200));
93
94 return 0;
95}
96
97static int ps2_gpio_write(struct serio *serio, unsigned char val)
98{
99 struct ps2_gpio_data *drvdata = serio->port_data;
100 int ret = 0;
101
102 if (in_task()) {
103 mutex_lock(&drvdata->tx_mutex);
104 __ps2_gpio_write(serio, val);
105 if (!wait_for_completion_timeout(&drvdata->tx_done,
106 msecs_to_jiffies(10000)))
107 ret = SERIO_TIMEOUT;
108 mutex_unlock(&drvdata->tx_mutex);
109 } else {
110 __ps2_gpio_write(serio, val);
111 }
112
113 return ret;
114}
115
116static void ps2_gpio_tx_work_fn(struct work_struct *work)
117{
118 struct delayed_work *dwork = to_delayed_work(work);
119 struct ps2_gpio_data *drvdata = container_of(dwork,
120 struct ps2_gpio_data,
121 tx_work);
122
123 enable_irq(drvdata->irq);
124 gpiod_direction_output(drvdata->gpio_data, 0);
125 gpiod_direction_input(drvdata->gpio_clk);
126}
127
128static irqreturn_t ps2_gpio_irq_rx(struct ps2_gpio_data *drvdata)
129{
130 unsigned char byte, cnt;
131 int data;
132 int rxflags = 0;
133 static unsigned long old_jiffies;
134
135 byte = drvdata->rx_byte;
136 cnt = drvdata->rx_cnt;
137
138 if (old_jiffies == 0)
139 old_jiffies = jiffies;
140
141 if ((jiffies - old_jiffies) > usecs_to_jiffies(100)) {
142 dev_err(drvdata->dev,
143 "RX: timeout, probably we missed an interrupt\n");
144 goto err;
145 }
146 old_jiffies = jiffies;
147
148 data = gpiod_get_value(drvdata->gpio_data);
149 if (unlikely(data < 0)) {
150 dev_err(drvdata->dev, "RX: failed to get data gpio val: %d\n",
151 data);
152 goto err;
153 }
154
155 switch (cnt) {
156 case PS2_START_BIT:
157 /* start bit should be low */
158 if (unlikely(data)) {
159 dev_err(drvdata->dev, "RX: start bit should be low\n");
160 goto err;
161 }
162 break;
163 case PS2_DATA_BIT0:
164 case PS2_DATA_BIT1:
165 case PS2_DATA_BIT2:
166 case PS2_DATA_BIT3:
167 case PS2_DATA_BIT4:
168 case PS2_DATA_BIT5:
169 case PS2_DATA_BIT6:
170 case PS2_DATA_BIT7:
171 /* processing data bits */
172 if (data)
173 byte |= (data << (cnt - 1));
174 break;
175 case PS2_PARITY_BIT:
176 /* check odd parity */
177 if (!((hweight8(byte) & 1) ^ data)) {
178 rxflags |= SERIO_PARITY;
179 dev_warn(drvdata->dev, "RX: parity error\n");
180 if (!drvdata->write_enable)
181 goto err;
182 }
183
184 /* Do not send spurious ACK's and NACK's when write fn is
185 * not provided.
186 */
187 if (!drvdata->write_enable) {
188 if (byte == PS2_DEV_RET_NACK)
189 goto err;
190 else if (byte == PS2_DEV_RET_ACK)
191 break;
192 }
193
194 /* Let's send the data without waiting for the stop bit to be
195 * sent. It may happen that we miss the stop bit. When this
196 * happens we have no way to recover from this, certainly
197 * missing the parity bit would be recognized when processing
198 * the stop bit. When missing both, data is lost.
199 */
200 serio_interrupt(drvdata->serio, byte, rxflags);
201 dev_dbg(drvdata->dev, "RX: sending byte 0x%x\n", byte);
202 break;
203 case PS2_STOP_BIT:
204 /* stop bit should be high */
205 if (unlikely(!data)) {
206 dev_err(drvdata->dev, "RX: stop bit should be high\n");
207 goto err;
208 }
209 cnt = byte = 0;
210 old_jiffies = 0;
211 goto end; /* success */
212 default:
213 dev_err(drvdata->dev, "RX: got out of sync with the device\n");
214 goto err;
215 }
216
217 cnt++;
218 goto end; /* success */
219
220err:
221 cnt = byte = 0;
222 old_jiffies = 0;
223 __ps2_gpio_write(drvdata->serio, PS2_CMD_RESEND);
224end:
225 drvdata->rx_cnt = cnt;
226 drvdata->rx_byte = byte;
227 return IRQ_HANDLED;
228}
229
230static irqreturn_t ps2_gpio_irq_tx(struct ps2_gpio_data *drvdata)
231{
232 unsigned char byte, cnt;
233 int data;
234 static unsigned long old_jiffies;
235
236 cnt = drvdata->tx_cnt;
237 byte = drvdata->tx_byte;
238
239 if (old_jiffies == 0)
240 old_jiffies = jiffies;
241
242 if ((jiffies - old_jiffies) > usecs_to_jiffies(100)) {
243 dev_err(drvdata->dev,
244 "TX: timeout, probably we missed an interrupt\n");
245 goto err;
246 }
247 old_jiffies = jiffies;
248
249 switch (cnt) {
250 case PS2_START_BIT:
251 /* should never happen */
252 dev_err(drvdata->dev,
253 "TX: start bit should have been sent already\n");
254 goto err;
255 case PS2_DATA_BIT0:
256 case PS2_DATA_BIT1:
257 case PS2_DATA_BIT2:
258 case PS2_DATA_BIT3:
259 case PS2_DATA_BIT4:
260 case PS2_DATA_BIT5:
261 case PS2_DATA_BIT6:
262 case PS2_DATA_BIT7:
263 data = byte & BIT(cnt - 1);
264 gpiod_set_value(drvdata->gpio_data, data);
265 break;
266 case PS2_PARITY_BIT:
267 /* do odd parity */
268 data = !(hweight8(byte) & 1);
269 gpiod_set_value(drvdata->gpio_data, data);
270 break;
271 case PS2_STOP_BIT:
272 /* release data line to generate stop bit */
273 gpiod_direction_input(drvdata->gpio_data);
274 break;
275 case PS2_TX_TIMEOUT:
276 /* Devices generate one extra clock pulse before sending the
277 * acknowledgment.
278 */
279 break;
280 case PS2_ACK_BIT:
281 gpiod_direction_input(drvdata->gpio_data);
282 data = gpiod_get_value(drvdata->gpio_data);
283 if (data) {
284 dev_warn(drvdata->dev, "TX: received NACK, retry\n");
285 goto err;
286 }
287
288 drvdata->mode = PS2_MODE_RX;
289 complete(&drvdata->tx_done);
290
291 cnt = 1;
292 old_jiffies = 0;
293 goto end; /* success */
294 default:
295 /* Probably we missed the stop bit. Therefore we release data
296 * line and try again.
297 */
298 gpiod_direction_input(drvdata->gpio_data);
299 dev_err(drvdata->dev, "TX: got out of sync with the device\n");
300 goto err;
301 }
302
303 cnt++;
304 goto end; /* success */
305
306err:
307 cnt = 1;
308 old_jiffies = 0;
309 gpiod_direction_input(drvdata->gpio_data);
310 __ps2_gpio_write(drvdata->serio, drvdata->tx_byte);
311end:
312 drvdata->tx_cnt = cnt;
313 return IRQ_HANDLED;
314}
315
316static irqreturn_t ps2_gpio_irq(int irq, void *dev_id)
317{
318 struct ps2_gpio_data *drvdata = dev_id;
319
320 return drvdata->mode ? ps2_gpio_irq_tx(drvdata) :
321 ps2_gpio_irq_rx(drvdata);
322}
323
324static int ps2_gpio_get_props(struct device *dev,
325 struct ps2_gpio_data *drvdata)
326{
327 drvdata->gpio_data = devm_gpiod_get(dev, "data", GPIOD_IN);
328 if (IS_ERR(drvdata->gpio_data)) {
329 dev_err(dev, "failed to request data gpio: %ld",
330 PTR_ERR(drvdata->gpio_data));
331 return PTR_ERR(drvdata->gpio_data);
332 }
333
334 drvdata->gpio_clk = devm_gpiod_get(dev, "clk", GPIOD_IN);
335 if (IS_ERR(drvdata->gpio_clk)) {
336 dev_err(dev, "failed to request clock gpio: %ld",
337 PTR_ERR(drvdata->gpio_clk));
338 return PTR_ERR(drvdata->gpio_clk);
339 }
340
341 drvdata->write_enable = device_property_read_bool(dev,
342 "write-enable");
343
344 return 0;
345}
346
347static int ps2_gpio_probe(struct platform_device *pdev)
348{
349 struct ps2_gpio_data *drvdata;
350 struct serio *serio;
351 struct device *dev = &pdev->dev;
352 int error;
353
354 drvdata = devm_kzalloc(dev, sizeof(struct ps2_gpio_data), GFP_KERNEL);
355 serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
356 if (!drvdata || !serio) {
357 error = -ENOMEM;
358 goto err_free_serio;
359 }
360
361 error = ps2_gpio_get_props(dev, drvdata);
362 if (error)
363 goto err_free_serio;
364
365 if (gpiod_cansleep(drvdata->gpio_data) ||
366 gpiod_cansleep(drvdata->gpio_clk)) {
367 dev_err(dev, "GPIO data or clk are connected via slow bus\n");
368 error = -EINVAL;
369 }
370
371 drvdata->irq = platform_get_irq(pdev, 0);
372 if (drvdata->irq < 0) {
373 dev_err(dev, "failed to get irq from platform resource: %d\n",
374 drvdata->irq);
375 error = drvdata->irq;
376 goto err_free_serio;
377 }
378
379 error = devm_request_irq(dev, drvdata->irq, ps2_gpio_irq,
380 IRQF_NO_THREAD, DRIVER_NAME, drvdata);
381 if (error) {
382 dev_err(dev, "failed to request irq %d: %d\n",
383 drvdata->irq, error);
384 goto err_free_serio;
385 }
386
387 /* Keep irq disabled until serio->open is called. */
388 disable_irq(drvdata->irq);
389
390 serio->id.type = SERIO_8042;
391 serio->open = ps2_gpio_open;
392 serio->close = ps2_gpio_close;
393 /* Write can be enabled in platform/dt data, but possibly it will not
394 * work because of the tough timings.
395 */
396 serio->write = drvdata->write_enable ? ps2_gpio_write : NULL;
397 serio->port_data = drvdata;
398 serio->dev.parent = dev;
399 strlcpy(serio->name, dev_name(dev), sizeof(serio->name));
400 strlcpy(serio->phys, dev_name(dev), sizeof(serio->phys));
401
402 drvdata->serio = serio;
403 drvdata->dev = dev;
404 drvdata->mode = PS2_MODE_RX;
405
406 /* Tx count always starts at 1, as the start bit is sent implicitly by
407 * host-to-device communication initialization.
408 */
409 drvdata->tx_cnt = 1;
410
411 INIT_DELAYED_WORK(&drvdata->tx_work, ps2_gpio_tx_work_fn);
412 init_completion(&drvdata->tx_done);
413 mutex_init(&drvdata->tx_mutex);
414
415 serio_register_port(serio);
416 platform_set_drvdata(pdev, drvdata);
417
418 return 0; /* success */
419
420err_free_serio:
421 kfree(serio);
422 return error;
423}
424
425static int ps2_gpio_remove(struct platform_device *pdev)
426{
427 struct ps2_gpio_data *drvdata = platform_get_drvdata(pdev);
428
429 serio_unregister_port(drvdata->serio);
430 return 0;
431}
432
433#if defined(CONFIG_OF)
434static const struct of_device_id ps2_gpio_match[] = {
435 { .compatible = "ps2-gpio", },
436 { },
437};
438MODULE_DEVICE_TABLE(of, ps2_gpio_match);
439#endif
440
441static struct platform_driver ps2_gpio_driver = {
442 .probe = ps2_gpio_probe,
443 .remove = ps2_gpio_remove,
444 .driver = {
445 .name = DRIVER_NAME,
446 .of_match_table = of_match_ptr(ps2_gpio_match),
447 },
448};
449module_platform_driver(ps2_gpio_driver);
450
451MODULE_AUTHOR("Danilo Krummrich <danilokrummrich@dk-develop.de>");
452MODULE_DESCRIPTION("GPIO PS2 driver");
453MODULE_LICENSE("GPL v2");