public inbox for linux-omap@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/9] OMAP: HSMMC: Patches
@ 2008-11-21  9:23 Adrian Hunter
  2008-11-21  9:37 ` Adrian Hunter
  0 siblings, 1 reply; 17+ messages in thread
From: Adrian Hunter @ 2008-11-21  9:23 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: linux-omap@vger.kernel.org Mailing List

Hi

OMAP HSMMC is not ready for mainline, but development is ongoing.

In the meantime these patches are best posted and applied via
omap mailing list and tree.

Regards
Adrian

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 0/9] OMAP: HSMMC: Patches
  2008-11-21  9:23 [PATCH 0/9] OMAP: HSMMC: Patches Adrian Hunter
@ 2008-11-21  9:37 ` Adrian Hunter
  2008-11-21  9:43   ` [PATCH 1/9] OMAP: HSMMC: Make driver support dynamic idle Adrian Hunter
                     ` (9 more replies)
  0 siblings, 10 replies; 17+ messages in thread
From: Adrian Hunter @ 2008-11-21  9:37 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: linux-omap@vger.kernel.org Mailing List

Adrian Hunter wrote:
> Hi
> 
> OMAP HSMMC is not ready for mainline, but development is ongoing.
> 
> In the meantime these patches are best posted and applied via
> omap mailing list and tree.
> 
> Regards
> Adrian
> -- 
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

Just realised I forgot the from lines in all those patches - will resend.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 1/9] OMAP: HSMMC: Make driver support dynamic idle
  2008-11-21  9:37 ` Adrian Hunter
@ 2008-11-21  9:43   ` Adrian Hunter
  2008-11-21  9:44   ` [PATCH 2/9] OMAP: HSMMC: Ensure fclk is running before accessing HSMMC registers Adrian Hunter
                     ` (8 subsequent siblings)
  9 siblings, 0 replies; 17+ messages in thread
From: Adrian Hunter @ 2008-11-21  9:43 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: linux-omap@vger.kernel.org Mailing List

From: Amit Kucheria <amit.kucheria@verdurent.com>
Date: Mon, 22 Sep 2008 10:23:09 +0300

Add a timer that is kept active by MMC requests. FCLK is disabled on timeout

Signed-off-by: Amit Kucheria <amit.kucheria@verdurent.com>
---
 drivers/mmc/host/omap_hsmmc.c |   73 +++++++++++++++++++++++++++++++++-------
 1 files changed, 60 insertions(+), 13 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 0df6841..ee21a64 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -121,6 +121,9 @@
 #define OMAP_HSMMC_WRITE(base, reg, val) \
 	__raw_writel((val), (base) + OMAP_HSMMC_##reg)
 
+enum {OFF = 0, ON};
+#define IDLE_TIMEOUT (5*HZ)
+
 struct mmc_omap_host {
 	struct	device		*dev;
 	struct	mmc_host	*mmc;
@@ -148,9 +151,50 @@ struct mmc_omap_host {
 	int			initstr;
 	int			slot_id;
 	int			dbclk_enabled;
+
+	struct timer_list       idle_timer;
+	spinlock_t		clk_lock;     /* for changing enabled state */
+	int			fclk_enabled:1;
+
 	struct	omap_mmc_platform_data	*pdata;
 };
 
+int mmc_omap_fclk_state(struct mmc_omap_host *host, unsigned int state)
+{
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&host->clk_lock, flags);
+	if (host->fclk_enabled != state) {
+		if (state == ON) {
+			if (host->fclk_enabled == OFF) {
+				ret = clk_enable(host->fclk);
+				if (ret != 0)
+					return ret;
+				dev_dbg(mmc_dev(host->mmc),
+					"mmc_fclk: enabled\n");
+			}
+			/* Revisit: Change the timer bump based on real
+			   MMC usage characteristics */
+			mod_timer(&host->idle_timer, jiffies + IDLE_TIMEOUT);
+		} else {
+			clk_disable(host->fclk);
+			dev_dbg(mmc_dev(host->mmc), "mmc_fclk: disabled\n");
+			del_timer(&host->idle_timer);
+		}
+		host->fclk_enabled = state;
+	}
+	spin_unlock_irqrestore(&host->clk_lock, flags);
+	return 0;
+}
+
+static void mmc_omap_idle_timer(unsigned long data)
+{
+	struct mmc_omap_host *host = (struct mmc_omap_host *) data;
+
+	mmc_omap_fclk_state(host, OFF);
+}
+
 /*
  * Stop clock to the card
  */
@@ -457,7 +501,7 @@ static int omap_mmc_switch_opcond(struct mmc_omap_host *host, int vdd)
 	int ret;
 
 	/* Disable the clocks */
-	clk_disable(host->fclk);
+	mmc_omap_fclk_state(host, OFF);
 	clk_disable(host->iclk);
 	clk_disable(host->dbclk);
 
@@ -471,7 +515,7 @@ static int omap_mmc_switch_opcond(struct mmc_omap_host *host, int vdd)
 	if (ret != 0)
 		goto err;
 
-	clk_enable(host->fclk);
+	mmc_omap_fclk_state(host, ON);
 	clk_enable(host->iclk);
 	clk_enable(host->dbclk);
 
@@ -742,10 +786,10 @@ static void omap_mmc_request(struct mmc_host *mmc, struct mmc_request *req)
 	WARN_ON(host->mrq != NULL);
 	host->mrq = req;
 	mmc_omap_prepare_data(host, req);
+	mmc_omap_fclk_state(host, ON);
 	mmc_omap_start_command(host, req->cmd, req->data);
 }
 
-
 /* Routine to configure clock values. Exposed API to core */
 static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
@@ -824,6 +868,7 @@ static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
 		OMAP_HSMMC_WRITE(host->base, CON,
 				OMAP_HSMMC_READ(host->base, CON) | OD);
+
 }
 
 static int omap_hsmmc_get_cd(struct mmc_host *mmc)
@@ -860,7 +905,7 @@ static int __init omap_mmc_probe(struct platform_device *pdev)
 	struct mmc_host *mmc;
 	struct mmc_omap_host *host = NULL;
 	struct resource *res;
-	int ret = 0, irq;
+	int ret = 0, irq, reg;
 	u32 hctl, capa;
 
 	if (pdata == NULL) {
@@ -925,14 +970,17 @@ static int __init omap_mmc_probe(struct platform_device *pdev)
 		goto err1;
 	}
 
-	if (clk_enable(host->fclk) != 0) {
+	spin_lock_init(&host->clk_lock);
+	setup_timer(&host->idle_timer, mmc_omap_idle_timer,
+		    (unsigned long) host);
+
+	if (mmc_omap_fclk_state(host, ON) != 0) {
 		clk_put(host->iclk);
 		clk_put(host->fclk);
 		goto err1;
 	}
-
 	if (clk_enable(host->iclk) != 0) {
-		clk_disable(host->fclk);
+		mmc_omap_fclk_state(host, OFF);
 		clk_put(host->iclk);
 		clk_put(host->fclk);
 		goto err1;
@@ -1047,7 +1095,7 @@ err_irq_cd:
 err_irq_cd_init:
 	free_irq(host->irq, host);
 err_irq:
-	clk_disable(host->fclk);
+	mmc_omap_fclk_state(host, OFF);
 	clk_disable(host->iclk);
 	clk_put(host->fclk);
 	clk_put(host->iclk);
@@ -1096,7 +1144,7 @@ static int omap_mmc_remove(struct platform_device *pdev)
 			free_irq(mmc_slot(host).card_detect_irq, host);
 		flush_scheduled_work();
 
-		clk_disable(host->fclk);
+		mmc_omap_fclk_state(host, OFF);
 		clk_disable(host->iclk);
 		clk_put(host->fclk);
 		clk_put(host->iclk);
@@ -1149,7 +1197,7 @@ static int omap_mmc_suspend(struct platform_device *pdev, pm_message_t state)
 					| SDBP);
 			}
 
-			clk_disable(host->fclk);
+			mmc_omap_fclk_state(host, OFF);
 			clk_disable(host->iclk);
 			clk_disable(host->dbclk);
 		}
@@ -1169,13 +1217,12 @@ static int omap_mmc_resume(struct platform_device *pdev)
 
 	if (host) {
 
-		ret = clk_enable(host->fclk);
-		if (ret)
+		if (mmc_omap_fclk_state(host, ON) != 0)
 			goto clk_en_err;
 
 		ret = clk_enable(host->iclk);
 		if (ret) {
-			clk_disable(host->fclk);
+			mmc_omap_fclk_state(host, OFF);
 			clk_put(host->fclk);
 			goto clk_en_err;
 		}
-- 
1.5.4.3


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 2/9] OMAP: HSMMC: Ensure fclk is running before accessing HSMMC registers
  2008-11-21  9:37 ` Adrian Hunter
  2008-11-21  9:43   ` [PATCH 1/9] OMAP: HSMMC: Make driver support dynamic idle Adrian Hunter
@ 2008-11-21  9:44   ` Adrian Hunter
  2008-11-21  9:45   ` [PATCH 3/9] OMAP: HSMMC: Make fclk disable request driven Adrian Hunter
                     ` (7 subsequent siblings)
  9 siblings, 0 replies; 17+ messages in thread
From: Adrian Hunter @ 2008-11-21  9:44 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: linux-omap@vger.kernel.org Mailing List

From: Jarkko Lavinen <jarkko.lavinen@nokia.com>
Date: Fri, 24 Oct 2008 16:03:23 +0300

Signed-off-by: Jarkko Lavinen <jarkko.lavinen@nokia.com>
---
 drivers/mmc/host/omap_hsmmc.c |   32 ++++++++++++++++++++------------
 1 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index ee21a64..2eed691 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -154,26 +154,24 @@ struct mmc_omap_host {
 
 	struct timer_list       idle_timer;
 	spinlock_t		clk_lock;     /* for changing enabled state */
-	int			fclk_enabled:1;
+	unsigned int		fclk_enabled:1;
 
 	struct	omap_mmc_platform_data	*pdata;
 };
 
-int mmc_omap_fclk_state(struct mmc_omap_host *host, unsigned int state)
+static int mmc_omap_fclk_state(struct mmc_omap_host *host, unsigned int state)
 {
 	unsigned long flags;
-	int ret;
+	int ret = 0;
 
 	spin_lock_irqsave(&host->clk_lock, flags);
 	if (host->fclk_enabled != state) {
 		if (state == ON) {
-			if (host->fclk_enabled == OFF) {
-				ret = clk_enable(host->fclk);
-				if (ret != 0)
-					return ret;
-				dev_dbg(mmc_dev(host->mmc),
-					"mmc_fclk: enabled\n");
-			}
+			ret = clk_enable(host->fclk);
+			if (ret != 0)
+				goto err_out;
+
+			dev_dbg(mmc_dev(host->mmc), "mmc_fclk: enabled\n");
 			/* Revisit: Change the timer bump based on real
 			   MMC usage characteristics */
 			mod_timer(&host->idle_timer, jiffies + IDLE_TIMEOUT);
@@ -184,8 +182,10 @@ int mmc_omap_fclk_state(struct mmc_omap_host *host, unsigned int state)
 		}
 		host->fclk_enabled = state;
 	}
+
+err_out:
 	spin_unlock_irqrestore(&host->clk_lock, flags);
-	return 0;
+	return ret;
 }
 
 static void mmc_omap_idle_timer(unsigned long data)
@@ -557,6 +557,7 @@ static void mmc_omap_detect(struct work_struct *work)
 						mmc_carddetect_work);
 
 	sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch");
+	mmc_omap_fclk_state(host, ON);
 	if (host->carddetect) {
 		if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) {
 			/*
@@ -785,8 +786,8 @@ static void omap_mmc_request(struct mmc_host *mmc, struct mmc_request *req)
 
 	WARN_ON(host->mrq != NULL);
 	host->mrq = req;
-	mmc_omap_prepare_data(host, req);
 	mmc_omap_fclk_state(host, ON);
+	mmc_omap_prepare_data(host, req);
 	mmc_omap_start_command(host, req->cmd, req->data);
 }
 
@@ -798,6 +799,8 @@ static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	unsigned long regval;
 	unsigned long timeout;
 
+	mmc_omap_fclk_state(host, ON);
+
 	switch (ios->power_mode) {
 	case MMC_POWER_OFF:
 		mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0);
@@ -869,6 +872,8 @@ static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 		OMAP_HSMMC_WRITE(host->base, CON,
 				OMAP_HSMMC_READ(host->base, CON) | OD);
 
+	if (ios->power_mode == MMC_POWER_OFF)
+		mmc_omap_fclk_state(host, OFF);
 }
 
 static int omap_hsmmc_get_cd(struct mmc_host *mmc)
@@ -1120,6 +1125,7 @@ static int omap_mmc_remove(struct platform_device *pdev)
 	struct resource *res;
 	u16 vdd = 0;
 
+	mmc_omap_fclk_state(host, ON);
 	if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) {
 	/*
 	 * Set the vdd back to 3V,
@@ -1170,6 +1176,8 @@ static int omap_mmc_suspend(struct platform_device *pdev, pm_message_t state)
 		return 0;
 
 	if (host) {
+		mmc_omap_fclk_state(host, ON);
+
 		ret = mmc_suspend_host(host->mmc, state);
 		if (ret == 0) {
 			host->suspended = 1;
-- 
1.5.4.3


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 3/9] OMAP: HSMMC: Make fclk disable request driven.
  2008-11-21  9:37 ` Adrian Hunter
  2008-11-21  9:43   ` [PATCH 1/9] OMAP: HSMMC: Make driver support dynamic idle Adrian Hunter
  2008-11-21  9:44   ` [PATCH 2/9] OMAP: HSMMC: Ensure fclk is running before accessing HSMMC registers Adrian Hunter
@ 2008-11-21  9:45   ` Adrian Hunter
  2008-11-21  9:46   ` [PATCH 4/9] OMAP: HSMMC: Fix suspend/resume for MMCHS2 Adrian Hunter
                     ` (6 subsequent siblings)
  9 siblings, 0 replies; 17+ messages in thread
From: Adrian Hunter @ 2008-11-21  9:45 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: linux-omap@vger.kernel.org Mailing List

From: Jarkko Lavinen <jarkko.lavinen@nokia.com>
Date: Fri, 24 Oct 2008 16:30:26 +0300

Start idle timer only at the end of request or request like operation
such card detect, set_ios, probe, or resume. This will ensure the fclk is
disable quickly after the operation is done, but never too early.

Signed-off-by: Jarkko Lavinen <jarkko.lavinen@nokia.com>
---
 drivers/mmc/host/omap_hsmmc.c |   15 ++++++++++-----
 1 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 2eed691..a134f76 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -122,7 +122,7 @@
 	__raw_writel((val), (base) + OMAP_HSMMC_##reg)
 
 enum {OFF = 0, ON};
-#define IDLE_TIMEOUT (5*HZ)
+#define IDLE_TIMEOUT (jiffies_to_msecs(10))
 
 struct mmc_omap_host {
 	struct	device		*dev;
@@ -165,6 +165,7 @@ static int mmc_omap_fclk_state(struct mmc_omap_host *host, unsigned int state)
 	int ret = 0;
 
 	spin_lock_irqsave(&host->clk_lock, flags);
+	del_timer(&host->idle_timer);
 	if (host->fclk_enabled != state) {
 		if (state == ON) {
 			ret = clk_enable(host->fclk);
@@ -172,13 +173,9 @@ static int mmc_omap_fclk_state(struct mmc_omap_host *host, unsigned int state)
 				goto err_out;
 
 			dev_dbg(mmc_dev(host->mmc), "mmc_fclk: enabled\n");
-			/* Revisit: Change the timer bump based on real
-			   MMC usage characteristics */
-			mod_timer(&host->idle_timer, jiffies + IDLE_TIMEOUT);
 		} else {
 			clk_disable(host->fclk);
 			dev_dbg(mmc_dev(host->mmc), "mmc_fclk: disabled\n");
-			del_timer(&host->idle_timer);
 		}
 		host->fclk_enabled = state;
 	}
@@ -335,6 +332,7 @@ mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data)
 
 	if (!data->stop) {
 		host->mrq = NULL;
+		mod_timer(&host->idle_timer, jiffies + IDLE_TIMEOUT);
 		mmc_request_done(host->mmc, data->mrq);
 		return;
 	}
@@ -363,6 +361,7 @@ mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd)
 	}
 	if (host->data == NULL || cmd->error) {
 		host->mrq = NULL;
+		mod_timer(&host->idle_timer, jiffies + IDLE_TIMEOUT);
 		mmc_request_done(host->mmc, cmd->mrq);
 	}
 }
@@ -575,6 +574,7 @@ static void mmc_omap_detect(struct work_struct *work)
 		while (OMAP_HSMMC_READ(host->base, SYSCTL) & SRD) ;
 		mmc_detect_change(host->mmc, (HZ * 50) / 1000);
 	}
+	mod_timer(&host->idle_timer, jiffies + IDLE_TIMEOUT);
 }
 
 /*
@@ -874,6 +874,8 @@ static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 
 	if (ios->power_mode == MMC_POWER_OFF)
 		mmc_omap_fclk_state(host, OFF);
+	else
+		mod_timer(&host->idle_timer, jiffies + IDLE_TIMEOUT);
 }
 
 static int omap_hsmmc_get_cd(struct mmc_host *mmc)
@@ -1088,6 +1090,7 @@ static int __init omap_mmc_probe(struct platform_device *pdev)
 		if (ret < 0)
 			goto err_cover_switch;
 	}
+	mod_timer(&host->idle_timer, jiffies + IDLE_TIMEOUT);
 
 	return 0;
 
@@ -1250,6 +1253,8 @@ static int omap_mmc_resume(struct platform_device *pdev)
 		ret = mmc_resume_host(host->mmc);
 		if (ret == 0)
 			host->suspended = 0;
+
+		mod_timer(&host->idle_timer, jiffies + IDLE_TIMEOUT);
 	}
 
 	return ret;
-- 
1.5.4.3


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 4/9] OMAP: HSMMC: Fix suspend/resume for MMCHS2
  2008-11-21  9:37 ` Adrian Hunter
                     ` (2 preceding siblings ...)
  2008-11-21  9:45   ` [PATCH 3/9] OMAP: HSMMC: Make fclk disable request driven Adrian Hunter
@ 2008-11-21  9:46   ` Adrian Hunter
  2008-11-21  9:47   ` [PATCH 5/9] OMAP: HSMMC: Fix oops in omap_mmc_remove Adrian Hunter
                     ` (5 subsequent siblings)
  9 siblings, 0 replies; 17+ messages in thread
From: Adrian Hunter @ 2008-11-21  9:46 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: linux-omap@vger.kernel.org Mailing List

From: Jarkko Lavinen <jarkko.lavinen@nokia.com>
Date: Tue, 28 Oct 2008 11:12:28 +0200

For HSMMC2 and HSMMC3 set SDVSS to 1.8V in HCTL before enabling the SDBP bit.

Fixes bug 84194.

Signed-off-by: Jarkko Lavinen <jarkko.lavinen@nokia.com>
---
 drivers/mmc/host/omap_hsmmc.c |   19 ++++++++++---------
 1 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index a134f76..4bc25c0 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -1197,15 +1197,16 @@ static int omap_mmc_suspend(struct platform_device *pdev, pm_message_t state)
 			}
 
 			if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) {
-				OMAP_HSMMC_WRITE(host->base, HCTL,
-					OMAP_HSMMC_READ(host->base, HCTL)
-					& SDVSCLR);
-				OMAP_HSMMC_WRITE(host->base, HCTL,
-					OMAP_HSMMC_READ(host->base, HCTL)
-					| SDVS30);
-				OMAP_HSMMC_WRITE(host->base, HCTL,
-					OMAP_HSMMC_READ(host->base, HCTL)
-					| SDBP);
+				u32 hctl = OMAP_HSMMC_READ(host->base, HCTL) &
+					SDVSCLR;
+
+				if (host->id == OMAP_MMC1_DEVID)
+					hctl |= SDVS30;
+				else
+					hctl |= SDVS18;
+
+				OMAP_HSMMC_WRITE(host->base, HCTL, hctl);
+				OMAP_HSMMC_WRITE(host->base, HCTL, hctl | SDBP);
 			}
 
 			mmc_omap_fclk_state(host, OFF);
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 5/9] OMAP: HSMMC: Fix oops in omap_mmc_remove
  2008-11-21  9:37 ` Adrian Hunter
                     ` (3 preceding siblings ...)
  2008-11-21  9:46   ` [PATCH 4/9] OMAP: HSMMC: Fix suspend/resume for MMCHS2 Adrian Hunter
@ 2008-11-21  9:47   ` Adrian Hunter
  2008-11-21  9:51   ` [PATCH] OMAP: HSMMC: Fix SDVS values in omap_mmc_switch_opcond Adrian Hunter
                     ` (4 subsequent siblings)
  9 siblings, 0 replies; 17+ messages in thread
From: Adrian Hunter @ 2008-11-21  9:47 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: linux-omap@vger.kernel.org Mailing List

From: Jarkko Lavinen <jarkko.lavinen@nokia.com>
Date: Thu, 6 Nov 2008 16:02:29 +0200

Do not access host in omap_mmc_remove() if it is null.  This
occurs when module is removed before its platform data is set.

This fixes the oops part in bug 86677.

Signed-off-by: Jarkko Lavinen <jarkko.lavinen@nokia.com>
---
 drivers/mmc/host/omap_hsmmc.c |   20 +++++++++++---------
 1 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 4bc25c0..f4b7c30 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -1128,15 +1128,17 @@ static int omap_mmc_remove(struct platform_device *pdev)
 	struct resource *res;
 	u16 vdd = 0;
 
-	mmc_omap_fclk_state(host, ON);
-	if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) {
-	/*
-	 * Set the vdd back to 3V,
-	 * applicable for dual volt support.
-	 */
-		vdd = fls(host->mmc->ocr_avail) - 1;
-		if (omap_mmc_switch_opcond(host, vdd) != 0)
-			host->mmc->ios.vdd = vdd;
+	if (host) {
+		mmc_omap_fclk_state(host, ON);
+		if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) {
+			/*
+			 * Set the vdd back to 3V,
+			 * applicable for dual volt support.
+			 */
+			vdd = fls(host->mmc->ocr_avail) - 1;
+			if (omap_mmc_switch_opcond(host, vdd) != 0)
+				host->mmc->ios.vdd = vdd;
+		}
 	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH] OMAP: HSMMC: Fix SDVS values in omap_mmc_switch_opcond
  2008-11-21  9:37 ` Adrian Hunter
                     ` (4 preceding siblings ...)
  2008-11-21  9:47   ` [PATCH 5/9] OMAP: HSMMC: Fix oops in omap_mmc_remove Adrian Hunter
@ 2008-11-21  9:51   ` Adrian Hunter
  2008-11-21  9:52   ` [PATCH 7/9] OMAP: HSMMC: Use mod_timer from a single point for readability Adrian Hunter
                     ` (3 subsequent siblings)
  9 siblings, 0 replies; 17+ messages in thread
From: Adrian Hunter @ 2008-11-21  9:51 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: linux-omap@vger.kernel.org Mailing List

From: Jarkko Lavinen <jarkko.lavinen@nokia.com>
Date: Thu, 6 Nov 2008 16:02:28 +0200

Set only 1.8V as SDVS value in HCTL register for HSMMC2 and HSMMC3.

Signed-off-by: Jarkko Lavinen <jarkko.lavinen@nokia.com>
---
 drivers/mmc/host/omap_hsmmc.c |   11 +++++++----
 1 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index f4b7c30..e329115 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -529,10 +529,13 @@ static int omap_mmc_switch_opcond(struct mmc_omap_host *host, int vdd)
 	 * Only MMC1 supports 3.0V.  MMC2 will not function if SDVS30 is
 	 * set in HCTL.
 	 */
-	if (host->id == OMAP_MMC1_DEVID && (((1 << vdd) == MMC_VDD_32_33) ||
-				((1 << vdd) == MMC_VDD_33_34)))
-		reg_val |= SDVS30;
-	if ((1 << vdd) == MMC_VDD_165_195)
+	if (host->id == OMAP_MMC1_DEVID) {
+		if (((1 << vdd) == MMC_VDD_32_33) ||
+		    ((1 << vdd) == MMC_VDD_33_34))
+			reg_val |= SDVS30;
+		else if ((1 << vdd) == MMC_VDD_165_195)
+			reg_val |= SDVS18;
+	} else
 		reg_val |= SDVS18;
 
 	OMAP_HSMMC_WRITE(host->base, HCTL, reg_val);
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 7/9] OMAP: HSMMC: Use mod_timer from a single point for readability.
  2008-11-21  9:37 ` Adrian Hunter
                     ` (5 preceding siblings ...)
  2008-11-21  9:51   ` [PATCH] OMAP: HSMMC: Fix SDVS values in omap_mmc_switch_opcond Adrian Hunter
@ 2008-11-21  9:52   ` Adrian Hunter
  2008-11-21  9:53   ` [PATCH 8/9] OMAP: HSMMC: Implement scatter-gather emulation Adrian Hunter
                     ` (2 subsequent siblings)
  9 siblings, 0 replies; 17+ messages in thread
From: Adrian Hunter @ 2008-11-21  9:52 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: linux-omap@vger.kernel.org Mailing List

From: Jarkko Lavinen <jarkko.lavinen@nokia.com>
Date: Thu, 6 Nov 2008 16:02:30 +0200

Signed-off-by: Jarkko Lavinen <jarkko.lavinen@nokia.com>
---
 drivers/mmc/host/omap_hsmmc.c |   18 +++++++++++-------
 1 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index e329115..d81f9af 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -192,6 +192,11 @@ static void mmc_omap_idle_timer(unsigned long data)
 	mmc_omap_fclk_state(host, OFF);
 }
 
+static void mmc_omap_fclk_lazy_disable(struct mmc_omap_host *host)
+{
+	mod_timer(&host->idle_timer, jiffies + IDLE_TIMEOUT);
+}
+
 /*
  * Stop clock to the card
  */
@@ -332,7 +337,7 @@ mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data)
 
 	if (!data->stop) {
 		host->mrq = NULL;
-		mod_timer(&host->idle_timer, jiffies + IDLE_TIMEOUT);
+		mmc_omap_fclk_lazy_disable(host);
 		mmc_request_done(host->mmc, data->mrq);
 		return;
 	}
@@ -361,7 +366,7 @@ mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd)
 	}
 	if (host->data == NULL || cmd->error) {
 		host->mrq = NULL;
-		mod_timer(&host->idle_timer, jiffies + IDLE_TIMEOUT);
+		mmc_omap_fclk_lazy_disable(host);
 		mmc_request_done(host->mmc, cmd->mrq);
 	}
 }
@@ -577,7 +582,7 @@ static void mmc_omap_detect(struct work_struct *work)
 		while (OMAP_HSMMC_READ(host->base, SYSCTL) & SRD) ;
 		mmc_detect_change(host->mmc, (HZ * 50) / 1000);
 	}
-	mod_timer(&host->idle_timer, jiffies + IDLE_TIMEOUT);
+	mmc_omap_fclk_lazy_disable(host);
 }
 
 /*
@@ -878,7 +883,7 @@ static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	if (ios->power_mode == MMC_POWER_OFF)
 		mmc_omap_fclk_state(host, OFF);
 	else
-		mod_timer(&host->idle_timer, jiffies + IDLE_TIMEOUT);
+		mmc_omap_fclk_lazy_disable(host);
 }
 
 static int omap_hsmmc_get_cd(struct mmc_host *mmc)
@@ -1093,7 +1098,7 @@ static int __init omap_mmc_probe(struct platform_device *pdev)
 		if (ret < 0)
 			goto err_cover_switch;
 	}
-	mod_timer(&host->idle_timer, jiffies + IDLE_TIMEOUT);
+	mmc_omap_fclk_lazy_disable(host);
 
 	return 0;
 
@@ -1233,7 +1238,6 @@ static int omap_mmc_resume(struct platform_device *pdev)
 		return 0;
 
 	if (host) {
-
 		if (mmc_omap_fclk_state(host, ON) != 0)
 			goto clk_en_err;
 
@@ -1260,7 +1264,7 @@ static int omap_mmc_resume(struct platform_device *pdev)
 		if (ret == 0)
 			host->suspended = 0;
 
-		mod_timer(&host->idle_timer, jiffies + IDLE_TIMEOUT);
+		mmc_omap_fclk_lazy_disable(host);
 	}
 
 	return ret;
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 8/9] OMAP: HSMMC: Implement scatter-gather emulation
  2008-11-21  9:37 ` Adrian Hunter
                     ` (6 preceding siblings ...)
  2008-11-21  9:52   ` [PATCH 7/9] OMAP: HSMMC: Use mod_timer from a single point for readability Adrian Hunter
@ 2008-11-21  9:53   ` Adrian Hunter
  2008-11-21  9:53   ` [PATCH 9/9] OMAP: HSMMC: SDBP and missing clock enabled fixes Adrian Hunter
  2008-11-21  9:55   ` [PATCH 0/9] OMAP: HSMMC: Patches Adrian Hunter
  9 siblings, 0 replies; 17+ messages in thread
From: Adrian Hunter @ 2008-11-21  9:53 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: linux-omap@vger.kernel.org Mailing List

From: Juha Yrjola <juha.yrjola@solidboot.com>
Date: Fri, 14 Nov 2008 15:22:00 +0200

Instead of using the bounce buffer, using scatter-gather emulation
(as in the OMAP1/2 MMC driver) removes the need of one extra memory
copy and improves performance.

Signed-off-by: Juha Yrjola <juha.yrjola@solidboot.com>
---
 drivers/mmc/host/omap_hsmmc.c |  174 ++++++++++++++++++++++------------------
 1 files changed, 96 insertions(+), 78 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index d81f9af..6058a70 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -98,9 +98,6 @@
 #define OMAP_MMC1_DEVID		0
 #define OMAP_MMC2_DEVID		1
 
-#define OMAP_MMC_DATADIR_NONE	0
-#define OMAP_MMC_DATADIR_READ	1
-#define OMAP_MMC_DATADIR_WRITE	2
 #define MMC_TIMEOUT_MS		20
 #define OMAP_MMC_MASTER_CLOCK	96000000
 #define DRIVER_NAME		"mmci-omap"
@@ -139,16 +136,14 @@ struct mmc_omap_host {
 	resource_size_t		mapbase;
 	unsigned int		id;
 	unsigned int		dma_len;
-	unsigned int		dma_dir;
+	unsigned int		dma_sg_idx;
 	unsigned char		bus_mode;
-	unsigned char		datadir;
 	u32			*buffer;
 	u32			bytesleft;
 	int			suspended;
 	int			irq;
 	int			carddetect;
 	int			use_dma, dma_ch;
-	int			initstr;
 	int			slot_id;
 	int			dbclk_enabled;
 
@@ -316,6 +311,15 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd,
 	OMAP_HSMMC_WRITE(host->base, CMD, cmdreg);
 }
 
+static int
+mmc_omap_get_dma_dir(struct mmc_omap_host *host, struct mmc_data *data)
+{
+	if (data->flags & MMC_DATA_WRITE)
+		return DMA_TO_DEVICE;
+	else
+		return DMA_FROM_DEVICE;
+}
+
 /*
  * Notify the transfer complete to MMC core
  */
@@ -326,9 +330,7 @@ mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data)
 
 	if (host->use_dma && host->dma_ch != -1)
 		dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len,
-			host->dma_dir);
-
-	host->datadir = OMAP_MMC_DATADIR_NONE;
+			mmc_omap_get_dma_dir(host, data));
 
 	if (!data->error)
 		data->bytes_xfered += data->blocks * (data->blksz);
@@ -380,13 +382,12 @@ static void mmc_dma_cleanup(struct mmc_omap_host *host)
 
 	if (host->use_dma && host->dma_ch != -1) {
 		dma_unmap_sg(mmc_dev(host->mmc), host->data->sg, host->dma_len,
-			host->dma_dir);
+			mmc_omap_get_dma_dir(host, host->data));
 		omap_free_dma(host->dma_ch);
 		host->dma_ch = -1;
 		up(&host->sem);
 	}
 	host->data = NULL;
-	host->datadir = OMAP_MMC_DATADIR_NONE;
 }
 
 /*
@@ -598,6 +599,55 @@ static irqreturn_t omap_mmc_cd_handler(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
+static int mmc_omap_get_dma_sync_dev(struct mmc_omap_host *host,
+				     struct mmc_data *data)
+{
+	int sync_dev;
+
+	if (data->flags & MMC_DATA_WRITE) {
+		if (host->id == OMAP_MMC1_DEVID)
+			sync_dev = OMAP24XX_DMA_MMC1_TX;
+		else
+			sync_dev = OMAP24XX_DMA_MMC2_TX;
+	} else {
+		if (host->id == OMAP_MMC1_DEVID)
+			sync_dev = OMAP24XX_DMA_MMC1_RX;
+		else
+			sync_dev = OMAP24XX_DMA_MMC2_RX;
+	}
+	return sync_dev;
+}
+
+static void mmc_omap_config_dma_params(struct mmc_omap_host *host,
+				       struct mmc_data *data,
+				       struct scatterlist *sgl)
+{
+	int blksz, nblk, dma_ch;
+
+	dma_ch = host->dma_ch;
+	if (data->flags & MMC_DATA_WRITE) {
+		omap_set_dma_dest_params(dma_ch, 0, OMAP_DMA_AMODE_CONSTANT,
+			(host->mapbase + OMAP_HSMMC_DATA), 0, 0);
+		omap_set_dma_src_params(dma_ch, 0, OMAP_DMA_AMODE_POST_INC,
+			sg_dma_address(sgl), 0, 0);
+	} else {
+		omap_set_dma_src_params(dma_ch, 0, OMAP_DMA_AMODE_CONSTANT,
+					(host->mapbase + OMAP_HSMMC_DATA), 0, 0);
+		omap_set_dma_dest_params(dma_ch, 0, OMAP_DMA_AMODE_POST_INC,
+			sg_dma_address(sgl), 0, 0);
+	}
+
+	blksz = host->data->blksz;
+	nblk = sg_dma_len(sgl) / blksz;
+
+	omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S32,
+			blksz / 4, nblk, OMAP_DMA_SYNC_FRAME,
+			mmc_omap_get_dma_sync_dev(host, data),
+			!(data->flags & MMC_DATA_WRITE));
+
+	omap_start_dma(dma_ch);
+}
+
 /*
  * DMA call back function
  */
@@ -611,6 +661,14 @@ static void mmc_omap_dma_cb(int lch, u16 ch_status, void *data)
 	if (host->dma_ch < 0)
 		return;
 
+	host->dma_sg_idx++;
+	if (host->dma_sg_idx < host->dma_len) {
+		/* Fire up the next transfer. */
+		mmc_omap_config_dma_params(host, host->data,
+					   host->data->sg + host->dma_sg_idx);
+		return;
+	}
+
 	omap_free_dma(host->dma_ch);
 	host->dma_ch = -1;
 	/*
@@ -621,38 +679,28 @@ static void mmc_omap_dma_cb(int lch, u16 ch_status, void *data)
 }
 
 /*
- * Configure dma src and destination parameters
- */
-static int mmc_omap_config_dma_param(int sync_dir, struct mmc_omap_host *host,
-				struct mmc_data *data)
-{
-	if (sync_dir == 0) {
-		omap_set_dma_dest_params(host->dma_ch, 0,
-			OMAP_DMA_AMODE_CONSTANT,
-			(host->mapbase + OMAP_HSMMC_DATA), 0, 0);
-		omap_set_dma_src_params(host->dma_ch, 0,
-			OMAP_DMA_AMODE_POST_INC,
-			sg_dma_address(&data->sg[0]), 0, 0);
-	} else {
-		omap_set_dma_src_params(host->dma_ch, 0,
-			OMAP_DMA_AMODE_CONSTANT,
-			(host->mapbase + OMAP_HSMMC_DATA), 0, 0);
-		omap_set_dma_dest_params(host->dma_ch, 0,
-			OMAP_DMA_AMODE_POST_INC,
-			sg_dma_address(&data->sg[0]), 0, 0);
-	}
-	return 0;
-}
-/*
  * Routine to configure and start DMA for the MMC card
  */
 static int
 mmc_omap_start_dma_transfer(struct mmc_omap_host *host, struct mmc_request *req)
 {
-	int sync_dev, sync_dir = 0;
-	int dma_ch = 0, ret = 0, err = 1;
+	int dma_ch = 0, ret = 0, err = 1, i;
 	struct mmc_data *data = req->data;
 
+	/* Sanity check: all the SG entries must be aligned by block size. */
+	for (i = 0; i < host->dma_len; i++) {
+		struct scatterlist *sgl;
+
+		sgl = data->sg + i;
+		if (sgl->length % data->blksz)
+			return -EINVAL;
+	}
+	if ((data->blksz % 4) != 0)
+		/* REVISIT: The MMC buffer increments only when MSB is written.
+		 * Return error for blksz which is non multiple of four.
+		 */
+		return -EINVAL;
+
 	/*
 	 * If for some reason the DMA transfer is still active,
 	 * we wait for timeout period and free the dma
@@ -671,49 +719,22 @@ mmc_omap_start_dma_transfer(struct mmc_omap_host *host, struct mmc_request *req)
 			return err;
 	}
 
-	if (!(data->flags & MMC_DATA_WRITE)) {
-		host->dma_dir = DMA_FROM_DEVICE;
-		if (host->id == OMAP_MMC1_DEVID)
-			sync_dev = OMAP24XX_DMA_MMC1_RX;
-		else
-			sync_dev = OMAP24XX_DMA_MMC2_RX;
-	} else {
-		host->dma_dir = DMA_TO_DEVICE;
-		if (host->id == OMAP_MMC1_DEVID)
-			sync_dev = OMAP24XX_DMA_MMC1_TX;
-		else
-			sync_dev = OMAP24XX_DMA_MMC2_TX;
-	}
-
-	ret = omap_request_dma(sync_dev, "MMC/SD", mmc_omap_dma_cb,
-			host, &dma_ch);
+	ret = omap_request_dma(mmc_omap_get_dma_sync_dev(host, data), "MMC/SD",
+			       mmc_omap_dma_cb,host, &dma_ch);
 	if (ret != 0) {
-		dev_dbg(mmc_dev(host->mmc),
+		dev_err(mmc_dev(host->mmc),
 			"%s: omap_request_dma() failed with %d\n",
 			mmc_hostname(host->mmc), ret);
 		return ret;
 	}
 
 	host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg,
-			data->sg_len, host->dma_dir);
+			data->sg_len, mmc_omap_get_dma_dir(host, data));
 	host->dma_ch = dma_ch;
+	host->dma_sg_idx = 0;
 
-	if (!(data->flags & MMC_DATA_WRITE))
-		mmc_omap_config_dma_param(1, host, data);
-	else
-		mmc_omap_config_dma_param(0, host, data);
-
-	if ((data->blksz % 4) == 0)
-		omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S32,
-			(data->blksz / 4), data->blocks, OMAP_DMA_SYNC_FRAME,
-			sync_dev, sync_dir);
-	else
-		/* REVISIT: The MMC buffer increments only when MSB is written.
-		 * Return error for blksz which is non multiple of four.
-		 */
-		return -EINVAL;
+	mmc_omap_config_dma_params(host, data, data->sg);
 
-	omap_start_dma(dma_ch);
 	return 0;
 }
 
@@ -763,7 +784,6 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req)
 	host->data = req->data;
 
 	if (req->data == NULL) {
-		host->datadir = OMAP_MMC_DATADIR_NONE;
 		OMAP_HSMMC_WRITE(host->base, BLK, 0);
 		return 0;
 	}
@@ -772,9 +792,6 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req)
 					| (req->data->blocks << 16));
 	set_data_timeout(host, req);
 
-	host->datadir = (req->data->flags & MMC_DATA_WRITE) ?
-			OMAP_MMC_DATADIR_WRITE : OMAP_MMC_DATADIR_READ;
-
 	if (host->use_dma) {
 		ret = mmc_omap_start_dma_transfer(host, req);
 		if (ret != 0) {
@@ -920,7 +937,7 @@ static int __init omap_mmc_probe(struct platform_device *pdev)
 	struct mmc_host *mmc;
 	struct mmc_omap_host *host = NULL;
 	struct resource *res;
-	int ret = 0, irq, reg;
+	int ret = 0, irq;
 	u32 hctl, capa;
 
 	if (pdata == NULL) {
@@ -1014,10 +1031,11 @@ static int __init omap_mmc_probe(struct platform_device *pdev)
 		else
 			host->dbclk_enabled = 1;
 
-#ifdef CONFIG_MMC_BLOCK_BOUNCE
-	mmc->max_phys_segs = 1;
-	mmc->max_hw_segs = 1;
-#endif
+	/* Since we do only SG emulation, we can have as many segs
+	 * as we want. */
+	mmc->max_phys_segs = 1024;
+	mmc->max_hw_segs = 1024;
+
 	mmc->max_blk_size = 512;       /* Block Length at max can be 1024 */
 	mmc->max_blk_count = 0xFFFF;    /* No. of Blocks is 16 bits */
 	mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
-- 
1.5.4.3


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 9/9] OMAP: HSMMC: SDBP and missing clock enabled fixes
  2008-11-21  9:37 ` Adrian Hunter
                     ` (7 preceding siblings ...)
  2008-11-21  9:53   ` [PATCH 8/9] OMAP: HSMMC: Implement scatter-gather emulation Adrian Hunter
@ 2008-11-21  9:53   ` Adrian Hunter
  2008-11-21  9:55   ` [PATCH 0/9] OMAP: HSMMC: Patches Adrian Hunter
  9 siblings, 0 replies; 17+ messages in thread
From: Adrian Hunter @ 2008-11-21  9:53 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: linux-omap@vger.kernel.org Mailing List

From: Jarkko Lavinen <jarkko.lavinen@nokia.com>
Date: Wed, 19 Nov 2008 15:49:52 +0200

Disable SDBP at suspend and enable it resume. Make sure
fclk is running at suspend before touching HCTL.

Signed-off-by: Jarkko Lavinen <jarkko.lavinen@nokia.com>
---
 drivers/mmc/host/omap_hsmmc.c |   31 ++++++++++++-------------------
 1 files changed, 12 insertions(+), 19 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 6058a70..78c5c18 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -897,10 +897,7 @@ static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 		OMAP_HSMMC_WRITE(host->base, CON,
 				OMAP_HSMMC_READ(host->base, CON) | OD);
 
-	if (ios->power_mode == MMC_POWER_OFF)
-		mmc_omap_fclk_state(host, OFF);
-	else
-		mmc_omap_fclk_lazy_disable(host);
+	mmc_omap_fclk_lazy_disable(host);
 }
 
 static int omap_hsmmc_get_cd(struct mmc_host *mmc)
@@ -1207,12 +1204,11 @@ static int omap_mmc_suspend(struct platform_device *pdev, pm_message_t state)
 		return 0;
 
 	if (host) {
-		mmc_omap_fclk_state(host, ON);
-
 		ret = mmc_suspend_host(host->mmc, state);
 		if (ret == 0) {
 			host->suspended = 1;
 
+			mmc_omap_fclk_state(host, ON);
 			OMAP_HSMMC_WRITE(host->base, ISE, 0);
 			OMAP_HSMMC_WRITE(host->base, IE, 0);
 
@@ -1224,19 +1220,8 @@ static int omap_mmc_suspend(struct platform_device *pdev, pm_message_t state)
 						" level suspend\n");
 			}
 
-			if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) {
-				u32 hctl = OMAP_HSMMC_READ(host->base, HCTL) &
-					SDVSCLR;
-
-				if (host->id == OMAP_MMC1_DEVID)
-					hctl |= SDVS30;
-				else
-					hctl |= SDVS18;
-
-				OMAP_HSMMC_WRITE(host->base, HCTL, hctl);
-				OMAP_HSMMC_WRITE(host->base, HCTL, hctl | SDBP);
-			}
-
+			OMAP_HSMMC_WRITE(host->base, HCTL,
+					 OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP);
 			mmc_omap_fclk_state(host, OFF);
 			clk_disable(host->iclk);
 			clk_disable(host->dbclk);
@@ -1256,6 +1241,7 @@ static int omap_mmc_resume(struct platform_device *pdev)
 		return 0;
 
 	if (host) {
+		int i;
 		if (mmc_omap_fclk_state(host, ON) != 0)
 			goto clk_en_err;
 
@@ -1270,6 +1256,13 @@ static int omap_mmc_resume(struct platform_device *pdev)
 			dev_dbg(mmc_dev(host->mmc),
 					"Enabling debounce clk failed\n");
 
+		OMAP_HSMMC_WRITE(host->base, HCTL,
+				 OMAP_HSMMC_READ(host->base, HCTL) | SDBP);
+
+		for (i = 0; i < 100; i++)
+			if (OMAP_HSMMC_READ(host->base, HCTL) & SDBP)
+				break;
+
 		if (host->pdata->resume) {
 			ret = host->pdata->resume(&pdev->dev, host->slot_id);
 			if (ret)
-- 
1.5.4.3


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH 0/9] OMAP: HSMMC: Patches
  2008-11-21  9:37 ` Adrian Hunter
                     ` (8 preceding siblings ...)
  2008-11-21  9:53   ` [PATCH 9/9] OMAP: HSMMC: SDBP and missing clock enabled fixes Adrian Hunter
@ 2008-11-21  9:55   ` Adrian Hunter
  2008-11-21  9:57     ` [PATCH 4/9] OMAP: HSMMC: Fix suspend/resume for MMCHS2 Adrian Hunter
  2008-11-21  9:58     ` [PATCH 5/9] OMAP: HSMMC: Fix oops in omap_mmc_remove Adrian Hunter
  9 siblings, 2 replies; 17+ messages in thread
From: Adrian Hunter @ 2008-11-21  9:55 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: linux-omap@vger.kernel.org Mailing List

Adrian Hunter wrote:
> Adrian Hunter wrote:
>> OMAP HSMMC is not ready for mainline, but development is ongoing.
>>
>> In the meantime these patches are best posted and applied via
>> omap mailing list and tree.
>
> Just realised I forgot the from lines in all those patches - will resend.
>

And now 4 and 5 again without the spurious bug references...

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 4/9] OMAP: HSMMC: Fix suspend/resume for MMCHS2
  2008-11-21  9:55   ` [PATCH 0/9] OMAP: HSMMC: Patches Adrian Hunter
@ 2008-11-21  9:57     ` Adrian Hunter
  2008-11-21  9:58     ` [PATCH 5/9] OMAP: HSMMC: Fix oops in omap_mmc_remove Adrian Hunter
  1 sibling, 0 replies; 17+ messages in thread
From: Adrian Hunter @ 2008-11-21  9:57 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: linux-omap@vger.kernel.org Mailing List

From: Jarkko Lavinen <jarkko.lavinen@nokia.com>
Date: Tue, 28 Oct 2008 11:12:28 +0200

For HSMMC2 and HSMMC3 set SDVSS to 1.8V in HCTL before enabling the SDBP bit.

Signed-off-by: Jarkko Lavinen <jarkko.lavinen@nokia.com>
---
 drivers/mmc/host/omap_hsmmc.c |   19 ++++++++++---------
 1 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index a134f76..4bc25c0 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -1197,15 +1197,16 @@ static int omap_mmc_suspend(struct platform_device *pdev, pm_message_t state)
 			}
 
 			if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) {
-				OMAP_HSMMC_WRITE(host->base, HCTL,
-					OMAP_HSMMC_READ(host->base, HCTL)
-					& SDVSCLR);
-				OMAP_HSMMC_WRITE(host->base, HCTL,
-					OMAP_HSMMC_READ(host->base, HCTL)
-					| SDVS30);
-				OMAP_HSMMC_WRITE(host->base, HCTL,
-					OMAP_HSMMC_READ(host->base, HCTL)
-					| SDBP);
+				u32 hctl = OMAP_HSMMC_READ(host->base, HCTL) &
+					SDVSCLR;
+
+				if (host->id == OMAP_MMC1_DEVID)
+					hctl |= SDVS30;
+				else
+					hctl |= SDVS18;
+
+				OMAP_HSMMC_WRITE(host->base, HCTL, hctl);
+				OMAP_HSMMC_WRITE(host->base, HCTL, hctl | SDBP);
 			}
 
 			mmc_omap_fclk_state(host, OFF);
-- 
1.5.4.3

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 5/9] OMAP: HSMMC: Fix oops in omap_mmc_remove
  2008-11-21  9:55   ` [PATCH 0/9] OMAP: HSMMC: Patches Adrian Hunter
  2008-11-21  9:57     ` [PATCH 4/9] OMAP: HSMMC: Fix suspend/resume for MMCHS2 Adrian Hunter
@ 2008-11-21  9:58     ` Adrian Hunter
  2008-11-21 14:03       ` Grazvydas Ignotas
  1 sibling, 1 reply; 17+ messages in thread
From: Adrian Hunter @ 2008-11-21  9:58 UTC (permalink / raw)
  To: Tony Lindgren; +Cc: linux-omap@vger.kernel.org Mailing List

From: Jarkko Lavinen <jarkko.lavinen@nokia.com>
Date: Thu, 6 Nov 2008 16:02:29 +0200

Do not access host in omap_mmc_remove() if it is null.  This
occurs when module is removed before its platform data is set.

Signed-off-by: Jarkko Lavinen <jarkko.lavinen@nokia.com>
---
 drivers/mmc/host/omap_hsmmc.c |   20 +++++++++++---------
 1 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 4bc25c0..f4b7c30 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -1128,15 +1128,17 @@ static int omap_mmc_remove(struct platform_device *pdev)
 	struct resource *res;
 	u16 vdd = 0;
 
-	mmc_omap_fclk_state(host, ON);
-	if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) {
-	/*
-	 * Set the vdd back to 3V,
-	 * applicable for dual volt support.
-	 */
-		vdd = fls(host->mmc->ocr_avail) - 1;
-		if (omap_mmc_switch_opcond(host, vdd) != 0)
-			host->mmc->ios.vdd = vdd;
+	if (host) {
+		mmc_omap_fclk_state(host, ON);
+		if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) {
+			/*
+			 * Set the vdd back to 3V,
+			 * applicable for dual volt support.
+			 */
+			vdd = fls(host->mmc->ocr_avail) - 1;
+			if (omap_mmc_switch_opcond(host, vdd) != 0)
+				host->mmc->ios.vdd = vdd;
+		}
 	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-- 
1.5.4.3


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH 5/9] OMAP: HSMMC: Fix oops in omap_mmc_remove
  2008-11-21  9:58     ` [PATCH 5/9] OMAP: HSMMC: Fix oops in omap_mmc_remove Adrian Hunter
@ 2008-11-21 14:03       ` Grazvydas Ignotas
  2008-11-21 15:27         ` Jarkko Lavinen
  0 siblings, 1 reply; 17+ messages in thread
From: Grazvydas Ignotas @ 2008-11-21 14:03 UTC (permalink / raw)
  To: Adrian Hunter; +Cc: linux-omap@vger.kernel.org Mailing List

On Fri, Nov 21, 2008 at 11:58 AM, Adrian Hunter
<ext-adrian.hunter@nokia.com> wrote:
<snip>
> @@ -1128,15 +1128,17 @@ static int omap_mmc_remove(struct platform_device
<snip>
> +               mmc_omap_fclk_state(host, ON);
> +               if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) {
> +                       /*
> +                        * Set the vdd back to 3V,
> +                        * applicable for dual volt support.
> +                        */
> +                       vdd = fls(host->mmc->ocr_avail) - 1;
> +                       if (omap_mmc_switch_opcond(host, vdd) != 0)
> +                               host->mmc->ios.vdd = vdd;
> +               }

I wonder what this block is for? Wouldn't simple
   host->mmc->ios.vdd = vdd;
be enough? It calls omap_mmc_switch_opcond() which toggles clocks and
power without good reason (I think). Clocks will be turned off later
in omap_mmc_remove() anyway, and .set_ios will turn off power. Also,
HCTL SDVSDET bit will never be set for MMC2 and MMC3, causing
mentioned omap_mmc_switch_opcond() to be called unconditionally here.

The same block can be found in mmc_omap_detect() function, where it is
executed on card removal. There it causes MMC2 controller to stop
working completely on pandora board :(

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 5/9] OMAP: HSMMC: Fix oops in omap_mmc_remove
  2008-11-21 14:03       ` Grazvydas Ignotas
@ 2008-11-21 15:27         ` Jarkko Lavinen
  2008-11-21 21:08           ` Grazvydas Ignotas
  0 siblings, 1 reply; 17+ messages in thread
From: Jarkko Lavinen @ 2008-11-21 15:27 UTC (permalink / raw)
  To: Grazvydas Ignotas; +Cc: Adrian Hunter, linux-omap@vger.kernel.org Mailing List

On Fri, Nov 21, 2008 at 04:03:25PM +0200, ext Grazvydas Ignotas wrote:
...
> Also, HCTL SDVSDET bit will never be set for MMC2 and MMC3, causing
> mentioned omap_mmc_switch_opcond() to be called unconditionally here.
> 
> The same block can be found in mmc_omap_detect() function, where it is
> executed on card removal. There it causes MMC2 controller to stop
> working completely on pandora board :(

TI TRM saus HSMMC2 and HSMMC3 works only with SDVS set to 1.8V in HCTL.

If the voltage is set to 3.0V and then SDBP (bus power bit) is set,
it is rejected and SDBP remains zero, the controller does nothing and 
is seemingly frozen.

The wrong voltage for MMC2 SDVS is set in omap_mmc_switch_opcond() if 
vdd different from 1.8V.

Also omap_mmc_suspend() set SDVS to 3.0V even for MMC2 and MMC3.  When
suspending, everything seemed to work and at resume MMC2 was hung
and failed to detect the card since not even CMD0 was sent.

Regards
Jarkko Lavinen

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 5/9] OMAP: HSMMC: Fix oops in omap_mmc_remove
  2008-11-21 15:27         ` Jarkko Lavinen
@ 2008-11-21 21:08           ` Grazvydas Ignotas
  0 siblings, 0 replies; 17+ messages in thread
From: Grazvydas Ignotas @ 2008-11-21 21:08 UTC (permalink / raw)
  To: Jarkko Lavinen; +Cc: Adrian Hunter, linux-omap@vger.kernel.org Mailing List

On Fri, Nov 21, 2008 at 5:27 PM, Jarkko Lavinen
<jarkko.lavinen@nokia.com> wrote:
> On Fri, Nov 21, 2008 at 04:03:25PM +0200, ext Grazvydas Ignotas wrote:
> ...
>> Also, HCTL SDVSDET bit will never be set for MMC2 and MMC3, causing
>> mentioned omap_mmc_switch_opcond() to be called unconditionally here.
>>
>> The same block can be found in mmc_omap_detect() function, where it is
>> executed on card removal. There it causes MMC2 controller to stop
>> working completely on pandora board :(
>
> TI TRM saus HSMMC2 and HSMMC3 works only with SDVS set to 1.8V in HCTL.
>
> If the voltage is set to 3.0V and then SDBP (bus power bit) is set,
> it is rejected and SDBP remains zero, the controller does nothing and
> is seemingly frozen.
>
> The wrong voltage for MMC2 SDVS is set in omap_mmc_switch_opcond() if
> vdd different from 1.8V.
>
> Also omap_mmc_suspend() set SDVS to 3.0V even for MMC2 and MMC3.  When
> suspending, everything seemed to work and at resume MMC2 was hung
> and failed to detect the card since not even CMD0 was sent.

ok, but why there are calls to  omap_mmc_switch_opcond() from both
omap_mmc_remove() and mmc_omap_detect() at all? This basically causes
power and clocks to be turned off, then on, then again off whenever
card is or host driver removed. This is probably no big deal, but
still.

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2008-11-21 21:08 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-11-21  9:23 [PATCH 0/9] OMAP: HSMMC: Patches Adrian Hunter
2008-11-21  9:37 ` Adrian Hunter
2008-11-21  9:43   ` [PATCH 1/9] OMAP: HSMMC: Make driver support dynamic idle Adrian Hunter
2008-11-21  9:44   ` [PATCH 2/9] OMAP: HSMMC: Ensure fclk is running before accessing HSMMC registers Adrian Hunter
2008-11-21  9:45   ` [PATCH 3/9] OMAP: HSMMC: Make fclk disable request driven Adrian Hunter
2008-11-21  9:46   ` [PATCH 4/9] OMAP: HSMMC: Fix suspend/resume for MMCHS2 Adrian Hunter
2008-11-21  9:47   ` [PATCH 5/9] OMAP: HSMMC: Fix oops in omap_mmc_remove Adrian Hunter
2008-11-21  9:51   ` [PATCH] OMAP: HSMMC: Fix SDVS values in omap_mmc_switch_opcond Adrian Hunter
2008-11-21  9:52   ` [PATCH 7/9] OMAP: HSMMC: Use mod_timer from a single point for readability Adrian Hunter
2008-11-21  9:53   ` [PATCH 8/9] OMAP: HSMMC: Implement scatter-gather emulation Adrian Hunter
2008-11-21  9:53   ` [PATCH 9/9] OMAP: HSMMC: SDBP and missing clock enabled fixes Adrian Hunter
2008-11-21  9:55   ` [PATCH 0/9] OMAP: HSMMC: Patches Adrian Hunter
2008-11-21  9:57     ` [PATCH 4/9] OMAP: HSMMC: Fix suspend/resume for MMCHS2 Adrian Hunter
2008-11-21  9:58     ` [PATCH 5/9] OMAP: HSMMC: Fix oops in omap_mmc_remove Adrian Hunter
2008-11-21 14:03       ` Grazvydas Ignotas
2008-11-21 15:27         ` Jarkko Lavinen
2008-11-21 21:08           ` Grazvydas Ignotas

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox