diff mbox series

[v2,3/4] mmc: sdhci-xenon: use clk only with DT

Message ID 20201120032639.24386-4-mw@semihalf.com
State New
Headers show
Series sdhci-xenon ACPI support | expand

Commit Message

Marcin Wojtas Nov. 20, 2020, 3:26 a.m. UTC
As a preparation for supporting ACPI, modify the driver
to use the clk framework only when booting with DT -
otherwise rely on the configuration done by firmware.
For that purpose introduce also a custom SDHCI get_max_clock
callback.

Signed-off-by: Marcin Wojtas <mw@semihalf.com>
---
 drivers/mmc/host/sdhci-xenon.c | 80 +++++++++++++-------
 1 file changed, 51 insertions(+), 29 deletions(-)

Comments

Ulf Hansson Nov. 24, 2020, 11:31 a.m. UTC | #1
On Fri, 20 Nov 2020 at 04:27, Marcin Wojtas <mw@semihalf.com> wrote:
>

> As a preparation for supporting ACPI, modify the driver

> to use the clk framework only when booting with DT -

> otherwise rely on the configuration done by firmware.

> For that purpose introduce also a custom SDHCI get_max_clock

> callback.

>

> Signed-off-by: Marcin Wojtas <mw@semihalf.com>


[...]

> @@ -561,9 +574,11 @@ static int xenon_probe(struct platform_device *pdev)

>         pm_runtime_put_noidle(&pdev->dev);

>         xenon_sdhc_unprepare(host);

>  err_clk_axi:

> -       clk_disable_unprepare(priv->axi_clk);

> +       if (dev->of_node)

> +               clk_disable_unprepare(priv->axi_clk);

>  err_clk:

> -       clk_disable_unprepare(pltfm_host->clk);

> +       if (dev->of_node)

> +               clk_disable_unprepare(pltfm_host->clk);


There's no need to check the dev->of_node, I believe. The
clk_disable_unprepare() is capable of managing a NULL pointer as
in-parameter.

[...]

Kind regards
Uffe
Marcin Wojtas Nov. 25, 2020, 11:50 a.m. UTC | #2
Hi Ulf


wt., 24 lis 2020 o 12:31 Ulf Hansson <ulf.hansson@linaro.org> napisaƂ(a):
>

> On Fri, 20 Nov 2020 at 04:27, Marcin Wojtas <mw@semihalf.com> wrote:

> >

> > As a preparation for supporting ACPI, modify the driver

> > to use the clk framework only when booting with DT -

> > otherwise rely on the configuration done by firmware.

> > For that purpose introduce also a custom SDHCI get_max_clock

> > callback.

> >

> > Signed-off-by: Marcin Wojtas <mw@semihalf.com>

>

> [...]

>

> > @@ -561,9 +574,11 @@ static int xenon_probe(struct platform_device *pdev)

> >         pm_runtime_put_noidle(&pdev->dev);

> >         xenon_sdhc_unprepare(host);

> >  err_clk_axi:

> > -       clk_disable_unprepare(priv->axi_clk);

> > +       if (dev->of_node)

> > +               clk_disable_unprepare(priv->axi_clk);

> >  err_clk:

> > -       clk_disable_unprepare(pltfm_host->clk);

> > +       if (dev->of_node)

> > +               clk_disable_unprepare(pltfm_host->clk);

>

> There's no need to check the dev->of_node, I believe. The

> clk_disable_unprepare() is capable of managing a NULL pointer as

> in-parameter.

>


Indeed, clk_disable_unprepare() can handle the NULL pointers. I will
wait a couple of days for other comments/remarks and will update this
patch in v3.

Best regards,
Marcin
diff mbox series

Patch

diff --git a/drivers/mmc/host/sdhci-xenon.c b/drivers/mmc/host/sdhci-xenon.c
index bfc76b0e3eaa..dfc3b5f62a6d 100644
--- a/drivers/mmc/host/sdhci-xenon.c
+++ b/drivers/mmc/host/sdhci-xenon.c
@@ -247,6 +247,16 @@  static void xenon_voltage_switch(struct sdhci_host *host)
 	sdhci_readw(host, SDHCI_HOST_CONTROL2);
 }
 
+static unsigned int xenon_get_max_clock(struct sdhci_host *host)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+
+	if (pltfm_host->clk)
+		return sdhci_pltfm_clk_get_max_clock(host);
+	else
+		return pltfm_host->clock;
+}
+
 static const struct sdhci_ops sdhci_xenon_ops = {
 	.voltage_switch		= xenon_voltage_switch,
 	.set_clock		= sdhci_set_clock,
@@ -254,7 +264,7 @@  static const struct sdhci_ops sdhci_xenon_ops = {
 	.set_bus_width		= sdhci_set_bus_width,
 	.reset			= xenon_reset,
 	.set_uhs_signaling	= xenon_set_uhs_signaling,
-	.get_max_clock		= sdhci_pltfm_clk_get_max_clock,
+	.get_max_clock		= xenon_get_max_clock,
 };
 
 static const struct sdhci_pltfm_data sdhci_xenon_pdata = {
@@ -483,6 +493,7 @@  static void xenon_sdhc_unprepare(struct sdhci_host *host)
 static int xenon_probe(struct platform_device *pdev)
 {
 	struct sdhci_pltfm_host *pltfm_host;
+	struct device *dev = &pdev->dev;
 	struct sdhci_host *host;
 	struct xenon_priv *priv;
 	int err;
@@ -503,25 +514,27 @@  static int xenon_probe(struct platform_device *pdev)
 	 */
 	xenon_replace_mmc_host_ops(host);
 
-	pltfm_host->clk = devm_clk_get(&pdev->dev, "core");
-	if (IS_ERR(pltfm_host->clk)) {
-		err = PTR_ERR(pltfm_host->clk);
-		dev_err(&pdev->dev, "Failed to setup input clk: %d\n", err);
-		goto free_pltfm;
-	}
-	err = clk_prepare_enable(pltfm_host->clk);
-	if (err)
-		goto free_pltfm;
-
-	priv->axi_clk = devm_clk_get(&pdev->dev, "axi");
-	if (IS_ERR(priv->axi_clk)) {
-		err = PTR_ERR(priv->axi_clk);
-		if (err == -EPROBE_DEFER)
-			goto err_clk;
-	} else {
-		err = clk_prepare_enable(priv->axi_clk);
+	if (dev->of_node) {
+		pltfm_host->clk = devm_clk_get(&pdev->dev, "core");
+		if (IS_ERR(pltfm_host->clk)) {
+			err = PTR_ERR(pltfm_host->clk);
+			dev_err(&pdev->dev, "Failed to setup input clk: %d\n", err);
+			goto free_pltfm;
+		}
+		err = clk_prepare_enable(pltfm_host->clk);
 		if (err)
-			goto err_clk;
+			goto free_pltfm;
+
+		priv->axi_clk = devm_clk_get(&pdev->dev, "axi");
+		if (IS_ERR(priv->axi_clk)) {
+			err = PTR_ERR(priv->axi_clk);
+			if (err == -EPROBE_DEFER)
+				goto err_clk;
+		} else {
+			err = clk_prepare_enable(priv->axi_clk);
+			if (err)
+				goto err_clk;
+		}
 	}
 
 	err = mmc_of_parse(host->mmc);
@@ -561,9 +574,11 @@  static int xenon_probe(struct platform_device *pdev)
 	pm_runtime_put_noidle(&pdev->dev);
 	xenon_sdhc_unprepare(host);
 err_clk_axi:
-	clk_disable_unprepare(priv->axi_clk);
+	if (dev->of_node)
+		clk_disable_unprepare(priv->axi_clk);
 err_clk:
-	clk_disable_unprepare(pltfm_host->clk);
+	if (dev->of_node)
+		clk_disable_unprepare(pltfm_host->clk);
 free_pltfm:
 	sdhci_pltfm_free(pdev);
 	return err;
@@ -574,6 +589,7 @@  static int xenon_remove(struct platform_device *pdev)
 	struct sdhci_host *host = platform_get_drvdata(pdev);
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
+	struct device *dev = &pdev->dev;
 
 	pm_runtime_get_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
@@ -582,8 +598,10 @@  static int xenon_remove(struct platform_device *pdev)
 	sdhci_remove_host(host, 0);
 
 	xenon_sdhc_unprepare(host);
-	clk_disable_unprepare(priv->axi_clk);
-	clk_disable_unprepare(pltfm_host->clk);
+	if (dev->of_node) {
+		clk_disable_unprepare(priv->axi_clk);
+		clk_disable_unprepare(pltfm_host->clk);
+	}
 
 	sdhci_pltfm_free(pdev);
 
@@ -620,7 +638,8 @@  static int xenon_runtime_suspend(struct device *dev)
 	if (host->tuning_mode != SDHCI_TUNING_MODE_3)
 		mmc_retune_needed(host->mmc);
 
-	clk_disable_unprepare(pltfm_host->clk);
+	if (dev->of_node)
+		clk_disable_unprepare(pltfm_host->clk);
 	/*
 	 * Need to update the priv->clock here, or when runtime resume
 	 * back, phy don't aware the clock change and won't adjust phy
@@ -637,10 +656,12 @@  static int xenon_runtime_resume(struct device *dev)
 	struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
 	int ret;
 
-	ret = clk_prepare_enable(pltfm_host->clk);
-	if (ret) {
-		dev_err(dev, "can't enable mainck\n");
-		return ret;
+	if (dev->of_node) {
+		ret = clk_prepare_enable(pltfm_host->clk);
+		if (ret) {
+			dev_err(dev, "can't enable mainck\n");
+			return ret;
+		}
 	}
 
 	if (priv->restore_needed) {
@@ -655,7 +676,8 @@  static int xenon_runtime_resume(struct device *dev)
 		goto out;
 	return 0;
 out:
-	clk_disable_unprepare(pltfm_host->clk);
+	if (dev->of_node)
+		clk_disable_unprepare(pltfm_host->clk);
 	return ret;
 }
 #endif /* CONFIG_PM */