From: David Brownell <[email protected]>

SDIO support in the MMC framework seems to involve no more than just
being able to report SDIO irqs.  Here's (untested) code to do that.

Signed-off-by: David Brownell <[email protected]>
---
 drivers/mmc/host/davinci_mmc.c |   48 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 47 insertions(+), 1 deletion(-)

--- a/drivers/mmc/host/davinci_mmc.c
+++ b/drivers/mmc/host/davinci_mmc.c
@@ -174,6 +174,7 @@ struct mmc_davinci_host {
        void __iomem *base;
        struct resource *mem_res;
        int irq;
+       int sdio_irq;
        unsigned char bus_mode;
 
 #define DAVINCI_MMC_DATADIR_NONE       0
@@ -950,6 +951,30 @@ static irqreturn_t mmc_davinci_irq(int i
        return IRQ_HANDLED;
 }
 
+static irqreturn_t mmc_davinci_sdio_irq(int irq, void *dev_id)
+{
+       struct mmc_davinci_host *host = dev_id;
+       u32                     sdiost;
+
+       sdiost = readl(host->base + DAVINCI_SDIOST);
+       if (sdiost & BIT(0))
+               mmc_signal_sdio_irq(host->mmc);
+       return IRQ_HANDLED;
+}
+
+static void mmc_davinci_enable_sdio_irq(struct mmc_host *mmc, int enable)
+{
+       struct mmc_davinci_host *host = mmc_priv(mmc);
+       u32                     sdioen;
+
+       sdioen = readl(host->base + DAVINCI_SDIOEN);
+       if (!enable)
+               sdioen &= ~BIT(0);
+       else
+               sdioen |= BIT(0);
+       writel(sdioen, host->base + DAVINCI_SDIOEN);
+}
+
 static int mmc_davinci_get_cd(struct mmc_host *mmc)
 {
        struct platform_device *pdev = to_platform_device(mmc->parent);
@@ -975,6 +1000,7 @@ static struct mmc_host_ops mmc_davinci_o
        .set_ios        = mmc_davinci_set_ios,
        .get_cd         = mmc_davinci_get_cd,
        .get_ro         = mmc_davinci_get_ro,
+       .enable_sdio_irq = mmc_davinci_enable_sdio_irq,
 };
 
 static void __init init_mmcsd_host(struct mmc_davinci_host *host)
@@ -995,6 +1021,8 @@ static void __init init_mmcsd_host(struc
        writel(0xFFFF, host->base + DAVINCI_MMCTOR);
        writel(0xFFFF, host->base + DAVINCI_MMCTOD);
 
+       writel(0, host->base + DAVINCI_SDIOEN);
+
        writel(readl(host->base + DAVINCI_MMCCTL) & ~MMCCTL_DATRST,
                host->base + DAVINCI_MMCCTL);
        writel(readl(host->base + DAVINCI_MMCCTL) & ~MMCCTL_CMDRST,
@@ -1069,9 +1097,24 @@ static int __init davinci_mmcsd_probe(st
        /* REVISIT:  someday, support IRQ-driven card detection.  */
        mmc->caps |= MMC_CAP_NEEDS_POLL;
 
-       if (!pdata || pdata->wires == 4 || pdata->wires == 0)
+       if (!pdata || pdata->wires == 4 || pdata->wires == 0) {
                mmc->caps |= MMC_CAP_4_BIT_DATA;
 
+               /* for now, no support for IRQs (on DAT1) except
+                * when 4-wire mode is supported.
+                * REVISIT there's a DAT2 read-wait IRQ too ...
+                */
+               host->sdio_irq = platform_get_irq(pdev, 1);
+               if (host->sdio_irq > 0) {
+                       ret = request_irq(host->sdio_irq,
+                               mmc_davinci_sdio_irq, 0,
+                               mmc_hostname(mmc), host);
+                       if (ret == 0)
+                               mmc->caps |= MMC_CAP_SDIO_IRQ;
+               }
+       }
+
+
        mmc->ops = &mmc_davinci_ops;
        mmc->f_min = 312500;
        mmc->f_max = 52000000;  /* MMCplus @52 MHz; SDHC @50 MHz */
@@ -1144,6 +1187,9 @@ static int __exit davinci_mmcsd_remove(s
 
        platform_set_drvdata(pdev, NULL);
        if (host) {
+               if (host->mmc->caps & MMC_CAP_SDIO_IRQ)
+                       free_irq(host->sdio_irq, host);
+
                mmc_remove_host(host->mmc);
                free_irq(host->irq, host);
 

_______________________________________________
Davinci-linux-open-source mailing list
[email protected]
http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source

Reply via email to