Grant Likely | 08a543a | 2011-07-26 03:19:06 -0600 | [diff] [blame] | 1 | /* |
| 2 | * irq_domain - IRQ translation domains |
| 3 | * |
| 4 | * Translation infrastructure between hw and linux irq numbers. This is |
| 5 | * helpful for interrupt controllers to implement mapping between hardware |
| 6 | * irq numbers and the Linux irq number space. |
| 7 | * |
| 8 | * irq_domains also have a hook for translating device tree interrupt |
| 9 | * representation into a hardware irq number that can be mapped back to a |
| 10 | * Linux irq number without any extra platform support code. |
| 11 | * |
| 12 | * irq_domain is expected to be embedded in an interrupt controller's private |
| 13 | * data structure. |
| 14 | */ |
| 15 | #ifndef _LINUX_IRQDOMAIN_H |
| 16 | #define _LINUX_IRQDOMAIN_H |
| 17 | |
| 18 | #include <linux/irq.h> |
Grant Likely | 7e71330 | 2011-07-26 03:19:06 -0600 | [diff] [blame] | 19 | #include <linux/mod_devicetable.h> |
Grant Likely | 08a543a | 2011-07-26 03:19:06 -0600 | [diff] [blame] | 20 | |
| 21 | #ifdef CONFIG_IRQ_DOMAIN |
| 22 | struct device_node; |
| 23 | struct irq_domain; |
| 24 | |
| 25 | /** |
| 26 | * struct irq_domain_ops - Methods for irq_domain objects |
| 27 | * @to_irq: (optional) given a local hardware irq number, return the linux |
| 28 | * irq number. If to_irq is not implemented, then the irq_domain |
| 29 | * will use this translation: irq = (domain->irq_base + hwirq) |
| 30 | * @dt_translate: Given a device tree node and interrupt specifier, decode |
| 31 | * the hardware irq number and linux irq type value. |
| 32 | */ |
| 33 | struct irq_domain_ops { |
| 34 | unsigned int (*to_irq)(struct irq_domain *d, unsigned long hwirq); |
| 35 | |
| 36 | #ifdef CONFIG_OF |
| 37 | int (*dt_translate)(struct irq_domain *d, struct device_node *node, |
| 38 | const u32 *intspec, unsigned int intsize, |
| 39 | unsigned long *out_hwirq, unsigned int *out_type); |
| 40 | #endif /* CONFIG_OF */ |
| 41 | }; |
| 42 | |
| 43 | /** |
| 44 | * struct irq_domain - Hardware interrupt number translation object |
| 45 | * @list: Element in global irq_domain list. |
| 46 | * @irq_base: Start of irq_desc range assigned to the irq_domain. The creator |
| 47 | * of the irq_domain is responsible for allocating the array of |
| 48 | * irq_desc structures. |
| 49 | * @nr_irq: Number of irqs managed by the irq domain |
Rob Herring | 6d27430 | 2011-09-30 10:48:38 -0500 | [diff] [blame] | 50 | * @hwirq_base: Starting number for hwirqs managed by the irq domain |
Grant Likely | 08a543a | 2011-07-26 03:19:06 -0600 | [diff] [blame] | 51 | * @ops: pointer to irq_domain methods |
| 52 | * @priv: private data pointer for use by owner. Not touched by irq_domain |
| 53 | * core code. |
| 54 | * @of_node: (optional) Pointer to device tree nodes associated with the |
| 55 | * irq_domain. Used when decoding device tree interrupt specifiers. |
| 56 | */ |
| 57 | struct irq_domain { |
| 58 | struct list_head list; |
| 59 | unsigned int irq_base; |
| 60 | unsigned int nr_irq; |
Rob Herring | 6d27430 | 2011-09-30 10:48:38 -0500 | [diff] [blame] | 61 | unsigned int hwirq_base; |
Grant Likely | 08a543a | 2011-07-26 03:19:06 -0600 | [diff] [blame] | 62 | const struct irq_domain_ops *ops; |
| 63 | void *priv; |
| 64 | struct device_node *of_node; |
| 65 | }; |
| 66 | |
| 67 | /** |
| 68 | * irq_domain_to_irq() - Translate from a hardware irq to a linux irq number |
| 69 | * |
| 70 | * Returns the linux irq number associated with a hardware irq. By default, |
| 71 | * the mapping is irq == domain->irq_base + hwirq, but this mapping can |
| 72 | * be overridden if the irq_domain implements a .to_irq() hook. |
| 73 | */ |
| 74 | static inline unsigned int irq_domain_to_irq(struct irq_domain *d, |
| 75 | unsigned long hwirq) |
| 76 | { |
Rob Herring | 6d27430 | 2011-09-30 10:48:38 -0500 | [diff] [blame] | 77 | if (d->ops->to_irq) |
| 78 | return d->ops->to_irq(d, hwirq); |
| 79 | if (WARN_ON(hwirq < d->hwirq_base)) |
| 80 | return 0; |
| 81 | return d->irq_base + hwirq - d->hwirq_base; |
Grant Likely | 08a543a | 2011-07-26 03:19:06 -0600 | [diff] [blame] | 82 | } |
| 83 | |
Rob Herring | 6d27430 | 2011-09-30 10:48:38 -0500 | [diff] [blame] | 84 | #define irq_domain_for_each_hwirq(d, hw) \ |
| 85 | for (hw = d->hwirq_base; hw < d->hwirq_base + d->nr_irq; hw++) |
| 86 | |
| 87 | #define irq_domain_for_each_irq(d, hw, irq) \ |
| 88 | for (hw = d->hwirq_base, irq = irq_domain_to_irq(d, hw); \ |
| 89 | hw < d->hwirq_base + d->nr_irq; \ |
| 90 | hw++, irq = irq_domain_to_irq(d, hw)) |
| 91 | |
Grant Likely | 08a543a | 2011-07-26 03:19:06 -0600 | [diff] [blame] | 92 | extern void irq_domain_add(struct irq_domain *domain); |
| 93 | extern void irq_domain_del(struct irq_domain *domain); |
| 94 | #endif /* CONFIG_IRQ_DOMAIN */ |
| 95 | |
Grant Likely | 7e71330 | 2011-07-26 03:19:06 -0600 | [diff] [blame] | 96 | #if defined(CONFIG_IRQ_DOMAIN) && defined(CONFIG_OF_IRQ) |
Rob Herring | 5bd078d | 2011-09-14 11:31:36 -0500 | [diff] [blame] | 97 | extern struct irq_domain_ops irq_domain_simple_ops; |
Grant Likely | 7e71330 | 2011-07-26 03:19:06 -0600 | [diff] [blame] | 98 | extern void irq_domain_add_simple(struct device_node *controller, int irq_base); |
| 99 | extern void irq_domain_generate_simple(const struct of_device_id *match, |
| 100 | u64 phys_base, unsigned int irq_start); |
| 101 | #else /* CONFIG_IRQ_DOMAIN && CONFIG_OF_IRQ */ |
| 102 | static inline void irq_domain_generate_simple(const struct of_device_id *match, |
| 103 | u64 phys_base, unsigned int irq_start) { } |
| 104 | #endif /* CONFIG_IRQ_DOMAIN && CONFIG_OF_IRQ */ |
| 105 | |
Grant Likely | 08a543a | 2011-07-26 03:19:06 -0600 | [diff] [blame] | 106 | #endif /* _LINUX_IRQDOMAIN_H */ |