1515#include <linux/regmap.h>
1616#include <linux/irq.h>
1717#include <linux/interrupt.h>
18+ #include <linux/irqdomain.h>
1819#include <linux/slab.h>
1920
2021#include "internal.h"
@@ -26,6 +27,7 @@ struct regmap_irq_chip_data {
2627 struct regmap_irq_chip * chip ;
2728
2829 int irq_base ;
30+ struct irq_domain * domain ;
2931
3032 void * status_reg_buf ;
3133 unsigned int * status_buf ;
@@ -37,7 +39,7 @@ static inline const
3739struct regmap_irq * irq_to_regmap_irq (struct regmap_irq_chip_data * data ,
3840 int irq )
3941{
40- return & data -> chip -> irqs [irq - data -> irq_base ];
42+ return & data -> chip -> irqs [irq ];
4143}
4244
4345static void regmap_irq_lock (struct irq_data * data )
@@ -74,7 +76,7 @@ static void regmap_irq_enable(struct irq_data *data)
7476{
7577 struct regmap_irq_chip_data * d = irq_data_get_irq_chip_data (data );
7678 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 );
7880
7981 d -> mask_buf [irq_data -> reg_offset / map -> reg_stride ] &= ~irq_data -> mask ;
8082}
@@ -83,7 +85,7 @@ static void regmap_irq_disable(struct irq_data *data)
8385{
8486 struct regmap_irq_chip_data * d = irq_data_get_irq_chip_data (data );
8587 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 );
8789
8890 d -> mask_buf [irq_data -> reg_offset / map -> reg_stride ] |= irq_data -> mask ;
8991}
@@ -153,7 +155,7 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
153155 for (i = 0 ; i < chip -> num_irqs ; i ++ ) {
154156 if (data -> status_buf [chip -> irqs [i ].reg_offset /
155157 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 ) );
157159 handled = true;
158160 }
159161 }
@@ -164,6 +166,31 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
164166 return IRQ_NONE ;
165167}
166168
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+
167194/**
168195 * regmap_add_irq_chip(): Use standard regmap IRQ controller handling
169196 *
@@ -184,7 +211,7 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
184211 struct regmap_irq_chip_data * * data )
185212{
186213 struct regmap_irq_chip_data * d ;
187- int cur_irq , i ;
214+ int i ;
188215 int ret = - ENOMEM ;
189216
190217 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,
195222 return - EINVAL ;
196223 }
197224
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+ }
203232 }
204233
205234 d = kzalloc (sizeof (* d ), GFP_KERNEL );
@@ -249,33 +278,31 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
249278 }
250279 }
251280
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 ;
268293 }
269294
270295 ret = request_threaded_irq (irq , NULL , regmap_irq_thread , irq_flags ,
271296 chip -> name , d );
272297 if (ret != 0 ) {
273298 dev_err (map -> dev , "Failed to request IRQ %d: %d\n" , irq , ret );
274- goto err_alloc ;
299+ goto err_domain ;
275300 }
276301
277302 return 0 ;
278303
304+ err_domain :
305+ /* Should really dispose of the domain but... */
279306err_alloc :
280307 kfree (d -> mask_buf_def );
281308 kfree (d -> mask_buf );
@@ -298,6 +325,7 @@ void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *d)
298325 return ;
299326
300327 free_irq (irq , d );
328+ /* We should unmap the domain but... */
301329 kfree (d -> mask_buf_def );
302330 kfree (d -> mask_buf );
303331 kfree (d -> status_reg_buf );
@@ -315,6 +343,21 @@ EXPORT_SYMBOL_GPL(regmap_del_irq_chip);
315343 */
316344int regmap_irq_chip_get_base (struct regmap_irq_chip_data * data )
317345{
346+ WARN_ON (!data -> irq_base );
318347 return data -> irq_base ;
319348}
320349EXPORT_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