diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-21 21:04:54 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-21 21:04:54 +0100 |
commit | e67bd12d6036ae3de9eeb0ba52e43691264ec850 (patch) | |
tree | 0232867e68e2b56fd601f7c31b0d5f87d7ec3792 /drivers/mmc/host/sh_mobile_sdhi.c | |
parent | Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi (diff) | |
parent | mmc: core: add mmc prefix for blk_fixups (diff) | |
download | linux-e67bd12d6036ae3de9eeb0ba52e43691264ec850.tar.xz linux-e67bd12d6036ae3de9eeb0ba52e43691264ec850.zip |
Merge tag 'mmc-v4.11' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc
Pull MMC updates from Ulf Hansson:
"MMC core:
- Add support for Marvell SD8787 Wifi/BT chip
- Improve UHS support for SDIO
- Invent MMC_CAP_3_3V_DDR and a DT binding for eMMC DDR 3.3V mode
- Detect Auto BKOPS enable bit
- Export eMMC device lifetime information through sysfs
- First take to slim down the public mmc headers to avoid abuse
- Re-factoring of the mmc block device driver to prepare for blkmq
- Cleanup code for the mmc block device driver
- Clarify and cleanup code dealing with data requests
- Cleanup some code by converting to ida_simple_ functions
- Cleanup code dealing with card quirks
- Cleanup private and public mmc header files
MMC host:
- Don't rely on public mmc headers to include non-mmc related headers
- meson: Add support for eMMC HS400 mode
- meson: Various cleanups and improvements
- omap_hsmmc: Use the proper provided busy timeout from the core
- sunxi: Enable new timings for the A64 MMC controllers
- sunxi: Improvements for clock management
- tmio: Improvements for SDIO interrupts
- mxs-mmc: Add CMD23 support
- sdhci-msm: Enable HS400 enhanced strobe mode support
- sdhci-msm: Correct HS400 tuning sequence
- sdhci-acpi: Support deferred probe
- sdhci-pci: Add support for eMMC HS200 tuning mode on AMD
- mediatek: Correct the implementation of card busy detection
- dw_mmc: Initial support for ZX mmc controller
- sh_mobile_sdhi: Enable support for eMMC HS200 mode
- sh_mmcif: Various cleanups and improvements"
* tag 'mmc-v4.11' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc: (145 commits)
mmc: core: add mmc prefix for blk_fixups
mmc: core: move all quirks together into quirks.h
mmc: core: improve the quirks for sdio devices
mmc: core: move some sdio IDs out of quirks file
mmc: core: change quirks.c to be a header file
mmc: sdhci-cadence: fix bit shift of read data from PHY port
mmc: Adding AUTO_BKOPS_EN bit set for Auto BKOPS support
mmc: MAN_BKOPS_EN inverse debug message logic
mmc: meson-gx: add support for HS400 mode
mmc: meson-gx: remove unneeded checks in remove
mmc: meson-gx: reduce bounce buffer size
mmc: meson-gx: set max block count and request size
mmc: meson-gx: improve interrupt handling
mmc: meson-gx: improve meson_mmc_irq_thread
mmc: meson-gx: improve meson_mmc_clk_set
mmc: meson-gx: minor improvements in meson_mmc_set_ios
mmc: meson: Assign the minimum clk rate as close to 400KHz as possible
mmc: core: start to break apart mmc_start_areq()
mmc: block: respect bool returned from blk_end_request()
mmc: block: return errorcode from mmc_sd_num_wr_blocks()
...
Diffstat (limited to 'drivers/mmc/host/sh_mobile_sdhi.c')
-rw-r--r-- | drivers/mmc/host/sh_mobile_sdhi.c | 95 |
1 files changed, 50 insertions, 45 deletions
diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c index d46c2d00c182..bc6be0dbea39 100644 --- a/drivers/mmc/host/sh_mobile_sdhi.c +++ b/drivers/mmc/host/sh_mobile_sdhi.c @@ -143,6 +143,7 @@ MODULE_DEVICE_TABLE(of, sh_mobile_sdhi_of_match); struct sh_mobile_sdhi { struct clk *clk; + struct clk *clk_cd; struct tmio_mmc_data mmc_data; struct tmio_mmc_dma dma_priv; struct pinctrl *pinctrl; @@ -190,6 +191,12 @@ static int sh_mobile_sdhi_clk_enable(struct tmio_mmc_host *host) if (ret < 0) return ret; + ret = clk_prepare_enable(priv->clk_cd); + if (ret < 0) { + clk_disable_unprepare(priv->clk); + return ret; + } + /* * The clock driver may not know what maximum frequency * actually works, so it should be set with the max-frequency @@ -255,6 +262,7 @@ static void sh_mobile_sdhi_clk_disable(struct tmio_mmc_host *host) struct sh_mobile_sdhi *priv = host_to_priv(host); clk_disable_unprepare(priv->clk); + clk_disable_unprepare(priv->clk_cd); } static int sh_mobile_sdhi_card_busy(struct mmc_host *mmc) @@ -335,9 +343,6 @@ static unsigned int sh_mobile_sdhi_init_tuning(struct tmio_mmc_host *host) { struct sh_mobile_sdhi *priv; - if (!(host->mmc->caps & MMC_CAP_UHS_SDR104)) - return 0; - priv = host_to_priv(host); /* set sampling clock selection range */ @@ -444,12 +449,7 @@ static int sh_mobile_sdhi_select_tuning(struct tmio_mmc_host *host) static bool sh_mobile_sdhi_check_scc_error(struct tmio_mmc_host *host) { - struct sh_mobile_sdhi *priv; - - if (!(host->mmc->caps & MMC_CAP_UHS_SDR104)) - return 0; - - priv = host_to_priv(host); + struct sh_mobile_sdhi *priv = host_to_priv(host); /* Check SCC error */ if (sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL) & @@ -468,9 +468,6 @@ static void sh_mobile_sdhi_hw_reset(struct tmio_mmc_host *host) { struct sh_mobile_sdhi *priv; - if (!(host->mmc->caps & MMC_CAP_UHS_SDR104)) - return; - priv = host_to_priv(host); /* Reset SCC */ @@ -556,8 +553,7 @@ static void sh_mobile_sdhi_enable_dma(struct tmio_mmc_host *host, bool enable) static int sh_mobile_sdhi_probe(struct platform_device *pdev) { - const struct of_device_id *of_id = - of_match_device(sh_mobile_sdhi_of_match, &pdev->dev); + const struct sh_mobile_sdhi_of_data *of_data = of_device_get_match_data(&pdev->dev); struct sh_mobile_sdhi *priv; struct tmio_mmc_data *mmc_data; struct tmio_mmc_data *mmd = pdev->dev.platform_data; @@ -584,6 +580,21 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev) goto eprobe; } + /* + * Some controllers provide a 2nd clock just to run the internal card + * detection logic. Unfortunately, the existing driver architecture does + * not support a separation of clocks for runtime PM usage. When + * native hotplug is used, the tmio driver assumes that the core + * must continue to run for card detect to stay active, so we cannot + * disable it. + * Additionally, it is prohibited to supply a clock to the core but not + * to the card detect circuit. That leaves us with if separate clocks + * are presented, we must treat them both as virtually 1 clock. + */ + priv->clk_cd = devm_clk_get(&pdev->dev, "cd"); + if (IS_ERR(priv->clk_cd)) + priv->clk_cd = NULL; + priv->pinctrl = devm_pinctrl_get(&pdev->dev); if (!IS_ERR(priv->pinctrl)) { priv->pins_default = pinctrl_lookup_state(priv->pinctrl, @@ -598,9 +609,8 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev) goto eprobe; } - if (of_id && of_id->data) { - const struct sh_mobile_sdhi_of_data *of_data = of_id->data; + if (of_data) { mmc_data->flags |= of_data->tmio_flags; mmc_data->ocr_mask = of_data->tmio_ocr_mask; mmc_data->capabilities |= of_data->capabilities; @@ -623,11 +633,6 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev) host->card_busy = sh_mobile_sdhi_card_busy; host->start_signal_voltage_switch = sh_mobile_sdhi_start_signal_voltage_switch; - host->init_tuning = sh_mobile_sdhi_init_tuning; - host->prepare_tuning = sh_mobile_sdhi_prepare_tuning; - host->select_tuning = sh_mobile_sdhi_select_tuning; - host->check_scc_error = sh_mobile_sdhi_check_scc_error; - host->hw_reset = sh_mobile_sdhi_hw_reset; } /* Orginally registers were 16 bit apart, could be 32 or 64 nowadays */ @@ -659,40 +664,40 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev) */ mmc_data->flags |= TMIO_MMC_HAVE_CMD12_CTRL; - /* - * All SDHI need SDIO_INFO1 reserved bit - */ - mmc_data->flags |= TMIO_MMC_SDIO_STATUS_QUIRK; + /* All SDHI have SDIO status bits which must be 1 */ + mmc_data->flags |= TMIO_MMC_SDIO_STATUS_SETBITS; ret = tmio_mmc_host_probe(host, mmc_data); if (ret < 0) goto efree; - if (host->mmc->caps & MMC_CAP_UHS_SDR104) { + /* Enable tuning iff we have an SCC and a supported mode */ + if (of_data && of_data->scc_offset && + (host->mmc->caps & MMC_CAP_UHS_SDR104 || + host->mmc->caps2 & MMC_CAP2_HS200_1_8V_SDR)) { + const struct sh_mobile_sdhi_scc *taps = of_data->taps; + bool hit = false; + host->mmc->caps |= MMC_CAP_HW_RESET; - if (of_id && of_id->data) { - const struct sh_mobile_sdhi_of_data *of_data; - const struct sh_mobile_sdhi_scc *taps; - bool hit = false; - - of_data = of_id->data; - taps = of_data->taps; - - for (i = 0; i < of_data->taps_num; i++) { - if (taps[i].clk_rate == 0 || - taps[i].clk_rate == host->mmc->f_max) { - host->scc_tappos = taps->tap; - hit = true; - break; - } + for (i = 0; i < of_data->taps_num; i++) { + if (taps[i].clk_rate == 0 || + taps[i].clk_rate == host->mmc->f_max) { + host->scc_tappos = taps->tap; + hit = true; + break; } + } - if (!hit) - dev_warn(&host->pdev->dev, "Unknown clock rate for SDR104\n"); + if (!hit) + dev_warn(&host->pdev->dev, "Unknown clock rate for SDR104\n"); - priv->scc_ctl = host->ctl + of_data->scc_offset; - } + priv->scc_ctl = host->ctl + of_data->scc_offset; + host->init_tuning = sh_mobile_sdhi_init_tuning; + host->prepare_tuning = sh_mobile_sdhi_prepare_tuning; + host->select_tuning = sh_mobile_sdhi_select_tuning; + host->check_scc_error = sh_mobile_sdhi_check_scc_error; + host->hw_reset = sh_mobile_sdhi_hw_reset; } i = 0; |