aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2016-01-16 23:46:24 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2016-03-02 12:30:06 -0500
commitdee520e368f54e1bc0e387bfda7ef4e0676e248b (patch)
tree10f1ed503f37b5a058241b5169b56a4dd0828162
parentd9202af2ffa083f096684fd5f4b530aebbc07439 (diff)
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 <timo.teras@iki.fi> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
-rw-r--r--drivers/input/misc/rotary_encoder.c33
1 files changed, 25 insertions, 8 deletions
diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c
index ebbadf3f0579..aeeaaea69610 100644
--- a/drivers/input/misc/rotary_encoder.c
+++ b/drivers/input/misc/rotary_encoder.c
@@ -33,6 +33,7 @@
33struct rotary_encoder { 33struct rotary_encoder {
34 struct input_dev *input; 34 struct input_dev *input;
35 const struct rotary_encoder_platform_data *pdata; 35 const struct rotary_encoder_platform_data *pdata;
36 struct mutex access_mutex;
36 37
37 unsigned int axis; 38 unsigned int axis;
38 unsigned int pos; 39 unsigned int pos;
@@ -48,8 +49,8 @@ struct rotary_encoder {
48 49
49static int rotary_encoder_get_state(const struct rotary_encoder_platform_data *pdata) 50static int rotary_encoder_get_state(const struct rotary_encoder_platform_data *pdata)
50{ 51{
51 int a = !!gpio_get_value(pdata->gpio_a); 52 int a = !!gpio_get_value_cansleep(pdata->gpio_a);
52 int b = !!gpio_get_value(pdata->gpio_b); 53 int b = !!gpio_get_value_cansleep(pdata->gpio_b);
53 54
54 a ^= pdata->inverted_a; 55 a ^= pdata->inverted_a;
55 b ^= pdata->inverted_b; 56 b ^= pdata->inverted_b;
@@ -94,6 +95,8 @@ static irqreturn_t rotary_encoder_irq(int irq, void *dev_id)
94 struct rotary_encoder *encoder = dev_id; 95 struct rotary_encoder *encoder = dev_id;
95 int state; 96 int state;
96 97
98 mutex_lock(&encoder->access_mutex);
99
97 state = rotary_encoder_get_state(encoder->pdata); 100 state = rotary_encoder_get_state(encoder->pdata);
98 101
99 switch (state) { 102 switch (state) {
@@ -115,6 +118,8 @@ static irqreturn_t rotary_encoder_irq(int irq, void *dev_id)
115 break; 118 break;
116 } 119 }
117 120
121 mutex_unlock(&encoder->access_mutex);
122
118 return IRQ_HANDLED; 123 return IRQ_HANDLED;
119} 124}
120 125
@@ -123,6 +128,8 @@ static irqreturn_t rotary_encoder_half_period_irq(int irq, void *dev_id)
123 struct rotary_encoder *encoder = dev_id; 128 struct rotary_encoder *encoder = dev_id;
124 int state; 129 int state;
125 130
131 mutex_lock(&encoder->access_mutex);
132
126 state = rotary_encoder_get_state(encoder->pdata); 133 state = rotary_encoder_get_state(encoder->pdata);
127 134
128 switch (state) { 135 switch (state) {
@@ -140,6 +147,8 @@ static irqreturn_t rotary_encoder_half_period_irq(int irq, void *dev_id)
140 break; 147 break;
141 } 148 }
142 149
150 mutex_unlock(&encoder->access_mutex);
151
143 return IRQ_HANDLED; 152 return IRQ_HANDLED;
144} 153}
145 154
@@ -149,6 +158,8 @@ static irqreturn_t rotary_encoder_quarter_period_irq(int irq, void *dev_id)
149 unsigned char sum; 158 unsigned char sum;
150 int state; 159 int state;
151 160
161 mutex_lock(&encoder->access_mutex);
162
152 state = rotary_encoder_get_state(encoder->pdata); 163 state = rotary_encoder_get_state(encoder->pdata);
153 164
154 /* 165 /*
@@ -189,6 +200,8 @@ static irqreturn_t rotary_encoder_quarter_period_irq(int irq, void *dev_id)
189 200
190out: 201out:
191 encoder->last_stable = state; 202 encoder->last_stable = state;
203 mutex_unlock(&encoder->access_mutex);
204
192 return IRQ_HANDLED; 205 return IRQ_HANDLED;
193} 206}
194 207
@@ -285,6 +298,8 @@ static int rotary_encoder_probe(struct platform_device *pdev)
285 if (!input) 298 if (!input)
286 return -ENOMEM; 299 return -ENOMEM;
287 300
301 mutex_init(&encoder->access_mutex);
302
288 encoder->input = input; 303 encoder->input = input;
289 encoder->pdata = pdata; 304 encoder->pdata = pdata;
290 305
@@ -337,17 +352,19 @@ static int rotary_encoder_probe(struct platform_device *pdev)
337 return -EINVAL; 352 return -EINVAL;
338 } 353 }
339 354
340 err = devm_request_irq(dev, encoder->irq_a, handler, 355 err = devm_request_threaded_irq(dev, encoder->irq_a, NULL, handler,
341 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 356 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
342 DRV_NAME, encoder); 357 IRQF_ONESHOT,
358 DRV_NAME, encoder);
343 if (err) { 359 if (err) {
344 dev_err(dev, "unable to request IRQ %d\n", encoder->irq_a); 360 dev_err(dev, "unable to request IRQ %d\n", encoder->irq_a);
345 return err; 361 return err;
346 } 362 }
347 363
348 err = devm_request_irq(dev, encoder->irq_b, handler, 364 err = devm_request_threaded_irq(dev, encoder->irq_b, NULL, handler,
349 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 365 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
350 DRV_NAME, encoder); 366 IRQF_ONESHOT,
367 DRV_NAME, encoder);
351 if (err) { 368 if (err) {
352 dev_err(dev, "unable to request IRQ %d\n", encoder->irq_b); 369 dev_err(dev, "unable to request IRQ %d\n", encoder->irq_b);
353 return err; 370 return err;