summaryrefslogtreecommitdiff
path: root/drivers/mmc/host/sdhci-omap.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/host/sdhci-omap.c')
-rw-r--r--drivers/mmc/host/sdhci-omap.c84
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,
},
};