diff options
author | Christian Hemp <c.hemp@phytec.de> | 2013-10-04 11:35:40 +0200 |
---|---|---|
committer | Justin Waters <justin.waters@timesys.com> | 2013-11-12 11:44:12 -0500 |
commit | ecacd71082e5eab9fdc6a82fa197ba7092374f2d (patch) | |
tree | 5850eeab12c0e63717cb978960b988d11b402da0 | |
parent | db29867c3a08bd41d83d260fc86ea8b88b242fac (diff) |
drivers: mmc: prepare mmc driver for tiwi
Signed-off-by: Grigory Milev <g.milev@sam-solutions.net>
Signed-off-by: Christian Hemp <c.hemp@phytec.de>
-rw-r--r-- | arch/arm/plat-mxc/include/mach/esdhc.h | 1 | ||||
-rw-r--r-- | drivers/mmc/core/sdio.c | 74 | ||||
-rw-r--r-- | drivers/mmc/core/sdio_cis.c | 18 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-esdhc-imx.c | 1 |
4 files changed, 91 insertions, 3 deletions
diff --git a/arch/arm/plat-mxc/include/mach/esdhc.h b/arch/arm/plat-mxc/include/mach/esdhc.h index bb15db1ecbc2..294e4cdc338e 100644 --- a/arch/arm/plat-mxc/include/mach/esdhc.h +++ b/arch/arm/plat-mxc/include/mach/esdhc.h @@ -34,6 +34,7 @@ struct esdhc_platform_data { unsigned int support_18v; unsigned int support_8bit; unsigned int keep_power_at_suspend; + unsigned int caps; unsigned int delay_line; int (*platform_pad_change)(unsigned int index, int clock); }; diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index cc3736bedb2b..6871378578a1 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -882,3 +882,77 @@ err: return err; } +int sdio_reset_comm(struct mmc_card *card) +{ + struct mmc_host *host = card->host; + u32 ocr; + int err; + + printk(KERN_ERR "%s():\n", __func__); + mmc_claim_host(host); + + mmc_go_idle(host); + + mmc_set_clock(host, host->f_min); + + err = mmc_send_io_op_cond(host, 0, &ocr); + if (err) + goto err; + + host->ocr = mmc_select_voltage(host, ocr); + if (!host->ocr) { + err = -EINVAL; + goto err; + } + + err = mmc_send_io_op_cond(host, host->ocr, &ocr); + if (err) + goto err; + + if (mmc_host_is_spi(host)) { + err = mmc_spi_set_crc(host, use_spi_crc); + if (err) + goto err; + } + + if (!mmc_host_is_spi(host)) { + err = mmc_send_relative_addr(host, &card->rca); + if (err) + goto err; + mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL); + } + if (!mmc_host_is_spi(host)) { + err = mmc_select_card(card); + if (err) + goto err; + } + + /* + * Switch to high-speed (if supported). + */ + err = sdio_enable_hs(card); + if (err > 0) + mmc_sd_go_highspeed(card); + else if (err) + goto err; + + /* + * Change to the card's maximum speed. + */ + mmc_set_clock(host, mmc_sdio_get_max_clock(card)); + + err = sdio_enable_4bit_bus(card); + if (err > 0) + mmc_set_bus_width(host, MMC_BUS_WIDTH_4); + else if (err) + goto err; + + mmc_release_host(host); + return 0; +err: + printk(KERN_ERR "%s: Error resetting SDIO communications (%d)\n", + mmc_hostname(host), err); + mmc_release_host(host); + return err; +} +EXPORT_SYMBOL(sdio_reset_comm); diff --git a/drivers/mmc/core/sdio_cis.c b/drivers/mmc/core/sdio_cis.c index 541bdb89e0c5..3b0ca8379897 100644 --- a/drivers/mmc/core/sdio_cis.c +++ b/drivers/mmc/core/sdio_cis.c @@ -230,6 +230,7 @@ static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func) int ret; struct sdio_func_tuple *this, **prev; unsigned i, ptr = 0; + unsigned ptr_null_end; /* * Note that this works for the common CIS (function number 0) as @@ -258,6 +259,7 @@ static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func) BUG_ON(*prev); + ptr_null_end = (ptr | 0xff) + 1; do { unsigned char tpl_code, tpl_link; @@ -269,6 +271,9 @@ static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func) if (tpl_code == 0xff) break; + if ((tpl_code == 0x00) && (ptr == ptr_null_end)) + break; /* patch for misbehaving rtl8712 card */ + /* null entries have no link field or data */ if (tpl_code == 0x00) continue; @@ -282,9 +287,10 @@ static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func) break; this = kmalloc(sizeof(*this) + tpl_link, GFP_KERNEL); - if (!this) - return -ENOMEM; - + if (!this) { + ret = -ENOMEM; + break; + } for (i = 0; i < tpl_link; i++) { ret = mmc_io_rw_direct(card, 0, 0, ptr + i, 0, &this->data[i]); @@ -328,6 +334,12 @@ static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func) * not going to be queued for a driver. */ kfree(this); + if (ret) { + printk(KERN_WARNING "%s: dropping invalid" + " CIS tuple 0x%02x (%u bytes)\n", + mmc_hostname(card->host), + tpl_code, tpl_link); + } } ptr += tpl_link; diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 35fd825f4709..7b08196eb4cf 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -855,6 +855,7 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd if (boarddata->support_8bit) host->mmc->caps |= MMC_CAP_8_BIT_DATA; + host->mmc->caps |= boarddata->caps; if (boarddata->keep_power_at_suspend) host->mmc->pm_caps |= (MMC_PM_KEEP_POWER | \ MMC_PM_WAKE_SDIO_IRQ); |