summaryrefslogtreecommitdiffstats
path: root/drivers/mfd/arizona-irq.c
diff options
context:
space:
mode:
authorCharles Keepax <ckeepax@opensource.wolfsonmicro.com>2015-12-16 08:53:59 -0500
committerLee Jones <lee.jones@linaro.org>2016-01-11 01:41:47 -0500
commit6c006b1b17f8841d83f09b2bc34227e2f9428872 (patch)
tree0cd9e0554fd934c3413eee77846947023a705b32 /drivers/mfd/arizona-irq.c
parent7d07d15abb606f6e0c611e9bc9a2de4745456e5f (diff)
mfd: arizona: Request parent IRQ before we request child IRQs
Currently the driver requests the boot done and control interface IRQs before it has requested its own IRQ line. This can cause problems on edge triggered IRQ systems as if an edge occurs before the parent IRQ is enabled it will be missed. Whilst we are changing the error handling remove an unused label as well. Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com> Signed-off-by: Lee Jones <lee.jones@linaro.org>
Diffstat (limited to 'drivers/mfd/arizona-irq.c')
-rw-r--r--drivers/mfd/arizona-irq.c57
1 files changed, 27 insertions, 30 deletions
diff --git a/drivers/mfd/arizona-irq.c b/drivers/mfd/arizona-irq.c
index 682bc865fa8b..5fef014920a3 100644
--- a/drivers/mfd/arizona-irq.c
+++ b/drivers/mfd/arizona-irq.c
@@ -310,7 +310,7 @@ int arizona_irq_init(struct arizona *arizona)
310 if (ret != 0) { 310 if (ret != 0) {
311 dev_err(arizona->dev, 311 dev_err(arizona->dev,
312 "Failed to add AOD IRQs: %d\n", ret); 312 "Failed to add AOD IRQs: %d\n", ret);
313 goto err_domain; 313 goto err;
314 } 314 }
315 } 315 }
316 316
@@ -323,30 +323,6 @@ int arizona_irq_init(struct arizona *arizona)
323 goto err_aod; 323 goto err_aod;
324 } 324 }
325 325
326 /* Make sure the boot done IRQ is unmasked for resumes */
327 i = arizona_map_irq(arizona, ARIZONA_IRQ_BOOT_DONE);
328 ret = request_threaded_irq(i, NULL, arizona_boot_done, IRQF_ONESHOT,
329 "Boot done", arizona);
330 if (ret != 0) {
331 dev_err(arizona->dev, "Failed to request boot done %d: %d\n",
332 arizona->irq, ret);
333 goto err_boot_done;
334 }
335
336 /* Handle control interface errors in the core */
337 if (arizona->ctrlif_error) {
338 i = arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR);
339 ret = request_threaded_irq(i, NULL, arizona_ctrlif_err,
340 IRQF_ONESHOT,
341 "Control interface error", arizona);
342 if (ret != 0) {
343 dev_err(arizona->dev,
344 "Failed to request CTRLIF_ERR %d: %d\n",
345 arizona->irq, ret);
346 goto err_ctrlif;
347 }
348 }
349
350 /* Used to emulate edge trigger and to work around broken pinmux */ 326 /* Used to emulate edge trigger and to work around broken pinmux */
351 if (arizona->pdata.irq_gpio) { 327 if (arizona->pdata.irq_gpio) {
352 if (gpio_to_irq(arizona->pdata.irq_gpio) != arizona->irq) { 328 if (gpio_to_irq(arizona->pdata.irq_gpio) != arizona->irq) {
@@ -376,21 +352,42 @@ int arizona_irq_init(struct arizona *arizona)
376 goto err_main_irq; 352 goto err_main_irq;
377 } 353 }
378 354
355 /* Make sure the boot done IRQ is unmasked for resumes */
356 i = arizona_map_irq(arizona, ARIZONA_IRQ_BOOT_DONE);
357 ret = request_threaded_irq(i, NULL, arizona_boot_done, IRQF_ONESHOT,
358 "Boot done", arizona);
359 if (ret != 0) {
360 dev_err(arizona->dev, "Failed to request boot done %d: %d\n",
361 arizona->irq, ret);
362 goto err_boot_done;
363 }
364
365 /* Handle control interface errors in the core */
366 if (arizona->ctrlif_error) {
367 i = arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR);
368 ret = request_threaded_irq(i, NULL, arizona_ctrlif_err,
369 IRQF_ONESHOT,
370 "Control interface error", arizona);
371 if (ret != 0) {
372 dev_err(arizona->dev,
373 "Failed to request CTRLIF_ERR %d: %d\n",
374 arizona->irq, ret);
375 goto err_ctrlif;
376 }
377 }
378
379 return 0; 379 return 0;
380 380
381err_main_irq:
382 if (arizona->ctrlif_error)
383 free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR),
384 arizona);
385err_ctrlif: 381err_ctrlif:
386 free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_BOOT_DONE), arizona); 382 free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_BOOT_DONE), arizona);
387err_boot_done: 383err_boot_done:
384 free_irq(arizona->irq, arizona);
385err_main_irq:
388 regmap_del_irq_chip(irq_create_mapping(arizona->virq, 1), 386 regmap_del_irq_chip(irq_create_mapping(arizona->virq, 1),
389 arizona->irq_chip); 387 arizona->irq_chip);
390err_aod: 388err_aod:
391 regmap_del_irq_chip(irq_create_mapping(arizona->virq, 0), 389 regmap_del_irq_chip(irq_create_mapping(arizona->virq, 0),
392 arizona->aod_irq_chip); 390 arizona->aod_irq_chip);
393err_domain:
394err: 391err:
395 return ret; 392 return ret;
396} 393}