diff options
| -rw-r--r-- | drivers/mmc/host/atmel-mci.c | 25 | ||||
| -rw-r--r-- | drivers/mmc/host/omap_hsmmc.c | 51 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci-acpi.c | 69 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci-esdhc-imx.c | 41 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci-pci.c | 54 |
5 files changed, 195 insertions, 45 deletions
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index e75774f72606..aca59d93d5a9 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c | |||
| @@ -2230,10 +2230,15 @@ static void __exit atmci_cleanup_slot(struct atmel_mci_slot *slot, | |||
| 2230 | mmc_free_host(slot->mmc); | 2230 | mmc_free_host(slot->mmc); |
| 2231 | } | 2231 | } |
| 2232 | 2232 | ||
| 2233 | static bool atmci_filter(struct dma_chan *chan, void *slave) | 2233 | static bool atmci_filter(struct dma_chan *chan, void *pdata) |
| 2234 | { | 2234 | { |
| 2235 | struct mci_dma_data *sl = slave; | 2235 | struct mci_platform_data *sl_pdata = pdata; |
| 2236 | struct mci_dma_data *sl; | ||
| 2236 | 2237 | ||
| 2238 | if (!sl_pdata) | ||
| 2239 | return false; | ||
| 2240 | |||
| 2241 | sl = sl_pdata->dma_slave; | ||
| 2237 | if (sl && find_slave_dev(sl) == chan->device->dev) { | 2242 | if (sl && find_slave_dev(sl) == chan->device->dev) { |
| 2238 | chan->private = slave_data_ptr(sl); | 2243 | chan->private = slave_data_ptr(sl); |
| 2239 | return true; | 2244 | return true; |
| @@ -2245,24 +2250,18 @@ static bool atmci_filter(struct dma_chan *chan, void *slave) | |||
| 2245 | static bool atmci_configure_dma(struct atmel_mci *host) | 2250 | static bool atmci_configure_dma(struct atmel_mci *host) |
| 2246 | { | 2251 | { |
| 2247 | struct mci_platform_data *pdata; | 2252 | struct mci_platform_data *pdata; |
| 2253 | dma_cap_mask_t mask; | ||
| 2248 | 2254 | ||
| 2249 | if (host == NULL) | 2255 | if (host == NULL) |
| 2250 | return false; | 2256 | return false; |
| 2251 | 2257 | ||
| 2252 | pdata = host->pdev->dev.platform_data; | 2258 | pdata = host->pdev->dev.platform_data; |
| 2253 | 2259 | ||
| 2254 | if (!pdata) | 2260 | dma_cap_zero(mask); |
| 2255 | return false; | 2261 | dma_cap_set(DMA_SLAVE, mask); |
| 2256 | 2262 | ||
| 2257 | if (pdata->dma_slave && find_slave_dev(pdata->dma_slave)) { | 2263 | host->dma.chan = dma_request_slave_channel_compat(mask, atmci_filter, pdata, |
| 2258 | dma_cap_mask_t mask; | 2264 | &host->pdev->dev, "rxtx"); |
| 2259 | |||
| 2260 | /* Try to grab a DMA channel */ | ||
| 2261 | dma_cap_zero(mask); | ||
| 2262 | dma_cap_set(DMA_SLAVE, mask); | ||
| 2263 | host->dma.chan = | ||
| 2264 | dma_request_channel(mask, atmci_filter, pdata->dma_slave); | ||
| 2265 | } | ||
| 2266 | if (!host->dma.chan) { | 2265 | if (!host->dma.chan) { |
| 2267 | dev_warn(&host->pdev->dev, "no DMA channel available\n"); | 2266 | dev_warn(&host->pdev->dev, "no DMA channel available\n"); |
| 2268 | return false; | 2267 | return false; |
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 6e44025acf01..eccedc7d06a4 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c | |||
| @@ -161,6 +161,7 @@ struct omap_hsmmc_host { | |||
| 161 | */ | 161 | */ |
| 162 | struct regulator *vcc; | 162 | struct regulator *vcc; |
| 163 | struct regulator *vcc_aux; | 163 | struct regulator *vcc_aux; |
| 164 | int pbias_disable; | ||
| 164 | void __iomem *base; | 165 | void __iomem *base; |
| 165 | resource_size_t mapbase; | 166 | resource_size_t mapbase; |
| 166 | spinlock_t irq_lock; /* Prevent races with irq handler */ | 167 | spinlock_t irq_lock; /* Prevent races with irq handler */ |
| @@ -255,11 +256,11 @@ static int omap_hsmmc_set_power(struct device *dev, int slot, int power_on, | |||
| 255 | if (!host->vcc) | 256 | if (!host->vcc) |
| 256 | return 0; | 257 | return 0; |
| 257 | /* | 258 | /* |
| 258 | * With DT, never turn OFF the regulator. This is because | 259 | * With DT, never turn OFF the regulator for MMC1. This is because |
| 259 | * the pbias cell programming support is still missing when | 260 | * the pbias cell programming support is still missing when |
| 260 | * booting with Device tree | 261 | * booting with Device tree |
| 261 | */ | 262 | */ |
| 262 | if (dev->of_node && !vdd) | 263 | if (host->pbias_disable && !vdd) |
| 263 | return 0; | 264 | return 0; |
| 264 | 265 | ||
| 265 | if (mmc_slot(host).before_set_reg) | 266 | if (mmc_slot(host).before_set_reg) |
| @@ -1520,10 +1521,10 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
| 1520 | (ios->vdd == DUAL_VOLT_OCR_BIT) && | 1521 | (ios->vdd == DUAL_VOLT_OCR_BIT) && |
| 1521 | /* | 1522 | /* |
| 1522 | * With pbias cell programming missing, this | 1523 | * With pbias cell programming missing, this |
| 1523 | * can't be allowed when booting with device | 1524 | * can't be allowed on MMC1 when booting with device |
| 1524 | * tree. | 1525 | * tree. |
| 1525 | */ | 1526 | */ |
| 1526 | !host->dev->of_node) { | 1527 | !host->pbias_disable) { |
| 1527 | /* | 1528 | /* |
| 1528 | * The mmc_select_voltage fn of the core does | 1529 | * The mmc_select_voltage fn of the core does |
| 1529 | * not seem to set the power_mode to | 1530 | * not seem to set the power_mode to |
| @@ -1871,6 +1872,10 @@ static int omap_hsmmc_probe(struct platform_device *pdev) | |||
| 1871 | 1872 | ||
| 1872 | omap_hsmmc_context_save(host); | 1873 | omap_hsmmc_context_save(host); |
| 1873 | 1874 | ||
| 1875 | /* This can be removed once we support PBIAS with DT */ | ||
| 1876 | if (host->dev->of_node && host->mapbase == 0x4809c000) | ||
| 1877 | host->pbias_disable = 1; | ||
| 1878 | |||
| 1874 | host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck"); | 1879 | host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck"); |
| 1875 | /* | 1880 | /* |
| 1876 | * MMC can still work without debounce clock. | 1881 | * MMC can still work without debounce clock. |
| @@ -1906,33 +1911,41 @@ static int omap_hsmmc_probe(struct platform_device *pdev) | |||
| 1906 | 1911 | ||
| 1907 | omap_hsmmc_conf_bus_power(host); | 1912 | omap_hsmmc_conf_bus_power(host); |
| 1908 | 1913 | ||
| 1909 | res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx"); | 1914 | if (!pdev->dev.of_node) { |
| 1910 | if (!res) { | 1915 | res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx"); |
| 1911 | dev_err(mmc_dev(host->mmc), "cannot get DMA TX channel\n"); | 1916 | if (!res) { |
| 1912 | ret = -ENXIO; | 1917 | dev_err(mmc_dev(host->mmc), "cannot get DMA TX channel\n"); |
| 1913 | goto err_irq; | 1918 | ret = -ENXIO; |
| 1914 | } | 1919 | goto err_irq; |
| 1915 | tx_req = res->start; | 1920 | } |
| 1921 | tx_req = res->start; | ||
| 1916 | 1922 | ||
| 1917 | res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx"); | 1923 | res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx"); |
| 1918 | if (!res) { | 1924 | if (!res) { |
| 1919 | dev_err(mmc_dev(host->mmc), "cannot get DMA RX channel\n"); | 1925 | dev_err(mmc_dev(host->mmc), "cannot get DMA RX channel\n"); |
| 1920 | ret = -ENXIO; | 1926 | ret = -ENXIO; |
| 1921 | goto err_irq; | 1927 | goto err_irq; |
| 1928 | } | ||
| 1929 | rx_req = res->start; | ||
| 1922 | } | 1930 | } |
| 1923 | rx_req = res->start; | ||
| 1924 | 1931 | ||
| 1925 | dma_cap_zero(mask); | 1932 | dma_cap_zero(mask); |
| 1926 | dma_cap_set(DMA_SLAVE, mask); | 1933 | dma_cap_set(DMA_SLAVE, mask); |
| 1927 | 1934 | ||
| 1928 | host->rx_chan = dma_request_channel(mask, omap_dma_filter_fn, &rx_req); | 1935 | host->rx_chan = |
| 1936 | dma_request_slave_channel_compat(mask, omap_dma_filter_fn, | ||
| 1937 | &rx_req, &pdev->dev, "rx"); | ||
| 1938 | |||
| 1929 | if (!host->rx_chan) { | 1939 | if (!host->rx_chan) { |
| 1930 | dev_err(mmc_dev(host->mmc), "unable to obtain RX DMA engine channel %u\n", rx_req); | 1940 | dev_err(mmc_dev(host->mmc), "unable to obtain RX DMA engine channel %u\n", rx_req); |
| 1931 | ret = -ENXIO; | 1941 | ret = -ENXIO; |
| 1932 | goto err_irq; | 1942 | goto err_irq; |
| 1933 | } | 1943 | } |
| 1934 | 1944 | ||
| 1935 | host->tx_chan = dma_request_channel(mask, omap_dma_filter_fn, &tx_req); | 1945 | host->tx_chan = |
| 1946 | dma_request_slave_channel_compat(mask, omap_dma_filter_fn, | ||
| 1947 | &tx_req, &pdev->dev, "tx"); | ||
| 1948 | |||
| 1936 | if (!host->tx_chan) { | 1949 | if (!host->tx_chan) { |
| 1937 | dev_err(mmc_dev(host->mmc), "unable to obtain TX DMA engine channel %u\n", tx_req); | 1950 | dev_err(mmc_dev(host->mmc), "unable to obtain TX DMA engine channel %u\n", tx_req); |
| 1938 | ret = -ENXIO; | 1951 | ret = -ENXIO; |
diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index 7bcf74b1a5cd..706d9cb1a49e 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c | |||
| @@ -87,6 +87,12 @@ static const struct sdhci_ops sdhci_acpi_ops_dflt = { | |||
| 87 | .enable_dma = sdhci_acpi_enable_dma, | 87 | .enable_dma = sdhci_acpi_enable_dma, |
| 88 | }; | 88 | }; |
| 89 | 89 | ||
| 90 | static const struct sdhci_acpi_slot sdhci_acpi_slot_int_emmc = { | ||
| 91 | .caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE, | ||
| 92 | .caps2 = MMC_CAP2_HC_ERASE_SZ, | ||
| 93 | .flags = SDHCI_ACPI_RUNTIME_PM, | ||
| 94 | }; | ||
| 95 | |||
| 90 | static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = { | 96 | static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = { |
| 91 | .quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON, | 97 | .quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON, |
| 92 | .caps = MMC_CAP_NONREMOVABLE | MMC_CAP_POWER_OFF_CARD, | 98 | .caps = MMC_CAP_NONREMOVABLE | MMC_CAP_POWER_OFF_CARD, |
| @@ -94,23 +100,67 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = { | |||
| 94 | .pm_caps = MMC_PM_KEEP_POWER, | 100 | .pm_caps = MMC_PM_KEEP_POWER, |
| 95 | }; | 101 | }; |
| 96 | 102 | ||
| 103 | static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sd = { | ||
| 104 | }; | ||
| 105 | |||
| 106 | struct sdhci_acpi_uid_slot { | ||
| 107 | const char *hid; | ||
| 108 | const char *uid; | ||
| 109 | const struct sdhci_acpi_slot *slot; | ||
| 110 | }; | ||
| 111 | |||
| 112 | static const struct sdhci_acpi_uid_slot sdhci_acpi_uids[] = { | ||
| 113 | { "80860F14" , "1" , &sdhci_acpi_slot_int_emmc }, | ||
| 114 | { "80860F14" , "3" , &sdhci_acpi_slot_int_sd }, | ||
| 115 | { "INT33BB" , "2" , &sdhci_acpi_slot_int_sdio }, | ||
| 116 | { "INT33C6" , NULL, &sdhci_acpi_slot_int_sdio }, | ||
| 117 | { "PNP0D40" }, | ||
| 118 | { }, | ||
| 119 | }; | ||
| 120 | |||
| 97 | static const struct acpi_device_id sdhci_acpi_ids[] = { | 121 | static const struct acpi_device_id sdhci_acpi_ids[] = { |
| 98 | { "INT33C6", (kernel_ulong_t)&sdhci_acpi_slot_int_sdio }, | 122 | { "80860F14" }, |
| 99 | { "PNP0D40" }, | 123 | { "INT33BB" }, |
| 124 | { "INT33C6" }, | ||
| 125 | { "PNP0D40" }, | ||
| 100 | { }, | 126 | { }, |
| 101 | }; | 127 | }; |
| 102 | MODULE_DEVICE_TABLE(acpi, sdhci_acpi_ids); | 128 | MODULE_DEVICE_TABLE(acpi, sdhci_acpi_ids); |
| 103 | 129 | ||
| 104 | static const struct sdhci_acpi_slot *sdhci_acpi_get_slot(const char *hid) | 130 | static const struct sdhci_acpi_slot *sdhci_acpi_get_slot_by_ids(const char *hid, |
| 131 | const char *uid) | ||
| 105 | { | 132 | { |
| 106 | const struct acpi_device_id *id; | 133 | const struct sdhci_acpi_uid_slot *u; |
| 107 | 134 | ||
| 108 | for (id = sdhci_acpi_ids; id->id[0]; id++) | 135 | for (u = sdhci_acpi_uids; u->hid; u++) { |
| 109 | if (!strcmp(id->id, hid)) | 136 | if (strcmp(u->hid, hid)) |
| 110 | return (const struct sdhci_acpi_slot *)id->driver_data; | 137 | continue; |
| 138 | if (!u->uid) | ||
| 139 | return u->slot; | ||
| 140 | if (uid && !strcmp(u->uid, uid)) | ||
| 141 | return u->slot; | ||
| 142 | } | ||
| 111 | return NULL; | 143 | return NULL; |
| 112 | } | 144 | } |
| 113 | 145 | ||
| 146 | static const struct sdhci_acpi_slot *sdhci_acpi_get_slot(acpi_handle handle, | ||
| 147 | const char *hid) | ||
| 148 | { | ||
| 149 | const struct sdhci_acpi_slot *slot; | ||
| 150 | struct acpi_device_info *info; | ||
| 151 | const char *uid = NULL; | ||
| 152 | acpi_status status; | ||
| 153 | |||
| 154 | status = acpi_get_object_info(handle, &info); | ||
| 155 | if (!ACPI_FAILURE(status) && (info->valid & ACPI_VALID_UID)) | ||
| 156 | uid = info->unique_id.string; | ||
| 157 | |||
| 158 | slot = sdhci_acpi_get_slot_by_ids(hid, uid); | ||
| 159 | |||
| 160 | kfree(info); | ||
| 161 | return slot; | ||
| 162 | } | ||
| 163 | |||
| 114 | static int sdhci_acpi_probe(struct platform_device *pdev) | 164 | static int sdhci_acpi_probe(struct platform_device *pdev) |
| 115 | { | 165 | { |
| 116 | struct device *dev = &pdev->dev; | 166 | struct device *dev = &pdev->dev; |
| @@ -148,7 +198,7 @@ static int sdhci_acpi_probe(struct platform_device *pdev) | |||
| 148 | 198 | ||
| 149 | c = sdhci_priv(host); | 199 | c = sdhci_priv(host); |
| 150 | c->host = host; | 200 | c->host = host; |
| 151 | c->slot = sdhci_acpi_get_slot(hid); | 201 | c->slot = sdhci_acpi_get_slot(handle, hid); |
| 152 | c->pdev = pdev; | 202 | c->pdev = pdev; |
| 153 | c->use_runtime_pm = sdhci_acpi_flag(c, SDHCI_ACPI_RUNTIME_PM); | 203 | c->use_runtime_pm = sdhci_acpi_flag(c, SDHCI_ACPI_RUNTIME_PM); |
| 154 | 204 | ||
| @@ -202,6 +252,7 @@ static int sdhci_acpi_probe(struct platform_device *pdev) | |||
| 202 | goto err_free; | 252 | goto err_free; |
| 203 | 253 | ||
| 204 | if (c->use_runtime_pm) { | 254 | if (c->use_runtime_pm) { |
| 255 | pm_runtime_set_active(dev); | ||
| 205 | pm_suspend_ignore_children(dev, 1); | 256 | pm_suspend_ignore_children(dev, 1); |
| 206 | pm_runtime_set_autosuspend_delay(dev, 50); | 257 | pm_runtime_set_autosuspend_delay(dev, 50); |
| 207 | pm_runtime_use_autosuspend(dev); | 258 | pm_runtime_use_autosuspend(dev); |
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 67d6dde2ff19..d5f0d59e1310 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c | |||
| @@ -85,6 +85,12 @@ struct pltfm_imx_data { | |||
| 85 | struct clk *clk_ipg; | 85 | struct clk *clk_ipg; |
| 86 | struct clk *clk_ahb; | 86 | struct clk *clk_ahb; |
| 87 | struct clk *clk_per; | 87 | struct clk *clk_per; |
| 88 | enum { | ||
| 89 | NO_CMD_PENDING, /* no multiblock command pending*/ | ||
| 90 | MULTIBLK_IN_PROCESS, /* exact multiblock cmd in process */ | ||
| 91 | WAIT_FOR_INT, /* sent CMD12, waiting for response INT */ | ||
| 92 | } multiblock_status; | ||
| 93 | |||
| 88 | }; | 94 | }; |
| 89 | 95 | ||
| 90 | static struct platform_device_id imx_esdhc_devtype[] = { | 96 | static struct platform_device_id imx_esdhc_devtype[] = { |
| @@ -154,6 +160,8 @@ static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, i | |||
| 154 | 160 | ||
| 155 | static u32 esdhc_readl_le(struct sdhci_host *host, int reg) | 161 | static u32 esdhc_readl_le(struct sdhci_host *host, int reg) |
| 156 | { | 162 | { |
| 163 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
| 164 | struct pltfm_imx_data *imx_data = pltfm_host->priv; | ||
| 157 | u32 val = readl(host->ioaddr + reg); | 165 | u32 val = readl(host->ioaddr + reg); |
| 158 | 166 | ||
| 159 | if (unlikely(reg == SDHCI_CAPABILITIES)) { | 167 | if (unlikely(reg == SDHCI_CAPABILITIES)) { |
| @@ -175,6 +183,18 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg) | |||
| 175 | val &= ~ESDHC_INT_VENDOR_SPEC_DMA_ERR; | 183 | val &= ~ESDHC_INT_VENDOR_SPEC_DMA_ERR; |
| 176 | val |= SDHCI_INT_ADMA_ERROR; | 184 | val |= SDHCI_INT_ADMA_ERROR; |
| 177 | } | 185 | } |
| 186 | |||
| 187 | /* | ||
| 188 | * mask off the interrupt we get in response to the manually | ||
| 189 | * sent CMD12 | ||
| 190 | */ | ||
| 191 | if ((imx_data->multiblock_status == WAIT_FOR_INT) && | ||
| 192 | ((val & SDHCI_INT_RESPONSE) == SDHCI_INT_RESPONSE)) { | ||
| 193 | val &= ~SDHCI_INT_RESPONSE; | ||
| 194 | writel(SDHCI_INT_RESPONSE, host->ioaddr + | ||
| 195 | SDHCI_INT_STATUS); | ||
| 196 | imx_data->multiblock_status = NO_CMD_PENDING; | ||
| 197 | } | ||
| 178 | } | 198 | } |
| 179 | 199 | ||
| 180 | return val; | 200 | return val; |
| @@ -211,6 +231,15 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg) | |||
| 211 | v = readl(host->ioaddr + ESDHC_VENDOR_SPEC); | 231 | v = readl(host->ioaddr + ESDHC_VENDOR_SPEC); |
| 212 | v &= ~ESDHC_VENDOR_SPEC_SDIO_QUIRK; | 232 | v &= ~ESDHC_VENDOR_SPEC_SDIO_QUIRK; |
| 213 | writel(v, host->ioaddr + ESDHC_VENDOR_SPEC); | 233 | writel(v, host->ioaddr + ESDHC_VENDOR_SPEC); |
| 234 | |||
| 235 | if (imx_data->multiblock_status == MULTIBLK_IN_PROCESS) | ||
| 236 | { | ||
| 237 | /* send a manual CMD12 with RESPTYP=none */ | ||
| 238 | data = MMC_STOP_TRANSMISSION << 24 | | ||
| 239 | SDHCI_CMD_ABORTCMD << 16; | ||
| 240 | writel(data, host->ioaddr + SDHCI_TRANSFER_MODE); | ||
| 241 | imx_data->multiblock_status = WAIT_FOR_INT; | ||
| 242 | } | ||
| 214 | } | 243 | } |
| 215 | 244 | ||
| 216 | if (unlikely(reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)) { | 245 | if (unlikely(reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)) { |
| @@ -277,11 +306,13 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) | |||
| 277 | } | 306 | } |
| 278 | return; | 307 | return; |
| 279 | case SDHCI_COMMAND: | 308 | case SDHCI_COMMAND: |
| 280 | if ((host->cmd->opcode == MMC_STOP_TRANSMISSION || | 309 | if (host->cmd->opcode == MMC_STOP_TRANSMISSION) |
| 281 | host->cmd->opcode == MMC_SET_BLOCK_COUNT) && | ||
| 282 | (imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT)) | ||
| 283 | val |= SDHCI_CMD_ABORTCMD; | 310 | val |= SDHCI_CMD_ABORTCMD; |
| 284 | 311 | ||
| 312 | if ((host->cmd->opcode == MMC_SET_BLOCK_COUNT) && | ||
| 313 | (imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT)) | ||
| 314 | imx_data->multiblock_status = MULTIBLK_IN_PROCESS; | ||
| 315 | |||
| 285 | if (is_imx6q_usdhc(imx_data)) | 316 | if (is_imx6q_usdhc(imx_data)) |
| 286 | writel(val << 16, | 317 | writel(val << 16, |
| 287 | host->ioaddr + SDHCI_TRANSFER_MODE); | 318 | host->ioaddr + SDHCI_TRANSFER_MODE); |
| @@ -324,8 +355,10 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg) | |||
| 324 | /* | 355 | /* |
| 325 | * Do not touch buswidth bits here. This is done in | 356 | * Do not touch buswidth bits here. This is done in |
| 326 | * esdhc_pltfm_bus_width. | 357 | * esdhc_pltfm_bus_width. |
| 358 | * Do not touch the D3CD bit either which is used for the | ||
| 359 | * SDIO interrupt errata workaround. | ||
| 327 | */ | 360 | */ |
| 328 | mask = 0xffff & ~ESDHC_CTRL_BUSWIDTH_MASK; | 361 | mask = 0xffff & ~(ESDHC_CTRL_BUSWIDTH_MASK | ESDHC_CTRL_D3CD); |
| 329 | 362 | ||
| 330 | esdhc_clrset_le(host, mask, new_val, reg); | 363 | esdhc_clrset_le(host, mask, new_val, reg); |
| 331 | return; | 364 | return; |
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 0012d3fdc999..701d06d0e1fb 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c | |||
| @@ -33,6 +33,9 @@ | |||
| 33 | */ | 33 | */ |
| 34 | #define PCI_DEVICE_ID_INTEL_PCH_SDIO0 0x8809 | 34 | #define PCI_DEVICE_ID_INTEL_PCH_SDIO0 0x8809 |
| 35 | #define PCI_DEVICE_ID_INTEL_PCH_SDIO1 0x880a | 35 | #define PCI_DEVICE_ID_INTEL_PCH_SDIO1 0x880a |
| 36 | #define PCI_DEVICE_ID_INTEL_BYT_EMMC 0x0f14 | ||
| 37 | #define PCI_DEVICE_ID_INTEL_BYT_SDIO 0x0f15 | ||
| 38 | #define PCI_DEVICE_ID_INTEL_BYT_SD 0x0f16 | ||
| 36 | 39 | ||
| 37 | /* | 40 | /* |
| 38 | * PCI registers | 41 | * PCI registers |
| @@ -304,6 +307,33 @@ static const struct sdhci_pci_fixes sdhci_intel_pch_sdio = { | |||
| 304 | .probe_slot = pch_hc_probe_slot, | 307 | .probe_slot = pch_hc_probe_slot, |
| 305 | }; | 308 | }; |
| 306 | 309 | ||
| 310 | static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot) | ||
| 311 | { | ||
| 312 | slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE; | ||
| 313 | slot->host->mmc->caps2 |= MMC_CAP2_HC_ERASE_SZ; | ||
| 314 | return 0; | ||
| 315 | } | ||
| 316 | |||
| 317 | static int byt_sdio_probe_slot(struct sdhci_pci_slot *slot) | ||
| 318 | { | ||
| 319 | slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_NONREMOVABLE; | ||
| 320 | return 0; | ||
| 321 | } | ||
| 322 | |||
| 323 | static const struct sdhci_pci_fixes sdhci_intel_byt_emmc = { | ||
| 324 | .allow_runtime_pm = true, | ||
| 325 | .probe_slot = byt_emmc_probe_slot, | ||
| 326 | }; | ||
| 327 | |||
| 328 | static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = { | ||
| 329 | .quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON, | ||
| 330 | .allow_runtime_pm = true, | ||
| 331 | .probe_slot = byt_sdio_probe_slot, | ||
| 332 | }; | ||
| 333 | |||
| 334 | static const struct sdhci_pci_fixes sdhci_intel_byt_sd = { | ||
| 335 | }; | ||
| 336 | |||
| 307 | /* O2Micro extra registers */ | 337 | /* O2Micro extra registers */ |
| 308 | #define O2_SD_LOCK_WP 0xD3 | 338 | #define O2_SD_LOCK_WP 0xD3 |
| 309 | #define O2_SD_MULTI_VCC3V 0xEE | 339 | #define O2_SD_MULTI_VCC3V 0xEE |
| @@ -856,6 +886,30 @@ static const struct pci_device_id pci_ids[] = { | |||
| 856 | }, | 886 | }, |
| 857 | 887 | ||
| 858 | { | 888 | { |
| 889 | .vendor = PCI_VENDOR_ID_INTEL, | ||
| 890 | .device = PCI_DEVICE_ID_INTEL_BYT_EMMC, | ||
| 891 | .subvendor = PCI_ANY_ID, | ||
| 892 | .subdevice = PCI_ANY_ID, | ||
| 893 | .driver_data = (kernel_ulong_t)&sdhci_intel_byt_emmc, | ||
| 894 | }, | ||
| 895 | |||
| 896 | { | ||
| 897 | .vendor = PCI_VENDOR_ID_INTEL, | ||
| 898 | .device = PCI_DEVICE_ID_INTEL_BYT_SDIO, | ||
| 899 | .subvendor = PCI_ANY_ID, | ||
| 900 | .subdevice = PCI_ANY_ID, | ||
| 901 | .driver_data = (kernel_ulong_t)&sdhci_intel_byt_sdio, | ||
| 902 | }, | ||
| 903 | |||
| 904 | { | ||
| 905 | .vendor = PCI_VENDOR_ID_INTEL, | ||
| 906 | .device = PCI_DEVICE_ID_INTEL_BYT_SD, | ||
| 907 | .subvendor = PCI_ANY_ID, | ||
| 908 | .subdevice = PCI_ANY_ID, | ||
| 909 | .driver_data = (kernel_ulong_t)&sdhci_intel_byt_sd, | ||
| 910 | }, | ||
| 911 | |||
| 912 | { | ||
| 859 | .vendor = PCI_VENDOR_ID_O2, | 913 | .vendor = PCI_VENDOR_ID_O2, |
| 860 | .device = PCI_DEVICE_ID_O2_8120, | 914 | .device = PCI_DEVICE_ID_O2_8120, |
| 861 | .subvendor = PCI_ANY_ID, | 915 | .subvendor = PCI_ANY_ID, |
