mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-03-19 21:20:00 +07:00
MMC fixes for 3.10-rc5:
- sdhci-acpi: Fix initial runtime PM status, add more ACPI IDs - atmel-mci, omap_hsmmc: DT handling fixes - esdhc-imx: Fix SDIO IRQs, fix multiblock reads (both h/w errata) -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.13 (GNU/Linux) iQIcBAABAgAGBQJRq4CwAAoJEHNBYZ7TNxYMMasQANRnWqA7FVa3Jk/hL5t32P37 TWso0z29jGPdeUaHD4nZiJN+fMFqsvrmw1rjZ6ftqNiTA/beHopgCKHocu13A7si t7Mc0LtVXchjJfLljw/H0qMO8Zg4H843/vw53S+dkRaJz/8WdTXg27jnXzlRuR1N itB2gRKnc57LtmHSBtqNhyqY+BJzlut960+By4JWyFrHZha0iC4PdpSLiT9kr9S6 QpJQndjVxhG3GoFOpoaDchaci9yGjwvWlaQClVCQ2rLmcWAmW+kx4aIQQxDYLeXD /JVIZkbi4IE6P99v6Zyswqa22IOT4lJVYY0YHEB7nScen181KykdDaF+QOcYRtW5 myXm4e3bVK5FnzH6jKIIb+lfVtys2jQEDp88hniYhL4Ede2pZnqxJemeoBvWZ7G/ t40JlDzJojw9GyWGqFZ4k1Vg8J1YtpmzB6jDSOQNMXMDli2Jf4XmaHNL8wQk9/nx /kL71P5TY/AxKs5dN2DJPuBnr9cmYNYwFgnOV36N/6CUKkcojKSDYGyA4uowYhh9 ycAJjaNMwwaJFK8nupe14ENvIkEBT+jp97mZss7hAgg2egpOtt0gSvltlRLPEGAR 5W0kEA1j5AgMnMREmhYgQ528z4uADN3+ABdRlUdUpIf+BD/XPBMhVNrkp5kB+ZFu Oru8VcPysPWbUxegy+eK =Fq1Y -----END PGP SIGNATURE----- Merge tag 'mmc-fixes-for-3.10-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc Pull MMC fixes from Chris Ball: - sdhci-acpi: Fix initial runtime PM status, add more ACPI IDs - atmel-mci, omap_hsmmc: DT handling fixes - esdhc-imx: Fix SDIO IRQs, fix multiblock reads (both h/w errata) * tag 'mmc-fixes-for-3.10-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc: mmc: omap_hsmmc: Skip platform_get_resource_byname() for dt case mmc: omap_hsmmc: convert to dma_request_slave_channel_compat mmc: omap_hsmmc: Fix the DT pbias workaround for MMC controllers 2 to 5 mmc: sdhci-pci: add more device ids mmc: sdhci-acpi: add more device ids mmc: sdhci-acpi: fix initial runtime pm status mmc: atmel-mci: convert to dma_request_slave_channel_compat() mmc: sdhci-esdhc-imx: fix multiblock reads on i.MX53 mmc: sdhci-esdhc-imx: Fix SDIO interrupts
This commit is contained in:
commit
844ce9f204
@ -2230,10 +2230,15 @@ static void __exit atmci_cleanup_slot(struct atmel_mci_slot *slot,
|
|||||||
mmc_free_host(slot->mmc);
|
mmc_free_host(slot->mmc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool atmci_filter(struct dma_chan *chan, void *slave)
|
static bool atmci_filter(struct dma_chan *chan, void *pdata)
|
||||||
{
|
{
|
||||||
struct mci_dma_data *sl = slave;
|
struct mci_platform_data *sl_pdata = pdata;
|
||||||
|
struct mci_dma_data *sl;
|
||||||
|
|
||||||
|
if (!sl_pdata)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
sl = sl_pdata->dma_slave;
|
||||||
if (sl && find_slave_dev(sl) == chan->device->dev) {
|
if (sl && find_slave_dev(sl) == chan->device->dev) {
|
||||||
chan->private = slave_data_ptr(sl);
|
chan->private = slave_data_ptr(sl);
|
||||||
return true;
|
return true;
|
||||||
@ -2245,24 +2250,18 @@ static bool atmci_filter(struct dma_chan *chan, void *slave)
|
|||||||
static bool atmci_configure_dma(struct atmel_mci *host)
|
static bool atmci_configure_dma(struct atmel_mci *host)
|
||||||
{
|
{
|
||||||
struct mci_platform_data *pdata;
|
struct mci_platform_data *pdata;
|
||||||
|
dma_cap_mask_t mask;
|
||||||
|
|
||||||
if (host == NULL)
|
if (host == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
pdata = host->pdev->dev.platform_data;
|
pdata = host->pdev->dev.platform_data;
|
||||||
|
|
||||||
if (!pdata)
|
dma_cap_zero(mask);
|
||||||
return false;
|
dma_cap_set(DMA_SLAVE, mask);
|
||||||
|
|
||||||
if (pdata->dma_slave && find_slave_dev(pdata->dma_slave)) {
|
host->dma.chan = dma_request_slave_channel_compat(mask, atmci_filter, pdata,
|
||||||
dma_cap_mask_t mask;
|
&host->pdev->dev, "rxtx");
|
||||||
|
|
||||||
/* Try to grab a DMA channel */
|
|
||||||
dma_cap_zero(mask);
|
|
||||||
dma_cap_set(DMA_SLAVE, mask);
|
|
||||||
host->dma.chan =
|
|
||||||
dma_request_channel(mask, atmci_filter, pdata->dma_slave);
|
|
||||||
}
|
|
||||||
if (!host->dma.chan) {
|
if (!host->dma.chan) {
|
||||||
dev_warn(&host->pdev->dev, "no DMA channel available\n");
|
dev_warn(&host->pdev->dev, "no DMA channel available\n");
|
||||||
return false;
|
return false;
|
||||||
|
@ -161,6 +161,7 @@ struct omap_hsmmc_host {
|
|||||||
*/
|
*/
|
||||||
struct regulator *vcc;
|
struct regulator *vcc;
|
||||||
struct regulator *vcc_aux;
|
struct regulator *vcc_aux;
|
||||||
|
int pbias_disable;
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
resource_size_t mapbase;
|
resource_size_t mapbase;
|
||||||
spinlock_t irq_lock; /* Prevent races with irq handler */
|
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,
|
|||||||
if (!host->vcc)
|
if (!host->vcc)
|
||||||
return 0;
|
return 0;
|
||||||
/*
|
/*
|
||||||
* With DT, never turn OFF the regulator. This is because
|
* With DT, never turn OFF the regulator for MMC1. This is because
|
||||||
* the pbias cell programming support is still missing when
|
* the pbias cell programming support is still missing when
|
||||||
* booting with Device tree
|
* booting with Device tree
|
||||||
*/
|
*/
|
||||||
if (dev->of_node && !vdd)
|
if (host->pbias_disable && !vdd)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (mmc_slot(host).before_set_reg)
|
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)
|
|||||||
(ios->vdd == DUAL_VOLT_OCR_BIT) &&
|
(ios->vdd == DUAL_VOLT_OCR_BIT) &&
|
||||||
/*
|
/*
|
||||||
* With pbias cell programming missing, this
|
* With pbias cell programming missing, this
|
||||||
* can't be allowed when booting with device
|
* can't be allowed on MMC1 when booting with device
|
||||||
* tree.
|
* tree.
|
||||||
*/
|
*/
|
||||||
!host->dev->of_node) {
|
!host->pbias_disable) {
|
||||||
/*
|
/*
|
||||||
* The mmc_select_voltage fn of the core does
|
* The mmc_select_voltage fn of the core does
|
||||||
* not seem to set the power_mode to
|
* not seem to set the power_mode to
|
||||||
@ -1871,6 +1872,10 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
omap_hsmmc_context_save(host);
|
omap_hsmmc_context_save(host);
|
||||||
|
|
||||||
|
/* This can be removed once we support PBIAS with DT */
|
||||||
|
if (host->dev->of_node && host->mapbase == 0x4809c000)
|
||||||
|
host->pbias_disable = 1;
|
||||||
|
|
||||||
host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck");
|
host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck");
|
||||||
/*
|
/*
|
||||||
* MMC can still work without debounce clock.
|
* MMC can still work without debounce clock.
|
||||||
@ -1906,33 +1911,41 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
omap_hsmmc_conf_bus_power(host);
|
omap_hsmmc_conf_bus_power(host);
|
||||||
|
|
||||||
res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
|
if (!pdev->dev.of_node) {
|
||||||
if (!res) {
|
res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
|
||||||
dev_err(mmc_dev(host->mmc), "cannot get DMA TX channel\n");
|
if (!res) {
|
||||||
ret = -ENXIO;
|
dev_err(mmc_dev(host->mmc), "cannot get DMA TX channel\n");
|
||||||
goto err_irq;
|
ret = -ENXIO;
|
||||||
}
|
goto err_irq;
|
||||||
tx_req = res->start;
|
}
|
||||||
|
tx_req = res->start;
|
||||||
|
|
||||||
res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
|
res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
|
||||||
if (!res) {
|
if (!res) {
|
||||||
dev_err(mmc_dev(host->mmc), "cannot get DMA RX channel\n");
|
dev_err(mmc_dev(host->mmc), "cannot get DMA RX channel\n");
|
||||||
ret = -ENXIO;
|
ret = -ENXIO;
|
||||||
goto err_irq;
|
goto err_irq;
|
||||||
|
}
|
||||||
|
rx_req = res->start;
|
||||||
}
|
}
|
||||||
rx_req = res->start;
|
|
||||||
|
|
||||||
dma_cap_zero(mask);
|
dma_cap_zero(mask);
|
||||||
dma_cap_set(DMA_SLAVE, mask);
|
dma_cap_set(DMA_SLAVE, mask);
|
||||||
|
|
||||||
host->rx_chan = dma_request_channel(mask, omap_dma_filter_fn, &rx_req);
|
host->rx_chan =
|
||||||
|
dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
|
||||||
|
&rx_req, &pdev->dev, "rx");
|
||||||
|
|
||||||
if (!host->rx_chan) {
|
if (!host->rx_chan) {
|
||||||
dev_err(mmc_dev(host->mmc), "unable to obtain RX DMA engine channel %u\n", rx_req);
|
dev_err(mmc_dev(host->mmc), "unable to obtain RX DMA engine channel %u\n", rx_req);
|
||||||
ret = -ENXIO;
|
ret = -ENXIO;
|
||||||
goto err_irq;
|
goto err_irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
host->tx_chan = dma_request_channel(mask, omap_dma_filter_fn, &tx_req);
|
host->tx_chan =
|
||||||
|
dma_request_slave_channel_compat(mask, omap_dma_filter_fn,
|
||||||
|
&tx_req, &pdev->dev, "tx");
|
||||||
|
|
||||||
if (!host->tx_chan) {
|
if (!host->tx_chan) {
|
||||||
dev_err(mmc_dev(host->mmc), "unable to obtain TX DMA engine channel %u\n", tx_req);
|
dev_err(mmc_dev(host->mmc), "unable to obtain TX DMA engine channel %u\n", tx_req);
|
||||||
ret = -ENXIO;
|
ret = -ENXIO;
|
||||||
|
@ -87,6 +87,12 @@ static const struct sdhci_ops sdhci_acpi_ops_dflt = {
|
|||||||
.enable_dma = sdhci_acpi_enable_dma,
|
.enable_dma = sdhci_acpi_enable_dma,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct sdhci_acpi_slot sdhci_acpi_slot_int_emmc = {
|
||||||
|
.caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE,
|
||||||
|
.caps2 = MMC_CAP2_HC_ERASE_SZ,
|
||||||
|
.flags = SDHCI_ACPI_RUNTIME_PM,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = {
|
static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = {
|
||||||
.quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON,
|
.quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON,
|
||||||
.caps = MMC_CAP_NONREMOVABLE | MMC_CAP_POWER_OFF_CARD,
|
.caps = MMC_CAP_NONREMOVABLE | MMC_CAP_POWER_OFF_CARD,
|
||||||
@ -94,23 +100,67 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = {
|
|||||||
.pm_caps = MMC_PM_KEEP_POWER,
|
.pm_caps = MMC_PM_KEEP_POWER,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sd = {
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sdhci_acpi_uid_slot {
|
||||||
|
const char *hid;
|
||||||
|
const char *uid;
|
||||||
|
const struct sdhci_acpi_slot *slot;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct sdhci_acpi_uid_slot sdhci_acpi_uids[] = {
|
||||||
|
{ "80860F14" , "1" , &sdhci_acpi_slot_int_emmc },
|
||||||
|
{ "80860F14" , "3" , &sdhci_acpi_slot_int_sd },
|
||||||
|
{ "INT33BB" , "2" , &sdhci_acpi_slot_int_sdio },
|
||||||
|
{ "INT33C6" , NULL, &sdhci_acpi_slot_int_sdio },
|
||||||
|
{ "PNP0D40" },
|
||||||
|
{ },
|
||||||
|
};
|
||||||
|
|
||||||
static const struct acpi_device_id sdhci_acpi_ids[] = {
|
static const struct acpi_device_id sdhci_acpi_ids[] = {
|
||||||
{ "INT33C6", (kernel_ulong_t)&sdhci_acpi_slot_int_sdio },
|
{ "80860F14" },
|
||||||
{ "PNP0D40" },
|
{ "INT33BB" },
|
||||||
|
{ "INT33C6" },
|
||||||
|
{ "PNP0D40" },
|
||||||
{ },
|
{ },
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(acpi, sdhci_acpi_ids);
|
MODULE_DEVICE_TABLE(acpi, sdhci_acpi_ids);
|
||||||
|
|
||||||
static const struct sdhci_acpi_slot *sdhci_acpi_get_slot(const char *hid)
|
static const struct sdhci_acpi_slot *sdhci_acpi_get_slot_by_ids(const char *hid,
|
||||||
|
const char *uid)
|
||||||
{
|
{
|
||||||
const struct acpi_device_id *id;
|
const struct sdhci_acpi_uid_slot *u;
|
||||||
|
|
||||||
for (id = sdhci_acpi_ids; id->id[0]; id++)
|
for (u = sdhci_acpi_uids; u->hid; u++) {
|
||||||
if (!strcmp(id->id, hid))
|
if (strcmp(u->hid, hid))
|
||||||
return (const struct sdhci_acpi_slot *)id->driver_data;
|
continue;
|
||||||
|
if (!u->uid)
|
||||||
|
return u->slot;
|
||||||
|
if (uid && !strcmp(u->uid, uid))
|
||||||
|
return u->slot;
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct sdhci_acpi_slot *sdhci_acpi_get_slot(acpi_handle handle,
|
||||||
|
const char *hid)
|
||||||
|
{
|
||||||
|
const struct sdhci_acpi_slot *slot;
|
||||||
|
struct acpi_device_info *info;
|
||||||
|
const char *uid = NULL;
|
||||||
|
acpi_status status;
|
||||||
|
|
||||||
|
status = acpi_get_object_info(handle, &info);
|
||||||
|
if (!ACPI_FAILURE(status) && (info->valid & ACPI_VALID_UID))
|
||||||
|
uid = info->unique_id.string;
|
||||||
|
|
||||||
|
slot = sdhci_acpi_get_slot_by_ids(hid, uid);
|
||||||
|
|
||||||
|
kfree(info);
|
||||||
|
return slot;
|
||||||
|
}
|
||||||
|
|
||||||
static int sdhci_acpi_probe(struct platform_device *pdev)
|
static int sdhci_acpi_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
@ -148,7 +198,7 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
c = sdhci_priv(host);
|
c = sdhci_priv(host);
|
||||||
c->host = host;
|
c->host = host;
|
||||||
c->slot = sdhci_acpi_get_slot(hid);
|
c->slot = sdhci_acpi_get_slot(handle, hid);
|
||||||
c->pdev = pdev;
|
c->pdev = pdev;
|
||||||
c->use_runtime_pm = sdhci_acpi_flag(c, SDHCI_ACPI_RUNTIME_PM);
|
c->use_runtime_pm = sdhci_acpi_flag(c, SDHCI_ACPI_RUNTIME_PM);
|
||||||
|
|
||||||
@ -202,6 +252,7 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
|
|||||||
goto err_free;
|
goto err_free;
|
||||||
|
|
||||||
if (c->use_runtime_pm) {
|
if (c->use_runtime_pm) {
|
||||||
|
pm_runtime_set_active(dev);
|
||||||
pm_suspend_ignore_children(dev, 1);
|
pm_suspend_ignore_children(dev, 1);
|
||||||
pm_runtime_set_autosuspend_delay(dev, 50);
|
pm_runtime_set_autosuspend_delay(dev, 50);
|
||||||
pm_runtime_use_autosuspend(dev);
|
pm_runtime_use_autosuspend(dev);
|
||||||
|
@ -85,6 +85,12 @@ struct pltfm_imx_data {
|
|||||||
struct clk *clk_ipg;
|
struct clk *clk_ipg;
|
||||||
struct clk *clk_ahb;
|
struct clk *clk_ahb;
|
||||||
struct clk *clk_per;
|
struct clk *clk_per;
|
||||||
|
enum {
|
||||||
|
NO_CMD_PENDING, /* no multiblock command pending*/
|
||||||
|
MULTIBLK_IN_PROCESS, /* exact multiblock cmd in process */
|
||||||
|
WAIT_FOR_INT, /* sent CMD12, waiting for response INT */
|
||||||
|
} multiblock_status;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct platform_device_id imx_esdhc_devtype[] = {
|
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
|
|||||||
|
|
||||||
static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
|
static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
|
||||||
{
|
{
|
||||||
|
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
|
||||||
|
struct pltfm_imx_data *imx_data = pltfm_host->priv;
|
||||||
u32 val = readl(host->ioaddr + reg);
|
u32 val = readl(host->ioaddr + reg);
|
||||||
|
|
||||||
if (unlikely(reg == SDHCI_CAPABILITIES)) {
|
if (unlikely(reg == SDHCI_CAPABILITIES)) {
|
||||||
@ -175,6 +183,18 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
|
|||||||
val &= ~ESDHC_INT_VENDOR_SPEC_DMA_ERR;
|
val &= ~ESDHC_INT_VENDOR_SPEC_DMA_ERR;
|
||||||
val |= SDHCI_INT_ADMA_ERROR;
|
val |= SDHCI_INT_ADMA_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* mask off the interrupt we get in response to the manually
|
||||||
|
* sent CMD12
|
||||||
|
*/
|
||||||
|
if ((imx_data->multiblock_status == WAIT_FOR_INT) &&
|
||||||
|
((val & SDHCI_INT_RESPONSE) == SDHCI_INT_RESPONSE)) {
|
||||||
|
val &= ~SDHCI_INT_RESPONSE;
|
||||||
|
writel(SDHCI_INT_RESPONSE, host->ioaddr +
|
||||||
|
SDHCI_INT_STATUS);
|
||||||
|
imx_data->multiblock_status = NO_CMD_PENDING;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return val;
|
return val;
|
||||||
@ -211,6 +231,15 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg)
|
|||||||
v = readl(host->ioaddr + ESDHC_VENDOR_SPEC);
|
v = readl(host->ioaddr + ESDHC_VENDOR_SPEC);
|
||||||
v &= ~ESDHC_VENDOR_SPEC_SDIO_QUIRK;
|
v &= ~ESDHC_VENDOR_SPEC_SDIO_QUIRK;
|
||||||
writel(v, host->ioaddr + ESDHC_VENDOR_SPEC);
|
writel(v, host->ioaddr + ESDHC_VENDOR_SPEC);
|
||||||
|
|
||||||
|
if (imx_data->multiblock_status == MULTIBLK_IN_PROCESS)
|
||||||
|
{
|
||||||
|
/* send a manual CMD12 with RESPTYP=none */
|
||||||
|
data = MMC_STOP_TRANSMISSION << 24 |
|
||||||
|
SDHCI_CMD_ABORTCMD << 16;
|
||||||
|
writel(data, host->ioaddr + SDHCI_TRANSFER_MODE);
|
||||||
|
imx_data->multiblock_status = WAIT_FOR_INT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)) {
|
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)
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case SDHCI_COMMAND:
|
case SDHCI_COMMAND:
|
||||||
if ((host->cmd->opcode == MMC_STOP_TRANSMISSION ||
|
if (host->cmd->opcode == MMC_STOP_TRANSMISSION)
|
||||||
host->cmd->opcode == MMC_SET_BLOCK_COUNT) &&
|
|
||||||
(imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT))
|
|
||||||
val |= SDHCI_CMD_ABORTCMD;
|
val |= SDHCI_CMD_ABORTCMD;
|
||||||
|
|
||||||
|
if ((host->cmd->opcode == MMC_SET_BLOCK_COUNT) &&
|
||||||
|
(imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT))
|
||||||
|
imx_data->multiblock_status = MULTIBLK_IN_PROCESS;
|
||||||
|
|
||||||
if (is_imx6q_usdhc(imx_data))
|
if (is_imx6q_usdhc(imx_data))
|
||||||
writel(val << 16,
|
writel(val << 16,
|
||||||
host->ioaddr + SDHCI_TRANSFER_MODE);
|
host->ioaddr + SDHCI_TRANSFER_MODE);
|
||||||
@ -324,8 +355,10 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg)
|
|||||||
/*
|
/*
|
||||||
* Do not touch buswidth bits here. This is done in
|
* Do not touch buswidth bits here. This is done in
|
||||||
* esdhc_pltfm_bus_width.
|
* esdhc_pltfm_bus_width.
|
||||||
|
* Do not touch the D3CD bit either which is used for the
|
||||||
|
* SDIO interrupt errata workaround.
|
||||||
*/
|
*/
|
||||||
mask = 0xffff & ~ESDHC_CTRL_BUSWIDTH_MASK;
|
mask = 0xffff & ~(ESDHC_CTRL_BUSWIDTH_MASK | ESDHC_CTRL_D3CD);
|
||||||
|
|
||||||
esdhc_clrset_le(host, mask, new_val, reg);
|
esdhc_clrset_le(host, mask, new_val, reg);
|
||||||
return;
|
return;
|
||||||
|
@ -33,6 +33,9 @@
|
|||||||
*/
|
*/
|
||||||
#define PCI_DEVICE_ID_INTEL_PCH_SDIO0 0x8809
|
#define PCI_DEVICE_ID_INTEL_PCH_SDIO0 0x8809
|
||||||
#define PCI_DEVICE_ID_INTEL_PCH_SDIO1 0x880a
|
#define PCI_DEVICE_ID_INTEL_PCH_SDIO1 0x880a
|
||||||
|
#define PCI_DEVICE_ID_INTEL_BYT_EMMC 0x0f14
|
||||||
|
#define PCI_DEVICE_ID_INTEL_BYT_SDIO 0x0f15
|
||||||
|
#define PCI_DEVICE_ID_INTEL_BYT_SD 0x0f16
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PCI registers
|
* PCI registers
|
||||||
@ -304,6 +307,33 @@ static const struct sdhci_pci_fixes sdhci_intel_pch_sdio = {
|
|||||||
.probe_slot = pch_hc_probe_slot,
|
.probe_slot = pch_hc_probe_slot,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot)
|
||||||
|
{
|
||||||
|
slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE;
|
||||||
|
slot->host->mmc->caps2 |= MMC_CAP2_HC_ERASE_SZ;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int byt_sdio_probe_slot(struct sdhci_pci_slot *slot)
|
||||||
|
{
|
||||||
|
slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_NONREMOVABLE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct sdhci_pci_fixes sdhci_intel_byt_emmc = {
|
||||||
|
.allow_runtime_pm = true,
|
||||||
|
.probe_slot = byt_emmc_probe_slot,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = {
|
||||||
|
.quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON,
|
||||||
|
.allow_runtime_pm = true,
|
||||||
|
.probe_slot = byt_sdio_probe_slot,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct sdhci_pci_fixes sdhci_intel_byt_sd = {
|
||||||
|
};
|
||||||
|
|
||||||
/* O2Micro extra registers */
|
/* O2Micro extra registers */
|
||||||
#define O2_SD_LOCK_WP 0xD3
|
#define O2_SD_LOCK_WP 0xD3
|
||||||
#define O2_SD_MULTI_VCC3V 0xEE
|
#define O2_SD_MULTI_VCC3V 0xEE
|
||||||
@ -855,6 +885,30 @@ static const struct pci_device_id pci_ids[] = {
|
|||||||
.driver_data = (kernel_ulong_t)&sdhci_intel_pch_sdio,
|
.driver_data = (kernel_ulong_t)&sdhci_intel_pch_sdio,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
.vendor = PCI_VENDOR_ID_INTEL,
|
||||||
|
.device = PCI_DEVICE_ID_INTEL_BYT_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_BYT_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_BYT_SD,
|
||||||
|
.subvendor = PCI_ANY_ID,
|
||||||
|
.subdevice = PCI_ANY_ID,
|
||||||
|
.driver_data = (kernel_ulong_t)&sdhci_intel_byt_sd,
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
.vendor = PCI_VENDOR_ID_O2,
|
.vendor = PCI_VENDOR_ID_O2,
|
||||||
.device = PCI_DEVICE_ID_O2_8120,
|
.device = PCI_DEVICE_ID_O2_8120,
|
||||||
|
Loading…
Reference in New Issue
Block a user