All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/2] Simple irq_domain implementation
@ 2011-07-26  9:36 Grant Likely
  2011-07-26  9:36   ` Grant Likely
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Grant Likely @ 2011-07-26  9:36 UTC (permalink / raw)
  To: devicetree-discuss, tglx, linux, linux-kernel

In the interest of getting this infrastructure merged, I've reworked the
basic irq_domain patch to implement only what is required for ARM device
tree board support.  That means it doesn't affect any architectures other
than ARM, and I'll send follow-on patches targeted at v3.2 to migrate
MIPS, Microblaze, x86 embedded and PowerPC over to it.

Thomas, can you please take a look?  I've got devicetree board support
queued up and ready to be merged but for this infrastructure.

g.

---

Grant Likely (2):
      irq: add irq_domain translation infrastructure
      dt/irq: add irq_domain_generate_simple() helper


 arch/arm/Kconfig            |    1 
 arch/arm/include/asm/prom.h |    5 -
 arch/arm/kernel/devtree.c   |   14 ---
 include/linux/irq.h         |    6 +
 include/linux/irqdomain.h   |   93 ++++++++++++++++++++++
 include/linux/of_irq.h      |    4 +
 kernel/irq/Kconfig          |    4 +
 kernel/irq/Makefile         |    1 
 kernel/irq/irqdomain.c      |  180 +++++++++++++++++++++++++++++++++++++++++++
 9 files changed, 289 insertions(+), 19 deletions(-)
 create mode 100644 include/linux/irqdomain.h
 create mode 100644 kernel/irq/irqdomain.c

-- 
Signature

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v3 1/2] irq: add irq_domain translation infrastructure
  2011-07-26  9:36 [PATCH v3 0/2] Simple irq_domain implementation Grant Likely
@ 2011-07-26  9:36   ` Grant Likely
  2011-07-26  9:36   ` Grant Likely
  2011-07-28  9:31 ` [PATCH v3 0/2] Simple irq_domain implementation Thomas Gleixner
  2 siblings, 0 replies; 10+ messages in thread
From: Grant Likely @ 2011-07-26  9:36 UTC (permalink / raw)
  To: devicetree-discuss, tglx, linux, linux-kernel

This patch adds irq_domain infrastructure for translating from
hardware irq numbers to linux irqs.  This is particularly important
for architectures adding device tree support because the current
implementation (excluding PowerPC and SPARC) cannot handle
translation for more than a single interrupt controller.  irq_domain
supports device tree translation for any number of interrupt
controllers.

This patch converts x86, Microblaze, ARM and MIPS to use irq_domain
for device tree irq translation.  x86 is untested beyond compiling it,
irq_domain is enabled for MIPS and Microblaze, but the old behaviour is
preserved until the core code is modified to actually register an
irq_domain yet.  On ARM it works and is required for much of the new
ARM device tree board support.

PowerPC has /not/ been converted to use this new infrastructure.  It
is still missing some features before it can replace the virq
infrastructure already in powerpc (see documentation on
irq_domain_map/unmap for details).  Followup patches will add the
missing pieces and migrate PowerPC to use irq_domain.

SPARC has its own method of managing interrupts from the device tree
and is unaffected by this change.

Acked-by: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
 arch/arm/Kconfig            |    1 
 arch/arm/include/asm/prom.h |    5 --
 arch/arm/kernel/devtree.c   |   14 -----
 include/linux/irq.h         |    6 ++
 include/linux/irqdomain.h   |   81 ++++++++++++++++++++++++++++
 include/linux/of_irq.h      |    4 +
 kernel/irq/Kconfig          |    4 +
 kernel/irq/Makefile         |    1 
 kernel/irq/irqdomain.c      |  123 +++++++++++++++++++++++++++++++++++++++++++
 9 files changed, 220 insertions(+), 19 deletions(-)
 create mode 100644 include/linux/irqdomain.h
 create mode 100644 kernel/irq/irqdomain.c

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 9cb1f4b..b2695aa 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1680,6 +1680,7 @@ config USE_OF
 	bool "Flattened Device Tree support"
 	select OF
 	select OF_EARLY_FLATTREE
+	select IRQ_DOMAIN
 	help
 	  Include support for flattened device tree machine descriptions.
 
diff --git a/arch/arm/include/asm/prom.h b/arch/arm/include/asm/prom.h
index 11b8708..6f65ca8 100644
--- a/arch/arm/include/asm/prom.h
+++ b/arch/arm/include/asm/prom.h
@@ -16,11 +16,6 @@
 #include <asm/setup.h>
 #include <asm/irq.h>
 
-static inline void irq_dispose_mapping(unsigned int virq)
-{
-	return;
-}
-
 extern struct machine_desc *setup_machine_fdt(unsigned int dt_phys);
 extern void arm_dt_memblock_reserve(void);
 
diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c
index 0cdd7b4..1a33e9d 100644
--- a/arch/arm/kernel/devtree.c
+++ b/arch/arm/kernel/devtree.c
@@ -132,17 +132,3 @@ struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys)
 
 	return mdesc_best;
 }
-
-/**
- * irq_create_of_mapping - Hook to resolve OF irq specifier into a Linux irq#
- *
- * Currently the mapping mechanism is trivial; simple flat hwirq numbers are
- * mapped 1:1 onto Linux irq numbers.  Cascaded irq controllers are not
- * supported.
- */
-unsigned int irq_create_of_mapping(struct device_node *controller,
-				   const u32 *intspec, unsigned int intsize)
-{
-	return intspec[0];
-}
-EXPORT_SYMBOL_GPL(irq_create_of_mapping);
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 5f69504..87a06f3 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -108,14 +108,18 @@ enum {
 };
 
 struct msi_desc;
+struct irq_domain;
 
 /**
  * struct irq_data - per irq and irq chip data passed down to chip functions
  * @irq:		interrupt number
+ * @hwirq:		hardware interrupt number, local to the interrupt domain
  * @node:		node index useful for balancing
  * @state_use_accessors: status information for irq chip functions.
  *			Use accessor functions to deal with it
  * @chip:		low level interrupt hardware access
+ * @domain:		Interrupt translation domain; responsible for mapping
+ *			between hwirq number and linux irq number.
  * @handler_data:	per-IRQ data for the irq_chip methods
  * @chip_data:		platform-specific per-chip private data for the chip
  *			methods, to allow shared chip implementations
@@ -128,9 +132,11 @@ struct msi_desc;
  */
 struct irq_data {
 	unsigned int		irq;
+	unsigned long		hwirq;
 	unsigned int		node;
 	unsigned int		state_use_accessors;
 	struct irq_chip		*chip;
+	struct irq_domain	*domain;
 	void			*handler_data;
 	void			*chip_data;
 	struct msi_desc		*msi_desc;
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
new file mode 100644
index 0000000..8f2c10a
--- /dev/null
+++ b/include/linux/irqdomain.h
@@ -0,0 +1,81 @@
+/*
+ * irq_domain - IRQ translation domains
+ *
+ * Translation infrastructure between hw and linux irq numbers.  This is
+ * helpful for interrupt controllers to implement mapping between hardware
+ * irq numbers and the Linux irq number space.
+ *
+ * irq_domains also have a hook for translating device tree interrupt
+ * representation into a hardware irq number that can be mapped back to a
+ * Linux irq number without any extra platform support code.
+ *
+ * irq_domain is expected to be embedded in an interrupt controller's private
+ * data structure.
+ */
+#ifndef _LINUX_IRQDOMAIN_H
+#define _LINUX_IRQDOMAIN_H
+
+#include <linux/irq.h>
+
+#ifdef CONFIG_IRQ_DOMAIN
+struct device_node;
+struct irq_domain;
+
+/**
+ * struct irq_domain_ops - Methods for irq_domain objects
+ * @to_irq: (optional) given a local hardware irq number, return the linux
+ *          irq number.  If to_irq is not implemented, then the irq_domain
+ *          will use this translation: irq = (domain->irq_base + hwirq)
+ * @dt_translate: Given a device tree node and interrupt specifier, decode
+ *                the hardware irq number and linux irq type value.
+ */
+struct irq_domain_ops {
+	unsigned int (*to_irq)(struct irq_domain *d, unsigned long hwirq);
+
+#ifdef CONFIG_OF
+	int (*dt_translate)(struct irq_domain *d, struct device_node *node,
+			    const u32 *intspec, unsigned int intsize,
+			    unsigned long *out_hwirq, unsigned int *out_type);
+#endif /* CONFIG_OF */
+};
+
+/**
+ * struct irq_domain - Hardware interrupt number translation object
+ * @list: Element in global irq_domain list.
+ * @irq_base: Start of irq_desc range assigned to the irq_domain.  The creator
+ *            of the irq_domain is responsible for allocating the array of
+ *            irq_desc structures.
+ * @nr_irq: Number of irqs managed by the irq domain
+ * @ops: pointer to irq_domain methods
+ * @priv: private data pointer for use by owner.  Not touched by irq_domain
+ *        core code.
+ * @of_node: (optional) Pointer to device tree nodes associated with the
+ *           irq_domain.  Used when decoding device tree interrupt specifiers.
+ */
+struct irq_domain {
+	struct list_head list;
+	unsigned int irq_base;
+	unsigned int nr_irq;
+	const struct irq_domain_ops *ops;
+	void *priv;
+	struct device_node *of_node;
+};
+
+/**
+ * irq_domain_to_irq() - Translate from a hardware irq to a linux irq number
+ *
+ * Returns the linux irq number associated with a hardware irq.  By default,
+ * the mapping is irq == domain->irq_base + hwirq, but this mapping can
+ * be overridden if the irq_domain implements a .to_irq() hook.
+ */
+static inline unsigned int irq_domain_to_irq(struct irq_domain *d,
+					     unsigned long hwirq)
+{
+	return d->ops->to_irq ? d->ops->to_irq(d, hwirq) : d->irq_base + hwirq;
+}
+
+extern void irq_domain_add(struct irq_domain *domain);
+extern void irq_domain_del(struct irq_domain *domain);
+#endif /* CONFIG_IRQ_DOMAIN */
+
+#endif /* _LINUX_IRQDOMAIN_H */
diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h
index e6955f5..cd2e61c 100644
--- a/include/linux/of_irq.h
+++ b/include/linux/of_irq.h
@@ -63,6 +63,9 @@ extern int of_irq_map_one(struct device_node *device, int index,
 extern unsigned int irq_create_of_mapping(struct device_node *controller,
 					  const u32 *intspec,
 					  unsigned int intsize);
+#ifdef CONFIG_IRQ_DOMAIN
+extern void irq_dispose_mapping(unsigned int irq);
+#endif
 extern int of_irq_to_resource(struct device_node *dev, int index,
 			      struct resource *r);
 extern int of_irq_count(struct device_node *dev);
@@ -70,6 +73,7 @@ extern int of_irq_to_resource_table(struct device_node *dev,
 		struct resource *res, int nr_irqs);
 extern struct device_node *of_irq_find_parent(struct device_node *child);
 
+
 #endif /* CONFIG_OF_IRQ */
 #endif /* CONFIG_OF */
 #endif /* __OF_IRQ_H */
diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig
index d1d051b3..5a38bf4 100644
--- a/kernel/irq/Kconfig
+++ b/kernel/irq/Kconfig
@@ -52,6 +52,10 @@ config IRQ_EDGE_EOI_HANDLER
 config GENERIC_IRQ_CHIP
        bool
 
+# Generic irq_domain hw <--> linux irq number translation
+config IRQ_DOMAIN
+	bool
+
 # Support forced irq threading
 config IRQ_FORCED_THREADING
        bool
diff --git a/kernel/irq/Makefile b/kernel/irq/Makefile
index 7329005..fff1738 100644
--- a/kernel/irq/Makefile
+++ b/kernel/irq/Makefile
@@ -2,6 +2,7 @@
 obj-y := irqdesc.o handle.o manage.o spurious.o resend.o chip.o dummychip.o devres.o
 obj-$(CONFIG_GENERIC_IRQ_CHIP) += generic-chip.o
 obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o
+obj-$(CONFIG_IRQ_DOMAIN) += irqdomain.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o
 obj-$(CONFIG_PM_SLEEP) += pm.o
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
new file mode 100644
index 0000000..171b754
--- /dev/null
+++ b/kernel/irq/irqdomain.c
@@ -0,0 +1,123 @@
+
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+
+static LIST_HEAD(irq_domain_list);
+static DEFINE_MUTEX(irq_domain_mutex);
+
+/**
+ * irq_domain_add() - Register an irq_domain
+ * @domain: ptr to initialized irq_domain structure
+ *
+ * Registers an irq_domain structure.  The irq_domain must at a minimum be
+ * initialized with an ops structure pointer, and either a ->to_irq hook or
+ * a valid irq_base value.  Everything else is optional.
+ */
+void irq_domain_add(struct irq_domain *domain)
+{
+	struct irq_data *d;
+	int hwirq;
+
+	/*
+	 * This assumes that the irq_domain owner has already allocated
+	 * the irq_descs.  This block will be removed when support for dynamic
+	 * allocation of irq_descs is added to irq_domain.
+	 */
+	for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
+		d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
+		if (d || d->domain) {
+			/* things are broken; just report, don't clean up */
+			WARN(1, "error: irq_desc already assigned to a domain");
+			return;
+		}
+		d->domain = domain;
+		d->hwirq = hwirq;
+	}
+
+	mutex_lock(&irq_domain_mutex);
+	list_add(&domain->list, &irq_domain_list);
+	mutex_unlock(&irq_domain_mutex);
+}
+
+/**
+ * irq_domain_del() - Unregister an irq_domain
+ * @domain: ptr to registered irq_domain.
+ */
+void irq_domain_del(struct irq_domain *domain)
+{
+	struct irq_data *d;
+	int hwirq;
+
+	mutex_lock(&irq_domain_mutex);
+	list_del(&domain->list);
+	mutex_unlock(&irq_domain_mutex);
+
+	/* Clear the irq_domain assignments */
+	for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
+		d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
+		d->domain = NULL;
+	}
+}
+
+#if defined(CONFIG_OF_IRQ)
+/**
+ * irq_create_of_mapping() - Map a linux irq number from a DT interrupt spec
+ *
+ * Used by the device tree interrupt mapping code to translate a device tree
+ * interrupt specifier to a valid linux irq number.  Returns either a valid
+ * linux IRQ number or 0.
+ *
+ * When the caller no longer need the irq number returned by this function it
+ * should arrange to call irq_dispose_mapping().
+ */
+unsigned int irq_create_of_mapping(struct device_node *controller,
+				   const u32 *intspec, unsigned int intsize)
+{
+	struct irq_domain *domain;
+	unsigned long hwirq;
+	unsigned int irq, type;
+	int rc = -EINVAL;
+
+	/* Find a domain which can translate the irq spec */
+	mutex_lock(&irq_domain_mutex);
+	list_for_each_entry(domain, &irq_domain_list, list) {
+		if (!domain->ops->dt_translate)
+			continue;
+		rc = domain->ops->dt_translate(domain, controller,
+					intspec, intsize, &hwirq, &type);
+		if (rc == 0)
+			break;
+	}
+	mutex_unlock(&irq_domain_mutex);
+
+	if (rc != 0)
+		return 0;
+
+	irq = irq_domain_to_irq(domain, hwirq);
+	if (type != IRQ_TYPE_NONE)
+		irq_set_irq_type(irq, type);
+	pr_debug("%s: mapped hwirq=%i to irq=%i, flags=%x\n",
+		 controller->full_name, (int)hwirq, irq, type);
+	return irq;
+}
+EXPORT_SYMBOL_GPL(irq_create_of_mapping);
+
+/**
+ * irq_dispose_mapping() - Discard a mapping created by irq_create_of_mapping()
+ * @irq: linux irq number to be discarded
+ *
+ * Calling this function indicates the caller no longer needs a reference to
+ * the linux irq number returned by a prior call to irq_create_of_mapping().
+ */
+void irq_dispose_mapping(unsigned int irq)
+{
+	/*
+	 * nothing yet; will be filled when support for dynamic allocation of
+	 * irq_descs is added to irq_domain
+	 */
+}
+EXPORT_SYMBOL_GPL(irq_dispose_mapping);
+#endif /* CONFIG_OF_IRQ */


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v3 1/2] irq: add irq_domain translation infrastructure
@ 2011-07-26  9:36   ` Grant Likely
  0 siblings, 0 replies; 10+ messages in thread
From: Grant Likely @ 2011-07-26  9:36 UTC (permalink / raw)
  To: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	tglx-hfZtesqFncYOwBW4kG4KsQ, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

This patch adds irq_domain infrastructure for translating from
hardware irq numbers to linux irqs.  This is particularly important
for architectures adding device tree support because the current
implementation (excluding PowerPC and SPARC) cannot handle
translation for more than a single interrupt controller.  irq_domain
supports device tree translation for any number of interrupt
controllers.

This patch converts x86, Microblaze, ARM and MIPS to use irq_domain
for device tree irq translation.  x86 is untested beyond compiling it,
irq_domain is enabled for MIPS and Microblaze, but the old behaviour is
preserved until the core code is modified to actually register an
irq_domain yet.  On ARM it works and is required for much of the new
ARM device tree board support.

PowerPC has /not/ been converted to use this new infrastructure.  It
is still missing some features before it can replace the virq
infrastructure already in powerpc (see documentation on
irq_domain_map/unmap for details).  Followup patches will add the
missing pieces and migrate PowerPC to use irq_domain.

SPARC has its own method of managing interrupts from the device tree
and is unaffected by this change.

Acked-by: Ralf Baechle <ralf-6z/3iImG2C8G8FEW9MqTrA@public.gmane.org>
Signed-off-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
---
 arch/arm/Kconfig            |    1 
 arch/arm/include/asm/prom.h |    5 --
 arch/arm/kernel/devtree.c   |   14 -----
 include/linux/irq.h         |    6 ++
 include/linux/irqdomain.h   |   81 ++++++++++++++++++++++++++++
 include/linux/of_irq.h      |    4 +
 kernel/irq/Kconfig          |    4 +
 kernel/irq/Makefile         |    1 
 kernel/irq/irqdomain.c      |  123 +++++++++++++++++++++++++++++++++++++++++++
 9 files changed, 220 insertions(+), 19 deletions(-)
 create mode 100644 include/linux/irqdomain.h
 create mode 100644 kernel/irq/irqdomain.c

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 9cb1f4b..b2695aa 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1680,6 +1680,7 @@ config USE_OF
 	bool "Flattened Device Tree support"
 	select OF
 	select OF_EARLY_FLATTREE
+	select IRQ_DOMAIN
 	help
 	  Include support for flattened device tree machine descriptions.
 
diff --git a/arch/arm/include/asm/prom.h b/arch/arm/include/asm/prom.h
index 11b8708..6f65ca8 100644
--- a/arch/arm/include/asm/prom.h
+++ b/arch/arm/include/asm/prom.h
@@ -16,11 +16,6 @@
 #include <asm/setup.h>
 #include <asm/irq.h>
 
-static inline void irq_dispose_mapping(unsigned int virq)
-{
-	return;
-}
-
 extern struct machine_desc *setup_machine_fdt(unsigned int dt_phys);
 extern void arm_dt_memblock_reserve(void);
 
diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c
index 0cdd7b4..1a33e9d 100644
--- a/arch/arm/kernel/devtree.c
+++ b/arch/arm/kernel/devtree.c
@@ -132,17 +132,3 @@ struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys)
 
 	return mdesc_best;
 }
-
-/**
- * irq_create_of_mapping - Hook to resolve OF irq specifier into a Linux irq#
- *
- * Currently the mapping mechanism is trivial; simple flat hwirq numbers are
- * mapped 1:1 onto Linux irq numbers.  Cascaded irq controllers are not
- * supported.
- */
-unsigned int irq_create_of_mapping(struct device_node *controller,
-				   const u32 *intspec, unsigned int intsize)
-{
-	return intspec[0];
-}
-EXPORT_SYMBOL_GPL(irq_create_of_mapping);
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 5f69504..87a06f3 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -108,14 +108,18 @@ enum {
 };
 
 struct msi_desc;
+struct irq_domain;
 
 /**
  * struct irq_data - per irq and irq chip data passed down to chip functions
  * @irq:		interrupt number
+ * @hwirq:		hardware interrupt number, local to the interrupt domain
  * @node:		node index useful for balancing
  * @state_use_accessors: status information for irq chip functions.
  *			Use accessor functions to deal with it
  * @chip:		low level interrupt hardware access
+ * @domain:		Interrupt translation domain; responsible for mapping
+ *			between hwirq number and linux irq number.
  * @handler_data:	per-IRQ data for the irq_chip methods
  * @chip_data:		platform-specific per-chip private data for the chip
  *			methods, to allow shared chip implementations
@@ -128,9 +132,11 @@ struct msi_desc;
  */
 struct irq_data {
 	unsigned int		irq;
+	unsigned long		hwirq;
 	unsigned int		node;
 	unsigned int		state_use_accessors;
 	struct irq_chip		*chip;
+	struct irq_domain	*domain;
 	void			*handler_data;
 	void			*chip_data;
 	struct msi_desc		*msi_desc;
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
new file mode 100644
index 0000000..8f2c10a
--- /dev/null
+++ b/include/linux/irqdomain.h
@@ -0,0 +1,81 @@
+/*
+ * irq_domain - IRQ translation domains
+ *
+ * Translation infrastructure between hw and linux irq numbers.  This is
+ * helpful for interrupt controllers to implement mapping between hardware
+ * irq numbers and the Linux irq number space.
+ *
+ * irq_domains also have a hook for translating device tree interrupt
+ * representation into a hardware irq number that can be mapped back to a
+ * Linux irq number without any extra platform support code.
+ *
+ * irq_domain is expected to be embedded in an interrupt controller's private
+ * data structure.
+ */
+#ifndef _LINUX_IRQDOMAIN_H
+#define _LINUX_IRQDOMAIN_H
+
+#include <linux/irq.h>
+
+#ifdef CONFIG_IRQ_DOMAIN
+struct device_node;
+struct irq_domain;
+
+/**
+ * struct irq_domain_ops - Methods for irq_domain objects
+ * @to_irq: (optional) given a local hardware irq number, return the linux
+ *          irq number.  If to_irq is not implemented, then the irq_domain
+ *          will use this translation: irq = (domain->irq_base + hwirq)
+ * @dt_translate: Given a device tree node and interrupt specifier, decode
+ *                the hardware irq number and linux irq type value.
+ */
+struct irq_domain_ops {
+	unsigned int (*to_irq)(struct irq_domain *d, unsigned long hwirq);
+
+#ifdef CONFIG_OF
+	int (*dt_translate)(struct irq_domain *d, struct device_node *node,
+			    const u32 *intspec, unsigned int intsize,
+			    unsigned long *out_hwirq, unsigned int *out_type);
+#endif /* CONFIG_OF */
+};
+
+/**
+ * struct irq_domain - Hardware interrupt number translation object
+ * @list: Element in global irq_domain list.
+ * @irq_base: Start of irq_desc range assigned to the irq_domain.  The creator
+ *            of the irq_domain is responsible for allocating the array of
+ *            irq_desc structures.
+ * @nr_irq: Number of irqs managed by the irq domain
+ * @ops: pointer to irq_domain methods
+ * @priv: private data pointer for use by owner.  Not touched by irq_domain
+ *        core code.
+ * @of_node: (optional) Pointer to device tree nodes associated with the
+ *           irq_domain.  Used when decoding device tree interrupt specifiers.
+ */
+struct irq_domain {
+	struct list_head list;
+	unsigned int irq_base;
+	unsigned int nr_irq;
+	const struct irq_domain_ops *ops;
+	void *priv;
+	struct device_node *of_node;
+};
+
+/**
+ * irq_domain_to_irq() - Translate from a hardware irq to a linux irq number
+ *
+ * Returns the linux irq number associated with a hardware irq.  By default,
+ * the mapping is irq == domain->irq_base + hwirq, but this mapping can
+ * be overridden if the irq_domain implements a .to_irq() hook.
+ */
+static inline unsigned int irq_domain_to_irq(struct irq_domain *d,
+					     unsigned long hwirq)
+{
+	return d->ops->to_irq ? d->ops->to_irq(d, hwirq) : d->irq_base + hwirq;
+}
+
+extern void irq_domain_add(struct irq_domain *domain);
+extern void irq_domain_del(struct irq_domain *domain);
+#endif /* CONFIG_IRQ_DOMAIN */
+
+#endif /* _LINUX_IRQDOMAIN_H */
diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h
index e6955f5..cd2e61c 100644
--- a/include/linux/of_irq.h
+++ b/include/linux/of_irq.h
@@ -63,6 +63,9 @@ extern int of_irq_map_one(struct device_node *device, int index,
 extern unsigned int irq_create_of_mapping(struct device_node *controller,
 					  const u32 *intspec,
 					  unsigned int intsize);
+#ifdef CONFIG_IRQ_DOMAIN
+extern void irq_dispose_mapping(unsigned int irq);
+#endif
 extern int of_irq_to_resource(struct device_node *dev, int index,
 			      struct resource *r);
 extern int of_irq_count(struct device_node *dev);
@@ -70,6 +73,7 @@ extern int of_irq_to_resource_table(struct device_node *dev,
 		struct resource *res, int nr_irqs);
 extern struct device_node *of_irq_find_parent(struct device_node *child);
 
+
 #endif /* CONFIG_OF_IRQ */
 #endif /* CONFIG_OF */
 #endif /* __OF_IRQ_H */
diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig
index d1d051b3..5a38bf4 100644
--- a/kernel/irq/Kconfig
+++ b/kernel/irq/Kconfig
@@ -52,6 +52,10 @@ config IRQ_EDGE_EOI_HANDLER
 config GENERIC_IRQ_CHIP
        bool
 
+# Generic irq_domain hw <--> linux irq number translation
+config IRQ_DOMAIN
+	bool
+
 # Support forced irq threading
 config IRQ_FORCED_THREADING
        bool
diff --git a/kernel/irq/Makefile b/kernel/irq/Makefile
index 7329005..fff1738 100644
--- a/kernel/irq/Makefile
+++ b/kernel/irq/Makefile
@@ -2,6 +2,7 @@
 obj-y := irqdesc.o handle.o manage.o spurious.o resend.o chip.o dummychip.o devres.o
 obj-$(CONFIG_GENERIC_IRQ_CHIP) += generic-chip.o
 obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o
+obj-$(CONFIG_IRQ_DOMAIN) += irqdomain.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o
 obj-$(CONFIG_PM_SLEEP) += pm.o
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
new file mode 100644
index 0000000..171b754
--- /dev/null
+++ b/kernel/irq/irqdomain.c
@@ -0,0 +1,123 @@
+
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+
+static LIST_HEAD(irq_domain_list);
+static DEFINE_MUTEX(irq_domain_mutex);
+
+/**
+ * irq_domain_add() - Register an irq_domain
+ * @domain: ptr to initialized irq_domain structure
+ *
+ * Registers an irq_domain structure.  The irq_domain must at a minimum be
+ * initialized with an ops structure pointer, and either a ->to_irq hook or
+ * a valid irq_base value.  Everything else is optional.
+ */
+void irq_domain_add(struct irq_domain *domain)
+{
+	struct irq_data *d;
+	int hwirq;
+
+	/*
+	 * This assumes that the irq_domain owner has already allocated
+	 * the irq_descs.  This block will be removed when support for dynamic
+	 * allocation of irq_descs is added to irq_domain.
+	 */
+	for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
+		d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
+		if (d || d->domain) {
+			/* things are broken; just report, don't clean up */
+			WARN(1, "error: irq_desc already assigned to a domain");
+			return;
+		}
+		d->domain = domain;
+		d->hwirq = hwirq;
+	}
+
+	mutex_lock(&irq_domain_mutex);
+	list_add(&domain->list, &irq_domain_list);
+	mutex_unlock(&irq_domain_mutex);
+}
+
+/**
+ * irq_domain_del() - Unregister an irq_domain
+ * @domain: ptr to registered irq_domain.
+ */
+void irq_domain_del(struct irq_domain *domain)
+{
+	struct irq_data *d;
+	int hwirq;
+
+	mutex_lock(&irq_domain_mutex);
+	list_del(&domain->list);
+	mutex_unlock(&irq_domain_mutex);
+
+	/* Clear the irq_domain assignments */
+	for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
+		d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
+		d->domain = NULL;
+	}
+}
+
+#if defined(CONFIG_OF_IRQ)
+/**
+ * irq_create_of_mapping() - Map a linux irq number from a DT interrupt spec
+ *
+ * Used by the device tree interrupt mapping code to translate a device tree
+ * interrupt specifier to a valid linux irq number.  Returns either a valid
+ * linux IRQ number or 0.
+ *
+ * When the caller no longer need the irq number returned by this function it
+ * should arrange to call irq_dispose_mapping().
+ */
+unsigned int irq_create_of_mapping(struct device_node *controller,
+				   const u32 *intspec, unsigned int intsize)
+{
+	struct irq_domain *domain;
+	unsigned long hwirq;
+	unsigned int irq, type;
+	int rc = -EINVAL;
+
+	/* Find a domain which can translate the irq spec */
+	mutex_lock(&irq_domain_mutex);
+	list_for_each_entry(domain, &irq_domain_list, list) {
+		if (!domain->ops->dt_translate)
+			continue;
+		rc = domain->ops->dt_translate(domain, controller,
+					intspec, intsize, &hwirq, &type);
+		if (rc == 0)
+			break;
+	}
+	mutex_unlock(&irq_domain_mutex);
+
+	if (rc != 0)
+		return 0;
+
+	irq = irq_domain_to_irq(domain, hwirq);
+	if (type != IRQ_TYPE_NONE)
+		irq_set_irq_type(irq, type);
+	pr_debug("%s: mapped hwirq=%i to irq=%i, flags=%x\n",
+		 controller->full_name, (int)hwirq, irq, type);
+	return irq;
+}
+EXPORT_SYMBOL_GPL(irq_create_of_mapping);
+
+/**
+ * irq_dispose_mapping() - Discard a mapping created by irq_create_of_mapping()
+ * @irq: linux irq number to be discarded
+ *
+ * Calling this function indicates the caller no longer needs a reference to
+ * the linux irq number returned by a prior call to irq_create_of_mapping().
+ */
+void irq_dispose_mapping(unsigned int irq)
+{
+	/*
+	 * nothing yet; will be filled when support for dynamic allocation of
+	 * irq_descs is added to irq_domain
+	 */
+}
+EXPORT_SYMBOL_GPL(irq_dispose_mapping);
+#endif /* CONFIG_OF_IRQ */

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v3 2/2] dt/irq: add irq_domain_generate_simple() helper
  2011-07-26  9:36 [PATCH v3 0/2] Simple irq_domain implementation Grant Likely
@ 2011-07-26  9:36   ` Grant Likely
  2011-07-26  9:36   ` Grant Likely
  2011-07-28  9:31 ` [PATCH v3 0/2] Simple irq_domain implementation Thomas Gleixner
  2 siblings, 0 replies; 10+ messages in thread
From: Grant Likely @ 2011-07-26  9:36 UTC (permalink / raw)
  To: devicetree-discuss, tglx, linux, linux-kernel

irq_domain_generate_simple() is an easy way to generate an irq translation
domain for simple irq controllers.  It assumes a flat 1:1 mapping from
hardware irq number to an offset of the first linux irq number assigned
to the controller

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
 include/linux/irqdomain.h |   12 +++++++++
 kernel/irq/irqdomain.c    |   59 ++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 70 insertions(+), 1 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 8f2c10a..8e3ea36 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -16,6 +16,7 @@
 #define _LINUX_IRQDOMAIN_H
 
 #include <linux/irq.h>
+#include <linux/mod_devicetable.h>
 
 #ifdef CONFIG_IRQ_DOMAIN
 struct device_node;
@@ -76,6 +77,17 @@ static inline unsigned int irq_domain_to_irq(struct irq_domain *d,
 
 extern void irq_domain_add(struct irq_domain *domain);
 extern void irq_domain_del(struct irq_domain *domain);
+
+#ifdef CONFIG_OF_IRQ
+extern void irq_domain_add_simple(struct device_node *controller, int irq_base);
+extern void irq_domain_generate_simple(const struct of_device_id *match,
+					u64 phys_base, unsigned int irq_start);
+#else /* CONFIG_OF_IRQ */
+static inline void irq_domain_generate_simple(const struct of_device_id *match,
+					u64 phys_base, unsigned int irq_start) { }
+#endif /* CONFIG_OF_IRQ */
+
+
 #endif /* CONFIG_IRQ_DOMAIN */
 
 #endif /* _LINUX_IRQDOMAIN_H */
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 171b754..d5828da 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -1,9 +1,10 @@
-
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
 
 static LIST_HEAD(irq_domain_list);
 static DEFINE_MUTEX(irq_domain_mutex);
@@ -120,4 +121,60 @@ void irq_dispose_mapping(unsigned int irq)
 	 */
 }
 EXPORT_SYMBOL_GPL(irq_dispose_mapping);
+
+int irq_domain_simple_dt_translate(struct irq_domain *d,
+			    struct device_node *controller,
+			    const u32 *intspec, unsigned int intsize,
+			    unsigned long *out_hwirq, unsigned int *out_type)
+{
+	if (d->of_node != controller)
+		return -EINVAL;
+	if (intsize < 1)
+		return -EINVAL;
+
+	*out_hwirq = intspec[0];
+	*out_type = IRQ_TYPE_NONE;
+	if (intsize > 1)
+		*out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
+	return 0;
+}
+
+struct irq_domain_ops irq_domain_simple_ops = {
+	.dt_translate = irq_domain_simple_dt_translate,
+};
+EXPORT_SYMBOL_GPL(irq_domain_simple_ops);
+
+/**
+ * irq_domain_create_simple() - Set up a 'simple' translation range
+ */
+void irq_domain_add_simple(struct device_node *controller, int irq_base)
+{
+	struct irq_domain *domain;
+
+	domain = kzalloc(sizeof(*domain), GFP_KERNEL);
+	if (!domain) {
+		WARN_ON(1);
+		return;
+	}
+
+	domain->irq_base = irq_base;
+	domain->of_node = of_node_get(controller);
+	domain->ops = &irq_domain_simple_ops;
+	irq_domain_add(domain);
+}
+EXPORT_SYMBOL_GPL(irq_domain_add_simple);
+
+void irq_domain_generate_simple(const struct of_device_id *match,
+				u64 phys_base, unsigned int irq_start)
+{
+	struct device_node *node;
+	pr_info("looking for phys_base=%llx, irq_start=%i\n",
+		(unsigned long long) phys_base, (int) irq_start);
+	node = of_find_matching_node_by_address(NULL, match, phys_base);
+	if (node)
+		irq_domain_add_simple(node, irq_start);
+	else
+		pr_info("no node found\n");
+}
+EXPORT_SYMBOL_GPL(irq_domain_generate_simple);
 #endif /* CONFIG_OF_IRQ */


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v3 2/2] dt/irq: add irq_domain_generate_simple() helper
@ 2011-07-26  9:36   ` Grant Likely
  0 siblings, 0 replies; 10+ messages in thread
From: Grant Likely @ 2011-07-26  9:36 UTC (permalink / raw)
  To: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	tglx-hfZtesqFncYOwBW4kG4KsQ, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

irq_domain_generate_simple() is an easy way to generate an irq translation
domain for simple irq controllers.  It assumes a flat 1:1 mapping from
hardware irq number to an offset of the first linux irq number assigned
to the controller

Signed-off-by: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
---
 include/linux/irqdomain.h |   12 +++++++++
 kernel/irq/irqdomain.c    |   59 ++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 70 insertions(+), 1 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 8f2c10a..8e3ea36 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -16,6 +16,7 @@
 #define _LINUX_IRQDOMAIN_H
 
 #include <linux/irq.h>
+#include <linux/mod_devicetable.h>
 
 #ifdef CONFIG_IRQ_DOMAIN
 struct device_node;
@@ -76,6 +77,17 @@ static inline unsigned int irq_domain_to_irq(struct irq_domain *d,
 
 extern void irq_domain_add(struct irq_domain *domain);
 extern void irq_domain_del(struct irq_domain *domain);
+
+#ifdef CONFIG_OF_IRQ
+extern void irq_domain_add_simple(struct device_node *controller, int irq_base);
+extern void irq_domain_generate_simple(const struct of_device_id *match,
+					u64 phys_base, unsigned int irq_start);
+#else /* CONFIG_OF_IRQ */
+static inline void irq_domain_generate_simple(const struct of_device_id *match,
+					u64 phys_base, unsigned int irq_start) { }
+#endif /* CONFIG_OF_IRQ */
+
+
 #endif /* CONFIG_IRQ_DOMAIN */
 
 #endif /* _LINUX_IRQDOMAIN_H */
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 171b754..d5828da 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -1,9 +1,10 @@
-
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
 
 static LIST_HEAD(irq_domain_list);
 static DEFINE_MUTEX(irq_domain_mutex);
@@ -120,4 +121,60 @@ void irq_dispose_mapping(unsigned int irq)
 	 */
 }
 EXPORT_SYMBOL_GPL(irq_dispose_mapping);
+
+int irq_domain_simple_dt_translate(struct irq_domain *d,
+			    struct device_node *controller,
+			    const u32 *intspec, unsigned int intsize,
+			    unsigned long *out_hwirq, unsigned int *out_type)
+{
+	if (d->of_node != controller)
+		return -EINVAL;
+	if (intsize < 1)
+		return -EINVAL;
+
+	*out_hwirq = intspec[0];
+	*out_type = IRQ_TYPE_NONE;
+	if (intsize > 1)
+		*out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
+	return 0;
+}
+
+struct irq_domain_ops irq_domain_simple_ops = {
+	.dt_translate = irq_domain_simple_dt_translate,
+};
+EXPORT_SYMBOL_GPL(irq_domain_simple_ops);
+
+/**
+ * irq_domain_create_simple() - Set up a 'simple' translation range
+ */
+void irq_domain_add_simple(struct device_node *controller, int irq_base)
+{
+	struct irq_domain *domain;
+
+	domain = kzalloc(sizeof(*domain), GFP_KERNEL);
+	if (!domain) {
+		WARN_ON(1);
+		return;
+	}
+
+	domain->irq_base = irq_base;
+	domain->of_node = of_node_get(controller);
+	domain->ops = &irq_domain_simple_ops;
+	irq_domain_add(domain);
+}
+EXPORT_SYMBOL_GPL(irq_domain_add_simple);
+
+void irq_domain_generate_simple(const struct of_device_id *match,
+				u64 phys_base, unsigned int irq_start)
+{
+	struct device_node *node;
+	pr_info("looking for phys_base=%llx, irq_start=%i\n",
+		(unsigned long long) phys_base, (int) irq_start);
+	node = of_find_matching_node_by_address(NULL, match, phys_base);
+	if (node)
+		irq_domain_add_simple(node, irq_start);
+	else
+		pr_info("no node found\n");
+}
+EXPORT_SYMBOL_GPL(irq_domain_generate_simple);
 #endif /* CONFIG_OF_IRQ */

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v3 1/2] irq: add irq_domain translation infrastructure
  2011-07-26  9:36   ` Grant Likely
@ 2011-07-26  9:40     ` Grant Likely
  -1 siblings, 0 replies; 10+ messages in thread
From: Grant Likely @ 2011-07-26  9:40 UTC (permalink / raw)
  To: devicetree-discuss, tglx, linux, linux-kernel, linux-arm-kernel

On Tue, Jul 26, 2011 at 3:36 AM, Grant Likely <grant.likely@secretlab.ca> wrote:
> This patch adds irq_domain infrastructure for translating from
> hardware irq numbers to linux irqs.  This is particularly important
> for architectures adding device tree support because the current
> implementation (excluding PowerPC and SPARC) cannot handle
> translation for more than a single interrupt controller.  irq_domain
> supports device tree translation for any number of interrupt
> controllers.
>
> This patch converts x86, Microblaze, ARM and MIPS to use irq_domain
> for device tree irq translation.  x86 is untested beyond compiling it,
> irq_domain is enabled for MIPS and Microblaze, but the old behaviour is
> preserved until the core code is modified to actually register an
> irq_domain yet.  On ARM it works and is required for much of the new
> ARM device tree board support.

Oops, I obviously forgot to update the commit text.  This patch only
affects ARM, I've split the MIPS, Microblaze and x86 bits out into a
separate patch.  I'll craft new commit text before reposting.

g.

>
> PowerPC has /not/ been converted to use this new infrastructure.  It
> is still missing some features before it can replace the virq
> infrastructure already in powerpc (see documentation on
> irq_domain_map/unmap for details).  Followup patches will add the
> missing pieces and migrate PowerPC to use irq_domain.
>
> SPARC has its own method of managing interrupts from the device tree
> and is unaffected by this change.
>
> Acked-by: Ralf Baechle <ralf@linux-mips.org>
> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
> ---
>  arch/arm/Kconfig            |    1
>  arch/arm/include/asm/prom.h |    5 --
>  arch/arm/kernel/devtree.c   |   14 -----
>  include/linux/irq.h         |    6 ++
>  include/linux/irqdomain.h   |   81 ++++++++++++++++++++++++++++
>  include/linux/of_irq.h      |    4 +
>  kernel/irq/Kconfig          |    4 +
>  kernel/irq/Makefile         |    1
>  kernel/irq/irqdomain.c      |  123 +++++++++++++++++++++++++++++++++++++++++++
>  9 files changed, 220 insertions(+), 19 deletions(-)
>  create mode 100644 include/linux/irqdomain.h
>  create mode 100644 kernel/irq/irqdomain.c
>
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 9cb1f4b..b2695aa 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -1680,6 +1680,7 @@ config USE_OF
>        bool "Flattened Device Tree support"
>        select OF
>        select OF_EARLY_FLATTREE
> +       select IRQ_DOMAIN
>        help
>          Include support for flattened device tree machine descriptions.
>
> diff --git a/arch/arm/include/asm/prom.h b/arch/arm/include/asm/prom.h
> index 11b8708..6f65ca8 100644
> --- a/arch/arm/include/asm/prom.h
> +++ b/arch/arm/include/asm/prom.h
> @@ -16,11 +16,6 @@
>  #include <asm/setup.h>
>  #include <asm/irq.h>
>
> -static inline void irq_dispose_mapping(unsigned int virq)
> -{
> -       return;
> -}
> -
>  extern struct machine_desc *setup_machine_fdt(unsigned int dt_phys);
>  extern void arm_dt_memblock_reserve(void);
>
> diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c
> index 0cdd7b4..1a33e9d 100644
> --- a/arch/arm/kernel/devtree.c
> +++ b/arch/arm/kernel/devtree.c
> @@ -132,17 +132,3 @@ struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys)
>
>        return mdesc_best;
>  }
> -
> -/**
> - * irq_create_of_mapping - Hook to resolve OF irq specifier into a Linux irq#
> - *
> - * Currently the mapping mechanism is trivial; simple flat hwirq numbers are
> - * mapped 1:1 onto Linux irq numbers.  Cascaded irq controllers are not
> - * supported.
> - */
> -unsigned int irq_create_of_mapping(struct device_node *controller,
> -                                  const u32 *intspec, unsigned int intsize)
> -{
> -       return intspec[0];
> -}
> -EXPORT_SYMBOL_GPL(irq_create_of_mapping);
> diff --git a/include/linux/irq.h b/include/linux/irq.h
> index 5f69504..87a06f3 100644
> --- a/include/linux/irq.h
> +++ b/include/linux/irq.h
> @@ -108,14 +108,18 @@ enum {
>  };
>
>  struct msi_desc;
> +struct irq_domain;
>
>  /**
>  * struct irq_data - per irq and irq chip data passed down to chip functions
>  * @irq:               interrupt number
> + * @hwirq:             hardware interrupt number, local to the interrupt domain
>  * @node:              node index useful for balancing
>  * @state_use_accessors: status information for irq chip functions.
>  *                     Use accessor functions to deal with it
>  * @chip:              low level interrupt hardware access
> + * @domain:            Interrupt translation domain; responsible for mapping
> + *                     between hwirq number and linux irq number.
>  * @handler_data:      per-IRQ data for the irq_chip methods
>  * @chip_data:         platform-specific per-chip private data for the chip
>  *                     methods, to allow shared chip implementations
> @@ -128,9 +132,11 @@ struct msi_desc;
>  */
>  struct irq_data {
>        unsigned int            irq;
> +       unsigned long           hwirq;
>        unsigned int            node;
>        unsigned int            state_use_accessors;
>        struct irq_chip         *chip;
> +       struct irq_domain       *domain;
>        void                    *handler_data;
>        void                    *chip_data;
>        struct msi_desc         *msi_desc;
> diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
> new file mode 100644
> index 0000000..8f2c10a
> --- /dev/null
> +++ b/include/linux/irqdomain.h
> @@ -0,0 +1,81 @@
> +/*
> + * irq_domain - IRQ translation domains
> + *
> + * Translation infrastructure between hw and linux irq numbers.  This is
> + * helpful for interrupt controllers to implement mapping between hardware
> + * irq numbers and the Linux irq number space.
> + *
> + * irq_domains also have a hook for translating device tree interrupt
> + * representation into a hardware irq number that can be mapped back to a
> + * Linux irq number without any extra platform support code.
> + *
> + * irq_domain is expected to be embedded in an interrupt controller's private
> + * data structure.
> + */
> +#ifndef _LINUX_IRQDOMAIN_H
> +#define _LINUX_IRQDOMAIN_H
> +
> +#include <linux/irq.h>
> +
> +#ifdef CONFIG_IRQ_DOMAIN
> +struct device_node;
> +struct irq_domain;
> +
> +/**
> + * struct irq_domain_ops - Methods for irq_domain objects
> + * @to_irq: (optional) given a local hardware irq number, return the linux
> + *          irq number.  If to_irq is not implemented, then the irq_domain
> + *          will use this translation: irq = (domain->irq_base + hwirq)
> + * @dt_translate: Given a device tree node and interrupt specifier, decode
> + *                the hardware irq number and linux irq type value.
> + */
> +struct irq_domain_ops {
> +       unsigned int (*to_irq)(struct irq_domain *d, unsigned long hwirq);
> +
> +#ifdef CONFIG_OF
> +       int (*dt_translate)(struct irq_domain *d, struct device_node *node,
> +                           const u32 *intspec, unsigned int intsize,
> +                           unsigned long *out_hwirq, unsigned int *out_type);
> +#endif /* CONFIG_OF */
> +};
> +
> +/**
> + * struct irq_domain - Hardware interrupt number translation object
> + * @list: Element in global irq_domain list.
> + * @irq_base: Start of irq_desc range assigned to the irq_domain.  The creator
> + *            of the irq_domain is responsible for allocating the array of
> + *            irq_desc structures.
> + * @nr_irq: Number of irqs managed by the irq domain
> + * @ops: pointer to irq_domain methods
> + * @priv: private data pointer for use by owner.  Not touched by irq_domain
> + *        core code.
> + * @of_node: (optional) Pointer to device tree nodes associated with the
> + *           irq_domain.  Used when decoding device tree interrupt specifiers.
> + */
> +struct irq_domain {
> +       struct list_head list;
> +       unsigned int irq_base;
> +       unsigned int nr_irq;
> +       const struct irq_domain_ops *ops;
> +       void *priv;
> +       struct device_node *of_node;
> +};
> +
> +/**
> + * irq_domain_to_irq() - Translate from a hardware irq to a linux irq number
> + *
> + * Returns the linux irq number associated with a hardware irq.  By default,
> + * the mapping is irq == domain->irq_base + hwirq, but this mapping can
> + * be overridden if the irq_domain implements a .to_irq() hook.
> + */
> +static inline unsigned int irq_domain_to_irq(struct irq_domain *d,
> +                                            unsigned long hwirq)
> +{
> +       return d->ops->to_irq ? d->ops->to_irq(d, hwirq) : d->irq_base + hwirq;
> +}
> +
> +extern void irq_domain_add(struct irq_domain *domain);
> +extern void irq_domain_del(struct irq_domain *domain);
> +#endif /* CONFIG_IRQ_DOMAIN */
> +
> +#endif /* _LINUX_IRQDOMAIN_H */
> diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h
> index e6955f5..cd2e61c 100644
> --- a/include/linux/of_irq.h
> +++ b/include/linux/of_irq.h
> @@ -63,6 +63,9 @@ extern int of_irq_map_one(struct device_node *device, int index,
>  extern unsigned int irq_create_of_mapping(struct device_node *controller,
>                                          const u32 *intspec,
>                                          unsigned int intsize);
> +#ifdef CONFIG_IRQ_DOMAIN
> +extern void irq_dispose_mapping(unsigned int irq);
> +#endif
>  extern int of_irq_to_resource(struct device_node *dev, int index,
>                              struct resource *r);
>  extern int of_irq_count(struct device_node *dev);
> @@ -70,6 +73,7 @@ extern int of_irq_to_resource_table(struct device_node *dev,
>                struct resource *res, int nr_irqs);
>  extern struct device_node *of_irq_find_parent(struct device_node *child);
>
> +
>  #endif /* CONFIG_OF_IRQ */
>  #endif /* CONFIG_OF */
>  #endif /* __OF_IRQ_H */
> diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig
> index d1d051b3..5a38bf4 100644
> --- a/kernel/irq/Kconfig
> +++ b/kernel/irq/Kconfig
> @@ -52,6 +52,10 @@ config IRQ_EDGE_EOI_HANDLER
>  config GENERIC_IRQ_CHIP
>        bool
>
> +# Generic irq_domain hw <--> linux irq number translation
> +config IRQ_DOMAIN
> +       bool
> +
>  # Support forced irq threading
>  config IRQ_FORCED_THREADING
>        bool
> diff --git a/kernel/irq/Makefile b/kernel/irq/Makefile
> index 7329005..fff1738 100644
> --- a/kernel/irq/Makefile
> +++ b/kernel/irq/Makefile
> @@ -2,6 +2,7 @@
>  obj-y := irqdesc.o handle.o manage.o spurious.o resend.o chip.o dummychip.o devres.o
>  obj-$(CONFIG_GENERIC_IRQ_CHIP) += generic-chip.o
>  obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o
> +obj-$(CONFIG_IRQ_DOMAIN) += irqdomain.o
>  obj-$(CONFIG_PROC_FS) += proc.o
>  obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o
>  obj-$(CONFIG_PM_SLEEP) += pm.o
> diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> new file mode 100644
> index 0000000..171b754
> --- /dev/null
> +++ b/kernel/irq/irqdomain.c
> @@ -0,0 +1,123 @@
> +
> +#include <linux/irq.h>
> +#include <linux/irqdomain.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/of.h>
> +
> +static LIST_HEAD(irq_domain_list);
> +static DEFINE_MUTEX(irq_domain_mutex);
> +
> +/**
> + * irq_domain_add() - Register an irq_domain
> + * @domain: ptr to initialized irq_domain structure
> + *
> + * Registers an irq_domain structure.  The irq_domain must at a minimum be
> + * initialized with an ops structure pointer, and either a ->to_irq hook or
> + * a valid irq_base value.  Everything else is optional.
> + */
> +void irq_domain_add(struct irq_domain *domain)
> +{
> +       struct irq_data *d;
> +       int hwirq;
> +
> +       /*
> +        * This assumes that the irq_domain owner has already allocated
> +        * the irq_descs.  This block will be removed when support for dynamic
> +        * allocation of irq_descs is added to irq_domain.
> +        */
> +       for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
> +               d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
> +               if (d || d->domain) {
> +                       /* things are broken; just report, don't clean up */
> +                       WARN(1, "error: irq_desc already assigned to a domain");
> +                       return;
> +               }
> +               d->domain = domain;
> +               d->hwirq = hwirq;
> +       }
> +
> +       mutex_lock(&irq_domain_mutex);
> +       list_add(&domain->list, &irq_domain_list);
> +       mutex_unlock(&irq_domain_mutex);
> +}
> +
> +/**
> + * irq_domain_del() - Unregister an irq_domain
> + * @domain: ptr to registered irq_domain.
> + */
> +void irq_domain_del(struct irq_domain *domain)
> +{
> +       struct irq_data *d;
> +       int hwirq;
> +
> +       mutex_lock(&irq_domain_mutex);
> +       list_del(&domain->list);
> +       mutex_unlock(&irq_domain_mutex);
> +
> +       /* Clear the irq_domain assignments */
> +       for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
> +               d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
> +               d->domain = NULL;
> +       }
> +}
> +
> +#if defined(CONFIG_OF_IRQ)
> +/**
> + * irq_create_of_mapping() - Map a linux irq number from a DT interrupt spec
> + *
> + * Used by the device tree interrupt mapping code to translate a device tree
> + * interrupt specifier to a valid linux irq number.  Returns either a valid
> + * linux IRQ number or 0.
> + *
> + * When the caller no longer need the irq number returned by this function it
> + * should arrange to call irq_dispose_mapping().
> + */
> +unsigned int irq_create_of_mapping(struct device_node *controller,
> +                                  const u32 *intspec, unsigned int intsize)
> +{
> +       struct irq_domain *domain;
> +       unsigned long hwirq;
> +       unsigned int irq, type;
> +       int rc = -EINVAL;
> +
> +       /* Find a domain which can translate the irq spec */
> +       mutex_lock(&irq_domain_mutex);
> +       list_for_each_entry(domain, &irq_domain_list, list) {
> +               if (!domain->ops->dt_translate)
> +                       continue;
> +               rc = domain->ops->dt_translate(domain, controller,
> +                                       intspec, intsize, &hwirq, &type);
> +               if (rc == 0)
> +                       break;
> +       }
> +       mutex_unlock(&irq_domain_mutex);
> +
> +       if (rc != 0)
> +               return 0;
> +
> +       irq = irq_domain_to_irq(domain, hwirq);
> +       if (type != IRQ_TYPE_NONE)
> +               irq_set_irq_type(irq, type);
> +       pr_debug("%s: mapped hwirq=%i to irq=%i, flags=%x\n",
> +                controller->full_name, (int)hwirq, irq, type);
> +       return irq;
> +}
> +EXPORT_SYMBOL_GPL(irq_create_of_mapping);
> +
> +/**
> + * irq_dispose_mapping() - Discard a mapping created by irq_create_of_mapping()
> + * @irq: linux irq number to be discarded
> + *
> + * Calling this function indicates the caller no longer needs a reference to
> + * the linux irq number returned by a prior call to irq_create_of_mapping().
> + */
> +void irq_dispose_mapping(unsigned int irq)
> +{
> +       /*
> +        * nothing yet; will be filled when support for dynamic allocation of
> +        * irq_descs is added to irq_domain
> +        */
> +}
> +EXPORT_SYMBOL_GPL(irq_dispose_mapping);
> +#endif /* CONFIG_OF_IRQ */
>
>



-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v3 1/2] irq: add irq_domain translation infrastructure
@ 2011-07-26  9:40     ` Grant Likely
  0 siblings, 0 replies; 10+ messages in thread
From: Grant Likely @ 2011-07-26  9:40 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jul 26, 2011 at 3:36 AM, Grant Likely <grant.likely@secretlab.ca> wrote:
> This patch adds irq_domain infrastructure for translating from
> hardware irq numbers to linux irqs. ?This is particularly important
> for architectures adding device tree support because the current
> implementation (excluding PowerPC and SPARC) cannot handle
> translation for more than a single interrupt controller. ?irq_domain
> supports device tree translation for any number of interrupt
> controllers.
>
> This patch converts x86, Microblaze, ARM and MIPS to use irq_domain
> for device tree irq translation. ?x86 is untested beyond compiling it,
> irq_domain is enabled for MIPS and Microblaze, but the old behaviour is
> preserved until the core code is modified to actually register an
> irq_domain yet. ?On ARM it works and is required for much of the new
> ARM device tree board support.

Oops, I obviously forgot to update the commit text.  This patch only
affects ARM, I've split the MIPS, Microblaze and x86 bits out into a
separate patch.  I'll craft new commit text before reposting.

g.

>
> PowerPC has /not/ been converted to use this new infrastructure. ?It
> is still missing some features before it can replace the virq
> infrastructure already in powerpc (see documentation on
> irq_domain_map/unmap for details). ?Followup patches will add the
> missing pieces and migrate PowerPC to use irq_domain.
>
> SPARC has its own method of managing interrupts from the device tree
> and is unaffected by this change.
>
> Acked-by: Ralf Baechle <ralf@linux-mips.org>
> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
> ---
> ?arch/arm/Kconfig ? ? ? ? ? ?| ? ?1
> ?arch/arm/include/asm/prom.h | ? ?5 --
> ?arch/arm/kernel/devtree.c ? | ? 14 -----
> ?include/linux/irq.h ? ? ? ? | ? ?6 ++
> ?include/linux/irqdomain.h ? | ? 81 ++++++++++++++++++++++++++++
> ?include/linux/of_irq.h ? ? ?| ? ?4 +
> ?kernel/irq/Kconfig ? ? ? ? ?| ? ?4 +
> ?kernel/irq/Makefile ? ? ? ? | ? ?1
> ?kernel/irq/irqdomain.c ? ? ?| ?123 +++++++++++++++++++++++++++++++++++++++++++
> ?9 files changed, 220 insertions(+), 19 deletions(-)
> ?create mode 100644 include/linux/irqdomain.h
> ?create mode 100644 kernel/irq/irqdomain.c
>
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 9cb1f4b..b2695aa 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -1680,6 +1680,7 @@ config USE_OF
> ? ? ? ?bool "Flattened Device Tree support"
> ? ? ? ?select OF
> ? ? ? ?select OF_EARLY_FLATTREE
> + ? ? ? select IRQ_DOMAIN
> ? ? ? ?help
> ? ? ? ? ?Include support for flattened device tree machine descriptions.
>
> diff --git a/arch/arm/include/asm/prom.h b/arch/arm/include/asm/prom.h
> index 11b8708..6f65ca8 100644
> --- a/arch/arm/include/asm/prom.h
> +++ b/arch/arm/include/asm/prom.h
> @@ -16,11 +16,6 @@
> ?#include <asm/setup.h>
> ?#include <asm/irq.h>
>
> -static inline void irq_dispose_mapping(unsigned int virq)
> -{
> - ? ? ? return;
> -}
> -
> ?extern struct machine_desc *setup_machine_fdt(unsigned int dt_phys);
> ?extern void arm_dt_memblock_reserve(void);
>
> diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c
> index 0cdd7b4..1a33e9d 100644
> --- a/arch/arm/kernel/devtree.c
> +++ b/arch/arm/kernel/devtree.c
> @@ -132,17 +132,3 @@ struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys)
>
> ? ? ? ?return mdesc_best;
> ?}
> -
> -/**
> - * irq_create_of_mapping - Hook to resolve OF irq specifier into a Linux irq#
> - *
> - * Currently the mapping mechanism is trivial; simple flat hwirq numbers are
> - * mapped 1:1 onto Linux irq numbers. ?Cascaded irq controllers are not
> - * supported.
> - */
> -unsigned int irq_create_of_mapping(struct device_node *controller,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?const u32 *intspec, unsigned int intsize)
> -{
> - ? ? ? return intspec[0];
> -}
> -EXPORT_SYMBOL_GPL(irq_create_of_mapping);
> diff --git a/include/linux/irq.h b/include/linux/irq.h
> index 5f69504..87a06f3 100644
> --- a/include/linux/irq.h
> +++ b/include/linux/irq.h
> @@ -108,14 +108,18 @@ enum {
> ?};
>
> ?struct msi_desc;
> +struct irq_domain;
>
> ?/**
> ?* struct irq_data - per irq and irq chip data passed down to chip functions
> ?* @irq: ? ? ? ? ? ? ? interrupt number
> + * @hwirq: ? ? ? ? ? ? hardware interrupt number, local to the interrupt domain
> ?* @node: ? ? ? ? ? ? ?node index useful for balancing
> ?* @state_use_accessors: status information for irq chip functions.
> ?* ? ? ? ? ? ? ? ? ? ? Use accessor functions to deal with it
> ?* @chip: ? ? ? ? ? ? ?low level interrupt hardware access
> + * @domain: ? ? ? ? ? ?Interrupt translation domain; responsible for mapping
> + * ? ? ? ? ? ? ? ? ? ? between hwirq number and linux irq number.
> ?* @handler_data: ? ? ?per-IRQ data for the irq_chip methods
> ?* @chip_data: ? ? ? ? platform-specific per-chip private data for the chip
> ?* ? ? ? ? ? ? ? ? ? ? methods, to allow shared chip implementations
> @@ -128,9 +132,11 @@ struct msi_desc;
> ?*/
> ?struct irq_data {
> ? ? ? ?unsigned int ? ? ? ? ? ?irq;
> + ? ? ? unsigned long ? ? ? ? ? hwirq;
> ? ? ? ?unsigned int ? ? ? ? ? ?node;
> ? ? ? ?unsigned int ? ? ? ? ? ?state_use_accessors;
> ? ? ? ?struct irq_chip ? ? ? ? *chip;
> + ? ? ? struct irq_domain ? ? ? *domain;
> ? ? ? ?void ? ? ? ? ? ? ? ? ? ?*handler_data;
> ? ? ? ?void ? ? ? ? ? ? ? ? ? ?*chip_data;
> ? ? ? ?struct msi_desc ? ? ? ? *msi_desc;
> diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
> new file mode 100644
> index 0000000..8f2c10a
> --- /dev/null
> +++ b/include/linux/irqdomain.h
> @@ -0,0 +1,81 @@
> +/*
> + * irq_domain - IRQ translation domains
> + *
> + * Translation infrastructure between hw and linux irq numbers. ?This is
> + * helpful for interrupt controllers to implement mapping between hardware
> + * irq numbers and the Linux irq number space.
> + *
> + * irq_domains also have a hook for translating device tree interrupt
> + * representation into a hardware irq number that can be mapped back to a
> + * Linux irq number without any extra platform support code.
> + *
> + * irq_domain is expected to be embedded in an interrupt controller's private
> + * data structure.
> + */
> +#ifndef _LINUX_IRQDOMAIN_H
> +#define _LINUX_IRQDOMAIN_H
> +
> +#include <linux/irq.h>
> +
> +#ifdef CONFIG_IRQ_DOMAIN
> +struct device_node;
> +struct irq_domain;
> +
> +/**
> + * struct irq_domain_ops - Methods for irq_domain objects
> + * @to_irq: (optional) given a local hardware irq number, return the linux
> + * ? ? ? ? ?irq number. ?If to_irq is not implemented, then the irq_domain
> + * ? ? ? ? ?will use this translation: irq = (domain->irq_base + hwirq)
> + * @dt_translate: Given a device tree node and interrupt specifier, decode
> + * ? ? ? ? ? ? ? ?the hardware irq number and linux irq type value.
> + */
> +struct irq_domain_ops {
> + ? ? ? unsigned int (*to_irq)(struct irq_domain *d, unsigned long hwirq);
> +
> +#ifdef CONFIG_OF
> + ? ? ? int (*dt_translate)(struct irq_domain *d, struct device_node *node,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? const u32 *intspec, unsigned int intsize,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? unsigned long *out_hwirq, unsigned int *out_type);
> +#endif /* CONFIG_OF */
> +};
> +
> +/**
> + * struct irq_domain - Hardware interrupt number translation object
> + * @list: Element in global irq_domain list.
> + * @irq_base: Start of irq_desc range assigned to the irq_domain. ?The creator
> + * ? ? ? ? ? ?of the irq_domain is responsible for allocating the array of
> + * ? ? ? ? ? ?irq_desc structures.
> + * @nr_irq: Number of irqs managed by the irq domain
> + * @ops: pointer to irq_domain methods
> + * @priv: private data pointer for use by owner. ?Not touched by irq_domain
> + * ? ? ? ?core code.
> + * @of_node: (optional) Pointer to device tree nodes associated with the
> + * ? ? ? ? ? irq_domain. ?Used when decoding device tree interrupt specifiers.
> + */
> +struct irq_domain {
> + ? ? ? struct list_head list;
> + ? ? ? unsigned int irq_base;
> + ? ? ? unsigned int nr_irq;
> + ? ? ? const struct irq_domain_ops *ops;
> + ? ? ? void *priv;
> + ? ? ? struct device_node *of_node;
> +};
> +
> +/**
> + * irq_domain_to_irq() - Translate from a hardware irq to a linux irq number
> + *
> + * Returns the linux irq number associated with a hardware irq. ?By default,
> + * the mapping is irq == domain->irq_base + hwirq, but this mapping can
> + * be overridden if the irq_domain implements a .to_irq() hook.
> + */
> +static inline unsigned int irq_domain_to_irq(struct irq_domain *d,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?unsigned long hwirq)
> +{
> + ? ? ? return d->ops->to_irq ? d->ops->to_irq(d, hwirq) : d->irq_base + hwirq;
> +}
> +
> +extern void irq_domain_add(struct irq_domain *domain);
> +extern void irq_domain_del(struct irq_domain *domain);
> +#endif /* CONFIG_IRQ_DOMAIN */
> +
> +#endif /* _LINUX_IRQDOMAIN_H */
> diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h
> index e6955f5..cd2e61c 100644
> --- a/include/linux/of_irq.h
> +++ b/include/linux/of_irq.h
> @@ -63,6 +63,9 @@ extern int of_irq_map_one(struct device_node *device, int index,
> ?extern unsigned int irq_create_of_mapping(struct device_node *controller,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?const u32 *intspec,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?unsigned int intsize);
> +#ifdef CONFIG_IRQ_DOMAIN
> +extern void irq_dispose_mapping(unsigned int irq);
> +#endif
> ?extern int of_irq_to_resource(struct device_node *dev, int index,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct resource *r);
> ?extern int of_irq_count(struct device_node *dev);
> @@ -70,6 +73,7 @@ extern int of_irq_to_resource_table(struct device_node *dev,
> ? ? ? ? ? ? ? ?struct resource *res, int nr_irqs);
> ?extern struct device_node *of_irq_find_parent(struct device_node *child);
>
> +
> ?#endif /* CONFIG_OF_IRQ */
> ?#endif /* CONFIG_OF */
> ?#endif /* __OF_IRQ_H */
> diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig
> index d1d051b3..5a38bf4 100644
> --- a/kernel/irq/Kconfig
> +++ b/kernel/irq/Kconfig
> @@ -52,6 +52,10 @@ config IRQ_EDGE_EOI_HANDLER
> ?config GENERIC_IRQ_CHIP
> ? ? ? ?bool
>
> +# Generic irq_domain hw <--> linux irq number translation
> +config IRQ_DOMAIN
> + ? ? ? bool
> +
> ?# Support forced irq threading
> ?config IRQ_FORCED_THREADING
> ? ? ? ?bool
> diff --git a/kernel/irq/Makefile b/kernel/irq/Makefile
> index 7329005..fff1738 100644
> --- a/kernel/irq/Makefile
> +++ b/kernel/irq/Makefile
> @@ -2,6 +2,7 @@
> ?obj-y := irqdesc.o handle.o manage.o spurious.o resend.o chip.o dummychip.o devres.o
> ?obj-$(CONFIG_GENERIC_IRQ_CHIP) += generic-chip.o
> ?obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o
> +obj-$(CONFIG_IRQ_DOMAIN) += irqdomain.o
> ?obj-$(CONFIG_PROC_FS) += proc.o
> ?obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o
> ?obj-$(CONFIG_PM_SLEEP) += pm.o
> diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> new file mode 100644
> index 0000000..171b754
> --- /dev/null
> +++ b/kernel/irq/irqdomain.c
> @@ -0,0 +1,123 @@
> +
> +#include <linux/irq.h>
> +#include <linux/irqdomain.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/of.h>
> +
> +static LIST_HEAD(irq_domain_list);
> +static DEFINE_MUTEX(irq_domain_mutex);
> +
> +/**
> + * irq_domain_add() - Register an irq_domain
> + * @domain: ptr to initialized irq_domain structure
> + *
> + * Registers an irq_domain structure. ?The irq_domain must at a minimum be
> + * initialized with an ops structure pointer, and either a ->to_irq hook or
> + * a valid irq_base value. ?Everything else is optional.
> + */
> +void irq_domain_add(struct irq_domain *domain)
> +{
> + ? ? ? struct irq_data *d;
> + ? ? ? int hwirq;
> +
> + ? ? ? /*
> + ? ? ? ?* This assumes that the irq_domain owner has already allocated
> + ? ? ? ?* the irq_descs. ?This block will be removed when support for dynamic
> + ? ? ? ?* allocation of irq_descs is added to irq_domain.
> + ? ? ? ?*/
> + ? ? ? for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
> + ? ? ? ? ? ? ? d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
> + ? ? ? ? ? ? ? if (d || d->domain) {
> + ? ? ? ? ? ? ? ? ? ? ? /* things are broken; just report, don't clean up */
> + ? ? ? ? ? ? ? ? ? ? ? WARN(1, "error: irq_desc already assigned to a domain");
> + ? ? ? ? ? ? ? ? ? ? ? return;
> + ? ? ? ? ? ? ? }
> + ? ? ? ? ? ? ? d->domain = domain;
> + ? ? ? ? ? ? ? d->hwirq = hwirq;
> + ? ? ? }
> +
> + ? ? ? mutex_lock(&irq_domain_mutex);
> + ? ? ? list_add(&domain->list, &irq_domain_list);
> + ? ? ? mutex_unlock(&irq_domain_mutex);
> +}
> +
> +/**
> + * irq_domain_del() - Unregister an irq_domain
> + * @domain: ptr to registered irq_domain.
> + */
> +void irq_domain_del(struct irq_domain *domain)
> +{
> + ? ? ? struct irq_data *d;
> + ? ? ? int hwirq;
> +
> + ? ? ? mutex_lock(&irq_domain_mutex);
> + ? ? ? list_del(&domain->list);
> + ? ? ? mutex_unlock(&irq_domain_mutex);
> +
> + ? ? ? /* Clear the irq_domain assignments */
> + ? ? ? for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {
> + ? ? ? ? ? ? ? d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));
> + ? ? ? ? ? ? ? d->domain = NULL;
> + ? ? ? }
> +}
> +
> +#if defined(CONFIG_OF_IRQ)
> +/**
> + * irq_create_of_mapping() - Map a linux irq number from a DT interrupt spec
> + *
> + * Used by the device tree interrupt mapping code to translate a device tree
> + * interrupt specifier to a valid linux irq number. ?Returns either a valid
> + * linux IRQ number or 0.
> + *
> + * When the caller no longer need the irq number returned by this function it
> + * should arrange to call irq_dispose_mapping().
> + */
> +unsigned int irq_create_of_mapping(struct device_node *controller,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?const u32 *intspec, unsigned int intsize)
> +{
> + ? ? ? struct irq_domain *domain;
> + ? ? ? unsigned long hwirq;
> + ? ? ? unsigned int irq, type;
> + ? ? ? int rc = -EINVAL;
> +
> + ? ? ? /* Find a domain which can translate the irq spec */
> + ? ? ? mutex_lock(&irq_domain_mutex);
> + ? ? ? list_for_each_entry(domain, &irq_domain_list, list) {
> + ? ? ? ? ? ? ? if (!domain->ops->dt_translate)
> + ? ? ? ? ? ? ? ? ? ? ? continue;
> + ? ? ? ? ? ? ? rc = domain->ops->dt_translate(domain, controller,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? intspec, intsize, &hwirq, &type);
> + ? ? ? ? ? ? ? if (rc == 0)
> + ? ? ? ? ? ? ? ? ? ? ? break;
> + ? ? ? }
> + ? ? ? mutex_unlock(&irq_domain_mutex);
> +
> + ? ? ? if (rc != 0)
> + ? ? ? ? ? ? ? return 0;
> +
> + ? ? ? irq = irq_domain_to_irq(domain, hwirq);
> + ? ? ? if (type != IRQ_TYPE_NONE)
> + ? ? ? ? ? ? ? irq_set_irq_type(irq, type);
> + ? ? ? pr_debug("%s: mapped hwirq=%i to irq=%i, flags=%x\n",
> + ? ? ? ? ? ? ? ?controller->full_name, (int)hwirq, irq, type);
> + ? ? ? return irq;
> +}
> +EXPORT_SYMBOL_GPL(irq_create_of_mapping);
> +
> +/**
> + * irq_dispose_mapping() - Discard a mapping created by irq_create_of_mapping()
> + * @irq: linux irq number to be discarded
> + *
> + * Calling this function indicates the caller no longer needs a reference to
> + * the linux irq number returned by a prior call to irq_create_of_mapping().
> + */
> +void irq_dispose_mapping(unsigned int irq)
> +{
> + ? ? ? /*
> + ? ? ? ?* nothing yet; will be filled when support for dynamic allocation of
> + ? ? ? ?* irq_descs is added to irq_domain
> + ? ? ? ?*/
> +}
> +EXPORT_SYMBOL_GPL(irq_dispose_mapping);
> +#endif /* CONFIG_OF_IRQ */
>
>



-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v3 0/2] Simple irq_domain implementation
  2011-07-26  9:36 [PATCH v3 0/2] Simple irq_domain implementation Grant Likely
  2011-07-26  9:36   ` Grant Likely
  2011-07-26  9:36   ` Grant Likely
@ 2011-07-28  9:31 ` Thomas Gleixner
  2011-07-28 22:20     ` Grant Likely
  2 siblings, 1 reply; 10+ messages in thread
From: Thomas Gleixner @ 2011-07-28  9:31 UTC (permalink / raw)
  To: Grant Likely; +Cc: devicetree-discuss, Russell King, LKML, Sebastian Sewior

On Tue, 26 Jul 2011, Grant Likely wrote:

> In the interest of getting this infrastructure merged, I've reworked the
> basic irq_domain patch to implement only what is required for ARM device
> tree board support.  That means it doesn't affect any architectures other
> than ARM, and I'll send follow-on patches targeted at v3.2 to migrate
> MIPS, Microblaze, x86 embedded and PowerPC over to it.

There is also this GPIO driver pending for quite some time ...
 
> Thomas, can you please take a look?  I've got devicetree board support
> queued up and ready to be merged but for this infrastructure.

Looks reasonable, please merge them through your tree.

Reviewed-by: Thomas Gleixner <tglx@linutronix.de>

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v3 0/2] Simple irq_domain implementation
  2011-07-28  9:31 ` [PATCH v3 0/2] Simple irq_domain implementation Thomas Gleixner
@ 2011-07-28 22:20     ` Grant Likely
  0 siblings, 0 replies; 10+ messages in thread
From: Grant Likely @ 2011-07-28 22:20 UTC (permalink / raw)
  To: Thomas Gleixner; +Cc: devicetree-discuss, Russell King, LKML, Sebastian Sewior

On Thu, Jul 28, 2011 at 11:31:03AM +0200, Thomas Gleixner wrote:
> On Tue, 26 Jul 2011, Grant Likely wrote:
> 
> > In the interest of getting this infrastructure merged, I've reworked the
> > basic irq_domain patch to implement only what is required for ARM device
> > tree board support.  That means it doesn't affect any architectures other
> > than ARM, and I'll send follow-on patches targeted at v3.2 to migrate
> > MIPS, Microblaze, x86 embedded and PowerPC over to it.
> 
> There is also this GPIO driver pending for quite some time ...
>  
> > Thomas, can you please take a look?  I've got devicetree board support
> > queued up and ready to be merged but for this infrastructure.
> 
> Looks reasonable, please merge them through your tree.
> 
> Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
> 
> Thanks,
> 
> 	tglx

Thanks Thomas.  Arnd has sent it as part of his DT board support pull
req to Linus.

g.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v3 0/2] Simple irq_domain implementation
@ 2011-07-28 22:20     ` Grant Likely
  0 siblings, 0 replies; 10+ messages in thread
From: Grant Likely @ 2011-07-28 22:20 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Russell King, LKML,
	Sebastian Sewior

On Thu, Jul 28, 2011 at 11:31:03AM +0200, Thomas Gleixner wrote:
> On Tue, 26 Jul 2011, Grant Likely wrote:
> 
> > In the interest of getting this infrastructure merged, I've reworked the
> > basic irq_domain patch to implement only what is required for ARM device
> > tree board support.  That means it doesn't affect any architectures other
> > than ARM, and I'll send follow-on patches targeted at v3.2 to migrate
> > MIPS, Microblaze, x86 embedded and PowerPC over to it.
> 
> There is also this GPIO driver pending for quite some time ...
>  
> > Thomas, can you please take a look?  I've got devicetree board support
> > queued up and ready to be merged but for this infrastructure.
> 
> Looks reasonable, please merge them through your tree.
> 
> Reviewed-by: Thomas Gleixner <tglx-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
> 
> Thanks,
> 
> 	tglx

Thanks Thomas.  Arnd has sent it as part of his DT board support pull
req to Linus.

g.

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2011-07-28 22:20 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-26  9:36 [PATCH v3 0/2] Simple irq_domain implementation Grant Likely
2011-07-26  9:36 ` [PATCH v3 1/2] irq: add irq_domain translation infrastructure Grant Likely
2011-07-26  9:36   ` Grant Likely
2011-07-26  9:40   ` Grant Likely
2011-07-26  9:40     ` Grant Likely
2011-07-26  9:36 ` [PATCH v3 2/2] dt/irq: add irq_domain_generate_simple() helper Grant Likely
2011-07-26  9:36   ` Grant Likely
2011-07-28  9:31 ` [PATCH v3 0/2] Simple irq_domain implementation Thomas Gleixner
2011-07-28 22:20   ` Grant Likely
2011-07-28 22:20     ` Grant Likely

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.