diff options
Diffstat (limited to 'drivers/mmc/host/sdhci-pci.c')
-rw-r--r-- | drivers/mmc/host/sdhci-pci.c | 70 |
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; |