diff options
| -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 | ||
