diff options
Diffstat (limited to 'drivers/mmc/core')
-rw-r--r-- | drivers/mmc/core/core.c | 38 | ||||
-rw-r--r-- | drivers/mmc/core/core.h | 3 | ||||
-rw-r--r-- | drivers/mmc/core/host.c | 12 | ||||
-rw-r--r-- | drivers/mmc/core/mmc_ops.c | 6 | ||||
-rw-r--r-- | drivers/mmc/core/sd.c | 6 | ||||
-rw-r--r-- | drivers/mmc/core/sdio.c | 17 |
6 files changed, 71 insertions, 11 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 8f94c2539508..ca4e640eafb1 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -52,6 +52,8 @@ static const unsigned freqs[] = { 400000, 300000, 200000, 100000 }; +static int __mmc_max_reserved_idx = -1; + /* * Enabling software CRCs on the data blocks can be a significant (30%) * performance cost, and for other reasons may not always be desired. @@ -2395,10 +2397,46 @@ void mmc_stop_host(struct mmc_host *host) mmc_release_host(host); } +/* + * mmc_first_nonreserved_index() - get the first index that + * is not reserved + */ +int mmc_first_nonreserved_index(void) +{ + return __mmc_max_reserved_idx + 1; +} +EXPORT_SYMBOL(mmc_first_nonreserved_index); + +/* + * mmc_get_reserved_index() - get the index reserved for this host + * Return: The index reserved for this host or negative error value + * if no index is reserved for this host + */ +int mmc_get_reserved_index(struct mmc_host *host) +{ + return of_alias_get_id(host->parent->of_node, "mmc"); +} +EXPORT_SYMBOL(mmc_get_reserved_index); + +static void mmc_of_reserve_idx(void) +{ + int max; + + max = of_alias_max_index("mmc"); + if (max < 0) + return; + + __mmc_max_reserved_idx = max; + pr_debug("MMC: reserving %d slots for of aliases\n", + __mmc_max_reserved_idx + 1); +} + static int __init mmc_init(void) { int ret; + mmc_of_reserve_idx(); + ret = mmc_register_bus(); if (ret) return ret; diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index db3c9c68875d..09a11032d635 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -79,7 +79,8 @@ int mmc_detect_card_removed(struct mmc_host *host); int mmc_attach_mmc(struct mmc_host *host); int mmc_attach_sd(struct mmc_host *host); int mmc_attach_sdio(struct mmc_host *host); - +int mmc_first_nonreserved_index(void); +int mmc_get_reserved_index(struct mmc_host *host); /* Module parameters */ extern bool use_spi_crc; diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index f7339590a84c..b077e071505a 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -433,6 +433,7 @@ EXPORT_SYMBOL(mmc_of_parse_voltage); struct mmc_host *mmc_alloc_host(int extra, struct device *dev) { int err; + int alias_id; struct mmc_host *host; host = kzalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL); @@ -441,8 +442,16 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) /* scanning will be enabled when we're ready */ host->rescan_disable = 1; + host->parent = dev; - err = ida_simple_get(&mmc_host_ida, 0, 0, GFP_KERNEL); + alias_id = mmc_get_reserved_index(host); + if (alias_id >= 0) + err = ida_simple_get(&mmc_host_ida, alias_id, + alias_id + 1, GFP_KERNEL); + else + err = ida_simple_get(&mmc_host_ida, + mmc_first_nonreserved_index(), + 0, GFP_KERNEL); if (err < 0) { kfree(host); return NULL; @@ -452,7 +461,6 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) dev_set_name(&host->class_dev, "mmc%d", host->index); - host->parent = dev; host->class_dev.parent = dev; host->class_dev.class = &mmc_host_class; device_initialize(&host->class_dev); diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 09311c2bd858..2d9715378b42 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -589,6 +589,12 @@ out_tim: if (timing) mmc_set_timing(host, timing); + /* + * WORKAROUND: for Sandisk eMMC cards, it might need certain delay + * before sending CMD13 after CMD6 + */ + mdelay(1); + if (send_status) { err = mmc_switch_status(card); if (err && timing) diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index c6d7a0adde0d..b6fef82a9add 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -504,6 +504,12 @@ static int sd_set_bus_speed_mode(struct mmc_card *card, u8 *status) else { mmc_set_timing(card->host, timing); mmc_set_clock(card->host, card->sw_caps.uhs_max_dtr); + /* + * FIXME: Sandisk SD3.0 cards DDR50 mode requires such + * delay to get stable, without this delay we may encounter + * CRC errors after switch to DDR50 mode + */ + mmc_delay(100); } return 0; diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 0bf33786fc5c..3627c9d6452e 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -158,15 +158,18 @@ static int sdio_read_cccr(struct mmc_card *card, u32 ocr) if (mmc_host_uhs(card->host)) { if (data & SDIO_UHS_DDR50) card->sw_caps.sd3_bus_mode - |= SD_MODE_UHS_DDR50; + |= SD_MODE_UHS_DDR50 | SD_MODE_UHS_SDR50 + | SD_MODE_UHS_SDR25 | SD_MODE_UHS_SDR12; if (data & SDIO_UHS_SDR50) card->sw_caps.sd3_bus_mode - |= SD_MODE_UHS_SDR50; + |= SD_MODE_UHS_SDR50 | SD_MODE_UHS_SDR25 + | SD_MODE_UHS_SDR12; if (data & SDIO_UHS_SDR104) card->sw_caps.sd3_bus_mode - |= SD_MODE_UHS_SDR104; + |= SD_MODE_UHS_SDR104 | SD_MODE_UHS_SDR50 + | SD_MODE_UHS_SDR25 | SD_MODE_UHS_SDR12; } ret = mmc_io_rw_direct(card, 0, 0, @@ -500,10 +503,8 @@ static int sdio_set_bus_speed_mode(struct mmc_card *card) max_rate = min_not_zero(card->quirk_max_rate, card->sw_caps.uhs_max_dtr); - if (bus_speed) { - mmc_set_timing(card->host, timing); - mmc_set_clock(card->host, max_rate); - } + mmc_set_timing(card->host, timing); + mmc_set_clock(card->host, max_rate); return 0; } @@ -1026,7 +1027,7 @@ static int mmc_sdio_resume(struct mmc_host *host) if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD)) wake_up_process(host->sdio_irq_thread); else if (host->caps & MMC_CAP_SDIO_IRQ) - queue_delayed_work(system_wq, &host->sdio_irq_work, 0); + queue_delayed_work(system_wq, &host->sdio_irq_work, 1); } out: |