diff mbox

DM355 SDIO support

Message ID 200907291124.49242.david-b@pacbell.net (mailing list archive)
State Rejected
Headers show

Commit Message

David Brownell July 29, 2009, 6:24 p.m. UTC
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 <phani@embwise.com>

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
diff mbox

Patch

==============
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);