From a8ee32310d3ed6fe66e639314ccae72d2fbbc886 Mon Sep 17 00:00:00 2001
From: warmcat <andy@warmcat.com>
Date: Sun, 13 Apr 2008 07:25:50 +0100
Subject: [PATCH] fix-glamo-mci-fake-reset-opcode-in-suspend.patch

---
 arch/arm/mach-s3c2440/mach-gta02.c |    4 ++--
 drivers/mfd/glamo/glamo-core.c     |   16 +++++++++-------
 drivers/mfd/glamo/glamo-mci.c      |   29 +++++++++++++++++++++--------
 3 files changed, 32 insertions(+), 17 deletions(-)

diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
index 750fd97..f18c8fd 100644
--- a/arch/arm/mach-s3c2440/mach-gta02.c
+++ b/arch/arm/mach-s3c2440/mach-gta02.c
@@ -1281,6 +1281,8 @@ static void __init gta02_machine_init(void)
 		s3c2410_gpio_setpin(GTA02_GPIO_nWLAN_RESET, 1);
 		break;
 	}
+	mangle_glamo_res_by_system_rev();
+	platform_device_register(&gta02_glamo_dev);
 
 	platform_device_register(&s3c_device_spi_acc);
 	platform_device_register(&gta01_button_dev);
@@ -1291,8 +1293,6 @@ static void __init gta02_machine_init(void)
 	platform_device_register(&gta01_led_dev);
 	platform_device_register(&gta02_led_dev);
 
-	mangle_glamo_res_by_system_rev();
-	platform_device_register(&gta02_glamo_dev);
 
 	platform_device_register(&gta02_sdio_dev);
 
diff --git a/drivers/mfd/glamo/glamo-core.c b/drivers/mfd/glamo/glamo-core.c
index 2076e61..4d8e47f 100644
--- a/drivers/mfd/glamo/glamo-core.c
+++ b/drivers/mfd/glamo/glamo-core.c
@@ -822,6 +822,8 @@ static void glamo_power(struct glamo_core *glamo,
 {
 	spin_lock(&glamo->lock);
 
+	dev_dbg(&glamo->pdev->dev, "***** glamo_power -> %d\n", new_state);
+
 	switch (new_state) {
 	case GLAMO_POWER_ON:
 		/* power up PLL1 and PLL2 */
@@ -1026,13 +1028,6 @@ static int __init glamo_probe(struct platform_device *pdev)
 	glamo_mci_def_pdata.glamo_irq_is_wired =
 					glamo->pdata->glamo_irq_is_wired;
 
-	glamo_mmc_dev.dev.parent = &pdev->dev;
-	/* we need it later to give to the engine enable and disable */
-	glamo_mci_def_pdata.pglamo = glamo;
-	mangle_mem_resources(glamo_mmc_dev.resource,
-			     glamo_mmc_dev.num_resources, glamo->mem);
-	platform_device_register(&glamo_mmc_dev);
-
 	glamo_2d_dev.dev.parent = &pdev->dev;
 	mangle_mem_resources(glamo_2d_dev.resource,
 			     glamo_2d_dev.num_resources, glamo->mem);
@@ -1065,6 +1060,13 @@ static int __init glamo_probe(struct platform_device *pdev)
 	glamo_spigpio_dev.dev.platform_data = glamo->pdata->spigpio_info;
 	platform_device_register(&glamo_spigpio_dev);
 
+	glamo_mmc_dev.dev.parent = &pdev->dev;
+	/* we need it later to give to the engine enable and disable */
+	glamo_mci_def_pdata.pglamo = glamo;
+	mangle_mem_resources(glamo_mmc_dev.resource,
+			     glamo_mmc_dev.num_resources, glamo->mem);
+	platform_device_register(&glamo_mmc_dev);
+
 	/* only request the generic, hostbus and memory controller MMIO */
 	glamo->mem = request_mem_region(glamo->mem->start,
 					GLAMO_REGOFS_VIDCAP, "glamo-core");
diff --git a/drivers/mfd/glamo/glamo-mci.c b/drivers/mfd/glamo/glamo-mci.c
index bbbbe4d..d8847c5 100644
--- a/drivers/mfd/glamo/glamo-mci.c
+++ b/drivers/mfd/glamo/glamo-mci.c
@@ -405,11 +405,11 @@ static void glamo_mci_send_request(struct mmc_host *mmc)
 	u16 * reg_resp = (u16 *)(host->base + GLAMO_REG_MMC_CMD_RSP1);
 	u16 status;
 	int n;
+	int timeout = 100000000;
 
 	if (host->suspending) {
-		cmd->error = -EIO;
-		if (cmd->data)
-			cmd->data->error = -EIO;
+		dev_err(&host->pdev->dev, "faking cmd %d "
+			"during suspend\n", cmd->opcode);
 		mmc_request_done(mmc, mrq);
 		return;
 	}
@@ -502,10 +502,23 @@ static void glamo_mci_send_request(struct mmc_host *mmc)
 	 * our own INT# line"
 	 */
 	if (!glamo_mci_def_pdata.pglamo->irq_works) {
-		/* we have faith we will get an "interrupt"... */
-		while (!(readw_dly(glamo_mci_def_pdata.pglamo->base +
-			 GLAMO_REG_IRQ_STATUS) & GLAMO_IRQ_MMC))
+		/*
+		 * we have faith we will get an "interrupt"...
+		 * but something insane like suspend problems can mean
+		 * we spin here forever, so we timeout after a LONG time
+		 */
+		while ((!(readw_dly(glamo_mci_def_pdata.pglamo->base +
+			 GLAMO_REG_IRQ_STATUS) & GLAMO_IRQ_MMC)) &&
+		       (timeout--))
 			;
+
+		if (timeout < 0) {
+			if (cmd->data->error)
+				cmd->data->error = -ETIMEDOUT;
+			dev_err(&host->pdev->dev, "Payload timeout\n");
+			return;
+		}
+
 		/* yay we are an interrupt controller! -- call the ISR */
 		glamo_mci_irq(IRQ_GLAMO(GLAMO_IRQIDX_MMC),
 			      irq_desc + IRQ_GLAMO(GLAMO_IRQIDX_MMC));
@@ -529,6 +542,7 @@ static void glamo_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 
 static void glamo_mci_reset(struct glamo_mci_host *host)
 {
+	dev_dbg(&host->pdev->dev, "******* glamo_mci_reset\n");
 	/* reset MMC controller */
 	writew_dly(GLAMO_CLOCK_MMC_RESET | GLAMO_CLOCK_MMC_DG_TCLK |
 		   GLAMO_CLOCK_MMC_EN_TCLK | GLAMO_CLOCK_MMC_DG_M9CLK |
@@ -803,8 +817,7 @@ static int glamo_mci_suspend(struct platform_device *dev, pm_message_t state)
 	struct glamo_mci_host 	*host = mmc_priv(mmc);
 
 	host->suspending++;
-
-	return  mmc_suspend_host(mmc, state);
+	return mmc_suspend_host(mmc, state);
 }
 
 static int glamo_mci_resume(struct platform_device *dev)
-- 
1.5.6.5