Commit 7e71330169d8056536b299290544980bccc6b300
1 parent
08a543ad33
Exists in
master
and in
4 other branches
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>
Showing 2 changed files with 68 additions and 0 deletions Side-by-side Diff
include/linux/irqdomain.h
... | ... | @@ -16,6 +16,7 @@ |
16 | 16 | #define _LINUX_IRQDOMAIN_H |
17 | 17 | |
18 | 18 | #include <linux/irq.h> |
19 | +#include <linux/mod_devicetable.h> | |
19 | 20 | |
20 | 21 | #ifdef CONFIG_IRQ_DOMAIN |
21 | 22 | struct device_node; |
... | ... | @@ -77,6 +78,15 @@ |
77 | 78 | extern void irq_domain_add(struct irq_domain *domain); |
78 | 79 | extern void irq_domain_del(struct irq_domain *domain); |
79 | 80 | #endif /* CONFIG_IRQ_DOMAIN */ |
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 */ | |
80 | 90 | |
81 | 91 | #endif /* _LINUX_IRQDOMAIN_H */ |
kernel/irq/irqdomain.c
... | ... | @@ -3,6 +3,8 @@ |
3 | 3 | #include <linux/module.h> |
4 | 4 | #include <linux/mutex.h> |
5 | 5 | #include <linux/of.h> |
6 | +#include <linux/of_address.h> | |
7 | +#include <linux/slab.h> | |
6 | 8 | |
7 | 9 | static LIST_HEAD(irq_domain_list); |
8 | 10 | static DEFINE_MUTEX(irq_domain_mutex); |
... | ... | @@ -119,5 +121,61 @@ |
119 | 121 | */ |
120 | 122 | } |
121 | 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 | 180 | #endif /* CONFIG_OF_IRQ */ |