[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