sdhci: remove custom controller name
[deliverable/linux.git] / drivers / mmc / host / sdhci.c
index d7c5b94d8c583de00136f8c8f2e435347375b497..71e020d6718db2329f2154a2b90bb86fbd7ef06f 100644 (file)
@@ -1,12 +1,16 @@
 /*
  *  linux/drivers/mmc/host/sdhci.c - Secure Digital Host Controller Interface driver
  *
- *  Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved.
+ *  Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * 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>
@@ -17,8 +21,6 @@
 
 #include <linux/mmc/host.h>
 
-#include <asm/scatterlist.h>
-
 #include "sdhci.h"
 
 #define DRIVER_NAME "sdhci"
 
 static unsigned int debug_quirks = 0;
 
+/*
+ * Different quirks to handle when the hardware deviates from a strict
+ * interpretation of the SDHCI specification.
+ */
+
+/* Controller doesn't honor resets unless we touch the clock register */
 #define SDHCI_QUIRK_CLOCK_BEFORE_RESET                 (1<<0)
+/* Controller has bad caps bits, but really supports DMA */
 #define SDHCI_QUIRK_FORCE_DMA                          (1<<1)
 /* Controller doesn't like some resets when there is no card inserted. */
 #define SDHCI_QUIRK_NO_CARD_NO_RESET                   (1<<2)
+/* Controller doesn't like clearing the power reg before a change */
 #define SDHCI_QUIRK_SINGLE_POWER_WRITE                 (1<<3)
+/* Controller has flaky internal state so reset it on each ios change */
 #define SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS              (1<<4)
+/* Controller has an unusable DMA engine */
 #define SDHCI_QUIRK_BROKEN_DMA                         (1<<5)
+/* Controller can only DMA from 32-bit aligned addresses */
+#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 = {
        {
@@ -99,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)
        },
@@ -421,7 +449,29 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
 
        writeb(count, host->ioaddr + SDHCI_TIMEOUT_CONTROL);
 
-       if (host->flags & SDHCI_USE_DMA) {
+       if (host->flags & SDHCI_USE_DMA)
+               host->flags |= SDHCI_REQ_USE_DMA;
+
+       if (unlikely((host->flags & SDHCI_REQ_USE_DMA) &&
+               (host->chip->quirks & SDHCI_QUIRK_32BIT_DMA_SIZE) &&
+               ((data->blksz * data->blocks) & 0x3))) {
+               DBG("Reverting to PIO because of transfer size (%d)\n",
+                       data->blksz * data->blocks);
+               host->flags &= ~SDHCI_REQ_USE_DMA;
+       }
+
+       /*
+        * The assumption here being that alignment is the same after
+        * translation to device address space.
+        */
+       if (unlikely((host->flags & SDHCI_REQ_USE_DMA) &&
+               (host->chip->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) &&
+               (data->sg->offset & 0x3))) {
+               DBG("Reverting to PIO because of bad alignment\n");
+               host->flags &= ~SDHCI_REQ_USE_DMA;
+       }
+
+       if (host->flags & SDHCI_REQ_USE_DMA) {
                int count;
 
                count = pci_map_sg(host->chip->pdev, data->sg, data->sg_len,
@@ -458,7 +508,7 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host,
                mode |= SDHCI_TRNS_MULTI;
        if (data->flags & MMC_DATA_READ)
                mode |= SDHCI_TRNS_READ;
-       if (host->flags & SDHCI_USE_DMA)
+       if (host->flags & SDHCI_REQ_USE_DMA)
                mode |= SDHCI_TRNS_DMA;
 
        writew(mode, host->ioaddr + SDHCI_TRANSFER_MODE);
@@ -474,7 +524,7 @@ static void sdhci_finish_data(struct sdhci_host *host)
        data = host->data;
        host->data = NULL;
 
-       if (host->flags & SDHCI_USE_DMA) {
+       if (host->flags & SDHCI_REQ_USE_DMA) {
                pci_unmap_sg(host->chip->pdev, data->sg, data->sg_len,
                        (data->flags & MMC_DATA_READ)?PCI_DMA_FROMDEVICE:PCI_DMA_TODEVICE);
        }
@@ -888,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) {
@@ -1050,7 +1101,8 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
                goto out;
        }
 
-       DBG("*** %s got interrupt: 0x%08x\n", host->slot_descr, intmask);
+       DBG("*** %s got interrupt: 0x%08x\n",
+               mmc_hostname(host->mmc), intmask);
 
        if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
                writel(intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE),
@@ -1180,7 +1232,7 @@ static int sdhci_resume (struct pci_dev *pdev)
                if (chip->hosts[i]->flags & SDHCI_USE_DMA)
                        pci_set_master(pdev);
                ret = request_irq(chip->hosts[i]->irq, sdhci_irq,
-                       IRQF_SHARED, chip->hosts[i]->slot_descr,
+                       IRQF_SHARED, mmc_hostname(chip->hosts[i]->mmc),
                        chip->hosts[i]);
                if (ret)
                        return ret;
@@ -1269,9 +1321,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
 
        DBG("slot %d at 0x%08lx, irq %d\n", slot, host->addr, host->irq);
 
-       snprintf(host->slot_descr, 20, "sdhci:slot%d", slot);
-
-       ret = pci_request_region(pdev, host->bar, host->slot_descr);
+       ret = pci_request_region(pdev, host->bar, mmc_hostname(mmc));
        if (ret)
                goto free;
 
@@ -1286,9 +1336,9 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
 
        version = readw(host->ioaddr + SDHCI_HOST_VERSION);
        version = (version & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT;
-       if (version != 0) {
+       if (version > 1) {
                printk(KERN_ERR "%s: Unknown controller version (%d). "
-                       "You may experience problems.\n", host->slot_descr,
+                       "You may experience problems.\n", mmc_hostname(mmc),
                        version);
        }
 
@@ -1303,7 +1353,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
 
        if ((chip->quirks & SDHCI_QUIRK_BROKEN_DMA) &&
                (host->flags & SDHCI_USE_DMA)) {
-               DBG("Disabling DMA as it is marked broken");
+               DBG("Disabling DMA as it is marked broken\n");
                host->flags &= ~SDHCI_USE_DMA;
        }
 
@@ -1311,13 +1361,13 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
                (host->flags & SDHCI_USE_DMA)) {
                printk(KERN_WARNING "%s: Will use DMA "
                        "mode even though HW doesn't fully "
-                       "claim to support it.\n", host->slot_descr);
+                       "claim to support it.\n", mmc_hostname(mmc));
        }
 
        if (host->flags & SDHCI_USE_DMA) {
                if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
                        printk(KERN_WARNING "%s: No suitable DMA available. "
-                               "Falling back to PIO.\n", host->slot_descr);
+                               "Falling back to PIO.\n", mmc_hostname(mmc));
                        host->flags &= ~SDHCI_USE_DMA;
                }
        }
@@ -1331,7 +1381,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
                (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT;
        if (host->max_clk == 0) {
                printk(KERN_ERR "%s: Hardware doesn't specify base clock "
-                       "frequency.\n", host->slot_descr);
+                       "frequency.\n", mmc_hostname(mmc));
                ret = -ENODEV;
                goto unmap;
        }
@@ -1341,7 +1391,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
                (caps & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT;
        if (host->timeout_clk == 0) {
                printk(KERN_ERR "%s: Hardware doesn't specify timeout clock "
-                       "frequency.\n", host->slot_descr);
+                       "frequency.\n", mmc_hostname(mmc));
                ret = -ENODEV;
                goto unmap;
        }
@@ -1369,7 +1419,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
 
        if (mmc->ocr_avail == 0) {
                printk(KERN_ERR "%s: Hardware doesn't report any "
-                       "support voltages.\n", host->slot_descr);
+                       "support voltages.\n", mmc_hostname(mmc));
                ret = -ENODEV;
                goto unmap;
        }
@@ -1403,8 +1453,8 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
         */
        mmc->max_blk_size = (caps & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT;
        if (mmc->max_blk_size >= 3) {
-               printk(KERN_WARNING "%s: Invalid maximum block size, assuming 512\n",
-                       host->slot_descr);
+               printk(KERN_WARNING "%s: Invalid maximum block size, "
+                       "assuming 512 bytes\n", mmc_hostname(mmc));
                mmc->max_blk_size = 512;
        } else
                mmc->max_blk_size = 512 << mmc->max_blk_size;
@@ -1425,7 +1475,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
        setup_timer(&host->timer, sdhci_timeout_timer, (unsigned long)host);
 
        ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
-               host->slot_descr, host);
+               mmc_hostname(mmc), host);
        if (ret)
                goto untasklet;
 
@@ -1439,8 +1489,8 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
 
        mmc_add_host(mmc);
 
-       printk(KERN_INFO "%s: SDHCI at 0x%08lx irq %d %s\n", mmc_hostname(mmc),
-               host->addr, host->irq,
+       printk(KERN_INFO "%s: SDHCI at 0x%08lx irq %d %s\n",
+               mmc_hostname(mmc), host->addr, host->irq,
                (host->flags & SDHCI_USE_DMA)?"DMA":"PIO");
 
        return 0;
This page took 0.035653 seconds and 5 git commands to generate.