diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-05-07 12:56:19 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-05-07 12:56:19 -0700 |
commit | 01e5d1830cf54ac45768ef9ceb3e79cea2e1198c (patch) | |
tree | 139cab6f6ea7e927d07e75028a74e7a98d554055 /drivers/mmc/core | |
parent | b4b52b881cf08e13d110eac811d4becc0775abbf (diff) | |
parent | 0a49a619e7e1aeb3f5f5511ca59314423c83dae2 (diff) | |
download | linux-01e5d1830cf54ac45768ef9ceb3e79cea2e1198c.tar.gz linux-01e5d1830cf54ac45768ef9ceb3e79cea2e1198c.tar.bz2 linux-01e5d1830cf54ac45768ef9ceb3e79cea2e1198c.zip |
Merge tag 'mmc-v5.2' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc
Pull MMC updates from Ulf Hansson:
"MMC core:
- Fix a few memoryleaks
- Minor improvements to the card initialization sequence
- Partially support sleepy GPIO controllers for pwrseq eMMC
MMC host:
- alcor: Work with multiple-entry sglists
- alcor: Enable DMA for writes
- meson-gx: Improve tuning support
- meson-gx: Avoid clock glitch when switching to DDR modes
- meson-gx: Disable unreliable HS400 mode
- mmci: Minor updates for support of HW busy detection
- mmci: Support data transfers for the stm32_sdmmc variant
- mmci: Restructure code to better support different variants
- mtk-sd: Add support for version found on MT7620 family SOCs
- mtk-sd: Add support for the MT8516 version
- mtk-sd: Add Chaotian Jing as the maintainer
- sdhci: Reorganize request-code to convert from tasklet to workqueue
- sdhci_am654: Stabilize support for lower speed modes
- sdhci-esdhc-imx: Add HS400 support for iMX7ULP
- sdhci-esdhc-imx: Add support for iMX7ULP version
- sdhci-of-arasan: Allow to disable DCMDs via DT for CQE
- sdhci-of-esdhc: Add support for the ls1028a version
- sdhci-of-esdhc: Several fixups for errata
- sdhci-pci: Fix BYT OCP setting
- sdhci-pci: Add support for Intel CML
- sdhci-tegra: Add support for system suspend/resume
- sdhci-tegra: Add CQE support for Tegra186 WAR
- sdhci-tegra: Add support for Tegra194
- sdhci-tegra: Update HW tuning process
MEMSTICK:
- I volunteered to help as a maintainer for the memstick subsystem,
which is reflected by an update to the MAINTAINERS file. Changes
are funneled through my MMC git and we will use the linux-mmc
mailing list.
MEMSTICK host:
- A few minor cleanups"
* tag 'mmc-v5.2' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc: (87 commits)
mmc: sdhci-pci: Fix BYT OCP setting
dt-bindings: mmc: add DT bindings for ls1028a eSDHC host controller
mmc: alcor: Drop pointer to mmc_host from alcor_sdmmc_host
mmc: mtk-sd: select REGULATOR
mmc: mtk-sd: enable internal card-detect logic.
mmc: mtk-sd: add support for config found in mt7620 family SOCs.
mmc: mtk-sd: don't hard-code interrupt trigger type
mmc: core: Fix tag set memory leak
dt-bindings: mmc: Add support for MT8516 to mtk-sd
mmc: mmci: Prevent polling for busy detection in IRQ context
mmc: mmci: Cleanup mmci_cmd_irq() for busy detect
mmc: usdhi6rol0: mark expected switch fall-throughs
mmc: core: Verify SD bus width
mmc: sdhci-esdhc-imx: Add HS400 support for iMX7ULP
mmc: sdhci-esdhc-imx: add pm_qos to interact with cpuidle
dt-bindings: mmc: fsl-imx-esdhc: add imx7ulp compatible string
mmc: meson-gx: add signal resampling tuning
mmc: meson-gx: remove Rx phase tuning
mmc: meson-gx: avoid clock glitch when switching to DDR modes
mmc: meson-gx: disable HS400
...
Diffstat (limited to 'drivers/mmc/core')
-rw-r--r-- | drivers/mmc/core/host.c | 4 | ||||
-rw-r--r-- | drivers/mmc/core/mmc_ops.c | 16 | ||||
-rw-r--r-- | drivers/mmc/core/pwrseq_emmc.c | 38 | ||||
-rw-r--r-- | drivers/mmc/core/queue.c | 1 | ||||
-rw-r--r-- | drivers/mmc/core/sd.c | 8 |
5 files changed, 41 insertions, 26 deletions
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 3a4402a79904..6a51f7a06ce7 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -363,11 +363,11 @@ int mmc_of_parse_voltage(struct device_node *np, u32 *mask) int num_ranges, i; voltage_ranges = of_get_property(np, "voltage-ranges", &num_ranges); - num_ranges = num_ranges / sizeof(*voltage_ranges) / 2; if (!voltage_ranges) { pr_debug("%pOF: voltage-ranges unspecified\n", np); return 0; } + num_ranges = num_ranges / sizeof(*voltage_ranges) / 2; if (!num_ranges) { pr_err("%pOF: voltage-ranges empty\n", np); return -EINVAL; @@ -429,8 +429,6 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) if (mmc_gpio_alloc(host)) { put_device(&host->class_dev); - ida_simple_remove(&mmc_host_ida, host->index); - kfree(host); return NULL; } diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index c5208fb312ae..a533cab8fccc 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -184,11 +184,7 @@ int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) if (err) break; - /* if we're just probing, do a single pass */ - if (ocr == 0) - break; - - /* otherwise wait until reset completes */ + /* wait until reset completes */ if (mmc_host_is_spi(host)) { if (!(cmd.resp[0] & R1_SPI_IDLE)) break; @@ -200,6 +196,16 @@ int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) err = -ETIMEDOUT; mmc_delay(10); + + /* + * According to eMMC specification v5.1 section 6.4.3, we + * should issue CMD1 repeatedly in the idle state until + * the eMMC is ready. Otherwise some eMMC devices seem to enter + * the inactive mode after mmc_init_card() issued CMD0 when + * the eMMC device is busy. + */ + if (!ocr && !mmc_host_is_spi(host)) + cmd.arg = cmd.resp[0] | BIT(30); } if (rocr && !mmc_host_is_spi(host)) diff --git a/drivers/mmc/core/pwrseq_emmc.c b/drivers/mmc/core/pwrseq_emmc.c index efb8a7965dd4..154f4204d58c 100644 --- a/drivers/mmc/core/pwrseq_emmc.c +++ b/drivers/mmc/core/pwrseq_emmc.c @@ -30,19 +30,14 @@ struct mmc_pwrseq_emmc { #define to_pwrseq_emmc(p) container_of(p, struct mmc_pwrseq_emmc, pwrseq) -static void __mmc_pwrseq_emmc_reset(struct mmc_pwrseq_emmc *pwrseq) -{ - gpiod_set_value(pwrseq->reset_gpio, 1); - udelay(1); - gpiod_set_value(pwrseq->reset_gpio, 0); - udelay(200); -} - static void mmc_pwrseq_emmc_reset(struct mmc_host *host) { struct mmc_pwrseq_emmc *pwrseq = to_pwrseq_emmc(host->pwrseq); - __mmc_pwrseq_emmc_reset(pwrseq); + gpiod_set_value_cansleep(pwrseq->reset_gpio, 1); + udelay(1); + gpiod_set_value_cansleep(pwrseq->reset_gpio, 0); + udelay(200); } static int mmc_pwrseq_emmc_reset_nb(struct notifier_block *this, @@ -50,8 +45,11 @@ static int mmc_pwrseq_emmc_reset_nb(struct notifier_block *this, { struct mmc_pwrseq_emmc *pwrseq = container_of(this, struct mmc_pwrseq_emmc, reset_nb); + gpiod_set_value(pwrseq->reset_gpio, 1); + udelay(1); + gpiod_set_value(pwrseq->reset_gpio, 0); + udelay(200); - __mmc_pwrseq_emmc_reset(pwrseq); return NOTIFY_DONE; } @@ -72,14 +70,18 @@ static int mmc_pwrseq_emmc_probe(struct platform_device *pdev) if (IS_ERR(pwrseq->reset_gpio)) return PTR_ERR(pwrseq->reset_gpio); - /* - * register reset handler to ensure emmc reset also from - * emergency_reboot(), priority 255 is the highest priority - * so it will be executed before any system reboot handler. - */ - pwrseq->reset_nb.notifier_call = mmc_pwrseq_emmc_reset_nb; - pwrseq->reset_nb.priority = 255; - register_restart_handler(&pwrseq->reset_nb); + if (!gpiod_cansleep(pwrseq->reset_gpio)) { + /* + * register reset handler to ensure emmc reset also from + * emergency_reboot(), priority 255 is the highest priority + * so it will be executed before any system reboot handler. + */ + pwrseq->reset_nb.notifier_call = mmc_pwrseq_emmc_reset_nb; + pwrseq->reset_nb.priority = 255; + register_restart_handler(&pwrseq->reset_nb); + } else { + dev_notice(dev, "EMMC reset pin tied to a sleepy GPIO driver; reset on emergency-reboot disabled\n"); + } pwrseq->pwrseq.ops = &mmc_pwrseq_emmc_ops; pwrseq->pwrseq.dev = dev; diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c index 7c364a9c4eeb..b5b9c6142f08 100644 --- a/drivers/mmc/core/queue.c +++ b/drivers/mmc/core/queue.c @@ -472,6 +472,7 @@ void mmc_cleanup_queue(struct mmc_queue *mq) blk_mq_unquiesce_queue(q); blk_cleanup_queue(q); + blk_mq_free_tag_set(&mq->tag_set); /* * A request can be completed before the next request, potentially diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 265e1aeeb9d8..d3d32f9a2cb1 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -221,6 +221,14 @@ static int mmc_decode_scr(struct mmc_card *card) if (scr->sda_spec3) scr->cmds = UNSTUFF_BITS(resp, 32, 2); + + /* SD Spec says: any SD Card shall set at least bits 0 and 2 */ + if (!(scr->bus_widths & SD_SCR_BUS_WIDTH_1) || + !(scr->bus_widths & SD_SCR_BUS_WIDTH_4)) { + pr_err("%s: invalid bus width\n", mmc_hostname(card->host)); + return -EINVAL; + } + return 0; } |