Commit 8ed92556 authored by Dmitry Torokhov's avatar Dmitry Torokhov

Input: gpio_keys - replace timer and workqueue with delayed workqueue

We do not need to roll our own implementation of delayed work now that we
have proper implementation of mod_delayed_work.

For interrupt-only driven buttons we retain the timer, but we rename
it to release_timer to better reflect its purpose.
Tested-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
parent 97d86e07
...@@ -35,9 +35,13 @@ ...@@ -35,9 +35,13 @@
struct gpio_button_data { struct gpio_button_data {
const struct gpio_keys_button *button; const struct gpio_keys_button *button;
struct input_dev *input; struct input_dev *input;
struct timer_list timer;
struct work_struct work; struct timer_list release_timer;
unsigned int timer_debounce; /* in msecs */ unsigned int release_delay; /* in msecs, for IRQ-only buttons */
struct delayed_work work;
unsigned int software_debounce; /* in msecs, for GPIO-driven buttons */
unsigned int irq; unsigned int irq;
spinlock_t lock; spinlock_t lock;
bool disabled; bool disabled;
...@@ -116,11 +120,14 @@ static void gpio_keys_disable_button(struct gpio_button_data *bdata) ...@@ -116,11 +120,14 @@ static void gpio_keys_disable_button(struct gpio_button_data *bdata)
{ {
if (!bdata->disabled) { if (!bdata->disabled) {
/* /*
* Disable IRQ and possible debouncing timer. * Disable IRQ and associated timer/work structure.
*/ */
disable_irq(bdata->irq); disable_irq(bdata->irq);
if (bdata->timer_debounce)
del_timer_sync(&bdata->timer); if (gpio_is_valid(bdata->button->gpio))
cancel_delayed_work_sync(&bdata->work);
else
del_timer_sync(&bdata->release_timer);
bdata->disabled = true; bdata->disabled = true;
} }
...@@ -343,7 +350,7 @@ static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata) ...@@ -343,7 +350,7 @@ static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata)
static void gpio_keys_gpio_work_func(struct work_struct *work) static void gpio_keys_gpio_work_func(struct work_struct *work)
{ {
struct gpio_button_data *bdata = struct gpio_button_data *bdata =
container_of(work, struct gpio_button_data, work); container_of(work, struct gpio_button_data, work.work);
gpio_keys_gpio_report_event(bdata); gpio_keys_gpio_report_event(bdata);
...@@ -351,13 +358,6 @@ static void gpio_keys_gpio_work_func(struct work_struct *work) ...@@ -351,13 +358,6 @@ static void gpio_keys_gpio_work_func(struct work_struct *work)
pm_relax(bdata->input->dev.parent); pm_relax(bdata->input->dev.parent);
} }
static void gpio_keys_gpio_timer(unsigned long _data)
{
struct gpio_button_data *bdata = (struct gpio_button_data *)_data;
schedule_work(&bdata->work);
}
static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id) static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id)
{ {
struct gpio_button_data *bdata = dev_id; struct gpio_button_data *bdata = dev_id;
...@@ -366,11 +366,10 @@ static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id) ...@@ -366,11 +366,10 @@ static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id)
if (bdata->button->wakeup) if (bdata->button->wakeup)
pm_stay_awake(bdata->input->dev.parent); pm_stay_awake(bdata->input->dev.parent);
if (bdata->timer_debounce)
mod_timer(&bdata->timer, mod_delayed_work(system_wq,
jiffies + msecs_to_jiffies(bdata->timer_debounce)); &bdata->work,
else msecs_to_jiffies(bdata->software_debounce));
schedule_work(&bdata->work);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -408,7 +407,7 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id) ...@@ -408,7 +407,7 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id)
input_event(input, EV_KEY, button->code, 1); input_event(input, EV_KEY, button->code, 1);
input_sync(input); input_sync(input);
if (!bdata->timer_debounce) { if (!bdata->release_delay) {
input_event(input, EV_KEY, button->code, 0); input_event(input, EV_KEY, button->code, 0);
input_sync(input); input_sync(input);
goto out; goto out;
...@@ -417,9 +416,9 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id) ...@@ -417,9 +416,9 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id)
bdata->key_pressed = true; bdata->key_pressed = true;
} }
if (bdata->timer_debounce) if (bdata->release_delay)
mod_timer(&bdata->timer, mod_timer(&bdata->release_timer,
jiffies + msecs_to_jiffies(bdata->timer_debounce)); jiffies + msecs_to_jiffies(bdata->release_delay));
out: out:
spin_unlock_irqrestore(&bdata->lock, flags); spin_unlock_irqrestore(&bdata->lock, flags);
return IRQ_HANDLED; return IRQ_HANDLED;
...@@ -429,10 +428,10 @@ static void gpio_keys_quiesce_key(void *data) ...@@ -429,10 +428,10 @@ static void gpio_keys_quiesce_key(void *data)
{ {
struct gpio_button_data *bdata = data; struct gpio_button_data *bdata = data;
if (bdata->timer_debounce) if (gpio_is_valid(bdata->button->gpio))
del_timer_sync(&bdata->timer); cancel_delayed_work_sync(&bdata->work);
else
cancel_work_sync(&bdata->work); del_timer_sync(&bdata->release_timer);
} }
static int gpio_keys_setup_key(struct platform_device *pdev, static int gpio_keys_setup_key(struct platform_device *pdev,
...@@ -466,7 +465,7 @@ static int gpio_keys_setup_key(struct platform_device *pdev, ...@@ -466,7 +465,7 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
button->debounce_interval * 1000); button->debounce_interval * 1000);
/* use timer if gpiolib doesn't provide debounce */ /* use timer if gpiolib doesn't provide debounce */
if (error < 0) if (error < 0)
bdata->timer_debounce = bdata->software_debounce =
button->debounce_interval; button->debounce_interval;
} }
...@@ -484,9 +483,7 @@ static int gpio_keys_setup_key(struct platform_device *pdev, ...@@ -484,9 +483,7 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
bdata->irq = irq; bdata->irq = irq;
} }
INIT_WORK(&bdata->work, gpio_keys_gpio_work_func); INIT_DELAYED_WORK(&bdata->work, gpio_keys_gpio_work_func);
setup_timer(&bdata->timer,
gpio_keys_gpio_timer, (unsigned long)bdata);
isr = gpio_keys_gpio_isr; isr = gpio_keys_gpio_isr;
irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
...@@ -503,8 +500,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev, ...@@ -503,8 +500,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
return -EINVAL; return -EINVAL;
} }
bdata->timer_debounce = button->debounce_interval; bdata->release_delay = button->debounce_interval;
setup_timer(&bdata->timer, setup_timer(&bdata->release_timer,
gpio_keys_irq_timer, (unsigned long)bdata); gpio_keys_irq_timer, (unsigned long)bdata);
isr = gpio_keys_irq_isr; isr = gpio_keys_irq_isr;
...@@ -514,7 +511,7 @@ static int gpio_keys_setup_key(struct platform_device *pdev, ...@@ -514,7 +511,7 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
input_set_capability(input, button->type ?: EV_KEY, button->code); input_set_capability(input, button->type ?: EV_KEY, button->code);
/* /*
* Install custom action to cancel debounce timer and * Install custom action to cancel release timer and
* workqueue item. * workqueue item.
*/ */
error = devm_add_action(&pdev->dev, gpio_keys_quiesce_key, bdata); error = devm_add_action(&pdev->dev, gpio_keys_quiesce_key, bdata);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment