summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/linux/irq.h6
-rw-r--r--include/linux/irqdomain.h81
-rw-r--r--include/linux/of_irq.h4
3 files changed, 91 insertions, 0 deletions
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 5f695041090..87a06f345bd 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 00000000000..8f2c10a784a
--- /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 e6955f5d1f0..cd2e61ce4e8 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 */