OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [input/] [keyboard/] [omap-keypad.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * linux/drivers/input/keyboard/omap-keypad.c
3
 *
4
 * OMAP Keypad Driver
5
 *
6
 * Copyright (C) 2003 Nokia Corporation
7
 * Written by Timo Teräs <ext-timo.teras@nokia.com>
8
 *
9
 * Added support for H2 & H3 Keypad
10
 * Copyright (C) 2004 Texas Instruments
11
 *
12
 * This program is free software; you can redistribute it and/or modify
13
 * it under the terms of the GNU General Public License as published by
14
 * the Free Software Foundation; either version 2 of the License, or
15
 * (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
 * GNU General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU General Public License
23
 * along with this program; if not, write to the Free Software
24
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25
 */
26
 
27
#include <linux/module.h>
28
#include <linux/init.h>
29
#include <linux/interrupt.h>
30
#include <linux/types.h>
31
#include <linux/input.h>
32
#include <linux/kernel.h>
33
#include <linux/delay.h>
34
#include <linux/platform_device.h>
35
#include <linux/mutex.h>
36
#include <linux/errno.h>
37
#include <asm/arch/gpio.h>
38
#include <asm/arch/keypad.h>
39
#include <asm/arch/menelaus.h>
40
#include <asm/irq.h>
41
#include <asm/hardware.h>
42
#include <asm/io.h>
43
#include <asm/mach-types.h>
44
#include <asm/arch/mux.h>
45
 
46
#undef NEW_BOARD_LEARNING_MODE
47
 
48
static void omap_kp_tasklet(unsigned long);
49
static void omap_kp_timer(unsigned long);
50
 
51
static unsigned char keypad_state[8];
52
static DEFINE_MUTEX(kp_enable_mutex);
53
static int kp_enable = 1;
54
static int kp_cur_group = -1;
55
 
56
struct omap_kp {
57
        struct input_dev *input;
58
        struct timer_list timer;
59
        int irq;
60
        unsigned int rows;
61
        unsigned int cols;
62
        unsigned long delay;
63
        unsigned int debounce;
64
};
65
 
66
DECLARE_TASKLET_DISABLED(kp_tasklet, omap_kp_tasklet, 0);
67
 
68
static int *keymap;
69
static unsigned int *row_gpios;
70
static unsigned int *col_gpios;
71
 
72
#ifdef CONFIG_ARCH_OMAP2
73
static void set_col_gpio_val(struct omap_kp *omap_kp, u8 value)
74
{
75
        int col;
76
        for (col = 0; col < omap_kp->cols; col++) {
77
                if (value & (1 << col))
78
                        omap_set_gpio_dataout(col_gpios[col], 1);
79
                else
80
                        omap_set_gpio_dataout(col_gpios[col], 0);
81
        }
82
}
83
 
84
static u8 get_row_gpio_val(struct omap_kp *omap_kp)
85
{
86
        int row;
87
        u8 value = 0;
88
 
89
        for (row = 0; row < omap_kp->rows; row++) {
90
                if (omap_get_gpio_datain(row_gpios[row]))
91
                        value |= (1 << row);
92
        }
93
        return value;
94
}
95
#else
96
#define         set_col_gpio_val(x, y)  do {} while (0)
97
#define         get_row_gpio_val(x)     0
98
#endif
99
 
100
static irqreturn_t omap_kp_interrupt(int irq, void *dev_id)
101
{
102
        struct omap_kp *omap_kp = dev_id;
103
 
104
        /* disable keyboard interrupt and schedule for handling */
105
        if (cpu_is_omap24xx()) {
106
                int i;
107
                for (i = 0; i < omap_kp->rows; i++)
108
                        disable_irq(OMAP_GPIO_IRQ(row_gpios[i]));
109
        } else
110
                /* disable keyboard interrupt and schedule for handling */
111
                omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
112
 
113
        tasklet_schedule(&kp_tasklet);
114
 
115
        return IRQ_HANDLED;
116
}
117
 
118
static void omap_kp_timer(unsigned long data)
119
{
120
        tasklet_schedule(&kp_tasklet);
121
}
122
 
123
static void omap_kp_scan_keypad(struct omap_kp *omap_kp, unsigned char *state)
124
{
125
        int col = 0;
126
 
127
        /* read the keypad status */
128
        if (cpu_is_omap24xx()) {
129
                int i;
130
                for (i = 0; i < omap_kp->rows; i++)
131
                        disable_irq(OMAP_GPIO_IRQ(row_gpios[i]));
132
 
133
                /* read the keypad status */
134
                for (col = 0; col < omap_kp->cols; col++) {
135
                        set_col_gpio_val(omap_kp, ~(1 << col));
136
                        state[col] = ~(get_row_gpio_val(omap_kp)) & 0x3f;
137
                }
138
                set_col_gpio_val(omap_kp, 0);
139
 
140
        } else {
141
                /* disable keyboard interrupt and schedule for handling */
142
                omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
143
 
144
                /* read the keypad status */
145
                omap_writew(0xff, OMAP_MPUIO_BASE + OMAP_MPUIO_KBC);
146
                for (col = 0; col < omap_kp->cols; col++) {
147
                        omap_writew(~(1 << col) & 0xff,
148
                                    OMAP_MPUIO_BASE + OMAP_MPUIO_KBC);
149
 
150
                        udelay(omap_kp->delay);
151
 
152
                        state[col] = ~omap_readw(OMAP_MPUIO_BASE +
153
                                                 OMAP_MPUIO_KBR_LATCH) & 0xff;
154
                }
155
                omap_writew(0x00, OMAP_MPUIO_BASE + OMAP_MPUIO_KBC);
156
                udelay(2);
157
        }
158
}
159
 
160
static inline int omap_kp_find_key(int col, int row)
161
{
162
        int i, key;
163
 
164
        key = KEY(col, row, 0);
165
        for (i = 0; keymap[i] != 0; i++)
166
                if ((keymap[i] & 0xff000000) == key)
167
                        return keymap[i] & 0x00ffffff;
168
        return -1;
169
}
170
 
171
static void omap_kp_tasklet(unsigned long data)
172
{
173
        struct omap_kp *omap_kp_data = (struct omap_kp *) data;
174
        unsigned char new_state[8], changed, key_down = 0;
175
        int col, row;
176
        int spurious = 0;
177
 
178
        /* check for any changes */
179
        omap_kp_scan_keypad(omap_kp_data, new_state);
180
 
181
        /* check for changes and print those */
182
        for (col = 0; col < omap_kp_data->cols; col++) {
183
                changed = new_state[col] ^ keypad_state[col];
184
                key_down |= new_state[col];
185
                if (changed == 0)
186
                        continue;
187
 
188
                for (row = 0; row < omap_kp_data->rows; row++) {
189
                        int key;
190
                        if (!(changed & (1 << row)))
191
                                continue;
192
#ifdef NEW_BOARD_LEARNING_MODE
193
                        printk(KERN_INFO "omap-keypad: key %d-%d %s\n", col,
194
                               row, (new_state[col] & (1 << row)) ?
195
                               "pressed" : "released");
196
#else
197
                        key = omap_kp_find_key(col, row);
198
                        if (key < 0) {
199
                                printk(KERN_WARNING
200
                                      "omap-keypad: Spurious key event %d-%d\n",
201
                                       col, row);
202
                                /* We scan again after a couple of seconds */
203
                                spurious = 1;
204
                                continue;
205
                        }
206
 
207
                        if (!(kp_cur_group == (key & GROUP_MASK) ||
208
                              kp_cur_group == -1))
209
                                continue;
210
 
211
                        kp_cur_group = key & GROUP_MASK;
212
                        input_report_key(omap_kp_data->input, key & ~GROUP_MASK,
213
                                         new_state[col] & (1 << row));
214
#endif
215
                }
216
        }
217
        memcpy(keypad_state, new_state, sizeof(keypad_state));
218
 
219
        if (key_down) {
220
                int delay = HZ / 20;
221
                /* some key is pressed - keep irq disabled and use timer
222
                 * to poll the keypad */
223
                if (spurious)
224
                        delay = 2 * HZ;
225
                mod_timer(&omap_kp_data->timer, jiffies + delay);
226
        } else {
227
                /* enable interrupts */
228
                if (cpu_is_omap24xx()) {
229
                        int i;
230
                        for (i = 0; i < omap_kp_data->rows; i++)
231
                                enable_irq(OMAP_GPIO_IRQ(row_gpios[i]));
232
                } else {
233
                        omap_writew(0, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
234
                        kp_cur_group = -1;
235
                }
236
        }
237
}
238
 
239
static ssize_t omap_kp_enable_show(struct device *dev,
240
                                   struct device_attribute *attr, char *buf)
241
{
242
        return sprintf(buf, "%u\n", kp_enable);
243
}
244
 
245
static ssize_t omap_kp_enable_store(struct device *dev, struct device_attribute *attr,
246
                                    const char *buf, size_t count)
247
{
248
        int state;
249
 
250
        if (sscanf(buf, "%u", &state) != 1)
251
                return -EINVAL;
252
 
253
        if ((state != 1) && (state != 0))
254
                return -EINVAL;
255
 
256
        mutex_lock(&kp_enable_mutex);
257
        if (state != kp_enable) {
258
                if (state)
259
                        enable_irq(INT_KEYBOARD);
260
                else
261
                        disable_irq(INT_KEYBOARD);
262
                kp_enable = state;
263
        }
264
        mutex_unlock(&kp_enable_mutex);
265
 
266
        return strnlen(buf, count);
267
}
268
 
269
static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, omap_kp_enable_show, omap_kp_enable_store);
270
 
271
#ifdef CONFIG_PM
272
static int omap_kp_suspend(struct platform_device *dev, pm_message_t state)
273
{
274
        /* Nothing yet */
275
 
276
        return 0;
277
}
278
 
279
static int omap_kp_resume(struct platform_device *dev)
280
{
281
        /* Nothing yet */
282
 
283
        return 0;
284
}
285
#else
286
#define omap_kp_suspend NULL
287
#define omap_kp_resume  NULL
288
#endif
289
 
290
static int __init omap_kp_probe(struct platform_device *pdev)
291
{
292
        struct omap_kp *omap_kp;
293
        struct input_dev *input_dev;
294
        struct omap_kp_platform_data *pdata =  pdev->dev.platform_data;
295
        int i, col_idx, row_idx, irq_idx, ret;
296
 
297
        if (!pdata->rows || !pdata->cols || !pdata->keymap) {
298
                printk(KERN_ERR "No rows, cols or keymap from pdata\n");
299
                return -EINVAL;
300
        }
301
 
302
        omap_kp = kzalloc(sizeof(struct omap_kp), GFP_KERNEL);
303
        input_dev = input_allocate_device();
304
        if (!omap_kp || !input_dev) {
305
                kfree(omap_kp);
306
                input_free_device(input_dev);
307
                return -ENOMEM;
308
        }
309
 
310
        platform_set_drvdata(pdev, omap_kp);
311
 
312
        omap_kp->input = input_dev;
313
 
314
        /* Disable the interrupt for the MPUIO keyboard */
315
        if (!cpu_is_omap24xx())
316
                omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
317
 
318
        keymap = pdata->keymap;
319
 
320
        if (pdata->rep)
321
                __set_bit(EV_REP, input_dev->evbit);
322
 
323
        if (pdata->delay)
324
                omap_kp->delay = pdata->delay;
325
 
326
        if (pdata->row_gpios && pdata->col_gpios) {
327
                row_gpios = pdata->row_gpios;
328
                col_gpios = pdata->col_gpios;
329
        }
330
 
331
        omap_kp->rows = pdata->rows;
332
        omap_kp->cols = pdata->cols;
333
 
334
        if (cpu_is_omap24xx()) {
335
                /* Cols: outputs */
336
                for (col_idx = 0; col_idx < omap_kp->cols; col_idx++) {
337
                        if (omap_request_gpio(col_gpios[col_idx]) < 0) {
338
                                printk(KERN_ERR "Failed to request"
339
                                       "GPIO%d for keypad\n",
340
                                       col_gpios[col_idx]);
341
                                goto err1;
342
                        }
343
                        omap_set_gpio_direction(col_gpios[col_idx], 0);
344
                }
345
                /* Rows: inputs */
346
                for (row_idx = 0; row_idx < omap_kp->rows; row_idx++) {
347
                        if (omap_request_gpio(row_gpios[row_idx]) < 0) {
348
                                printk(KERN_ERR "Failed to request"
349
                                       "GPIO%d for keypad\n",
350
                                       row_gpios[row_idx]);
351
                                goto err2;
352
                        }
353
                        omap_set_gpio_direction(row_gpios[row_idx], 1);
354
                }
355
        }
356
 
357
        setup_timer(&omap_kp->timer, omap_kp_timer, (unsigned long)omap_kp);
358
 
359
        /* get the irq and init timer*/
360
        tasklet_enable(&kp_tasklet);
361
        kp_tasklet.data = (unsigned long) omap_kp;
362
 
363
        ret = device_create_file(&pdev->dev, &dev_attr_enable);
364
        if (ret < 0)
365
                goto err2;
366
 
367
        /* setup input device */
368
        __set_bit(EV_KEY, input_dev->evbit);
369
        for (i = 0; keymap[i] != 0; i++)
370
                __set_bit(keymap[i] & KEY_MAX, input_dev->keybit);
371
        input_dev->name = "omap-keypad";
372
        input_dev->phys = "omap-keypad/input0";
373
        input_dev->dev.parent = &pdev->dev;
374
 
375
        input_dev->id.bustype = BUS_HOST;
376
        input_dev->id.vendor = 0x0001;
377
        input_dev->id.product = 0x0001;
378
        input_dev->id.version = 0x0100;
379
 
380
        ret = input_register_device(omap_kp->input);
381
        if (ret < 0) {
382
                printk(KERN_ERR "Unable to register omap-keypad input device\n");
383
                goto err3;
384
        }
385
 
386
        if (pdata->dbounce)
387
                omap_writew(0xff, OMAP_MPUIO_BASE + OMAP_MPUIO_GPIO_DEBOUNCING);
388
 
389
        /* scan current status and enable interrupt */
390
        omap_kp_scan_keypad(omap_kp, keypad_state);
391
        if (!cpu_is_omap24xx()) {
392
                omap_kp->irq = platform_get_irq(pdev, 0);
393
                if (omap_kp->irq >= 0) {
394
                        if (request_irq(omap_kp->irq, omap_kp_interrupt, 0,
395
                                        "omap-keypad", omap_kp) < 0)
396
                                goto err4;
397
                }
398
                omap_writew(0, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
399
        } else {
400
                for (irq_idx = 0; irq_idx < omap_kp->rows; irq_idx++) {
401
                        if (request_irq(OMAP_GPIO_IRQ(row_gpios[irq_idx]),
402
                                        omap_kp_interrupt,
403
                                        IRQF_TRIGGER_FALLING,
404
                                        "omap-keypad", omap_kp) < 0)
405
                                goto err5;
406
                }
407
        }
408
        return 0;
409
err5:
410
        for (i = irq_idx - 1; i >=0; i--)
411
                free_irq(row_gpios[i], 0);
412
err4:
413
        input_unregister_device(omap_kp->input);
414
        input_dev = NULL;
415
err3:
416
        device_remove_file(&pdev->dev, &dev_attr_enable);
417
err2:
418
        for (i = row_idx-1; i >=0; i--)
419
                omap_free_gpio(row_gpios[i]);
420
err1:
421
        for (i = col_idx-1; i >=0; i--)
422
                omap_free_gpio(col_gpios[i]);
423
 
424
        kfree(omap_kp);
425
        input_free_device(input_dev);
426
 
427
        return -EINVAL;
428
}
429
 
430
static int omap_kp_remove(struct platform_device *pdev)
431
{
432
        struct omap_kp *omap_kp = platform_get_drvdata(pdev);
433
 
434
        /* disable keypad interrupt handling */
435
        tasklet_disable(&kp_tasklet);
436
        if (cpu_is_omap24xx()) {
437
                int i;
438
                for (i = 0; i < omap_kp->cols; i++)
439
                        omap_free_gpio(col_gpios[i]);
440
                for (i = 0; i < omap_kp->rows; i++) {
441
                        omap_free_gpio(row_gpios[i]);
442
                        free_irq(OMAP_GPIO_IRQ(row_gpios[i]), 0);
443
                }
444
        } else {
445
                omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
446
                free_irq(omap_kp->irq, 0);
447
        }
448
 
449
        del_timer_sync(&omap_kp->timer);
450
        tasklet_kill(&kp_tasklet);
451
 
452
        /* unregister everything */
453
        input_unregister_device(omap_kp->input);
454
 
455
        kfree(omap_kp);
456
 
457
        return 0;
458
}
459
 
460
static struct platform_driver omap_kp_driver = {
461
        .probe          = omap_kp_probe,
462
        .remove         = omap_kp_remove,
463
        .suspend        = omap_kp_suspend,
464
        .resume         = omap_kp_resume,
465
        .driver         = {
466
                .name   = "omap-keypad",
467
        },
468
};
469
 
470
static int __devinit omap_kp_init(void)
471
{
472
        printk(KERN_INFO "OMAP Keypad Driver\n");
473
        return platform_driver_register(&omap_kp_driver);
474
}
475
 
476
static void __exit omap_kp_exit(void)
477
{
478
        platform_driver_unregister(&omap_kp_driver);
479
}
480
 
481
module_init(omap_kp_init);
482
module_exit(omap_kp_exit);
483
 
484
MODULE_AUTHOR("Timo Teräs");
485
MODULE_DESCRIPTION("OMAP Keypad Driver");
486
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.