15
15
#include <linux/regmap.h>
16
16
#include <linux/irq.h>
17
17
#include <linux/interrupt.h>
18
+ #include <linux/irqdomain.h>
18
19
#include <linux/slab.h>
19
20
20
21
#include "internal.h"
@@ -26,6 +27,7 @@ struct regmap_irq_chip_data {
26
27
struct regmap_irq_chip * chip ;
27
28
28
29
int irq_base ;
30
+ struct irq_domain * domain ;
29
31
30
32
void * status_reg_buf ;
31
33
unsigned int * status_buf ;
@@ -37,7 +39,7 @@ static inline const
37
39
struct regmap_irq * irq_to_regmap_irq (struct regmap_irq_chip_data * data ,
38
40
int irq )
39
41
{
40
- return & data -> chip -> irqs [irq - data -> irq_base ];
42
+ return & data -> chip -> irqs [irq ];
41
43
}
42
44
43
45
static void regmap_irq_lock (struct irq_data * data )
@@ -74,7 +76,7 @@ static void regmap_irq_enable(struct irq_data *data)
74
76
{
75
77
struct regmap_irq_chip_data * d = irq_data_get_irq_chip_data (data );
76
78
struct regmap * map = d -> map ;
77
- const struct regmap_irq * irq_data = irq_to_regmap_irq (d , data -> irq );
79
+ const struct regmap_irq * irq_data = irq_to_regmap_irq (d , data -> hwirq );
78
80
79
81
d -> mask_buf [irq_data -> reg_offset / map -> reg_stride ] &= ~irq_data -> mask ;
80
82
}
@@ -83,7 +85,7 @@ static void regmap_irq_disable(struct irq_data *data)
83
85
{
84
86
struct regmap_irq_chip_data * d = irq_data_get_irq_chip_data (data );
85
87
struct regmap * map = d -> map ;
86
- const struct regmap_irq * irq_data = irq_to_regmap_irq (d , data -> irq );
88
+ const struct regmap_irq * irq_data = irq_to_regmap_irq (d , data -> hwirq );
87
89
88
90
d -> mask_buf [irq_data -> reg_offset / map -> reg_stride ] |= irq_data -> mask ;
89
91
}
@@ -153,7 +155,7 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
153
155
for (i = 0 ; i < chip -> num_irqs ; i ++ ) {
154
156
if (data -> status_buf [chip -> irqs [i ].reg_offset /
155
157
map -> reg_stride ] & chip -> irqs [i ].mask ) {
156
- handle_nested_irq (data -> irq_base + i );
158
+ handle_nested_irq (irq_find_mapping ( data -> domain , i ) );
157
159
handled = true;
158
160
}
159
161
}
@@ -164,6 +166,31 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
164
166
return IRQ_NONE ;
165
167
}
166
168
169
+ static int regmap_irq_map (struct irq_domain * h , unsigned int virq ,
170
+ irq_hw_number_t hw )
171
+ {
172
+ struct regmap_irq_chip_data * data = h -> host_data ;
173
+
174
+ irq_set_chip_data (virq , data );
175
+ irq_set_chip_and_handler (virq , & regmap_irq_chip , handle_edge_irq );
176
+ irq_set_nested_thread (virq , 1 );
177
+
178
+ /* ARM needs us to explicitly flag the IRQ as valid
179
+ * and will set them noprobe when we do so. */
180
+ #ifdef CONFIG_ARM
181
+ set_irq_flags (virq , IRQF_VALID );
182
+ #else
183
+ irq_set_noprobe (virq );
184
+ #endif
185
+
186
+ return 0 ;
187
+ }
188
+
189
+ static struct irq_domain_ops regmap_domain_ops = {
190
+ .map = regmap_irq_map ,
191
+ .xlate = irq_domain_xlate_twocell ,
192
+ };
193
+
167
194
/**
168
195
* regmap_add_irq_chip(): Use standard regmap IRQ controller handling
169
196
*
@@ -184,7 +211,7 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
184
211
struct regmap_irq_chip_data * * data )
185
212
{
186
213
struct regmap_irq_chip_data * d ;
187
- int cur_irq , i ;
214
+ int i ;
188
215
int ret = - ENOMEM ;
189
216
190
217
for (i = 0 ; i < chip -> num_irqs ; i ++ ) {
@@ -195,11 +222,13 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
195
222
return - EINVAL ;
196
223
}
197
224
198
- irq_base = irq_alloc_descs (irq_base , 0 , chip -> num_irqs , 0 );
199
- if (irq_base < 0 ) {
200
- dev_warn (map -> dev , "Failed to allocate IRQs: %d\n" ,
201
- irq_base );
202
- return irq_base ;
225
+ if (irq_base ) {
226
+ irq_base = irq_alloc_descs (irq_base , 0 , chip -> num_irqs , 0 );
227
+ if (irq_base < 0 ) {
228
+ dev_warn (map -> dev , "Failed to allocate IRQs: %d\n" ,
229
+ irq_base );
230
+ return irq_base ;
231
+ }
203
232
}
204
233
205
234
d = kzalloc (sizeof (* d ), GFP_KERNEL );
@@ -249,33 +278,31 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
249
278
}
250
279
}
251
280
252
- /* Register them with genirq */
253
- for (cur_irq = irq_base ;
254
- cur_irq < chip -> num_irqs + irq_base ;
255
- cur_irq ++ ) {
256
- irq_set_chip_data (cur_irq , d );
257
- irq_set_chip_and_handler (cur_irq , & regmap_irq_chip ,
258
- handle_edge_irq );
259
- irq_set_nested_thread (cur_irq , 1 );
260
-
261
- /* ARM needs us to explicitly flag the IRQ as valid
262
- * and will set them noprobe when we do so. */
263
- #ifdef CONFIG_ARM
264
- set_irq_flags (cur_irq , IRQF_VALID );
265
- #else
266
- irq_set_noprobe (cur_irq );
267
- #endif
281
+ if (irq_base )
282
+ d -> domain = irq_domain_add_legacy (map -> dev -> of_node ,
283
+ chip -> num_irqs , irq_base , 0 ,
284
+ & regmap_domain_ops , d );
285
+ else
286
+ d -> domain = irq_domain_add_linear (map -> dev -> of_node ,
287
+ chip -> num_irqs ,
288
+ & regmap_domain_ops , d );
289
+ if (!d -> domain ) {
290
+ dev_err (map -> dev , "Failed to create IRQ domain\n" );
291
+ ret = - ENOMEM ;
292
+ goto err_alloc ;
268
293
}
269
294
270
295
ret = request_threaded_irq (irq , NULL , regmap_irq_thread , irq_flags ,
271
296
chip -> name , d );
272
297
if (ret != 0 ) {
273
298
dev_err (map -> dev , "Failed to request IRQ %d: %d\n" , irq , ret );
274
- goto err_alloc ;
299
+ goto err_domain ;
275
300
}
276
301
277
302
return 0 ;
278
303
304
+ err_domain :
305
+ /* Should really dispose of the domain but... */
279
306
err_alloc :
280
307
kfree (d -> mask_buf_def );
281
308
kfree (d -> mask_buf );
@@ -298,6 +325,7 @@ void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *d)
298
325
return ;
299
326
300
327
free_irq (irq , d );
328
+ /* We should unmap the domain but... */
301
329
kfree (d -> mask_buf_def );
302
330
kfree (d -> mask_buf );
303
331
kfree (d -> status_reg_buf );
@@ -315,6 +343,21 @@ EXPORT_SYMBOL_GPL(regmap_del_irq_chip);
315
343
*/
316
344
int regmap_irq_chip_get_base (struct regmap_irq_chip_data * data )
317
345
{
346
+ WARN_ON (!data -> irq_base );
318
347
return data -> irq_base ;
319
348
}
320
349
EXPORT_SYMBOL_GPL (regmap_irq_chip_get_base );
350
+
351
+ /**
352
+ * regmap_irq_get_virq(): Map an interrupt on a chip to a virtual IRQ
353
+ *
354
+ * Useful for drivers to request their own IRQs.
355
+ *
356
+ * @data: regmap_irq controller to operate on.
357
+ * @irq: index of the interrupt requested in the chip IRQs
358
+ */
359
+ int regmap_irq_get_virq (struct regmap_irq_chip_data * data , int irq )
360
+ {
361
+ return irq_create_mapping (data -> domain , irq );
362
+ }
363
+ EXPORT_SYMBOL_GPL (regmap_irq_get_virq );
0 commit comments