diff options
author | Stephen Boyd <sboyd@codeaurora.org> | 2014-03-29 15:35:35 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2014-03-30 16:25:19 -0400 |
commit | 86ea5e6b793d45fa7d2aa504ac3aefc813f0fd55 (patch) | |
tree | b6d996281712bd64eb47664422af180c4684b561 /drivers/input/keyboard/pmic8xxx-keypad.c | |
parent | a5dde0c72ccbb0f66b3491ee83f4c579aea0651d (diff) |
Input: pmic8xxx-keypad - migrate to DT
The driver is only supported on DT enabled platforms. Convert the
driver to DT so that it can probe properly.
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input/keyboard/pmic8xxx-keypad.c')
-rw-r--r-- | drivers/input/keyboard/pmic8xxx-keypad.c | 150 |
1 files changed, 86 insertions, 64 deletions
diff --git a/drivers/input/keyboard/pmic8xxx-keypad.c b/drivers/input/keyboard/pmic8xxx-keypad.c index 0efd11e16b7e..80c6b0ef3fc8 100644 --- a/drivers/input/keyboard/pmic8xxx-keypad.c +++ b/drivers/input/keyboard/pmic8xxx-keypad.c | |||
@@ -20,8 +20,8 @@ | |||
20 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
21 | #include <linux/mutex.h> | 21 | #include <linux/mutex.h> |
22 | #include <linux/regmap.h> | 22 | #include <linux/regmap.h> |
23 | 23 | #include <linux/of.h> | |
24 | #include <linux/input/pmic8xxx-keypad.h> | 24 | #include <linux/input/matrix_keypad.h> |
25 | 25 | ||
26 | #define PM8XXX_MAX_ROWS 18 | 26 | #define PM8XXX_MAX_ROWS 18 |
27 | #define PM8XXX_MAX_COLS 8 | 27 | #define PM8XXX_MAX_COLS 8 |
@@ -84,7 +84,8 @@ | |||
84 | 84 | ||
85 | /** | 85 | /** |
86 | * struct pmic8xxx_kp - internal keypad data structure | 86 | * struct pmic8xxx_kp - internal keypad data structure |
87 | * @pdata - keypad platform data pointer | 87 | * @num_cols - number of columns of keypad |
88 | * @num_rows - number of row of keypad | ||
88 | * @input - input device pointer for keypad | 89 | * @input - input device pointer for keypad |
89 | * @regmap - regmap handle | 90 | * @regmap - regmap handle |
90 | * @key_sense_irq - key press/release irq number | 91 | * @key_sense_irq - key press/release irq number |
@@ -96,7 +97,8 @@ | |||
96 | * @ctrl_reg - control register value | 97 | * @ctrl_reg - control register value |
97 | */ | 98 | */ |
98 | struct pmic8xxx_kp { | 99 | struct pmic8xxx_kp { |
99 | const struct pm8xxx_keypad_platform_data *pdata; | 100 | unsigned int num_rows; |
101 | unsigned int num_cols; | ||
100 | struct input_dev *input; | 102 | struct input_dev *input; |
101 | struct regmap *regmap; | 103 | struct regmap *regmap; |
102 | int key_sense_irq; | 104 | int key_sense_irq; |
@@ -115,9 +117,9 @@ static u8 pmic8xxx_col_state(struct pmic8xxx_kp *kp, u8 col) | |||
115 | { | 117 | { |
116 | /* all keys pressed on that particular row? */ | 118 | /* all keys pressed on that particular row? */ |
117 | if (col == 0x00) | 119 | if (col == 0x00) |
118 | return 1 << kp->pdata->num_cols; | 120 | return 1 << kp->num_cols; |
119 | else | 121 | else |
120 | return col & ((1 << kp->pdata->num_cols) - 1); | 122 | return col & ((1 << kp->num_cols) - 1); |
121 | } | 123 | } |
122 | 124 | ||
123 | /* | 125 | /* |
@@ -180,10 +182,10 @@ static int pmic8xxx_kp_read_matrix(struct pmic8xxx_kp *kp, u16 *new_state, | |||
180 | int rc, read_rows; | 182 | int rc, read_rows; |
181 | unsigned int scan_val; | 183 | unsigned int scan_val; |
182 | 184 | ||
183 | if (kp->pdata->num_rows < PM8XXX_MIN_ROWS) | 185 | if (kp->num_rows < PM8XXX_MIN_ROWS) |
184 | read_rows = PM8XXX_MIN_ROWS; | 186 | read_rows = PM8XXX_MIN_ROWS; |
185 | else | 187 | else |
186 | read_rows = kp->pdata->num_rows; | 188 | read_rows = kp->num_rows; |
187 | 189 | ||
188 | pmic8xxx_chk_sync_read(kp); | 190 | pmic8xxx_chk_sync_read(kp); |
189 | 191 | ||
@@ -227,13 +229,13 @@ static void __pmic8xxx_kp_scan_matrix(struct pmic8xxx_kp *kp, u16 *new_state, | |||
227 | { | 229 | { |
228 | int row, col, code; | 230 | int row, col, code; |
229 | 231 | ||
230 | for (row = 0; row < kp->pdata->num_rows; row++) { | 232 | for (row = 0; row < kp->num_rows; row++) { |
231 | int bits_changed = new_state[row] ^ old_state[row]; | 233 | int bits_changed = new_state[row] ^ old_state[row]; |
232 | 234 | ||
233 | if (!bits_changed) | 235 | if (!bits_changed) |
234 | continue; | 236 | continue; |
235 | 237 | ||
236 | for (col = 0; col < kp->pdata->num_cols; col++) { | 238 | for (col = 0; col < kp->num_cols; col++) { |
237 | if (!(bits_changed & (1 << col))) | 239 | if (!(bits_changed & (1 << col))) |
238 | continue; | 240 | continue; |
239 | 241 | ||
@@ -259,9 +261,9 @@ static bool pmic8xxx_detect_ghost_keys(struct pmic8xxx_kp *kp, u16 *new_state) | |||
259 | u16 check, row_state; | 261 | u16 check, row_state; |
260 | 262 | ||
261 | check = 0; | 263 | check = 0; |
262 | for (row = 0; row < kp->pdata->num_rows; row++) { | 264 | for (row = 0; row < kp->num_rows; row++) { |
263 | row_state = (~new_state[row]) & | 265 | row_state = (~new_state[row]) & |
264 | ((1 << kp->pdata->num_cols) - 1); | 266 | ((1 << kp->num_cols) - 1); |
265 | 267 | ||
266 | if (hweight16(row_state) > 1) { | 268 | if (hweight16(row_state) > 1) { |
267 | if (found_first == -1) | 269 | if (found_first == -1) |
@@ -369,8 +371,13 @@ static irqreturn_t pmic8xxx_kp_irq(int irq, void *data) | |||
369 | return IRQ_HANDLED; | 371 | return IRQ_HANDLED; |
370 | } | 372 | } |
371 | 373 | ||
372 | static int pmic8xxx_kpd_init(struct pmic8xxx_kp *kp) | 374 | static int pmic8xxx_kpd_init(struct pmic8xxx_kp *kp, |
375 | struct platform_device *pdev) | ||
373 | { | 376 | { |
377 | const struct device_node *of_node = pdev->dev.of_node; | ||
378 | unsigned int scan_delay_ms; | ||
379 | unsigned int row_hold_ns; | ||
380 | unsigned int debounce_ms; | ||
374 | int bits, rc, cycles; | 381 | int bits, rc, cycles; |
375 | u8 scan_val = 0, ctrl_val = 0; | 382 | u8 scan_val = 0, ctrl_val = 0; |
376 | static const u8 row_bits[] = { | 383 | static const u8 row_bits[] = { |
@@ -378,18 +385,18 @@ static int pmic8xxx_kpd_init(struct pmic8xxx_kp *kp) | |||
378 | }; | 385 | }; |
379 | 386 | ||
380 | /* Find column bits */ | 387 | /* Find column bits */ |
381 | if (kp->pdata->num_cols < KEYP_CTRL_SCAN_COLS_MIN) | 388 | if (kp->num_cols < KEYP_CTRL_SCAN_COLS_MIN) |
382 | bits = 0; | 389 | bits = 0; |
383 | else | 390 | else |
384 | bits = kp->pdata->num_cols - KEYP_CTRL_SCAN_COLS_MIN; | 391 | bits = kp->num_cols - KEYP_CTRL_SCAN_COLS_MIN; |
385 | ctrl_val = (bits & KEYP_CTRL_SCAN_COLS_BITS) << | 392 | ctrl_val = (bits & KEYP_CTRL_SCAN_COLS_BITS) << |
386 | KEYP_CTRL_SCAN_COLS_SHIFT; | 393 | KEYP_CTRL_SCAN_COLS_SHIFT; |
387 | 394 | ||
388 | /* Find row bits */ | 395 | /* Find row bits */ |
389 | if (kp->pdata->num_rows < KEYP_CTRL_SCAN_ROWS_MIN) | 396 | if (kp->num_rows < KEYP_CTRL_SCAN_ROWS_MIN) |
390 | bits = 0; | 397 | bits = 0; |
391 | else | 398 | else |
392 | bits = row_bits[kp->pdata->num_rows - KEYP_CTRL_SCAN_ROWS_MIN]; | 399 | bits = row_bits[kp->num_rows - KEYP_CTRL_SCAN_ROWS_MIN]; |
393 | 400 | ||
394 | ctrl_val |= (bits << KEYP_CTRL_SCAN_ROWS_SHIFT); | 401 | ctrl_val |= (bits << KEYP_CTRL_SCAN_ROWS_SHIFT); |
395 | 402 | ||
@@ -399,15 +406,44 @@ static int pmic8xxx_kpd_init(struct pmic8xxx_kp *kp) | |||
399 | return rc; | 406 | return rc; |
400 | } | 407 | } |
401 | 408 | ||
402 | bits = (kp->pdata->debounce_ms / 5) - 1; | 409 | if (of_property_read_u32(of_node, "scan-delay", &scan_delay_ms)) |
410 | scan_delay_ms = MIN_SCAN_DELAY; | ||
411 | |||
412 | if (scan_delay_ms > MAX_SCAN_DELAY || scan_delay_ms < MIN_SCAN_DELAY || | ||
413 | !is_power_of_2(scan_delay_ms)) { | ||
414 | dev_err(&pdev->dev, "invalid keypad scan time supplied\n"); | ||
415 | return -EINVAL; | ||
416 | } | ||
417 | |||
418 | if (of_property_read_u32(of_node, "row-hold", &row_hold_ns)) | ||
419 | row_hold_ns = MIN_ROW_HOLD_DELAY; | ||
420 | |||
421 | if (row_hold_ns > MAX_ROW_HOLD_DELAY || | ||
422 | row_hold_ns < MIN_ROW_HOLD_DELAY || | ||
423 | ((row_hold_ns % MIN_ROW_HOLD_DELAY) != 0)) { | ||
424 | dev_err(&pdev->dev, "invalid keypad row hold time supplied\n"); | ||
425 | return -EINVAL; | ||
426 | } | ||
427 | |||
428 | if (of_property_read_u32(of_node, "debounce", &debounce_ms)) | ||
429 | debounce_ms = MIN_DEBOUNCE_TIME; | ||
430 | |||
431 | if (((debounce_ms % 5) != 0) || | ||
432 | debounce_ms > MAX_DEBOUNCE_TIME || | ||
433 | debounce_ms < MIN_DEBOUNCE_TIME) { | ||
434 | dev_err(&pdev->dev, "invalid debounce time supplied\n"); | ||
435 | return -EINVAL; | ||
436 | } | ||
437 | |||
438 | bits = (debounce_ms / 5) - 1; | ||
403 | 439 | ||
404 | scan_val |= (bits << KEYP_SCAN_DBOUNCE_SHIFT); | 440 | scan_val |= (bits << KEYP_SCAN_DBOUNCE_SHIFT); |
405 | 441 | ||
406 | bits = fls(kp->pdata->scan_delay_ms) - 1; | 442 | bits = fls(scan_delay_ms) - 1; |
407 | scan_val |= (bits << KEYP_SCAN_PAUSE_SHIFT); | 443 | scan_val |= (bits << KEYP_SCAN_PAUSE_SHIFT); |
408 | 444 | ||
409 | /* Row hold time is a multiple of 32KHz cycles. */ | 445 | /* Row hold time is a multiple of 32KHz cycles. */ |
410 | cycles = (kp->pdata->row_hold_ns * KEYP_CLOCK_FREQ) / NSEC_PER_SEC; | 446 | cycles = (row_hold_ns * KEYP_CLOCK_FREQ) / NSEC_PER_SEC; |
411 | 447 | ||
412 | scan_val |= (cycles << KEYP_SCAN_ROW_HOLD_SHIFT); | 448 | scan_val |= (cycles << KEYP_SCAN_ROW_HOLD_SHIFT); |
413 | 449 | ||
@@ -471,50 +507,27 @@ static void pmic8xxx_kp_close(struct input_dev *dev) | |||
471 | */ | 507 | */ |
472 | static int pmic8xxx_kp_probe(struct platform_device *pdev) | 508 | static int pmic8xxx_kp_probe(struct platform_device *pdev) |
473 | { | 509 | { |
474 | const struct pm8xxx_keypad_platform_data *pdata = | 510 | unsigned int rows, cols; |
475 | dev_get_platdata(&pdev->dev); | 511 | bool repeat; |
476 | const struct matrix_keymap_data *keymap_data; | 512 | bool wakeup; |
477 | struct pmic8xxx_kp *kp; | 513 | struct pmic8xxx_kp *kp; |
478 | int rc; | 514 | int rc; |
479 | unsigned int ctrl_val; | 515 | unsigned int ctrl_val; |
480 | 516 | ||
481 | if (!pdata || !pdata->num_cols || !pdata->num_rows || | 517 | rc = matrix_keypad_parse_of_params(&pdev->dev, &rows, &cols); |
482 | pdata->num_cols > PM8XXX_MAX_COLS || | 518 | if (rc) |
483 | pdata->num_rows > PM8XXX_MAX_ROWS || | 519 | return rc; |
484 | pdata->num_cols < PM8XXX_MIN_COLS) { | ||
485 | dev_err(&pdev->dev, "invalid platform data\n"); | ||
486 | return -EINVAL; | ||
487 | } | ||
488 | |||
489 | if (!pdata->scan_delay_ms || | ||
490 | pdata->scan_delay_ms > MAX_SCAN_DELAY || | ||
491 | pdata->scan_delay_ms < MIN_SCAN_DELAY || | ||
492 | !is_power_of_2(pdata->scan_delay_ms)) { | ||
493 | dev_err(&pdev->dev, "invalid keypad scan time supplied\n"); | ||
494 | return -EINVAL; | ||
495 | } | ||
496 | |||
497 | if (!pdata->row_hold_ns || | ||
498 | pdata->row_hold_ns > MAX_ROW_HOLD_DELAY || | ||
499 | pdata->row_hold_ns < MIN_ROW_HOLD_DELAY || | ||
500 | ((pdata->row_hold_ns % MIN_ROW_HOLD_DELAY) != 0)) { | ||
501 | dev_err(&pdev->dev, "invalid keypad row hold time supplied\n"); | ||
502 | return -EINVAL; | ||
503 | } | ||
504 | 520 | ||
505 | if (!pdata->debounce_ms || | 521 | if (cols > PM8XXX_MAX_COLS || rows > PM8XXX_MAX_ROWS || |
506 | ((pdata->debounce_ms % 5) != 0) || | 522 | cols < PM8XXX_MIN_COLS) { |
507 | pdata->debounce_ms > MAX_DEBOUNCE_TIME || | 523 | dev_err(&pdev->dev, "invalid platform data\n"); |
508 | pdata->debounce_ms < MIN_DEBOUNCE_TIME) { | ||
509 | dev_err(&pdev->dev, "invalid debounce time supplied\n"); | ||
510 | return -EINVAL; | 524 | return -EINVAL; |
511 | } | 525 | } |
512 | 526 | ||
513 | keymap_data = pdata->keymap_data; | 527 | repeat = !of_property_read_bool(pdev->dev.of_node, |
514 | if (!keymap_data) { | 528 | "linux,input-no-autorepeat"); |
515 | dev_err(&pdev->dev, "no keymap data supplied\n"); | 529 | wakeup = of_property_read_bool(pdev->dev.of_node, |
516 | return -EINVAL; | 530 | "linux,keypad-wakeup"); |
517 | } | ||
518 | 531 | ||
519 | kp = devm_kzalloc(&pdev->dev, sizeof(*kp), GFP_KERNEL); | 532 | kp = devm_kzalloc(&pdev->dev, sizeof(*kp), GFP_KERNEL); |
520 | if (!kp) | 533 | if (!kp) |
@@ -526,7 +539,8 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev) | |||
526 | 539 | ||
527 | platform_set_drvdata(pdev, kp); | 540 | platform_set_drvdata(pdev, kp); |
528 | 541 | ||
529 | kp->pdata = pdata; | 542 | kp->num_rows = rows; |
543 | kp->num_cols = cols; | ||
530 | kp->dev = &pdev->dev; | 544 | kp->dev = &pdev->dev; |
531 | 545 | ||
532 | kp->input = devm_input_allocate_device(&pdev->dev); | 546 | kp->input = devm_input_allocate_device(&pdev->dev); |
@@ -547,8 +561,8 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev) | |||
547 | return kp->key_stuck_irq; | 561 | return kp->key_stuck_irq; |
548 | } | 562 | } |
549 | 563 | ||
550 | kp->input->name = pdata->input_name ? : "PMIC8XXX keypad"; | 564 | kp->input->name = "PMIC8XXX keypad"; |
551 | kp->input->phys = pdata->input_phys_device ? : "pmic8xxx_keypad/input0"; | 565 | kp->input->phys = "pmic8xxx_keypad/input0"; |
552 | 566 | ||
553 | kp->input->id.bustype = BUS_I2C; | 567 | kp->input->id.bustype = BUS_I2C; |
554 | kp->input->id.version = 0x0001; | 568 | kp->input->id.version = 0x0001; |
@@ -558,7 +572,7 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev) | |||
558 | kp->input->open = pmic8xxx_kp_open; | 572 | kp->input->open = pmic8xxx_kp_open; |
559 | kp->input->close = pmic8xxx_kp_close; | 573 | kp->input->close = pmic8xxx_kp_close; |
560 | 574 | ||
561 | rc = matrix_keypad_build_keymap(keymap_data, NULL, | 575 | rc = matrix_keypad_build_keymap(NULL, NULL, |
562 | PM8XXX_MAX_ROWS, PM8XXX_MAX_COLS, | 576 | PM8XXX_MAX_ROWS, PM8XXX_MAX_COLS, |
563 | kp->keycodes, kp->input); | 577 | kp->keycodes, kp->input); |
564 | if (rc) { | 578 | if (rc) { |
@@ -566,7 +580,7 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev) | |||
566 | return rc; | 580 | return rc; |
567 | } | 581 | } |
568 | 582 | ||
569 | if (pdata->rep) | 583 | if (repeat) |
570 | __set_bit(EV_REP, kp->input->evbit); | 584 | __set_bit(EV_REP, kp->input->evbit); |
571 | input_set_capability(kp->input, EV_MSC, MSC_SCAN); | 585 | input_set_capability(kp->input, EV_MSC, MSC_SCAN); |
572 | 586 | ||
@@ -576,7 +590,7 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev) | |||
576 | memset(kp->keystate, 0xff, sizeof(kp->keystate)); | 590 | memset(kp->keystate, 0xff, sizeof(kp->keystate)); |
577 | memset(kp->stuckstate, 0xff, sizeof(kp->stuckstate)); | 591 | memset(kp->stuckstate, 0xff, sizeof(kp->stuckstate)); |
578 | 592 | ||
579 | rc = pmic8xxx_kpd_init(kp); | 593 | rc = pmic8xxx_kpd_init(kp, pdev); |
580 | if (rc < 0) { | 594 | if (rc < 0) { |
581 | dev_err(&pdev->dev, "unable to initialize keypad controller\n"); | 595 | dev_err(&pdev->dev, "unable to initialize keypad controller\n"); |
582 | return rc; | 596 | return rc; |
@@ -612,7 +626,7 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev) | |||
612 | return rc; | 626 | return rc; |
613 | } | 627 | } |
614 | 628 | ||
615 | device_init_wakeup(&pdev->dev, pdata->wakeup); | 629 | device_init_wakeup(&pdev->dev, wakeup); |
616 | 630 | ||
617 | return 0; | 631 | return 0; |
618 | } | 632 | } |
@@ -662,12 +676,20 @@ static int pmic8xxx_kp_resume(struct device *dev) | |||
662 | static SIMPLE_DEV_PM_OPS(pm8xxx_kp_pm_ops, | 676 | static SIMPLE_DEV_PM_OPS(pm8xxx_kp_pm_ops, |
663 | pmic8xxx_kp_suspend, pmic8xxx_kp_resume); | 677 | pmic8xxx_kp_suspend, pmic8xxx_kp_resume); |
664 | 678 | ||
679 | static const struct of_device_id pm8xxx_match_table[] = { | ||
680 | { .compatible = "qcom,pm8058-keypad" }, | ||
681 | { .compatible = "qcom,pm8921-keypad" }, | ||
682 | { } | ||
683 | }; | ||
684 | MODULE_DEVICE_TABLE(of, pm8xxx_match_table); | ||
685 | |||
665 | static struct platform_driver pmic8xxx_kp_driver = { | 686 | static struct platform_driver pmic8xxx_kp_driver = { |
666 | .probe = pmic8xxx_kp_probe, | 687 | .probe = pmic8xxx_kp_probe, |
667 | .driver = { | 688 | .driver = { |
668 | .name = PM8XXX_KEYPAD_DEV_NAME, | 689 | .name = "pm8xxx-keypad", |
669 | .owner = THIS_MODULE, | 690 | .owner = THIS_MODULE, |
670 | .pm = &pm8xxx_kp_pm_ops, | 691 | .pm = &pm8xxx_kp_pm_ops, |
692 | .of_match_table = pm8xxx_match_table, | ||
671 | }, | 693 | }, |
672 | }; | 694 | }; |
673 | module_platform_driver(pmic8xxx_kp_driver); | 695 | module_platform_driver(pmic8xxx_kp_driver); |