diff options
Diffstat (limited to 'drivers/mmc/host/sdhci-st.c')
| -rw-r--r-- | drivers/mmc/host/sdhci-st.c | 91 |
1 files changed, 42 insertions, 49 deletions
diff --git a/drivers/mmc/host/sdhci-st.c b/drivers/mmc/host/sdhci-st.c index 68c36c9fa231..bf6685805137 100644 --- a/drivers/mmc/host/sdhci-st.c +++ b/drivers/mmc/host/sdhci-st.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Support for SDHCI on STMicroelectronics SoCs * @@ -6,16 +7,6 @@ * Contributors: Peter Griffin <peter.griffin@linaro.org> * * Based on sdhci-cns3xxx.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * */ #include <linux/io.h> @@ -357,7 +348,6 @@ static int sdhci_st_probe(struct platform_device *pdev) struct clk *clk, *icnclk; int ret = 0; u16 host_version; - struct resource *res; struct reset_control *rstc; clk = devm_clk_get(&pdev->dev, "mmc"); @@ -371,11 +361,10 @@ static int sdhci_st_probe(struct platform_device *pdev) if (IS_ERR(icnclk)) icnclk = NULL; - rstc = devm_reset_control_get(&pdev->dev, NULL); + rstc = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); if (IS_ERR(rstc)) - rstc = NULL; - else - reset_control_deassert(rstc); + return PTR_ERR(rstc); + reset_control_deassert(rstc); host = sdhci_pltfm_init(pdev, &sdhci_st_pdata, sizeof(*pdata)); if (IS_ERR(host)) { @@ -391,20 +380,25 @@ static int sdhci_st_probe(struct platform_device *pdev) ret = mmc_of_parse(host->mmc); if (ret) { dev_err(&pdev->dev, "Failed mmc_of_parse\n"); - goto err_of; + goto err_pltfm_init; + } + + ret = clk_prepare_enable(clk); + if (ret) { + dev_err(&pdev->dev, "Failed to prepare clock\n"); + goto err_pltfm_init; } - clk_prepare_enable(clk); - clk_prepare_enable(icnclk); + ret = clk_prepare_enable(icnclk); + if (ret) { + dev_err(&pdev->dev, "Failed to prepare icn clock\n"); + goto err_icnclk; + } /* Configure the FlashSS Top registers for setting eMMC TX/RX delay */ - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, - "top-mmc-delay"); - pdata->top_ioaddr = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(pdata->top_ioaddr)) { - dev_warn(&pdev->dev, "FlashSS Top Dly registers not available"); + pdata->top_ioaddr = devm_platform_ioremap_resource_byname(pdev, "top-mmc-delay"); + if (IS_ERR(pdata->top_ioaddr)) pdata->top_ioaddr = NULL; - } pltfm_host->clk = clk; pdata->icnclk = icnclk; @@ -413,10 +407,8 @@ static int sdhci_st_probe(struct platform_device *pdev) st_mmcss_cconfig(np, host); ret = sdhci_add_host(host); - if (ret) { - dev_err(&pdev->dev, "Failed sdhci_add_host\n"); + if (ret) goto err_out; - } host_version = readw_relaxed((host->ioaddr + SDHCI_HOST_VERSION)); @@ -429,35 +421,30 @@ static int sdhci_st_probe(struct platform_device *pdev) err_out: clk_disable_unprepare(icnclk); +err_icnclk: clk_disable_unprepare(clk); -err_of: - sdhci_pltfm_free(pdev); err_pltfm_init: - if (rstc) - reset_control_assert(rstc); + reset_control_assert(rstc); return ret; } -static int sdhci_st_remove(struct platform_device *pdev) +static void sdhci_st_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host); struct reset_control *rstc = pdata->rstc; - int ret; + struct clk *clk = pltfm_host->clk; - ret = sdhci_pltfm_unregister(pdev); + sdhci_pltfm_remove(pdev); clk_disable_unprepare(pdata->icnclk); + clk_disable_unprepare(clk); - if (rstc) - reset_control_assert(rstc); - - return ret; + reset_control_assert(rstc); } -#ifdef CONFIG_PM_SLEEP static int sdhci_st_suspend(struct device *dev) { struct sdhci_host *host = dev_get_drvdata(dev); @@ -472,8 +459,7 @@ static int sdhci_st_suspend(struct device *dev) if (ret) goto out; - if (pdata->rstc) - reset_control_assert(pdata->rstc); + reset_control_assert(pdata->rstc); clk_disable_unprepare(pdata->icnclk); clk_disable_unprepare(pltfm_host->clk); @@ -487,20 +473,26 @@ static int sdhci_st_resume(struct device *dev) struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host); struct device_node *np = dev->of_node; + int ret; + + ret = clk_prepare_enable(pltfm_host->clk); + if (ret) + return ret; - clk_prepare_enable(pltfm_host->clk); - clk_prepare_enable(pdata->icnclk); + ret = clk_prepare_enable(pdata->icnclk); + if (ret) { + clk_disable_unprepare(pltfm_host->clk); + return ret; + } - if (pdata->rstc) - reset_control_deassert(pdata->rstc); + reset_control_deassert(pdata->rstc); st_mmcss_cconfig(np, host); return sdhci_resume_host(host); } -#endif -static SIMPLE_DEV_PM_OPS(sdhci_st_pmops, sdhci_st_suspend, sdhci_st_resume); +static DEFINE_SIMPLE_DEV_PM_OPS(sdhci_st_pmops, sdhci_st_suspend, sdhci_st_resume); static const struct of_device_id st_sdhci_match[] = { { .compatible = "st,sdhci" }, @@ -514,8 +506,9 @@ static struct platform_driver sdhci_st_driver = { .remove = sdhci_st_remove, .driver = { .name = "sdhci-st", - .pm = &sdhci_st_pmops, - .of_match_table = of_match_ptr(st_sdhci_match), + .probe_type = PROBE_PREFER_ASYNCHRONOUS, + .pm = pm_sleep_ptr(&sdhci_st_pmops), + .of_match_table = st_sdhci_match, }, }; |
