Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
[linux-drm-fsl-dcu.git] / drivers / mmc / sdhci.c
index c2d13d7e99111f986e4c4d136f3c72ba95a5f4d8..7522f76b15ec48db85c9c3091dfb4a933d2ca3ab 100644 (file)
@@ -22,9 +22,6 @@
 #include "sdhci.h"
 
 #define DRIVER_NAME "sdhci"
-#define DRIVER_VERSION "0.12"
-
-#define BUGMAIL "<sdhci-devel@list.drzeus.cx>"
 
 #define DBG(f, x...) \
        pr_debug(DRIVER_NAME " [%s()]: " f, __func__,## x)
@@ -37,6 +34,7 @@ static unsigned int debug_quirks = 0;
 #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)
+#define SDHCI_QUIRK_SINGLE_POWER_WRITE                 (1<<3)
 
 static const struct pci_device_id pci_ids[] __devinitdata = {
        {
@@ -65,6 +63,14 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
                .driver_data    = SDHCI_QUIRK_FORCE_DMA,
        },
 
+       {
+               .vendor         = PCI_VENDOR_ID_ENE,
+               .device         = PCI_DEVICE_ID_ENE_CB712_SD,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .driver_data    = SDHCI_QUIRK_SINGLE_POWER_WRITE,
+       },
+
        {       /* Generic SD host controller */
                PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00)
        },
@@ -145,8 +151,7 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask)
        /* hw clears the bit when it's done */
        while (readb(host->ioaddr + SDHCI_SOFTWARE_RESET) & mask) {
                if (timeout == 0) {
-                       printk(KERN_ERR "%s: Reset 0x%x never completed. "
-                               "Please report this to " BUGMAIL ".\n",
+                       printk(KERN_ERR "%s: Reset 0x%x never completed.\n",
                                mmc_hostname(host->mmc), (int)mask);
                        sdhci_dumpregs(host);
                        return;
@@ -197,15 +202,9 @@ static void sdhci_deactivate_led(struct sdhci_host *host)
  *                                                                           *
 \*****************************************************************************/
 
-static inline char* sdhci_kmap_sg(struct sdhci_host* host)
+static inline char* sdhci_sg_to_buffer(struct sdhci_host* host)
 {
-       host->mapped_sg = kmap_atomic(host->cur_sg->page, KM_BIO_SRC_IRQ);
-       return host->mapped_sg + host->cur_sg->offset;
-}
-
-static inline void sdhci_kunmap_sg(struct sdhci_host* host)
-{
-       kunmap_atomic(host->mapped_sg, KM_BIO_SRC_IRQ);
+       return page_address(host->cur_sg->page) + host->cur_sg->offset;
 }
 
 static inline int sdhci_next_sg(struct sdhci_host* host)
@@ -240,7 +239,7 @@ static void sdhci_read_block_pio(struct sdhci_host *host)
        chunk_remain = 0;
        data = 0;
 
-       buffer = sdhci_kmap_sg(host) + host->offset;
+       buffer = sdhci_sg_to_buffer(host) + host->offset;
 
        while (blksize) {
                if (chunk_remain == 0) {
@@ -264,16 +263,13 @@ static void sdhci_read_block_pio(struct sdhci_host *host)
                }
 
                if (host->remain == 0) {
-                       sdhci_kunmap_sg(host);
                        if (sdhci_next_sg(host) == 0) {
                                BUG_ON(blksize != 0);
                                return;
                        }
-                       buffer = sdhci_kmap_sg(host);
+                       buffer = sdhci_sg_to_buffer(host);
                }
        }
-
-       sdhci_kunmap_sg(host);
 }
 
 static void sdhci_write_block_pio(struct sdhci_host *host)
@@ -290,7 +286,7 @@ static void sdhci_write_block_pio(struct sdhci_host *host)
        data = 0;
 
        bytes = 0;
-       buffer = sdhci_kmap_sg(host) + host->offset;
+       buffer = sdhci_sg_to_buffer(host) + host->offset;
 
        while (blksize) {
                size = min(host->size, host->remain);
@@ -314,16 +310,13 @@ static void sdhci_write_block_pio(struct sdhci_host *host)
                }
 
                if (host->remain == 0) {
-                       sdhci_kunmap_sg(host);
                        if (sdhci_next_sg(host) == 0) {
                                BUG_ON(blksize != 0);
                                return;
                        }
-                       buffer = sdhci_kmap_sg(host);
+                       buffer = sdhci_sg_to_buffer(host);
                }
        }
-
-       sdhci_kunmap_sg(host);
 }
 
 static void sdhci_transfer_pio(struct sdhci_host *host)
@@ -372,7 +365,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
 
        /* Sanity checks */
        BUG_ON(data->blksz * data->blocks > 524288);
-       BUG_ON(data->blksz > host->max_block);
+       BUG_ON(data->blksz > host->mmc->max_blk_size);
        BUG_ON(data->blocks > 65535);
 
        /* timeout in us */
@@ -477,12 +470,11 @@ static void sdhci_finish_data(struct sdhci_host *host)
 
        if ((data->error == MMC_ERR_NONE) && blocks) {
                printk(KERN_ERR "%s: Controller signalled completion even "
-                       "though there were blocks left. Please report this "
-                       "to " BUGMAIL ".\n", mmc_hostname(host->mmc));
+                       "though there were blocks left.\n",
+                       mmc_hostname(host->mmc));
                data->error = MMC_ERR_FAILED;
        } else if (host->size != 0) {
-               printk(KERN_ERR "%s: %d bytes were left untransferred. "
-                       "Please report this to " BUGMAIL ".\n",
+               printk(KERN_ERR "%s: %d bytes were left untransferred.\n",
                        mmc_hostname(host->mmc), host->size);
                data->error = MMC_ERR_FAILED;
        }
@@ -529,8 +521,7 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
        while (readl(host->ioaddr + SDHCI_PRESENT_STATE) & mask) {
                if (timeout == 0) {
                        printk(KERN_ERR "%s: Controller never released "
-                               "inhibit bit(s). Please report this to "
-                               BUGMAIL ".\n", mmc_hostname(host->mmc));
+                               "inhibit bit(s).\n", mmc_hostname(host->mmc));
                        sdhci_dumpregs(host);
                        cmd->error = MMC_ERR_FAILED;
                        tasklet_schedule(&host->finish_tasklet);
@@ -551,8 +542,7 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
        sdhci_set_transfer_mode(host, cmd->data);
 
        if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) {
-               printk(KERN_ERR "%s: Unsupported response type! "
-                       "Please report this to " BUGMAIL ".\n",
+               printk(KERN_ERR "%s: Unsupported response type!\n",
                        mmc_hostname(host->mmc));
                cmd->error = MMC_ERR_INVALID;
                tasklet_schedule(&host->finish_tasklet);
@@ -650,9 +640,8 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
        while (!((clk = readw(host->ioaddr + SDHCI_CLOCK_CONTROL))
                & SDHCI_CLOCK_INT_STABLE)) {
                if (timeout == 0) {
-                       printk(KERN_ERR "%s: Internal clock never stabilised. "
-                               "Please report this to " BUGMAIL ".\n",
-                               mmc_hostname(host->mmc));
+                       printk(KERN_ERR "%s: Internal clock never "
+                               "stabilised.\n", mmc_hostname(host->mmc));
                        sdhci_dumpregs(host);
                        return;
                }
@@ -674,10 +663,17 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
        if (host->power == power)
                return;
 
-       writeb(0, host->ioaddr + SDHCI_POWER_CONTROL);
-
-       if (power == (unsigned short)-1)
+       if (power == (unsigned short)-1) {
+               writeb(0, host->ioaddr + SDHCI_POWER_CONTROL);
                goto out;
+       }
+
+       /*
+        * Spec says that we should clear the power reg before setting
+        * a new value. Some controllers don't seem to like this though.
+        */
+       if (!(host->chip->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE))
+               writeb(0, host->ioaddr + SDHCI_POWER_CONTROL);
 
        pwr = SDHCI_POWER_ON;
 
@@ -895,9 +891,8 @@ static void sdhci_timeout_timer(unsigned long data)
        spin_lock_irqsave(&host->lock, flags);
 
        if (host->mrq) {
-               printk(KERN_ERR "%s: Timeout waiting for hardware interrupt. "
-                       "Please report this to " BUGMAIL ".\n",
-                       mmc_hostname(host->mmc));
+               printk(KERN_ERR "%s: Timeout waiting for hardware "
+                       "interrupt.\n", mmc_hostname(host->mmc));
                sdhci_dumpregs(host);
 
                if (host->data) {
@@ -931,8 +926,6 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
                printk(KERN_ERR "%s: Got command interrupt even though no "
                        "command operation was in progress.\n",
                        mmc_hostname(host->mmc));
-               printk(KERN_ERR "%s: Please report this to " BUGMAIL ".\n",
-                       mmc_hostname(host->mmc));
                sdhci_dumpregs(host);
                return;
        }
@@ -968,8 +961,6 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
                printk(KERN_ERR "%s: Got data interrupt even though no "
                        "data operation was in progress.\n",
                        mmc_hostname(host->mmc));
-               printk(KERN_ERR "%s: Please report this to " BUGMAIL ".\n",
-                       mmc_hostname(host->mmc));
                sdhci_dumpregs(host);
 
                return;
@@ -1041,8 +1032,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
        intmask &= SDHCI_INT_BUS_POWER;
 
        if (intmask) {
-               printk(KERN_ERR "%s: Unexpected interrupt 0x%08x. Please "
-                       "report this to " BUGMAIL ".\n",
+               printk(KERN_ERR "%s: Unexpected interrupt 0x%08x.\n",
                        mmc_hostname(host->mmc), intmask);
                sdhci_dumpregs(host);
 
@@ -1109,7 +1099,9 @@ static int sdhci_resume (struct pci_dev *pdev)
 
        pci_set_power_state(pdev, PCI_D0);
        pci_restore_state(pdev);
-       pci_enable_device(pdev);
+       ret = pci_enable_device(pdev);
+       if (ret)
+               return ret;
 
        for (i = 0;i < chip->num_slots;i++) {
                if (!chip->hosts[i])
@@ -1274,15 +1266,6 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
        if (caps & SDHCI_TIMEOUT_CLK_UNIT)
                host->timeout_clk *= 1000;
 
-       host->max_block = (caps & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT;
-       if (host->max_block >= 3) {
-               printk(KERN_ERR "%s: Invalid maximum block size.\n",
-                       host->slot_descr);
-               ret = -ENODEV;
-               goto unmap;
-       }
-       host->max_block = 512 << host->max_block;
-
        /*
         * Set host parameters.
         */
@@ -1294,9 +1277,9 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
        mmc->ocr_avail = 0;
        if (caps & SDHCI_CAN_VDD_330)
                mmc->ocr_avail |= MMC_VDD_32_33|MMC_VDD_33_34;
-       else if (caps & SDHCI_CAN_VDD_300)
+       if (caps & SDHCI_CAN_VDD_300)
                mmc->ocr_avail |= MMC_VDD_29_30|MMC_VDD_30_31;
-       else if (caps & SDHCI_CAN_VDD_180)
+       if (caps & SDHCI_CAN_VDD_180)
                mmc->ocr_avail |= MMC_VDD_17_18|MMC_VDD_18_19;
 
        if ((host->max_clk > 25000000) && !(caps & SDHCI_CAN_DO_HISPD)) {
@@ -1326,15 +1309,33 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
 
        /*
         * Maximum number of sectors in one transfer. Limited by DMA boundary
-        * size (512KiB), which means (512 KiB/512=) 1024 entries.
+        * size (512KiB).
         */
-       mmc->max_sectors = 1024;
+       mmc->max_req_size = 524288;
 
        /*
         * Maximum segment size. Could be one segment with the maximum number
-        * of sectors.
+        * of bytes.
+        */
+       mmc->max_seg_size = mmc->max_req_size;
+
+       /*
+        * Maximum block size. This varies from controller to controller and
+        * is specified in the capabilities register.
+        */
+       mmc->max_blk_size = (caps & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT;
+       if (mmc->max_blk_size >= 3) {
+               printk(KERN_ERR "%s: Invalid maximum block size.\n",
+                       host->slot_descr);
+               ret = -ENODEV;
+               goto unmap;
+       }
+       mmc->max_blk_size = 512 << mmc->max_blk_size;
+
+       /*
+        * Maximum block count.
         */
-       mmc->max_seg_size = mmc->max_sectors * 512;
+       mmc->max_blk_count = 65535;
 
        /*
         * Init tasklets.
@@ -1513,8 +1514,7 @@ static struct pci_driver sdhci_driver = {
 static int __init sdhci_drv_init(void)
 {
        printk(KERN_INFO DRIVER_NAME
-               ": Secure Digital Host Controller Interface driver, "
-               DRIVER_VERSION "\n");
+               ": Secure Digital Host Controller Interface driver\n");
        printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n");
 
        return pci_register_driver(&sdhci_driver);
@@ -1536,7 +1536,6 @@ module_param(debug_quirks, uint, 0444);
 
 MODULE_AUTHOR("Pierre Ossman <drzeus@drzeus.cx>");
 MODULE_DESCRIPTION("Secure Digital Host Controller Interface driver");
-MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL");
 
 MODULE_PARM_DESC(debug_nodma, "Forcefully disable DMA transfers. (default 0)");