diff mbox series

[RFC,v3.1,18/27] mmc: sdhci-uhs2: add clock operations

Message ID 20201106022726.19831-19-takahiro.akashi@linaro.org
State New
Headers show
Series Add support UHS-II for GL9755 | expand

Commit Message

AKASHI Takahiro Nov. 6, 2020, 2:27 a.m. UTC
This is a sdhci version of mmc's uhs2_[enable|disable]_clk operations.

Signed-off-by: Ben Chuang <ben.chuang@genesyslogic.com.tw>

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>

---
 drivers/mmc/host/sdhci-uhs2.c | 41 +++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)

-- 
2.28.0

Comments

Adrian Hunter Nov. 26, 2020, 8:17 a.m. UTC | #1
On 6/11/20 4:27 am, AKASHI Takahiro wrote:
> This is a sdhci version of mmc's uhs2_[enable|disable]_clk operations.

> 

> Signed-off-by: Ben Chuang <ben.chuang@genesyslogic.com.tw>

> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>

> ---

>  drivers/mmc/host/sdhci-uhs2.c | 41 +++++++++++++++++++++++++++++++++++

>  1 file changed, 41 insertions(+)

> 

> diff --git a/drivers/mmc/host/sdhci-uhs2.c b/drivers/mmc/host/sdhci-uhs2.c

> index 994dff967e85..55362ace1857 100644

> --- a/drivers/mmc/host/sdhci-uhs2.c

> +++ b/drivers/mmc/host/sdhci-uhs2.c

> @@ -11,6 +11,7 @@

>   */

>  

>  #include <linux/delay.h>

> +#include <linux/ktime.h>

>  #include <linux/module.h>

>  

>  #include "sdhci.h"

> @@ -385,6 +386,42 @@ void sdhci_uhs2_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)

>  	__sdhci_uhs2_set_ios(mmc, ios);

>  }

>  

> +static void sdhci_uhs2_disable_clk(struct mmc_host *mmc)

> +{

> +        struct sdhci_host *host = mmc_priv(mmc);

> +	u16 clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);

> +

> +	clk &= ~SDHCI_CLOCK_CARD_EN;

> +	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);

> +}

> +

> +static void sdhci_uhs2_enable_clk(struct mmc_host *mmc)

> +{

> +        struct sdhci_host *host = mmc_priv(mmc);

> +	u16 clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);

> +	ktime_t timeout;

> +

> +	clk |= SDHCI_CLOCK_CARD_EN;

> +	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);

> +

> +	/* Wait max 20 ms */

> +	timeout = ktime_add_ms(ktime_get(), 20);

> +	while (1) {

> +		bool timedout = ktime_after(ktime_get(), timeout);

> +

> +		clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);


Can use read_poll_timeout(sdhci_readw,..., host, SDHCI_CLOCK_CONTROL)

> +		if (clk & SDHCI_CLOCK_INT_STABLE)

> +			break;

> +		if (timedout) {

> +			pr_err("%s: Internal clock never stabilised.\n",

> +			       mmc_hostname(host->mmc));

> +			sdhci_dumpregs(host);

> +			return;

> +		}

> +		udelay(10);

> +	}

> +}

> +

>  /*****************************************************************************\

>   *                                                                           *

>   * Driver init/exit                                                          *

> @@ -556,6 +593,10 @@ static int sdhci_uhs2_host_ops_init(struct sdhci_host *host)

>  

>  	if (!host->mmc_host_ops.uhs2_detect_init)

>  		host->mmc_host_ops.uhs2_detect_init = sdhci_uhs2_do_detect_init;

> +	if (!host->mmc_host_ops.uhs2_disable_clk)

> +		host->mmc_host_ops.uhs2_disable_clk = sdhci_uhs2_disable_clk;

> +	if (!host->mmc_host_ops.uhs2_enable_clk)

> +		host->mmc_host_ops.uhs2_enable_clk = sdhci_uhs2_enable_clk;

>  

>  	return 0;

>  }

>
AKASHI Takahiro Dec. 1, 2020, 2:27 a.m. UTC | #2
On Thu, Nov 26, 2020 at 10:17:59AM +0200, Adrian Hunter wrote:
> On 6/11/20 4:27 am, AKASHI Takahiro wrote:

> > This is a sdhci version of mmc's uhs2_[enable|disable]_clk operations.

> > 

> > Signed-off-by: Ben Chuang <ben.chuang@genesyslogic.com.tw>

> > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>

> > ---

> >  drivers/mmc/host/sdhci-uhs2.c | 41 +++++++++++++++++++++++++++++++++++

> >  1 file changed, 41 insertions(+)

> > 

> > diff --git a/drivers/mmc/host/sdhci-uhs2.c b/drivers/mmc/host/sdhci-uhs2.c

> > index 994dff967e85..55362ace1857 100644

> > --- a/drivers/mmc/host/sdhci-uhs2.c

> > +++ b/drivers/mmc/host/sdhci-uhs2.c

> > @@ -11,6 +11,7 @@

> >   */

> >  

> >  #include <linux/delay.h>

> > +#include <linux/ktime.h>

> >  #include <linux/module.h>

> >  

> >  #include "sdhci.h"

> > @@ -385,6 +386,42 @@ void sdhci_uhs2_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)

> >  	__sdhci_uhs2_set_ios(mmc, ios);

> >  }

> >  

> > +static void sdhci_uhs2_disable_clk(struct mmc_host *mmc)

> > +{

> > +        struct sdhci_host *host = mmc_priv(mmc);

> > +	u16 clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);

> > +

> > +	clk &= ~SDHCI_CLOCK_CARD_EN;

> > +	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);

> > +}

> > +

> > +static void sdhci_uhs2_enable_clk(struct mmc_host *mmc)

> > +{

> > +        struct sdhci_host *host = mmc_priv(mmc);

> > +	u16 clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);

> > +	ktime_t timeout;

> > +

> > +	clk |= SDHCI_CLOCK_CARD_EN;

> > +	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);

> > +

> > +	/* Wait max 20 ms */

> > +	timeout = ktime_add_ms(ktime_get(), 20);

> > +	while (1) {

> > +		bool timedout = ktime_after(ktime_get(), timeout);

> > +

> > +		clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);

> 

> Can use read_poll_timeout(sdhci_readw,..., host, SDHCI_CLOCK_CONTROL)


Okay.

-Takahiro Akashi

> > +		if (clk & SDHCI_CLOCK_INT_STABLE)

> > +			break;

> > +		if (timedout) {

> > +			pr_err("%s: Internal clock never stabilised.\n",

> > +			       mmc_hostname(host->mmc));

> > +			sdhci_dumpregs(host);

> > +			return;

> > +		}

> > +		udelay(10);

> > +	}

> > +}

> > +

> >  /*****************************************************************************\

> >   *                                                                           *

> >   * Driver init/exit                                                          *

> > @@ -556,6 +593,10 @@ static int sdhci_uhs2_host_ops_init(struct sdhci_host *host)

> >  

> >  	if (!host->mmc_host_ops.uhs2_detect_init)

> >  		host->mmc_host_ops.uhs2_detect_init = sdhci_uhs2_do_detect_init;

> > +	if (!host->mmc_host_ops.uhs2_disable_clk)

> > +		host->mmc_host_ops.uhs2_disable_clk = sdhci_uhs2_disable_clk;

> > +	if (!host->mmc_host_ops.uhs2_enable_clk)

> > +		host->mmc_host_ops.uhs2_enable_clk = sdhci_uhs2_enable_clk;

> >  

> >  	return 0;

> >  }

> > 

>
diff mbox series

Patch

diff --git a/drivers/mmc/host/sdhci-uhs2.c b/drivers/mmc/host/sdhci-uhs2.c
index 994dff967e85..55362ace1857 100644
--- a/drivers/mmc/host/sdhci-uhs2.c
+++ b/drivers/mmc/host/sdhci-uhs2.c
@@ -11,6 +11,7 @@ 
  */
 
 #include <linux/delay.h>
+#include <linux/ktime.h>
 #include <linux/module.h>
 
 #include "sdhci.h"
@@ -385,6 +386,42 @@  void sdhci_uhs2_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	__sdhci_uhs2_set_ios(mmc, ios);
 }
 
+static void sdhci_uhs2_disable_clk(struct mmc_host *mmc)
+{
+        struct sdhci_host *host = mmc_priv(mmc);
+	u16 clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+
+	clk &= ~SDHCI_CLOCK_CARD_EN;
+	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+}
+
+static void sdhci_uhs2_enable_clk(struct mmc_host *mmc)
+{
+        struct sdhci_host *host = mmc_priv(mmc);
+	u16 clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+	ktime_t timeout;
+
+	clk |= SDHCI_CLOCK_CARD_EN;
+	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+
+	/* Wait max 20 ms */
+	timeout = ktime_add_ms(ktime_get(), 20);
+	while (1) {
+		bool timedout = ktime_after(ktime_get(), timeout);
+
+		clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+		if (clk & SDHCI_CLOCK_INT_STABLE)
+			break;
+		if (timedout) {
+			pr_err("%s: Internal clock never stabilised.\n",
+			       mmc_hostname(host->mmc));
+			sdhci_dumpregs(host);
+			return;
+		}
+		udelay(10);
+	}
+}
+
 /*****************************************************************************\
  *                                                                           *
  * Driver init/exit                                                          *
@@ -556,6 +593,10 @@  static int sdhci_uhs2_host_ops_init(struct sdhci_host *host)
 
 	if (!host->mmc_host_ops.uhs2_detect_init)
 		host->mmc_host_ops.uhs2_detect_init = sdhci_uhs2_do_detect_init;
+	if (!host->mmc_host_ops.uhs2_disable_clk)
+		host->mmc_host_ops.uhs2_disable_clk = sdhci_uhs2_disable_clk;
+	if (!host->mmc_host_ops.uhs2_enable_clk)
+		host->mmc_host_ops.uhs2_enable_clk = sdhci_uhs2_enable_clk;
 
 	return 0;
 }