aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/twl4030-irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mfd/twl4030-irq.c')
-rw-r--r--drivers/mfd/twl4030-irq.c342
1 files changed, 131 insertions, 211 deletions
diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c
index 8a7ee3139b86..f062c8cc6c38 100644
--- a/drivers/mfd/twl4030-irq.c
+++ b/drivers/mfd/twl4030-irq.c
@@ -30,7 +30,6 @@
30#include <linux/init.h> 30#include <linux/init.h>
31#include <linux/interrupt.h> 31#include <linux/interrupt.h>
32#include <linux/irq.h> 32#include <linux/irq.h>
33#include <linux/kthread.h>
34#include <linux/slab.h> 33#include <linux/slab.h>
35 34
36#include <linux/i2c/twl.h> 35#include <linux/i2c/twl.h>
@@ -278,59 +277,6 @@ static const struct sih sih_modules_twl5031[8] = {
278 277
279static unsigned twl4030_irq_base; 278static unsigned twl4030_irq_base;
280 279
281static struct completion irq_event;
282
283/*
284 * This thread processes interrupts reported by the Primary Interrupt Handler.
285 */
286static int twl4030_irq_thread(void *data)
287{
288 long irq = (long)data;
289 static unsigned i2c_errors;
290 static const unsigned max_i2c_errors = 100;
291
292
293 current->flags |= PF_NOFREEZE;
294
295 while (!kthread_should_stop()) {
296 int ret;
297 int module_irq;
298 u8 pih_isr;
299
300 /* Wait for IRQ, then read PIH irq status (also blocking) */
301 wait_for_completion_interruptible(&irq_event);
302
303 ret = twl_i2c_read_u8(TWL4030_MODULE_PIH, &pih_isr,
304 REG_PIH_ISR_P1);
305 if (ret) {
306 pr_warning("twl4030: I2C error %d reading PIH ISR\n",
307 ret);
308 if (++i2c_errors >= max_i2c_errors) {
309 printk(KERN_ERR "Maximum I2C error count"
310 " exceeded. Terminating %s.\n",
311 __func__);
312 break;
313 }
314 complete(&irq_event);
315 continue;
316 }
317
318 /* these handlers deal with the relevant SIH irq status */
319 local_irq_disable();
320 for (module_irq = twl4030_irq_base;
321 pih_isr;
322 pih_isr >>= 1, module_irq++) {
323 if (pih_isr & 0x1)
324 generic_handle_irq(module_irq);
325 }
326 local_irq_enable();
327
328 enable_irq(irq);
329 }
330
331 return 0;
332}
333
334/* 280/*
335 * handle_twl4030_pih() is the desc->handle method for the twl4030 interrupt. 281 * handle_twl4030_pih() is the desc->handle method for the twl4030 interrupt.
336 * This is a chained interrupt, so there is no desc->action method for it. 282 * This is a chained interrupt, so there is no desc->action method for it.
@@ -342,9 +288,25 @@ static int twl4030_irq_thread(void *data)
342 */ 288 */
343static irqreturn_t handle_twl4030_pih(int irq, void *devid) 289static irqreturn_t handle_twl4030_pih(int irq, void *devid)
344{ 290{
345 /* Acknowledge, clear *AND* mask the interrupt... */ 291 int module_irq;
346 disable_irq_nosync(irq); 292 irqreturn_t ret;
347 complete(devid); 293 u8 pih_isr;
294
295 ret = twl_i2c_read_u8(TWL4030_MODULE_PIH, &pih_isr,
296 REG_PIH_ISR_P1);
297 if (ret) {
298 pr_warning("twl4030: I2C error %d reading PIH ISR\n", ret);
299 return IRQ_NONE;
300 }
301
302 /* these handlers deal with the relevant SIH irq status */
303 for (module_irq = twl4030_irq_base;
304 pih_isr;
305 pih_isr >>= 1, module_irq++) {
306 if (pih_isr & 0x1)
307 handle_nested_irq(module_irq);
308 }
309
348 return IRQ_HANDLED; 310 return IRQ_HANDLED;
349} 311}
350/*----------------------------------------------------------------------*/ 312/*----------------------------------------------------------------------*/
@@ -460,113 +422,17 @@ static inline void activate_irq(int irq)
460 422
461/*----------------------------------------------------------------------*/ 423/*----------------------------------------------------------------------*/
462 424
463static DEFINE_SPINLOCK(sih_agent_lock);
464
465static struct workqueue_struct *wq;
466
467struct sih_agent { 425struct sih_agent {
468 int irq_base; 426 int irq_base;
469 const struct sih *sih; 427 const struct sih *sih;
470 428
471 u32 imr; 429 u32 imr;
472 bool imr_change_pending; 430 bool imr_change_pending;
473 struct work_struct mask_work;
474
475 u32 edge_change;
476 struct work_struct edge_work;
477};
478
479static void twl4030_sih_do_mask(struct work_struct *work)
480{
481 struct sih_agent *agent;
482 const struct sih *sih;
483 union {
484 u8 bytes[4];
485 u32 word;
486 } imr;
487 int status;
488 431
489 agent = container_of(work, struct sih_agent, mask_work);
490
491 /* see what work we have */
492 spin_lock_irq(&sih_agent_lock);
493 if (agent->imr_change_pending) {
494 sih = agent->sih;
495 /* byte[0] gets overwritten as we write ... */
496 imr.word = cpu_to_le32(agent->imr << 8);
497 agent->imr_change_pending = false;
498 } else
499 sih = NULL;
500 spin_unlock_irq(&sih_agent_lock);
501 if (!sih)
502 return;
503
504 /* write the whole mask ... simpler than subsetting it */
505 status = twl_i2c_write(sih->module, imr.bytes,
506 sih->mask[irq_line].imr_offset, sih->bytes_ixr);
507 if (status)
508 pr_err("twl4030: %s, %s --> %d\n", __func__,
509 "write", status);
510}
511
512static void twl4030_sih_do_edge(struct work_struct *work)
513{
514 struct sih_agent *agent;
515 const struct sih *sih;
516 u8 bytes[6];
517 u32 edge_change; 432 u32 edge_change;
518 int status;
519
520 agent = container_of(work, struct sih_agent, edge_work);
521
522 /* see what work we have */
523 spin_lock_irq(&sih_agent_lock);
524 edge_change = agent->edge_change;
525 agent->edge_change = 0;
526 sih = edge_change ? agent->sih : NULL;
527 spin_unlock_irq(&sih_agent_lock);
528 if (!sih)
529 return;
530
531 /* Read, reserving first byte for write scratch. Yes, this
532 * could be cached for some speedup ... but be careful about
533 * any processor on the other IRQ line, EDR registers are
534 * shared.
535 */
536 status = twl_i2c_read(sih->module, bytes + 1,
537 sih->edr_offset, sih->bytes_edr);
538 if (status) {
539 pr_err("twl4030: %s, %s --> %d\n", __func__,
540 "read", status);
541 return;
542 }
543
544 /* Modify only the bits we know must change */
545 while (edge_change) {
546 int i = fls(edge_change) - 1;
547 struct irq_data *idata = irq_get_irq_data(i + agent->irq_base);
548 int byte = 1 + (i >> 2);
549 int off = (i & 0x3) * 2;
550 unsigned int type;
551
552 bytes[byte] &= ~(0x03 << off);
553 433
554 type = irqd_get_trigger_type(idata); 434 struct mutex irq_lock;
555 if (type & IRQ_TYPE_EDGE_RISING) 435};
556 bytes[byte] |= BIT(off + 1);
557 if (type & IRQ_TYPE_EDGE_FALLING)
558 bytes[byte] |= BIT(off + 0);
559
560 edge_change &= ~BIT(i);
561 }
562
563 /* Write */
564 status = twl_i2c_write(sih->module, bytes,
565 sih->edr_offset, sih->bytes_edr);
566 if (status)
567 pr_err("twl4030: %s, %s --> %d\n", __func__,
568 "write", status);
569}
570 436
571/*----------------------------------------------------------------------*/ 437/*----------------------------------------------------------------------*/
572 438
@@ -579,50 +445,125 @@ static void twl4030_sih_do_edge(struct work_struct *work)
579 445
580static void twl4030_sih_mask(struct irq_data *data) 446static void twl4030_sih_mask(struct irq_data *data)
581{ 447{
582 struct sih_agent *sih = irq_data_get_irq_chip_data(data); 448 struct sih_agent *agent = irq_data_get_irq_chip_data(data);
583 unsigned long flags; 449
584 450 agent->imr |= BIT(data->irq - agent->irq_base);
585 spin_lock_irqsave(&sih_agent_lock, flags); 451 agent->imr_change_pending = true;
586 sih->imr |= BIT(data->irq - sih->irq_base);
587 sih->imr_change_pending = true;
588 queue_work(wq, &sih->mask_work);
589 spin_unlock_irqrestore(&sih_agent_lock, flags);
590} 452}
591 453
592static void twl4030_sih_unmask(struct irq_data *data) 454static void twl4030_sih_unmask(struct irq_data *data)
593{ 455{
594 struct sih_agent *sih = irq_data_get_irq_chip_data(data); 456 struct sih_agent *agent = irq_data_get_irq_chip_data(data);
595 unsigned long flags; 457
596 458 agent->imr &= ~BIT(data->irq - agent->irq_base);
597 spin_lock_irqsave(&sih_agent_lock, flags); 459 agent->imr_change_pending = true;
598 sih->imr &= ~BIT(data->irq - sih->irq_base);
599 sih->imr_change_pending = true;
600 queue_work(wq, &sih->mask_work);
601 spin_unlock_irqrestore(&sih_agent_lock, flags);
602} 460}
603 461
604static int twl4030_sih_set_type(struct irq_data *data, unsigned trigger) 462static int twl4030_sih_set_type(struct irq_data *data, unsigned trigger)
605{ 463{
606 struct sih_agent *sih = irq_data_get_irq_chip_data(data); 464 struct sih_agent *agent = irq_data_get_irq_chip_data(data);
607 unsigned long flags;
608 465
609 if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) 466 if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
610 return -EINVAL; 467 return -EINVAL;
611 468
612 spin_lock_irqsave(&sih_agent_lock, flags); 469 if (irqd_get_trigger_type(data) != trigger)
613 if (irqd_get_trigger_type(data) != trigger) { 470 agent->edge_change |= BIT(data->irq - agent->irq_base);
614 sih->edge_change |= BIT(data->irq - sih->irq_base); 471
615 queue_work(wq, &sih->edge_work);
616 }
617 spin_unlock_irqrestore(&sih_agent_lock, flags);
618 return 0; 472 return 0;
619} 473}
620 474
475static void twl4030_sih_bus_lock(struct irq_data *data)
476{
477 struct sih_agent *agent = irq_data_get_irq_chip_data(data);
478
479 mutex_lock(&agent->irq_lock);
480}
481
482static void twl4030_sih_bus_sync_unlock(struct irq_data *data)
483{
484 struct sih_agent *agent = irq_data_get_irq_chip_data(data);
485 const struct sih *sih = agent->sih;
486 int status;
487
488 if (agent->imr_change_pending) {
489 union {
490 u32 word;
491 u8 bytes[4];
492 } imr;
493
494 /* byte[0] gets overwriten as we write ... */
495 imr.word = cpu_to_le32(agent->imr << 8);
496 agent->imr_change_pending = false;
497
498 /* write the whole mask ... simpler than subsetting it */
499 status = twl_i2c_write(sih->module, imr.bytes,
500 sih->mask[irq_line].imr_offset,
501 sih->bytes_ixr);
502 if (status)
503 pr_err("twl4030: %s, %s --> %d\n", __func__,
504 "write", status);
505 }
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
557 mutex_unlock(&agent->irq_lock);
558}
559
621static struct irq_chip twl4030_sih_irq_chip = { 560static struct irq_chip twl4030_sih_irq_chip = {
622 .name = "twl4030", 561 .name = "twl4030",
623 .irq_mask = twl4030_sih_mask, 562 .irq_mask = twl4030_sih_mask,
624 .irq_unmask = twl4030_sih_unmask, 563 .irq_unmask = twl4030_sih_unmask,
625 .irq_set_type = twl4030_sih_set_type, 564 .irq_set_type = twl4030_sih_set_type,
565 .irq_bus_lock = twl4030_sih_bus_lock,
566 .irq_bus_sync_unlock = twl4030_sih_bus_sync_unlock,
626}; 567};
627 568
628/*----------------------------------------------------------------------*/ 569/*----------------------------------------------------------------------*/
@@ -655,9 +596,7 @@ static void handle_twl4030_sih(unsigned irq, struct irq_desc *desc)
655 int isr; 596 int isr;
656 597
657 /* reading ISR acks the IRQs, using clear-on-read mode */ 598 /* reading ISR acks the IRQs, using clear-on-read mode */
658 local_irq_enable();
659 isr = sih_read_isr(sih); 599 isr = sih_read_isr(sih);
660 local_irq_disable();
661 600
662 if (isr < 0) { 601 if (isr < 0) {
663 pr_err("twl4030: %s SIH, read ISR error %d\n", 602 pr_err("twl4030: %s SIH, read ISR error %d\n",
@@ -672,7 +611,7 @@ static void handle_twl4030_sih(unsigned irq, struct irq_desc *desc)
672 isr &= ~BIT(irq); 611 isr &= ~BIT(irq);
673 612
674 if (irq < sih->bits) 613 if (irq < sih->bits)
675 generic_handle_irq(agent->irq_base + irq); 614 handle_nested_irq(agent->irq_base + irq);
676 else 615 else
677 pr_err("twl4030: %s SIH, invalid ISR bit %d\n", 616 pr_err("twl4030: %s SIH, invalid ISR bit %d\n",
678 sih->name, irq); 617 sih->name, irq);
@@ -718,15 +657,14 @@ int twl4030_sih_setup(int module)
718 agent->irq_base = irq_base; 657 agent->irq_base = irq_base;
719 agent->sih = sih; 658 agent->sih = sih;
720 agent->imr = ~0; 659 agent->imr = ~0;
721 INIT_WORK(&agent->mask_work, twl4030_sih_do_mask); 660 mutex_init(&agent->irq_lock);
722 INIT_WORK(&agent->edge_work, twl4030_sih_do_edge);
723 661
724 for (i = 0; i < sih->bits; i++) { 662 for (i = 0; i < sih->bits; i++) {
725 irq = irq_base + i; 663 irq = irq_base + i;
726 664
665 irq_set_chip_data(irq, agent);
727 irq_set_chip_and_handler(irq, &twl4030_sih_irq_chip, 666 irq_set_chip_and_handler(irq, &twl4030_sih_irq_chip,
728 handle_edge_irq); 667 handle_edge_irq);
729 irq_set_chip_data(irq, agent);
730 activate_irq(irq); 668 activate_irq(irq);
731 } 669 }
732 670
@@ -758,7 +696,6 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
758 696
759 int status; 697 int status;
760 int i; 698 int i;
761 struct task_struct *task;
762 699
763 /* 700 /*
764 * Mask and clear all TWL4030 interrupts since initially we do 701 * Mask and clear all TWL4030 interrupts since initially we do
@@ -768,12 +705,6 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
768 if (status < 0) 705 if (status < 0)
769 return status; 706 return status;
770 707
771 wq = create_singlethread_workqueue("twl4030-irqchip");
772 if (!wq) {
773 pr_err("twl4030: workqueue FAIL\n");
774 return -ESRCH;
775 }
776
777 twl4030_irq_base = irq_base; 708 twl4030_irq_base = irq_base;
778 709
779 /* install an irq handler for each of the SIH modules; 710 /* install an irq handler for each of the SIH modules;
@@ -787,6 +718,7 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
787 for (i = irq_base; i < irq_end; i++) { 718 for (i = irq_base; i < irq_end; i++) {
788 irq_set_chip_and_handler(i, &twl4030_irq_chip, 719 irq_set_chip_and_handler(i, &twl4030_irq_chip,
789 handle_simple_irq); 720 handle_simple_irq);
721 irq_set_nested_thread(i, 1);
790 activate_irq(i); 722 activate_irq(i);
791 } 723 }
792 twl4030_irq_next = i; 724 twl4030_irq_next = i;
@@ -801,34 +733,22 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
801 } 733 }
802 734
803 /* install an irq handler to demultiplex the TWL4030 interrupt */ 735 /* install an irq handler to demultiplex the TWL4030 interrupt */
804 736 status = request_threaded_irq(irq_num, NULL, handle_twl4030_pih, 0,
805 737 "TWL4030-PIH", NULL);
806 init_completion(&irq_event);
807
808 status = request_irq(irq_num, handle_twl4030_pih, IRQF_DISABLED,
809 "TWL4030-PIH", &irq_event);
810 if (status < 0) { 738 if (status < 0) {
811 pr_err("twl4030: could not claim irq%d: %d\n", irq_num, status); 739 pr_err("twl4030: could not claim irq%d: %d\n", irq_num, status);
812 goto fail_rqirq; 740 goto fail_rqirq;
813 } 741 }
814 742
815 task = kthread_run(twl4030_irq_thread, (void *)(long)irq_num,
816 "twl4030-irq");
817 if (IS_ERR(task)) {
818 pr_err("twl4030: could not create irq %d thread!\n", irq_num);
819 status = PTR_ERR(task);
820 goto fail_kthread;
821 }
822 return status; 743 return status;
823fail_kthread:
824 free_irq(irq_num, &irq_event);
825fail_rqirq: 744fail_rqirq:
826 /* clean up twl4030_sih_setup */ 745 /* clean up twl4030_sih_setup */
827fail: 746fail:
828 for (i = irq_base; i < irq_end; i++) 747 for (i = irq_base; i < irq_end; i++) {
748 irq_set_nested_thread(i, 0);
829 irq_set_chip_and_handler(i, NULL, NULL); 749 irq_set_chip_and_handler(i, NULL, NULL);
830 destroy_workqueue(wq); 750 }
831 wq = NULL; 751
832 return status; 752 return status;
833} 753}
834 754