Re: [PATCH v2 3/3] mmc: sdhci: update signal voltage switch code

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

 



On Dec 17, 2012, at 8:50 AM, Kevin Liu <kliu5@xxxxxxxxxxx> wrote:

> The protocal related code is moved to core stack. So update the host
> driver accordingly.
> 
> Signed-off-by: Kevin Liu <kliu5@xxxxxxxxxxx>
> Tested-by: Tim Wang <wangtt@xxxxxxxxxxx>
> ---
> drivers/mmc/host/sdhci.c |  194 +++++++++++++++++++---------------------------
> 1 files changed, 81 insertions(+), 113 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 6f0bfc0..beaa233 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -1608,145 +1608,99 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
> 	spin_unlock_irqrestore(&host->lock, flags);
> }
> 
> -static int sdhci_do_3_3v_signal_voltage_switch(struct sdhci_host *host,
> -						u16 ctrl)
> +static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
> +						int signal_voltage)
> {
> +	u16 ctrl;
> 	int ret;
> 
> -	/* Set 1.8V Signal Enable in the Host Control2 register to 0 */
> -	ctrl &= ~SDHCI_CTRL_VDD_180;
> -	sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
> -
> -	if (host->vqmmc) {
> -		ret = regulator_set_voltage(host->vqmmc, 2700000, 3600000);
> -		if (ret) {
> -			pr_warning("%s: Switching to 3.3V signalling voltage "
> -				   " failed\n", mmc_hostname(host->mmc));
> -			return -EIO;
> -		}
> -	}
> -	/* Wait for 5ms */
> -	usleep_range(5000, 5500);
> -
> -	/* 3.3V regulator output should be stable within 5 ms */
> -	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
> -	if (!(ctrl & SDHCI_CTRL_VDD_180))
> +	/*
> +	 * Signal Voltage Switching is only applicable for Host Controllers
> +	 * v3.00 and above.
> +	 */
> +	if (host->version < SDHCI_SPEC_300)
> 		return 0;
> 
> -	pr_warning("%s: 3.3V regulator output did not became stable\n",
> -		   mmc_hostname(host->mmc));
> -
> -	return -EIO;
> -}
> +	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
> 
> -static int sdhci_do_1_8v_signal_voltage_switch(struct sdhci_host *host,
> -						u16 ctrl)
> -{
> -	u8 pwr;
> -	u16 clk;
> -	u32 present_state;
> -	int ret;
> +	switch (signal_voltage) {
> 
> -	/* Stop SDCLK */
> -	clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
> -	clk &= ~SDHCI_CLOCK_CARD_EN;
> -	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
> +	case MMC_SIGNAL_VOLTAGE_330:
> +		/* Set 1.8V Signal Enable in the Host Control2 register to 0 */
> +		ctrl &= ~SDHCI_CTRL_VDD_180;
> +		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
> 
> -	/* 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
> -		 */
> -		if (host->vqmmc)
> -			ret = regulator_set_voltage(host->vqmmc,
> -				1700000, 1950000);
> -		else
> -			ret = 0;
> +		if (host->vqmmc) {
> +			ret = regulator_set_voltage(host->vqmmc, 2700000, 3600000);
> +			if (ret) {
> +				pr_warning("%s: Switching to 3.3V signalling voltage "
> +						" failed\n", mmc_hostname(host->mmc));
> +				return -EIO;
> +			}
> +		}
> +		/* Wait for 5ms */
> +		usleep_range(5000, 5500);
> 
> -		if (!ret) {
> -			ctrl |= SDHCI_CTRL_VDD_180;
> -			sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
> +		/* 3.3V regulator output should be stable within 5 ms */
> +		ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
> +		if (!(ctrl & SDHCI_CTRL_VDD_180))
> +			return 0;
> 
> -			/* Wait for 5ms */
> -			usleep_range(5000, 5500);
> +		pr_warning("%s: 3.3V regulator output did not became stable\n",
> +				mmc_hostname(host->mmc));
> 
> -			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);
> -				usleep_range(1000, 1500);
> +		return -EAGAIN;
> 
> -				/*
> -				 * 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)
> -					return 0;
> +	case MMC_SIGNAL_VOLTAGE_180:
> +		if (host->vqmmc) {
> +			ret = regulator_set_voltage(host->vqmmc,
> +					1700000, 1950000);
> +			if (ret) {
> +				pr_warning("%s: Switching to 1.8V signalling voltage "
> +						" failed\n", mmc_hostname(host->mmc));
> +				return -EIO;
> 			}
> 		}
> -	}
> 
> -	/*
> -	 * If we are here, that means the switch to 1.8V signaling
> -	 * failed. We power cycle 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);
> -	if (host->vmmc)
> -		regulator_disable(host->vmmc);
> +		/*
> +		 * Enable 1.8V Signal Enable in the Host Control2
> +		 * register
> +		 */
> +		ctrl |= SDHCI_CTRL_VDD_180;
> +		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
> 
> -	/* Wait for 1ms as per the spec */
> -	usleep_range(1000, 1500);
> -	pwr |= SDHCI_POWER_ON;
> -	sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
> -	if (host->vmmc)
> -		regulator_enable(host->vmmc);
> +		/* Wait for 5ms */
> +		usleep_range(5000, 5500);
> 
> -	pr_warning("%s: Switching to 1.8V signalling voltage failed, "
> -		   "retrying with S18R set to 0\n", mmc_hostname(host->mmc));
> +		/* 1.8V regulator output should be stable within 5 ms */
> +		ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
> +		if (ctrl & SDHCI_CTRL_VDD_180)
> +			return 0;
> 
> -	return -EAGAIN;
> -}
> +		pr_warning("%s: 1.8V regulator output did not became stable\n",
> +				mmc_hostname(host->mmc));
> 
> -static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
> -						struct mmc_ios *ios)
> -{
> -	u16 ctrl;
> +		return -EAGAIN;
> 
> -	/*
> -	 * Signal Voltage Switching is only applicable for Host Controllers
> -	 * v3.00 and above.
> -	 */
> -	if (host->version < SDHCI_SPEC_300)
> +	case MMC_SIGNAL_VOLTAGE_120:
> +		if (host->vqmmc) {
> +			ret = regulator_set_voltage(host->vqmmc, 2700000, 3600000);

?? 

> +			if (ret) {
> +				pr_warning("%s: Switching to 1.2V signalling voltage "
> +						" failed\n", mmc_hostname(host->mmc));
> +				return -EIO;
> +			}
> +		}

> +			ret = regulator_set_voltage(host->vqmmc, 2700000, 3600000);

Is this right for 1.2v vmmcq.  
> 		return 0;
> 
> -	/*
> -	 * We first check whether the request is to set signalling voltage
> -	 * to 3.3V. If so, we change the voltage to 3.3V and return quickly.
> -	 */
> -	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
> -	if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330)
> -		return sdhci_do_3_3v_signal_voltage_switch(host, ctrl);
> -	else if (!(ctrl & SDHCI_CTRL_VDD_180) &&
> -			(ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180))
> -		return sdhci_do_1_8v_signal_voltage_switch(host, ctrl);
> -	else
> +	default:
> 		/* No signal voltage switch required */
> 		return 0;
> +	}
> }
> 
> static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
> -	struct mmc_ios *ios)
> +	int signal_voltage)
> {
> 	struct sdhci_host *host = mmc_priv(mmc);
> 	int err;
> @@ -1754,11 +1708,24 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
> 	if (host->version < SDHCI_SPEC_300)
> 		return 0;
> 	sdhci_runtime_pm_get(host);
> -	err = sdhci_do_start_signal_voltage_switch(host, ios);
> +	err = sdhci_do_start_signal_voltage_switch(host, signal_voltage);
> 	sdhci_runtime_pm_put(host);
> 	return err;
> }
> 
> +static int sdhci_card_busy(struct mmc_host *mmc)
> +{
> +	struct sdhci_host *host = mmc_priv(mmc);
> +	u32 present_state;
> +
> +	sdhci_runtime_pm_get(host);
> +	/* Check whether DAT[3:0] is 0000 */
> +	present_state = sdhci_readl(host, SDHCI_PRESENT_STATE);
> +	sdhci_runtime_pm_put(host);
> +
> +	return !(present_state & SDHCI_DATA_LVL_MASK);
> +}
> +
> static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
> {
> 	struct sdhci_host *host;
> @@ -2029,6 +1996,7 @@ static const struct mmc_host_ops sdhci_ops = {
> 	.execute_tuning			= sdhci_execute_tuning,
> 	.enable_preset_value		= sdhci_enable_preset_value,
> 	.card_event			= sdhci_card_event,
> +	.card_busy	= sdhci_card_busy,
> };
> 
> /*****************************************************************************\
> -- 
> 1.7.0.4
> 

-----------------------------------------------------------------------------------
This email message is for the sole use of the intended recipient(s) and may contain
confidential information.  Any unauthorized review, use, disclosure or distribution
is prohibited.  If you are not the intended recipient, please contact the sender by
reply email and destroy all copies of the original message.
-----------------------------------------------------------------------------------
--
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