Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/input/keyboard/matrix_keypad.c
15112 views
1
/*
2
* GPIO driven matrix keyboard driver
3
*
4
* Copyright (c) 2008 Marek Vasut <[email protected]>
5
*
6
* Based on corgikbd.c
7
*
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License version 2 as
10
* published by the Free Software Foundation.
11
*
12
*/
13
14
#include <linux/types.h>
15
#include <linux/delay.h>
16
#include <linux/platform_device.h>
17
#include <linux/init.h>
18
#include <linux/input.h>
19
#include <linux/irq.h>
20
#include <linux/interrupt.h>
21
#include <linux/jiffies.h>
22
#include <linux/module.h>
23
#include <linux/gpio.h>
24
#include <linux/input/matrix_keypad.h>
25
#include <linux/slab.h>
26
27
struct matrix_keypad {
28
const struct matrix_keypad_platform_data *pdata;
29
struct input_dev *input_dev;
30
unsigned short *keycodes;
31
unsigned int row_shift;
32
33
DECLARE_BITMAP(disabled_gpios, MATRIX_MAX_ROWS);
34
35
uint32_t last_key_state[MATRIX_MAX_COLS];
36
struct delayed_work work;
37
spinlock_t lock;
38
bool scan_pending;
39
bool stopped;
40
bool gpio_all_disabled;
41
};
42
43
/*
44
* NOTE: normally the GPIO has to be put into HiZ when de-activated to cause
45
* minmal side effect when scanning other columns, here it is configured to
46
* be input, and it should work on most platforms.
47
*/
48
static void __activate_col(const struct matrix_keypad_platform_data *pdata,
49
int col, bool on)
50
{
51
bool level_on = !pdata->active_low;
52
53
if (on) {
54
gpio_direction_output(pdata->col_gpios[col], level_on);
55
} else {
56
gpio_set_value_cansleep(pdata->col_gpios[col], !level_on);
57
gpio_direction_input(pdata->col_gpios[col]);
58
}
59
}
60
61
static void activate_col(const struct matrix_keypad_platform_data *pdata,
62
int col, bool on)
63
{
64
__activate_col(pdata, col, on);
65
66
if (on && pdata->col_scan_delay_us)
67
udelay(pdata->col_scan_delay_us);
68
}
69
70
static void activate_all_cols(const struct matrix_keypad_platform_data *pdata,
71
bool on)
72
{
73
int col;
74
75
for (col = 0; col < pdata->num_col_gpios; col++)
76
__activate_col(pdata, col, on);
77
}
78
79
static bool row_asserted(const struct matrix_keypad_platform_data *pdata,
80
int row)
81
{
82
return gpio_get_value_cansleep(pdata->row_gpios[row]) ?
83
!pdata->active_low : pdata->active_low;
84
}
85
86
static void enable_row_irqs(struct matrix_keypad *keypad)
87
{
88
const struct matrix_keypad_platform_data *pdata = keypad->pdata;
89
int i;
90
91
if (pdata->clustered_irq > 0)
92
enable_irq(pdata->clustered_irq);
93
else {
94
for (i = 0; i < pdata->num_row_gpios; i++)
95
enable_irq(gpio_to_irq(pdata->row_gpios[i]));
96
}
97
}
98
99
static void disable_row_irqs(struct matrix_keypad *keypad)
100
{
101
const struct matrix_keypad_platform_data *pdata = keypad->pdata;
102
int i;
103
104
if (pdata->clustered_irq > 0)
105
disable_irq_nosync(pdata->clustered_irq);
106
else {
107
for (i = 0; i < pdata->num_row_gpios; i++)
108
disable_irq_nosync(gpio_to_irq(pdata->row_gpios[i]));
109
}
110
}
111
112
/*
113
* This gets the keys from keyboard and reports it to input subsystem
114
*/
115
static void matrix_keypad_scan(struct work_struct *work)
116
{
117
struct matrix_keypad *keypad =
118
container_of(work, struct matrix_keypad, work.work);
119
struct input_dev *input_dev = keypad->input_dev;
120
const struct matrix_keypad_platform_data *pdata = keypad->pdata;
121
uint32_t new_state[MATRIX_MAX_COLS];
122
int row, col, code;
123
124
/* de-activate all columns for scanning */
125
activate_all_cols(pdata, false);
126
127
memset(new_state, 0, sizeof(new_state));
128
129
/* assert each column and read the row status out */
130
for (col = 0; col < pdata->num_col_gpios; col++) {
131
132
activate_col(pdata, col, true);
133
134
for (row = 0; row < pdata->num_row_gpios; row++)
135
new_state[col] |=
136
row_asserted(pdata, row) ? (1 << row) : 0;
137
138
activate_col(pdata, col, false);
139
}
140
141
for (col = 0; col < pdata->num_col_gpios; col++) {
142
uint32_t bits_changed;
143
144
bits_changed = keypad->last_key_state[col] ^ new_state[col];
145
if (bits_changed == 0)
146
continue;
147
148
for (row = 0; row < pdata->num_row_gpios; row++) {
149
if ((bits_changed & (1 << row)) == 0)
150
continue;
151
152
code = MATRIX_SCAN_CODE(row, col, keypad->row_shift);
153
input_event(input_dev, EV_MSC, MSC_SCAN, code);
154
input_report_key(input_dev,
155
keypad->keycodes[code],
156
new_state[col] & (1 << row));
157
}
158
}
159
input_sync(input_dev);
160
161
memcpy(keypad->last_key_state, new_state, sizeof(new_state));
162
163
activate_all_cols(pdata, true);
164
165
/* Enable IRQs again */
166
spin_lock_irq(&keypad->lock);
167
keypad->scan_pending = false;
168
enable_row_irqs(keypad);
169
spin_unlock_irq(&keypad->lock);
170
}
171
172
static irqreturn_t matrix_keypad_interrupt(int irq, void *id)
173
{
174
struct matrix_keypad *keypad = id;
175
unsigned long flags;
176
177
spin_lock_irqsave(&keypad->lock, flags);
178
179
/*
180
* See if another IRQ beaten us to it and scheduled the
181
* scan already. In that case we should not try to
182
* disable IRQs again.
183
*/
184
if (unlikely(keypad->scan_pending || keypad->stopped))
185
goto out;
186
187
disable_row_irqs(keypad);
188
keypad->scan_pending = true;
189
schedule_delayed_work(&keypad->work,
190
msecs_to_jiffies(keypad->pdata->debounce_ms));
191
192
out:
193
spin_unlock_irqrestore(&keypad->lock, flags);
194
return IRQ_HANDLED;
195
}
196
197
static int matrix_keypad_start(struct input_dev *dev)
198
{
199
struct matrix_keypad *keypad = input_get_drvdata(dev);
200
201
keypad->stopped = false;
202
mb();
203
204
/*
205
* Schedule an immediate key scan to capture current key state;
206
* columns will be activated and IRQs be enabled after the scan.
207
*/
208
schedule_delayed_work(&keypad->work, 0);
209
210
return 0;
211
}
212
213
static void matrix_keypad_stop(struct input_dev *dev)
214
{
215
struct matrix_keypad *keypad = input_get_drvdata(dev);
216
217
keypad->stopped = true;
218
mb();
219
flush_work(&keypad->work.work);
220
/*
221
* matrix_keypad_scan() will leave IRQs enabled;
222
* we should disable them now.
223
*/
224
disable_row_irqs(keypad);
225
}
226
227
#ifdef CONFIG_PM
228
static void matrix_keypad_enable_wakeup(struct matrix_keypad *keypad)
229
{
230
const struct matrix_keypad_platform_data *pdata = keypad->pdata;
231
unsigned int gpio;
232
int i;
233
234
if (pdata->clustered_irq > 0) {
235
if (enable_irq_wake(pdata->clustered_irq) == 0)
236
keypad->gpio_all_disabled = true;
237
} else {
238
239
for (i = 0; i < pdata->num_row_gpios; i++) {
240
if (!test_bit(i, keypad->disabled_gpios)) {
241
gpio = pdata->row_gpios[i];
242
243
if (enable_irq_wake(gpio_to_irq(gpio)) == 0)
244
__set_bit(i, keypad->disabled_gpios);
245
}
246
}
247
}
248
}
249
250
static void matrix_keypad_disable_wakeup(struct matrix_keypad *keypad)
251
{
252
const struct matrix_keypad_platform_data *pdata = keypad->pdata;
253
unsigned int gpio;
254
int i;
255
256
if (pdata->clustered_irq > 0) {
257
if (keypad->gpio_all_disabled) {
258
disable_irq_wake(pdata->clustered_irq);
259
keypad->gpio_all_disabled = false;
260
}
261
} else {
262
for (i = 0; i < pdata->num_row_gpios; i++) {
263
if (test_and_clear_bit(i, keypad->disabled_gpios)) {
264
gpio = pdata->row_gpios[i];
265
disable_irq_wake(gpio_to_irq(gpio));
266
}
267
}
268
}
269
}
270
271
static int matrix_keypad_suspend(struct device *dev)
272
{
273
struct platform_device *pdev = to_platform_device(dev);
274
struct matrix_keypad *keypad = platform_get_drvdata(pdev);
275
276
matrix_keypad_stop(keypad->input_dev);
277
278
if (device_may_wakeup(&pdev->dev))
279
matrix_keypad_enable_wakeup(keypad);
280
281
return 0;
282
}
283
284
static int matrix_keypad_resume(struct device *dev)
285
{
286
struct platform_device *pdev = to_platform_device(dev);
287
struct matrix_keypad *keypad = platform_get_drvdata(pdev);
288
289
if (device_may_wakeup(&pdev->dev))
290
matrix_keypad_disable_wakeup(keypad);
291
292
matrix_keypad_start(keypad->input_dev);
293
294
return 0;
295
}
296
297
static const SIMPLE_DEV_PM_OPS(matrix_keypad_pm_ops,
298
matrix_keypad_suspend, matrix_keypad_resume);
299
#endif
300
301
static int __devinit init_matrix_gpio(struct platform_device *pdev,
302
struct matrix_keypad *keypad)
303
{
304
const struct matrix_keypad_platform_data *pdata = keypad->pdata;
305
int i, err = -EINVAL;
306
307
/* initialized strobe lines as outputs, activated */
308
for (i = 0; i < pdata->num_col_gpios; i++) {
309
err = gpio_request(pdata->col_gpios[i], "matrix_kbd_col");
310
if (err) {
311
dev_err(&pdev->dev,
312
"failed to request GPIO%d for COL%d\n",
313
pdata->col_gpios[i], i);
314
goto err_free_cols;
315
}
316
317
gpio_direction_output(pdata->col_gpios[i], !pdata->active_low);
318
}
319
320
for (i = 0; i < pdata->num_row_gpios; i++) {
321
err = gpio_request(pdata->row_gpios[i], "matrix_kbd_row");
322
if (err) {
323
dev_err(&pdev->dev,
324
"failed to request GPIO%d for ROW%d\n",
325
pdata->row_gpios[i], i);
326
goto err_free_rows;
327
}
328
329
gpio_direction_input(pdata->row_gpios[i]);
330
}
331
332
if (pdata->clustered_irq > 0) {
333
err = request_irq(pdata->clustered_irq,
334
matrix_keypad_interrupt,
335
pdata->clustered_irq_flags,
336
"matrix-keypad", keypad);
337
if (err) {
338
dev_err(&pdev->dev,
339
"Unable to acquire clustered interrupt\n");
340
goto err_free_rows;
341
}
342
} else {
343
for (i = 0; i < pdata->num_row_gpios; i++) {
344
err = request_irq(gpio_to_irq(pdata->row_gpios[i]),
345
matrix_keypad_interrupt,
346
IRQF_DISABLED |
347
IRQF_TRIGGER_RISING |
348
IRQF_TRIGGER_FALLING,
349
"matrix-keypad", keypad);
350
if (err) {
351
dev_err(&pdev->dev,
352
"Unable to acquire interrupt "
353
"for GPIO line %i\n",
354
pdata->row_gpios[i]);
355
goto err_free_irqs;
356
}
357
}
358
}
359
360
/* initialized as disabled - enabled by input->open */
361
disable_row_irqs(keypad);
362
return 0;
363
364
err_free_irqs:
365
while (--i >= 0)
366
free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad);
367
i = pdata->num_row_gpios;
368
err_free_rows:
369
while (--i >= 0)
370
gpio_free(pdata->row_gpios[i]);
371
i = pdata->num_col_gpios;
372
err_free_cols:
373
while (--i >= 0)
374
gpio_free(pdata->col_gpios[i]);
375
376
return err;
377
}
378
379
static int __devinit matrix_keypad_probe(struct platform_device *pdev)
380
{
381
const struct matrix_keypad_platform_data *pdata;
382
const struct matrix_keymap_data *keymap_data;
383
struct matrix_keypad *keypad;
384
struct input_dev *input_dev;
385
unsigned short *keycodes;
386
unsigned int row_shift;
387
int err;
388
389
pdata = pdev->dev.platform_data;
390
if (!pdata) {
391
dev_err(&pdev->dev, "no platform data defined\n");
392
return -EINVAL;
393
}
394
395
keymap_data = pdata->keymap_data;
396
if (!keymap_data) {
397
dev_err(&pdev->dev, "no keymap data defined\n");
398
return -EINVAL;
399
}
400
401
row_shift = get_count_order(pdata->num_col_gpios);
402
403
keypad = kzalloc(sizeof(struct matrix_keypad), GFP_KERNEL);
404
keycodes = kzalloc((pdata->num_row_gpios << row_shift) *
405
sizeof(*keycodes),
406
GFP_KERNEL);
407
input_dev = input_allocate_device();
408
if (!keypad || !keycodes || !input_dev) {
409
err = -ENOMEM;
410
goto err_free_mem;
411
}
412
413
keypad->input_dev = input_dev;
414
keypad->pdata = pdata;
415
keypad->keycodes = keycodes;
416
keypad->row_shift = row_shift;
417
keypad->stopped = true;
418
INIT_DELAYED_WORK(&keypad->work, matrix_keypad_scan);
419
spin_lock_init(&keypad->lock);
420
421
input_dev->name = pdev->name;
422
input_dev->id.bustype = BUS_HOST;
423
input_dev->dev.parent = &pdev->dev;
424
input_dev->evbit[0] = BIT_MASK(EV_KEY);
425
if (!pdata->no_autorepeat)
426
input_dev->evbit[0] |= BIT_MASK(EV_REP);
427
input_dev->open = matrix_keypad_start;
428
input_dev->close = matrix_keypad_stop;
429
430
input_dev->keycode = keycodes;
431
input_dev->keycodesize = sizeof(*keycodes);
432
input_dev->keycodemax = pdata->num_row_gpios << row_shift;
433
434
matrix_keypad_build_keymap(keymap_data, row_shift,
435
input_dev->keycode, input_dev->keybit);
436
437
input_set_capability(input_dev, EV_MSC, MSC_SCAN);
438
input_set_drvdata(input_dev, keypad);
439
440
err = init_matrix_gpio(pdev, keypad);
441
if (err)
442
goto err_free_mem;
443
444
err = input_register_device(keypad->input_dev);
445
if (err)
446
goto err_free_mem;
447
448
device_init_wakeup(&pdev->dev, pdata->wakeup);
449
platform_set_drvdata(pdev, keypad);
450
451
return 0;
452
453
err_free_mem:
454
input_free_device(input_dev);
455
kfree(keycodes);
456
kfree(keypad);
457
return err;
458
}
459
460
static int __devexit matrix_keypad_remove(struct platform_device *pdev)
461
{
462
struct matrix_keypad *keypad = platform_get_drvdata(pdev);
463
const struct matrix_keypad_platform_data *pdata = keypad->pdata;
464
int i;
465
466
device_init_wakeup(&pdev->dev, 0);
467
468
if (pdata->clustered_irq > 0) {
469
free_irq(pdata->clustered_irq, keypad);
470
} else {
471
for (i = 0; i < pdata->num_row_gpios; i++)
472
free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad);
473
}
474
475
for (i = 0; i < pdata->num_row_gpios; i++)
476
gpio_free(pdata->row_gpios[i]);
477
478
for (i = 0; i < pdata->num_col_gpios; i++)
479
gpio_free(pdata->col_gpios[i]);
480
481
input_unregister_device(keypad->input_dev);
482
platform_set_drvdata(pdev, NULL);
483
kfree(keypad->keycodes);
484
kfree(keypad);
485
486
return 0;
487
}
488
489
static struct platform_driver matrix_keypad_driver = {
490
.probe = matrix_keypad_probe,
491
.remove = __devexit_p(matrix_keypad_remove),
492
.driver = {
493
.name = "matrix-keypad",
494
.owner = THIS_MODULE,
495
#ifdef CONFIG_PM
496
.pm = &matrix_keypad_pm_ops,
497
#endif
498
},
499
};
500
501
static int __init matrix_keypad_init(void)
502
{
503
return platform_driver_register(&matrix_keypad_driver);
504
}
505
506
static void __exit matrix_keypad_exit(void)
507
{
508
platform_driver_unregister(&matrix_keypad_driver);
509
}
510
511
module_init(matrix_keypad_init);
512
module_exit(matrix_keypad_exit);
513
514
MODULE_AUTHOR("Marek Vasut <[email protected]>");
515
MODULE_DESCRIPTION("GPIO Driven Matrix Keypad Driver");
516
MODULE_LICENSE("GPL v2");
517
MODULE_ALIAS("platform:matrix-keypad");
518
519