]> Pileus Git - ~andy/linux/blobdiff - drivers/mfd/arizona-irq.c
Merge tag 'sound-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
[~andy/linux] / drivers / mfd / arizona-irq.c
index 98ac345f468e23517d904a80ea6035933bac8c9c..ef0f2d001df20524695906c42993b368d9fa8a81 100644 (file)
@@ -94,7 +94,8 @@ static irqreturn_t arizona_ctrlif_err(int irq, void *data)
 static irqreturn_t arizona_irq_thread(int irq, void *data)
 {
        struct arizona *arizona = data;
-       int i, ret;
+       unsigned int val;
+       int ret;
 
        ret = pm_runtime_get_sync(arizona->dev);
        if (ret < 0) {
@@ -102,9 +103,20 @@ static irqreturn_t arizona_irq_thread(int irq, void *data)
                return IRQ_NONE;
        }
 
-       /* Check both domains */
-       for (i = 0; i < 2; i++)
-               handle_nested_irq(irq_find_mapping(arizona->virq, i));
+       /* Always handle the AoD domain */
+       handle_nested_irq(irq_find_mapping(arizona->virq, 0));
+
+       /*
+        * Check if one of the main interrupts is asserted and only
+        * check that domain if it is.
+        */
+       ret = regmap_read(arizona->regmap, ARIZONA_IRQ_PIN_STATUS, &val);
+       if (ret == 0 && val & ARIZONA_IRQ1_STS) {
+               handle_nested_irq(irq_find_mapping(arizona->virq, 1));
+       } else if (ret != 0) {
+               dev_err(arizona->dev, "Failed to read main IRQ status: %d\n",
+                       ret);
+       }
 
        pm_runtime_mark_last_busy(arizona->dev);
        pm_runtime_put_autosuspend(arizona->dev);
@@ -156,18 +168,36 @@ int arizona_irq_init(struct arizona *arizona)
        int flags = IRQF_ONESHOT;
        int ret, i;
        const struct regmap_irq_chip *aod, *irq;
+       bool ctrlif_error = true;
 
        switch (arizona->type) {
 #ifdef CONFIG_MFD_WM5102
        case WM5102:
                aod = &wm5102_aod;
                irq = &wm5102_irq;
+
+               switch (arizona->rev) {
+               case 0:
+                       ctrlif_error = false;
+                       break;
+               default:
+                       break;
+               }
                break;
 #endif
 #ifdef CONFIG_MFD_WM5110
        case WM5110:
                aod = &wm5110_aod;
                irq = &wm5110_irq;
+
+               switch (arizona->rev) {
+               case 0:
+               case 1:
+                       ctrlif_error = false;
+                       break;
+               default:
+                       break;
+               }
                break;
 #endif
        default:
@@ -226,13 +256,17 @@ int arizona_irq_init(struct arizona *arizona)
        }
 
        /* Handle control interface errors in the core */
-       i = arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR);
-       ret = request_threaded_irq(i, NULL, arizona_ctrlif_err, IRQF_ONESHOT,
-                                  "Control interface error", arizona);
-       if (ret != 0) {
-               dev_err(arizona->dev, "Failed to request boot done %d: %d\n",
-                       arizona->irq, ret);
-               goto err_ctrlif;
+       if (ctrlif_error) {
+               i = arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR);
+               ret = request_threaded_irq(i, NULL, arizona_ctrlif_err,
+                                          IRQF_ONESHOT,
+                                          "Control interface error", arizona);
+               if (ret != 0) {
+                       dev_err(arizona->dev,
+                               "Failed to request CTRLIF_ERR %d: %d\n",
+                               arizona->irq, ret);
+                       goto err_ctrlif;
+               }
        }
 
        ret = request_threaded_irq(arizona->irq, NULL, arizona_irq_thread,