Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Input: ads7846 - handle IRQs that were latched during disabled IRQs

The pen down IRQ will toggle during each X,Y,Z measurement cycle.
Even though the IRQ is disabled it will be latched and delivered
when after enable_irq. Thus in the IRQ handler we must avoid
starting a new measurement cycle when such an "unwanted" IRQ happens.
Add a get_pendown_state platform function, which will probably
determine this by reading the current GPIO level of the pen IRQ pin.

Move the IRQ reenabling from the SPI RX function to the timer. After
the last power down message the pen IRQ pin is still active for a
while and get_pendown_state would report incorrectly a pen down state.

When suspending we should check the ts->pending flag instead of
ts->pendown, since the timer can be pending regardless of ts->pendown.
Also if ts->pending is set we can be sure that the timer is running,
so no need to rearm it. Similarly if ts->pending is not set we can
be sure that the IRQ is enabled (and the timer is not).

Signed-off-by: Imre Deak <imre.deak@nokia.com>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>

authored by

Imre Deak and committed by
Dmitry Torokhov
c9e617a5 7de90a8c

+52 -36
+50 -36
drivers/input/touchscreen/ads7846.c
··· 102 102 // FIXME remove "irq_disabled" 103 103 unsigned irq_disabled:1; /* P: lock */ 104 104 unsigned disabled:1; 105 + 106 + int (*get_pendown_state)(void); 105 107 }; 106 108 107 109 /* leave chip selected when we're done, for quicker re-select? */ ··· 177 175 static void ads7846_enable(struct ads7846 *ts); 178 176 static void ads7846_disable(struct ads7846 *ts); 179 177 178 + static int device_suspended(struct device *dev) 179 + { 180 + struct ads7846 *ts = dev_get_drvdata(dev); 181 + return dev->power.power_state.event != PM_EVENT_ON || ts->disabled; 182 + } 183 + 180 184 static int ads7846_read12_ser(struct device *dev, unsigned command) 181 185 { 182 186 struct spi_device *spi = to_spi_device(dev); ··· 235 227 for (i = 0; i < 6; i++) 236 228 spi_message_add_tail(&req->xfer[i], &req->msg); 237 229 230 + ts->irq_disabled = 1; 238 231 disable_irq(spi->irq); 239 232 status = spi_sync(spi, &req->msg); 233 + ts->irq_disabled = 0; 240 234 enable_irq(spi->irq); 241 235 242 236 if (req->msg.status) ··· 343 333 if (x == MAX_12BIT) 344 334 x = 0; 345 335 346 - if (x && z1 && ts->spi->dev.power.power_state.event == PM_EVENT_ON) { 336 + if (likely(x && z1 && !device_suspended(&ts->spi->dev))) { 347 337 /* compute touch pressure resistance using equation #2 */ 348 338 Rt = z2; 349 339 Rt -= z1; ··· 387 377 x, y, Rt, Rt ? "" : " UP"); 388 378 #endif 389 379 390 - /* don't retrigger while we're suspended */ 391 380 spin_lock_irqsave(&ts->lock, flags); 392 381 393 382 ts->pendown = (Rt != 0); 394 - ts->pending = 0; 395 - 396 - if (ts->spi->dev.power.power_state.event == PM_EVENT_ON) { 397 - if (ts->pendown) 398 - mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD); 399 - else if (ts->irq_disabled) { 400 - ts->irq_disabled = 0; 401 - enable_irq(ts->spi->irq); 402 - } 403 - } 383 + mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD); 404 384 405 385 spin_unlock_irqrestore(&ts->lock, flags); 406 386 } ··· 431 431 struct ads7846 *ts = (void *)handle; 432 432 int status = 0; 433 433 434 - ts->msg_idx = 0; 435 - status = spi_async(ts->spi, &ts->msg[0]); 436 - if (status) 437 - dev_err(&ts->spi->dev, "spi_async --> %d\n", status); 434 + spin_lock_irq(&ts->lock); 435 + 436 + if (unlikely(ts->msg_idx && !ts->pendown)) { 437 + /* measurment cycle ended */ 438 + if (!device_suspended(&ts->spi->dev)) { 439 + ts->irq_disabled = 0; 440 + enable_irq(ts->spi->irq); 441 + } 442 + ts->pending = 0; 443 + ts->msg_idx = 0; 444 + } else { 445 + /* pen is still down, continue with the measurement */ 446 + ts->msg_idx = 0; 447 + status = spi_async(ts->spi, &ts->msg[0]); 448 + if (status) 449 + dev_err(&ts->spi->dev, "spi_async --> %d\n", status); 450 + } 451 + 452 + spin_unlock_irq(&ts->lock); 438 453 } 439 454 440 455 static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs) ··· 458 443 unsigned long flags; 459 444 460 445 spin_lock_irqsave(&ts->lock, flags); 461 - if (likely(!ts->irq_disabled && !ts->disabled)) { 446 + if (likely(ts->get_pendown_state())) { 462 447 if (!ts->irq_disabled) { 463 448 /* REVISIT irq logic for many ARM chips has cloned a 464 449 * bug wherein disabling an irq in its handler won't ··· 467 452 * that state here. 468 453 */ 469 454 ts->irq_disabled = 1; 470 - 471 455 disable_irq(ts->spi->irq); 472 - } 473 - if (!ts->pending) { 474 456 ts->pending = 1; 475 457 mod_timer(&ts->timer, jiffies); 476 458 } ··· 485 473 if (ts->disabled) 486 474 return; 487 475 488 - /* are we waiting for IRQ, or polling? */ 489 - if (!ts->pendown) { 490 - if (!ts->irq_disabled) { 491 - ts->irq_disabled = 1; 492 - disable_irq(ts->spi->irq); 493 - } 494 - } else { 495 - /* polling; force a final SPI completion; 496 - * that will clean things up neatly 497 - */ 498 - if (!ts->pending) 499 - mod_timer(&ts->timer, jiffies); 476 + ts->disabled = 1; 500 477 501 - while (ts->pendown || ts->pending) { 478 + /* are we waiting for IRQ, or polling? */ 479 + if (!ts->pending) { 480 + ts->irq_disabled = 1; 481 + disable_irq(ts->spi->irq); 482 + } else { 483 + /* the timer will run at least once more, and 484 + * leave everything in a clean state, IRQ disabled 485 + */ 486 + while (ts->pending) { 502 487 spin_unlock_irq(&ts->lock); 503 488 msleep(1); 504 489 spin_lock_irq(&ts->lock); ··· 506 497 * leave it that way after every request 507 498 */ 508 499 509 - ts->disabled = 1; 510 500 } 511 501 512 502 /* Must be called with ts->lock held */ ··· 574 566 return -EINVAL; 575 567 } 576 568 569 + if (pdata->get_pendown_state == NULL) { 570 + dev_dbg(&spi->dev, "no get_pendown_state function?\n"); 571 + return -EINVAL; 572 + } 573 + 577 574 /* We'd set the wordsize to 12 bits ... except that some controllers 578 575 * will then treat the 8 bit command words as 12 bits (and drop the 579 576 * four MSBs of the 12 bit result). Result: inputs must be shifted ··· 609 596 ts->x_plate_ohms = pdata->x_plate_ohms ? : 400; 610 597 ts->debounce_max = pdata->debounce_max ? : 1; 611 598 ts->debounce_tol = pdata->debounce_tol ? : 10; 599 + ts->get_pendown_state = pdata->get_pendown_state; 612 600 613 601 snprintf(ts->phys, sizeof(ts->phys), "%s/input0", spi->dev.bus_id); 614 602 ··· 800 786 device_remove_file(&spi->dev, &dev_attr_vaux); 801 787 802 788 free_irq(ts->spi->irq, ts); 803 - if (ts->irq_disabled) 804 - enable_irq(ts->spi->irq); 789 + /* suspend left the IRQ disabled */ 790 + enable_irq(ts->spi->irq); 805 791 806 792 kfree(ts); 807 793
+2
include/linux/spi/ads7846.h
··· 17 17 18 18 u16 debounce_max; /* max number of readings per sample */ 19 19 u16 debounce_tol; /* tolerance used for filtering */ 20 + 21 + int (*get_pendown_state)(void); 20 22 }; 21 23