diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-06 02:11:43 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-06 02:11:43 +0300 |
commit | f60342fac9fae20ada2cd5faadbc2a1337cae03f (patch) | |
tree | fe64b1cb3ea699d819e5e808264903aee2d8dc9a /drivers/mmc/core/sdio.c | |
parent | 5231804cf9e584f3e7e763a0d6d2fffe011c1bce (diff) | |
parent | ef5332c10d4f332a2ac79e9ad5452f4e89d1815a (diff) | |
download | linux-f60342fac9fae20ada2cd5faadbc2a1337cae03f.tar.xz |
Merge tag 'mmc-v4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc
Pull MMC updates from Ulf Hansson:
"MMC core:
- Decrease polling rate for erase/trim/discard
- Allow non-sleeping GPIOs for card detect
- Improve mmc block removal path
- Enable support for mmc_sw_reset() for SDIO cards
- Add mmc_sw_reset() to allow users to do a soft reset of the card
- Allow power delay to be tunable via DT
- Allow card detect debounce delay to be tunable via DT
- Enable new quirk to limit clock rate for Marvell 8887 chip
- Don't show eMMC RPMB and BOOT areas in /proc/partitions
- Add capability to avoid 3.3V signaling for fragile HWs
MMC host:
- Improve/fixup support for handle highmem pages
- Remove depends on HAS_DMA in case of platform dependency
- mvsdio: Enable support for erase/trim/discard
- rtsx_usb: Enable support for erase/trim/discard
- renesas_sdhi: Fix WP logic regressions
- renesas_sdhi: Add r8a77965 support
- renesas_sdhi: Add R8A77980 to whitelist
- meson: Add optional support for device reset
- meson: Add support for the Meson-AXG platform
- dw_mmc: Add new driver for BlueField DW variant
- mediatek: Add support for 64G DRAM DMA
- sunxi: Deploy runtime PM support
- jz4740: Add support for JZ4780
- jz4740: Enable support for DT based platforms
- sdhci: Various improvement to timeout handling
- sdhci: Disable support for HS200/HS400/UHS when no 1.8V support
- sdhci-omap: Add support for controller in k2g SoC
- sdhci-omap: Add workarounds for a couple of Erratas
- sdhci-omap: Enable support for generic sdhci DT properties
- sdhci-cadence: Re-send tune request to deal with errata
- sdhci-pci: Fix 3.3V voltage switch for some BYT-based Intel controllers
- sdhci-pci: Avoid 3.3V signaling on some NI 904x
- sdhci-esdhc-imx: Use watermark levels for PIO access
- sdhci-msm: Improve card detection handling
- sdhci-msm: Add support voltage pad switching"
* tag 'mmc-v4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc: (104 commits)
mmc: renesas_sdhi: really fix WP logic regressions
mmc: mvsdio: Enable MMC_CAP_ERASE
mmc: mvsdio: Respect card busy time out from mmc core
mmc: sdhci-msm: Remove NO_CARD_NO_RESET quirk
mmc: sunxi: Use ifdef rather than __maybe_unused
mmc: mxmmc: Use ifdef rather than __maybe_unused
mmc: mxmmc: include linux/highmem.h
mmc: sunxi: mark PM functions as __maybe_unused
mmc: Throttle calls to MMC_SEND_STATUS during mmc_do_erase()
mmc: au1xmmc: handle highmem pages
mmc: Allow non-sleeping GPIO cd
mmc: sdhci-*: Don't emit error msg if sdhci_add_host() fails
mmc: sd: Define name for default speed dtr
mmc: core: Move calls to ->prepare_hs400_tuning() closer to mmc code
mmc: sdhci-xenon: use match_string() helper
mmc: wbsd: handle highmem pages
mmc: ushc: handle highmem pages
mmc: mxcmmc: handle highmem pages
mmc: atmel-mci: use sg_copy_{from,to}_buffer
mmc: android-goldfish: use sg_copy_{from,to}_buffer
...
Diffstat (limited to 'drivers/mmc/core/sdio.c')
-rw-r--r-- | drivers/mmc/core/sdio.c | 70 |
1 files changed, 47 insertions, 23 deletions
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index c599a628a387..a86490dbca70 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -444,6 +444,7 @@ static int sdio_set_bus_speed_mode(struct mmc_card *card) unsigned int bus_speed, timing; int err; unsigned char speed; + unsigned int max_rate; /* * If the host doesn't support any of the UHS-I modes, fallback on @@ -500,9 +501,12 @@ static int sdio_set_bus_speed_mode(struct mmc_card *card) if (err) return err; + 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, card->sw_caps.uhs_max_dtr); + mmc_set_clock(card->host, max_rate); } return 0; @@ -788,6 +792,14 @@ try_again: if (err) goto remove; } + + if (host->caps2 & MMC_CAP2_AVOID_3_3V && + host->ios.signal_voltage == MMC_SIGNAL_VOLTAGE_330) { + pr_err("%s: Host failed to negotiate down from 3.3V\n", + mmc_hostname(host)); + err = -EINVAL; + goto remove; + } finish: if (!oldcard) host->card = card; @@ -801,6 +813,22 @@ err: return err; } +static int mmc_sdio_reinit_card(struct mmc_host *host, bool powered_resume) +{ + int ret; + + sdio_reset(host); + mmc_go_idle(host); + mmc_send_if_cond(host, host->card->ocr); + + ret = mmc_send_io_op_cond(host, 0, NULL); + if (ret) + return ret; + + return mmc_sdio_init_card(host, host->card->ocr, host->card, + powered_resume); +} + /* * Host is being removed. Free up the current card. */ @@ -948,14 +976,7 @@ static int mmc_sdio_resume(struct mmc_host *host) /* No need to reinitialize powered-resumed nonremovable cards */ if (mmc_card_is_removable(host) || !mmc_card_keep_power(host)) { - sdio_reset(host); - mmc_go_idle(host); - mmc_send_if_cond(host, host->card->ocr); - err = mmc_send_io_op_cond(host, 0, NULL); - if (!err) - err = mmc_sdio_init_card(host, host->card->ocr, - host->card, - mmc_card_keep_power(host)); + err = mmc_sdio_reinit_card(host, mmc_card_keep_power(host)); } else if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) { /* We may have switched to 1-bit mode during suspend */ err = sdio_enable_4bit_bus(host->card); @@ -978,8 +999,6 @@ static int mmc_sdio_power_restore(struct mmc_host *host) { int ret; - mmc_claim_host(host); - /* * Reset the card by performing the same steps that are taken by * mmc_rescan_try_freq() and mmc_attach_sdio() during a "normal" probe. @@ -997,20 +1016,12 @@ static int mmc_sdio_power_restore(struct mmc_host *host) * */ - sdio_reset(host); - mmc_go_idle(host); - mmc_send_if_cond(host, host->card->ocr); - - ret = mmc_send_io_op_cond(host, 0, NULL); - if (ret) - goto out; + mmc_claim_host(host); - ret = mmc_sdio_init_card(host, host->card->ocr, host->card, - mmc_card_keep_power(host)); + ret = mmc_sdio_reinit_card(host, mmc_card_keep_power(host)); if (!ret && host->sdio_irqs) mmc_signal_sdio_irq(host); -out: mmc_release_host(host); return ret; @@ -1039,12 +1050,24 @@ static int mmc_sdio_runtime_resume(struct mmc_host *host) return ret; } -static int mmc_sdio_reset(struct mmc_host *host) +static int mmc_sdio_hw_reset(struct mmc_host *host) { mmc_power_cycle(host, host->card->ocr); return mmc_sdio_power_restore(host); } +static int mmc_sdio_sw_reset(struct mmc_host *host) +{ + mmc_set_clock(host, host->f_init); + sdio_reset(host); + mmc_go_idle(host); + + mmc_set_initial_state(host); + mmc_set_initial_signal_voltage(host); + + return mmc_sdio_reinit_card(host, 0); +} + static const struct mmc_bus_ops mmc_sdio_ops = { .remove = mmc_sdio_remove, .detect = mmc_sdio_detect, @@ -1055,7 +1078,8 @@ static const struct mmc_bus_ops mmc_sdio_ops = { .runtime_resume = mmc_sdio_runtime_resume, .power_restore = mmc_sdio_power_restore, .alive = mmc_sdio_alive, - .reset = mmc_sdio_reset, + .hw_reset = mmc_sdio_hw_reset, + .sw_reset = mmc_sdio_sw_reset, }; |