diff mbox

[1/4] mmc: omap_hsmmc: Fix context save and restore for DT

Message ID 20130607214950.18581.56829.stgit@localhost (mailing list archive)
State New, archived
Headers show

Commit Message

Tony Lindgren June 7, 2013, 9:49 p.m. UTC
We want to get rid of the omap specific platform init code
callbacks as they don't play nice with device tree.

Let's convert the context loss check to be based on a
register state detection instead.

Cc: Andreas Fenkart <afenkart@gmail.com>
Cc: Balaji T K <balajitk@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 drivers/mmc/host/omap_hsmmc.c |   41 ++++++++---------------------------------
 1 file changed, 8 insertions(+), 33 deletions(-)


--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Felipe Balbi June 8, 2013, 4:25 a.m. UTC | #1
Hi,

On Fri, Jun 07, 2013 at 02:49:50PM -0700, Tony Lindgren wrote:
> We want to get rid of the omap specific platform init code
> callbacks as they don't play nice with device tree.

right, any plans to have similar functionality generically ? Maybe
something like:

probe()
{
	...

	/*
	 * tell PM runtime layer that we can handle runtime
	 * power gating of this device in certain conditions.
	 *
	 * Actual power gating will be triggered depending on
	 * PM QoS wakeup requirements.
	 */
	pm_runtime_enable_power_gating(dev);

	...
}

runtime_suspend()
{
	if (pm_runtime_will_power_gate(dev))
		save_context();
}

runtime_resume()
{
	if (pm_runtime_has_lost_power(dev))
		restore_context();
}

???

> Let's convert the context loss check to be based on a
> register state detection instead.

that might not work always. Specially when you consider that default
register values can change on every silicon release. I guess the above
might be a bit nicer, although a lot more work :-p
Tony Lindgren June 8, 2013, 3:02 p.m. UTC | #2
* Felipe Balbi <balbi@ti.com> [130607 21:32]:
> Hi,
> 
> On Fri, Jun 07, 2013 at 02:49:50PM -0700, Tony Lindgren wrote:
> > We want to get rid of the omap specific platform init code
> > callbacks as they don't play nice with device tree.
> 
> right, any plans to have similar functionality generically ? Maybe
> something like:
> 
> probe()
> {
> 	...
> 
> 	/*
> 	 * tell PM runtime layer that we can handle runtime
> 	 * power gating of this device in certain conditions.
> 	 *
> 	 * Actual power gating will be triggered depending on
> 	 * PM QoS wakeup requirements.
> 	 */
> 	pm_runtime_enable_power_gating(dev);
> 
> 	...
> }
> 
> runtime_suspend()
> {
> 	if (pm_runtime_will_power_gate(dev))
> 		save_context();
> }
> 
> runtime_resume()
> {
> 	if (pm_runtime_has_lost_power(dev))
> 		restore_context();
> }
> 
> ???

Yes some kind of generic approach is needed too, at least for some
drivers. The above API makes sense to me, sounds like you might
have a PM runtime patch coming along those lines?
 
> > Let's convert the context loss check to be based on a
> > register state detection instead.
> 
> that might not work always. Specially when you consider that default
> register values can change on every silicon release. I guess the above
> might be a bit nicer, although a lot more work :-p

These are not revision registers, here the driver configured values
are saved in PM runtime suspend, and then restored in resume.
We are already doing the same for GPIO for example. In these cases the
context loss count is not needed AFAIK.

With some hardware it is of course possible that the power cycle is so
short that the hardare is stuck in a limbo state and for those cases
keeping track of the context loss via PM runtime.

Regards,

Tony
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 6e44025..478849b 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -169,19 +169,19 @@  struct omap_hsmmc_host {
 	unsigned char		bus_mode;
 	unsigned char		power_mode;
 	int			suspended;
+	u32			hctl;
+	u32			capa;
 	int			irq;
 	int			use_dma, dma_ch;
 	struct dma_chan		*tx_chan;
 	struct dma_chan		*rx_chan;
 	int			slot_id;
 	int			response_busy;
-	int			context_loss;
 	int			protect_card;
 	int			reqs_blocked;
 	int			use_reg;
 	int			req_in_progress;
 	struct omap_hsmmc_next	next_data;
-
 	struct	omap_mmc_platform_data	*pdata;
 };
 
@@ -595,25 +595,16 @@  static void omap_hsmmc_set_bus_mode(struct omap_hsmmc_host *host)
 static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host)
 {
 	struct mmc_ios *ios = &host->mmc->ios;
-	struct omap_mmc_platform_data *pdata = host->pdata;
-	int context_loss = 0;
 	u32 hctl, capa;
 	unsigned long timeout;
 
-	if (pdata->get_context_loss_count) {
-		context_loss = pdata->get_context_loss_count(host->dev);
-		if (context_loss < 0)
-			return 1;
-	}
-
-	dev_dbg(mmc_dev(host->mmc), "context was %slost\n",
-		context_loss == host->context_loss ? "not " : "");
-	if (host->context_loss == context_loss)
-		return 1;
-
 	if (!OMAP_HSMMC_READ(host->base, SYSSTATUS) & RESETDONE)
 		return 1;
 
+	if (host->hctl == OMAP_HSMMC_READ(host->base, HCTL) &&
+	    host->capa == OMAP_HSMMC_READ(host->base, CAPA))
+		return 0;
+
 	if (host->pdata->controller_flags & OMAP_HSMMC_SUPPORTS_DUAL_VOLT) {
 		if (host->power_mode != MMC_POWER_OFF &&
 		    (1 << ios->vdd) <= MMC_VDD_23_24)
@@ -653,8 +644,6 @@  static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host)
 	omap_hsmmc_set_bus_mode(host);
 
 out:
-	host->context_loss = context_loss;
-
 	dev_dbg(mmc_dev(host->mmc), "context is restored\n");
 	return 0;
 }
@@ -664,15 +653,8 @@  out:
  */
 static void omap_hsmmc_context_save(struct omap_hsmmc_host *host)
 {
-	struct omap_mmc_platform_data *pdata = host->pdata;
-	int context_loss;
-
-	if (pdata->get_context_loss_count) {
-		context_loss = pdata->get_context_loss_count(host->dev);
-		if (context_loss < 0)
-			return;
-		host->context_loss = context_loss;
-	}
+	host->hctl = OMAP_HSMMC_READ(host->base, HCTL);
+	host->capa = OMAP_HSMMC_READ(host->base, CAPA);
 }
 
 #else
@@ -1633,13 +1615,6 @@  static int omap_hsmmc_regs_show(struct seq_file *s, void *data)
 {
 	struct mmc_host *mmc = s->private;
 	struct omap_hsmmc_host *host = mmc_priv(mmc);
-	int context_loss = 0;
-
-	if (host->pdata->get_context_loss_count)
-		context_loss = host->pdata->get_context_loss_count(host->dev);
-
-	seq_printf(s, "mmc%d:\n ctx_loss:\t%d:%d\n\nregs:\n",
-			mmc->index, host->context_loss, context_loss);
 
 	if (host->suspended) {
 		seq_printf(s, "host suspended, can't read registers\n");