Skip to content

Commit dee520e

Browse files
fableddtor
authored andcommitted
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: Timo Teräs <[email protected]> Signed-off-by: Dmitry Torokhov <[email protected]>
1 parent d9202af commit dee520e

File tree

1 file changed

+25
-8
lines changed

1 file changed

+25
-8
lines changed

drivers/input/misc/rotary_encoder.c

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
struct rotary_encoder {
3434
struct input_dev *input;
3535
const struct rotary_encoder_platform_data *pdata;
36+
struct mutex access_mutex;
3637

3738
unsigned int axis;
3839
unsigned int pos;
@@ -48,8 +49,8 @@ struct rotary_encoder {
4849

4950
static int rotary_encoder_get_state(const struct rotary_encoder_platform_data *pdata)
5051
{
51-
int a = !!gpio_get_value(pdata->gpio_a);
52-
int b = !!gpio_get_value(pdata->gpio_b);
52+
int a = !!gpio_get_value_cansleep(pdata->gpio_a);
53+
int b = !!gpio_get_value_cansleep(pdata->gpio_b);
5354

5455
a ^= pdata->inverted_a;
5556
b ^= pdata->inverted_b;
@@ -94,6 +95,8 @@ static irqreturn_t rotary_encoder_irq(int irq, void *dev_id)
9495
struct rotary_encoder *encoder = dev_id;
9596
int state;
9697

98+
mutex_lock(&encoder->access_mutex);
99+
97100
state = rotary_encoder_get_state(encoder->pdata);
98101

99102
switch (state) {
@@ -115,6 +118,8 @@ static irqreturn_t rotary_encoder_irq(int irq, void *dev_id)
115118
break;
116119
}
117120

121+
mutex_unlock(&encoder->access_mutex);
122+
118123
return IRQ_HANDLED;
119124
}
120125

@@ -123,6 +128,8 @@ static irqreturn_t rotary_encoder_half_period_irq(int irq, void *dev_id)
123128
struct rotary_encoder *encoder = dev_id;
124129
int state;
125130

131+
mutex_lock(&encoder->access_mutex);
132+
126133
state = rotary_encoder_get_state(encoder->pdata);
127134

128135
switch (state) {
@@ -140,6 +147,8 @@ static irqreturn_t rotary_encoder_half_period_irq(int irq, void *dev_id)
140147
break;
141148
}
142149

150+
mutex_unlock(&encoder->access_mutex);
151+
143152
return IRQ_HANDLED;
144153
}
145154

@@ -149,6 +158,8 @@ static irqreturn_t rotary_encoder_quarter_period_irq(int irq, void *dev_id)
149158
unsigned char sum;
150159
int state;
151160

161+
mutex_lock(&encoder->access_mutex);
162+
152163
state = rotary_encoder_get_state(encoder->pdata);
153164

154165
/*
@@ -189,6 +200,8 @@ static irqreturn_t rotary_encoder_quarter_period_irq(int irq, void *dev_id)
189200

190201
out:
191202
encoder->last_stable = state;
203+
mutex_unlock(&encoder->access_mutex);
204+
192205
return IRQ_HANDLED;
193206
}
194207

@@ -285,6 +298,8 @@ static int rotary_encoder_probe(struct platform_device *pdev)
285298
if (!input)
286299
return -ENOMEM;
287300

301+
mutex_init(&encoder->access_mutex);
302+
288303
encoder->input = input;
289304
encoder->pdata = pdata;
290305

@@ -337,17 +352,19 @@ static int rotary_encoder_probe(struct platform_device *pdev)
337352
return -EINVAL;
338353
}
339354

340-
err = devm_request_irq(dev, encoder->irq_a, handler,
341-
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
342-
DRV_NAME, encoder);
355+
err = devm_request_threaded_irq(dev, encoder->irq_a, NULL, handler,
356+
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
357+
IRQF_ONESHOT,
358+
DRV_NAME, encoder);
343359
if (err) {
344360
dev_err(dev, "unable to request IRQ %d\n", encoder->irq_a);
345361
return err;
346362
}
347363

348-
err = devm_request_irq(dev, encoder->irq_b, handler,
349-
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
350-
DRV_NAME, encoder);
364+
err = devm_request_threaded_irq(dev, encoder->irq_b, NULL, handler,
365+
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
366+
IRQF_ONESHOT,
367+
DRV_NAME, encoder);
351368
if (err) {
352369
dev_err(dev, "unable to request IRQ %d\n", encoder->irq_b);
353370
return err;

0 commit comments

Comments
 (0)