diff options
Diffstat (limited to 'drivers/input/keyboard')
-rw-r--r-- | drivers/input/keyboard/pxa27x_keypad.c | 158 |
1 files changed, 124 insertions, 34 deletions
diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index cd25b3414491..ceaf1e0ab540 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c | |||
@@ -31,25 +31,71 @@ | |||
31 | #include <asm/mach/map.h> | 31 | #include <asm/mach/map.h> |
32 | 32 | ||
33 | #include <asm/arch/hardware.h> | 33 | #include <asm/arch/hardware.h> |
34 | #include <asm/arch/pxa-regs.h> | ||
35 | #include <asm/arch/irqs.h> | ||
36 | #include <asm/arch/pxa27x_keypad.h> | 34 | #include <asm/arch/pxa27x_keypad.h> |
37 | 35 | ||
38 | #define DRIVER_NAME "pxa27x-keypad" | 36 | /* |
39 | 37 | * Keypad Controller registers | |
38 | */ | ||
39 | #define KPC 0x0000 /* Keypad Control register */ | ||
40 | #define KPDK 0x0008 /* Keypad Direct Key register */ | ||
41 | #define KPREC 0x0010 /* Keypad Rotary Encoder register */ | ||
42 | #define KPMK 0x0018 /* Keypad Matrix Key register */ | ||
43 | #define KPAS 0x0020 /* Keypad Automatic Scan register */ | ||
44 | |||
45 | /* Keypad Automatic Scan Multiple Key Presser register 0-3 */ | ||
46 | #define KPASMKP0 0x0028 | ||
47 | #define KPASMKP1 0x0030 | ||
48 | #define KPASMKP2 0x0038 | ||
49 | #define KPASMKP3 0x0040 | ||
50 | #define KPKDI 0x0048 | ||
51 | |||
52 | /* bit definitions */ | ||
40 | #define KPC_MKRN(n) ((((n) & 0x7) - 1) << 26) /* matrix key row number */ | 53 | #define KPC_MKRN(n) ((((n) & 0x7) - 1) << 26) /* matrix key row number */ |
41 | #define KPC_MKCN(n) ((((n) & 0x7) - 1) << 23) /* matrix key column number */ | 54 | #define KPC_MKCN(n) ((((n) & 0x7) - 1) << 23) /* matrix key column number */ |
42 | #define KPC_DKN(n) ((((n) & 0x7) - 1) << 6) /* direct key number */ | 55 | #define KPC_DKN(n) ((((n) & 0x7) - 1) << 6) /* direct key number */ |
43 | 56 | ||
57 | #define KPC_AS (0x1 << 30) /* Automatic Scan bit */ | ||
58 | #define KPC_ASACT (0x1 << 29) /* Automatic Scan on Activity */ | ||
59 | #define KPC_MI (0x1 << 22) /* Matrix interrupt bit */ | ||
60 | #define KPC_IMKP (0x1 << 21) /* Ignore Multiple Key Press */ | ||
61 | |||
62 | #define KPC_MS(n) (0x1 << (13 + (n))) /* Matrix scan line 'n' */ | ||
63 | #define KPC_MS_ALL (0xff << 13) | ||
64 | |||
65 | #define KPC_ME (0x1 << 12) /* Matrix Keypad Enable */ | ||
66 | #define KPC_MIE (0x1 << 11) /* Matrix Interrupt Enable */ | ||
67 | #define KPC_DK_DEB_SEL (0x1 << 9) /* Direct Keypad Debounce Select */ | ||
68 | #define KPC_DI (0x1 << 5) /* Direct key interrupt bit */ | ||
69 | #define KPC_RE_ZERO_DEB (0x1 << 4) /* Rotary Encoder Zero Debounce */ | ||
70 | #define KPC_REE1 (0x1 << 3) /* Rotary Encoder1 Enable */ | ||
71 | #define KPC_REE0 (0x1 << 2) /* Rotary Encoder0 Enable */ | ||
72 | #define KPC_DE (0x1 << 1) /* Direct Keypad Enable */ | ||
73 | #define KPC_DIE (0x1 << 0) /* Direct Keypad interrupt Enable */ | ||
74 | |||
44 | #define KPDK_DKP (0x1 << 31) | 75 | #define KPDK_DKP (0x1 << 31) |
45 | #define KPDK_DK(n) ((n) & 0xff) | 76 | #define KPDK_DK(n) ((n) & 0xff) |
46 | 77 | ||
47 | #define KPAS_MUKP(n) (((n) >> 26) & 0x1f) | 78 | #define KPREC_OF1 (0x1 << 31) |
48 | #define KPAS_RP(n) (((n) >> 4) & 0xf) | 79 | #define kPREC_UF1 (0x1 << 30) |
49 | #define KPAS_CP(n) ((n) & 0xf) | 80 | #define KPREC_OF0 (0x1 << 15) |
81 | #define KPREC_UF0 (0x1 << 14) | ||
82 | |||
83 | #define KPREC_RECOUNT0(n) ((n) & 0xff) | ||
84 | #define KPREC_RECOUNT1(n) (((n) >> 16) & 0xff) | ||
85 | |||
86 | #define KPMK_MKP (0x1 << 31) | ||
87 | #define KPAS_SO (0x1 << 31) | ||
88 | #define KPASMKPx_SO (0x1 << 31) | ||
89 | |||
90 | #define KPAS_MUKP(n) (((n) >> 26) & 0x1f) | ||
91 | #define KPAS_RP(n) (((n) >> 4) & 0xf) | ||
92 | #define KPAS_CP(n) ((n) & 0xf) | ||
50 | 93 | ||
51 | #define KPASMKP_MKC_MASK (0xff) | 94 | #define KPASMKP_MKC_MASK (0xff) |
52 | 95 | ||
96 | #define keypad_readl(off) __raw_readl(keypad->mmio_base + (off)) | ||
97 | #define keypad_writel(off, v) __raw_writel((v), keypad->mmio_base + (off)) | ||
98 | |||
53 | #define MAX_MATRIX_KEY_NUM (8 * 8) | 99 | #define MAX_MATRIX_KEY_NUM (8 * 8) |
54 | 100 | ||
55 | struct pxa27x_keypad { | 101 | struct pxa27x_keypad { |
@@ -57,6 +103,7 @@ struct pxa27x_keypad { | |||
57 | 103 | ||
58 | struct clk *clk; | 104 | struct clk *clk; |
59 | struct input_dev *input_dev; | 105 | struct input_dev *input_dev; |
106 | void __iomem *mmio_base; | ||
60 | 107 | ||
61 | /* matrix key code map */ | 108 | /* matrix key code map */ |
62 | unsigned int matrix_keycodes[MAX_MATRIX_KEY_NUM]; | 109 | unsigned int matrix_keycodes[MAX_MATRIX_KEY_NUM]; |
@@ -120,7 +167,7 @@ static void pxa27x_keypad_scan_matrix(struct pxa27x_keypad *keypad) | |||
120 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; | 167 | struct pxa27x_keypad_platform_data *pdata = keypad->pdata; |
121 | int row, col, num_keys_pressed = 0; | 168 | int row, col, num_keys_pressed = 0; |
122 | uint32_t new_state[MAX_MATRIX_KEY_COLS]; | 169 | uint32_t new_state[MAX_MATRIX_KEY_COLS]; |
123 | uint32_t kpas = KPAS; | 170 | uint32_t kpas = keypad_readl(KPAS); |
124 | 171 | ||
125 | num_keys_pressed = KPAS_MUKP(kpas); | 172 | num_keys_pressed = KPAS_MUKP(kpas); |
126 | 173 | ||
@@ -143,10 +190,10 @@ static void pxa27x_keypad_scan_matrix(struct pxa27x_keypad *keypad) | |||
143 | } | 190 | } |
144 | 191 | ||
145 | if (num_keys_pressed > 1) { | 192 | if (num_keys_pressed > 1) { |
146 | uint32_t kpasmkp0 = KPASMKP0; | 193 | uint32_t kpasmkp0 = keypad_readl(KPASMKP0); |
147 | uint32_t kpasmkp1 = KPASMKP1; | 194 | uint32_t kpasmkp1 = keypad_readl(KPASMKP1); |
148 | uint32_t kpasmkp2 = KPASMKP2; | 195 | uint32_t kpasmkp2 = keypad_readl(KPASMKP2); |
149 | uint32_t kpasmkp3 = KPASMKP3; | 196 | uint32_t kpasmkp3 = keypad_readl(KPASMKP3); |
150 | 197 | ||
151 | new_state[0] = kpasmkp0 & KPASMKP_MKC_MASK; | 198 | new_state[0] = kpasmkp0 & KPASMKP_MKC_MASK; |
152 | new_state[1] = (kpasmkp0 >> 16) & KPASMKP_MKC_MASK; | 199 | new_state[1] = (kpasmkp0 >> 16) & KPASMKP_MKC_MASK; |
@@ -218,8 +265,8 @@ static void pxa27x_keypad_scan_rotary(struct pxa27x_keypad *keypad) | |||
218 | uint32_t kprec; | 265 | uint32_t kprec; |
219 | 266 | ||
220 | /* read and reset to default count value */ | 267 | /* read and reset to default count value */ |
221 | kprec = KPREC; | 268 | kprec = keypad_readl(KPREC); |
222 | KPREC = DEFAULT_KPREC; | 269 | keypad_writel(KPREC, DEFAULT_KPREC); |
223 | 270 | ||
224 | if (pdata->enable_rotary0) | 271 | if (pdata->enable_rotary0) |
225 | report_rotary_event(keypad, 0, rotary_delta(kprec)); | 272 | report_rotary_event(keypad, 0, rotary_delta(kprec)); |
@@ -235,7 +282,7 @@ static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad) | |||
235 | uint32_t kpdk, bits_changed; | 282 | uint32_t kpdk, bits_changed; |
236 | int i; | 283 | int i; |
237 | 284 | ||
238 | kpdk = KPDK; | 285 | kpdk = keypad_readl(KPDK); |
239 | 286 | ||
240 | if (pdata->enable_rotary0 || pdata->enable_rotary1) | 287 | if (pdata->enable_rotary0 || pdata->enable_rotary1) |
241 | pxa27x_keypad_scan_rotary(keypad); | 288 | pxa27x_keypad_scan_rotary(keypad); |
@@ -262,7 +309,7 @@ static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad) | |||
262 | static irqreturn_t pxa27x_keypad_irq_handler(int irq, void *dev_id) | 309 | static irqreturn_t pxa27x_keypad_irq_handler(int irq, void *dev_id) |
263 | { | 310 | { |
264 | struct pxa27x_keypad *keypad = dev_id; | 311 | struct pxa27x_keypad *keypad = dev_id; |
265 | unsigned long kpc = KPC; | 312 | unsigned long kpc = keypad_readl(KPC); |
266 | 313 | ||
267 | if (kpc & KPC_DI) | 314 | if (kpc & KPC_DI) |
268 | pxa27x_keypad_scan_direct(keypad); | 315 | pxa27x_keypad_scan_direct(keypad); |
@@ -308,8 +355,8 @@ static void pxa27x_keypad_config(struct pxa27x_keypad *keypad) | |||
308 | if (direct_key_num) | 355 | if (direct_key_num) |
309 | kpc |= KPC_DE | KPC_DIE | KPC_DKN(direct_key_num); | 356 | kpc |= KPC_DE | KPC_DIE | KPC_DKN(direct_key_num); |
310 | 357 | ||
311 | KPC = kpc | KPC_RE_ZERO_DEB; | 358 | keypad_writel(KPC, kpc | KPC_RE_ZERO_DEB); |
312 | KPREC = DEFAULT_KPREC; | 359 | keypad_writel(KPREC, DEFAULT_KPREC); |
313 | } | 360 | } |
314 | 361 | ||
315 | static int pxa27x_keypad_open(struct input_dev *dev) | 362 | static int pxa27x_keypad_open(struct input_dev *dev) |
@@ -362,11 +409,14 @@ static int pxa27x_keypad_resume(struct platform_device *pdev) | |||
362 | #define pxa27x_keypad_resume NULL | 409 | #define pxa27x_keypad_resume NULL |
363 | #endif | 410 | #endif |
364 | 411 | ||
412 | #define res_size(res) ((res)->end - (res)->start + 1) | ||
413 | |||
365 | static int __devinit pxa27x_keypad_probe(struct platform_device *pdev) | 414 | static int __devinit pxa27x_keypad_probe(struct platform_device *pdev) |
366 | { | 415 | { |
367 | struct pxa27x_keypad *keypad; | 416 | struct pxa27x_keypad *keypad; |
368 | struct input_dev *input_dev; | 417 | struct input_dev *input_dev; |
369 | int error; | 418 | struct resource *res; |
419 | int irq, error; | ||
370 | 420 | ||
371 | keypad = kzalloc(sizeof(struct pxa27x_keypad), GFP_KERNEL); | 421 | keypad = kzalloc(sizeof(struct pxa27x_keypad), GFP_KERNEL); |
372 | if (keypad == NULL) { | 422 | if (keypad == NULL) { |
@@ -381,11 +431,39 @@ static int __devinit pxa27x_keypad_probe(struct platform_device *pdev) | |||
381 | goto failed_free; | 431 | goto failed_free; |
382 | } | 432 | } |
383 | 433 | ||
434 | irq = platform_get_irq(pdev, 0); | ||
435 | if (irq < 0) { | ||
436 | dev_err(&pdev->dev, "failed to get keypad irq\n"); | ||
437 | error = -ENXIO; | ||
438 | goto failed_free; | ||
439 | } | ||
440 | |||
441 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
442 | if (res == NULL) { | ||
443 | dev_err(&pdev->dev, "failed to get I/O memory\n"); | ||
444 | error = -ENXIO; | ||
445 | goto failed_free; | ||
446 | } | ||
447 | |||
448 | res = request_mem_region(res->start, res_size(res), pdev->name); | ||
449 | if (res == NULL) { | ||
450 | dev_err(&pdev->dev, "failed to request I/O memory\n"); | ||
451 | error = -EBUSY; | ||
452 | goto failed_free; | ||
453 | } | ||
454 | |||
455 | keypad->mmio_base = ioremap(res->start, res_size(res)); | ||
456 | if (keypad->mmio_base == NULL) { | ||
457 | dev_err(&pdev->dev, "failed to remap I/O memory\n"); | ||
458 | error = -ENXIO; | ||
459 | goto failed_free_mem; | ||
460 | } | ||
461 | |||
384 | keypad->clk = clk_get(&pdev->dev, "KBDCLK"); | 462 | keypad->clk = clk_get(&pdev->dev, "KBDCLK"); |
385 | if (IS_ERR(keypad->clk)) { | 463 | if (IS_ERR(keypad->clk)) { |
386 | dev_err(&pdev->dev, "failed to get keypad clock\n"); | 464 | dev_err(&pdev->dev, "failed to get keypad clock\n"); |
387 | error = PTR_ERR(keypad->clk); | 465 | error = PTR_ERR(keypad->clk); |
388 | goto failed_free; | 466 | goto failed_free_io; |
389 | } | 467 | } |
390 | 468 | ||
391 | /* Create and register the input driver. */ | 469 | /* Create and register the input driver. */ |
@@ -396,7 +474,7 @@ static int __devinit pxa27x_keypad_probe(struct platform_device *pdev) | |||
396 | goto failed_put_clk; | 474 | goto failed_put_clk; |
397 | } | 475 | } |
398 | 476 | ||
399 | input_dev->name = DRIVER_NAME; | 477 | input_dev->name = pdev->name; |
400 | input_dev->id.bustype = BUS_HOST; | 478 | input_dev->id.bustype = BUS_HOST; |
401 | input_dev->open = pxa27x_keypad_open; | 479 | input_dev->open = pxa27x_keypad_open; |
402 | input_dev->close = pxa27x_keypad_close; | 480 | input_dev->close = pxa27x_keypad_close; |
@@ -409,30 +487,35 @@ static int __devinit pxa27x_keypad_probe(struct platform_device *pdev) | |||
409 | BIT_MASK(EV_REL); | 487 | BIT_MASK(EV_REL); |
410 | 488 | ||
411 | pxa27x_keypad_build_keycode(keypad); | 489 | pxa27x_keypad_build_keycode(keypad); |
490 | platform_set_drvdata(pdev, keypad); | ||
412 | 491 | ||
413 | error = request_irq(IRQ_KEYPAD, pxa27x_keypad_irq_handler, IRQF_DISABLED, | 492 | error = request_irq(irq, pxa27x_keypad_irq_handler, IRQF_DISABLED, |
414 | DRIVER_NAME, keypad); | 493 | pdev->name, keypad); |
415 | if (error) { | 494 | if (error) { |
416 | printk(KERN_ERR "Cannot request keypad IRQ\n"); | 495 | dev_err(&pdev->dev, "failed to request IRQ\n"); |
417 | goto err_free_dev; | 496 | goto failed_free_dev; |
418 | } | 497 | } |
419 | 498 | ||
420 | platform_set_drvdata(pdev, keypad); | ||
421 | |||
422 | /* Register the input device */ | 499 | /* Register the input device */ |
423 | error = input_register_device(input_dev); | 500 | error = input_register_device(input_dev); |
424 | if (error) | 501 | if (error) { |
425 | goto err_free_irq; | 502 | dev_err(&pdev->dev, "failed to register input device\n"); |
503 | goto failed_free_irq; | ||
504 | } | ||
426 | 505 | ||
427 | return 0; | 506 | return 0; |
428 | 507 | ||
429 | err_free_irq: | 508 | failed_free_irq: |
509 | free_irq(irq, pdev); | ||
430 | platform_set_drvdata(pdev, NULL); | 510 | platform_set_drvdata(pdev, NULL); |
431 | free_irq(IRQ_KEYPAD, pdev); | 511 | failed_free_dev: |
432 | err_free_dev: | ||
433 | input_free_device(input_dev); | 512 | input_free_device(input_dev); |
434 | failed_put_clk: | 513 | failed_put_clk: |
435 | clk_put(keypad->clk); | 514 | clk_put(keypad->clk); |
515 | failed_free_io: | ||
516 | iounmap(keypad->mmio_base); | ||
517 | failed_free_mem: | ||
518 | release_mem_region(res->start, res_size(res)); | ||
436 | failed_free: | 519 | failed_free: |
437 | kfree(keypad); | 520 | kfree(keypad); |
438 | return error; | 521 | return error; |
@@ -441,13 +524,20 @@ failed_free: | |||
441 | static int __devexit pxa27x_keypad_remove(struct platform_device *pdev) | 524 | static int __devexit pxa27x_keypad_remove(struct platform_device *pdev) |
442 | { | 525 | { |
443 | struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); | 526 | struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); |
527 | struct resource *res; | ||
444 | 528 | ||
445 | free_irq(IRQ_KEYPAD, pdev); | 529 | free_irq(platform_get_irq(pdev, 0), pdev); |
446 | 530 | ||
447 | clk_disable(keypad->clk); | 531 | clk_disable(keypad->clk); |
448 | clk_put(keypad->clk); | 532 | clk_put(keypad->clk); |
449 | 533 | ||
450 | input_unregister_device(keypad->input_dev); | 534 | input_unregister_device(keypad->input_dev); |
535 | input_free_device(keypad->input_dev); | ||
536 | |||
537 | iounmap(keypad->mmio_base); | ||
538 | |||
539 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
540 | release_mem_region(res->start, res_size(res)); | ||
451 | 541 | ||
452 | platform_set_drvdata(pdev, NULL); | 542 | platform_set_drvdata(pdev, NULL); |
453 | kfree(keypad); | 543 | kfree(keypad); |
@@ -460,7 +550,7 @@ static struct platform_driver pxa27x_keypad_driver = { | |||
460 | .suspend = pxa27x_keypad_suspend, | 550 | .suspend = pxa27x_keypad_suspend, |
461 | .resume = pxa27x_keypad_resume, | 551 | .resume = pxa27x_keypad_resume, |
462 | .driver = { | 552 | .driver = { |
463 | .name = DRIVER_NAME, | 553 | .name = "pxa27x-keypad", |
464 | }, | 554 | }, |
465 | }; | 555 | }; |
466 | 556 | ||