aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd
diff options
context:
space:
mode:
authorFelipe Balbi <balbi@ti.com>2011-06-30 05:51:05 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2011-10-24 08:09:11 -0400
commit91e3569ff487784edd206de1b324507b5ecc8439 (patch)
tree39a3daeca44e8d6eea808ee394394d32718eb14c /drivers/mfd
parent8cd6af2938945ce71e99182c8f092033cf9a5e17 (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.c37
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
463static DEFINE_SPINLOCK(sih_agent_lock);
464
465static struct workqueue_struct *wq; 463static struct workqueue_struct *wq;
466 464
467struct sih_agent { 465struct 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
479static void twl4030_sih_do_mask(struct work_struct *work) 479static 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)
580static void twl4030_sih_mask(struct irq_data *data) 576static 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
592static void twl4030_sih_unmask(struct irq_data *data) 585static 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
604static int twl4030_sih_set_type(struct irq_data *data, unsigned trigger) 594static 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
609static 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
616static 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
621static struct irq_chip twl4030_sih_irq_chip = { 623static 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