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 /kernel | |
| 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>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/irq/irqdomain.c | 58 |
1 files changed, 58 insertions, 0 deletions
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 */ |
