diff mbox

mmci-omap regressions

Message ID 20091021211506.GA6498@localhost.localdomain (mailing list archive)
State Awaiting Upstream, archived
Delegated to: Tony Lindgren
Headers show

Commit Message

Ladislav.Michl@seznam.cz Oct. 21, 2009, 9:15 p.m. UTC
None
diff mbox

Patch

diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index 5d773b8..0bcd6b0 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -123,15 +123,16 @@  struct mmc_omap_host {
 	struct mmc_data *	data;
 	struct mmc_host *	mmc;
 	struct device *		dev;
-	unsigned char		id; /* 16xx chips have 2 MMC blocks */
 	struct clk *		iclk;
 	struct clk *		fclk;
 	struct resource		*mem_res;
 	void __iomem		*virt_base;
 	unsigned int		phys_base;
 	int			irq;
+	unsigned char		id; /* 16xx chips have 2 MMC blocks */
 	unsigned char		bus_mode;
 	unsigned char		hw_bus_mode;
+	unsigned char		power_mode;
 
 	struct work_struct	cmd_abort_work;
 	unsigned		abort:1;
@@ -1233,7 +1234,7 @@  static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	struct mmc_omap_slot *slot = mmc_priv(mmc);
 	struct mmc_omap_host *host = slot->host;
 	int i, dsor;
-	int clk_enabled;
+	int clk_enabled, init_stream;
 
 	mmc_omap_select_slot(slot, 0);
 
@@ -1243,20 +1244,27 @@  static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 		slot->vdd = ios->vdd;
 
 	clk_enabled = 0;
+	init_stream = 0;
 	switch (ios->power_mode) {
 	case MMC_POWER_OFF:
+		printk("MMC_POWER_OFF\n");
 		mmc_omap_set_power(slot, 0, ios->vdd);
 		break;
 	case MMC_POWER_UP:
+		printk("MMC_POWER_UP\n");
 		/* Cannot touch dsor yet, just power up MMC */
 		mmc_omap_set_power(slot, 1, ios->vdd);
+		host->power_mode = ios->power_mode;
 		goto exit;
 	case MMC_POWER_ON:
+		printk("MMC_POWER_ON\n");
 		mmc_omap_fclk_enable(host, 1);
 		clk_enabled = 1;
-		dsor |= 1 << 11;
+		if (host->power_mode != MMC_POWER_ON)
+			init_stream = 1;
 		break;
 	}
+	host->power_mode = ios->power_mode;
 
 	if (slot->bus_mode != ios->bus_mode) {
 		if (slot->pdata->set_bus_mode != NULL)
@@ -1269,12 +1277,15 @@  static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	 * goes somehow out of sync, and the POW bit is not being set,
 	 * which results in the while loop below getting stuck.
 	 * Writing to the CON register twice seems to do the trick. */
+	if (ios->power_mode == MMC_POWER_ON)
+		dsor |= 1 << 11;
+	printk("MMC dsor: %x\n", dsor);
 	for (i = 0; i < 2; i++)
 		OMAP_MMC_WRITE(host, CON, dsor);
 	slot->saved_con = dsor;
-	if (ios->power_mode == MMC_POWER_ON) {
+	if (init_stream) {
 		/* worst case at 400kHz, 80 cycles makes 200 microsecs */
-		int usecs = 250;
+		int usecs = 512;
 
 		/* Send clock cycles, poll completion */
 		OMAP_MMC_WRITE(host, IE, 0);
@@ -1285,8 +1296,8 @@  static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 			usecs--;
 		}
 		OMAP_MMC_WRITE(host, STAT, 1);
+		printk("time elapsed: %dus\n", 512 - usecs);
 	}
-
 exit:
 	mmc_omap_release_slot(slot, clk_enabled);
 }
@@ -1445,6 +1456,7 @@  static int __init mmc_omap_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, host);
 
 	host->id = pdev->id;
+	host->power_mode = -1;
 	host->mem_res = res;
 	host->irq = irq;
 
@@ -1459,8 +1471,10 @@  static int __init mmc_omap_probe(struct platform_device *pdev)
 		goto err_ioremap;
 
 	host->iclk = clk_get(&pdev->dev, "ick");
-	if (IS_ERR(host->iclk))
+	if (IS_ERR(host->iclk)) {
+		ret = PTR_ERR(host->iclk);
 		goto err_free_mmc_host;
+	}
 	clk_enable(host->iclk);
 
 	host->fclk = clk_get(&pdev->dev, "fck");
@@ -1500,10 +1514,8 @@  err_free_irq:
 err_free_fclk:
 	clk_put(host->fclk);
 err_free_iclk:
-	if (host->iclk != NULL) {
-		clk_disable(host->iclk);
-		clk_put(host->iclk);
-	}
+	clk_disable(host->iclk);
+	clk_put(host->iclk);
 err_free_mmc_host:
 	iounmap(host->virt_base);
 err_ioremap:
@@ -1529,6 +1541,7 @@  static int mmc_omap_remove(struct platform_device *pdev)
 		host->pdata->cleanup(&pdev->dev);
 
 	mmc_omap_fclk_enable(host, 0);
+	free_irq(host->irq, host);
 	clk_put(host->fclk);
 	clk_disable(host->iclk);
 	clk_put(host->iclk);