1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32#ifndef _LINUX_IRQDOMAIN_H
33#define _LINUX_IRQDOMAIN_H
34
35#include <linux/types.h>
36#include <linux/irqhandler.h>
37#include <linux/radix-tree.h>
38
39struct device_node;
40struct irq_domain;
41struct of_device_id;
42struct irq_chip;
43struct irq_data;
44
45
46#define NUM_ISA_INTERRUPTS 16
47
48
49
50
51
52
53
54
55enum irq_domain_bus_token {
56 DOMAIN_BUS_ANY = 0,
57 DOMAIN_BUS_PCI_MSI,
58 DOMAIN_BUS_PLATFORM_MSI,
59 DOMAIN_BUS_NEXUS,
60};
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77struct irq_domain_ops {
78 int (*match)(struct irq_domain *d, struct device_node *node,
79 enum irq_domain_bus_token bus_token);
80 int (*map)(struct irq_domain *d, unsigned int virq, irq_hw_number_t hw);
81 void (*unmap)(struct irq_domain *d, unsigned int virq);
82 int (*xlate)(struct irq_domain *d, struct device_node *node,
83 const u32 *intspec, unsigned int intsize,
84 unsigned long *out_hwirq, unsigned int *out_type);
85
86#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
87
88 int (*alloc)(struct irq_domain *d, unsigned int virq,
89 unsigned int nr_irqs, void *arg);
90 void (*free)(struct irq_domain *d, unsigned int virq,
91 unsigned int nr_irqs);
92 void (*activate)(struct irq_domain *d, struct irq_data *irq_data);
93 void (*deactivate)(struct irq_domain *d, struct irq_data *irq_data);
94#endif
95};
96
97extern struct irq_domain_ops irq_generic_chip_ops;
98
99struct irq_domain_chip_generic;
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125struct irq_domain {
126 struct list_head link;
127 const char *name;
128 const struct irq_domain_ops *ops;
129 void *host_data;
130 unsigned int flags;
131
132
133 struct device_node *of_node;
134 enum irq_domain_bus_token bus_token;
135 struct irq_domain_chip_generic *gc;
136#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
137 struct irq_domain *parent;
138#endif
139
140
141 irq_hw_number_t hwirq_max;
142 unsigned int revmap_direct_max_irq;
143 unsigned int revmap_size;
144 struct radix_tree_root revmap_tree;
145 unsigned int linear_revmap[];
146};
147
148
149enum {
150
151 IRQ_DOMAIN_FLAG_HIERARCHY = (1 << 0),
152
153
154 IRQ_DOMAIN_FLAG_AUTO_RECURSIVE = (1 << 1),
155
156
157
158
159
160
161 IRQ_DOMAIN_FLAG_NONCORE = (1 << 16),
162};
163
164static inline struct device_node *irq_domain_get_of_node(struct irq_domain *d)
165{
166 return d->of_node;
167}
168
169#ifdef CONFIG_IRQ_DOMAIN
170struct irq_domain *__irq_domain_add(struct device_node *of_node, int size,
171 irq_hw_number_t hwirq_max, int direct_max,
172 const struct irq_domain_ops *ops,
173 void *host_data);
174struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
175 unsigned int size,
176 unsigned int first_irq,
177 const struct irq_domain_ops *ops,
178 void *host_data);
179struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
180 unsigned int size,
181 unsigned int first_irq,
182 irq_hw_number_t first_hwirq,
183 const struct irq_domain_ops *ops,
184 void *host_data);
185extern struct irq_domain *irq_find_matching_host(struct device_node *node,
186 enum irq_domain_bus_token bus_token);
187extern void irq_set_default_host(struct irq_domain *host);
188
189static inline struct irq_domain *irq_find_host(struct device_node *node)
190{
191 return irq_find_matching_host(node, DOMAIN_BUS_ANY);
192}
193
194
195
196
197
198
199
200
201static inline struct irq_domain *irq_domain_add_linear(struct device_node *of_node,
202 unsigned int size,
203 const struct irq_domain_ops *ops,
204 void *host_data)
205{
206 return __irq_domain_add(of_node, size, size, 0, ops, host_data);
207}
208static inline struct irq_domain *irq_domain_add_nomap(struct device_node *of_node,
209 unsigned int max_irq,
210 const struct irq_domain_ops *ops,
211 void *host_data)
212{
213 return __irq_domain_add(of_node, 0, max_irq, max_irq, ops, host_data);
214}
215static inline struct irq_domain *irq_domain_add_legacy_isa(
216 struct device_node *of_node,
217 const struct irq_domain_ops *ops,
218 void *host_data)
219{
220 return irq_domain_add_legacy(of_node, NUM_ISA_INTERRUPTS, 0, 0, ops,
221 host_data);
222}
223static inline struct irq_domain *irq_domain_add_tree(struct device_node *of_node,
224 const struct irq_domain_ops *ops,
225 void *host_data)
226{
227 return __irq_domain_add(of_node, 0, ~0, 0, ops, host_data);
228}
229
230extern void irq_domain_remove(struct irq_domain *host);
231
232extern int irq_domain_associate(struct irq_domain *domain, unsigned int irq,
233 irq_hw_number_t hwirq);
234extern void irq_domain_associate_many(struct irq_domain *domain,
235 unsigned int irq_base,
236 irq_hw_number_t hwirq_base, int count);
237extern void irq_domain_disassociate(struct irq_domain *domain,
238 unsigned int irq);
239
240extern unsigned int irq_create_mapping(struct irq_domain *host,
241 irq_hw_number_t hwirq);
242extern void irq_dispose_mapping(unsigned int virq);
243
244
245
246
247
248
249
250
251
252
253
254static inline unsigned int irq_linear_revmap(struct irq_domain *domain,
255 irq_hw_number_t hwirq)
256{
257 return hwirq < domain->revmap_size ? domain->linear_revmap[hwirq] : 0;
258}
259extern unsigned int irq_find_mapping(struct irq_domain *host,
260 irq_hw_number_t hwirq);
261extern unsigned int irq_create_direct_mapping(struct irq_domain *host);
262extern int irq_create_strict_mappings(struct irq_domain *domain,
263 unsigned int irq_base,
264 irq_hw_number_t hwirq_base, int count);
265
266static inline int irq_create_identity_mapping(struct irq_domain *host,
267 irq_hw_number_t hwirq)
268{
269 return irq_create_strict_mappings(host, hwirq, hwirq, 1);
270}
271
272extern const struct irq_domain_ops irq_domain_simple_ops;
273
274
275int irq_domain_xlate_onecell(struct irq_domain *d, struct device_node *ctrlr,
276 const u32 *intspec, unsigned int intsize,
277 irq_hw_number_t *out_hwirq, unsigned int *out_type);
278int irq_domain_xlate_twocell(struct irq_domain *d, struct device_node *ctrlr,
279 const u32 *intspec, unsigned int intsize,
280 irq_hw_number_t *out_hwirq, unsigned int *out_type);
281int irq_domain_xlate_onetwocell(struct irq_domain *d, struct device_node *ctrlr,
282 const u32 *intspec, unsigned int intsize,
283 irq_hw_number_t *out_hwirq, unsigned int *out_type);
284
285
286extern struct irq_data *irq_domain_get_irq_data(struct irq_domain *domain,
287 unsigned int virq);
288extern void irq_domain_set_info(struct irq_domain *domain, unsigned int virq,
289 irq_hw_number_t hwirq, struct irq_chip *chip,
290 void *chip_data, irq_flow_handler_t handler,
291 void *handler_data, const char *handler_name);
292#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
293extern struct irq_domain *irq_domain_add_hierarchy(struct irq_domain *parent,
294 unsigned int flags, unsigned int size,
295 struct device_node *node,
296 const struct irq_domain_ops *ops, void *host_data);
297extern int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base,
298 unsigned int nr_irqs, int node, void *arg,
299 bool realloc);
300extern void irq_domain_free_irqs(unsigned int virq, unsigned int nr_irqs);
301extern void irq_domain_activate_irq(struct irq_data *irq_data);
302extern void irq_domain_deactivate_irq(struct irq_data *irq_data);
303
304static inline int irq_domain_alloc_irqs(struct irq_domain *domain,
305 unsigned int nr_irqs, int node, void *arg)
306{
307 return __irq_domain_alloc_irqs(domain, -1, nr_irqs, node, arg, false);
308}
309
310extern int irq_domain_set_hwirq_and_chip(struct irq_domain *domain,
311 unsigned int virq,
312 irq_hw_number_t hwirq,
313 struct irq_chip *chip,
314 void *chip_data);
315extern void irq_domain_reset_irq_data(struct irq_data *irq_data);
316extern void irq_domain_free_irqs_common(struct irq_domain *domain,
317 unsigned int virq,
318 unsigned int nr_irqs);
319extern void irq_domain_free_irqs_top(struct irq_domain *domain,
320 unsigned int virq, unsigned int nr_irqs);
321
322extern int irq_domain_alloc_irqs_parent(struct irq_domain *domain,
323 unsigned int irq_base,
324 unsigned int nr_irqs, void *arg);
325
326extern void irq_domain_free_irqs_parent(struct irq_domain *domain,
327 unsigned int irq_base,
328 unsigned int nr_irqs);
329
330static inline bool irq_domain_is_hierarchy(struct irq_domain *domain)
331{
332 return domain->flags & IRQ_DOMAIN_FLAG_HIERARCHY;
333}
334#else
335static inline void irq_domain_activate_irq(struct irq_data *data) { }
336static inline void irq_domain_deactivate_irq(struct irq_data *data) { }
337static inline int irq_domain_alloc_irqs(struct irq_domain *domain,
338 unsigned int nr_irqs, int node, void *arg)
339{
340 return -1;
341}
342
343static inline bool irq_domain_is_hierarchy(struct irq_domain *domain)
344{
345 return false;
346}
347#endif
348
349#else
350static inline void irq_dispose_mapping(unsigned int virq) { }
351static inline void irq_domain_activate_irq(struct irq_data *data) { }
352static inline void irq_domain_deactivate_irq(struct irq_data *data) { }
353#endif
354
355#endif
356