twl4030-irq.c (5a903090e7aa561901b7f052eb744b480d6126d4) twl4030-irq.c (ec1a07b3440cc28946a77a974c21570bbef6ffa1)
1/*
2 * twl4030-irq.c - TWL4030/TPS659x0 irq support
3 *
4 * Copyright (C) 2005-2006 Texas Instruments, Inc.
5 *
6 * Modifications to defer interrupt handling to a kernel thread:
7 * Copyright (C) 2006 MontaVista Software, Inc.
8 *

--- 18 unchanged lines hidden (view full) ---

27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 */
29
30#include <linux/init.h>
31#include <linux/export.h>
32#include <linux/interrupt.h>
33#include <linux/irq.h>
34#include <linux/slab.h>
1/*
2 * twl4030-irq.c - TWL4030/TPS659x0 irq support
3 *
4 * Copyright (C) 2005-2006 Texas Instruments, Inc.
5 *
6 * Modifications to defer interrupt handling to a kernel thread:
7 * Copyright (C) 2006 MontaVista Software, Inc.
8 *

--- 18 unchanged lines hidden (view full) ---

27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 */
29
30#include <linux/init.h>
31#include <linux/export.h>
32#include <linux/interrupt.h>
33#include <linux/irq.h>
34#include <linux/slab.h>
35
36#include <linux/of.h>
37#include <linux/irqdomain.h>
38#include <linux/i2c/twl.h>
39
40#include "twl-core.h"
41
42/*
43 * TWL4030 IRQ handling has two stages in hardware, and thus in software.

--- 590 unchanged lines hidden (view full) ---

634{
635 int sih_mod;
636 const struct sih *sih = NULL;
637 struct sih_agent *agent;
638 int i, irq;
639 int status = -EINVAL;
640
641 /* only support modules with standard clear-on-read for now */
35#include <linux/of.h>
36#include <linux/irqdomain.h>
37#include <linux/i2c/twl.h>
38
39#include "twl-core.h"
40
41/*
42 * TWL4030 IRQ handling has two stages in hardware, and thus in software.

--- 590 unchanged lines hidden (view full) ---

633{
634 int sih_mod;
635 const struct sih *sih = NULL;
636 struct sih_agent *agent;
637 int i, irq;
638 int status = -EINVAL;
639
640 /* only support modules with standard clear-on-read for now */
642 for (sih_mod = 0, sih = sih_modules;
643 sih_mod < nr_sih_modules;
641 for (sih_mod = 0, sih = sih_modules; sih_mod < nr_sih_modules;
644 sih_mod++, sih++) {
645 if (sih->module == module && sih->set_cor) {
646 status = 0;
647 break;
648 }
649 }
642 sih_mod++, sih++) {
643 if (sih->module == module && sih->set_cor) {
644 status = 0;
645 break;
646 }
647 }
648
650 if (status < 0)
651 return status;
652
653 agent = kzalloc(sizeof *agent, GFP_KERNEL);
654 if (!agent)
655 return -ENOMEM;
656
657 agent->irq_base = irq_base;

--- 13 unchanged lines hidden (view full) ---

671
672 /* replace generic PIH handler (handle_simple_irq) */
673 irq = sih_mod + twl4030_irq_base;
674 irq_set_handler_data(irq, agent);
675 agent->irq_name = kasprintf(GFP_KERNEL, "twl4030_%s", sih->name);
676 status = request_threaded_irq(irq, NULL, handle_twl4030_sih, 0,
677 agent->irq_name ?: sih->name, NULL);
678
649 if (status < 0)
650 return status;
651
652 agent = kzalloc(sizeof *agent, GFP_KERNEL);
653 if (!agent)
654 return -ENOMEM;
655
656 agent->irq_base = irq_base;

--- 13 unchanged lines hidden (view full) ---

670
671 /* replace generic PIH handler (handle_simple_irq) */
672 irq = sih_mod + twl4030_irq_base;
673 irq_set_handler_data(irq, agent);
674 agent->irq_name = kasprintf(GFP_KERNEL, "twl4030_%s", sih->name);
675 status = request_threaded_irq(irq, NULL, handle_twl4030_sih, 0,
676 agent->irq_name ?: sih->name, NULL);
677
679 pr_info("twl4030: %s (irq %d) chaining IRQs %d..%d\n", sih->name,
678 dev_info(dev, "%s (irq %d) chaining IRQs %d..%d\n", sih->name,
680 irq, irq_base, irq_base + i - 1);
681
682 return status < 0 ? status : irq_base;
683}
684
685/* FIXME need a call to reverse twl4030_sih_setup() ... */
686
687/*----------------------------------------------------------------------*/
688
689/* FIXME pass in which interrupt line we'll use ... */
690#define twl_irq_line 0
691
692int twl4030_init_irq(struct device *dev, int irq_num)
693{
694 static struct irq_chip twl4030_irq_chip;
679 irq, irq_base, irq_base + i - 1);
680
681 return status < 0 ? status : irq_base;
682}
683
684/* FIXME need a call to reverse twl4030_sih_setup() ... */
685
686/*----------------------------------------------------------------------*/
687
688/* FIXME pass in which interrupt line we'll use ... */
689#define twl_irq_line 0
690
691int twl4030_init_irq(struct device *dev, int irq_num)
692{
693 static struct irq_chip twl4030_irq_chip;
694 int status, i;
695 int irq_base, irq_end, nr_irqs;
696 struct device_node *node = dev->of_node;
697
695 int irq_base, irq_end, nr_irqs;
696 struct device_node *node = dev->of_node;
697
698 int status;
699 int i;
700
701 /*
702 * TWL core and pwr interrupts must be contiguous because
703 * the hwirqs numbers are defined contiguously from 1 to 15.
704 * Create only one domain for both.
705 */
706 nr_irqs = TWL4030_PWR_NR_IRQS + TWL4030_CORE_NR_IRQS;
707
708 irq_base = irq_alloc_descs(-1, 0, nr_irqs, 0);

--- 13 unchanged lines hidden (view full) ---

722 */
723 status = twl4030_init_sih_modules(twl_irq_line);
724 if (status < 0)
725 return status;
726
727 twl4030_irq_base = irq_base;
728
729 /*
698 /*
699 * TWL core and pwr interrupts must be contiguous because
700 * the hwirqs numbers are defined contiguously from 1 to 15.
701 * Create only one domain for both.
702 */
703 nr_irqs = TWL4030_PWR_NR_IRQS + TWL4030_CORE_NR_IRQS;
704
705 irq_base = irq_alloc_descs(-1, 0, nr_irqs, 0);

--- 13 unchanged lines hidden (view full) ---

719 */
720 status = twl4030_init_sih_modules(twl_irq_line);
721 if (status < 0)
722 return status;
723
724 twl4030_irq_base = irq_base;
725
726 /*
730 * install an irq handler for each of the SIH modules;
727 * Install an irq handler for each of the SIH modules;
731 * clone dummy irq_chip since PIH can't *do* anything
732 */
733 twl4030_irq_chip = dummy_irq_chip;
734 twl4030_irq_chip.name = "twl4030";
735
736 twl4030_sih_irq_chip.irq_ack = dummy_irq_chip.irq_ack;
737
738 for (i = irq_base; i < irq_end; i++) {
739 irq_set_chip_and_handler(i, &twl4030_irq_chip,
740 handle_simple_irq);
741 irq_set_nested_thread(i, 1);
742 activate_irq(i);
743 }
744
728 * clone dummy irq_chip since PIH can't *do* anything
729 */
730 twl4030_irq_chip = dummy_irq_chip;
731 twl4030_irq_chip.name = "twl4030";
732
733 twl4030_sih_irq_chip.irq_ack = dummy_irq_chip.irq_ack;
734
735 for (i = irq_base; i < irq_end; i++) {
736 irq_set_chip_and_handler(i, &twl4030_irq_chip,
737 handle_simple_irq);
738 irq_set_nested_thread(i, 1);
739 activate_irq(i);
740 }
741
745 pr_info("twl4030: %s (irq %d) chaining IRQs %d..%d\n", "PIH",
742 dev_info(dev, "%s (irq %d) chaining IRQs %d..%d\n", "PIH",
746 irq_num, irq_base, irq_end);
747
748 /* ... and the PWR_INT module ... */
749 status = twl4030_sih_setup(dev, TWL4030_MODULE_INT, irq_end);
750 if (status < 0) {
743 irq_num, irq_base, irq_end);
744
745 /* ... and the PWR_INT module ... */
746 status = twl4030_sih_setup(dev, TWL4030_MODULE_INT, irq_end);
747 if (status < 0) {
751 pr_err("twl4030: sih_setup PWR INT --> %d\n", status);
748 dev_err(dev, "sih_setup PWR INT --> %d\n", status);
752 goto fail;
753 }
754
755 /* install an irq handler to demultiplex the TWL4030 interrupt */
756 status = request_threaded_irq(irq_num, NULL, handle_twl4030_pih,
757 IRQF_ONESHOT,
758 "TWL4030-PIH", NULL);
759 if (status < 0) {
749 goto fail;
750 }
751
752 /* install an irq handler to demultiplex the TWL4030 interrupt */
753 status = request_threaded_irq(irq_num, NULL, handle_twl4030_pih,
754 IRQF_ONESHOT,
755 "TWL4030-PIH", NULL);
756 if (status < 0) {
760 pr_err("twl4030: could not claim irq%d: %d\n", irq_num, status);
757 dev_err(dev, "could not claim irq%d: %d\n", irq_num, status);
761 goto fail_rqirq;
762 }
763
764 return irq_base;
765fail_rqirq:
766 /* clean up twl4030_sih_setup */
767fail:
768 for (i = irq_base; i < irq_end; i++) {

--- 29 unchanged lines hidden ---
758 goto fail_rqirq;
759 }
760
761 return irq_base;
762fail_rqirq:
763 /* clean up twl4030_sih_setup */
764fail:
765 for (i = irq_base; i < irq_end; i++) {

--- 29 unchanged lines hidden ---