[Gta04-owner] [PATCH] omap-hsmmc: enable sdio interrupt to enhance wifi sdio performance

Andreas Kemnade andreas at kemnade.info
Thu Jun 14 18:49:47 CEST 2012


This patch adds code to enable sdio interrupts.
It is based on f8c08bcf62b09c928217f56dc599c628370aae62
in the 2.6.32 gta04 hw verification kernel by
Phaneendra Kumar <phani at embwise.com>

Some sdio irqs seem to get lost, so I had to include a hack
to also do polling. But that still increases wifi performance.

Signed-off-by: Andreas Kemnade <andreas at kemnade.info>
---
 drivers/mmc/core/sdio_irq.c   |    4 +-
 drivers/mmc/host/omap_hsmmc.c |   60 +++++++++++++++++++++++++++++++++-------
 2 files changed, 51 insertions(+), 13 deletions(-)

diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c
index f573e7f..c2ba323 100644
--- a/drivers/mmc/core/sdio_irq.c
+++ b/drivers/mmc/core/sdio_irq.c
@@ -93,8 +93,8 @@ static int sdio_irq_thread(void *_host)
 	 * hence we poll for them in that case.
 	 */
 	idle_period = msecs_to_jiffies(10);
-	period = (host->caps & MMC_CAP_SDIO_IRQ) ?
-		MAX_SCHEDULE_TIMEOUT : idle_period;
+	period = /* (host->caps & MMC_CAP_SDIO_IRQ) ?
+		MAX_SCHEDULE_TIMEOUT : */ idle_period;
 
 	pr_debug("%s: IRQ thread started (poll period = %lu jiffies)\n",
 		 mmc_hostname(host), period);
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index b13a29a..94a3eb2 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -108,6 +108,10 @@
 #define SRD			(1 << 26)
 #define SOFTRESET		(1 << 1)
 #define RESETDONE		(1 << 0)
+#define CIRQ		(1 << 8)
+#define CIRQ_ENABLE	(1 << 8)
+#define CTPL		(1 << 11)
+#define CLKEXTFREE	(1 << 16)
 
 #define MMC_AUTOSUSPEND_DELAY	100
 #define MMC_TIMEOUT_MS		20
@@ -173,6 +177,7 @@ struct omap_hsmmc_host {
 	int			vdd;
 	int			protect_card;
 	int			reqs_blocked;
+	int			sdio_int;
 	int			use_reg;
 	int			req_in_progress;
 	struct omap_hsmmc_next	next_data;
@@ -746,6 +751,13 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd,
 
 	omap_hsmmc_enable_irq(host, cmd);
 
+	if (host->sdio_int) {
+		OMAP_HSMMC_WRITE(host->base, ISE,
+			(OMAP_HSMMC_READ(host->base, ISE) | CIRQ_ENABLE));
+		OMAP_HSMMC_WRITE(host->base, IE,
+			(OMAP_HSMMC_READ(host->base, IE) | CIRQ_ENABLE));
+	}
+
 	host->response_busy = 0;
 	if (cmd->flags & MMC_RSP_PRESENT) {
 		if (cmd->flags & MMC_RSP_136)
@@ -968,19 +980,20 @@ static inline void omap_hsmmc_reset_controller_fsm(struct omap_hsmmc_host *host,
 static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status)
 {
 	struct mmc_data *data;
-	int end_cmd = 0, end_trans = 0;
-
+	int end_cmd = 0, end_trans = 0, sdio_irq = 0;
+	data = host->data;
+	dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status);
+	if (host->mmc->caps & MMC_CAP_SDIO_IRQ) {
+		if (status & CIRQ) {
+			dev_dbg(mmc_dev(host->mmc), "SDIO Card Interrupt\n");
+			mmc_signal_sdio_irq(host->mmc);
+		}
+	}
 	if (!host->req_in_progress) {
-		do {
-			OMAP_HSMMC_WRITE(host->base, STAT, status);
-			/* Flush posted write */
-			status = OMAP_HSMMC_READ(host->base, STAT);
-		} while (status & INT_EN_MASK);
+		OMAP_HSMMC_WRITE(host->base, STAT, status);
 		return;
 	}
 
-	data = host->data;
-	dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status);
 
 	if (status & ERR) {
 		omap_hsmmc_dbg_report_irq(host, status);
@@ -1027,6 +1040,7 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status)
 			if (host->data)
 				end_trans = 1;
 		}
+
 	}
 
 	OMAP_HSMMC_WRITE(host->base, STAT, status);
@@ -1050,7 +1064,7 @@ static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id)
 		omap_hsmmc_do_irq(host, status);
 		/* Flush posted write */
 		status = OMAP_HSMMC_READ(host->base, STAT);
-	} while (status & INT_EN_MASK);
+	} while (status & (INT_EN_MASK | CIRQ_ENABLE));
 
 	return IRQ_HANDLED;
 }
@@ -1598,6 +1612,25 @@ static void omap_hsmmc_init_card(struct mmc_host *mmc, struct mmc_card *card)
 		mmc_slot(host).init_card(card);
 }
 
+static void omap_hsmmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
+{
+	struct omap_hsmmc_host *host = mmc_priv(mmc);
+
+	host->sdio_int = enable;
+	if (enable) {
+		OMAP_HSMMC_WRITE(host->base, ISE,
+			(OMAP_HSMMC_READ(host->base, ISE) | CIRQ_ENABLE));
+		OMAP_HSMMC_WRITE(host->base, IE,
+			(OMAP_HSMMC_READ(host->base, IE) | CIRQ_ENABLE));
+	} else {
+		OMAP_HSMMC_WRITE(host->base, IE,
+			(OMAP_HSMMC_READ(host->base, IE) & (~CIRQ_ENABLE)));
+		OMAP_HSMMC_WRITE(host->base, ISE,
+			(OMAP_HSMMC_READ(host->base, ISE) & (~CIRQ_ENABLE)));
+	}
+
+}
+
 static void omap_hsmmc_conf_bus_power(struct omap_hsmmc_host *host)
 {
 	u32 hctl, capa, value;
@@ -1654,7 +1687,7 @@ static const struct mmc_host_ops omap_hsmmc_ops = {
 	.get_cd = omap_hsmmc_get_cd,
 	.get_ro = omap_hsmmc_get_ro,
 	.init_card = omap_hsmmc_init_card,
-	/* NYET -- enable_sdio_irq */
+	.enable_sdio_irq = omap_hsmmc_enable_sdio_irq
 };
 
 #ifdef CONFIG_DEBUG_FS
@@ -1845,6 +1878,7 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
 	host->base	= ioremap(host->mapbase, SZ_4K);
 	host->power_mode = MMC_POWER_OFF;
 	host->next_data.cookie = 1;
+	host->sdio_int = 0;
 
 	platform_set_drvdata(pdev, host);
 
@@ -1923,6 +1957,10 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
 
 	mmc->pm_caps = mmc_slot(host).pm_caps;
 
+	mmc->caps |= MMC_CAP_SDIO_IRQ;
+	OMAP_HSMMC_WRITE(host->base, CON,
+			OMAP_HSMMC_READ(host->base, CON) | (CTPL | CLKEXTFREE));
+
 	omap_hsmmc_conf_bus_power(host);
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
-- 
1.7.2.5



More information about the Gta04-owner mailing list