Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/input/keyboard/imx_keypad.c
15109 views
1
/*
2
* Driver for the IMX keypad port.
3
* Copyright (C) 2009 Alberto Panizzo <[email protected]>
4
*
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License version 2 as
7
* published by the Free Software Foundation.
8
*
9
* <<Power management needs to be implemented>>.
10
*/
11
12
#include <linux/clk.h>
13
#include <linux/delay.h>
14
#include <linux/device.h>
15
#include <linux/err.h>
16
#include <linux/init.h>
17
#include <linux/input/matrix_keypad.h>
18
#include <linux/interrupt.h>
19
#include <linux/io.h>
20
#include <linux/jiffies.h>
21
#include <linux/kernel.h>
22
#include <linux/module.h>
23
#include <linux/platform_device.h>
24
#include <linux/slab.h>
25
#include <linux/timer.h>
26
27
/*
28
* Keypad Controller registers (halfword)
29
*/
30
#define KPCR 0x00 /* Keypad Control Register */
31
32
#define KPSR 0x02 /* Keypad Status Register */
33
#define KBD_STAT_KPKD (0x1 << 0) /* Key Press Interrupt Status bit (w1c) */
34
#define KBD_STAT_KPKR (0x1 << 1) /* Key Release Interrupt Status bit (w1c) */
35
#define KBD_STAT_KDSC (0x1 << 2) /* Key Depress Synch Chain Status bit (w1c)*/
36
#define KBD_STAT_KRSS (0x1 << 3) /* Key Release Synch Status bit (w1c)*/
37
#define KBD_STAT_KDIE (0x1 << 8) /* Key Depress Interrupt Enable Status bit */
38
#define KBD_STAT_KRIE (0x1 << 9) /* Key Release Interrupt Enable */
39
#define KBD_STAT_KPPEN (0x1 << 10) /* Keypad Clock Enable */
40
41
#define KDDR 0x04 /* Keypad Data Direction Register */
42
#define KPDR 0x06 /* Keypad Data Register */
43
44
#define MAX_MATRIX_KEY_ROWS 8
45
#define MAX_MATRIX_KEY_COLS 8
46
#define MATRIX_ROW_SHIFT 3
47
48
#define MAX_MATRIX_KEY_NUM (MAX_MATRIX_KEY_ROWS * MAX_MATRIX_KEY_COLS)
49
50
struct imx_keypad {
51
52
struct clk *clk;
53
struct input_dev *input_dev;
54
void __iomem *mmio_base;
55
56
int irq;
57
struct timer_list check_matrix_timer;
58
59
/*
60
* The matrix is stable only if no changes are detected after
61
* IMX_KEYPAD_SCANS_FOR_STABILITY scans
62
*/
63
#define IMX_KEYPAD_SCANS_FOR_STABILITY 3
64
int stable_count;
65
66
bool enabled;
67
68
/* Masks for enabled rows/cols */
69
unsigned short rows_en_mask;
70
unsigned short cols_en_mask;
71
72
unsigned short keycodes[MAX_MATRIX_KEY_NUM];
73
74
/*
75
* Matrix states:
76
* -stable: achieved after a complete debounce process.
77
* -unstable: used in the debouncing process.
78
*/
79
unsigned short matrix_stable_state[MAX_MATRIX_KEY_COLS];
80
unsigned short matrix_unstable_state[MAX_MATRIX_KEY_COLS];
81
};
82
83
/* Scan the matrix and return the new state in *matrix_volatile_state. */
84
static void imx_keypad_scan_matrix(struct imx_keypad *keypad,
85
unsigned short *matrix_volatile_state)
86
{
87
int col;
88
unsigned short reg_val;
89
90
for (col = 0; col < MAX_MATRIX_KEY_COLS; col++) {
91
if ((keypad->cols_en_mask & (1 << col)) == 0)
92
continue;
93
/*
94
* Discharge keypad capacitance:
95
* 2. write 1s on column data.
96
* 3. configure columns as totem-pole to discharge capacitance.
97
* 4. configure columns as open-drain.
98
*/
99
reg_val = readw(keypad->mmio_base + KPDR);
100
reg_val |= 0xff00;
101
writew(reg_val, keypad->mmio_base + KPDR);
102
103
reg_val = readw(keypad->mmio_base + KPCR);
104
reg_val &= ~((keypad->cols_en_mask & 0xff) << 8);
105
writew(reg_val, keypad->mmio_base + KPCR);
106
107
udelay(2);
108
109
reg_val = readw(keypad->mmio_base + KPCR);
110
reg_val |= (keypad->cols_en_mask & 0xff) << 8;
111
writew(reg_val, keypad->mmio_base + KPCR);
112
113
/*
114
* 5. Write a single column to 0, others to 1.
115
* 6. Sample row inputs and save data.
116
* 7. Repeat steps 2 - 6 for remaining columns.
117
*/
118
reg_val = readw(keypad->mmio_base + KPDR);
119
reg_val &= ~(1 << (8 + col));
120
writew(reg_val, keypad->mmio_base + KPDR);
121
122
/*
123
* Delay added to avoid propagating the 0 from column to row
124
* when scanning.
125
*/
126
udelay(5);
127
128
/*
129
* 1s in matrix_volatile_state[col] means key pressures
130
* throw data from non enabled rows.
131
*/
132
reg_val = readw(keypad->mmio_base + KPDR);
133
matrix_volatile_state[col] = (~reg_val) & keypad->rows_en_mask;
134
}
135
136
/*
137
* Return in standby mode:
138
* 9. write 0s to columns
139
*/
140
reg_val = readw(keypad->mmio_base + KPDR);
141
reg_val &= 0x00ff;
142
writew(reg_val, keypad->mmio_base + KPDR);
143
}
144
145
/*
146
* Compare the new matrix state (volatile) with the stable one stored in
147
* keypad->matrix_stable_state and fire events if changes are detected.
148
*/
149
static void imx_keypad_fire_events(struct imx_keypad *keypad,
150
unsigned short *matrix_volatile_state)
151
{
152
struct input_dev *input_dev = keypad->input_dev;
153
int row, col;
154
155
for (col = 0; col < MAX_MATRIX_KEY_COLS; col++) {
156
unsigned short bits_changed;
157
int code;
158
159
if ((keypad->cols_en_mask & (1 << col)) == 0)
160
continue; /* Column is not enabled */
161
162
bits_changed = keypad->matrix_stable_state[col] ^
163
matrix_volatile_state[col];
164
165
if (bits_changed == 0)
166
continue; /* Column does not contain changes */
167
168
for (row = 0; row < MAX_MATRIX_KEY_ROWS; row++) {
169
if ((keypad->rows_en_mask & (1 << row)) == 0)
170
continue; /* Row is not enabled */
171
if ((bits_changed & (1 << row)) == 0)
172
continue; /* Row does not contain changes */
173
174
code = MATRIX_SCAN_CODE(row, col, MATRIX_ROW_SHIFT);
175
input_event(input_dev, EV_MSC, MSC_SCAN, code);
176
input_report_key(input_dev, keypad->keycodes[code],
177
matrix_volatile_state[col] & (1 << row));
178
dev_dbg(&input_dev->dev, "Event code: %d, val: %d",
179
keypad->keycodes[code],
180
matrix_volatile_state[col] & (1 << row));
181
}
182
}
183
input_sync(input_dev);
184
}
185
186
/*
187
* imx_keypad_check_for_events is the timer handler.
188
*/
189
static void imx_keypad_check_for_events(unsigned long data)
190
{
191
struct imx_keypad *keypad = (struct imx_keypad *) data;
192
unsigned short matrix_volatile_state[MAX_MATRIX_KEY_COLS];
193
unsigned short reg_val;
194
bool state_changed, is_zero_matrix;
195
int i;
196
197
memset(matrix_volatile_state, 0, sizeof(matrix_volatile_state));
198
199
imx_keypad_scan_matrix(keypad, matrix_volatile_state);
200
201
state_changed = false;
202
for (i = 0; i < MAX_MATRIX_KEY_COLS; i++) {
203
if ((keypad->cols_en_mask & (1 << i)) == 0)
204
continue;
205
206
if (keypad->matrix_unstable_state[i] ^ matrix_volatile_state[i]) {
207
state_changed = true;
208
break;
209
}
210
}
211
212
/*
213
* If the matrix state is changed from the previous scan
214
* (Re)Begin the debouncing process, saving the new state in
215
* keypad->matrix_unstable_state.
216
* else
217
* Increase the count of number of scans with a stable state.
218
*/
219
if (state_changed) {
220
memcpy(keypad->matrix_unstable_state, matrix_volatile_state,
221
sizeof(matrix_volatile_state));
222
keypad->stable_count = 0;
223
} else
224
keypad->stable_count++;
225
226
/*
227
* If the matrix is not as stable as we want reschedule scan
228
* in the near future.
229
*/
230
if (keypad->stable_count < IMX_KEYPAD_SCANS_FOR_STABILITY) {
231
mod_timer(&keypad->check_matrix_timer,
232
jiffies + msecs_to_jiffies(10));
233
return;
234
}
235
236
/*
237
* If the matrix state is stable, fire the events and save the new
238
* stable state. Note, if the matrix is kept stable for longer
239
* (keypad->stable_count > IMX_KEYPAD_SCANS_FOR_STABILITY) all
240
* events have already been generated.
241
*/
242
if (keypad->stable_count == IMX_KEYPAD_SCANS_FOR_STABILITY) {
243
imx_keypad_fire_events(keypad, matrix_volatile_state);
244
245
memcpy(keypad->matrix_stable_state, matrix_volatile_state,
246
sizeof(matrix_volatile_state));
247
}
248
249
is_zero_matrix = true;
250
for (i = 0; i < MAX_MATRIX_KEY_COLS; i++) {
251
if (matrix_volatile_state[i] != 0) {
252
is_zero_matrix = false;
253
break;
254
}
255
}
256
257
258
if (is_zero_matrix) {
259
/*
260
* All keys have been released. Enable only the KDI
261
* interrupt for future key presses (clear the KDI
262
* status bit and its sync chain before that).
263
*/
264
reg_val = readw(keypad->mmio_base + KPSR);
265
reg_val |= KBD_STAT_KPKD | KBD_STAT_KDSC;
266
writew(reg_val, keypad->mmio_base + KPSR);
267
268
reg_val = readw(keypad->mmio_base + KPSR);
269
reg_val |= KBD_STAT_KDIE;
270
reg_val &= ~KBD_STAT_KRIE;
271
writew(reg_val, keypad->mmio_base + KPSR);
272
} else {
273
/*
274
* Some keys are still pressed. Schedule a rescan in
275
* attempt to detect multiple key presses and enable
276
* the KRI interrupt to react quickly to key release
277
* event.
278
*/
279
mod_timer(&keypad->check_matrix_timer,
280
jiffies + msecs_to_jiffies(60));
281
282
reg_val = readw(keypad->mmio_base + KPSR);
283
reg_val |= KBD_STAT_KPKR | KBD_STAT_KRSS;
284
writew(reg_val, keypad->mmio_base + KPSR);
285
286
reg_val = readw(keypad->mmio_base + KPSR);
287
reg_val |= KBD_STAT_KRIE;
288
reg_val &= ~KBD_STAT_KDIE;
289
writew(reg_val, keypad->mmio_base + KPSR);
290
}
291
}
292
293
static irqreturn_t imx_keypad_irq_handler(int irq, void *dev_id)
294
{
295
struct imx_keypad *keypad = dev_id;
296
unsigned short reg_val;
297
298
reg_val = readw(keypad->mmio_base + KPSR);
299
300
/* Disable both interrupt types */
301
reg_val &= ~(KBD_STAT_KRIE | KBD_STAT_KDIE);
302
/* Clear interrupts status bits */
303
reg_val |= KBD_STAT_KPKR | KBD_STAT_KPKD;
304
writew(reg_val, keypad->mmio_base + KPSR);
305
306
if (keypad->enabled) {
307
/* The matrix is supposed to be changed */
308
keypad->stable_count = 0;
309
310
/* Schedule the scanning procedure near in the future */
311
mod_timer(&keypad->check_matrix_timer,
312
jiffies + msecs_to_jiffies(2));
313
}
314
315
return IRQ_HANDLED;
316
}
317
318
static void imx_keypad_config(struct imx_keypad *keypad)
319
{
320
unsigned short reg_val;
321
322
/*
323
* Include enabled rows in interrupt generation (KPCR[7:0])
324
* Configure keypad columns as open-drain (KPCR[15:8])
325
*/
326
reg_val = readw(keypad->mmio_base + KPCR);
327
reg_val |= keypad->rows_en_mask & 0xff; /* rows */
328
reg_val |= (keypad->cols_en_mask & 0xff) << 8; /* cols */
329
writew(reg_val, keypad->mmio_base + KPCR);
330
331
/* Write 0's to KPDR[15:8] (Colums) */
332
reg_val = readw(keypad->mmio_base + KPDR);
333
reg_val &= 0x00ff;
334
writew(reg_val, keypad->mmio_base + KPDR);
335
336
/* Configure columns as output, rows as input (KDDR[15:0]) */
337
writew(0xff00, keypad->mmio_base + KDDR);
338
339
/*
340
* Clear Key Depress and Key Release status bit.
341
* Clear both synchronizer chain.
342
*/
343
reg_val = readw(keypad->mmio_base + KPSR);
344
reg_val |= KBD_STAT_KPKR | KBD_STAT_KPKD |
345
KBD_STAT_KDSC | KBD_STAT_KRSS;
346
writew(reg_val, keypad->mmio_base + KPSR);
347
348
/* Enable KDI and disable KRI (avoid false release events). */
349
reg_val |= KBD_STAT_KDIE;
350
reg_val &= ~KBD_STAT_KRIE;
351
writew(reg_val, keypad->mmio_base + KPSR);
352
}
353
354
static void imx_keypad_inhibit(struct imx_keypad *keypad)
355
{
356
unsigned short reg_val;
357
358
/* Inhibit KDI and KRI interrupts. */
359
reg_val = readw(keypad->mmio_base + KPSR);
360
reg_val &= ~(KBD_STAT_KRIE | KBD_STAT_KDIE);
361
writew(reg_val, keypad->mmio_base + KPSR);
362
363
/* Colums as open drain and disable all rows */
364
writew(0xff00, keypad->mmio_base + KPCR);
365
}
366
367
static void imx_keypad_close(struct input_dev *dev)
368
{
369
struct imx_keypad *keypad = input_get_drvdata(dev);
370
371
dev_dbg(&dev->dev, ">%s\n", __func__);
372
373
/* Mark keypad as being inactive */
374
keypad->enabled = false;
375
synchronize_irq(keypad->irq);
376
del_timer_sync(&keypad->check_matrix_timer);
377
378
imx_keypad_inhibit(keypad);
379
380
/* Disable clock unit */
381
clk_disable(keypad->clk);
382
}
383
384
static int imx_keypad_open(struct input_dev *dev)
385
{
386
struct imx_keypad *keypad = input_get_drvdata(dev);
387
388
dev_dbg(&dev->dev, ">%s\n", __func__);
389
390
/* We became active from now */
391
keypad->enabled = true;
392
393
/* Enable the kpp clock */
394
clk_enable(keypad->clk);
395
imx_keypad_config(keypad);
396
397
/* Sanity control, not all the rows must be actived now. */
398
if ((readw(keypad->mmio_base + KPDR) & keypad->rows_en_mask) == 0) {
399
dev_err(&dev->dev,
400
"too many keys pressed, control pins initialisation\n");
401
goto open_err;
402
}
403
404
return 0;
405
406
open_err:
407
imx_keypad_close(dev);
408
return -EIO;
409
}
410
411
static int __devinit imx_keypad_probe(struct platform_device *pdev)
412
{
413
const struct matrix_keymap_data *keymap_data = pdev->dev.platform_data;
414
struct imx_keypad *keypad;
415
struct input_dev *input_dev;
416
struct resource *res;
417
int irq, error, i;
418
419
if (keymap_data == NULL) {
420
dev_err(&pdev->dev, "no keymap defined\n");
421
return -EINVAL;
422
}
423
424
irq = platform_get_irq(pdev, 0);
425
if (irq < 0) {
426
dev_err(&pdev->dev, "no irq defined in platform data\n");
427
return -EINVAL;
428
}
429
430
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
431
if (res == NULL) {
432
dev_err(&pdev->dev, "no I/O memory defined in platform data\n");
433
return -EINVAL;
434
}
435
436
res = request_mem_region(res->start, resource_size(res), pdev->name);
437
if (res == NULL) {
438
dev_err(&pdev->dev, "failed to request I/O memory\n");
439
return -EBUSY;
440
}
441
442
input_dev = input_allocate_device();
443
if (!input_dev) {
444
dev_err(&pdev->dev, "failed to allocate the input device\n");
445
error = -ENOMEM;
446
goto failed_rel_mem;
447
}
448
449
keypad = kzalloc(sizeof(struct imx_keypad), GFP_KERNEL);
450
if (!keypad) {
451
dev_err(&pdev->dev, "not enough memory for driver data\n");
452
error = -ENOMEM;
453
goto failed_free_input;
454
}
455
456
keypad->input_dev = input_dev;
457
keypad->irq = irq;
458
keypad->stable_count = 0;
459
460
setup_timer(&keypad->check_matrix_timer,
461
imx_keypad_check_for_events, (unsigned long) keypad);
462
463
keypad->mmio_base = ioremap(res->start, resource_size(res));
464
if (keypad->mmio_base == NULL) {
465
dev_err(&pdev->dev, "failed to remap I/O memory\n");
466
error = -ENOMEM;
467
goto failed_free_priv;
468
}
469
470
keypad->clk = clk_get(&pdev->dev, "kpp");
471
if (IS_ERR(keypad->clk)) {
472
dev_err(&pdev->dev, "failed to get keypad clock\n");
473
error = PTR_ERR(keypad->clk);
474
goto failed_unmap;
475
}
476
477
/* Search for rows and cols enabled */
478
for (i = 0; i < keymap_data->keymap_size; i++) {
479
keypad->rows_en_mask |= 1 << KEY_ROW(keymap_data->keymap[i]);
480
keypad->cols_en_mask |= 1 << KEY_COL(keymap_data->keymap[i]);
481
}
482
483
if (keypad->rows_en_mask > ((1 << MAX_MATRIX_KEY_ROWS) - 1) ||
484
keypad->cols_en_mask > ((1 << MAX_MATRIX_KEY_COLS) - 1)) {
485
dev_err(&pdev->dev,
486
"invalid key data (too many rows or colums)\n");
487
error = -EINVAL;
488
goto failed_clock_put;
489
}
490
dev_dbg(&pdev->dev, "enabled rows mask: %x\n", keypad->rows_en_mask);
491
dev_dbg(&pdev->dev, "enabled cols mask: %x\n", keypad->cols_en_mask);
492
493
/* Init the Input device */
494
input_dev->name = pdev->name;
495
input_dev->id.bustype = BUS_HOST;
496
input_dev->dev.parent = &pdev->dev;
497
input_dev->open = imx_keypad_open;
498
input_dev->close = imx_keypad_close;
499
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
500
input_dev->keycode = keypad->keycodes;
501
input_dev->keycodesize = sizeof(keypad->keycodes[0]);
502
input_dev->keycodemax = ARRAY_SIZE(keypad->keycodes);
503
504
matrix_keypad_build_keymap(keymap_data, MATRIX_ROW_SHIFT,
505
keypad->keycodes, input_dev->keybit);
506
507
input_set_capability(input_dev, EV_MSC, MSC_SCAN);
508
input_set_drvdata(input_dev, keypad);
509
510
/* Ensure that the keypad will stay dormant until opened */
511
imx_keypad_inhibit(keypad);
512
513
error = request_irq(irq, imx_keypad_irq_handler, IRQF_DISABLED,
514
pdev->name, keypad);
515
if (error) {
516
dev_err(&pdev->dev, "failed to request IRQ\n");
517
goto failed_clock_put;
518
}
519
520
/* Register the input device */
521
error = input_register_device(input_dev);
522
if (error) {
523
dev_err(&pdev->dev, "failed to register input device\n");
524
goto failed_free_irq;
525
}
526
527
platform_set_drvdata(pdev, keypad);
528
device_init_wakeup(&pdev->dev, 1);
529
530
return 0;
531
532
failed_free_irq:
533
free_irq(irq, pdev);
534
failed_clock_put:
535
clk_put(keypad->clk);
536
failed_unmap:
537
iounmap(keypad->mmio_base);
538
failed_free_priv:
539
kfree(keypad);
540
failed_free_input:
541
input_free_device(input_dev);
542
failed_rel_mem:
543
release_mem_region(res->start, resource_size(res));
544
return error;
545
}
546
547
static int __devexit imx_keypad_remove(struct platform_device *pdev)
548
{
549
struct imx_keypad *keypad = platform_get_drvdata(pdev);
550
struct resource *res;
551
552
dev_dbg(&pdev->dev, ">%s\n", __func__);
553
554
platform_set_drvdata(pdev, NULL);
555
556
input_unregister_device(keypad->input_dev);
557
558
free_irq(keypad->irq, keypad);
559
clk_put(keypad->clk);
560
561
iounmap(keypad->mmio_base);
562
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
563
release_mem_region(res->start, resource_size(res));
564
565
kfree(keypad);
566
567
return 0;
568
}
569
570
static struct platform_driver imx_keypad_driver = {
571
.driver = {
572
.name = "imx-keypad",
573
.owner = THIS_MODULE,
574
},
575
.probe = imx_keypad_probe,
576
.remove = __devexit_p(imx_keypad_remove),
577
};
578
579
static int __init imx_keypad_init(void)
580
{
581
return platform_driver_register(&imx_keypad_driver);
582
}
583
584
static void __exit imx_keypad_exit(void)
585
{
586
platform_driver_unregister(&imx_keypad_driver);
587
}
588
589
module_init(imx_keypad_init);
590
module_exit(imx_keypad_exit);
591
592
MODULE_AUTHOR("Alberto Panizzo <[email protected]>");
593
MODULE_DESCRIPTION("IMX Keypad Port Driver");
594
MODULE_LICENSE("GPL v2");
595
MODULE_ALIAS("platform:imx-keypad");
596
597