diff options
Diffstat (limited to 'drivers/mmc/host/sdhci-omap.c')
| -rw-r--r-- | drivers/mmc/host/sdhci-omap.c | 84 |
1 files changed, 34 insertions, 50 deletions
diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c index 64e27c2821f9..b5d7c1a80a92 100644 --- a/drivers/mmc/host/sdhci-omap.c +++ b/drivers/mmc/host/sdhci-omap.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/** +/* * SDHCI Controller driver for TI's OMAP SoCs * * Copyright (C) 2017 Texas Instruments @@ -11,7 +11,6 @@ #include <linux/mmc/slot-gpio.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/of_irq.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> @@ -370,7 +369,7 @@ static int sdhci_omap_execute_tuning(struct mmc_host *mmc, u32 opcode) /* * Stage 1: Search for a maximum pass window ignoring any - * any single point failures. If the tuning value ends up + * single point failures. If the tuning value ends up * near it, move away from it in stage 2 below */ while (phase_delay <= MAX_PHASE_DELAY) { @@ -926,7 +925,7 @@ static void sdhci_omap_set_timeout(struct sdhci_host *host, __sdhci_set_timeout(host, cmd); } -static struct sdhci_ops sdhci_omap_ops = { +static const struct sdhci_ops sdhci_omap_ops = { .set_clock = sdhci_omap_set_clock, .set_power = sdhci_omap_set_power, .enable_dma = sdhci_omap_enable_dma, @@ -1219,16 +1218,11 @@ static int sdhci_omap_probe(struct platform_device *pdev) struct sdhci_pltfm_host *pltfm_host; struct sdhci_omap_host *omap_host; struct mmc_host *mmc; - const struct of_device_id *match; - struct sdhci_omap_data *data; + const struct sdhci_omap_data *data; const struct soc_device_attribute *soc; struct resource *regs; - match = of_match_device(omap_sdhci_match, dev); - if (!match) - return -EINVAL; - - data = (struct sdhci_omap_data *)match->data; + data = of_device_get_match_data(&pdev->dev); if (!data) { dev_err(dev, "no sdhci omap data\n"); return -EINVAL; @@ -1263,7 +1257,7 @@ static int sdhci_omap_probe(struct platform_device *pdev) sdhci_get_of_property(pdev); ret = mmc_of_parse(mmc); if (ret) - goto err_pltfm_free; + return ret; soc = soc_device_match(sdhci_omap_soc_devices); if (soc) { @@ -1276,26 +1270,23 @@ static int sdhci_omap_probe(struct platform_device *pdev) mmc->f_max = 48000000; } - if (!mmc_can_gpio_ro(mmc)) + if (!mmc_host_can_gpio_ro(mmc)) mmc->caps2 |= MMC_CAP2_NO_WRITE_PROTECT; pltfm_host->clk = devm_clk_get(dev, "fck"); - if (IS_ERR(pltfm_host->clk)) { - ret = PTR_ERR(pltfm_host->clk); - goto err_pltfm_free; - } + if (IS_ERR(pltfm_host->clk)) + return PTR_ERR(pltfm_host->clk); ret = clk_set_rate(pltfm_host->clk, mmc->f_max); - if (ret) { - dev_err(dev, "failed to set clock to %d\n", mmc->f_max); - goto err_pltfm_free; - } + if (ret) + return dev_err_probe(dev, ret, + "failed to set clock to %d\n", mmc->f_max); omap_host->pbias = devm_regulator_get_optional(dev, "pbias"); if (IS_ERR(omap_host->pbias)) { ret = PTR_ERR(omap_host->pbias); if (ret != -ENODEV) - goto err_pltfm_free; + return ret; dev_dbg(dev, "unable to get pbias regulator %d\n", ret); } omap_host->pbias_enabled = false; @@ -1303,8 +1294,9 @@ static int sdhci_omap_probe(struct platform_device *pdev) /* * omap_device_pm_domain has callbacks to enable the main * functional clock, interface clock and also configure the - * SYSCONFIG register of omap devices. The callback will be invoked - * as part of pm_runtime_get_sync. + * SYSCONFIG register to clear any boot loader set voltage + * capabilities before calling sdhci_setup_host(). The + * callback will be invoked as part of pm_runtime_get_sync. */ pm_runtime_use_autosuspend(dev); pm_runtime_set_autosuspend_delay(dev, 50); @@ -1344,8 +1336,8 @@ static int sdhci_omap_probe(struct platform_device *pdev) /* R1B responses is required to properly manage HW busy detection. */ mmc->caps |= MMC_CAP_NEED_RSP_BUSY; - /* Allow card power off and runtime PM for eMMC/SD card devices */ - mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_AGGRESSIVE_PM; + /* Enable SDIO card power off. */ + mmc->caps |= MMC_CAP_POWER_OFF_CARD; ret = sdhci_setup_host(host); if (ret) @@ -1378,7 +1370,6 @@ static int sdhci_omap_probe(struct platform_device *pdev) host->mmc->pm_caps |= MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ; } - pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); return 0; @@ -1387,18 +1378,14 @@ err_cleanup_host: sdhci_cleanup_host(host); err_rpm_put: - pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); err_rpm_disable: pm_runtime_dont_use_autosuspend(dev); pm_runtime_disable(dev); - -err_pltfm_free: - sdhci_pltfm_free(pdev); return ret; } -static int sdhci_omap_remove(struct platform_device *pdev) +static void sdhci_omap_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct sdhci_host *host = platform_get_drvdata(pdev); @@ -1411,13 +1398,9 @@ static int sdhci_omap_remove(struct platform_device *pdev) pm_runtime_put_sync(dev); /* Ensure device gets disabled despite userspace sysfs config */ pm_runtime_force_suspend(dev); - sdhci_pltfm_free(pdev); - - return 0; } -#ifdef CONFIG_PM -static void __maybe_unused sdhci_omap_context_save(struct sdhci_omap_host *omap_host) +static void sdhci_omap_context_save(struct sdhci_omap_host *omap_host) { omap_host->con = sdhci_omap_readl(omap_host, SDHCI_OMAP_CON); omap_host->hctl = sdhci_omap_readl(omap_host, SDHCI_OMAP_HCTL); @@ -1428,7 +1411,7 @@ static void __maybe_unused sdhci_omap_context_save(struct sdhci_omap_host *omap_ } /* Order matters here, HCTL must be restored in two phases */ -static void __maybe_unused sdhci_omap_context_restore(struct sdhci_omap_host *omap_host) +static void sdhci_omap_context_restore(struct sdhci_omap_host *omap_host) { sdhci_omap_writel(omap_host, SDHCI_OMAP_HCTL, omap_host->hctl); sdhci_omap_writel(omap_host, SDHCI_OMAP_CAPA, omap_host->capa); @@ -1440,13 +1423,17 @@ static void __maybe_unused sdhci_omap_context_restore(struct sdhci_omap_host *om sdhci_omap_writel(omap_host, SDHCI_OMAP_ISE, omap_host->ise); } -static int __maybe_unused sdhci_omap_runtime_suspend(struct device *dev) +static int sdhci_omap_runtime_suspend(struct device *dev) { struct sdhci_host *host = dev_get_drvdata(dev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_omap_host *omap_host = sdhci_pltfm_priv(pltfm_host); - sdhci_runtime_suspend_host(host); + if (host->tuning_mode != SDHCI_TUNING_MODE_3) + mmc_retune_needed(host->mmc); + + if (omap_host->con != -EINVAL) + sdhci_runtime_suspend_host(host); sdhci_omap_context_save(omap_host); @@ -1455,7 +1442,7 @@ static int __maybe_unused sdhci_omap_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused sdhci_omap_runtime_resume(struct device *dev) +static int sdhci_omap_runtime_resume(struct device *dev) { struct sdhci_host *host = dev_get_drvdata(dev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -1463,20 +1450,17 @@ static int __maybe_unused sdhci_omap_runtime_resume(struct device *dev) pinctrl_pm_select_default_state(dev); - if (omap_host->con != -EINVAL) + if (omap_host->con != -EINVAL) { sdhci_omap_context_restore(omap_host); - - sdhci_runtime_resume_host(host, 0); + sdhci_runtime_resume_host(host, 0); + } return 0; } -#endif static const struct dev_pm_ops sdhci_omap_dev_pm_ops = { - SET_RUNTIME_PM_OPS(sdhci_omap_runtime_suspend, - sdhci_omap_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + RUNTIME_PM_OPS(sdhci_omap_runtime_suspend, sdhci_omap_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; static struct platform_driver sdhci_omap_driver = { @@ -1485,7 +1469,7 @@ static struct platform_driver sdhci_omap_driver = { .driver = { .name = "sdhci-omap", .probe_type = PROBE_PREFER_ASYNCHRONOUS, - .pm = &sdhci_omap_dev_pm_ops, + .pm = pm_ptr(&sdhci_omap_dev_pm_ops), .of_match_table = omap_sdhci_match, }, }; |
