From: Magnus Damm <damm@opensource.se>

Signed-off-by: Magnus Damm <damm@opensource.se>
---

 arch/sh/kernel/cpu/sh4a/setup-sh7724.c |    4 +--
 drivers/mfd/sh_mobile_sdhi.c           |    2 -
 drivers/mmc/host/tmio_mmc.c            |   41 +++++++++++++++++++++++++++++++-
 drivers/mmc/host/tmio_mmc.h            |    2 +
 4 files changed, 45 insertions(+), 4 deletions(-)

--- 0001/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
+++ work/arch/sh/kernel/cpu/sh4a/setup-sh7724.c	2010-04-27 19:45:20.000000000 +0900
@@ -1059,7 +1059,7 @@ static struct intc_group groups[] __init
 static struct intc_mask_reg mask_registers[] __initdata = {
 	{ 0xa4080080, 0xa40800c0, 8, /* IMR0 / IMCR0 */
 	  { 0, TMU1_TUNI2, TMU1_TUNI1, TMU1_TUNI0,
-	    0, DISABLED, ENABLED, ENABLED } },
+	    0, ENABLED, ENABLED, ENABLED } },
 	{ 0xa4080084, 0xa40800c4, 8, /* IMR1 / IMCR1 */
 	  { VIO_VOU, VIO_VEU1, VIO_BEU0, VIO_CEU0,
 	    DMAC0A_DEI3, DMAC0A_DEI2, DMAC0A_DEI1, DMAC0A_DEI0 } },
@@ -1081,7 +1081,7 @@ static struct intc_mask_reg mask_registe
 	  { I2C0_DTEI, I2C0_WAITI, I2C0_TACKI, I2C0_ALI,
 	    I2C1_DTEI, I2C1_WAITI, I2C1_TACKI, I2C1_ALI } },
 	{ 0xa40800a0, 0xa40800e0, 8, /* IMR8 / IMCR8 */
-	  { DISABLED, DISABLED, ENABLED, ENABLED,
+	  { DISABLED, ENABLED, ENABLED, ENABLED,
 	    0, 0, SCIFA5, FSI } },
 	{ 0xa40800a4, 0xa40800e4, 8, /* IMR9 / IMCR9 */
 	  { 0, 0, 0, CMT, 0, USB1, USB0, 0 } },
--- 0001/drivers/mfd/sh_mobile_sdhi.c
+++ work/drivers/mfd/sh_mobile_sdhi.c	2010-04-27 19:45:20.000000000 +0900
@@ -98,7 +98,7 @@ static int __init sh_mobile_sdhi_probe(s
 
 	priv->mmc_data.hclk = clk_get_rate(priv->clk);
 	priv->mmc_data.set_pwr = sh_mobile_sdhi_set_pwr;
-	priv->mmc_data.capabilities = MMC_CAP_MMC_HIGHSPEED;
+	priv->mmc_data.capabilities = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SDIO_IRQ;
 
 	memcpy(&priv->cell_mmc, &sh_mobile_sdhi_cell, sizeof(priv->cell_mmc));
 	priv->cell_mmc.driver_data = &priv->mmc_data;
--- 0001/drivers/mmc/host/tmio_mmc.c
+++ work/drivers/mmc/host/tmio_mmc.c	2010-04-27 19:45:49.000000000 +0900
@@ -30,6 +30,7 @@
 #include <linux/device.h>
 #include <linux/delay.h>
 #include <linux/mmc/host.h>
+#include <linux/mmc/sdio.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/tmio.h>
 
@@ -54,8 +55,10 @@ static void tmio_mmc_set_clock(struct tm
 
 static void tmio_mmc_clk_stop(struct tmio_mmc_host *host)
 {
+#if 0
 	sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0000);
 	msleep(10);
+#endif
 	sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, ~0x0100 &
 		sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
 	msleep(10);
@@ -66,8 +69,10 @@ static void tmio_mmc_clk_start(struct tm
 	sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, 0x0100 |
 		sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
 	msleep(10);
+#if 0
 	sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0100);
 	msleep(10);
+#endif
 }
 
 static void reset(struct tmio_mmc_host *host)
@@ -298,9 +303,26 @@ static irqreturn_t tmio_mmc_irq(int irq,
 {
 	struct tmio_mmc_host *host = devid;
 	unsigned int ireg, irq_mask, status;
+	unsigned int sdio_ireg, sdio_irq_mask, sdio_status;
 
 	pr_debug("MMC IRQ begin\n");
 
+	sdio_ireg = 0;
+	if (host->mmc->caps & MMC_CAP_SDIO_IRQ) {
+		sdio_status = sd_ctrl_read16(host, CTL_SDIO_STATUS);
+		sdio_irq_mask = sd_ctrl_read16(host, CTL_SDIO_IRQ_MASK);
+		sdio_ireg = sdio_status & 0xc007 & ~sdio_irq_mask;
+
+		if (sdio_ireg)
+			printk("xxxxxxxxxxxxxx sdio 0x%08x\n", sdio_ireg);
+
+		sd_ctrl_write16(host, CTL_SDIO_STATUS, sdio_status & ~0xc007);
+
+		if (sdio_ireg & 1) {
+			mmc_signal_sdio_irq(host->mmc);
+		}
+	}
+
 	status = sd_ctrl_read32(host, CTL_STATUS);
 	irq_mask = sd_ctrl_read32(host, CTL_IRQ_MASK);
 	ireg = status & TMIO_MASK_IRQ & ~irq_mask;
@@ -308,7 +330,7 @@ static irqreturn_t tmio_mmc_irq(int irq,
 	pr_debug_status(status);
 	pr_debug_status(ireg);
 
-	if (!ireg) {
+	if (!ireg && !sdio_ireg) {
 		disable_mmc_irqs(host, status & ~irq_mask);
 
 		pr_debug("tmio_mmc: Spurious irq, disabling! "
@@ -462,10 +484,27 @@ static int tmio_mmc_get_ro(struct mmc_ho
 	return (sd_ctrl_read16(host, CTL_STATUS) & TMIO_STAT_WRPROTECT) ? 0 : 1;
 }
 
+static void tmio_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
+{
+	struct tmio_mmc_host *host = mmc_priv(mmc);
+
+	printk("enable_sdio_irq %d\n", enable);
+
+	if (enable) {
+		sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0001);
+		sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, 0x0006);
+	} else {
+		sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, 0xc007);
+		sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0000);
+	}
+
+}
+
 static struct mmc_host_ops tmio_mmc_ops = {
 	.request	= tmio_mmc_request,
 	.set_ios	= tmio_mmc_set_ios,
 	.get_ro         = tmio_mmc_get_ro,
+	.enable_sdio_irq = tmio_mmc_enable_sdio_irq,
 };
 
 #ifdef CONFIG_PM
--- 0001/drivers/mmc/host/tmio_mmc.h
+++ work/drivers/mmc/host/tmio_mmc.h	2010-04-27 19:45:20.000000000 +0900
@@ -24,6 +24,8 @@
 #define CTL_SD_ERROR_DETAIL_STATUS 0x2c
 #define CTL_SD_DATA_PORT 0x30
 #define CTL_TRANSACTION_CTL 0x34
+#define CTL_SDIO_STATUS 0x36
+#define CTL_SDIO_IRQ_MASK 0x38
 #define CTL_RESET_SD 0xe0
 #define CTL_SDIO_REGS 0x100
 #define CTL_CLK_AND_WAIT_CTL 0x138
