* Andreas Fenkart <afenk...@gmail.com> [131216 03:29]:
> --- a/drivers/mmc/host/omap_hsmmc.c
> +++ b/drivers/mmc/host/omap_hsmmc.c
> @@ -2098,8 +2186,28 @@ static int omap_hsmmc_probe(struct platform_device 
> *pdev)
>       if (pdev->dev.of_node) {
>               mmc->caps |= MMC_CAP_SDIO_IRQ;
>               if (pdata->controller_flags & OMAP_HSMMC_SWAKEUP_MISSING) {
> -                     /* no wakeup from deeper power states, use polling */
> -                     mmc->caps &= ~MMC_CAP_SDIO_IRQ;
> +                     /* use GPIO to wakeup from deeper power states */
> +                     if (!host->idle || !host->gpio_sdio_irq) {
> +                             dev_warn(mmc_dev(host->mmc),
> +                                      "Disable SDIO IRQ workaround, GPIO IRQ 
> or pinctrl idle state missing, falling back to polling\n");
> +                             mmc->caps &= ~MMC_CAP_SDIO_IRQ;
> +                     } else {
> +                             host->flags |= HSMMC_SWAKEUP_QUIRK;
> +
> +                     }
> +             }
> +
> +             if (host->flags & HSMMC_SWAKEUP_QUIRK) {
> +                     /* prevent auto-enabling of IRQ */
> +                     irq_set_status_flags(host->gpio_sdio_irq, IRQ_NOAUTOEN);
> +                     ret = request_irq(host->gpio_sdio_irq, omap_hsmmc_cirq,
> +                                       IRQF_TRIGGER_LOW | IRQF_ONESHOT,
> +                                       mmc_hostname(mmc), host);
> +                     if (ret) {
> +                             dev_err(mmc_dev(host->mmc),
> +                                     "Unable to grab GPIO SDIO IRQ\n");
> +                             goto err_irq_sdio;
> +                     }
>               }
>       }
>  

FYI This part needs to be changed a bit for the omaps that have a working
wake-up interrupt. I tried on 3730 with the following patch, but so far it
gets stuck in an infinite SDIO interrupt loop. I'll try to take a look at
it more but may not get to it very soon with the holidays coming up. Also
changed the naming to use wakeirq to make it a bit shorter and generic.

Regards,

Tony

8< ---------------------------------------
--- a/arch/arm/boot/dts/omap3-evm-37xx.dts
+++ b/arch/arm/boot/dts/omap3-evm-37xx.dts
@@ -48,7 +48,7 @@
                        0x128 (PIN_INPUT_PULLUP | MUX_MODE0)    /* 
sdmmc2_clk.sdmmc2_clk */
                        0x12a (PIN_INPUT_PULLUP | MUX_MODE0)    /* 
sdmmc2_cmd.sdmmc2_cmd */
                        0x12c (PIN_INPUT_PULLUP | MUX_MODE0)    /* 
sdmmc2_dat0.sdmmc2_dat0 */
-                       0x12e (WAKEUP_EN | PIN_INPUT_PULLUP | MUX_MODE0) /* 
sdmmc2_dat1.sdmmc2_dat1 */
+                       0x12e (PIN_INPUT_PULLUP | MUX_MODE0)    /* 
sdmmc2_dat1.sdmmc2_dat1 */
                        0x130 (PIN_INPUT_PULLUP | MUX_MODE0)    /* 
sdmmc2_dat2.sdmmc2_dat2 */
                        0x132 (PIN_INPUT_PULLUP | MUX_MODE0)    /* 
sdmmc2_dat3.sdmmc2_dat3 */
                >;
@@ -81,6 +81,7 @@
 };
 
 &mmc2 {
+       interrupts-extended = <&intc 86 &omap3_pmx_core 0x12e>;
        pinctrl-names = "default";
        pinctrl-0 = <&mmc2_pins>;
 };
--- a/arch/arm/boot/dts/omap3.dtsi
+++ b/arch/arm/boot/dts/omap3.dtsi
@@ -395,7 +395,7 @@
                mmc2: mmc@480b4000 {
                        compatible = "ti,omap3-hsmmc";
                        reg = <0x480b4000 0x200>;
-                       interrupts = <86>;
+                       interrupts-extended = <&intc 86>;
                        ti,hwmods = "mmc2";
                        dmas = <&sdma 47>, <&sdma 48>;
                        dma-names = "tx", "rx";
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 78e7b80..7da1532 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -182,7 +182,7 @@ struct omap_hsmmc_host {
        u32                     sysctl;
        u32                     capa;
        int                     irq;
-       int                     gpio_sdio_irq;
+       int                     wakeirq;
        int                     use_dma, dma_ch;
        struct dma_chan         *tx_chan;
        struct dma_chan         *rx_chan;
@@ -211,7 +211,7 @@ static irqreturn_t omap_hsmmc_cirq(int irq, void *dev_id)
 
        spin_lock_irqsave(&host->irq_lock, flags);
        if (host->flags & HSMMC_CIRQ_GPIO_ENABLED) {
-               disable_irq_nosync(host->gpio_sdio_irq);
+               disable_irq_nosync(host->wakeirq);
                host->flags &= ~HSMMC_CIRQ_GPIO_ENABLED;
        }
        spin_unlock_irqrestore(&host->irq_lock, flags);
@@ -1159,7 +1159,8 @@ static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id)
                        omap_hsmmc_do_irq(host, status);
 
                if (status & CIRQ_EN)
-                       mmc_signal_sdio_irq(host->mmc);
+                       if (host->mmc->sdio_irq_thread)
+                               mmc_signal_sdio_irq(host->mmc);
 
                /* Flush posted write */
                status = OMAP_HSMMC_READ(host->base, STAT);
@@ -1976,7 +1977,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
        host->use_dma   = 1;
        host->dma_ch    = -1;
        host->irq       = irq;
-       host->gpio_sdio_irq = irq2;
+       host->wakeirq   = irq2;
        host->slot_id   = 0;
        host->mapbase   = res->start + pdata->reg_offset;
        host->base      = ioremap(host->mapbase, SZ_4K);
@@ -2153,20 +2154,19 @@ static int omap_hsmmc_probe(struct platform_device 
*pdev)
                mmc->caps |= MMC_CAP_SDIO_IRQ;
                if (pdata->controller_flags & OMAP_HSMMC_SWAKEUP_MISSING) {
                        /* use GPIO to wakeup from deeper power states */
-                       if (!host->idle || !host->gpio_sdio_irq) {
+                       if (!host->idle || !host->wakeirq) {
                                dev_warn(mmc_dev(host->mmc),
                                         "Disable SDIO IRQ workaround, GPIO IRQ 
or pinctrl idle state missing, falling back to polling\n");
                                mmc->caps &= ~MMC_CAP_SDIO_IRQ;
-                       } else {
-                               host->flags |= HSMMC_SWAKEUP_QUIRK;
-
                        }
                }
 
-               if (host->flags & HSMMC_SWAKEUP_QUIRK) {
+               if (host->wakeirq) {
+                       host->flags |= HSMMC_SWAKEUP_QUIRK;
+
                        /* prevent auto-enabling of IRQ */
-                       irq_set_status_flags(host->gpio_sdio_irq, IRQ_NOAUTOEN);
-                       ret = request_irq(host->gpio_sdio_irq, omap_hsmmc_cirq,
+                       irq_set_status_flags(host->wakeirq, IRQ_NOAUTOEN);
+                       ret = request_irq(host->wakeirq, omap_hsmmc_cirq,
                                          IRQF_TRIGGER_LOW | IRQF_ONESHOT,
                                          mmc_hostname(mmc), host);
                        if (ret) {
@@ -2201,8 +2201,8 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
 
 err_slot_name:
        mmc_remove_host(mmc);
-       if (host->gpio_sdio_irq)
-               free_irq(host->gpio_sdio_irq, host);
+       if (host->wakeirq)
+               free_irq(host->wakeirq, host);
 err_irq_sdio:
        devm_pinctrl_put(host->pinctrl);
 err_pinctrl_state:
@@ -2252,8 +2252,8 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
        if (host->pdata->cleanup)
                host->pdata->cleanup(&pdev->dev);
        free_irq(host->irq, host);
-       if ((host->gpio_sdio_irq))
-               free_irq(host->gpio_sdio_irq, host);
+       if ((host->wakeirq))
+               free_irq(host->wakeirq, host);
        if (mmc_slot(host).card_detect_irq)
                free_irq(mmc_slot(host).card_detect_irq, host);
        if (host->tx_chan)
@@ -2317,7 +2317,7 @@ static int omap_hsmmc_suspend(struct device *dev)
        }
 
        if (host->flags & HSMMC_SWAKEUP_QUIRK)
-               disable_irq(host->gpio_sdio_irq);
+               disable_irq(host->wakeirq);
 
        if (host->dbclk)
                clk_disable_unprepare(host->dbclk);
@@ -2345,7 +2345,7 @@ static int omap_hsmmc_resume(struct device *dev)
        omap_hsmmc_protect_card(host);
 
        if (host->flags & HSMMC_SWAKEUP_QUIRK)
-               enable_irq(host->gpio_sdio_irq);
+               enable_irq(host->wakeirq);
 
        pm_runtime_mark_last_busy(host->dev);
        pm_runtime_put_autosuspend(host->dev);
@@ -2374,13 +2374,16 @@ static int omap_hsmmc_runtime_suspend(struct device 
*dev)
                OMAP_HSMMC_WRITE(host->base, IE, 0);
                OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
 
-               ret = pinctrl_select_state(host->pinctrl, host->idle);
-               if (ret < 0)
-                       dev_warn(mmc_dev(host->mmc), "Unable to select idle 
pinmux\n");
+               if (host->idle) {
+                       ret = pinctrl_select_state(host->pinctrl, host->idle);
+                       if (ret < 0)
+                               dev_warn(mmc_dev(host->mmc),
+                                        "Unable to select idle pinmux\n");
+               }
 
                spin_lock_irqsave(&host->irq_lock, flags);
                if (host->flags & HSMMC_SDIO_IRQ_ENABLED) {
-                       enable_irq(host->gpio_sdio_irq);
+                       enable_irq(host->wakeirq);
                        host->flags |= HSMMC_CIRQ_GPIO_ENABLED;
                }
                spin_unlock_irqrestore(&host->irq_lock, flags);
@@ -2403,14 +2406,17 @@ static int omap_hsmmc_runtime_resume(struct device *dev)
 
                spin_lock_irqsave(&host->irq_lock, flags);
                if (host->flags & HSMMC_CIRQ_GPIO_ENABLED) {
-                       disable_irq_nosync(host->gpio_sdio_irq);
+                       disable_irq_nosync(host->wakeirq);
                        host->flags &= ~HSMMC_CIRQ_GPIO_ENABLED;
                }
                spin_unlock_irqrestore(&host->irq_lock, flags);
 
-               ret = pinctrl_select_state(host->pinctrl, host->active);
-               if (ret < 0)
-                       dev_warn(mmc_dev(host->mmc), "Unable to select active 
pinmux\n");
+               if (host->active) {
+                       ret = pinctrl_select_state(host->pinctrl, host->active);
+                       if (ret < 0)
+                               dev_warn(mmc_dev(host->mmc),
+                                        "Unable to select active pinmux\n");
+               }
 
                OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
                OMAP_HSMMC_WRITE(host->base, ISE, CIRQ_EN);
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to