diff options
| author | Felipe Balbi <balbi@ti.com> | 2011-06-30 05:51:08 -0400 |
|---|---|---|
| committer | Samuel Ortiz <sameo@linux.intel.com> | 2011-10-24 08:09:11 -0400 |
| commit | 2f2a7d5ef76477f3d2a333663e7cf7a380aebd82 (patch) | |
| tree | 131cb39fa704c169b034befa3aa3e38593d2ef9d /drivers/mfd | |
| parent | 848684246fc180a9b96f1b373a1ad70bc3ee725f (diff) | |
mfd: Drop twl4030-irq's edge_work
... and do all the synchronization with the
hardware during bus_sync_unlock. We can now
remove all the workqueues.
Signed-off-by: Felipe Balbi <balbi@ti.com>
Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd')
| -rw-r--r-- | drivers/mfd/twl4030-irq.c | 124 |
1 files changed, 52 insertions, 72 deletions
diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c index bf62389fc7e5..1b9ab2f40d5b 100644 --- a/drivers/mfd/twl4030-irq.c +++ b/drivers/mfd/twl4030-irq.c | |||
| @@ -422,8 +422,6 @@ static inline void activate_irq(int irq) | |||
| 422 | 422 | ||
| 423 | /*----------------------------------------------------------------------*/ | 423 | /*----------------------------------------------------------------------*/ |
| 424 | 424 | ||
| 425 | static struct workqueue_struct *wq; | ||
| 426 | |||
| 427 | struct sih_agent { | 425 | struct sih_agent { |
| 428 | int irq_base; | 426 | int irq_base; |
| 429 | const struct sih *sih; | 427 | const struct sih *sih; |
| @@ -432,68 +430,10 @@ struct sih_agent { | |||
| 432 | bool imr_change_pending; | 430 | bool imr_change_pending; |
| 433 | 431 | ||
| 434 | u32 edge_change; | 432 | u32 edge_change; |
| 435 | struct work_struct edge_work; | ||
| 436 | 433 | ||
| 437 | struct mutex irq_lock; | 434 | struct mutex irq_lock; |
| 438 | }; | 435 | }; |
| 439 | 436 | ||
| 440 | static void twl4030_sih_do_edge(struct work_struct *work) | ||
| 441 | { | ||
| 442 | struct sih_agent *agent; | ||
| 443 | const struct sih *sih; | ||
| 444 | u8 bytes[6]; | ||
| 445 | u32 edge_change; | ||
| 446 | int status; | ||
| 447 | |||
| 448 | agent = container_of(work, struct sih_agent, edge_work); | ||
| 449 | |||
| 450 | /* see what work we have */ | ||
| 451 | edge_change = agent->edge_change; | ||
| 452 | agent->edge_change = 0; | ||
| 453 | sih = edge_change ? agent->sih : NULL; | ||
| 454 | if (!sih) | ||
| 455 | return; | ||
| 456 | |||
| 457 | /* Read, reserving first byte for write scratch. Yes, this | ||
| 458 | * could be cached for some speedup ... but be careful about | ||
| 459 | * any processor on the other IRQ line, EDR registers are | ||
| 460 | * shared. | ||
| 461 | */ | ||
| 462 | status = twl_i2c_read(sih->module, bytes + 1, | ||
| 463 | sih->edr_offset, sih->bytes_edr); | ||
| 464 | if (status) { | ||
| 465 | pr_err("twl4030: %s, %s --> %d\n", __func__, | ||
| 466 | "read", status); | ||
| 467 | return; | ||
| 468 | } | ||
| 469 | |||
| 470 | /* Modify only the bits we know must change */ | ||
| 471 | while (edge_change) { | ||
| 472 | int i = fls(edge_change) - 1; | ||
| 473 | struct irq_data *idata = irq_get_irq_data(i + agent->irq_base); | ||
| 474 | int byte = 1 + (i >> 2); | ||
| 475 | int off = (i & 0x3) * 2; | ||
| 476 | unsigned int type; | ||
| 477 | |||
| 478 | bytes[byte] &= ~(0x03 << off); | ||
| 479 | |||
| 480 | type = irqd_get_trigger_type(idata); | ||
| 481 | if (type & IRQ_TYPE_EDGE_RISING) | ||
| 482 | bytes[byte] |= BIT(off + 1); | ||
| 483 | if (type & IRQ_TYPE_EDGE_FALLING) | ||
| 484 | bytes[byte] |= BIT(off + 0); | ||
| 485 | |||
| 486 | edge_change &= ~BIT(i); | ||
| 487 | } | ||
| 488 | |||
| 489 | /* Write */ | ||
| 490 | status = twl_i2c_write(sih->module, bytes, | ||
| 491 | sih->edr_offset, sih->bytes_edr); | ||
| 492 | if (status) | ||
| 493 | pr_err("twl4030: %s, %s --> %d\n", __func__, | ||
| 494 | "write", status); | ||
| 495 | } | ||
| 496 | |||
| 497 | /*----------------------------------------------------------------------*/ | 437 | /*----------------------------------------------------------------------*/ |
| 498 | 438 | ||
| 499 | /* | 439 | /* |
| @@ -526,10 +466,8 @@ static int twl4030_sih_set_type(struct irq_data *data, unsigned trigger) | |||
| 526 | if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) | 466 | if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) |
| 527 | return -EINVAL; | 467 | return -EINVAL; |
| 528 | 468 | ||
| 529 | if (irqd_get_trigger_type(data) != trigger) { | 469 | if (irqd_get_trigger_type(data) != trigger) |
| 530 | agent->edge_change |= BIT(data->irq - agent->irq_base); | 470 | agent->edge_change |= BIT(data->irq - agent->irq_base); |
| 531 | queue_work(wq, &agent->edge_work); | ||
| 532 | } | ||
| 533 | 471 | ||
| 534 | return 0; | 472 | return 0; |
| 535 | } | 473 | } |
| @@ -566,6 +504,56 @@ static void twl4030_sih_bus_sync_unlock(struct irq_data *data) | |||
| 566 | "write", status); | 504 | "write", status); |
| 567 | } | 505 | } |
| 568 | 506 | ||
| 507 | if (agent->edge_change) { | ||
| 508 | u32 edge_change; | ||
| 509 | u8 bytes[6]; | ||
| 510 | |||
| 511 | edge_change = agent->edge_change; | ||
| 512 | agent->edge_change = 0; | ||
| 513 | |||
| 514 | /* | ||
| 515 | * Read, reserving first byte for write scratch. Yes, this | ||
| 516 | * could be cached for some speedup ... but be careful about | ||
| 517 | * any processor on the other IRQ line, EDR registers are | ||
| 518 | * shared. | ||
| 519 | */ | ||
| 520 | status = twl_i2c_read(sih->module, bytes + 1, | ||
| 521 | sih->edr_offset, sih->bytes_edr); | ||
| 522 | if (status) { | ||
| 523 | pr_err("twl4030: %s, %s --> %d\n", __func__, | ||
| 524 | "read", status); | ||
| 525 | return; | ||
| 526 | } | ||
| 527 | |||
| 528 | /* Modify only the bits we know must change */ | ||
| 529 | while (edge_change) { | ||
| 530 | int i = fls(edge_change) - 1; | ||
| 531 | struct irq_data *idata; | ||
| 532 | int byte = 1 + (i >> 2); | ||
| 533 | int off = (i & 0x3) * 2; | ||
| 534 | unsigned int type; | ||
| 535 | |||
| 536 | idata = irq_get_irq_data(i + agent->irq_base); | ||
| 537 | |||
| 538 | bytes[byte] &= ~(0x03 << off); | ||
| 539 | |||
| 540 | type = irqd_get_trigger_type(idata); | ||
| 541 | if (type & IRQ_TYPE_EDGE_RISING) | ||
| 542 | bytes[byte] |= BIT(off + 1); | ||
| 543 | if (type & IRQ_TYPE_EDGE_FALLING) | ||
| 544 | bytes[byte] |= BIT(off + 0); | ||
| 545 | |||
| 546 | edge_change &= ~BIT(i); | ||
| 547 | } | ||
| 548 | |||
| 549 | /* Write */ | ||
| 550 | status = twl_i2c_write(sih->module, bytes, | ||
| 551 | sih->edr_offset, sih->bytes_edr); | ||
| 552 | if (status) | ||
| 553 | pr_err("twl4030: %s, %s --> %d\n", __func__, | ||
| 554 | "write", status); | ||
| 555 | } | ||
| 556 | |||
| 569 | mutex_unlock(&agent->irq_lock); | 557 | mutex_unlock(&agent->irq_lock); |
| 570 | } | 558 | } |
| 571 | 559 | ||
| @@ -672,7 +660,6 @@ int twl4030_sih_setup(int module) | |||
| 672 | agent->sih = sih; | 660 | agent->sih = sih; |
| 673 | agent->imr = ~0; | 661 | agent->imr = ~0; |
| 674 | mutex_init(&agent->irq_lock); | 662 | mutex_init(&agent->irq_lock); |
| 675 | INIT_WORK(&agent->edge_work, twl4030_sih_do_edge); | ||
| 676 | 663 | ||
| 677 | for (i = 0; i < sih->bits; i++) { | 664 | for (i = 0; i < sih->bits; i++) { |
| 678 | irq = irq_base + i; | 665 | irq = irq_base + i; |
| @@ -720,12 +707,6 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) | |||
| 720 | if (status < 0) | 707 | if (status < 0) |
| 721 | return status; | 708 | return status; |
| 722 | 709 | ||
| 723 | wq = create_singlethread_workqueue("twl4030-irqchip"); | ||
| 724 | if (!wq) { | ||
| 725 | pr_err("twl4030: workqueue FAIL\n"); | ||
| 726 | return -ESRCH; | ||
| 727 | } | ||
| 728 | |||
| 729 | twl4030_irq_base = irq_base; | 710 | twl4030_irq_base = irq_base; |
| 730 | 711 | ||
| 731 | /* install an irq handler for each of the SIH modules; | 712 | /* install an irq handler for each of the SIH modules; |
| @@ -766,8 +747,7 @@ fail_rqirq: | |||
| 766 | fail: | 747 | fail: |
| 767 | for (i = irq_base; i < irq_end; i++) | 748 | for (i = irq_base; i < irq_end; i++) |
| 768 | irq_set_chip_and_handler(i, NULL, NULL); | 749 | irq_set_chip_and_handler(i, NULL, NULL); |
| 769 | destroy_workqueue(wq); | 750 | |
| 770 | wq = NULL; | ||
| 771 | return status; | 751 | return status; |
| 772 | } | 752 | } |
| 773 | 753 | ||
