diff options
Diffstat (limited to 'kernel/irq/irqdomain.c')
-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 */ |