Skip to content

Commit f1fbff6

Browse files
committed
Input: qt2160 - switch to using threaded interrupt handler
Instead of using combination of normal IRQ and work item which required careful handling on device teardown, use standard threaded interrupt that allows communication wityh the chip over slow (I2C) bus directly in the interrupt handler. To support polling mode switch to standard polling support implemented by the input core. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Dmitry Torokhov <[email protected]>
1 parent f94c3bc commit f1fbff6

File tree

1 file changed

+19
-34
lines changed

1 file changed

+19
-34
lines changed

drivers/input/keyboard/qt2160.c

Lines changed: 19 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232

3333
#define QT2160_NUM_LEDS_X 8
3434

35-
#define QT2160_CYCLE_INTERVAL (2*HZ)
35+
#define QT2160_CYCLE_INTERVAL 2000 /* msec - 2 sec */
3636

3737
static unsigned char qt2160_key2code[] = {
3838
KEY_0, KEY_1, KEY_2, KEY_3,
@@ -54,7 +54,6 @@ struct qt2160_led {
5454
struct qt2160_data {
5555
struct i2c_client *client;
5656
struct input_dev *input;
57-
struct delayed_work dwork;
5857
unsigned short keycodes[ARRAY_SIZE(qt2160_key2code)];
5958
u16 key_matrix;
6059
#ifdef CONFIG_LEDS_CLASS
@@ -155,10 +154,10 @@ static int qt2160_read_block(struct i2c_client *client,
155154
return 0;
156155
}
157156

158-
static int qt2160_get_key_matrix(struct qt2160_data *qt2160)
157+
static void qt2160_get_key_matrix(struct input_dev *input)
159158
{
159+
struct qt2160_data *qt2160 = input_get_drvdata(input);
160160
struct i2c_client *client = qt2160->client;
161-
struct input_dev *input = qt2160->input;
162161
u8 regs[6];
163162
u16 old_matrix, new_matrix;
164163
int ret, i, mask;
@@ -173,7 +172,7 @@ static int qt2160_get_key_matrix(struct qt2160_data *qt2160)
173172
if (ret) {
174173
dev_err(&client->dev,
175174
"could not perform chip read.\n");
176-
return ret;
175+
return;
177176
}
178177

179178
old_matrix = qt2160->key_matrix;
@@ -191,37 +190,17 @@ static int qt2160_get_key_matrix(struct qt2160_data *qt2160)
191190
}
192191

193192
input_sync(input);
194-
195-
return 0;
196193
}
197194

198-
static irqreturn_t qt2160_irq(int irq, void *_qt2160)
195+
static irqreturn_t qt2160_irq(int irq, void *data)
199196
{
200-
struct qt2160_data *qt2160 = _qt2160;
197+
struct input_dev *input = data;
201198

202-
mod_delayed_work(system_wq, &qt2160->dwork, 0);
199+
qt2160_get_key_matrix(input);
203200

204201
return IRQ_HANDLED;
205202
}
206203

207-
static void qt2160_schedule_read(struct qt2160_data *qt2160)
208-
{
209-
schedule_delayed_work(&qt2160->dwork, QT2160_CYCLE_INTERVAL);
210-
}
211-
212-
static void qt2160_worker(struct work_struct *work)
213-
{
214-
struct qt2160_data *qt2160 =
215-
container_of(work, struct qt2160_data, dwork.work);
216-
217-
dev_dbg(&qt2160->client->dev, "worker\n");
218-
219-
qt2160_get_key_matrix(qt2160);
220-
221-
/* Avoid device lock up by checking every so often */
222-
qt2160_schedule_read(qt2160);
223-
}
224-
225204
static int qt2160_read(struct i2c_client *client, u8 reg)
226205
{
227206
int ret;
@@ -365,7 +344,6 @@ static int qt2160_probe(struct i2c_client *client)
365344

366345
qt2160->client = client;
367346
qt2160->input = input;
368-
INIT_DELAYED_WORK(&qt2160->dwork, qt2160_worker);
369347

370348
input->name = "AT42QT2160 Touch Sense Keyboard";
371349
input->id.bustype = BUS_I2C;
@@ -382,6 +360,8 @@ static int qt2160_probe(struct i2c_client *client)
382360
}
383361
__clear_bit(KEY_RESERVED, input->keybit);
384362

363+
input_set_drvdata(input, qt2160);
364+
385365
/* Calibrate device */
386366
error = qt2160_write(client, QT2160_CMD_CALIBRATE, 1);
387367
if (error) {
@@ -390,13 +370,21 @@ static int qt2160_probe(struct i2c_client *client)
390370
}
391371

392372
if (client->irq) {
393-
error = request_irq(client->irq, qt2160_irq,
394-
IRQF_TRIGGER_FALLING, "qt2160", qt2160);
373+
error = request_threaded_irq(client->irq, NULL, qt2160_irq,
374+
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
375+
"qt2160", input);
395376
if (error) {
396377
dev_err(&client->dev,
397378
"failed to allocate irq %d\n", client->irq);
398379
goto err_free_mem;
399380
}
381+
} else {
382+
error = input_setup_polling(input, qt2160_get_key_matrix);
383+
if (error) {
384+
dev_err(&client->dev, "Failed to setup polling\n");
385+
goto err_free_mem;
386+
}
387+
input_set_poll_interval(input, QT2160_CYCLE_INTERVAL);
400388
}
401389

402390
error = qt2160_register_leds(qt2160);
@@ -413,7 +401,6 @@ static int qt2160_probe(struct i2c_client *client)
413401
}
414402

415403
i2c_set_clientdata(client, qt2160);
416-
qt2160_schedule_read(qt2160);
417404

418405
return 0;
419406

@@ -438,8 +425,6 @@ static void qt2160_remove(struct i2c_client *client)
438425
if (client->irq)
439426
free_irq(client->irq, qt2160);
440427

441-
cancel_delayed_work_sync(&qt2160->dwork);
442-
443428
input_unregister_device(qt2160->input);
444429
kfree(qt2160);
445430
}

0 commit comments

Comments
 (0)