| From 3105f044552138b2b05fa35fd4af2290997dfcb1 Mon Sep 17 00:00:00 2001 |
| From: Grant Likely <grant.likely@secretlab.ca> |
| Date: Tue, 26 Jul 2011 03:19:06 -0600 |
| Subject: dt/irq: add irq_domain_generate_simple() helper |
| |
| 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> |
| (cherry picked from commit 7e71330169d8056536b299290544980bccc6b300) |
| |
| Signed-off-by: Simon Horman <horms@verge.net.au> |
| --- |
| include/linux/irqdomain.h | 10 ++++++++ |
| kernel/irq/irqdomain.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++ |
| 2 files changed, 68 insertions(+) |
| |
| diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h |
| index 8f2c10a..e807ad6 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; |
| @@ -78,4 +79,13 @@ extern void irq_domain_add(struct irq_domain *domain); |
| extern void irq_domain_del(struct irq_domain *domain); |
| #endif /* CONFIG_IRQ_DOMAIN */ |
| |
| +#if defined(CONFIG_IRQ_DOMAIN) && defined(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_IRQ_DOMAIN && 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_IRQ_DOMAIN && CONFIG_OF_IRQ */ |
| + |
| #endif /* _LINUX_IRQDOMAIN_H */ |
| diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c |
| index 29c7bd4..d5828da 100644 |
| --- a/kernel/irq/irqdomain.c |
| +++ b/kernel/irq/irqdomain.c |
| @@ -3,6 +3,8 @@ |
| #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); |
| @@ -119,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 */ |
| -- |
| 1.7.10.2.565.gbd578b5 |
| |