From patchwork Wed Jul 22 06:52:08 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elvis Dowson X-Patchwork-Id: 36713 X-Patchwork-Delegate: khilman@deeprootsystems.com Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n6M6qDrH030070 for ; Wed, 22 Jul 2009 06:52:13 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1750852AbZGVGwK (ORCPT ); Wed, 22 Jul 2009 02:52:10 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1751032AbZGVGwK (ORCPT ); Wed, 22 Jul 2009 02:52:10 -0400 Received: from asmtpout020.mac.com ([17.148.16.95]:49965 "EHLO asmtpout020.mac.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750852AbZGVGwJ (ORCPT ); Wed, 22 Jul 2009 02:52:09 -0400 MIME-version: 1.0 Content-transfer-encoding: 7BIT Content-type: text/plain; charset=ISO-8859-1 Received: from spool002.mac.com ([10.150.69.52]) by asmtp020.mac.com (Sun Java(tm) System Messaging Server 6.3-8.01 (built Dec 16 2008; 32bit)) with ESMTP id <0KN600LI88EWOO30@asmtp020.mac.com> for linux-omap@vger.kernel.org; Tue, 21 Jul 2009 23:52:09 -0700 (PDT) Received: from webmail067 ([10.13.128.67]) by spool002.mac.com (Sun Java(tm) System Messaging Server 6.3-8.01 (built Dec 16 2008; 32bit)) with ESMTP id <0KN6009Z78EWAH90@spool002.mac.com>; Tue, 21 Jul 2009 23:52:08 -0700 (PDT) Date: Tue, 21 Jul 2009 23:52:08 -0700 From: Elvis Dowson To: "Pandita, Vikram" Cc: Kevin Hilman , Linux OMAP Users Message-id: <73861106703285855975964702821359240011-Webmail@me.com> Subject: RE: android-omap-2.6.29 for gumstix overo Received: from [89.31.192.188] from webmail.me.com with HTTP; Tue, 21 Jul 2009 23:52:08 -0700 Received: from [ 80.157.169.150] from webmail.me.com with HTTP; Tue, 21 Jul 2009 23:52:08 -0700 X-Originating-IP: 89.31.192.188, 80.157.169.150 Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org Hi Vikram, I took a look at the zoom2_pm_defconfig file that you sent me, and it is mising the following entries to activate power management # # Power management options # CONFIG_PM_SLEEP=y CONFIG_SUSPEND=y CONFIG_SUSPEND_FREEZER=y For the mmc off patch set, there are 2 patches, with one being slightly different from the other. Why is this so? Also which one should I use. I have reproduced the differences between patch set 1 and patch set 2 below: It differs in 3 areas: 1. use of int vs. unsigned 2. static int omap_hsmmc_enable_clks in patch set 1 has more code than the one in patch set 2 3. host->off_counter = 0; Patch set 1 + OMAP_HSMMC_WRITE(host->base, HCTL, OMAP_HSMMC_READ(host->base, + HCTL) | SDBP); +} + static int omap_hsmmc_enable_clks(struct mmc_omap_host *host) { - unsigned long flags; + unsigned long flags, timeout; int ret = 0; spin_lock_irqsave(&host->clk_lock, flags); @@ -190,6 +228,24 @@ static int omap_hsmmc_enable_clks(struct mmc_omap_host *host) host->dbclk_enabled = 1; } + if (!(host->pdata->context_loss) || + (host->pdata->context_loss(host->dev) != host->off_counter)) { + /* Coming out of OFF: + * The SRA bit of SYSCTL reg has a wrong reset + * value. + * The bit resets automatically in subsequent + * reads. Idealy it should have been 0 as per + * the reset value of the register. + * Wait for the reset to complete */ + timeout = jiffies + + msecs_to_jiffies(MMC_TIMEOUT_MS); + while ((OMAP_HSMMC_READ(host->base, SYSSTATUS) + & RESETDONE) != RESETDONE + && time_before(jiffies, timeout)) + ; + omap2_hsmmc_restore_ctx(host); + } + done: spin_unlock_irqrestore(&host->clk_lock, flags); return ret; @@ -211,6 +267,10 @@ static void omap_hsmmc_disable_clks(struct mmc_omap_host *host) if (!host->clks_enabled) goto done; + omap2_hsmmc_save_ctx(host); + if (host->pdata->context_loss) + host->off_counter = host->pdata->context_loss(host->dev); + clk_disable(host->fclk); clk_disable(host->iclk); host->clks_enabled = 0; @@ -1094,6 +1154,8 @@ static int __init omap_mmc_probe(struct platform_device *pdev) host->inact_timer.data = (unsigned long) host; host->clks_enabled = 0; + host->off_counter = 0; + host->iclk = clk_get(&pdev->dev, "mmchs_ick"); if (IS_ERR(host->iclk)) { ret = PTR_ERR(host->iclk); Best regards, Elvis --- 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 diff --git a/arch/arm/plat-omap/include/mach/mmc.h b/arch/arm/plat-omap/include/mach/mmc.h index de23cc8..ae4eea8 100644 --- a/arch/arm/plat-omap/include/mach/mmc.h +++ b/arch/arm/plat-omap/include/mach/mmc.h @@ -62,6 +62,9 @@ struct omap_mmc_platform_data { int (*suspend)(struct device *dev, int slot); int (*resume)(struct device *dev, int slot); + /* To get the OFF mode counter */ + int (*context_loss) (struct device *dev); + diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index eb40a47..546b49d 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -150,14 +152,50 @@ struct mmc_omap_host { int slot_id; int dbclk_enabled; int clks_enabled; + int off_counter; spinlock_t clk_lock; struct timer_list inact_timer; struct omap_mmc_platform_data *pdata; }; @@ -190,6 +228,43 @@ static int omap_hsmmc_enable_clks(struct mmc_omap_host *host) host->dbclk_enabled = 1; } + if (host->pdata->context_loss) { + if (host->pdata->context_loss(host->dev) > 0) { + if (host->pdata->context_loss(host->dev) > + host->off_counter) { + /* Coming out of OFF: + * The SRA bit of SYSCTL reg has a wrong reset + * value. + * The bit resets automatically in subsequent + * reads. Idealy it should have been 0 as per + * the reset value of the register. + * Wait for the reset to complete */ + timeout = jiffies + + msecs_to_jiffies(MMC_TIMEOUT_MS); + while ((OMAP_HSMMC_READ(host->base, SYSSTATUS) + & RESETDONE) != RESETDONE + && time_before(jiffies, timeout)) + ; + omap2_hsmmc_restore_ctx(host); + } + } + } else { + /* Restore allways */ + /* Coming out of OFF: + * The SRA bit of SYSCTL reg has a wrong reset + * value. + * The bit resets automatically in subsequent + * reads. Idealy it should have been 0 as per + * the reset value of the register. + * Wait for the reset to complete */ + timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS); + while ((OMAP_HSMMC_READ(host->base, SYSSTATUS) + & RESETDONE) != RESETDONE + && time_before(jiffies, timeout)) + ; + omap2_hsmmc_restore_ctx(host); + } + done: spin_unlock_irqrestore(&host->clk_lock, flags); return ret; @@ -211,6 +286,10 @@ static void omap_hsmmc_disable_clks(struct mmc_omap_host *host) if (!host->clks_enabled) goto done; + omap2_hsmmc_save_ctx(host); + if (host->pdata->context_loss) + host->off_counter = host->pdata->context_loss(host->dev); + clk_disable(host->fclk); clk_disable(host->iclk); host->clks_enabled = 0; patch set 2 diff --git a/arch/arm/plat-omap/include/mach/mmc.h b/arch/arm/plat-omap/include/mach/mmc.h index de23cc8..94617d3 100644 --- a/arch/arm/plat-omap/include/mach/mmc.h +++ b/arch/arm/plat-omap/include/mach/mmc.h @@ -62,6 +62,9 @@ struct omap_mmc_platform_data { int (*suspend)(struct device *dev, int slot); int (*resume)(struct device *dev, int slot); + /* To get the OFF mode counter */ + unsigned (*context_loss) (struct device *dev); + diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index eb40a47..d9b962e 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -150,14 +152,50 @@ struct mmc_omap_host { int slot_id; int dbclk_enabled; int clks_enabled; + unsigned off_counter; spinlock_t clk_lock; struct timer_list inact_timer; struct omap_mmc_platform_data *pdata; }; @@ -150,14 +152,50 @@ struct mmc_omap_host { int slot_id; int dbclk_enabled; int clks_enabled; + unsigned off_counter; spinlock_t clk_lock; struct timer_list inact_timer; struct omap_mmc_platform_data *pdata; }; +struct omap_hsmmc_regs { + u32 hctl; + u32 capa; + u32 sysconfig; + u32 ise; + u32 ie; + u32 con; + u32 sysctl; +}; +static struct omap_hsmmc_regs hsmmc_ctx[3]; + +static void omap2_hsmmc_save_ctx(struct mmc_omap_host *host) +{ + /* MMC : context save */ + hsmmc_ctx[host->id].hctl = OMAP_HSMMC_READ(host->base, HCTL); + hsmmc_ctx[host->id].capa = OMAP_HSMMC_READ(host->base, CAPA); + hsmmc_ctx[host->id].ise = OMAP_HSMMC_READ(host->base, ISE); + hsmmc_ctx[host->id].ie = OMAP_HSMMC_READ(host->base, IE); + hsmmc_ctx[host->id].con = OMAP_HSMMC_READ(host->base, CON); + hsmmc_ctx[host->id].sysctl = OMAP_HSMMC_READ(host->base, SYSCTL); +} + +static void omap2_hsmmc_restore_ctx(struct mmc_omap_host *host) +{ + /* MMC : context restore */ + OMAP_HSMMC_WRITE(host->base, HCTL, hsmmc_ctx[host->id].hctl); + OMAP_HSMMC_WRITE(host->base, CAPA, hsmmc_ctx[host->id].capa); + OMAP_HSMMC_WRITE(host->base, CON, hsmmc_ctx[host->id].con); + OMAP_HSMMC_WRITE(host->base, ISE, hsmmc_ctx[host->id].ise); + OMAP_HSMMC_WRITE(host->base, IE, hsmmc_ctx[host->id].ie); + OMAP_HSMMC_WRITE(host->base, SYSCTL, hsmmc_ctx[host->id].sysctl);