diff mbox

[V1,1/3] mmc: sdhci: Allow platform controlled voltage switching

Message ID 1532083566-43215-2-git-send-email-vviswana@codeaurora.org (mailing list archive)
State Not Applicable, archived
Delegated to: Andy Gross
Headers show

Commit Message

Vijay Viswanath July 20, 2018, 10:46 a.m. UTC
Some controllers can have internal mechanism to inform the SW that it
is ready for voltage switching. For such controllers, changing voltage
before the HW is ready can result in various issues.

During setup/cleanup of host, check whether regulator enable/disable
was already done by platform driver.

Signed-off-by: Vijay Viswanath <vviswana@codeaurora.org>
---
 drivers/mmc/host/sdhci.c | 21 ++++++++++++++++-----
 1 file changed, 16 insertions(+), 5 deletions(-)

Comments

Adrian Hunter July 25, 2018, 11:53 a.m. UTC | #1
On 20/07/18 13:46, Vijay Viswanath wrote:
> Some controllers can have internal mechanism to inform the SW that it
> is ready for voltage switching. For such controllers, changing voltage
> before the HW is ready can result in various issues.
> 
> During setup/cleanup of host, check whether regulator enable/disable
> was already done by platform driver.
> 
> Signed-off-by: Vijay Viswanath <vviswana@codeaurora.org>
> ---
>  drivers/mmc/host/sdhci.c | 21 ++++++++++++++++-----
>  1 file changed, 16 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 1c828e0..494a1e2 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -3472,6 +3472,7 @@ int sdhci_setup_host(struct sdhci_host *host)
>  	unsigned int override_timeout_clk;
>  	u32 max_clk;
>  	int ret;
> +	bool enable_vqmmc = false;
>  
>  	WARN_ON(host == NULL);
>  	if (host == NULL)
> @@ -3485,7 +3486,12 @@ int sdhci_setup_host(struct sdhci_host *host)
>  	 * the host can take the appropriate action if regulators are not
>  	 * available.
>  	 */
> -	ret = mmc_regulator_get_supply(mmc);
> +	if (!mmc->supply.vmmc) {
> +		ret = mmc_regulator_get_supply(mmc);
> +		enable_vqmmc  = true;
> +	} else {
> +		ret = 0;
> +	}
>  	if (ret)
>  		return ret;

Why not

	if (!mmc->supply.vmmc) {
		ret = mmc_regulator_get_supply(mmc);
	  	if (ret)
  			return ret;
		enable_vqmmc  = true;
	}

>  
> @@ -3736,7 +3742,10 @@ int sdhci_setup_host(struct sdhci_host *host)
>  
>  	/* If vqmmc regulator and no 1.8V signalling, then there's no UHS */
>  	if (!IS_ERR(mmc->supply.vqmmc)) {
> -		ret = regulator_enable(mmc->supply.vqmmc);
> +		if (enable_vqmmc)
> +			ret = regulator_enable(mmc->supply.vqmmc);

Please introduce host->vqmmc_enabled = !ret;

> +		else
> +			ret = 0;
>  		if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 1700000,
>  						    1950000))
>  			host->caps1 &= ~(SDHCI_SUPPORT_SDR104 |
> @@ -3984,7 +3993,7 @@ int sdhci_setup_host(struct sdhci_host *host)
>  	return 0;
>  
>  unreg:
> -	if (!IS_ERR(mmc->supply.vqmmc))
> +	if (!IS_ERR(mmc->supply.vqmmc) && enable_vqmmc)

And just make this

	if (host->vqmmc_enabled)

>  		regulator_disable(mmc->supply.vqmmc);
>  undma:
>  	if (host->align_buffer)
> @@ -4002,7 +4011,8 @@ void sdhci_cleanup_host(struct sdhci_host *host)
>  {
>  	struct mmc_host *mmc = host->mmc;
>  
> -	if (!IS_ERR(mmc->supply.vqmmc))
> +	if (!IS_ERR(mmc->supply.vqmmc) &&
> +			(regulator_is_enabled(mmc->supply.vqmmc) > 0))

	if (host->vqmmc_enabled)

>  		regulator_disable(mmc->supply.vqmmc);
>  
>  	if (host->align_buffer)
> @@ -4135,7 +4145,8 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
>  
>  	tasklet_kill(&host->finish_tasklet);
>  
> -	if (!IS_ERR(mmc->supply.vqmmc))
> +	if (!IS_ERR(mmc->supply.vqmmc) &&
> +			(regulator_is_enabled(mmc->supply.vqmmc) > 0))

	if (host->vqmmc_enabled)

>  		regulator_disable(mmc->supply.vqmmc);
>  
>  	if (host->align_buffer)
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Vijay Viswanath July 25, 2018, 12:23 p.m. UTC | #2
Hi Adrian,


On 7/25/2018 5:23 PM, Adrian Hunter wrote:
> On 20/07/18 13:46, Vijay Viswanath wrote:
>> Some controllers can have internal mechanism to inform the SW that it
>> is ready for voltage switching. For such controllers, changing voltage
>> before the HW is ready can result in various issues.
>>
>> During setup/cleanup of host, check whether regulator enable/disable
>> was already done by platform driver.
>>
>> Signed-off-by: Vijay Viswanath <vviswana@codeaurora.org>
>> ---
>>   drivers/mmc/host/sdhci.c | 21 ++++++++++++++++-----
>>   1 file changed, 16 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>> index 1c828e0..494a1e2 100644
>> --- a/drivers/mmc/host/sdhci.c
>> +++ b/drivers/mmc/host/sdhci.c
>> @@ -3472,6 +3472,7 @@ int sdhci_setup_host(struct sdhci_host *host)
>>   	unsigned int override_timeout_clk;
>>   	u32 max_clk;
>>   	int ret;
>> +	bool enable_vqmmc = false;
>>   
>>   	WARN_ON(host == NULL);
>>   	if (host == NULL)
>> @@ -3485,7 +3486,12 @@ int sdhci_setup_host(struct sdhci_host *host)
>>   	 * the host can take the appropriate action if regulators are not
>>   	 * available.
>>   	 */
>> -	ret = mmc_regulator_get_supply(mmc);
>> +	if (!mmc->supply.vmmc) {
>> +		ret = mmc_regulator_get_supply(mmc);
>> +		enable_vqmmc  = true;
>> +	} else {
>> +		ret = 0;
>> +	}
>>   	if (ret)
>>   		return ret;
> 
> Why not
> 
> 	if (!mmc->supply.vmmc) {
> 		ret = mmc_regulator_get_supply(mmc);
> 	  	if (ret)
>    			return ret;
> 		enable_vqmmc  = true;
> 	}
> 

looks neater. Will do.

>>   
>> @@ -3736,7 +3742,10 @@ int sdhci_setup_host(struct sdhci_host *host)
>>   
>>   	/* If vqmmc regulator and no 1.8V signalling, then there's no UHS */
>>   	if (!IS_ERR(mmc->supply.vqmmc)) {
>> -		ret = regulator_enable(mmc->supply.vqmmc);
>> +		if (enable_vqmmc)
>> +			ret = regulator_enable(mmc->supply.vqmmc);
> 
> Please introduce host->vqmmc_enabled = !ret;
> 

Any reason to introduce vqmmc_enabled variable in sdhci_host structure ? 
We can get around with a local variable and using regulator_is_enabled API.

>> +		else
>> +			ret = 0;
>>   		if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 1700000,
>>   						    1950000))
>>   			host->caps1 &= ~(SDHCI_SUPPORT_SDR104 |
>> @@ -3984,7 +3993,7 @@ int sdhci_setup_host(struct sdhci_host *host)
>>   	return 0;
>>   
>>   unreg:
>> -	if (!IS_ERR(mmc->supply.vqmmc))
>> +	if (!IS_ERR(mmc->supply.vqmmc) && enable_vqmmc)
> 
> And just make this
> 
> 	if (host->vqmmc_enabled)
> 
>>   		regulator_disable(mmc->supply.vqmmc);
>>   undma:
>>   	if (host->align_buffer)
>> @@ -4002,7 +4011,8 @@ void sdhci_cleanup_host(struct sdhci_host *host)
>>   {
>>   	struct mmc_host *mmc = host->mmc;
>>   
>> -	if (!IS_ERR(mmc->supply.vqmmc))
>> +	if (!IS_ERR(mmc->supply.vqmmc) &&
>> +			(regulator_is_enabled(mmc->supply.vqmmc) > 0))
> 
> 	if (host->vqmmc_enabled)
> 
>>   		regulator_disable(mmc->supply.vqmmc);
>>   
>>   	if (host->align_buffer)
>> @@ -4135,7 +4145,8 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
>>   
>>   	tasklet_kill(&host->finish_tasklet);
>>   
>> -	if (!IS_ERR(mmc->supply.vqmmc))
>> +	if (!IS_ERR(mmc->supply.vqmmc) &&
>> +			(regulator_is_enabled(mmc->supply.vqmmc) > 0))
> 
> 	if (host->vqmmc_enabled)
> 
>>   		regulator_disable(mmc->supply.vqmmc);
>>   
>>   	if (host->align_buffer)
>>
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

Thanks,
Vijay
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Adrian Hunter July 25, 2018, 12:37 p.m. UTC | #3
On 25/07/18 15:23, Vijay Viswanath wrote:
> Hi Adrian,
> 
> 
> On 7/25/2018 5:23 PM, Adrian Hunter wrote:
>> On 20/07/18 13:46, Vijay Viswanath wrote:
>>> Some controllers can have internal mechanism to inform the SW that it
>>> is ready for voltage switching. For such controllers, changing voltage
>>> before the HW is ready can result in various issues.
>>>
>>> During setup/cleanup of host, check whether regulator enable/disable
>>> was already done by platform driver.
>>>
>>> Signed-off-by: Vijay Viswanath <vviswana@codeaurora.org>
>>> ---
>>>   drivers/mmc/host/sdhci.c | 21 ++++++++++++++++-----
>>>   1 file changed, 16 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>>> index 1c828e0..494a1e2 100644
>>> --- a/drivers/mmc/host/sdhci.c
>>> +++ b/drivers/mmc/host/sdhci.c
>>> @@ -3472,6 +3472,7 @@ int sdhci_setup_host(struct sdhci_host *host)
>>>       unsigned int override_timeout_clk;
>>>       u32 max_clk;
>>>       int ret;
>>> +    bool enable_vqmmc = false;
>>>         WARN_ON(host == NULL);
>>>       if (host == NULL)
>>> @@ -3485,7 +3486,12 @@ int sdhci_setup_host(struct sdhci_host *host)
>>>        * the host can take the appropriate action if regulators are not
>>>        * available.
>>>        */
>>> -    ret = mmc_regulator_get_supply(mmc);
>>> +    if (!mmc->supply.vmmc) {
>>> +        ret = mmc_regulator_get_supply(mmc);
>>> +        enable_vqmmc  = true;
>>> +    } else {
>>> +        ret = 0;
>>> +    }
>>>       if (ret)
>>>           return ret;
>>
>> Why not
>>
>>     if (!mmc->supply.vmmc) {
>>         ret = mmc_regulator_get_supply(mmc);
>>           if (ret)
>>                return ret;
>>         enable_vqmmc  = true;
>>     }
>>
> 
> looks neater. Will do.
> 
>>>   @@ -3736,7 +3742,10 @@ int sdhci_setup_host(struct sdhci_host *host)
>>>         /* If vqmmc regulator and no 1.8V signalling, then there's no UHS */
>>>       if (!IS_ERR(mmc->supply.vqmmc)) {
>>> -        ret = regulator_enable(mmc->supply.vqmmc);
>>> +        if (enable_vqmmc)
>>> +            ret = regulator_enable(mmc->supply.vqmmc);
>>
>> Please introduce host->vqmmc_enabled = !ret;
>>
> 
> Any reason to introduce vqmmc_enabled variable in sdhci_host structure ? We
> can get around with a local variable and using regulator_is_enabled API.

regulator_enable() uses reference counting, so we have to use
regulator_disable() exactly the same number of times that we use
regulator_enable().

> 
>>> +        else
>>> +            ret = 0;
>>>           if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 1700000,
>>>                               1950000))
>>>               host->caps1 &= ~(SDHCI_SUPPORT_SDR104 |
>>> @@ -3984,7 +3993,7 @@ int sdhci_setup_host(struct sdhci_host *host)
>>>       return 0;
>>>     unreg:
>>> -    if (!IS_ERR(mmc->supply.vqmmc))
>>> +    if (!IS_ERR(mmc->supply.vqmmc) && enable_vqmmc)
>>
>> And just make this
>>
>>     if (host->vqmmc_enabled)
>>
>>>           regulator_disable(mmc->supply.vqmmc);
>>>   undma:
>>>       if (host->align_buffer)
>>> @@ -4002,7 +4011,8 @@ void sdhci_cleanup_host(struct sdhci_host *host)
>>>   {
>>>       struct mmc_host *mmc = host->mmc;
>>>   -    if (!IS_ERR(mmc->supply.vqmmc))
>>> +    if (!IS_ERR(mmc->supply.vqmmc) &&
>>> +            (regulator_is_enabled(mmc->supply.vqmmc) > 0))
>>
>>     if (host->vqmmc_enabled)
>>
>>>           regulator_disable(mmc->supply.vqmmc);
>>>         if (host->align_buffer)
>>> @@ -4135,7 +4145,8 @@ void sdhci_remove_host(struct sdhci_host *host, int
>>> dead)
>>>         tasklet_kill(&host->finish_tasklet);
>>>   -    if (!IS_ERR(mmc->supply.vqmmc))
>>> +    if (!IS_ERR(mmc->supply.vqmmc) &&
>>> +            (regulator_is_enabled(mmc->supply.vqmmc) > 0))
>>
>>     if (host->vqmmc_enabled)
>>
>>>           regulator_disable(mmc->supply.vqmmc);
>>>         if (host->align_buffer)
>>>
>>
>> -- 
>> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
> 
> Thanks,
> Vijay
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 1c828e0..494a1e2 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -3472,6 +3472,7 @@  int sdhci_setup_host(struct sdhci_host *host)
 	unsigned int override_timeout_clk;
 	u32 max_clk;
 	int ret;
+	bool enable_vqmmc = false;
 
 	WARN_ON(host == NULL);
 	if (host == NULL)
@@ -3485,7 +3486,12 @@  int sdhci_setup_host(struct sdhci_host *host)
 	 * the host can take the appropriate action if regulators are not
 	 * available.
 	 */
-	ret = mmc_regulator_get_supply(mmc);
+	if (!mmc->supply.vmmc) {
+		ret = mmc_regulator_get_supply(mmc);
+		enable_vqmmc  = true;
+	} else {
+		ret = 0;
+	}
 	if (ret)
 		return ret;
 
@@ -3736,7 +3742,10 @@  int sdhci_setup_host(struct sdhci_host *host)
 
 	/* If vqmmc regulator and no 1.8V signalling, then there's no UHS */
 	if (!IS_ERR(mmc->supply.vqmmc)) {
-		ret = regulator_enable(mmc->supply.vqmmc);
+		if (enable_vqmmc)
+			ret = regulator_enable(mmc->supply.vqmmc);
+		else
+			ret = 0;
 		if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 1700000,
 						    1950000))
 			host->caps1 &= ~(SDHCI_SUPPORT_SDR104 |
@@ -3984,7 +3993,7 @@  int sdhci_setup_host(struct sdhci_host *host)
 	return 0;
 
 unreg:
-	if (!IS_ERR(mmc->supply.vqmmc))
+	if (!IS_ERR(mmc->supply.vqmmc) && enable_vqmmc)
 		regulator_disable(mmc->supply.vqmmc);
 undma:
 	if (host->align_buffer)
@@ -4002,7 +4011,8 @@  void sdhci_cleanup_host(struct sdhci_host *host)
 {
 	struct mmc_host *mmc = host->mmc;
 
-	if (!IS_ERR(mmc->supply.vqmmc))
+	if (!IS_ERR(mmc->supply.vqmmc) &&
+			(regulator_is_enabled(mmc->supply.vqmmc) > 0))
 		regulator_disable(mmc->supply.vqmmc);
 
 	if (host->align_buffer)
@@ -4135,7 +4145,8 @@  void sdhci_remove_host(struct sdhci_host *host, int dead)
 
 	tasklet_kill(&host->finish_tasklet);
 
-	if (!IS_ERR(mmc->supply.vqmmc))
+	if (!IS_ERR(mmc->supply.vqmmc) &&
+			(regulator_is_enabled(mmc->supply.vqmmc) > 0))
 		regulator_disable(mmc->supply.vqmmc);
 
 	if (host->align_buffer)