diff options
Diffstat (limited to 'drivers/input/keyboard/gpio_keys.c')
-rw-r--r-- | drivers/input/keyboard/gpio_keys.c | 114 |
1 files changed, 57 insertions, 57 deletions
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index d4dd78a7d56b..883d6aed5b9a 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c | |||
@@ -35,9 +35,13 @@ | |||
35 | struct gpio_button_data { | 35 | struct gpio_button_data { |
36 | const struct gpio_keys_button *button; | 36 | const struct gpio_keys_button *button; |
37 | struct input_dev *input; | 37 | struct input_dev *input; |
38 | struct timer_list timer; | 38 | |
39 | struct work_struct work; | 39 | struct timer_list release_timer; |
40 | unsigned int timer_debounce; /* in msecs */ | 40 | unsigned int release_delay; /* in msecs, for IRQ-only buttons */ |
41 | |||
42 | struct delayed_work work; | ||
43 | unsigned int software_debounce; /* in msecs, for GPIO-driven buttons */ | ||
44 | |||
41 | unsigned int irq; | 45 | unsigned int irq; |
42 | spinlock_t lock; | 46 | spinlock_t lock; |
43 | bool disabled; | 47 | bool disabled; |
@@ -116,11 +120,14 @@ static void gpio_keys_disable_button(struct gpio_button_data *bdata) | |||
116 | { | 120 | { |
117 | if (!bdata->disabled) { | 121 | if (!bdata->disabled) { |
118 | /* | 122 | /* |
119 | * Disable IRQ and possible debouncing timer. | 123 | * Disable IRQ and associated timer/work structure. |
120 | */ | 124 | */ |
121 | disable_irq(bdata->irq); | 125 | disable_irq(bdata->irq); |
122 | if (bdata->timer_debounce) | 126 | |
123 | del_timer_sync(&bdata->timer); | 127 | if (gpio_is_valid(bdata->button->gpio)) |
128 | cancel_delayed_work_sync(&bdata->work); | ||
129 | else | ||
130 | del_timer_sync(&bdata->release_timer); | ||
124 | 131 | ||
125 | bdata->disabled = true; | 132 | bdata->disabled = true; |
126 | } | 133 | } |
@@ -343,7 +350,7 @@ static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata) | |||
343 | static void gpio_keys_gpio_work_func(struct work_struct *work) | 350 | static void gpio_keys_gpio_work_func(struct work_struct *work) |
344 | { | 351 | { |
345 | struct gpio_button_data *bdata = | 352 | struct gpio_button_data *bdata = |
346 | container_of(work, struct gpio_button_data, work); | 353 | container_of(work, struct gpio_button_data, work.work); |
347 | 354 | ||
348 | gpio_keys_gpio_report_event(bdata); | 355 | gpio_keys_gpio_report_event(bdata); |
349 | 356 | ||
@@ -351,13 +358,6 @@ static void gpio_keys_gpio_work_func(struct work_struct *work) | |||
351 | pm_relax(bdata->input->dev.parent); | 358 | pm_relax(bdata->input->dev.parent); |
352 | } | 359 | } |
353 | 360 | ||
354 | static void gpio_keys_gpio_timer(unsigned long _data) | ||
355 | { | ||
356 | struct gpio_button_data *bdata = (struct gpio_button_data *)_data; | ||
357 | |||
358 | schedule_work(&bdata->work); | ||
359 | } | ||
360 | |||
361 | static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id) | 361 | static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id) |
362 | { | 362 | { |
363 | struct gpio_button_data *bdata = dev_id; | 363 | struct gpio_button_data *bdata = dev_id; |
@@ -366,11 +366,10 @@ static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id) | |||
366 | 366 | ||
367 | if (bdata->button->wakeup) | 367 | if (bdata->button->wakeup) |
368 | pm_stay_awake(bdata->input->dev.parent); | 368 | pm_stay_awake(bdata->input->dev.parent); |
369 | if (bdata->timer_debounce) | 369 | |
370 | mod_timer(&bdata->timer, | 370 | mod_delayed_work(system_wq, |
371 | jiffies + msecs_to_jiffies(bdata->timer_debounce)); | 371 | &bdata->work, |
372 | else | 372 | msecs_to_jiffies(bdata->software_debounce)); |
373 | schedule_work(&bdata->work); | ||
374 | 373 | ||
375 | return IRQ_HANDLED; | 374 | return IRQ_HANDLED; |
376 | } | 375 | } |
@@ -408,7 +407,7 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id) | |||
408 | input_event(input, EV_KEY, button->code, 1); | 407 | input_event(input, EV_KEY, button->code, 1); |
409 | input_sync(input); | 408 | input_sync(input); |
410 | 409 | ||
411 | if (!bdata->timer_debounce) { | 410 | if (!bdata->release_delay) { |
412 | input_event(input, EV_KEY, button->code, 0); | 411 | input_event(input, EV_KEY, button->code, 0); |
413 | input_sync(input); | 412 | input_sync(input); |
414 | goto out; | 413 | goto out; |
@@ -417,9 +416,9 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id) | |||
417 | bdata->key_pressed = true; | 416 | bdata->key_pressed = true; |
418 | } | 417 | } |
419 | 418 | ||
420 | if (bdata->timer_debounce) | 419 | if (bdata->release_delay) |
421 | mod_timer(&bdata->timer, | 420 | mod_timer(&bdata->release_timer, |
422 | jiffies + msecs_to_jiffies(bdata->timer_debounce)); | 421 | jiffies + msecs_to_jiffies(bdata->release_delay)); |
423 | out: | 422 | out: |
424 | spin_unlock_irqrestore(&bdata->lock, flags); | 423 | spin_unlock_irqrestore(&bdata->lock, flags); |
425 | return IRQ_HANDLED; | 424 | return IRQ_HANDLED; |
@@ -429,10 +428,10 @@ static void gpio_keys_quiesce_key(void *data) | |||
429 | { | 428 | { |
430 | struct gpio_button_data *bdata = data; | 429 | struct gpio_button_data *bdata = data; |
431 | 430 | ||
432 | if (bdata->timer_debounce) | 431 | if (gpio_is_valid(bdata->button->gpio)) |
433 | del_timer_sync(&bdata->timer); | 432 | cancel_delayed_work_sync(&bdata->work); |
434 | 433 | else | |
435 | cancel_work_sync(&bdata->work); | 434 | del_timer_sync(&bdata->release_timer); |
436 | } | 435 | } |
437 | 436 | ||
438 | static int gpio_keys_setup_key(struct platform_device *pdev, | 437 | static int gpio_keys_setup_key(struct platform_device *pdev, |
@@ -466,23 +465,25 @@ static int gpio_keys_setup_key(struct platform_device *pdev, | |||
466 | button->debounce_interval * 1000); | 465 | button->debounce_interval * 1000); |
467 | /* use timer if gpiolib doesn't provide debounce */ | 466 | /* use timer if gpiolib doesn't provide debounce */ |
468 | if (error < 0) | 467 | if (error < 0) |
469 | bdata->timer_debounce = | 468 | bdata->software_debounce = |
470 | button->debounce_interval; | 469 | button->debounce_interval; |
471 | } | 470 | } |
472 | 471 | ||
473 | irq = gpio_to_irq(button->gpio); | 472 | if (button->irq) { |
474 | if (irq < 0) { | 473 | bdata->irq = button->irq; |
475 | error = irq; | 474 | } else { |
476 | dev_err(dev, | 475 | irq = gpio_to_irq(button->gpio); |
477 | "Unable to get irq number for GPIO %d, error %d\n", | 476 | if (irq < 0) { |
478 | button->gpio, error); | 477 | error = irq; |
479 | return error; | 478 | dev_err(dev, |
479 | "Unable to get irq number for GPIO %d, error %d\n", | ||
480 | button->gpio, error); | ||
481 | return error; | ||
482 | } | ||
483 | bdata->irq = irq; | ||
480 | } | 484 | } |
481 | bdata->irq = irq; | ||
482 | 485 | ||
483 | INIT_WORK(&bdata->work, gpio_keys_gpio_work_func); | 486 | INIT_DELAYED_WORK(&bdata->work, gpio_keys_gpio_work_func); |
484 | setup_timer(&bdata->timer, | ||
485 | gpio_keys_gpio_timer, (unsigned long)bdata); | ||
486 | 487 | ||
487 | isr = gpio_keys_gpio_isr; | 488 | isr = gpio_keys_gpio_isr; |
488 | irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; | 489 | irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; |
@@ -499,8 +500,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev, | |||
499 | return -EINVAL; | 500 | return -EINVAL; |
500 | } | 501 | } |
501 | 502 | ||
502 | bdata->timer_debounce = button->debounce_interval; | 503 | bdata->release_delay = button->debounce_interval; |
503 | setup_timer(&bdata->timer, | 504 | setup_timer(&bdata->release_timer, |
504 | gpio_keys_irq_timer, (unsigned long)bdata); | 505 | gpio_keys_irq_timer, (unsigned long)bdata); |
505 | 506 | ||
506 | isr = gpio_keys_irq_isr; | 507 | isr = gpio_keys_irq_isr; |
@@ -510,7 +511,7 @@ static int gpio_keys_setup_key(struct platform_device *pdev, | |||
510 | input_set_capability(input, button->type ?: EV_KEY, button->code); | 511 | input_set_capability(input, button->type ?: EV_KEY, button->code); |
511 | 512 | ||
512 | /* | 513 | /* |
513 | * Install custom action to cancel debounce timer and | 514 | * Install custom action to cancel release timer and |
514 | * workqueue item. | 515 | * workqueue item. |
515 | */ | 516 | */ |
516 | error = devm_add_action(&pdev->dev, gpio_keys_quiesce_key, bdata); | 517 | error = devm_add_action(&pdev->dev, gpio_keys_quiesce_key, bdata); |
@@ -618,33 +619,30 @@ gpio_keys_get_devtree_pdata(struct device *dev) | |||
618 | 619 | ||
619 | i = 0; | 620 | i = 0; |
620 | for_each_child_of_node(node, pp) { | 621 | for_each_child_of_node(node, pp) { |
621 | int gpio = -1; | ||
622 | enum of_gpio_flags flags; | 622 | enum of_gpio_flags flags; |
623 | 623 | ||
624 | button = &pdata->buttons[i++]; | 624 | button = &pdata->buttons[i++]; |
625 | 625 | ||
626 | if (!of_find_property(pp, "gpios", NULL)) { | 626 | button->gpio = of_get_gpio_flags(pp, 0, &flags); |
627 | button->irq = irq_of_parse_and_map(pp, 0); | 627 | if (button->gpio < 0) { |
628 | if (button->irq == 0) { | 628 | error = button->gpio; |
629 | i--; | 629 | if (error != -ENOENT) { |
630 | pdata->nbuttons--; | ||
631 | dev_warn(dev, "Found button without gpios or irqs\n"); | ||
632 | continue; | ||
633 | } | ||
634 | } else { | ||
635 | gpio = of_get_gpio_flags(pp, 0, &flags); | ||
636 | if (gpio < 0) { | ||
637 | error = gpio; | ||
638 | if (error != -EPROBE_DEFER) | 630 | if (error != -EPROBE_DEFER) |
639 | dev_err(dev, | 631 | dev_err(dev, |
640 | "Failed to get gpio flags, error: %d\n", | 632 | "Failed to get gpio flags, error: %d\n", |
641 | error); | 633 | error); |
642 | return ERR_PTR(error); | 634 | return ERR_PTR(error); |
643 | } | 635 | } |
636 | } else { | ||
637 | button->active_low = flags & OF_GPIO_ACTIVE_LOW; | ||
644 | } | 638 | } |
645 | 639 | ||
646 | button->gpio = gpio; | 640 | button->irq = irq_of_parse_and_map(pp, 0); |
647 | button->active_low = flags & OF_GPIO_ACTIVE_LOW; | 641 | |
642 | if (!gpio_is_valid(button->gpio) && !button->irq) { | ||
643 | dev_err(dev, "Found button without gpios or irqs\n"); | ||
644 | return ERR_PTR(-EINVAL); | ||
645 | } | ||
648 | 646 | ||
649 | if (of_property_read_u32(pp, "linux,code", &button->code)) { | 647 | if (of_property_read_u32(pp, "linux,code", &button->code)) { |
650 | dev_err(dev, "Button without keycode: 0x%x\n", | 648 | dev_err(dev, "Button without keycode: 0x%x\n", |
@@ -659,6 +657,8 @@ gpio_keys_get_devtree_pdata(struct device *dev) | |||
659 | 657 | ||
660 | button->wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL); | 658 | button->wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL); |
661 | 659 | ||
660 | button->can_disable = !!of_get_property(pp, "linux,can-disable", NULL); | ||
661 | |||
662 | if (of_property_read_u32(pp, "debounce-interval", | 662 | if (of_property_read_u32(pp, "debounce-interval", |
663 | &button->debounce_interval)) | 663 | &button->debounce_interval)) |
664 | button->debounce_interval = 5; | 664 | button->debounce_interval = 5; |