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#ifndef _LINUX_IRQDOMAIN_H
31#define _LINUX_IRQDOMAIN_H
32
33#include <linux/types.h>
34#include <linux/irqhandler.h>
35#include <linux/of.h>
36#include <linux/radix-tree.h>
37
38struct device_node;
39struct irq_domain;
40struct of_device_id;
41struct irq_chip;
42struct irq_data;
43struct cpumask;
44
45
46#define NUM_ISA_INTERRUPTS 16
47
48#define IRQ_DOMAIN_IRQ_SPEC_PARAMS 16
49
50
51
52
53
54
55
56
57
58
59
60struct irq_fwspec {
61 struct fwnode_handle *fwnode;
62 int param_count;
63 u32 param[IRQ_DOMAIN_IRQ_SPEC_PARAMS];
64};
65
66
67
68
69
70
71
72
73enum irq_domain_bus_token {
74 DOMAIN_BUS_ANY = 0,
75 DOMAIN_BUS_WIRED,
76 DOMAIN_BUS_PCI_MSI,
77 DOMAIN_BUS_PLATFORM_MSI,
78 DOMAIN_BUS_NEXUS,
79 DOMAIN_BUS_IPI,
80 DOMAIN_BUS_FSL_MC_MSI,
81};
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98struct irq_domain_ops {
99 int (*match)(struct irq_domain *d, struct device_node *node,
100 enum irq_domain_bus_token bus_token);
101 int (*select)(struct irq_domain *d, struct irq_fwspec *fwspec,
102 enum irq_domain_bus_token bus_token);
103 int (*map)(struct irq_domain *d, unsigned int virq, irq_hw_number_t hw);
104 void (*unmap)(struct irq_domain *d, unsigned int virq);
105 int (*xlate)(struct irq_domain *d, struct device_node *node,
106 const u32 *intspec, unsigned int intsize,
107 unsigned long *out_hwirq, unsigned int *out_type);
108
109#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
110
111 int (*alloc)(struct irq_domain *d, unsigned int virq,
112 unsigned int nr_irqs, void *arg);
113 void (*free)(struct irq_domain *d, unsigned int virq,
114 unsigned int nr_irqs);
115 void (*activate)(struct irq_domain *d, struct irq_data *irq_data);
116 void (*deactivate)(struct irq_domain *d, struct irq_data *irq_data);
117 int (*translate)(struct irq_domain *d, struct irq_fwspec *fwspec,
118 unsigned long *out_hwirq, unsigned int *out_type);
119#endif
120};
121
122extern struct irq_domain_ops irq_generic_chip_ops;
123
124struct irq_domain_chip_generic;
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152struct irq_domain {
153 struct list_head link;
154 const char *name;
155 const struct irq_domain_ops *ops;
156 void *host_data;
157 unsigned int flags;
158 unsigned int mapcount;
159
160
161 struct fwnode_handle *fwnode;
162 enum irq_domain_bus_token bus_token;
163 struct irq_domain_chip_generic *gc;
164#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
165 struct irq_domain *parent;
166#endif
167#ifdef CONFIG_GENERIC_IRQ_DEBUGFS
168 struct dentry *debugfs_file;
169#endif
170
171
172 irq_hw_number_t hwirq_max;
173 unsigned int revmap_direct_max_irq;
174 unsigned int revmap_size;
175 struct radix_tree_root revmap_tree;
176 unsigned int linear_revmap[];
177};
178
179
180enum {
181
182 IRQ_DOMAIN_FLAG_HIERARCHY = (1 << 0),
183
184
185 IRQ_DOMAIN_NAME_ALLOCATED = (1 << 6),
186
187
188 IRQ_DOMAIN_FLAG_IPI_PER_CPU = (1 << 2),
189
190
191 IRQ_DOMAIN_FLAG_IPI_SINGLE = (1 << 3),
192
193
194 IRQ_DOMAIN_FLAG_MSI = (1 << 4),
195
196
197 IRQ_DOMAIN_FLAG_MSI_REMAP = (1 << 5),
198
199
200
201
202
203
204 IRQ_DOMAIN_FLAG_NONCORE = (1 << 16),
205};
206
207static inline struct device_node *irq_domain_get_of_node(struct irq_domain *d)
208{
209 return to_of_node(d->fwnode);
210}
211
212#ifdef CONFIG_IRQ_DOMAIN
213struct fwnode_handle *__irq_domain_alloc_fwnode(unsigned int type, int id,
214 const char *name, void *data);
215
216enum {
217 IRQCHIP_FWNODE_REAL,
218 IRQCHIP_FWNODE_NAMED,
219 IRQCHIP_FWNODE_NAMED_ID,
220};
221
222static inline
223struct fwnode_handle *irq_domain_alloc_named_fwnode(const char *name)
224{
225 return __irq_domain_alloc_fwnode(IRQCHIP_FWNODE_NAMED, 0, name, NULL);
226}
227
228static inline
229struct fwnode_handle *irq_domain_alloc_named_id_fwnode(const char *name, int id)
230{
231 return __irq_domain_alloc_fwnode(IRQCHIP_FWNODE_NAMED_ID, id, name,
232 NULL);
233}
234
235static inline struct fwnode_handle *irq_domain_alloc_fwnode(void *data)
236{
237 return __irq_domain_alloc_fwnode(IRQCHIP_FWNODE_REAL, 0, NULL, data);
238}
239
240void irq_domain_free_fwnode(struct fwnode_handle *fwnode);
241struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size,
242 irq_hw_number_t hwirq_max, int direct_max,
243 const struct irq_domain_ops *ops,
244 void *host_data);
245struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
246 unsigned int size,
247 unsigned int first_irq,
248 const struct irq_domain_ops *ops,
249 void *host_data);
250struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
251 unsigned int size,
252 unsigned int first_irq,
253 irq_hw_number_t first_hwirq,
254 const struct irq_domain_ops *ops,
255 void *host_data);
256extern struct irq_domain *irq_find_matching_fwspec(struct irq_fwspec *fwspec,
257 enum irq_domain_bus_token bus_token);
258extern bool irq_domain_check_msi_remap(void);
259extern void irq_set_default_host(struct irq_domain *host);
260extern int irq_domain_alloc_descs(int virq, unsigned int nr_irqs,
261 irq_hw_number_t hwirq, int node,
262 const struct cpumask *affinity);
263
264static inline struct fwnode_handle *of_node_to_fwnode(struct device_node *node)
265{
266 return node ? &node->fwnode : NULL;
267}
268
269extern const struct fwnode_operations irqchip_fwnode_ops;
270
271static inline bool is_fwnode_irqchip(struct fwnode_handle *fwnode)
272{
273 return fwnode && fwnode->ops == &irqchip_fwnode_ops;
274}
275
276extern void irq_domain_update_bus_token(struct irq_domain *domain,
277 enum irq_domain_bus_token bus_token);
278
279static inline
280struct irq_domain *irq_find_matching_fwnode(struct fwnode_handle *fwnode,
281 enum irq_domain_bus_token bus_token)
282{
283 struct irq_fwspec fwspec = {
284 .fwnode = fwnode,
285 };
286
287 return irq_find_matching_fwspec(&fwspec, bus_token);
288}
289
290static inline struct irq_domain *irq_find_matching_host(struct device_node *node,
291 enum irq_domain_bus_token bus_token)
292{
293 return irq_find_matching_fwnode(of_node_to_fwnode(node), bus_token);
294}
295
296static inline struct irq_domain *irq_find_host(struct device_node *node)
297{
298 return irq_find_matching_host(node, DOMAIN_BUS_ANY);
299}
300
301
302
303
304
305
306
307
308static inline struct irq_domain *irq_domain_add_linear(struct device_node *of_node,
309 unsigned int size,
310 const struct irq_domain_ops *ops,
311 void *host_data)
312{
313 return __irq_domain_add(of_node_to_fwnode(of_node), size, size, 0, ops, host_data);
314}
315static inline struct irq_domain *irq_domain_add_nomap(struct device_node *of_node,
316 unsigned int max_irq,
317 const struct irq_domain_ops *ops,
318 void *host_data)
319{
320 return __irq_domain_add(of_node_to_fwnode(of_node), 0, max_irq, max_irq, ops, host_data);
321}
322static inline struct irq_domain *irq_domain_add_legacy_isa(
323 struct device_node *of_node,
324 const struct irq_domain_ops *ops,
325 void *host_data)
326{
327 return irq_domain_add_legacy(of_node, NUM_ISA_INTERRUPTS, 0, 0, ops,
328 host_data);
329}
330static inline struct irq_domain *irq_domain_add_tree(struct device_node *of_node,
331 const struct irq_domain_ops *ops,
332 void *host_data)
333{
334 return __irq_domain_add(of_node_to_fwnode(of_node), 0, ~0, 0, ops, host_data);
335}
336
337static inline struct irq_domain *irq_domain_create_linear(struct fwnode_handle *fwnode,
338 unsigned int size,
339 const struct irq_domain_ops *ops,
340 void *host_data)
341{
342 return __irq_domain_add(fwnode, size, size, 0, ops, host_data);
343}
344
345static inline struct irq_domain *irq_domain_create_tree(struct fwnode_handle *fwnode,
346 const struct irq_domain_ops *ops,
347 void *host_data)
348{
349 return __irq_domain_add(fwnode, 0, ~0, 0, ops, host_data);
350}
351
352extern void irq_domain_remove(struct irq_domain *host);
353
354extern int irq_domain_associate(struct irq_domain *domain, unsigned int irq,
355 irq_hw_number_t hwirq);
356extern void irq_domain_associate_many(struct irq_domain *domain,
357 unsigned int irq_base,
358 irq_hw_number_t hwirq_base, int count);
359extern void irq_domain_disassociate(struct irq_domain *domain,
360 unsigned int irq);
361
362extern unsigned int irq_create_mapping(struct irq_domain *host,
363 irq_hw_number_t hwirq);
364extern unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec);
365extern void irq_dispose_mapping(unsigned int virq);
366
367
368
369
370
371
372
373
374
375
376
377static inline unsigned int irq_linear_revmap(struct irq_domain *domain,
378 irq_hw_number_t hwirq)
379{
380 return hwirq < domain->revmap_size ? domain->linear_revmap[hwirq] : 0;
381}
382extern unsigned int irq_find_mapping(struct irq_domain *host,
383 irq_hw_number_t hwirq);
384extern unsigned int irq_create_direct_mapping(struct irq_domain *host);
385extern int irq_create_strict_mappings(struct irq_domain *domain,
386 unsigned int irq_base,
387 irq_hw_number_t hwirq_base, int count);
388
389static inline int irq_create_identity_mapping(struct irq_domain *host,
390 irq_hw_number_t hwirq)
391{
392 return irq_create_strict_mappings(host, hwirq, hwirq, 1);
393}
394
395extern const struct irq_domain_ops irq_domain_simple_ops;
396
397
398int irq_domain_xlate_onecell(struct irq_domain *d, struct device_node *ctrlr,
399 const u32 *intspec, unsigned int intsize,
400 irq_hw_number_t *out_hwirq, unsigned int *out_type);
401int irq_domain_xlate_twocell(struct irq_domain *d, struct device_node *ctrlr,
402 const u32 *intspec, unsigned int intsize,
403 irq_hw_number_t *out_hwirq, unsigned int *out_type);
404int irq_domain_xlate_onetwocell(struct irq_domain *d, struct device_node *ctrlr,
405 const u32 *intspec, unsigned int intsize,
406 irq_hw_number_t *out_hwirq, unsigned int *out_type);
407
408
409int irq_reserve_ipi(struct irq_domain *domain, const struct cpumask *dest);
410int irq_destroy_ipi(unsigned int irq, const struct cpumask *dest);
411
412
413extern struct irq_data *irq_domain_get_irq_data(struct irq_domain *domain,
414 unsigned int virq);
415extern void irq_domain_set_info(struct irq_domain *domain, unsigned int virq,
416 irq_hw_number_t hwirq, struct irq_chip *chip,
417 void *chip_data, irq_flow_handler_t handler,
418 void *handler_data, const char *handler_name);
419#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
420extern struct irq_domain *irq_domain_create_hierarchy(struct irq_domain *parent,
421 unsigned int flags, unsigned int size,
422 struct fwnode_handle *fwnode,
423 const struct irq_domain_ops *ops, void *host_data);
424
425static inline struct irq_domain *irq_domain_add_hierarchy(struct irq_domain *parent,
426 unsigned int flags,
427 unsigned int size,
428 struct device_node *node,
429 const struct irq_domain_ops *ops,
430 void *host_data)
431{
432 return irq_domain_create_hierarchy(parent, flags, size,
433 of_node_to_fwnode(node),
434 ops, host_data);
435}
436
437extern int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base,
438 unsigned int nr_irqs, int node, void *arg,
439 bool realloc, const struct cpumask *affinity);
440extern void irq_domain_free_irqs(unsigned int virq, unsigned int nr_irqs);
441extern void irq_domain_activate_irq(struct irq_data *irq_data);
442extern void irq_domain_deactivate_irq(struct irq_data *irq_data);
443
444static inline int irq_domain_alloc_irqs(struct irq_domain *domain,
445 unsigned int nr_irqs, int node, void *arg)
446{
447 return __irq_domain_alloc_irqs(domain, -1, nr_irqs, node, arg, false,
448 NULL);
449}
450
451extern int irq_domain_alloc_irqs_hierarchy(struct irq_domain *domain,
452 unsigned int irq_base,
453 unsigned int nr_irqs, void *arg);
454extern int irq_domain_set_hwirq_and_chip(struct irq_domain *domain,
455 unsigned int virq,
456 irq_hw_number_t hwirq,
457 struct irq_chip *chip,
458 void *chip_data);
459extern void irq_domain_reset_irq_data(struct irq_data *irq_data);
460extern void irq_domain_free_irqs_common(struct irq_domain *domain,
461 unsigned int virq,
462 unsigned int nr_irqs);
463extern void irq_domain_free_irqs_top(struct irq_domain *domain,
464 unsigned int virq, unsigned int nr_irqs);
465
466extern int irq_domain_push_irq(struct irq_domain *domain, int virq, void *arg);
467extern int irq_domain_pop_irq(struct irq_domain *domain, int virq);
468
469extern int irq_domain_alloc_irqs_parent(struct irq_domain *domain,
470 unsigned int irq_base,
471 unsigned int nr_irqs, void *arg);
472
473extern void irq_domain_free_irqs_parent(struct irq_domain *domain,
474 unsigned int irq_base,
475 unsigned int nr_irqs);
476
477static inline bool irq_domain_is_hierarchy(struct irq_domain *domain)
478{
479 return domain->flags & IRQ_DOMAIN_FLAG_HIERARCHY;
480}
481
482static inline bool irq_domain_is_ipi(struct irq_domain *domain)
483{
484 return domain->flags &
485 (IRQ_DOMAIN_FLAG_IPI_PER_CPU | IRQ_DOMAIN_FLAG_IPI_SINGLE);
486}
487
488static inline bool irq_domain_is_ipi_per_cpu(struct irq_domain *domain)
489{
490 return domain->flags & IRQ_DOMAIN_FLAG_IPI_PER_CPU;
491}
492
493static inline bool irq_domain_is_ipi_single(struct irq_domain *domain)
494{
495 return domain->flags & IRQ_DOMAIN_FLAG_IPI_SINGLE;
496}
497
498static inline bool irq_domain_is_msi(struct irq_domain *domain)
499{
500 return domain->flags & IRQ_DOMAIN_FLAG_MSI;
501}
502
503static inline bool irq_domain_is_msi_remap(struct irq_domain *domain)
504{
505 return domain->flags & IRQ_DOMAIN_FLAG_MSI_REMAP;
506}
507
508extern bool irq_domain_hierarchical_is_msi_remap(struct irq_domain *domain);
509
510#else
511static inline void irq_domain_activate_irq(struct irq_data *data) { }
512static inline void irq_domain_deactivate_irq(struct irq_data *data) { }
513static inline int irq_domain_alloc_irqs(struct irq_domain *domain,
514 unsigned int nr_irqs, int node, void *arg)
515{
516 return -1;
517}
518
519static inline void irq_domain_free_irqs(unsigned int virq,
520 unsigned int nr_irqs) { }
521
522static inline bool irq_domain_is_hierarchy(struct irq_domain *domain)
523{
524 return false;
525}
526
527static inline bool irq_domain_is_ipi(struct irq_domain *domain)
528{
529 return false;
530}
531
532static inline bool irq_domain_is_ipi_per_cpu(struct irq_domain *domain)
533{
534 return false;
535}
536
537static inline bool irq_domain_is_ipi_single(struct irq_domain *domain)
538{
539 return false;
540}
541
542static inline bool irq_domain_is_msi(struct irq_domain *domain)
543{
544 return false;
545}
546
547static inline bool irq_domain_is_msi_remap(struct irq_domain *domain)
548{
549 return false;
550}
551
552static inline bool
553irq_domain_hierarchical_is_msi_remap(struct irq_domain *domain)
554{
555 return false;
556}
557#endif
558
559#else
560static inline void irq_dispose_mapping(unsigned int virq) { }
561static inline void irq_domain_activate_irq(struct irq_data *data) { }
562static inline void irq_domain_deactivate_irq(struct irq_data *data) { }
563static inline struct irq_domain *irq_find_matching_fwnode(
564 struct fwnode_handle *fwnode, enum irq_domain_bus_token bus_token)
565{
566 return NULL;
567}
568static inline bool irq_domain_check_msi_remap(void)
569{
570 return false;
571}
572#endif
573
574#endif
575