Merge branch 'pm-runtime'
[cascardo/linux.git] / drivers / mmc / host / sdhci-pci.c
index 6119297..0342775 100644 (file)
@@ -134,7 +134,7 @@ static int pch_hc_probe_slot(struct sdhci_pci_slot *slot)
        return 0;
 }
 
-#ifdef CONFIG_PM_RUNTIME
+#ifdef CONFIG_PM
 
 static irqreturn_t sdhci_pci_sd_cd(int irq, void *dev_id)
 {
@@ -269,7 +269,9 @@ static void sdhci_pci_int_hw_reset(struct sdhci_host *host)
 static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot)
 {
        slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE |
-                                MMC_CAP_HW_RESET | MMC_CAP_1_8V_DDR;
+                                MMC_CAP_HW_RESET | MMC_CAP_1_8V_DDR |
+                                MMC_CAP_BUS_WIDTH_TEST |
+                                MMC_CAP_WAIT_WHILE_BUSY;
        slot->host->mmc->caps2 |= MMC_CAP2_HC_ERASE_SZ;
        slot->hw_reset = sdhci_pci_int_hw_reset;
        if (slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_BSW_EMMC)
@@ -279,12 +281,16 @@ static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot)
 
 static int byt_sdio_probe_slot(struct sdhci_pci_slot *slot)
 {
-       slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_NONREMOVABLE;
+       slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_NONREMOVABLE |
+                                MMC_CAP_BUS_WIDTH_TEST |
+                                MMC_CAP_WAIT_WHILE_BUSY;
        return 0;
 }
 
 static int byt_sd_probe_slot(struct sdhci_pci_slot *slot)
 {
+       slot->host->mmc->caps |= MMC_CAP_BUS_WIDTH_TEST |
+                                MMC_CAP_WAIT_WHILE_BUSY;
        slot->cd_con_id = NULL;
        slot->cd_idx = 0;
        slot->cd_override_level = true;
@@ -294,11 +300,13 @@ static int byt_sd_probe_slot(struct sdhci_pci_slot *slot)
 static const struct sdhci_pci_fixes sdhci_intel_byt_emmc = {
        .allow_runtime_pm = true,
        .probe_slot     = byt_emmc_probe_slot,
+       .quirks         = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
        .quirks2        = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
                          SDHCI_QUIRK2_STOP_WITH_TC,
 };
 
 static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = {
+       .quirks         = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
        .quirks2        = SDHCI_QUIRK2_HOST_OFF_CARD_ON |
                        SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
        .allow_runtime_pm = true,
@@ -306,6 +314,7 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = {
 };
 
 static const struct sdhci_pci_fixes sdhci_intel_byt_sd = {
+       .quirks         = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
        .quirks2        = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON |
                          SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
                          SDHCI_QUIRK2_STOP_WITH_TC,
@@ -645,6 +654,25 @@ static const struct sdhci_pci_fixes sdhci_rtsx = {
        .probe_slot     = rtsx_probe_slot,
 };
 
+static int amd_probe(struct sdhci_pci_chip *chip)
+{
+       struct pci_dev  *smbus_dev;
+
+       smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD,
+                       PCI_DEVICE_ID_AMD_HUDSON2_SMBUS, NULL);
+
+       if (smbus_dev && (smbus_dev->revision < 0x51)) {
+               chip->quirks2 |= SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD;
+               chip->quirks2 |= SDHCI_QUIRK2_BROKEN_HS200;
+       }
+
+       return 0;
+}
+
+static const struct sdhci_pci_fixes sdhci_amd = {
+       .probe          = amd_probe,
+};
+
 static const struct pci_device_id pci_ids[] = {
        {
                .vendor         = PCI_VENDOR_ID_RICOH,
@@ -1044,7 +1072,15 @@ static const struct pci_device_id pci_ids[] = {
                .subdevice      = PCI_ANY_ID,
                .driver_data    = (kernel_ulong_t)&sdhci_o2,
        },
-
+       {
+               .vendor         = PCI_VENDOR_ID_AMD,
+               .device         = PCI_ANY_ID,
+               .class          = PCI_CLASS_SYSTEM_SDHCI << 8,
+               .class_mask     = 0xFFFF00,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .driver_data    = (kernel_ulong_t)&sdhci_amd,
+       },
        {       /* Generic SD host controller */
                PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00)
        },
@@ -1064,7 +1100,7 @@ static int sdhci_pci_enable_dma(struct sdhci_host *host)
 {
        struct sdhci_pci_slot *slot;
        struct pci_dev *pdev;
-       int ret;
+       int ret = -1;
 
        slot = sdhci_priv(host);
        pdev = slot->chip->pdev;
@@ -1076,7 +1112,17 @@ static int sdhci_pci_enable_dma(struct sdhci_host *host)
                        "doesn't fully claim to support it.\n");
        }
 
-       ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+       if (host->flags & SDHCI_USE_64_BIT_DMA) {
+               if (host->quirks2 & SDHCI_QUIRK2_BROKEN_64_BIT_DMA) {
+                       host->flags &= ~SDHCI_USE_64_BIT_DMA;
+               } else {
+                       ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
+                       if (ret)
+                               dev_warn(&pdev->dev, "Failed to set 64-bit DMA mask\n");
+               }
+       }
+       if (ret)
+               ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
        if (ret)
                return ret;
 
@@ -1230,15 +1276,6 @@ static int sdhci_pci_resume(struct device *dev)
        return 0;
 }
 
-#else /* CONFIG_PM */
-
-#define sdhci_pci_suspend NULL
-#define sdhci_pci_resume NULL
-
-#endif /* CONFIG_PM */
-
-#ifdef CONFIG_PM_RUNTIME
-
 static int sdhci_pci_runtime_suspend(struct device *dev)
 {
        struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
@@ -1310,7 +1347,12 @@ static int sdhci_pci_runtime_idle(struct device *dev)
        return 0;
 }
 
-#endif
+#else /* CONFIG_PM */
+
+#define sdhci_pci_suspend NULL
+#define sdhci_pci_resume NULL
+
+#endif /* CONFIG_PM */
 
 static const struct dev_pm_ops sdhci_pci_pm_ops = {
        .suspend = sdhci_pci_suspend,