[U-Boot] [PATCH] mmc: sdhci-cadence: set timing mode register depending on frequency

Jaehoon Chung jh80.chung at samsung.com
Fri Sep 29 02:35:01 UTC 2017


On 09/28/2017 09:13 PM, Masahiro Yamada wrote:
> The MMC framework in U-Boot does not support a systematic API for
> timing switch like mmc_set_timing() in Linux.
> 
> U-Boot just provides a hook to change the clock frequency via
> mmc_set_clock().  It is up to drivers if additional register
> settings are needed.
> 
> This driver needs to set a correct timing mode into a register when
> it migrates to a different speed mode.  Only increasing clock frequency
> could result in setup/hold timing violation.
> 
> The timing mode should be decided by checking MMC_TIMING_* like
> drivers/mmc/host/sdhci-cadence.c in Linux, but "timing" is not
> supported by U-Boot for now.  Just use mmc->clock to decide the
> timing mode.
> 
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>

Applied to u-boot-mmc. Thanks!

Best Regards,
Jaehoon Chung

> ---
> 
> This is a repost.
> 
> I sent the same one before
> http://patchwork.ozlabs.org/patch/764647/
> 
> I retracted it because I saw amazing framework improvements for MMC.
> 
> 4 months have passed since then, but nothing happened.
> 
> I do not wait any more.  I am reposting it.
> 
> 
>  drivers/mmc/sdhci-cadence.c | 51 +++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 51 insertions(+)
> 
> diff --git a/drivers/mmc/sdhci-cadence.c b/drivers/mmc/sdhci-cadence.c
> index f83c1d7..72d1c64 100644
> --- a/drivers/mmc/sdhci-cadence.c
> +++ b/drivers/mmc/sdhci-cadence.c
> @@ -23,6 +23,18 @@
>  #define   SDHCI_CDNS_HRS04_WDATA_SHIFT		8
>  #define   SDHCI_CDNS_HRS04_ADDR_SHIFT		0
>  
> +#define SDHCI_CDNS_HRS06		0x18		/* eMMC control */
> +#define   SDHCI_CDNS_HRS06_TUNE_UP		BIT(15)
> +#define   SDHCI_CDNS_HRS06_TUNE_SHIFT		8
> +#define   SDHCI_CDNS_HRS06_TUNE_MASK		0x3f
> +#define   SDHCI_CDNS_HRS06_MODE_MASK		0x7
> +#define   SDHCI_CDNS_HRS06_MODE_SD		0x0
> +#define   SDHCI_CDNS_HRS06_MODE_MMC_SDR		0x2
> +#define   SDHCI_CDNS_HRS06_MODE_MMC_DDR		0x3
> +#define   SDHCI_CDNS_HRS06_MODE_MMC_HS200	0x4
> +#define   SDHCI_CDNS_HRS06_MODE_MMC_HS400	0x5
> +#define   SDHCI_CDNS_HRS06_MODE_MMC_HS400ES	0x6
> +
>  /* SRS - Slot Register Set (SDHCI-compatible) */
>  #define SDHCI_CDNS_SRS_BASE		0x200
>  
> @@ -111,6 +123,44 @@ static int sdhci_cdns_phy_init(struct sdhci_cdns_plat *plat,
>  	return 0;
>  }
>  
> +static void sdhci_cdns_set_control_reg(struct sdhci_host *host)
> +{
> +	struct mmc *mmc = host->mmc;
> +	struct sdhci_cdns_plat *plat = dev_get_platdata(mmc->dev);
> +	unsigned int clock = mmc->clock;
> +	u32 mode, tmp;
> +
> +	/*
> +	 * REVISIT:
> +	 * The mode should be decided by MMC_TIMING_* like Linux, but
> +	 * U-Boot does not support timing.  Use the clock frequency instead.
> +	 */
> +	if (clock <= 26000000)
> +		mode = SDHCI_CDNS_HRS06_MODE_SD; /* use this for Legacy */
> +	else if (clock <= 52000000) {
> +		if (mmc->ddr_mode)
> +			mode = SDHCI_CDNS_HRS06_MODE_MMC_DDR;
> +		else
> +			mode = SDHCI_CDNS_HRS06_MODE_MMC_SDR;
> +	} else {
> +		/*
> +		 * REVISIT:
> +		 * The IP supports HS200/HS400, revisit once U-Boot support it
> +		 */
> +		printf("unsupported frequency %d\n", clock);
> +		return;
> +	}
> +
> +	tmp = readl(plat->hrs_addr + SDHCI_CDNS_HRS06);
> +	tmp &= ~SDHCI_CDNS_HRS06_MODE_MASK;
> +	tmp |= mode;
> +	writel(tmp, plat->hrs_addr + SDHCI_CDNS_HRS06);
> +}
> +
> +static const struct sdhci_ops sdhci_cdns_ops = {
> +	.set_control_reg = sdhci_cdns_set_control_reg,
> +};
> +
>  static int sdhci_cdns_bind(struct udevice *dev)
>  {
>  	struct sdhci_cdns_plat *plat = dev_get_platdata(dev);
> @@ -137,6 +187,7 @@ static int sdhci_cdns_probe(struct udevice *dev)
>  
>  	host->name = dev->name;
>  	host->ioaddr = plat->hrs_addr + SDHCI_CDNS_SRS_BASE;
> +	host->ops = &sdhci_cdns_ops;
>  	host->quirks |= SDHCI_QUIRK_WAIT_SEND_CMD;
>  
>  	ret = sdhci_cdns_phy_init(plat, gd->fdt_blob, dev_of_offset(dev));
> 



More information about the U-Boot mailing list