RE: [PATCH 02/12] mmc: sd: add support for signal voltage switch procedure

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

 




> -----Original Message-----
> From: linux-mmc-owner@xxxxxxxxxxxxxxx [mailto:linux-mmc-
> owner@xxxxxxxxxxxxxxx] On Behalf Of Arindam Nath
> Sent: Tuesday, February 15, 2011 3:05 PM
> To: cjb@xxxxxxxxxx
> Cc: linux-mmc@xxxxxxxxxxxxxxx; henry.su@xxxxxxx; aaron.lu@xxxxxxx;
> anath.amd@xxxxxxxxx; Arindam Nath
> Subject: [PATCH 02/12] mmc: sd: add support for signal voltage switch
> procedure
> 
> Host Controller v3.00 adds another Capabilities register. We can
> directly read this register without any version checking since the
> new register bits will be considred as reserved in older controllers,
> and will be read as 0. Apart from other things, this new register
> indicates whether the Host Controller supports SDR50, SDR104, and
> DDR50 UHS-I modes. So depending on the host support, we set
> the corresponding MMC_CAP_* flags. One more new register. Host Control2
> is added in v3.00, which is used during Signal Voltage Switch prcedure
> described below.
> 
> Since as per v3.00 spec, UHS-I supported hosts should set S18R to 1,
> we set S18R (bit 24) of OCR before sending ACMD41. We also need to set
> XPC (bit 28) of OCR in case the host can supply >150mA. This support is
> indicated by the Maximum Current Capabilities register of the Host
> Controller.
> 
> If the response of ACMD41 has both CCS and S18A set, we start the
> signal voltage switch procedure, which if successfull, will switch
> the card from 3.3V signalling to 1.8V signalling. Signal voltage
> switch procedure adds support for a new command CMD11 in the Physical
> Layer Spec v3.01. As part of this procedure, we need to set 1.8V
> Signalling
> Enable (bit 3) of Host Control2 register, which if remains set after
> 5ms,
> means the switch to 1.8V signalling is successfull. Otherwise, we clear
> bit 24 of OCR and retry the initialization sequence.
> 
> Signed-off-by: Arindam Nath <arindam.nath@xxxxxxx>
> ---
>  drivers/mmc/core/sd.c     |   37 ++++++++++-
>  drivers/mmc/core/sd_ops.c |   25 ++++++++
>  drivers/mmc/core/sd_ops.h |    1 +
>  drivers/mmc/host/sdhci.c  |  147
> +++++++++++++++++++++++++++++++++++++++++----
>  drivers/mmc/host/sdhci.h  |   18 +++++-
>  include/linux/mmc/host.h  |    8 +++
>  include/linux/mmc/sd.h    |    1 +
>  7 files changed, 219 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
> index b3f8a3c..e968d5c 100644
> --- a/drivers/mmc/core/sd.c
> +++ b/drivers/mmc/core/sd.c
> @@ -408,6 +408,7 @@ struct device_type sd_type = {
>  int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid)
>  {
>  	int err;
> +	u32 rocr;
> 
>  	/*
>  	 * Since we're changing the OCR value, we seem to
> @@ -427,10 +428,25 @@ int mmc_sd_get_cid(struct mmc_host *host, u32
> ocr, u32 *cid)
>  	if (!err)
>  		ocr |= 1 << 30;
> 
> -	err = mmc_send_app_op_cond(host, ocr, NULL);
> +	/* If the host can supply more than 150mA, XPC should be set to
> 1. */
> +	if (host->caps & (MMC_CAP_SET_XPC_330 | MMC_CAP_SET_XPC_300 |
> +	    MMC_CAP_SET_XPC_180))
> +		ocr |= 1 << 28;
> +

Why do you need MMC_CAP_SET_XPC_300 here? MMC_CAP_SET_XPC_330 &
MMC_CAP_SET_XPC_180 is not enough?

> +	err = mmc_send_app_op_cond(host, ocr, &rocr);
>  	if (err)
>  		return err;
> 
> +	/*
> +	 * In case CCS and S18A in the response is set, start Signal
> Voltage
> +	 * Switch procedure. SPI mode doesn't support CMD11.
> +	 */	
> +	if (!mmc_host_is_spi(host) && (rocr & 0x41000000)) {
> +		err = mmc_start_voltage_switch(host);
> +		if (err)
> +			return err;
> +	}
> +

Looks good.

>  	if (mmc_host_is_spi(host))
>  		err = mmc_send_cid(host, cid);
>  	else
> @@ -827,11 +843,26 @@ int mmc_attach_sd(struct mmc_host *host)
>  	}
> 
>  	/*
> +	 * If the host supports one of UHS-I modes, request the card
> +	 * to switch to 1.8V signaling level.
> +	 */
> +	if (host->caps & (MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 |
> +	    MMC_CAP_UHS_DDR50))
> +		host->ocr |= (1 << 24);

What about SDR12 and SDR25 modes? Are we ignoring them?

> +
> +	/*
>  	 * Detect and init the card.
>  	 */
>  	err = mmc_sd_init_card(host, host->ocr, NULL);
> -	if (err)
> -		goto err;
> +	if (err == -EAGAIN) {
> +		/*
> +		 * Retry initialization with S18R set to 0.
> +		 */
> +		host->ocr &= ~(1 << 24);
> +		err = mmc_sd_init_card(host, host->ocr, NULL);
> +		if (err)
> +			goto err;
> +	}
> 
>  	mmc_release_host(host);
>  	err = mmc_add_card(host->card);
> diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c
> index 797cdb5..a0f97c9 100644
> --- a/drivers/mmc/core/sd_ops.c
> +++ b/drivers/mmc/core/sd_ops.c
> @@ -146,6 +146,31 @@ int mmc_app_set_bus_width(struct mmc_card *card,
> int width)
>  	return 0;
>  }
> 
> +int mmc_start_voltage_switch(struct mmc_host *host)
> +{
> +	struct mmc_command cmd;
> +	int err;
> +
> +	BUG_ON(!host);
> +
> +	memset(&cmd, 0, sizeof(struct mmc_command));
> +
> +	cmd.opcode = SD_SWITCH_VOLTAGE;
> +	cmd.arg = 0;
> +	cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
> +
> +	err = mmc_wait_for_cmd(host, &cmd, 0);
> +	if (err)
> +		return err;
> +
> +	if (!mmc_host_is_spi(host) && (cmd.resp[0] & R1_ERROR))
> +		return -EIO;
> +
> +	err = host->ops->start_signal_voltage_switch(host);

No Null check for start_signal_voltage_switch ops?

> +
> +	return err;
> +}
> +
>  int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
>  {
>  	struct mmc_command cmd;
> diff --git a/drivers/mmc/core/sd_ops.h b/drivers/mmc/core/sd_ops.h
> index ffc2305..3cfba59 100644
> --- a/drivers/mmc/core/sd_ops.h
> +++ b/drivers/mmc/core/sd_ops.h
> @@ -20,6 +20,7 @@ int mmc_app_send_scr(struct mmc_card *card, u32
> *scr);
>  int mmc_sd_switch(struct mmc_card *card, int mode, int group,
>  	u8 value, u8 *resp);
>  int mmc_app_sd_status(struct mmc_card *card, void *ssr);
> +int mmc_start_voltage_switch(struct mmc_host *host);
> 
>  #endif
> 
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 0b537cf..6d7a276 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -87,6 +87,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 ": Host ctl2: 0x%08x\n",
> +		sdhci_readw(host, SDHCI_HOST_CONTROL2));
> 
>  	if (host->flags & SDHCI_USE_ADMA)
>  		printk(KERN_DEBUG DRIVER_NAME ": ADMA Err: 0x%08x | ADMA
> Ptr: 0x%08x\n",
> @@ -1340,11 +1342,76 @@ out:
>  	spin_unlock_irqrestore(&host->lock, flags);
>  }
> 
> +static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc)
> +{
> +	struct sdhci_host *host;
> +	u8 pwr;
> +	u16 clk, ctrl;
> +	u32 present_state;
> +	unsigned long flags;
> +
> +	host = mmc_priv(mmc);
> +
> +	spin_lock_irqsave(&host->lock, flags);
> +
> +	/* Stop SDCLK */
> +	host = mmc_priv(mmc);
> +	clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
> +	clk &= ~SDHCI_CLOCK_CARD_EN;
> +	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
> +
> +	/* Check whether DAT[3:0] is 0000 */
> +	present_state = sdhci_readl(host, SDHCI_PRESENT_STATE);
> +	if (!((present_state & SDHCI_DATA_LVL_MASK) >>
> SDHCI_DATA_LVL_SHIFT)) {
> +		/* Enable 1.8V Signal Enable in the Host Control2 register
> */
> +		ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
> +		ctrl |= SDHCI_CTRL_VDD_180;
> +		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
> +
> +		/* Wait for 5ms */
> +		mdelay(5);

msleep would be more appropriate here.

> +
> +		ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
> +		if (ctrl & SDHCI_CTRL_VDD_180) {
> +			/* Provide SDCLK again and wait for 1ms*/
> +			clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
> +			clk |= SDHCI_CLOCK_CARD_EN;
> +			sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
> +			mdelay(1);
> +
> +			/*
> +			 * If DAT[3:0] level is 1111b, then the card was
> +			 * successfully switched to 1.8V signaling.
> +			 */
> +			present_state = sdhci_readl(host,
> SDHCI_PRESENT_STATE);
> +			if ((present_state & SDHCI_DATA_LVL_MASK) ==
> +			     SDHCI_DATA_LVL_MASK) {
> +				spin_unlock_irqrestore(&host->lock, flags);
> +				return 0;
> +			}

Sequence looks fine according to spec.


> +		}
> +	}
> +
> +	/*
> +	 * If we are here, that means the switch to 1.8V signaling
> failed. Stop
> +	 * power to the card, and retry initialization sequence by
> setting S18R
> +	 * to 0.
> +	 */
> +	pwr = sdhci_readb(host, SDHCI_POWER_CONTROL);
> +	pwr &= ~SDHCI_POWER_ON;
> +	sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
> +
> +	spin_unlock_irqrestore(&host->lock, flags);
> +
> +	return -EAGAIN;
> +}
> +
>  static const struct mmc_host_ops sdhci_ops = {
>  	.request	= sdhci_request,
>  	.set_ios	= sdhci_set_ios,
>  	.get_ro		= sdhci_get_ro,
>  	.enable_sdio_irq = sdhci_enable_sdio_irq,
> +	.start_signal_voltage_switch	=
> sdhci_start_signal_voltage_switch,
>  };

If possible can you shorthand ops name "start_signal_voltage_switch"?


> 
> 
> /**********************************************************************
> *******\
> @@ -1802,7 +1869,9 @@ EXPORT_SYMBOL_GPL(sdhci_alloc_host);
>  int sdhci_add_host(struct sdhci_host *host)
>  {
>  	struct mmc_host *mmc;
> -	unsigned int caps, ocr_avail;
> +	u32 caps[2];
> +	u32 max_current_caps;
> +	unsigned int ocr_avail;
>  	int ret;
> 
>  	WARN_ON(host == NULL);
> @@ -1825,12 +1894,13 @@ int sdhci_add_host(struct sdhci_host *host)
>  			host->version);
>  	}
> 
> -	caps = (host->quirks & SDHCI_QUIRK_MISSING_CAPS) ? host->caps :
> +	caps[0] = (host->quirks & SDHCI_QUIRK_MISSING_CAPS) ? host->caps
> :
>  		sdhci_readl(host, SDHCI_CAPABILITIES);
> +	caps[1] = sdhci_readl(host, SDHCI_CAPABILITIES_1);
> 
>  	if (host->quirks & SDHCI_QUIRK_FORCE_DMA)
>  		host->flags |= SDHCI_USE_SDMA;
> -	else if (!(caps & SDHCI_CAN_DO_SDMA))
> +	else if (!(caps[0] & SDHCI_CAN_DO_SDMA))
>  		DBG("Controller doesn't have SDMA capability\n");
>  	else
>  		host->flags |= SDHCI_USE_SDMA;
> @@ -1841,7 +1911,8 @@ int sdhci_add_host(struct sdhci_host *host)
>  		host->flags &= ~SDHCI_USE_SDMA;
>  	}
> 
> -	if ((host->version >= SDHCI_SPEC_200) && (caps &
> SDHCI_CAN_DO_ADMA2)) {
> +	if ((host->version >= SDHCI_SPEC_200) &&
> +		(caps[0] & SDHCI_CAN_DO_ADMA2)) {
>  		host->flags &= ~SDHCI_USE_SDMA;
>  		host->flags |= SDHCI_USE_ADMA;
>  	}
> @@ -1893,10 +1964,10 @@ int sdhci_add_host(struct sdhci_host *host)
>  	}
> 
>  	if (host->version >= SDHCI_SPEC_300)
> -		host->max_clk = (caps & SDHCI_CLOCK_V3_BASE_MASK)
> +		host->max_clk = (caps[0] & SDHCI_CLOCK_V3_BASE_MASK)
>  			>> SDHCI_CLOCK_BASE_SHIFT;
>  	else
> -		host->max_clk = (caps & SDHCI_CLOCK_BASE_MASK)
> +		host->max_clk = (caps[0] & SDHCI_CLOCK_BASE_MASK)
>  			>> SDHCI_CLOCK_BASE_SHIFT;
> 
>  	host->max_clk *= 1000000;
> @@ -1912,7 +1983,7 @@ int sdhci_add_host(struct sdhci_host *host)
>  	}
> 
>  	host->timeout_clk =
> -		(caps & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT;
> +		(caps[0] & SDHCI_TIMEOUT_CLK_MASK) >>
> SDHCI_TIMEOUT_CLK_SHIFT;
>  	if (host->timeout_clk == 0) {
>  		if (host->ops->get_timeout_clock) {
>  			host->timeout_clk = host->ops-
> >get_timeout_clock(host);
> @@ -1924,7 +1995,7 @@ int sdhci_add_host(struct sdhci_host *host)
>  			return -ENODEV;
>  		}
>  	}
> -	if (caps & SDHCI_TIMEOUT_CLK_UNIT)
> +	if (caps[0] & SDHCI_TIMEOUT_CLK_UNIT)
>  		host->timeout_clk *= 1000;
> 
>  	/*
> @@ -1951,21 +2022,71 @@ int sdhci_add_host(struct sdhci_host *host)
>  	if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA))
>  		mmc->caps |= MMC_CAP_4_BIT_DATA;
> 
> -	if (caps & SDHCI_CAN_DO_HISPD)
> +	if (caps[0] & SDHCI_CAN_DO_HISPD)
>  		mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
> 
>  	if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) &&
>  	    mmc_card_is_removable(mmc))
>  		mmc->caps |= MMC_CAP_NEEDS_POLL;
> 
> +	/* UHS-I mode(s) supported by the host controller. */
> +	if (caps[1] & SDHCI_SUPPORT_SDR50)
> +		mmc->caps |= MMC_CAP_UHS_SDR50;
> +	if (caps[1] & SDHCI_SUPPORT_SDR104)
> +		mmc->caps |= MMC_CAP_UHS_SDR104;

If SDR104 is supported then that SDR50 is by default supported. You may want
to take care of that.

> +	if (caps[1] & SDHCI_SUPPORT_DDR50)
> +		mmc->caps |= MMC_CAP_UHS_DDR50;
> +
>  	ocr_avail = 0;
> -	if (caps & SDHCI_CAN_VDD_330)
> +	/*
> +	 * According to SD Host Controller spec v3.00, if the Host System
> +	 * can afford more than 150mA, Host Driver should set XPC to 1.
> Also
> +	 * the value is meaningful only if Voltage Support in the
> Capabilities
> +	 * register is set. The actual current value is 4 times the
> register
> +	 * value.
> +	 */
> +	max_current_caps = sdhci_readl(host, SDHCI_MAX_CURRENT);
> +
> +	if (caps[0] & SDHCI_CAN_VDD_330) {
> +		int max_current_330;
> +
>  		ocr_avail |= MMC_VDD_32_33 | MMC_VDD_33_34;
> -	if (caps & SDHCI_CAN_VDD_300)
> +
> +		max_current_330 = ((max_current_caps &
> +				   SDHCI_MAX_CURRENT_330_MASK) >>
> +				   SDHCI_MAX_CURRENT_330_SHIFT) *
> +				   SDHCI_MAX_CURRENT_MULTIPLIER;
> +
> +		if (max_current_330 > 150)
> +			mmc->caps |= MMC_CAP_SET_XPC_330;
> +	}
> +	if (caps[0] & SDHCI_CAN_VDD_300) {
> +		int max_current_300;
> +
>  		ocr_avail |= MMC_VDD_29_30 | MMC_VDD_30_31;
> -	if (caps & SDHCI_CAN_VDD_180)
> +
> +		max_current_300 = ((max_current_caps &
> +				   SDHCI_MAX_CURRENT_300_MASK) >>
> +				   SDHCI_MAX_CURRENT_300_SHIFT) *
> +				   SDHCI_MAX_CURRENT_MULTIPLIER;
> +
> +		if (max_current_300 > 150)
> +			mmc->caps |= MMC_CAP_SET_XPC_300;
> +	}
> +	if (caps[0] & SDHCI_CAN_VDD_180) {
> +		int max_current_180;
> +
>  		ocr_avail |= MMC_VDD_165_195;
> 
> +		max_current_180 = ((max_current_caps &
> +				   SDHCI_MAX_CURRENT_180_MASK) >>
> +				   SDHCI_MAX_CURRENT_180_SHIFT) *
> +				   SDHCI_MAX_CURRENT_MULTIPLIER;
> +
> +		if (max_current_180 > 150)
> +			mmc->caps |= MMC_CAP_SET_XPC_180;
> +	}
> +
>  	mmc->ocr_avail = ocr_avail;
>  	mmc->ocr_avail_sdio = ocr_avail;
>  	if (host->ocr_avail_sdio)
> @@ -2025,7 +2146,7 @@ int sdhci_add_host(struct sdhci_host *host)
>  	if (host->quirks & SDHCI_QUIRK_FORCE_BLK_SZ_2048) {
>  		mmc->max_blk_size = 2;
>  	} else {
> -		mmc->max_blk_size = (caps & SDHCI_MAX_BLOCK_MASK) >>
> +		mmc->max_blk_size = (caps[0] & SDHCI_MAX_BLOCK_MASK) >>
>  				SDHCI_MAX_BLOCK_SHIFT;
>  		if (mmc->max_blk_size >= 3) {
>  			printk(KERN_WARNING "%s: Invalid maximum block size,
> "
> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
> index 223762c..95d70e6 100644
> --- a/drivers/mmc/host/sdhci.h
> +++ b/drivers/mmc/host/sdhci.h
> @@ -69,6 +69,8 @@
>  #define  SDHCI_DATA_AVAILABLE	0x00000800
>  #define  SDHCI_CARD_PRESENT	0x00010000
>  #define  SDHCI_WRITE_PROTECT	0x00080000
> +#define  SDHCI_DATA_LVL_MASK	0x00F00000
> +#define   SDHCI_DATA_LVL_SHIFT	20
> 
>  #define SDHCI_HOST_CONTROL 	0x28
>  #define  SDHCI_CTRL_LED		0x01
> @@ -147,7 +149,8 @@
> 
>  #define SDHCI_ACMD12_ERR	0x3C
> 
> -/* 3E-3F reserved */
> +#define SDHCI_HOST_CONTROL2		0x3E
> +#define  SDHCI_CTRL_VDD_180		0x0008
> 
>  #define SDHCI_CAPABILITIES	0x40
>  #define  SDHCI_TIMEOUT_CLK_MASK	0x0000003F
> @@ -168,9 +171,20 @@
>  #define  SDHCI_CAN_VDD_180	0x04000000
>  #define  SDHCI_CAN_64BIT	0x10000000
> 
> +#define  SDHCI_SUPPORT_SDR50	0x00000001
> +#define  SDHCI_SUPPORT_SDR104	0x00000002
> +#define  SDHCI_SUPPORT_DDR50	0x00000004
> +
>  #define SDHCI_CAPABILITIES_1	0x44
> 
> -#define SDHCI_MAX_CURRENT	0x48
> +#define SDHCI_MAX_CURRENT		0x48
> +#define  SDHCI_MAX_CURRENT_330_MASK	0x0000FF
> +#define  SDHCI_MAX_CURRENT_330_SHIFT	0
> +#define  SDHCI_MAX_CURRENT_300_MASK	0x00FF00
> +#define  SDHCI_MAX_CURRENT_300_SHIFT	8
> +#define  SDHCI_MAX_CURRENT_180_MASK	0xFF0000
> +#define  SDHCI_MAX_CURRENT_180_SHIFT	16
> +#define   SDHCI_MAX_CURRENT_MULTIPLIER	4
> 
>  /* 4C-4F reserved for more max current */
> 
> diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
> index bcb793e..ec09b32 100644
> --- a/include/linux/mmc/host.h
> +++ b/include/linux/mmc/host.h
> @@ -117,6 +117,8 @@ struct mmc_host_ops {
> 
>  	/* optional callback for HC quirks */
>  	void	(*init_card)(struct mmc_host *host, struct mmc_card *card);
> +
> +	int	(*start_signal_voltage_switch)(struct mmc_host *host);
>  };
> 
>  struct mmc_card;
> @@ -173,6 +175,12 @@ struct mmc_host {
>  						/* DDR mode at 1.2V */
>  #define MMC_CAP_POWER_OFF_CARD	(1 << 13)	/* Can power off
after
> boot */
>  #define MMC_CAP_BUS_WIDTH_TEST	(1 << 14)	/* CMD14/CMD19 bus
> width ok */
> +#define MMC_CAP_UHS_SDR50	(1 << 15)	/* Host supports UHS SDR50
> mode */
> +#define MMC_CAP_UHS_SDR104	(1 << 16)	/* Host supports UHS SDR104
> mode */
> +#define MMC_CAP_UHS_DDR50	(1 << 17)	/* Host supports UHS DDR50
> mode */
> +#define MMC_CAP_SET_XPC_330	(1 << 18)	/* Host supports >150mA
> current at 3.3V */
> +#define MMC_CAP_SET_XPC_300	(1 << 19)	/* Host supports >150mA
> current at 3.0V */
> +#define MMC_CAP_SET_XPC_180	(1 << 20)	/* Host supports >150mA
> current at 1.8V */
> 
>  	mmc_pm_flag_t		pm_caps;	/* supported pm features */
> 
> diff --git a/include/linux/mmc/sd.h b/include/linux/mmc/sd.h
> index 178363b..3ba5aa6 100644
> --- a/include/linux/mmc/sd.h
> +++ b/include/linux/mmc/sd.h
> @@ -17,6 +17,7 @@
>  /* This is basically the same command as for MMC with some quirks. */
>  #define SD_SEND_RELATIVE_ADDR     3   /* bcr                     R6
> */
>  #define SD_SEND_IF_COND           8   /* bcr  [11:0] See below   R7
> */
> +#define SD_SWITCH_VOLTAGE         11  /* ac                      R1
> */
> 
>    /* class 10 */
>  #define SD_SWITCH                 6   /* adtc [31:0] See below   R1
> */
> --
> 1.7.1
> 
> --
> 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