MMC: Tell emmc chip state to SCU via new field in Dekker mutex
authorSamu Onkalo <samu.onkalo@intel.com>
Fri, 27 Apr 2012 07:37:09 +0000 (10:37 +0300)
committerbuildbot <buildbot@intel.com>
Sun, 29 Apr 2012 19:43:16 +0000 (12:43 -0700)
BZ33846

SCU may access emmc while the kernel is between device suspend-resume
state. During that period the emmc chip is detached. SCU accesses fails
since the SCU doesn't power on the chip.
SCU must know the status of the emmc chip. Easiest way
is to pass the information from the kernel driver to SCU.

New field in the emmc dekker mutex may be updated only when
IA has successfully locked the mutex.

Change-Id: I9b9569d1b8d9f84fb9cf1b6ba96db99a65c08d4e
Signed-off-by: Samu Onkalo <samu.onkalo@intel.com>
Reviewed-on: http://android.intel.com:8080/46579
Reviewed-by: Dong, Chuanxiao <chuanxiao.dong@intel.com>
Reviewed-by: Koskinen, Ilkka <ilkka.koskinen@intel.com>
Tested-by: Sun, Jianhua <jianhua.sun@intel.com>
Reviewed-by: Tang, Richard <richard.tang@intel.com>
Reviewed-by: buildbot <buildbot@intel.com>
Tested-by: buildbot <buildbot@intel.com>
drivers/mmc/host/sdhci.c
include/linux/mmc/sdhci.h

index 3c6353f..b1b1610 100644 (file)
@@ -3222,6 +3222,13 @@ EXPORT_SYMBOL_GPL(sdhci_alloc_panic_host);
  * Suspend/resume                                                            *
  *                                                                           *
 \*****************************************************************************/
+static void sdhci_set_emmc_state(struct sdhci_host *host, uint32_t state)
+{
+       /* Only if there is dekker mutex available */
+       if (!host->sram_addr)
+               return;
+       writel(state, host->sram_addr + DEKKER_EMMC_STATE);
+}
 
 #ifdef CONFIG_PM
 
@@ -3245,6 +3252,8 @@ int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state)
        if (ret)
                goto out;
 
+       /* Card succesfully suspended. Tell information to SCU */
+       sdhci_set_emmc_state(host, DEKKER_EMMC_CHIP_SUSPENDED);
        free_irq(host->irq, host);
 
 out:
@@ -3274,6 +3283,8 @@ int sdhci_resume_host(struct sdhci_host *host)
        mmiowb();
 
        ret = mmc_resume_host(host->mmc);
+       /* Card back in active state */
+       sdhci_set_emmc_state(host, DEKKER_EMMC_CHIP_ACTIVE);
        sdhci_enable_card_detection(host);
 
        /* Set the re-tuning expiration flag */
index 5ae63cd..720f04e 100644 (file)
@@ -100,14 +100,22 @@ struct sdhci_host {
        int irq;                /* Device IRQ */
        void __iomem *ioaddr;   /* Mapped address */
 
-       /* XXX: SCU/X86 mutex variables base address in shared SRAM */
+       /*
+        * XXX: SCU/X86 mutex variables base address in shared SRAM
+        * NOTE: Max size of this struct is 16 bytes
+        * without shared SRAM re-organization.
+        */
        void __iomem *sram_addr;        /* Shared SRAM address */
 
        #define DEKKER_EMMC_OWNER_OFFSET        0
        #define DEKKER_IA_REQ_OFFSET            0x04
        #define DEKKER_SCU_REQ_OFFSET           0x08
+       /* 0xc offset: state of the emmc chip to SCU. */
+       #define DEKKER_EMMC_STATE               0x0c
        #define DEKKER_OWNER_IA                 0
        #define DEKKER_OWNER_SCU                1
+       #define DEKKER_EMMC_CHIP_ACTIVE         0
+       #define DEKKER_EMMC_CHIP_SUSPENDED      1
 
        atomic_t usage_cnt; /* eMMC mutex usage count */