1
2
3
4
5
6
7
8
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
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
172 if (data)
173 byte |= (data << (cnt - 1));
174 break;
175 case PS2_PARITY_BIT:
176
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
185
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
195
196
197
198
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
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;
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;
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
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
268 data = !(hweight8(byte) & 1);
269 gpiod_set_value(drvdata->gpio_data, data);
270 break;
271 case PS2_STOP_BIT:
272
273 gpiod_direction_input(drvdata->gpio_data);
274 break;
275 case PS2_TX_TIMEOUT:
276
277
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;
294 default:
295
296
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;
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
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
394
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
407
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;
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");
454