aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGrant Likely <grant.likely@secretlab.ca>2012-01-26 13:26:52 -0500
committerGrant Likely <grant.likely@secretlab.ca>2012-02-16 08:11:23 -0500
commit16b2e6e2f31dda41f114aa0acade04f7e10f67c9 (patch)
tree73f8f3066e09eb7bb427c51fe2711458ac9220a2
parent6b783f7c5dde2648fa0bbe7fc8ac80d78699e67f (diff)
irq_domain: Create common xlate functions that device drivers can use
Rather than having each interrupt controller driver creating its own barely unique .xlate function for irq_domain, create a library of translators which any driver can use directly. v5: - Remove irq_domain_xlate_pci(). It was incorrect. Signed-off-by: Grant Likely <grant.likely@secretlab.ca> Cc: Rob Herring <rob.herring@calxeda.com> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Mark Salter <msalter@redhat.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Milton Miller <miltonm@bga.com> Tested-by: Olof Johansson <olof@lixom.net>
-rw-r--r--include/linux/irqdomain.h12
-rw-r--r--kernel/irq/irqdomain.c65
2 files changed, 67 insertions, 10 deletions
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index e7379a3c4d7..ea58f36688a 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -163,6 +163,18 @@ extern unsigned int irq_linear_revmap(struct irq_domain *host,
163 irq_hw_number_t hwirq); 163 irq_hw_number_t hwirq);
164 164
165extern struct irq_domain_ops irq_domain_simple_ops; 165extern struct irq_domain_ops irq_domain_simple_ops;
166
167/* stock xlate functions */
168int irq_domain_xlate_onecell(struct irq_domain *d, struct device_node *ctrlr,
169 const u32 *intspec, unsigned int intsize,
170 irq_hw_number_t *out_hwirq, unsigned int *out_type);
171int irq_domain_xlate_twocell(struct irq_domain *d, struct device_node *ctrlr,
172 const u32 *intspec, unsigned int intsize,
173 irq_hw_number_t *out_hwirq, unsigned int *out_type);
174int irq_domain_xlate_onetwocell(struct irq_domain *d, struct device_node *ctrlr,
175 const u32 *intspec, unsigned int intsize,
176 irq_hw_number_t *out_hwirq, unsigned int *out_type);
177
166#if defined(CONFIG_OF_IRQ) 178#if defined(CONFIG_OF_IRQ)
167extern void irq_domain_generate_simple(const struct of_device_id *match, 179extern void irq_domain_generate_simple(const struct of_device_id *match,
168 u64 phys_base, unsigned int irq_start); 180 u64 phys_base, unsigned int irq_start);
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 6328d9350f0..456e3fc8387 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -699,25 +699,70 @@ int irq_domain_simple_map(struct irq_domain *d, unsigned int irq,
699 return 0; 699 return 0;
700} 700}
701 701
702int irq_domain_simple_xlate(struct irq_domain *d, 702/**
703 struct device_node *controller, 703 * irq_domain_xlate_onecell() - Generic xlate for direct one cell bindings
704 const u32 *intspec, unsigned int intsize, 704 *
705 unsigned long *out_hwirq, unsigned int *out_type) 705 * Device Tree IRQ specifier translation function which works with one cell
706 * bindings where the cell value maps directly to the hwirq number.
707 */
708int irq_domain_xlate_onecell(struct irq_domain *d, struct device_node *ctrlr,
709 const u32 *intspec, unsigned int intsize,
710 unsigned long *out_hwirq, unsigned int *out_type)
706{ 711{
707 if (d->of_node != controller) 712 if (WARN_ON(intsize < 1))
708 return -EINVAL;
709 if (intsize < 1)
710 return -EINVAL; 713 return -EINVAL;
711 *out_hwirq = intspec[0]; 714 *out_hwirq = intspec[0];
712 *out_type = IRQ_TYPE_NONE; 715 *out_type = IRQ_TYPE_NONE;
713 if (intsize > 1)
714 *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
715 return 0; 716 return 0;
716} 717}
718EXPORT_SYMBOL_GPL(irq_domain_xlate_onecell);
719
720/**
721 * irq_domain_xlate_twocell() - Generic xlate for direct two cell bindings
722 *
723 * Device Tree IRQ specifier translation function which works with two cell
724 * bindings where the cell values map directly to the hwirq number
725 * and linux irq flags.
726 */
727int irq_domain_xlate_twocell(struct irq_domain *d, struct device_node *ctrlr,
728 const u32 *intspec, unsigned int intsize,
729 irq_hw_number_t *out_hwirq, unsigned int *out_type)
730{
731 if (WARN_ON(intsize < 2))
732 return -EINVAL;
733 *out_hwirq = intspec[0];
734 *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
735 return 0;
736}
737EXPORT_SYMBOL_GPL(irq_domain_xlate_twocell);
738
739/**
740 * irq_domain_xlate_onetwocell() - Generic xlate for one or two cell bindings
741 *
742 * Device Tree IRQ specifier translation function which works with either one
743 * or two cell bindings where the cell values map directly to the hwirq number
744 * and linux irq flags.
745 *
746 * Note: don't use this function unless your interrupt controller explicitly
747 * supports both one and two cell bindings. For the majority of controllers
748 * the _onecell() or _twocell() variants above should be used.
749 */
750int irq_domain_xlate_onetwocell(struct irq_domain *d,
751 struct device_node *ctrlr,
752 const u32 *intspec, unsigned int intsize,
753 unsigned long *out_hwirq, unsigned int *out_type)
754{
755 if (WARN_ON(intsize < 1))
756 return -EINVAL;
757 *out_hwirq = intspec[0];
758 *out_type = (intsize > 1) ? intspec[1] : IRQ_TYPE_NONE;
759 return 0;
760}
761EXPORT_SYMBOL_GPL(irq_domain_xlate_onetwocell);
717 762
718struct irq_domain_ops irq_domain_simple_ops = { 763struct irq_domain_ops irq_domain_simple_ops = {
719 .map = irq_domain_simple_map, 764 .map = irq_domain_simple_map,
720 .xlate = irq_domain_simple_xlate, 765 .xlate = irq_domain_xlate_onetwocell,
721}; 766};
722EXPORT_SYMBOL_GPL(irq_domain_simple_ops); 767EXPORT_SYMBOL_GPL(irq_domain_simple_ops);
723 768