sdhci: Adding new Quirk for the sdhci controller.
authorAymen Zayet <aymenx.zayet@intel.com>
Mon, 21 Nov 2011 13:33:05 +0000 (14:33 +0100)
committerbuildbot <buildbot@intel.com>
Mon, 28 Nov 2011 19:37:51 +0000 (11:37 -0800)
BZ: 15061

The SDHCI controller is not able to perform a soft reset on resume.
So SDHCI_QUIRK_CANNOT_KEEP_POWERCTL is added to reset completely the
sdhci controller rather than resetting CMD / DATA.

Without this quirk, the reset on resume  will never complete and the
system hangs.

Change-Id: I00f46558624b5a65deb7f49cceec6dc2af7b37b4
Signed-off-by: Aymen Zayet <aymenx.zayet@intel.com>
Reviewed-on: http://android.intel.com:8080/25375
Reviewed-by: Champciaux, NicolasX <nicolasx.champciaux@intel.com>
Tested-by: Champciaux, NicolasX <nicolasx.champciaux@intel.com>
Reviewed-by: buildbot <buildbot@intel.com>
Tested-by: buildbot <buildbot@intel.com>
drivers/mmc/host/sdhci-pci.c
drivers/mmc/host/sdhci.c
include/linux/mmc/sdhci.h

index 3be533c..90b4774 100644 (file)
@@ -48,6 +48,7 @@ struct sdhci_pci_slot;
 
 struct sdhci_pci_fixes {
        unsigned int            quirks;
+       unsigned int            quirks2;
 
        int                     (*probe) (struct sdhci_pci_chip *);
 
@@ -73,6 +74,7 @@ struct sdhci_pci_chip {
        struct pci_dev          *pdev;
 
        unsigned int            quirks;
+       unsigned int            quirks2;
        const struct sdhci_pci_fixes *fixes;
 
        int                     num_slots;      /* Slots on controller */
@@ -353,6 +355,13 @@ static void mfd_emmc_mutex_register(struct sdhci_pci_slot *slot)
        }
 }
 
+static int intel_mfld_sdio_probe_slot(struct sdhci_pci_slot *slot)
+{
+       struct sdhci_host *host = slot->host;
+       host->mmc->caps |= MMC_CAP_NONREMOVABLE;
+       return 0;
+}
+
 static int mfd_emmc_probe_slot(struct sdhci_pci_slot *slot)
 {
        const char *name = NULL;
@@ -410,6 +419,8 @@ static const struct sdhci_pci_fixes sdhci_intel_mfd_sd = {
 
 static const struct sdhci_pci_fixes sdhci_intel_mfd_sdio = {
        .quirks         = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
+       .quirks2        = SDHCI_QUIRK_CANNOT_KEEP_POWERCTL,
+       .probe_slot     = intel_mfld_sdio_probe_slot,
 };
 
 static const struct sdhci_pci_fixes sdhci_intel_mfd_emmc = {
@@ -1310,6 +1321,7 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
        host->hw_name = "PCI";
        host->ops = &sdhci_pci_ops;
        host->quirks = chip->quirks;
+       host->quirks2 = chip->quirks2;
 
        host->irq = pdev->irq;
 
@@ -1440,8 +1452,11 @@ static int __devinit sdhci_pci_probe(struct pci_dev *pdev,
 
        chip->pdev = pdev;
        chip->fixes = (const struct sdhci_pci_fixes *)ent->driver_data;
-       if (chip->fixes)
+       if (chip->fixes) {
                chip->quirks = chip->fixes->quirks;
+               chip->quirks2 = chip->fixes->quirks2;
+       }
+
        chip->num_slots = slots;
 
        pci_set_drvdata(pdev, chip);
index 8c4c99d..085e037 100644 (file)
@@ -248,7 +248,7 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios);
 
 static void sdhci_init(struct sdhci_host *host, int soft)
 {
-       if (soft)
+       if (soft && !(host->quirks2 & SDHCI_QUIRK_CANNOT_KEEP_POWERCTL))
                sdhci_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA);
        else
                sdhci_reset(host, SDHCI_RESET_ALL);
@@ -262,6 +262,8 @@ static void sdhci_init(struct sdhci_host *host, int soft)
        if (soft) {
                /* force clock reconfiguration */
                host->clock = 0;
+               if (host->quirks2 & SDHCI_QUIRK_CANNOT_KEEP_POWERCTL)
+                       host->pwr = 0; /* force power reprogram */
                sdhci_set_ios(host->mmc, &host->mmc->ios);
        }
 }
index be8bfcb..7b21c2b 100644 (file)
@@ -91,6 +91,9 @@ struct sdhci_host {
        unsigned int quirks2;   /* More deviations from spec. */
 
 #define SDHCI_QUIRK2_OWN_CARD_DETECTION                        (1<<0)
+/* Host controller cannot keep power control value after power off */
+#define SDHCI_QUIRK_CANNOT_KEEP_POWERCTL               (1<<1)
+
 
        int irq;                /* Device IRQ */
        void __iomem *ioaddr;   /* Mapped address */