public inbox for linux-mmc@vger.kernel.org
 help / color / mirror / Atom feed
From: Chris Ball <cjb@laptop.org>
To: Philip Rakity <prakity@marvell.com>
Cc: "linux-mmc@vger.kernel.org" <linux-mmc@vger.kernel.org>,
	Mark Brown <markb@marvell.com>
Subject: Re: [PATCH V2 2/2] sdhci: Support for SD/MMC Dual Data Rate
Date: Sun, 2 Jan 2011 18:55:57 +0000	[thread overview]
Message-ID: <20110102185557.GB24820@void.printf.net> (raw)
In-Reply-To: <35CD48DB-A420-4319-968D-400D45EE9C0D@marvell.com>

Hi Philip,

On Sun, Jan 02, 2011 at 08:45:10AM -0800, Philip Rakity wrote:
> 
> mmc->caps MMC_CAP_1_8V_DDR is set by looking at cabability_1
> register if sd 3.0 controller.
> 
> Support for dual data rate (DDR50) with 1_8V signalling added
> with optional call back to enable external control of signalling
> voltage.
> 
> no support for 1.2V core voltage since SD 3.0 does not support
> this.
> 
> **** QUESTION ****
> should this be part of regulator framework ?
> 
> delay for signaling voltage to settle set to 5ms (per spec).
> 
> this code does not change the voltage supplied to the card.
> It assumes that this is correctly handled in the core/ layer.
> 
> There is no requirement that the card voltage be at 1.8v
> for DDR to work.  This violates DDR specification for
> SD Host Controller 3.0 since explicitly states card voltage
> is 3.3v while signalling voltage is set to 1.8v.
> 
> tested on mmp2 -- brownstone -- under linux-next.
> 
> Note:  this board design runs a fixed voltage to the card and
> signaling voltage cannot be changed.
> 
> Signed-off-by: Philip Rakity <prakity@marvell.com>
> ---
>  drivers/mmc/host/sdhci.c |   53 ++++++++++++++++++++++++++++++++++++++++++---
>  drivers/mmc/host/sdhci.h |    5 ++++
>  2 files changed, 54 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index d5febe5..805f850 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -84,6 +84,8 @@ static void sdhci_dumpregs(struct sdhci_host *host)
>  	printk(KERN_DEBUG DRIVER_NAME ": Cmd:      0x%08x | Max curr: 0x%08x\n",
>  		sdhci_readw(host, SDHCI_COMMAND),
>  		sdhci_readl(host, SDHCI_MAX_CURRENT));
> +	printk(KERN_DEBUG DRIVER_NAME ": HostCtrl2:0x%08x\n",
> +		sdhci_readw(host, SDHCI_HOST_CONTROL_2));
>  
>  	if (host->flags & SDHCI_USE_ADMA)
>  		printk(KERN_DEBUG DRIVER_NAME ": ADMA Err: 0x%08x | ADMA Ptr: 0x%08x\n",
> @@ -986,6 +988,38 @@ static void sdhci_finish_command(struct sdhci_host *host)
>  	host->cmd = NULL;
>  }
>  
> +/*
> + * Handle 1.8V signaling for DDR. No need to check for other
> + * DDR values since driver supports ONLY 1_8V DDR.  This is
> + * set by the MMC_CAP_1_8V_DDR.  1_2V DDR is not supported.
> + */
> +static void sdhci_set_ddr(struct sdhci_host *host, unsigned int ddr)
> +{
> +	u16 con;
> +
> +	if (ddr == MMC_SDR_MODE)
> +		return;
> +
> +	con = sdhci_readw(host, SDHCI_HOST_CONTROL_2);
> +	con |= SDCTRL_2_SDH_V18_EN;
> +	sdhci_writew(host, con, SDHCI_HOST_CONTROL_2);
> +
> +	/* Change sigalling voltage and wait for it to be stable */

signaling

> +	if (host->ops->set_signaling_voltage)
> +		host->ops->set_signaling_voltage(host, 18);

What do you think about passing the ddr mode itself (MMC_1_8V_DDR_MODE)
and having set_signaling_voltage() work out what voltage it needs to use
to achieve that?  I don't like passing the raw number around so much.

> +	else
> +		mdelay(5);
> +
> +	/*
> +	 * We can fail here but there is no higher level recovery
> +	 * since the card is already past the switch to ddr
> +	 */
> +	con = sdhci_readw(host, SDHCI_HOST_CONTROL_2);
> +	con &= ~SDCTRL_2_UHS_MODE_MASK;
> +	con |= SDCTRL_2_UHS_MODE_SEL_DDR50;
> +	sdhci_writew(host, con, SDHCI_HOST_CONTROL_2);
> +}
> +
>  static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
>  {
>  	int div;
> @@ -1180,6 +1214,7 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>  	}
>  
>  	sdhci_set_clock(host, ios->clock);
> +	sdhci_set_ddr(host, ios->ddr);
>  
>  	if (ios->power_mode == MMC_POWER_OFF)
>  		sdhci_set_power(host, -1);
> @@ -1744,7 +1779,7 @@ EXPORT_SYMBOL_GPL(sdhci_alloc_host);
>  int sdhci_add_host(struct sdhci_host *host)
>  {
>  	struct mmc_host *mmc;
> -	unsigned int caps, ocr_avail;
> +	unsigned int caps, caps_h, ocr_avail;

Maybe choose a more understandable name for caps_h?

>  	int ret;
>  
>  	WARN_ON(host == NULL);
> @@ -1767,8 +1802,19 @@ int sdhci_add_host(struct sdhci_host *host)
>  			host->version);
>  	}
>  
> -	caps = (host->quirks & SDHCI_QUIRK_MISSING_CAPS) ? host->caps :
> -		sdhci_readl(host, SDHCI_CAPABILITIES);
> +	if (host->quirks & SDHCI_QUIRK_MISSING_CAPS) {
> +		caps = host->caps;
> +		caps_h = 0;
> +	} else {
> +		caps = sdhci_readl(host, SDHCI_CAPABILITIES);
> +		if (host->version >= SDHCI_SPEC_300) 
> +			caps_h = sdhci_readl(host, SDHCI_CAPABILITIES_1);
> +		else
> +			caps_h = 0;
> +	}
> +
> +	if (caps_h & SDHCI_CAN_DDR50)
> +		mmc->caps |= MMC_CAP_1_8V_DDR;
>  
>  	if (host->quirks & SDHCI_QUIRK_FORCE_DMA)
>  		host->flags |= SDHCI_USE_SDMA;
> @@ -1905,7 +1951,6 @@ int sdhci_add_host(struct sdhci_host *host)
>  		ocr_avail |= MMC_VDD_29_30 | MMC_VDD_30_31;
>  	if (caps & SDHCI_CAN_VDD_180)
>  		ocr_avail |= MMC_VDD_165_195;
> -
>  	mmc->ocr_avail = ocr_avail;
>  	mmc->ocr_avail_sdio = ocr_avail;
>  	if (host->ocr_avail_sdio)

This whitespace change shouldn't be here.

> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
> index 36f3861..d976e4f 100644
> --- a/drivers/mmc/host/sdhci.h
> +++ b/drivers/mmc/host/sdhci.h
> @@ -182,6 +182,9 @@
>  #define  SDHCI_CAN_64BIT	0x10000000
>  
>  #define SDHCI_CAPABILITIES_1	0x44
> +#define  SDHCI_CAN_SDR50	0x00000001
> +#define  SDHCI_CAN_SDR104	0x00000002
> +#define  SDHCI_CAN_DDR50	0x00000004
>  

You could use the BIT(0..2) macros here.

>  #define SDHCI_MAX_CURRENT	0x48
>  
> @@ -237,6 +240,8 @@ struct sdhci_ops {
>  	void (*platform_send_init_74_clocks)(struct sdhci_host *host,
>  					     u8 power_mode);
>  	unsigned int    (*get_ro)(struct sdhci_host *host);
> +	unsigned int    (*set_signaling_voltage)(struct sdhci_host *host,
> +				unsigned short voltage);
>  };
>  
>  #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
> -- 

Thanks,

-- 
Chris Ball   <cjb@laptop.org>   <http://printf.net/>
One Laptop Per Child

  reply	other threads:[~2011-01-02 18:55 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-01-02 16:45 [PATCH V2 2/2] sdhci: Support for SD/MMC Dual Data Rate Philip Rakity
2011-01-02 18:55 ` Chris Ball [this message]
2011-01-02 19:02   ` Philip Rakity
2011-01-02 19:32     ` Chris Ball
2011-01-02 19:53       ` [PATCH V3 " Philip Rakity
2011-01-04  3:39 ` [PATCH V2 " zhangfei gao
2011-01-04  4:25   ` Philip Rakity
2011-01-04  4:37     ` Philip Rakity
2011-01-04  4:52       ` Philip Rakity
2011-01-04  4:41     ` Philip Rakity
2011-01-09 23:28   ` Chris Ball
2011-01-10  3:05     ` zhangfei gao

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20110102185557.GB24820@void.printf.net \
    --to=cjb@laptop.org \
    --cc=linux-mmc@vger.kernel.org \
    --cc=markb@marvell.com \
    --cc=prakity@marvell.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox