Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/input/keyboard/nomadik-ske-keypad.c
15111 views
1
/*
2
* Copyright (C) ST-Ericsson SA 2010
3
*
4
* Author: Naveen Kumar G <[email protected]> for ST-Ericsson
5
* Author: Sundar Iyer <[email protected]> for ST-Ericsson
6
*
7
* License terms:GNU General Public License (GPL) version 2
8
*
9
* Keypad controller driver for the SKE (Scroll Key Encoder) module used in
10
* the Nomadik 8815 and Ux500 platforms.
11
*/
12
13
#include <linux/platform_device.h>
14
#include <linux/interrupt.h>
15
#include <linux/spinlock.h>
16
#include <linux/io.h>
17
#include <linux/delay.h>
18
#include <linux/input.h>
19
#include <linux/slab.h>
20
#include <linux/clk.h>
21
22
#include <plat/ske.h>
23
24
/* SKE_CR bits */
25
#define SKE_KPMLT (0x1 << 6)
26
#define SKE_KPCN (0x7 << 3)
27
#define SKE_KPASEN (0x1 << 2)
28
#define SKE_KPASON (0x1 << 7)
29
30
/* SKE_IMSC bits */
31
#define SKE_KPIMA (0x1 << 2)
32
33
/* SKE_ICR bits */
34
#define SKE_KPICS (0x1 << 3)
35
#define SKE_KPICA (0x1 << 2)
36
37
/* SKE_RIS bits */
38
#define SKE_KPRISA (0x1 << 2)
39
40
#define SKE_KEYPAD_ROW_SHIFT 3
41
#define SKE_KPD_KEYMAP_SIZE (8 * 8)
42
43
/* keypad auto scan registers */
44
#define SKE_ASR0 0x20
45
#define SKE_ASR1 0x24
46
#define SKE_ASR2 0x28
47
#define SKE_ASR3 0x2C
48
49
#define SKE_NUM_ASRX_REGISTERS (4)
50
51
/**
52
* struct ske_keypad - data structure used by keypad driver
53
* @irq: irq no
54
* @reg_base: ske regsiters base address
55
* @input: pointer to input device object
56
* @board: keypad platform device
57
* @keymap: matrix scan code table for keycodes
58
* @clk: clock structure pointer
59
*/
60
struct ske_keypad {
61
int irq;
62
void __iomem *reg_base;
63
struct input_dev *input;
64
const struct ske_keypad_platform_data *board;
65
unsigned short keymap[SKE_KPD_KEYMAP_SIZE];
66
struct clk *clk;
67
spinlock_t ske_keypad_lock;
68
};
69
70
static void ske_keypad_set_bits(struct ske_keypad *keypad, u16 addr,
71
u8 mask, u8 data)
72
{
73
u32 ret;
74
75
spin_lock(&keypad->ske_keypad_lock);
76
77
ret = readl(keypad->reg_base + addr);
78
ret &= ~mask;
79
ret |= data;
80
writel(ret, keypad->reg_base + addr);
81
82
spin_unlock(&keypad->ske_keypad_lock);
83
}
84
85
/*
86
* ske_keypad_chip_init: init keypad controller configuration
87
*
88
* Enable Multi key press detection, auto scan mode
89
*/
90
static int __devinit ske_keypad_chip_init(struct ske_keypad *keypad)
91
{
92
u32 value;
93
int timeout = 50;
94
95
/* check SKE_RIS to be 0 */
96
while ((readl(keypad->reg_base + SKE_RIS) != 0x00000000) && timeout--)
97
cpu_relax();
98
99
if (!timeout)
100
return -EINVAL;
101
102
/*
103
* set debounce value
104
* keypad dbounce is configured in DBCR[15:8]
105
* dbounce value in steps of 32/32.768 ms
106
*/
107
spin_lock(&keypad->ske_keypad_lock);
108
value = readl(keypad->reg_base + SKE_DBCR);
109
value = value & 0xff;
110
value |= ((keypad->board->debounce_ms * 32000)/32768) << 8;
111
writel(value, keypad->reg_base + SKE_DBCR);
112
spin_unlock(&keypad->ske_keypad_lock);
113
114
/* enable multi key detection */
115
ske_keypad_set_bits(keypad, SKE_CR, 0x0, SKE_KPMLT);
116
117
/*
118
* set up the number of columns
119
* KPCN[5:3] defines no. of keypad columns to be auto scanned
120
*/
121
value = (keypad->board->kcol - 1) << 3;
122
ske_keypad_set_bits(keypad, SKE_CR, SKE_KPCN, value);
123
124
/* clear keypad interrupt for auto(and pending SW) scans */
125
ske_keypad_set_bits(keypad, SKE_ICR, 0x0, SKE_KPICA | SKE_KPICS);
126
127
/* un-mask keypad interrupts */
128
ske_keypad_set_bits(keypad, SKE_IMSC, 0x0, SKE_KPIMA);
129
130
/* enable automatic scan */
131
ske_keypad_set_bits(keypad, SKE_CR, 0x0, SKE_KPASEN);
132
133
return 0;
134
}
135
136
static void ske_keypad_read_data(struct ske_keypad *keypad)
137
{
138
struct input_dev *input = keypad->input;
139
u16 status;
140
int col = 0, row = 0, code;
141
int ske_asr, ske_ris, key_pressed, i;
142
143
/*
144
* Read the auto scan registers
145
*
146
* Each SKE_ASRx (x=0 to x=3) contains two row values.
147
* lower byte contains row value for column 2*x,
148
* upper byte contains row value for column 2*x + 1
149
*/
150
for (i = 0; i < SKE_NUM_ASRX_REGISTERS; i++) {
151
ske_asr = readl(keypad->reg_base + SKE_ASR0 + (4 * i));
152
if (!ske_asr)
153
continue;
154
155
/* now that ASRx is zero, find out the column x and row y*/
156
if (ske_asr & 0xff) {
157
col = i * 2;
158
status = ske_asr & 0xff;
159
} else {
160
col = (i * 2) + 1;
161
status = (ske_asr & 0xff00) >> 8;
162
}
163
164
/* find out the row */
165
row = __ffs(status);
166
167
code = MATRIX_SCAN_CODE(row, col, SKE_KEYPAD_ROW_SHIFT);
168
ske_ris = readl(keypad->reg_base + SKE_RIS);
169
key_pressed = ske_ris & SKE_KPRISA;
170
171
input_event(input, EV_MSC, MSC_SCAN, code);
172
input_report_key(input, keypad->keymap[code], key_pressed);
173
input_sync(input);
174
}
175
}
176
177
static irqreturn_t ske_keypad_irq(int irq, void *dev_id)
178
{
179
struct ske_keypad *keypad = dev_id;
180
int retries = 20;
181
182
/* disable auto scan interrupt; mask the interrupt generated */
183
ske_keypad_set_bits(keypad, SKE_IMSC, ~SKE_KPIMA, 0x0);
184
ske_keypad_set_bits(keypad, SKE_ICR, 0x0, SKE_KPICA);
185
186
while ((readl(keypad->reg_base + SKE_CR) & SKE_KPASON) && --retries)
187
msleep(5);
188
189
if (retries) {
190
/* SKEx registers are stable and can be read */
191
ske_keypad_read_data(keypad);
192
}
193
194
/* enable auto scan interrupts */
195
ske_keypad_set_bits(keypad, SKE_IMSC, 0x0, SKE_KPIMA);
196
197
return IRQ_HANDLED;
198
}
199
200
static int __devinit ske_keypad_probe(struct platform_device *pdev)
201
{
202
const struct ske_keypad_platform_data *plat = pdev->dev.platform_data;
203
struct ske_keypad *keypad;
204
struct input_dev *input;
205
struct resource *res;
206
int irq;
207
int error;
208
209
if (!plat) {
210
dev_err(&pdev->dev, "invalid keypad platform data\n");
211
return -EINVAL;
212
}
213
214
irq = platform_get_irq(pdev, 0);
215
if (irq < 0) {
216
dev_err(&pdev->dev, "failed to get keypad irq\n");
217
return -EINVAL;
218
}
219
220
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
221
if (!res) {
222
dev_err(&pdev->dev, "missing platform resources\n");
223
return -EINVAL;
224
}
225
226
keypad = kzalloc(sizeof(struct ske_keypad), GFP_KERNEL);
227
input = input_allocate_device();
228
if (!keypad || !input) {
229
dev_err(&pdev->dev, "failed to allocate keypad memory\n");
230
error = -ENOMEM;
231
goto err_free_mem;
232
}
233
234
keypad->irq = irq;
235
keypad->board = plat;
236
keypad->input = input;
237
spin_lock_init(&keypad->ske_keypad_lock);
238
239
if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
240
dev_err(&pdev->dev, "failed to request I/O memory\n");
241
error = -EBUSY;
242
goto err_free_mem;
243
}
244
245
keypad->reg_base = ioremap(res->start, resource_size(res));
246
if (!keypad->reg_base) {
247
dev_err(&pdev->dev, "failed to remap I/O memory\n");
248
error = -ENXIO;
249
goto err_free_mem_region;
250
}
251
252
keypad->clk = clk_get(&pdev->dev, NULL);
253
if (IS_ERR(keypad->clk)) {
254
dev_err(&pdev->dev, "failed to get clk\n");
255
error = PTR_ERR(keypad->clk);
256
goto err_iounmap;
257
}
258
259
input->id.bustype = BUS_HOST;
260
input->name = "ux500-ske-keypad";
261
input->dev.parent = &pdev->dev;
262
263
input->keycode = keypad->keymap;
264
input->keycodesize = sizeof(keypad->keymap[0]);
265
input->keycodemax = ARRAY_SIZE(keypad->keymap);
266
267
input_set_capability(input, EV_MSC, MSC_SCAN);
268
269
__set_bit(EV_KEY, input->evbit);
270
if (!plat->no_autorepeat)
271
__set_bit(EV_REP, input->evbit);
272
273
matrix_keypad_build_keymap(plat->keymap_data, SKE_KEYPAD_ROW_SHIFT,
274
input->keycode, input->keybit);
275
276
clk_enable(keypad->clk);
277
278
/* go through board initialization helpers */
279
if (keypad->board->init)
280
keypad->board->init();
281
282
error = ske_keypad_chip_init(keypad);
283
if (error) {
284
dev_err(&pdev->dev, "unable to init keypad hardware\n");
285
goto err_clk_disable;
286
}
287
288
error = request_threaded_irq(keypad->irq, NULL, ske_keypad_irq,
289
IRQF_ONESHOT, "ske-keypad", keypad);
290
if (error) {
291
dev_err(&pdev->dev, "allocate irq %d failed\n", keypad->irq);
292
goto err_clk_disable;
293
}
294
295
error = input_register_device(input);
296
if (error) {
297
dev_err(&pdev->dev,
298
"unable to register input device: %d\n", error);
299
goto err_free_irq;
300
}
301
302
if (plat->wakeup_enable)
303
device_init_wakeup(&pdev->dev, true);
304
305
platform_set_drvdata(pdev, keypad);
306
307
return 0;
308
309
err_free_irq:
310
free_irq(keypad->irq, keypad);
311
err_clk_disable:
312
clk_disable(keypad->clk);
313
clk_put(keypad->clk);
314
err_iounmap:
315
iounmap(keypad->reg_base);
316
err_free_mem_region:
317
release_mem_region(res->start, resource_size(res));
318
err_free_mem:
319
input_free_device(input);
320
kfree(keypad);
321
return error;
322
}
323
324
static int __devexit ske_keypad_remove(struct platform_device *pdev)
325
{
326
struct ske_keypad *keypad = platform_get_drvdata(pdev);
327
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
328
329
free_irq(keypad->irq, keypad);
330
331
input_unregister_device(keypad->input);
332
333
clk_disable(keypad->clk);
334
clk_put(keypad->clk);
335
336
if (keypad->board->exit)
337
keypad->board->exit();
338
339
iounmap(keypad->reg_base);
340
release_mem_region(res->start, resource_size(res));
341
kfree(keypad);
342
343
return 0;
344
}
345
346
#ifdef CONFIG_PM
347
static int ske_keypad_suspend(struct device *dev)
348
{
349
struct platform_device *pdev = to_platform_device(dev);
350
struct ske_keypad *keypad = platform_get_drvdata(pdev);
351
int irq = platform_get_irq(pdev, 0);
352
353
if (device_may_wakeup(dev))
354
enable_irq_wake(irq);
355
else
356
ske_keypad_set_bits(keypad, SKE_IMSC, ~SKE_KPIMA, 0x0);
357
358
return 0;
359
}
360
361
static int ske_keypad_resume(struct device *dev)
362
{
363
struct platform_device *pdev = to_platform_device(dev);
364
struct ske_keypad *keypad = platform_get_drvdata(pdev);
365
int irq = platform_get_irq(pdev, 0);
366
367
if (device_may_wakeup(dev))
368
disable_irq_wake(irq);
369
else
370
ske_keypad_set_bits(keypad, SKE_IMSC, 0x0, SKE_KPIMA);
371
372
return 0;
373
}
374
375
static const struct dev_pm_ops ske_keypad_dev_pm_ops = {
376
.suspend = ske_keypad_suspend,
377
.resume = ske_keypad_resume,
378
};
379
#endif
380
381
struct platform_driver ske_keypad_driver = {
382
.driver = {
383
.name = "nmk-ske-keypad",
384
.owner = THIS_MODULE,
385
#ifdef CONFIG_PM
386
.pm = &ske_keypad_dev_pm_ops,
387
#endif
388
},
389
.probe = ske_keypad_probe,
390
.remove = __devexit_p(ske_keypad_remove),
391
};
392
393
static int __init ske_keypad_init(void)
394
{
395
return platform_driver_probe(&ske_keypad_driver, ske_keypad_probe);
396
}
397
module_init(ske_keypad_init);
398
399
static void __exit ske_keypad_exit(void)
400
{
401
platform_driver_unregister(&ske_keypad_driver);
402
}
403
module_exit(ske_keypad_exit);
404
405
MODULE_LICENSE("GPL v2");
406
MODULE_AUTHOR("Naveen Kumar <[email protected]> / Sundar Iyer <[email protected]>");
407
MODULE_DESCRIPTION("Nomadik Scroll-Key-Encoder Keypad Driver");
408
MODULE_ALIAS("platform:nomadik-ske-keypad");
409
410