On Wednesday 29 July 2009, Phaneendra kumar wrote:
> This patch will add SDIO support to the DM355 host controller driver.
> 
> I have verified this on DM355 EVM board in both DMA and PIO modes.

The MMC driver isn't specific to that chip.  :)


> And i have used open source libertas driver for verifying the SDIO 
> functionality. 

That seems to be necessary.  Other SDIO hardware isn't very
easy to come by nowadays!


> Signed-off-by: Phaneendra Kumar <[email protected]>

This seems to be missing something basic:  a request_irq() call
for the SDIO interrupt.  See the appended, which is the updated
version of something I sent around several months ago ... hoping
someone had libertas hardware and some test/debug cycles!

Maybe you can combine the two and get code which works more like
it's supposed to work.  I see that you did address the "what if
the interrupt is already triggering" case, for example.

- Dave


==============
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.

# REVISIT -- errata doc, usage note 2.1.5, sez:
#  - issue: must check SDIOIST.IONT and sample SDIOST0.DAT1 to detect
#       level triggered SDIO using edge detect in ctrlr, given races
#       between irq enable at sdio card and (then) controller
#  - before enable:  sample DAT1 (INTPRD=1, DAT1=1)
#       ... may have been raised before enabled in ctrlr
#  - does sdio_irq() clear irq status as it reads it?
#       ... mask irq before signaling irq
---
 drivers/mmc/host/davinci_mmc.c |   53 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 52 insertions(+), 1 deletion(-)

--- a/drivers/mmc/host/davinci_mmc.c
+++ b/drivers/mmc/host/davinci_mmc.c
@@ -163,6 +163,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
@@ -1011,6 +1012,35 @@ 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;
+
+       /* FIXME card may already be issuing (level) IRQ ... so when
+        * enabling, check DAT1 here and handle the case where we won't
+        * trigger since the edge already happened.
+        */
+
+       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);
@@ -1036,6 +1066,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,
 };
 
 /*----------------------------------------------------------------------*/
@@ -1058,6 +1089,8 @@ static void __init init_mmcsd_host(struc
        writel(0x1FFF, 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,
@@ -1132,9 +1165,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;
+               }
+       }
+
+
        host->version = pdata->version;
 
        mmc->ops = &mmc_davinci_ops;
@@ -1215,6 +1263,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