mmc: sdhci-of-esdhc: disable CMD23 for some Freescale SoCs
authorJerry Huang <Chang-Ming.Huang@freescale.com>
Thu, 25 Oct 2012 05:47:19 +0000 (13:47 +0800)
committerChris Ball <cjb@laptop.org>
Wed, 7 Nov 2012 19:55:29 +0000 (14:55 -0500)
CMD23 causes lots of errors in kernel on some freescale SoCs
(P1020, P1021, P1022, P1024, P1025 and P4080) when MMC card used,
which is because these controllers does not support CMD23,
even on the SoCs which declares CMD23 is supported.
Therefore, we'll not use CMD23.

Signed-off-by: Jerry Huang <Chang-Ming.Huang@freescale.com>
Signed-off-by: Shaohui Xie <Shaohui.Xie@freescale.com>
Acked-by: Anton Vorontsov <cbouatmailru@gmail.com>
Signed-off-by: Chris Ball <cjb@laptop.org>
drivers/mmc/host/sdhci-of-esdhc.c
drivers/mmc/host/sdhci-pltfm.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/sdhci.h
include/linux/mmc/sdhci.h

index ae5fcbf..63d219f 100644 (file)
@@ -169,6 +169,16 @@ static void esdhc_of_resume(struct sdhci_host *host)
 }
 #endif
 
+static void esdhc_of_platform_init(struct sdhci_host *host)
+{
+       u32 vvn;
+
+       vvn = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS);
+       vvn = (vvn & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
+       if (vvn == VENDOR_V_22)
+               host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23;
+}
+
 static struct sdhci_ops sdhci_esdhc_ops = {
        .read_l = esdhc_readl,
        .read_w = esdhc_readw,
@@ -180,6 +190,7 @@ static struct sdhci_ops sdhci_esdhc_ops = {
        .enable_dma = esdhc_of_enable_dma,
        .get_max_clock = esdhc_of_get_max_clock,
        .get_min_clock = esdhc_of_get_min_clock,
+       .platform_init = esdhc_of_platform_init,
 #ifdef CONFIG_PM
        .platform_suspend = esdhc_of_suspend,
        .platform_resume = esdhc_of_resume,
index 65551a9..2716445 100644 (file)
@@ -150,6 +150,13 @@ struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
                goto err_remap;
        }
 
+       /*
+        * Some platforms need to probe the controller to be able to
+        * determine which caps should be used.
+        */
+       if (host->ops && host->ops->platform_init)
+               host->ops->platform_init(host);
+
        platform_set_drvdata(pdev, host);
 
        return host;
index 7922adb..f05a377 100644 (file)
@@ -2837,6 +2837,9 @@ int sdhci_add_host(struct sdhci_host *host)
        if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA))
                mmc->caps |= MMC_CAP_4_BIT_DATA;
 
+       if (host->quirks2 & SDHCI_QUIRK2_HOST_NO_CMD23)
+               mmc->caps &= ~MMC_CAP_CMD23;
+
        if (caps[0] & SDHCI_CAN_DO_HISPD)
                mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
 
index 97653ea..71a4a7e 100644 (file)
@@ -278,6 +278,7 @@ struct sdhci_ops {
        void    (*hw_reset)(struct sdhci_host *host);
        void    (*platform_suspend)(struct sdhci_host *host);
        void    (*platform_resume)(struct sdhci_host *host);
+       void    (*platform_init)(struct sdhci_host *host);
 };
 
 #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
index fa8529a..1edcb4d 100644 (file)
@@ -91,6 +91,7 @@ struct sdhci_host {
        unsigned int quirks2;   /* More deviations from spec. */
 
 #define SDHCI_QUIRK2_HOST_OFF_CARD_ON                  (1<<0)
+#define SDHCI_QUIRK2_HOST_NO_CMD23                     (1<<1)
 
        int irq;                /* Device IRQ */
        void __iomem *ioaddr;   /* Mapped address */