sdhci: support JMicron JMB38x chips
authorPierre Ossman <drzeus@drzeus.cx>
Sun, 2 Dec 2007 18:58:16 +0000 (19:58 +0100)
committerPierre Ossman <drzeus@drzeus.cx>
Wed, 12 Dec 2007 19:01:00 +0000 (20:01 +0100)
The JMicron JMB38x chip doesn't support transfers that aren't 32-bit
aligned (both size and start address). It also doesn't like switching
between PIO and DMA mode, so it needs to be reset after each request.

Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
drivers/mmc/host/sdhci.c
include/linux/pci_ids.h

index a5300f2..785bbdc 100644 (file)
@@ -7,6 +7,10 @@
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or (at
  * your option) any later version.
+ *
+ * Thanks to the following companies for their support:
+ *
+ *     - JMicron (hardware and technical support)
  */
 
 #include <linux/delay.h>
@@ -47,6 +51,8 @@ static unsigned int debug_quirks = 0;
 #define SDHCI_QUIRK_32BIT_DMA_ADDR                     (1<<6)
 /* Controller can only DMA chunk sizes that are a multiple of 32 bits */
 #define SDHCI_QUIRK_32BIT_DMA_SIZE                     (1<<7)
+/* Controller needs to be reset after each request to stay stable */
+#define SDHCI_QUIRK_RESET_AFTER_REQUEST                        (1<<8)
 
 static const struct pci_device_id pci_ids[] __devinitdata = {
        {
@@ -111,6 +117,16 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
                                  SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS,
        },
 
+       {
+               .vendor         = PCI_VENDOR_ID_JMICRON,
+               .device         = PCI_DEVICE_ID_JMICRON_JMB38X_SD,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .driver_data    = SDHCI_QUIRK_32BIT_DMA_ADDR |
+                                 SDHCI_QUIRK_32BIT_DMA_SIZE |
+                                 SDHCI_QUIRK_RESET_AFTER_REQUEST,
+       },
+
        {       /* Generic SD host controller */
                PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00)
        },
@@ -922,7 +938,8 @@ static void sdhci_tasklet_finish(unsigned long param)
         */
        if (mrq->cmd->error ||
                (mrq->data && (mrq->data->error ||
-               (mrq->data->stop && mrq->data->stop->error)))) {
+               (mrq->data->stop && mrq->data->stop->error))) ||
+               (host->chip->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST)) {
 
                /* Some controllers need this kick or reset won't work here */
                if (host->chip->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) {
index 111aa10..023656d 100644 (file)
 #define PCI_DEVICE_ID_JMICRON_JMB365   0x2365
 #define PCI_DEVICE_ID_JMICRON_JMB366   0x2366
 #define PCI_DEVICE_ID_JMICRON_JMB368   0x2368
+#define PCI_DEVICE_ID_JMICRON_JMB38X_SD        0x2381
 
 #define PCI_VENDOR_ID_KORENIX          0x1982
 #define PCI_DEVICE_ID_KORENIX_JETCARDF0        0x1600