RE: [v3, 1/7] mmc: sdhci-of-esdhc: add peripheral clock support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Adrian,


> -----Original Message-----
> From: linux-mmc-owner@xxxxxxxxxxxxxxx [mailto:linux-mmc-
> owner@xxxxxxxxxxxxxxx] On Behalf Of Y.B. Lu
> Sent: Tuesday, April 11, 2017 1:15 PM
> To: Adrian Hunter; linux-mmc@xxxxxxxxxxxxxxx; devicetree@xxxxxxxxxxxxxxx;
> linux-arm-kernel@xxxxxxxxxxxxxxxxxxx; ulf.hansson@xxxxxxxxxx; Rob Herring;
> Mark Rutland; Catalin Marinas; Will Deacon
> Cc: Xiaobo Xie
> Subject: RE: [v3, 1/7] mmc: sdhci-of-esdhc: add peripheral clock support
> 
> Hi Adrian,
> 
> 
> > -----Original Message-----
> > From: Adrian Hunter [mailto:adrian.hunter@xxxxxxxxx]
> > Sent: Monday, April 10, 2017 8:36 PM
> > To: Y.B. Lu; linux-mmc@xxxxxxxxxxxxxxx; devicetree@xxxxxxxxxxxxxxx;
> > linux-arm-kernel@xxxxxxxxxxxxxxxxxxx; ulf.hansson@xxxxxxxxxx; Rob
> > Herring; Mark Rutland; Catalin Marinas; Will Deacon
> > Cc: Xiaobo Xie
> > Subject: Re: [v3, 1/7] mmc: sdhci-of-esdhc: add peripheral clock
> > support
> >
> > On 27/03/17 10:49, Yangbo Lu wrote:
> > > eSDHC could select peripheral clock or platform clock as clock
> > > source by the PCS bit of eSDHC Control Register, and this bit
> > > couldn't be reset by software reset for all. In default, the
> > > platform clock is used. But we have to use peripheral clock since it
> > > has a higher frequency to support eMMC
> > > HS200 mode and SD UHS-I mode. This patch is to add peripheral clock
> > > support and use it instead of platform clock if it's declared in
> > > eSDHC
> > dts node.
> > >
> > > Signed-off-by: Yangbo Lu <yangbo.lu@xxxxxxx>
> >
> > Apart from minor comments:
> >
> > Acked-by: Adrian Hunter <adrian.hunter@xxxxxxxxx>
> >
> > > ---
> > > Changes for v2:
> > > 	- None
> > > Changes for v3:
> > > 	- None
> > > ---
> > >  drivers/mmc/host/sdhci-esdhc.h    |  1 +
> > >  drivers/mmc/host/sdhci-of-esdhc.c | 70
> > > +++++++++++++++++++++++++++++++++++++--
> > >  2 files changed, 69 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/drivers/mmc/host/sdhci-esdhc.h
> > > b/drivers/mmc/host/sdhci-esdhc.h index ece8b37..5343fc0 100644
> > > --- a/drivers/mmc/host/sdhci-esdhc.h
> > > +++ b/drivers/mmc/host/sdhci-esdhc.h
> > > @@ -54,6 +54,7 @@
> > >
> > >  /* Control Register for DMA transfer */
> > >  #define ESDHC_DMA_SYSCTL		0x40c
> > > +#define ESDHC_PERIPHERAL_CLK_SEL	0x00080000
> > >  #define ESDHC_DMA_SNOOP			0x00000040
> > >
> > >  #endif /* _DRIVERS_MMC_SDHCI_ESDHC_H */ diff --git
> > > a/drivers/mmc/host/sdhci-of-esdhc.c
> > > b/drivers/mmc/host/sdhci-of-esdhc.c
> > > index ff37e74..7ce1caf 100644
> > > --- a/drivers/mmc/host/sdhci-of-esdhc.c
> > > +++ b/drivers/mmc/host/sdhci-of-esdhc.c
> > > @@ -19,6 +19,7 @@
> > >  #include <linux/delay.h>
> > >  #include <linux/module.h>
> > >  #include <linux/sys_soc.h>
> > > +#include <linux/clk.h>
> > >  #include <linux/mmc/host.h>
> > >  #include "sdhci-pltfm.h"
> > >  #include "sdhci-esdhc.h"
> > > @@ -30,6 +31,7 @@ struct sdhci_esdhc {
> > >  	u8 vendor_ver;
> > >  	u8 spec_ver;
> > >  	bool quirk_incorrect_hostver;
> > > +	unsigned int peripheral_clock;
> > >  };
> > >
> > >  /**
> > > @@ -414,15 +416,25 @@ static int esdhc_of_enable_dma(struct
> > > sdhci_host
> > > *host)  static unsigned int esdhc_of_get_max_clock(struct sdhci_host
> > > *host)  {
> > >  	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> > > +	struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
> > >
> > > -	return pltfm_host->clock;
> > > +	if (esdhc->peripheral_clock)
> > > +		return esdhc->peripheral_clock;
> > > +	else
> > > +		return pltfm_host->clock;
> > >  }
> > >
> > >  static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host)
> > > {
> > >  	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> > > +	struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
> > > +	unsigned int clock;
> > >
> > > -	return pltfm_host->clock / 256 / 16;
> > > +	if (esdhc->peripheral_clock)
> > > +		clock = esdhc->peripheral_clock;
> > > +	else
> > > +		clock = pltfm_host->clock;
> > > +	return clock / 256 / 16;
> > >  }
> > >
> > >  static void esdhc_of_set_clock(struct sdhci_host *host, unsigned
> > > int
> > > clock) @@ -512,6 +524,33 @@ static void
> > esdhc_pltfm_set_bus_width(struct sdhci_host *host, int width)
> > >  	sdhci_writel(host, ctrl, ESDHC_PROCTL);  }
> > >
> > > +static void esdhc_clock_enable(struct sdhci_host *host, bool
> > > +enable) {
> > > +	u32 val;
> > > +	u32 timeout;
> > > +
> > > +	val = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
> > > +
> > > +	if (enable)
> > > +		val |= ESDHC_CLOCK_SDCLKEN;
> > > +	else
> > > +		val &= ~ESDHC_CLOCK_SDCLKEN;
> > > +
> > > +	sdhci_writel(host, val, ESDHC_SYSTEM_CONTROL);
> > > +
> > > +	timeout = 20;
> > > +	val = ESDHC_CLOCK_STABLE;
> > > +	while (!(sdhci_readl(host, ESDHC_PRSSTAT) & val)) {
> > > +		if (timeout == 0) {
> > > +			pr_err("%s: Internal clock never stabilised.\n",
> > > +				mmc_hostname(host->mmc));
> > > +			break;
> > > +		}
> > > +		timeout--;
> > > +		mdelay(1);
> >
> > If the time to stabilize is much less that 1 ms then this loop can
> > waste time.  Have a look at the change in sdhci.c.
> >
> 
> [Lu Yangbo-B47093] Thanks a lot. The method in sdhci.c is really better.
> I will send next version to use it soon.
> 
> Currently another place in esdhc driver could also change to use this
> method. I will send a separate patch for that later.
> 

[Lu Yangbo-B47093] I just sent another patch to fix the mdelay problem.
https://patchwork.kernel.org/patch/9700193/

Thank you very much.

> 
> > > +	}
> > > +}
> > > +
> > >  static void esdhc_reset(struct sdhci_host *host, u8 mask)  {
> > >  	sdhci_reset(host, mask);
> > > @@ -613,6 +652,9 @@ static void esdhc_init(struct platform_device
> > > *pdev, struct sdhci_host *host)  {
> > >  	struct sdhci_pltfm_host *pltfm_host;
> > >  	struct sdhci_esdhc *esdhc;
> > > +	struct device_node *np;
> > > +	struct clk *clk;
> > > +	u32 val;
> > >  	u16 host_ver;
> > >
> > >  	pltfm_host = sdhci_priv(host);
> > > @@ -626,6 +668,30 @@ static void esdhc_init(struct platform_device
> > *pdev, struct sdhci_host *host)
> > >  		esdhc->quirk_incorrect_hostver = true;
> > >  	else
> > >  		esdhc->quirk_incorrect_hostver = false;
> > > +
> > > +	np = pdev->dev.of_node;
> > > +	clk = of_clk_get(np, 0);
> >
> > Should there be a clk_put somewhere?
> 
> [Lu Yangbo-B47093] Will add it after driver gets the clock value.
> 
> >
> > > +	if (!IS_ERR(clk)) {
> > > +		/*
> > > +		 * esdhc->peripheral_clock would be assigned with a value
> > > +		 * which is eSDHC base clock when use periperal clock.
> > > +		 * For ls1046a, the clock value got by common clk API is
> > > +		 * peripheral clock while the eSDHC base clock is 1/2
> > > +		 * peripheral clock.
> > > +		 */
> > > +		if (of_device_is_compatible(np, "fsl,ls1046a-esdhc"))
> > > +			esdhc->peripheral_clock = clk_get_rate(clk) / 2;
> > > +		else
> > > +			esdhc->peripheral_clock = clk_get_rate(clk);
> > > +	}
> > > +
> > > +	if (esdhc->peripheral_clock) {
> > > +		esdhc_clock_enable(host, false);
> > > +		val = sdhci_readl(host, ESDHC_DMA_SYSCTL);
> > > +		val |= ESDHC_PERIPHERAL_CLK_SEL;
> > > +		sdhci_writel(host, val, ESDHC_DMA_SYSCTL);
> > > +		esdhc_clock_enable(host, true);
> > > +	}
> > >  }
> > >
> > >  static int sdhci_esdhc_probe(struct platform_device *pdev)
> > >
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at
> http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux