X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=kernel%2Fdrivers%2Fmmc%2Fcore%2Fsd.c;fp=kernel%2Fdrivers%2Fmmc%2Fcore%2Fsd.c;h=967535d76e3468199979be0ffff23a7d0d3c2a93;hb=e09b41010ba33a20a87472ee821fa407a5b8da36;hp=31a9ef256d0652d5b2ce64623d3a161bbcfcd6b7;hpb=f93b97fd65072de626c074dbe099a1fff05ce060;p=kvmfornfv.git diff --git a/kernel/drivers/mmc/core/sd.c b/kernel/drivers/mmc/core/sd.c index 31a9ef256..967535d76 100644 --- a/kernel/drivers/mmc/core/sd.c +++ b/kernel/drivers/mmc/core/sd.c @@ -357,8 +357,6 @@ int mmc_sd_switch_hs(struct mmc_card *card) if (card->sw_caps.hs_max_dtr == 0) return 0; - err = -EIO; - status = kmalloc(64, GFP_KERNEL); if (!status) { pr_err("%s: could not allocate a buffer for " @@ -386,64 +384,31 @@ out: static int sd_select_driver_type(struct mmc_card *card, u8 *status) { - int host_drv_type = SD_DRIVER_TYPE_B; - int card_drv_type = SD_DRIVER_TYPE_B; - int drive_strength; + int card_drv_type, drive_strength, drv_type; int err; - /* - * If the host doesn't support any of the Driver Types A,C or D, - * or there is no board specific handler then default Driver - * Type B is used. - */ - if (!(card->host->caps & (MMC_CAP_DRIVER_TYPE_A | MMC_CAP_DRIVER_TYPE_C - | MMC_CAP_DRIVER_TYPE_D))) - return 0; - - if (!card->host->ops->select_drive_strength) - return 0; - - if (card->host->caps & MMC_CAP_DRIVER_TYPE_A) - host_drv_type |= SD_DRIVER_TYPE_A; - - if (card->host->caps & MMC_CAP_DRIVER_TYPE_C) - host_drv_type |= SD_DRIVER_TYPE_C; - - if (card->host->caps & MMC_CAP_DRIVER_TYPE_D) - host_drv_type |= SD_DRIVER_TYPE_D; - - if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_A) - card_drv_type |= SD_DRIVER_TYPE_A; - - if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_C) - card_drv_type |= SD_DRIVER_TYPE_C; - - if (card->sw_caps.sd3_drv_type & SD_DRIVER_TYPE_D) - card_drv_type |= SD_DRIVER_TYPE_D; + card->drive_strength = 0; - /* - * The drive strength that the hardware can support - * depends on the board design. Pass the appropriate - * information and let the hardware specific code - * return what is possible given the options - */ - mmc_host_clk_hold(card->host); - drive_strength = card->host->ops->select_drive_strength( - card->sw_caps.uhs_max_dtr, - host_drv_type, card_drv_type); - mmc_host_clk_release(card->host); + card_drv_type = card->sw_caps.sd3_drv_type | SD_DRIVER_TYPE_B; - err = mmc_sd_switch(card, 1, 2, drive_strength, status); - if (err) - return err; + drive_strength = mmc_select_drive_strength(card, + card->sw_caps.uhs_max_dtr, + card_drv_type, &drv_type); - if ((status[15] & 0xF) != drive_strength) { - pr_warn("%s: Problem setting drive strength!\n", - mmc_hostname(card->host)); - return 0; + if (drive_strength) { + err = mmc_sd_switch(card, 1, 2, drive_strength, status); + if (err) + return err; + if ((status[15] & 0xF) != drive_strength) { + pr_warn("%s: Problem setting drive strength!\n", + mmc_hostname(card->host)); + return 0; + } + card->drive_strength = drive_strength; } - mmc_set_driver_type(card->host, drive_strength); + if (drv_type) + mmc_set_driver_type(card->host, drv_type); return 0; } @@ -661,9 +626,25 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card) * SDR104 mode SD-cards. Note that tuning is mandatory for SDR104. */ if (!mmc_host_is_spi(card->host) && - (card->sd_bus_speed == UHS_SDR50_BUS_SPEED || - card->sd_bus_speed == UHS_SDR104_BUS_SPEED)) + (card->host->ios.timing == MMC_TIMING_UHS_SDR50 || + card->host->ios.timing == MMC_TIMING_UHS_DDR50 || + card->host->ios.timing == MMC_TIMING_UHS_SDR104)) { err = mmc_execute_tuning(card); + + /* + * As SD Specifications Part1 Physical Layer Specification + * Version 3.01 says, CMD19 tuning is available for unlocked + * cards in transfer state of 1.8V signaling mode. The small + * difference between v3.00 and 3.01 spec means that CMD19 + * tuning is also available for DDR50 mode. + */ + if (err && card->host->ios.timing == MMC_TIMING_UHS_DDR50) { + pr_warn("%s: ddr50 tuning failed\n", + mmc_hostname(card->host)); + err = 0; + } + } + out: kfree(status); @@ -804,6 +785,26 @@ int mmc_sd_get_csd(struct mmc_host *host, struct mmc_card *card) return 0; } +static int mmc_sd_get_ro(struct mmc_host *host) +{ + int ro; + + /* + * Some systems don't feature a write-protect pin and don't need one. + * E.g. because they only have micro-SD card slot. For those systems + * assume that the SD card is always read-write. + */ + if (host->caps2 & MMC_CAP2_NO_WRITE_PROTECT) + return 0; + + if (!host->ops->get_ro) + return -1; + + ro = host->ops->get_ro(host); + + return ro; +} + int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card, bool reinit) { @@ -855,13 +856,7 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card, * Check if read-only switch is active. */ if (!reinit) { - int ro = -1; - - if (host->ops->get_ro) { - mmc_host_clk_hold(card->host); - ro = host->ops->get_ro(host); - mmc_host_clk_release(card->host); - } + int ro = mmc_sd_get_ro(host); if (ro < 0) { pr_warn("%s: host does not support reading read-only switch, assuming write-enable\n", @@ -1181,21 +1176,10 @@ static int mmc_sd_runtime_resume(struct mmc_host *host) return 0; } -static int mmc_sd_power_restore(struct mmc_host *host) -{ - int ret; - - mmc_claim_host(host); - ret = mmc_sd_init_card(host, host->card->ocr, host->card); - mmc_release_host(host); - - return ret; -} - static int mmc_sd_reset(struct mmc_host *host) { mmc_power_cycle(host, host->card->ocr); - return mmc_sd_power_restore(host); + return mmc_sd_init_card(host, host->card->ocr, host->card); } static const struct mmc_bus_ops mmc_sd_ops = { @@ -1205,7 +1189,6 @@ static const struct mmc_bus_ops mmc_sd_ops = { .runtime_resume = mmc_sd_runtime_resume, .suspend = mmc_sd_suspend, .resume = mmc_sd_resume, - .power_restore = mmc_sd_power_restore, .alive = mmc_sd_alive, .shutdown = mmc_sd_suspend, .reset = mmc_sd_reset, @@ -1260,14 +1243,13 @@ int mmc_attach_sd(struct mmc_host *host) mmc_release_host(host); err = mmc_add_card(host->card); - mmc_claim_host(host); if (err) goto remove_card; + mmc_claim_host(host); return 0; remove_card: - mmc_release_host(host); mmc_remove_card(host->card); host->card = NULL; mmc_claim_host(host);