Merge branch 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[pandora-kernel.git] / drivers / mmc / host / sdhci-pci.c
index f8b5f37..26c5286 100644 (file)
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
 #include <linux/device.h>
-
 #include <linux/mmc/host.h>
-
-#include <asm/scatterlist.h>
-#include <asm/io.h>
+#include <linux/scatterlist.h>
+#include <linux/io.h>
 
 #include "sdhci.h"
 
@@ -46,14 +44,14 @@ struct sdhci_pci_slot;
 struct sdhci_pci_fixes {
        unsigned int            quirks;
 
-       int                     (*probe)(struct sdhci_pci_chip*);
+       int                     (*probe) (struct sdhci_pci_chip *);
 
-       int                     (*probe_slot)(struct sdhci_pci_slot*);
-       void                    (*remove_slot)(struct sdhci_pci_slot*, int);
+       int                     (*probe_slot) (struct sdhci_pci_slot *);
+       void                    (*remove_slot) (struct sdhci_pci_slot *, int);
 
-       int                     (*suspend)(struct sdhci_pci_chip*,
+       int                     (*suspend) (struct sdhci_pci_chip *,
                                        pm_message_t);
-       int                     (*resume)(struct sdhci_pci_chip*);
+       int                     (*resume) (struct sdhci_pci_chip *);
 };
 
 struct sdhci_pci_slot {
@@ -145,6 +143,12 @@ static const struct sdhci_pci_fixes sdhci_cafe = {
                          SDHCI_QUIRK_BROKEN_TIMEOUT_VAL,
 };
 
+static int mrst_hc_probe_slot(struct sdhci_pci_slot *slot)
+{
+       slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA;
+       return 0;
+}
+
 /*
  * ADMA operation is disabled for Moorestown platform due to
  * hardware bugs.
@@ -159,8 +163,15 @@ static int mrst_hc_probe(struct sdhci_pci_chip *chip)
        return 0;
 }
 
+static int mfd_emmc_probe_slot(struct sdhci_pci_slot *slot)
+{
+       slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA;
+       return 0;
+}
+
 static const struct sdhci_pci_fixes sdhci_intel_mrst_hc0 = {
        .quirks         = SDHCI_QUIRK_BROKEN_ADMA | SDHCI_QUIRK_NO_HISPD_BIT,
+       .probe_slot     = mrst_hc_probe_slot,
 };
 
 static const struct sdhci_pci_fixes sdhci_intel_mrst_hc1_hc2 = {
@@ -172,10 +183,15 @@ static const struct sdhci_pci_fixes sdhci_intel_mfd_sd = {
        .quirks         = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
 };
 
-static const struct sdhci_pci_fixes sdhci_intel_mfd_emmc_sdio = {
+static const struct sdhci_pci_fixes sdhci_intel_mfd_sdio = {
        .quirks         = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
 };
 
+static const struct sdhci_pci_fixes sdhci_intel_mfd_emmc = {
+       .quirks         = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
+       .probe_slot     = mfd_emmc_probe_slot,
+};
+
 /* O2Micro extra registers */
 #define O2_SD_LOCK_WP          0xD3
 #define O2_SD_MULTI_VCC3V      0xEE
@@ -329,6 +345,11 @@ static int jmicron_probe(struct sdhci_pci_chip *chip)
                return ret;
        }
 
+       /* quirk for unsable RO-detection on JM388 chips */
+       if (chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB388_SD ||
+           chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB388_ESD)
+               chip->quirks |= SDHCI_QUIRK_UNSTABLE_RO_DETECT;
+
        return 0;
 }
 
@@ -402,7 +423,7 @@ static int jmicron_suspend(struct sdhci_pci_chip *chip, pm_message_t state)
 
        if (chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC ||
            chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB388_ESD) {
-               for (i = 0;i < chip->num_slots;i++)
+               for (i = 0; i < chip->num_slots; i++)
                        jmicron_enable_mmc(chip->slots[i]->host, 0);
        }
 
@@ -415,7 +436,7 @@ static int jmicron_resume(struct sdhci_pci_chip *chip)
 
        if (chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC ||
            chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB388_ESD) {
-               for (i = 0;i < chip->num_slots;i++)
+               for (i = 0; i < chip->num_slots; i++)
                        jmicron_enable_mmc(chip->slots[i]->host, 1);
        }
 
@@ -679,7 +700,7 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
                .device         = PCI_DEVICE_ID_INTEL_MFD_SDIO1,
                .subvendor      = PCI_ANY_ID,
                .subdevice      = PCI_ANY_ID,
-               .driver_data    = (kernel_ulong_t)&sdhci_intel_mfd_emmc_sdio,
+               .driver_data    = (kernel_ulong_t)&sdhci_intel_mfd_sdio,
        },
 
        {
@@ -687,7 +708,7 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
                .device         = PCI_DEVICE_ID_INTEL_MFD_SDIO2,
                .subvendor      = PCI_ANY_ID,
                .subdevice      = PCI_ANY_ID,
-               .driver_data    = (kernel_ulong_t)&sdhci_intel_mfd_emmc_sdio,
+               .driver_data    = (kernel_ulong_t)&sdhci_intel_mfd_sdio,
        },
 
        {
@@ -695,7 +716,7 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
                .device         = PCI_DEVICE_ID_INTEL_MFD_EMMC0,
                .subvendor      = PCI_ANY_ID,
                .subdevice      = PCI_ANY_ID,
-               .driver_data    = (kernel_ulong_t)&sdhci_intel_mfd_emmc_sdio,
+               .driver_data    = (kernel_ulong_t)&sdhci_intel_mfd_emmc,
        },
 
        {
@@ -703,7 +724,7 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
                .device         = PCI_DEVICE_ID_INTEL_MFD_EMMC1,
                .subvendor      = PCI_ANY_ID,
                .subdevice      = PCI_ANY_ID,
-               .driver_data    = (kernel_ulong_t)&sdhci_intel_mfd_emmc_sdio,
+               .driver_data    = (kernel_ulong_t)&sdhci_intel_mfd_emmc,
        },
 
        {
@@ -786,8 +807,34 @@ static int sdhci_pci_enable_dma(struct sdhci_host *host)
        return 0;
 }
 
+static int sdhci_pci_8bit_width(struct sdhci_host *host, int width)
+{
+       u8 ctrl;
+
+       ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
+
+       switch (width) {
+       case MMC_BUS_WIDTH_8:
+               ctrl |= SDHCI_CTRL_8BITBUS;
+               ctrl &= ~SDHCI_CTRL_4BITBUS;
+               break;
+       case MMC_BUS_WIDTH_4:
+               ctrl |= SDHCI_CTRL_4BITBUS;
+               ctrl &= ~SDHCI_CTRL_8BITBUS;
+               break;
+       default:
+               ctrl &= ~(SDHCI_CTRL_8BITBUS | SDHCI_CTRL_4BITBUS);
+               break;
+       }
+
+       sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
+
+       return 0;
+}
+
 static struct sdhci_ops sdhci_pci_ops = {
        .enable_dma     = sdhci_pci_enable_dma,
+       .platform_8bit_width    = sdhci_pci_8bit_width,
 };
 
 /*****************************************************************************\
@@ -798,7 +845,7 @@ static struct sdhci_ops sdhci_pci_ops = {
 
 #ifdef CONFIG_PM
 
-static int sdhci_pci_suspend (struct pci_dev *pdev, pm_message_t state)
+static int sdhci_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 {
        struct sdhci_pci_chip *chip;
        struct sdhci_pci_slot *slot;
@@ -810,7 +857,7 @@ static int sdhci_pci_suspend (struct pci_dev *pdev, pm_message_t state)
        if (!chip)
                return 0;
 
-       for (i = 0;i < chip->num_slots;i++) {
+       for (i = 0; i < chip->num_slots; i++) {
                slot = chip->slots[i];
                if (!slot)
                        continue;
@@ -818,7 +865,7 @@ static int sdhci_pci_suspend (struct pci_dev *pdev, pm_message_t state)
                ret = sdhci_suspend_host(slot->host, state);
 
                if (ret) {
-                       for (i--;i >= 0;i--)
+                       for (i--; i >= 0; i--)
                                sdhci_resume_host(chip->slots[i]->host);
                        return ret;
                }
@@ -833,7 +880,7 @@ static int sdhci_pci_suspend (struct pci_dev *pdev, pm_message_t state)
        if (chip->fixes && chip->fixes->suspend) {
                ret = chip->fixes->suspend(chip, state);
                if (ret) {
-                       for (i = chip->num_slots - 1;i >= 0;i--)
+                       for (i = chip->num_slots - 1; i >= 0; i--)
                                sdhci_resume_host(chip->slots[i]->host);
                        return ret;
                }
@@ -855,7 +902,7 @@ static int sdhci_pci_suspend (struct pci_dev *pdev, pm_message_t state)
        return 0;
 }
 
-static int sdhci_pci_resume (struct pci_dev *pdev)
+static int sdhci_pci_resume(struct pci_dev *pdev)
 {
        struct sdhci_pci_chip *chip;
        struct sdhci_pci_slot *slot;
@@ -877,7 +924,7 @@ static int sdhci_pci_resume (struct pci_dev *pdev)
                        return ret;
        }
 
-       for (i = 0;i < chip->num_slots;i++) {
+       for (i = 0; i < chip->num_slots; i++) {
                slot = chip->slots[i];
                if (!slot)
                        continue;
@@ -1059,7 +1106,7 @@ static int __devinit sdhci_pci_probe(struct pci_dev *pdev,
        }
 
        chip->pdev = pdev;
-       chip->fixes = (const struct sdhci_pci_fixes*)ent->driver_data;
+       chip->fixes = (const struct sdhci_pci_fixes *)ent->driver_data;
        if (chip->fixes)
                chip->quirks = chip->fixes->quirks;
        chip->num_slots = slots;
@@ -1074,10 +1121,10 @@ static int __devinit sdhci_pci_probe(struct pci_dev *pdev,
 
        slots = chip->num_slots;        /* Quirk may have changed this */
 
-       for (i = 0;i < slots;i++) {
+       for (i = 0; i < slots; i++) {
                slot = sdhci_pci_probe_slot(pdev, chip, first_bar + i);
                if (IS_ERR(slot)) {
-                       for (i--;i >= 0;i--)
+                       for (i--; i >= 0; i--)
                                sdhci_pci_remove_slot(chip->slots[i]);
                        ret = PTR_ERR(slot);
                        goto free;
@@ -1105,7 +1152,7 @@ static void __devexit sdhci_pci_remove(struct pci_dev *pdev)
        chip = pci_get_drvdata(pdev);
 
        if (chip) {
-               for (i = 0;i < chip->num_slots; i++)
+               for (i = 0; i < chip->num_slots; i++)
                        sdhci_pci_remove_slot(chip->slots[i]);
 
                pci_set_drvdata(pdev, NULL);
@@ -1116,9 +1163,9 @@ static void __devexit sdhci_pci_remove(struct pci_dev *pdev)
 }
 
 static struct pci_driver sdhci_driver = {
-       .name =         "sdhci-pci",
+       .name =         "sdhci-pci",
        .id_table =     pci_ids,
-       .probe =        sdhci_pci_probe,
+       .probe =        sdhci_pci_probe,
        .remove =       __devexit_p(sdhci_pci_remove),
        .suspend =      sdhci_pci_suspend,
        .resume =       sdhci_pci_resume,