提交 dee520e3 编写于 作者: T Timo Teräs 提交者: Dmitry Torokhov

Input: rotary_encoder - use threaded irqs

Convert to use threaded IRQs to support GPIOs that can sleep.
Protect the irq handler with mutex as it can be triggered from
two different irq lines accessing the same state.

This allows using GPIO expanders behind I2C or SPI bus.
Signed-off-by: NTimo Teräs <timo.teras@iki.fi>
Signed-off-by: NDmitry Torokhov <dmitry.torokhov@gmail.com>
上级 d9202af2
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
struct rotary_encoder { struct rotary_encoder {
struct input_dev *input; struct input_dev *input;
const struct rotary_encoder_platform_data *pdata; const struct rotary_encoder_platform_data *pdata;
struct mutex access_mutex;
unsigned int axis; unsigned int axis;
unsigned int pos; unsigned int pos;
...@@ -48,8 +49,8 @@ struct rotary_encoder { ...@@ -48,8 +49,8 @@ struct rotary_encoder {
static int rotary_encoder_get_state(const struct rotary_encoder_platform_data *pdata) static int rotary_encoder_get_state(const struct rotary_encoder_platform_data *pdata)
{ {
int a = !!gpio_get_value(pdata->gpio_a); int a = !!gpio_get_value_cansleep(pdata->gpio_a);
int b = !!gpio_get_value(pdata->gpio_b); int b = !!gpio_get_value_cansleep(pdata->gpio_b);
a ^= pdata->inverted_a; a ^= pdata->inverted_a;
b ^= pdata->inverted_b; b ^= pdata->inverted_b;
...@@ -94,6 +95,8 @@ static irqreturn_t rotary_encoder_irq(int irq, void *dev_id) ...@@ -94,6 +95,8 @@ static irqreturn_t rotary_encoder_irq(int irq, void *dev_id)
struct rotary_encoder *encoder = dev_id; struct rotary_encoder *encoder = dev_id;
int state; int state;
mutex_lock(&encoder->access_mutex);
state = rotary_encoder_get_state(encoder->pdata); state = rotary_encoder_get_state(encoder->pdata);
switch (state) { switch (state) {
...@@ -115,6 +118,8 @@ static irqreturn_t rotary_encoder_irq(int irq, void *dev_id) ...@@ -115,6 +118,8 @@ static irqreturn_t rotary_encoder_irq(int irq, void *dev_id)
break; break;
} }
mutex_unlock(&encoder->access_mutex);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -123,6 +128,8 @@ static irqreturn_t rotary_encoder_half_period_irq(int irq, void *dev_id) ...@@ -123,6 +128,8 @@ static irqreturn_t rotary_encoder_half_period_irq(int irq, void *dev_id)
struct rotary_encoder *encoder = dev_id; struct rotary_encoder *encoder = dev_id;
int state; int state;
mutex_lock(&encoder->access_mutex);
state = rotary_encoder_get_state(encoder->pdata); state = rotary_encoder_get_state(encoder->pdata);
switch (state) { switch (state) {
...@@ -140,6 +147,8 @@ static irqreturn_t rotary_encoder_half_period_irq(int irq, void *dev_id) ...@@ -140,6 +147,8 @@ static irqreturn_t rotary_encoder_half_period_irq(int irq, void *dev_id)
break; break;
} }
mutex_unlock(&encoder->access_mutex);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -149,6 +158,8 @@ static irqreturn_t rotary_encoder_quarter_period_irq(int irq, void *dev_id) ...@@ -149,6 +158,8 @@ static irqreturn_t rotary_encoder_quarter_period_irq(int irq, void *dev_id)
unsigned char sum; unsigned char sum;
int state; int state;
mutex_lock(&encoder->access_mutex);
state = rotary_encoder_get_state(encoder->pdata); state = rotary_encoder_get_state(encoder->pdata);
/* /*
...@@ -189,6 +200,8 @@ static irqreturn_t rotary_encoder_quarter_period_irq(int irq, void *dev_id) ...@@ -189,6 +200,8 @@ static irqreturn_t rotary_encoder_quarter_period_irq(int irq, void *dev_id)
out: out:
encoder->last_stable = state; encoder->last_stable = state;
mutex_unlock(&encoder->access_mutex);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -285,6 +298,8 @@ static int rotary_encoder_probe(struct platform_device *pdev) ...@@ -285,6 +298,8 @@ static int rotary_encoder_probe(struct platform_device *pdev)
if (!input) if (!input)
return -ENOMEM; return -ENOMEM;
mutex_init(&encoder->access_mutex);
encoder->input = input; encoder->input = input;
encoder->pdata = pdata; encoder->pdata = pdata;
...@@ -337,17 +352,19 @@ static int rotary_encoder_probe(struct platform_device *pdev) ...@@ -337,17 +352,19 @@ static int rotary_encoder_probe(struct platform_device *pdev)
return -EINVAL; return -EINVAL;
} }
err = devm_request_irq(dev, encoder->irq_a, handler, err = devm_request_threaded_irq(dev, encoder->irq_a, NULL, handler,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
DRV_NAME, encoder); IRQF_ONESHOT,
DRV_NAME, encoder);
if (err) { if (err) {
dev_err(dev, "unable to request IRQ %d\n", encoder->irq_a); dev_err(dev, "unable to request IRQ %d\n", encoder->irq_a);
return err; return err;
} }
err = devm_request_irq(dev, encoder->irq_b, handler, err = devm_request_threaded_irq(dev, encoder->irq_b, NULL, handler,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
DRV_NAME, encoder); IRQF_ONESHOT,
DRV_NAME, encoder);
if (err) { if (err) {
dev_err(dev, "unable to request IRQ %d\n", encoder->irq_b); dev_err(dev, "unable to request IRQ %d\n", encoder->irq_b);
return err; return err;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册