aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/sdhci-pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/host/sdhci-pci.c')
-rw-r--r--drivers/mmc/host/sdhci-pci.c70
1 files changed, 56 insertions, 14 deletions
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index c3a1debc9289..61192973e7cb 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -24,6 +24,7 @@
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/pm_runtime.h>
+#include <linux/mmc/slot-gpio.h>
#include <linux/mmc/sdhci-pci-data.h>
#include "sdhci.h"
@@ -271,6 +272,8 @@ static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot)
MMC_CAP_HW_RESET | MMC_CAP_1_8V_DDR;
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)
+ slot->host->timeout_clk = 1000; /* 1000 kHz i.e. 1 MHz */
return 0;
}
@@ -280,22 +283,35 @@ static int byt_sdio_probe_slot(struct sdhci_pci_slot *slot)
return 0;
}
+static int byt_sd_probe_slot(struct sdhci_pci_slot *slot)
+{
+ slot->cd_con_id = NULL;
+ slot->cd_idx = 0;
+ slot->cd_override_level = true;
+ return 0;
+}
+
static const struct sdhci_pci_fixes sdhci_intel_byt_emmc = {
.allow_runtime_pm = true,
.probe_slot = byt_emmc_probe_slot,
- .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
+ .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
+ SDHCI_QUIRK2_STOP_WITH_TC,
};
static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = {
- .quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON,
+ .quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON |
+ SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
.allow_runtime_pm = true,
.probe_slot = byt_sdio_probe_slot,
};
static const struct sdhci_pci_fixes sdhci_intel_byt_sd = {
- .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON,
+ .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON |
+ SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
+ SDHCI_QUIRK2_STOP_WITH_TC,
.allow_runtime_pm = true,
.own_cd_for_runtime_pm = true,
+ .probe_slot = byt_sd_probe_slot,
};
/* Define Host controllers for Intel Merrifield platform */
@@ -317,7 +333,9 @@ static int intel_mrfl_mmc_probe_slot(struct sdhci_pci_slot *slot)
static const struct sdhci_pci_fixes sdhci_intel_mrfl_mmc = {
.quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
- .quirks2 = SDHCI_QUIRK2_BROKEN_HS200,
+ .quirks2 = SDHCI_QUIRK2_BROKEN_HS200 |
+ SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
+ .allow_runtime_pm = true,
.probe_slot = intel_mrfl_mmc_probe_slot,
};
@@ -876,6 +894,29 @@ static const struct pci_device_id pci_ids[] = {
.driver_data = (kernel_ulong_t)&sdhci_intel_byt_emmc,
},
+ {
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_BSW_EMMC,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .driver_data = (kernel_ulong_t)&sdhci_intel_byt_emmc,
+ },
+
+ {
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_BSW_SDIO,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .driver_data = (kernel_ulong_t)&sdhci_intel_byt_sdio,
+ },
+
+ {
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_BSW_SD,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .driver_data = (kernel_ulong_t)&sdhci_intel_byt_sd,
+ },
{
.vendor = PCI_VENDOR_ID_INTEL,
@@ -1269,20 +1310,13 @@ static int sdhci_pci_runtime_idle(struct device *dev)
return 0;
}
-#else
-
-#define sdhci_pci_runtime_suspend NULL
-#define sdhci_pci_runtime_resume NULL
-#define sdhci_pci_runtime_idle NULL
-
#endif
static const struct dev_pm_ops sdhci_pci_pm_ops = {
.suspend = sdhci_pci_suspend,
.resume = sdhci_pci_resume,
- .runtime_suspend = sdhci_pci_runtime_suspend,
- .runtime_resume = sdhci_pci_runtime_resume,
- .runtime_idle = sdhci_pci_runtime_idle,
+ SET_RUNTIME_PM_OPS(sdhci_pci_runtime_suspend,
+ sdhci_pci_runtime_resume, sdhci_pci_runtime_idle)
};
/*****************************************************************************\
@@ -1332,6 +1366,7 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot(
slot->pci_bar = bar;
slot->rst_n_gpio = -EINVAL;
slot->cd_gpio = -EINVAL;
+ slot->cd_idx = -1;
/* Retrieve platform data if there is any */
if (*sdhci_pci_get_data)
@@ -1390,6 +1425,13 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot(
host->mmc->slotno = slotno;
host->mmc->caps2 |= MMC_CAP2_NO_PRESCAN_POWERUP;
+ if (slot->cd_idx >= 0 &&
+ mmc_gpiod_request_cd(host->mmc, slot->cd_con_id, slot->cd_idx,
+ slot->cd_override_level, 0, NULL)) {
+ dev_warn(&pdev->dev, "failed to setup card detect gpio\n");
+ slot->cd_idx = -1;
+ }
+
ret = sdhci_add_host(host);
if (ret)
goto remove;
@@ -1402,7 +1444,7 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot(
* Note sdhci_pci_add_own_cd() sets slot->cd_gpio to -EINVAL on failure.
*/
if (chip->fixes && chip->fixes->own_cd_for_runtime_pm &&
- !gpio_is_valid(slot->cd_gpio))
+ !gpio_is_valid(slot->cd_gpio) && slot->cd_idx < 0)
chip->allow_runtime_pm = false;
return slot;