diff options
author | Felipe Balbi <balbi@ti.com> | 2011-06-30 05:51:05 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2011-10-24 08:09:11 -0400 |
commit | 91e3569ff487784edd206de1b324507b5ecc8439 (patch) | |
tree | 39a3daeca44e8d6eea808ee394394d32718eb14c /drivers/mfd | |
parent | 8cd6af2938945ce71e99182c8f092033cf9a5e17 (diff) |
mfd: Implement bus_lock/bus_sync_unlock twl4030-irq methods
For doing that, drop the locking and change that
to a mutex.
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 | 37 |
1 files changed, 21 insertions, 16 deletions
diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c index 7be97cb2075d..291364c3943e 100644 --- a/drivers/mfd/twl4030-irq.c +++ b/drivers/mfd/twl4030-irq.c | |||
@@ -460,8 +460,6 @@ static inline void activate_irq(int irq) | |||
460 | 460 | ||
461 | /*----------------------------------------------------------------------*/ | 461 | /*----------------------------------------------------------------------*/ |
462 | 462 | ||
463 | static DEFINE_SPINLOCK(sih_agent_lock); | ||
464 | |||
465 | static struct workqueue_struct *wq; | 463 | static struct workqueue_struct *wq; |
466 | 464 | ||
467 | struct sih_agent { | 465 | struct sih_agent { |
@@ -474,6 +472,8 @@ struct sih_agent { | |||
474 | 472 | ||
475 | u32 edge_change; | 473 | u32 edge_change; |
476 | struct work_struct edge_work; | 474 | struct work_struct edge_work; |
475 | |||
476 | struct mutex irq_lock; | ||
477 | }; | 477 | }; |
478 | 478 | ||
479 | static void twl4030_sih_do_mask(struct work_struct *work) | 479 | static void twl4030_sih_do_mask(struct work_struct *work) |
@@ -489,7 +489,6 @@ static void twl4030_sih_do_mask(struct work_struct *work) | |||
489 | agent = container_of(work, struct sih_agent, mask_work); | 489 | agent = container_of(work, struct sih_agent, mask_work); |
490 | 490 | ||
491 | /* see what work we have */ | 491 | /* see what work we have */ |
492 | spin_lock_irq(&sih_agent_lock); | ||
493 | if (agent->imr_change_pending) { | 492 | if (agent->imr_change_pending) { |
494 | sih = agent->sih; | 493 | sih = agent->sih; |
495 | /* byte[0] gets overwritten as we write ... */ | 494 | /* byte[0] gets overwritten as we write ... */ |
@@ -497,7 +496,6 @@ static void twl4030_sih_do_mask(struct work_struct *work) | |||
497 | agent->imr_change_pending = false; | 496 | agent->imr_change_pending = false; |
498 | } else | 497 | } else |
499 | sih = NULL; | 498 | sih = NULL; |
500 | spin_unlock_irq(&sih_agent_lock); | ||
501 | if (!sih) | 499 | if (!sih) |
502 | return; | 500 | return; |
503 | 501 | ||
@@ -520,11 +518,9 @@ static void twl4030_sih_do_edge(struct work_struct *work) | |||
520 | agent = container_of(work, struct sih_agent, edge_work); | 518 | agent = container_of(work, struct sih_agent, edge_work); |
521 | 519 | ||
522 | /* see what work we have */ | 520 | /* see what work we have */ |
523 | spin_lock_irq(&sih_agent_lock); | ||
524 | edge_change = agent->edge_change; | 521 | edge_change = agent->edge_change; |
525 | agent->edge_change = 0; | 522 | agent->edge_change = 0; |
526 | sih = edge_change ? agent->sih : NULL; | 523 | sih = edge_change ? agent->sih : NULL; |
527 | spin_unlock_irq(&sih_agent_lock); | ||
528 | if (!sih) | 524 | if (!sih) |
529 | return; | 525 | return; |
530 | 526 | ||
@@ -580,49 +576,57 @@ static void twl4030_sih_do_edge(struct work_struct *work) | |||
580 | static void twl4030_sih_mask(struct irq_data *data) | 576 | static void twl4030_sih_mask(struct irq_data *data) |
581 | { | 577 | { |
582 | struct sih_agent *sih = irq_data_get_irq_chip_data(data); | 578 | struct sih_agent *sih = irq_data_get_irq_chip_data(data); |
583 | unsigned long flags; | ||
584 | 579 | ||
585 | spin_lock_irqsave(&sih_agent_lock, flags); | ||
586 | sih->imr |= BIT(data->irq - sih->irq_base); | 580 | sih->imr |= BIT(data->irq - sih->irq_base); |
587 | sih->imr_change_pending = true; | 581 | sih->imr_change_pending = true; |
588 | queue_work(wq, &sih->mask_work); | 582 | queue_work(wq, &sih->mask_work); |
589 | spin_unlock_irqrestore(&sih_agent_lock, flags); | ||
590 | } | 583 | } |
591 | 584 | ||
592 | static void twl4030_sih_unmask(struct irq_data *data) | 585 | static void twl4030_sih_unmask(struct irq_data *data) |
593 | { | 586 | { |
594 | struct sih_agent *sih = irq_data_get_irq_chip_data(data); | 587 | struct sih_agent *sih = irq_data_get_irq_chip_data(data); |
595 | unsigned long flags; | ||
596 | 588 | ||
597 | spin_lock_irqsave(&sih_agent_lock, flags); | ||
598 | sih->imr &= ~BIT(data->irq - sih->irq_base); | 589 | sih->imr &= ~BIT(data->irq - sih->irq_base); |
599 | sih->imr_change_pending = true; | 590 | sih->imr_change_pending = true; |
600 | queue_work(wq, &sih->mask_work); | 591 | queue_work(wq, &sih->mask_work); |
601 | spin_unlock_irqrestore(&sih_agent_lock, flags); | ||
602 | } | 592 | } |
603 | 593 | ||
604 | static int twl4030_sih_set_type(struct irq_data *data, unsigned trigger) | 594 | static int twl4030_sih_set_type(struct irq_data *data, unsigned trigger) |
605 | { | 595 | { |
606 | struct sih_agent *sih = irq_data_get_irq_chip_data(data); | 596 | struct sih_agent *sih = irq_data_get_irq_chip_data(data); |
607 | unsigned long flags; | ||
608 | 597 | ||
609 | if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) | 598 | if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) |
610 | return -EINVAL; | 599 | return -EINVAL; |
611 | 600 | ||
612 | spin_lock_irqsave(&sih_agent_lock, flags); | ||
613 | if (irqd_get_trigger_type(data) != trigger) { | 601 | if (irqd_get_trigger_type(data) != trigger) { |
614 | sih->edge_change |= BIT(data->irq - sih->irq_base); | 602 | sih->edge_change |= BIT(data->irq - sih->irq_base); |
615 | queue_work(wq, &sih->edge_work); | 603 | queue_work(wq, &sih->edge_work); |
616 | } | 604 | } |
617 | spin_unlock_irqrestore(&sih_agent_lock, flags); | 605 | |
618 | return 0; | 606 | return 0; |
619 | } | 607 | } |
620 | 608 | ||
609 | static void twl4030_sih_bus_lock(struct irq_data *data) | ||
610 | { | ||
611 | struct sih_agent *sih = irq_data_get_irq_chip_data(data); | ||
612 | |||
613 | mutex_lock(&sih->irq_lock); | ||
614 | } | ||
615 | |||
616 | static void twl4030_sih_bus_sync_unlock(struct irq_data *data) | ||
617 | { | ||
618 | struct sih_agent *sih = irq_data_get_irq_chip_data(data); | ||
619 | |||
620 | mutex_unlock(&sih->irq_lock); | ||
621 | } | ||
622 | |||
621 | static struct irq_chip twl4030_sih_irq_chip = { | 623 | static struct irq_chip twl4030_sih_irq_chip = { |
622 | .name = "twl4030", | 624 | .name = "twl4030", |
623 | .irq_mask = twl4030_sih_mask, | 625 | .irq_mask = twl4030_sih_mask, |
624 | .irq_unmask = twl4030_sih_unmask, | 626 | .irq_unmask = twl4030_sih_unmask, |
625 | .irq_set_type = twl4030_sih_set_type, | 627 | .irq_set_type = twl4030_sih_set_type, |
628 | .irq_bus_lock = twl4030_sih_bus_lock, | ||
629 | .irq_bus_sync_unlock = twl4030_sih_bus_sync_unlock, | ||
626 | }; | 630 | }; |
627 | 631 | ||
628 | /*----------------------------------------------------------------------*/ | 632 | /*----------------------------------------------------------------------*/ |
@@ -718,15 +722,16 @@ int twl4030_sih_setup(int module) | |||
718 | agent->irq_base = irq_base; | 722 | agent->irq_base = irq_base; |
719 | agent->sih = sih; | 723 | agent->sih = sih; |
720 | agent->imr = ~0; | 724 | agent->imr = ~0; |
725 | mutex_init(&agent->irq_lock); | ||
721 | INIT_WORK(&agent->mask_work, twl4030_sih_do_mask); | 726 | INIT_WORK(&agent->mask_work, twl4030_sih_do_mask); |
722 | INIT_WORK(&agent->edge_work, twl4030_sih_do_edge); | 727 | INIT_WORK(&agent->edge_work, twl4030_sih_do_edge); |
723 | 728 | ||
724 | for (i = 0; i < sih->bits; i++) { | 729 | for (i = 0; i < sih->bits; i++) { |
725 | irq = irq_base + i; | 730 | irq = irq_base + i; |
726 | 731 | ||
732 | irq_set_chip_data(irq, agent); | ||
727 | irq_set_chip_and_handler(irq, &twl4030_sih_irq_chip, | 733 | irq_set_chip_and_handler(irq, &twl4030_sih_irq_chip, |
728 | handle_edge_irq); | 734 | handle_edge_irq); |
729 | irq_set_chip_data(irq, agent); | ||
730 | activate_irq(irq); | 735 | activate_irq(irq); |
731 | } | 736 | } |
732 | 737 | ||