diff options
author | Grant Likely <grant.likely@secretlab.ca> | 2011-07-26 05:19:06 -0400 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2011-07-28 03:32:04 -0400 |
commit | 7e71330169d8056536b299290544980bccc6b300 (patch) | |
tree | 7dab4954a7683e35bbf66adadd89b26971960311 | |
parent | 08a543ad33fc188650801bd36eed4ffe272643e1 (diff) |
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>
-rw-r--r-- | include/linux/irqdomain.h | 10 | ||||
-rw-r--r-- | kernel/irq/irqdomain.c | 58 |
2 files changed, 68 insertions, 0 deletions
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index 8f2c10a784a4..e807ad687a07 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h | |||
@@ -16,6 +16,7 @@ | |||
16 | #define _LINUX_IRQDOMAIN_H | 16 | #define _LINUX_IRQDOMAIN_H |
17 | 17 | ||
18 | #include <linux/irq.h> | 18 | #include <linux/irq.h> |
19 | #include <linux/mod_devicetable.h> | ||
19 | 20 | ||
20 | #ifdef CONFIG_IRQ_DOMAIN | 21 | #ifdef CONFIG_IRQ_DOMAIN |
21 | struct device_node; | 22 | struct device_node; |
@@ -78,4 +79,13 @@ extern void irq_domain_add(struct irq_domain *domain); | |||
78 | extern void irq_domain_del(struct irq_domain *domain); | 79 | extern void irq_domain_del(struct irq_domain *domain); |
79 | #endif /* CONFIG_IRQ_DOMAIN */ | 80 | #endif /* CONFIG_IRQ_DOMAIN */ |
80 | 81 | ||
82 | #if defined(CONFIG_IRQ_DOMAIN) && defined(CONFIG_OF_IRQ) | ||
83 | extern void irq_domain_add_simple(struct device_node *controller, int irq_base); | ||
84 | extern void irq_domain_generate_simple(const struct of_device_id *match, | ||
85 | u64 phys_base, unsigned int irq_start); | ||
86 | #else /* CONFIG_IRQ_DOMAIN && CONFIG_OF_IRQ */ | ||
87 | static inline void irq_domain_generate_simple(const struct of_device_id *match, | ||
88 | u64 phys_base, unsigned int irq_start) { } | ||
89 | #endif /* CONFIG_IRQ_DOMAIN && CONFIG_OF_IRQ */ | ||
90 | |||
81 | #endif /* _LINUX_IRQDOMAIN_H */ | 91 | #endif /* _LINUX_IRQDOMAIN_H */ |
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 29c7bd42e25d..d5828da3fd38 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c | |||
@@ -3,6 +3,8 @@ | |||
3 | #include <linux/module.h> | 3 | #include <linux/module.h> |
4 | #include <linux/mutex.h> | 4 | #include <linux/mutex.h> |
5 | #include <linux/of.h> | 5 | #include <linux/of.h> |
6 | #include <linux/of_address.h> | ||
7 | #include <linux/slab.h> | ||
6 | 8 | ||
7 | static LIST_HEAD(irq_domain_list); | 9 | static LIST_HEAD(irq_domain_list); |
8 | static DEFINE_MUTEX(irq_domain_mutex); | 10 | static DEFINE_MUTEX(irq_domain_mutex); |
@@ -119,4 +121,60 @@ void irq_dispose_mapping(unsigned int irq) | |||
119 | */ | 121 | */ |
120 | } | 122 | } |
121 | EXPORT_SYMBOL_GPL(irq_dispose_mapping); | 123 | EXPORT_SYMBOL_GPL(irq_dispose_mapping); |
124 | |||
125 | int irq_domain_simple_dt_translate(struct irq_domain *d, | ||
126 | struct device_node *controller, | ||
127 | const u32 *intspec, unsigned int intsize, | ||
128 | unsigned long *out_hwirq, unsigned int *out_type) | ||
129 | { | ||
130 | if (d->of_node != controller) | ||
131 | return -EINVAL; | ||
132 | if (intsize < 1) | ||
133 | return -EINVAL; | ||
134 | |||
135 | *out_hwirq = intspec[0]; | ||
136 | *out_type = IRQ_TYPE_NONE; | ||
137 | if (intsize > 1) | ||
138 | *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK; | ||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | struct irq_domain_ops irq_domain_simple_ops = { | ||
143 | .dt_translate = irq_domain_simple_dt_translate, | ||
144 | }; | ||
145 | EXPORT_SYMBOL_GPL(irq_domain_simple_ops); | ||
146 | |||
147 | /** | ||
148 | * irq_domain_create_simple() - Set up a 'simple' translation range | ||
149 | */ | ||
150 | void irq_domain_add_simple(struct device_node *controller, int irq_base) | ||
151 | { | ||
152 | struct irq_domain *domain; | ||
153 | |||
154 | domain = kzalloc(sizeof(*domain), GFP_KERNEL); | ||
155 | if (!domain) { | ||
156 | WARN_ON(1); | ||
157 | return; | ||
158 | } | ||
159 | |||
160 | domain->irq_base = irq_base; | ||
161 | domain->of_node = of_node_get(controller); | ||
162 | domain->ops = &irq_domain_simple_ops; | ||
163 | irq_domain_add(domain); | ||
164 | } | ||
165 | EXPORT_SYMBOL_GPL(irq_domain_add_simple); | ||
166 | |||
167 | void irq_domain_generate_simple(const struct of_device_id *match, | ||
168 | u64 phys_base, unsigned int irq_start) | ||
169 | { | ||
170 | struct device_node *node; | ||
171 | pr_info("looking for phys_base=%llx, irq_start=%i\n", | ||
172 | (unsigned long long) phys_base, (int) irq_start); | ||
173 | node = of_find_matching_node_by_address(NULL, match, phys_base); | ||
174 | if (node) | ||
175 | irq_domain_add_simple(node, irq_start); | ||
176 | else | ||
177 | pr_info("no node found\n"); | ||
178 | } | ||
179 | EXPORT_SYMBOL_GPL(irq_domain_generate_simple); | ||
122 | #endif /* CONFIG_OF_IRQ */ | 180 | #endif /* CONFIG_OF_IRQ */ |