sdhci: Specific quirk vor VIA SDHCI controller in VX855ES
authorHarald Welte <HaraldWelte@viatech.com>
Thu, 18 Jun 2009 14:53:38 +0000 (16:53 +0200)
committerPierre Ossman <pierre@ossman.eu>
Sun, 21 Jun 2009 19:00:59 +0000 (21:00 +0200)
The SDHCI controller found in the VX855ES requires 10ms
delay between applying power and applying clock.

This issue has been discovered and documented by the OLPC XO1.5 team.

Signed-off-by: Harald Welte <HaraldWelte@viatech.com>
Signed-off-by: Pierre Ossman <pierre@ossman.eu>
drivers/mmc/host/sdhci-pci.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/sdhci.h

index 65be279..2f15cc1 100644 (file)
@@ -284,6 +284,18 @@ static const struct sdhci_pci_fixes sdhci_jmicron = {
        .resume         = jmicron_resume,
 };
 
+static int via_probe(struct sdhci_pci_chip *chip)
+{
+       if (chip->pdev->revision == 0x10)
+               chip->quirks |= SDHCI_QUIRK_DELAY_AFTER_POWER;
+
+       return 0;
+}
+
+static const struct sdhci_pci_fixes sdhci_via = {
+       .probe          = via_probe,
+};
+
 static const struct pci_device_id pci_ids[] __devinitdata = {
        {
                .vendor         = PCI_VENDOR_ID_RICOH,
@@ -349,6 +361,14 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
                .driver_data    = (kernel_ulong_t)&sdhci_jmicron,
        },
 
+       {
+               .vendor         = PCI_VENDOR_ID_VIA,
+               .device         = 0x95d0,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .driver_data    = (kernel_ulong_t)&sdhci_via,
+       },
+
        {       /* Generic SD host controller */
                PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00)
        },
index c758673..f4066fd 100644 (file)
@@ -1057,6 +1057,13 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
        pwr |= SDHCI_POWER_ON;
 
        sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
+
+       /*
+        * Some controllers need an extra 10ms delay of 10ms before they
+        * can apply clock after applying power
+        */
+       if ((host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER))
+               mdelay(10);
 }
 
 /*****************************************************************************\
index 5d37dd9..831ddf7 100644 (file)
@@ -230,6 +230,8 @@ struct sdhci_host {
 #define SDHCI_QUIRK_NO_MULTIBLOCK                      (1<<21)
 /* Controller can only handle 1-bit data transfers */
 #define SDHCI_QUIRK_FORCE_1_BIT_DATA                   (1<<22)
+/* Controller needs 10ms delay between applying power and clock */
+#define SDHCI_QUIRK_DELAY_AFTER_POWER                  (1<<23)
 
        int                     irq;            /* Device IRQ */
        void __iomem *          ioaddr;         /* Mapped address */