linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH RFC 0/2] Internal voltage control for platform drivers
@ 2018-06-21 12:23 Vijay Viswanath
  2018-06-21 12:23 ` [PATCH RFC 1/2] mmc: sdhci: Allow platform controlled voltage switching Vijay Viswanath
  2018-06-21 12:23 ` [PATCH RFC 2/2] mmc: sdhci-msm: Use internal voltage control Vijay Viswanath
  0 siblings, 2 replies; 12+ messages in thread
From: Vijay Viswanath @ 2018-06-21 12:23 UTC (permalink / raw)
  To: adrian.hunter, ulf.hansson, robh+dt, mark.rutland
  Cc: linux-mmc, linux-kernel, shawn.lin, linux-arm-msm, georgi.djakov,
	devicetree, asutoshd, stummala, venkatg, jeremymc, vviswana,
	bjorn.andersson, riteshh, vbadigan, dianders, sayalil

Certain SDHC controllers may require that voltage switching happen after
sepcial conditions. Added a QUIRK for such controllers to use.

For SDHCI-MSM controllers, power irq is a signal from controller to SW
that it is ready for voltage switch. So added support to register
voltage regulators from the msm driver and use them.
Voltage switching from core layer is causing CRC/cmd timeout errors in
some chipsets.

Tested on: sdm845, db410c
Requies patch series:"[PATCH V3 0/4] Changes for SDCC5 version"

Vijay Viswanath (2):
  mmc: sdhci: Allow platform controlled voltage switching
  mmc: sdhci-msm: Use internal voltage control

 drivers/mmc/host/sdhci-msm.c | 99 ++++++++++++++++++++++++++++++++++++++------
 drivers/mmc/host/sdhci.c     | 20 ++++++---
 drivers/mmc/host/sdhci.h     |  2 +
 3 files changed, 104 insertions(+), 17 deletions(-)

-- 
 Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH RFC 1/2] mmc: sdhci: Allow platform controlled voltage switching
  2018-06-21 12:23 [PATCH RFC 0/2] Internal voltage control for platform drivers Vijay Viswanath
@ 2018-06-21 12:23 ` Vijay Viswanath
  2018-07-10 11:07   ` Adrian Hunter
  2018-06-21 12:23 ` [PATCH RFC 2/2] mmc: sdhci-msm: Use internal voltage control Vijay Viswanath
  1 sibling, 1 reply; 12+ messages in thread
From: Vijay Viswanath @ 2018-06-21 12:23 UTC (permalink / raw)
  To: adrian.hunter, ulf.hansson, robh+dt, mark.rutland
  Cc: linux-mmc, linux-kernel, shawn.lin, linux-arm-msm, georgi.djakov,
	devicetree, asutoshd, stummala, venkatg, jeremymc, vviswana,
	bjorn.andersson, riteshh, vbadigan, dianders, sayalil

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.

Add a quirk, which can be used by drivers of such controllers.

Signed-off-by: Vijay Viswanath <vviswana@codeaurora.org>
---
 drivers/mmc/host/sdhci.c | 20 +++++++++++++++-----
 drivers/mmc/host/sdhci.h |  2 ++
 2 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 1c828e0..f0346d4 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1615,7 +1615,8 @@ void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode,
 void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
 		     unsigned short vdd)
 {
-	if (IS_ERR(host->mmc->supply.vmmc))
+	if (IS_ERR(host->mmc->supply.vmmc) ||
+			(host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL))
 		sdhci_set_power_noreg(host, mode, vdd);
 	else
 		sdhci_set_power_reg(host, mode, vdd);
@@ -2009,7 +2010,9 @@ int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
 		ctrl &= ~SDHCI_CTRL_VDD_180;
 		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
 
-		if (!IS_ERR(mmc->supply.vqmmc)) {
+		if (!IS_ERR(mmc->supply.vqmmc) &&
+				!(host->quirks2 &
+					SDHCI_QUIRK2_INTERNAL_PWR_CTL)) {
 			ret = mmc_regulator_set_vqmmc(mmc, ios);
 			if (ret) {
 				pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
@@ -2032,7 +2035,8 @@ int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
 	case MMC_SIGNAL_VOLTAGE_180:
 		if (!(host->flags & SDHCI_SIGNALING_180))
 			return -EINVAL;
-		if (!IS_ERR(mmc->supply.vqmmc)) {
+		if (!IS_ERR(mmc->supply.vqmmc) &&
+			!(host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL)) {
 			ret = mmc_regulator_set_vqmmc(mmc, ios);
 			if (ret) {
 				pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
@@ -3485,7 +3489,10 @@ 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 (!(host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL))
+		ret = mmc_regulator_get_supply(mmc);
+	else
+		ret = 0;
 	if (ret)
 		return ret;
 
@@ -3736,7 +3743,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 (!(host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL))
+			ret = regulator_enable(mmc->supply.vqmmc);
+		else
+			ret = 0;
 		if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 1700000,
 						    1950000))
 			host->caps1 &= ~(SDHCI_SUPPORT_SDR104 |
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 23966f8..3b0c97a 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -450,6 +450,8 @@ struct sdhci_host {
  * obtainable timeout.
  */
 #define SDHCI_QUIRK2_DISABLE_HW_TIMEOUT			(1<<17)
+/* Regulator voltage changes are being done from platform layer */
+#define SDHCI_QUIRK2_INTERNAL_PWR_CTL				(1<<18)
 
 	int irq;		/* Device IRQ */
 	void __iomem *ioaddr;	/* Mapped address */
-- 
 Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH RFC 2/2] mmc: sdhci-msm: Use internal voltage control
  2018-06-21 12:23 [PATCH RFC 0/2] Internal voltage control for platform drivers Vijay Viswanath
  2018-06-21 12:23 ` [PATCH RFC 1/2] mmc: sdhci: Allow platform controlled voltage switching Vijay Viswanath
@ 2018-06-21 12:23 ` Vijay Viswanath
  2018-07-10 11:26   ` Adrian Hunter
  1 sibling, 1 reply; 12+ messages in thread
From: Vijay Viswanath @ 2018-06-21 12:23 UTC (permalink / raw)
  To: adrian.hunter, ulf.hansson, robh+dt, mark.rutland
  Cc: linux-mmc, linux-kernel, shawn.lin, linux-arm-msm, georgi.djakov,
	devicetree, asutoshd, stummala, venkatg, jeremymc, vviswana,
	bjorn.andersson, riteshh, vbadigan, dianders, sayalil

Some sdhci-msm controllers require that voltage switching be done after
the HW is ready for it. The HW informs its readiness through power irq.
The voltage switching should happen only then.

Use the quirk for internal voltage switching and then control the
voltage switching using power irq.

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

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index a0dc3e1..ebdde29 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -43,7 +43,9 @@
 #define CORE_PWRCTL_IO_LOW	BIT(2)
 #define CORE_PWRCTL_IO_HIGH	BIT(3)
 #define CORE_PWRCTL_BUS_SUCCESS BIT(0)
+#define CORE_PWRCTL_BUS_FAIL    BIT(1)
 #define CORE_PWRCTL_IO_SUCCESS	BIT(2)
+#define CORE_PWRCTL_IO_FAIL     BIT(3)
 #define REQ_BUS_OFF		BIT(0)
 #define REQ_BUS_ON		BIT(1)
 #define REQ_IO_LOW		BIT(2)
@@ -258,6 +260,7 @@ struct sdhci_msm_host {
 	bool mci_removed;
 	const struct sdhci_msm_variant_ops *var_ops;
 	const struct sdhci_msm_offset *offset;
+	bool pltfm_init_done;
 };
 
 static const struct sdhci_msm_offset *sdhci_priv_msm_offset(struct sdhci_host *host)
@@ -1314,8 +1317,9 @@ static void sdhci_msm_handle_pwr_irq(struct sdhci_host *host, int irq)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+	struct mmc_host *mmc = host->mmc;
 	u32 irq_status, irq_ack = 0;
-	int retry = 10;
+	int retry = 10, ret = 0;
 	u32 pwr_state = 0, io_level = 0;
 	u32 config;
 	const struct sdhci_msm_offset *msm_offset = msm_host->offset;
@@ -1351,14 +1355,59 @@ static void sdhci_msm_handle_pwr_irq(struct sdhci_host *host, int irq)
 
 	/* Handle BUS ON/OFF*/
 	if (irq_status & CORE_PWRCTL_BUS_ON) {
-		pwr_state = REQ_BUS_ON;
-		io_level = REQ_IO_HIGH;
-		irq_ack |= CORE_PWRCTL_BUS_SUCCESS;
+		if (mmc->supply.vmmc) {
+			ret = regulator_set_load(mmc->supply.vmmc, 800000);
+			ret |= mmc_regulator_set_ocr(mmc, mmc->supply.vmmc,
+					mmc->ios.vdd);
+			if (ret)
+				pr_err("%s: vmmc enable failed: %d\n",
+						mmc_hostname(mmc), ret);
+		}
+		if (mmc->supply.vqmmc && !ret) {
+			ret = regulator_set_load(mmc->supply.vqmmc, 22000);
+			ret |= mmc_regulator_set_ocr(mmc, mmc->supply.vqmmc,
+					mmc->ios.vdd);
+			if (!ret)
+				ret = regulator_enable(mmc->supply.vqmmc);
+			if (ret)
+				pr_err("%s: vqmmc enable failed: %d\n",
+						mmc_hostname(mmc), ret);
+		}
+		if (!ret) {
+			pwr_state = REQ_BUS_ON;
+			io_level = REQ_IO_HIGH;
+			irq_ack |= CORE_PWRCTL_BUS_SUCCESS;
+		} else {
+			pr_err("%s: BUS_ON req failed(%d). irq_status: 0x%08x\n",
+					mmc_hostname(mmc), ret, irq_status);
+			irq_ack |= CORE_PWRCTL_BUS_FAIL;
+		}
 	}
 	if (irq_status & CORE_PWRCTL_BUS_OFF) {
-		pwr_state = REQ_BUS_OFF;
-		io_level = REQ_IO_LOW;
-		irq_ack |= CORE_PWRCTL_BUS_SUCCESS;
+		if (mmc->supply.vmmc && msm_host->pltfm_init_done) {
+			ret = regulator_set_load(mmc->supply.vmmc, 0);
+			ret |= mmc_regulator_set_ocr(mmc, mmc->supply.vmmc,
+					mmc->ios.vdd);
+			if (ret)
+				pr_err("%s: vqmmc disabling failed: %d\n",
+						mmc_hostname(mmc), ret);
+		}
+		if (mmc->supply.vqmmc && msm_host->pltfm_init_done && !ret) {
+			ret = regulator_set_load(mmc->supply.vqmmc, 0);
+			ret |= regulator_disable(mmc->supply.vqmmc);
+			if (ret)
+				pr_err("%s: vqmmc disabling failed: %d\n",
+						mmc_hostname(mmc), ret);
+		}
+		if (!ret) {
+			pwr_state = REQ_BUS_OFF;
+			io_level = REQ_IO_LOW;
+			irq_ack |= CORE_PWRCTL_BUS_SUCCESS;
+		} else {
+			pr_err("%s: BUS_ON req failed(%d). irq_status: 0x%08x\n",
+					mmc_hostname(mmc), ret, irq_status);
+			irq_ack |= CORE_PWRCTL_BUS_FAIL;
+		}
 	}
 	/* Handle IO LOW/HIGH */
 	if (irq_status & CORE_PWRCTL_IO_LOW) {
@@ -1370,6 +1419,15 @@ static void sdhci_msm_handle_pwr_irq(struct sdhci_host *host, int irq)
 		irq_ack |= CORE_PWRCTL_IO_SUCCESS;
 	}
 
+	if (io_level && mmc->supply.vqmmc && !pwr_state) {
+		ret = mmc_regulator_set_vqmmc(mmc, &mmc->ios);
+		if (ret)
+			pr_err("%s: IO_level setting failed(%d). signal_voltage: %d, vdd: %d irq_status: 0x%08x\n",
+					mmc_hostname(mmc), ret,
+					mmc->ios.signal_voltage, mmc->ios.vdd,
+					irq_status);
+	}
+
 	/*
 	 * The driver has to acknowledge the interrupt, switch voltages and
 	 * report back if it succeded or not to this register. The voltage
@@ -1415,10 +1473,9 @@ static void sdhci_msm_handle_pwr_irq(struct sdhci_host *host, int irq)
 		msm_host->curr_pwr_state = pwr_state;
 	if (io_level)
 		msm_host->curr_io_level = io_level;
-
 	pr_debug("%s: %s: Handled IRQ(%d), irq_status=0x%x, ack=0x%x\n",
-		mmc_hostname(msm_host->mmc), __func__, irq, irq_status,
-		irq_ack);
+			mmc_hostname(msm_host->mmc), __func__,
+			irq, irq_status, irq_ack);
 }
 
 static irqreturn_t sdhci_msm_pwr_irq(int irq, void *data)
@@ -1605,6 +1662,19 @@ static void sdhci_msm_set_regulator_caps(struct sdhci_msm_host *msm_host)
 	pr_debug("%s: supported caps: 0x%08x\n", mmc_hostname(mmc), caps);
 }
 
+static int sdhci_msm_register_vreg(struct sdhci_msm_host *msm_host)
+{
+	int ret = 0;
+
+	ret = mmc_regulator_get_supply(msm_host->mmc);
+	if (ret)
+		return ret;
+	sdhci_msm_set_regulator_caps(msm_host);
+
+	return 0;
+
+}
+
 static const struct sdhci_msm_variant_ops mci_var_ops = {
 	.msm_readl_relaxed = sdhci_msm_mci_variant_readl_relaxed,
 	.msm_writel_relaxed = sdhci_msm_mci_variant_writel_relaxed,
@@ -1650,7 +1720,8 @@ static void sdhci_msm_set_regulator_caps(struct sdhci_msm_host *msm_host)
 	.quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION |
 		  SDHCI_QUIRK_SINGLE_POWER_WRITE |
 		  SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
-	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
+	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
+		   SDHCI_QUIRK2_INTERNAL_PWR_CTL,
 	.ops = &sdhci_msm_ops,
 };
 
@@ -1819,6 +1890,10 @@ static int sdhci_msm_probe(struct platform_device *pdev)
 				msm_offset->core_vendor_spec_capabilities0);
 	}
 
+	ret = sdhci_msm_register_vreg(msm_host);
+	if (ret == -EPROBE_DEFER)
+		goto clk_disable;
+
 	/*
 	 * Power on reset state may trigger power irq if previous status of
 	 * PWRCTL was either BUS_ON or IO_HIGH_V. So before enabling pwr irq
@@ -1867,7 +1942,7 @@ static int sdhci_msm_probe(struct platform_device *pdev)
 	ret = sdhci_add_host(host);
 	if (ret)
 		goto pm_runtime_disable;
-	sdhci_msm_set_regulator_caps(msm_host);
+	msm_host->pltfm_init_done = true;
 
 	pm_runtime_mark_last_busy(&pdev->dev);
 	pm_runtime_put_autosuspend(&pdev->dev);
-- 
 Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc. 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH RFC 1/2] mmc: sdhci: Allow platform controlled voltage switching
  2018-06-21 12:23 ` [PATCH RFC 1/2] mmc: sdhci: Allow platform controlled voltage switching Vijay Viswanath
@ 2018-07-10 11:07   ` Adrian Hunter
  2018-07-17  5:14     ` Vijay Viswanath
  0 siblings, 1 reply; 12+ messages in thread
From: Adrian Hunter @ 2018-07-10 11:07 UTC (permalink / raw)
  To: Vijay Viswanath, ulf.hansson, robh+dt, mark.rutland
  Cc: linux-mmc, linux-kernel, shawn.lin, linux-arm-msm, georgi.djakov,
	devicetree, asutoshd, stummala, venkatg, jeremymc,
	bjorn.andersson, riteshh, vbadigan, dianders, sayalil

On 21/06/18 15:23, 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.
> 
> Add a quirk, which can be used by drivers of such controllers.
> 
> Signed-off-by: Vijay Viswanath <vviswana@codeaurora.org>
> ---
>  drivers/mmc/host/sdhci.c | 20 +++++++++++++++-----
>  drivers/mmc/host/sdhci.h |  2 ++
>  2 files changed, 17 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 1c828e0..f0346d4 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -1615,7 +1615,8 @@ void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode,
>  void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
>  		     unsigned short vdd)
>  {
> -	if (IS_ERR(host->mmc->supply.vmmc))
> +	if (IS_ERR(host->mmc->supply.vmmc) ||
> +			(host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL))

I think you should provide your own ->set_power() instead of this

>  		sdhci_set_power_noreg(host, mode, vdd);
>  	else
>  		sdhci_set_power_reg(host, mode, vdd);
> @@ -2009,7 +2010,9 @@ int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
>  		ctrl &= ~SDHCI_CTRL_VDD_180;
>  		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
>  
> -		if (!IS_ERR(mmc->supply.vqmmc)) {
> +		if (!IS_ERR(mmc->supply.vqmmc) &&
> +				!(host->quirks2 &
> +					SDHCI_QUIRK2_INTERNAL_PWR_CTL)) {

And your own ->start_signal_voltage_switch()

>  			ret = mmc_regulator_set_vqmmc(mmc, ios);
>  			if (ret) {
>  				pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
> @@ -2032,7 +2035,8 @@ int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
>  	case MMC_SIGNAL_VOLTAGE_180:
>  		if (!(host->flags & SDHCI_SIGNALING_180))
>  			return -EINVAL;
> -		if (!IS_ERR(mmc->supply.vqmmc)) {
> +		if (!IS_ERR(mmc->supply.vqmmc) &&
> +			!(host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL)) {
>  			ret = mmc_regulator_set_vqmmc(mmc, ios);
>  			if (ret) {
>  				pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
> @@ -3485,7 +3489,10 @@ 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 (!(host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL))

Since we expect mmc_regulator_get_supply() to have been called, this could be:

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

> +		ret = mmc_regulator_get_supply(mmc);
> +	else
> +		ret = 0;
>  	if (ret)
>  		return ret;
>  
> @@ -3736,7 +3743,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 (!(host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL))

And this could be:

		if (enable_vqmmc)
			ret = regulator_enable(mmc->supply.vqmmc);
		else
			ret = 0;

However, you still need to ensure regulator_disable(mmc->supply.vqmmc) is
only called if regulator_enable() was called.

> +			ret = regulator_enable(mmc->supply.vqmmc);
> +		else
> +			ret = 0;
>  		if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 1700000,
>  						    1950000))
>  			host->caps1 &= ~(SDHCI_SUPPORT_SDR104 |
> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
> index 23966f8..3b0c97a 100644
> --- a/drivers/mmc/host/sdhci.h
> +++ b/drivers/mmc/host/sdhci.h
> @@ -450,6 +450,8 @@ struct sdhci_host {
>   * obtainable timeout.
>   */
>  #define SDHCI_QUIRK2_DISABLE_HW_TIMEOUT			(1<<17)
> +/* Regulator voltage changes are being done from platform layer */
> +#define SDHCI_QUIRK2_INTERNAL_PWR_CTL				(1<<18)

So maybe the quirk is not needed.

>  
>  	int irq;		/* Device IRQ */
>  	void __iomem *ioaddr;	/* Mapped address */
> 


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH RFC 2/2] mmc: sdhci-msm: Use internal voltage control
  2018-06-21 12:23 ` [PATCH RFC 2/2] mmc: sdhci-msm: Use internal voltage control Vijay Viswanath
@ 2018-07-10 11:26   ` Adrian Hunter
  0 siblings, 0 replies; 12+ messages in thread
From: Adrian Hunter @ 2018-07-10 11:26 UTC (permalink / raw)
  To: Vijay Viswanath, ulf.hansson, robh+dt, mark.rutland
  Cc: linux-mmc, linux-kernel, shawn.lin, linux-arm-msm, georgi.djakov,
	devicetree, asutoshd, stummala, venkatg, jeremymc,
	bjorn.andersson, riteshh, vbadigan, dianders, sayalil

On 21/06/18 15:23, Vijay Viswanath wrote:
> Some sdhci-msm controllers require that voltage switching be done after
> the HW is ready for it. The HW informs its readiness through power irq.
> The voltage switching should happen only then.
> 
> Use the quirk for internal voltage switching and then control the
> voltage switching using power irq.
> 
> Signed-off-by: Vijay Viswanath <vviswana@codeaurora.org>
> ---
>  drivers/mmc/host/sdhci-msm.c | 99 ++++++++++++++++++++++++++++++++++++++------
>  1 file changed, 87 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
> index a0dc3e1..ebdde29 100644
> --- a/drivers/mmc/host/sdhci-msm.c
> +++ b/drivers/mmc/host/sdhci-msm.c
> @@ -43,7 +43,9 @@
>  #define CORE_PWRCTL_IO_LOW	BIT(2)
>  #define CORE_PWRCTL_IO_HIGH	BIT(3)
>  #define CORE_PWRCTL_BUS_SUCCESS BIT(0)
> +#define CORE_PWRCTL_BUS_FAIL    BIT(1)
>  #define CORE_PWRCTL_IO_SUCCESS	BIT(2)
> +#define CORE_PWRCTL_IO_FAIL     BIT(3)
>  #define REQ_BUS_OFF		BIT(0)
>  #define REQ_BUS_ON		BIT(1)
>  #define REQ_IO_LOW		BIT(2)
> @@ -258,6 +260,7 @@ struct sdhci_msm_host {
>  	bool mci_removed;
>  	const struct sdhci_msm_variant_ops *var_ops;
>  	const struct sdhci_msm_offset *offset;
> +	bool pltfm_init_done;

Wouldn't hurt to explain what 'pltfm_init_done' is for

>  };
>  
>  static const struct sdhci_msm_offset *sdhci_priv_msm_offset(struct sdhci_host *host)
> @@ -1314,8 +1317,9 @@ static void sdhci_msm_handle_pwr_irq(struct sdhci_host *host, int irq)
>  {
>  	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
>  	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
> +	struct mmc_host *mmc = host->mmc;
>  	u32 irq_status, irq_ack = 0;
> -	int retry = 10;
> +	int retry = 10, ret = 0;
>  	u32 pwr_state = 0, io_level = 0;
>  	u32 config;
>  	const struct sdhci_msm_offset *msm_offset = msm_host->offset;
> @@ -1351,14 +1355,59 @@ static void sdhci_msm_handle_pwr_irq(struct sdhci_host *host, int irq)
>  
>  	/* Handle BUS ON/OFF*/
>  	if (irq_status & CORE_PWRCTL_BUS_ON) {
> -		pwr_state = REQ_BUS_ON;
> -		io_level = REQ_IO_HIGH;
> -		irq_ack |= CORE_PWRCTL_BUS_SUCCESS;
> +		if (mmc->supply.vmmc) {

Since you call mmc_regulator_get_supply() first, mmc->supply.vmmc will never
be NULL.  Did you mean:

		if (!IS_ERR(mmc->supply.vmmc))

> +			ret = regulator_set_load(mmc->supply.vmmc, 800000);
> +			ret |= mmc_regulator_set_ocr(mmc, mmc->supply.vmmc,
> +					mmc->ios.vdd);
> +			if (ret)
> +				pr_err("%s: vmmc enable failed: %d\n",
> +						mmc_hostname(mmc), ret);
> +		}
> +		if (mmc->supply.vqmmc && !ret) {

Ditto for mmc->supply.vqmmc

> +			ret = regulator_set_load(mmc->supply.vqmmc, 22000);
> +			ret |= mmc_regulator_set_ocr(mmc, mmc->supply.vqmmc,
> +					mmc->ios.vdd);
> +			if (!ret)
> +				ret = regulator_enable(mmc->supply.vqmmc);
> +			if (ret)
> +				pr_err("%s: vqmmc enable failed: %d\n",
> +						mmc_hostname(mmc), ret);
> +		}
> +		if (!ret) {
> +			pwr_state = REQ_BUS_ON;
> +			io_level = REQ_IO_HIGH;
> +			irq_ack |= CORE_PWRCTL_BUS_SUCCESS;
> +		} else {
> +			pr_err("%s: BUS_ON req failed(%d). irq_status: 0x%08x\n",
> +					mmc_hostname(mmc), ret, irq_status);
> +			irq_ack |= CORE_PWRCTL_BUS_FAIL;
> +		}
>  	}
>  	if (irq_status & CORE_PWRCTL_BUS_OFF) {
> -		pwr_state = REQ_BUS_OFF;
> -		io_level = REQ_IO_LOW;
> -		irq_ack |= CORE_PWRCTL_BUS_SUCCESS;
> +		if (mmc->supply.vmmc && msm_host->pltfm_init_done) {
> +			ret = regulator_set_load(mmc->supply.vmmc, 0);
> +			ret |= mmc_regulator_set_ocr(mmc, mmc->supply.vmmc,
> +					mmc->ios.vdd);
> +			if (ret)
> +				pr_err("%s: vqmmc disabling failed: %d\n",
> +						mmc_hostname(mmc), ret);
> +		}
> +		if (mmc->supply.vqmmc && msm_host->pltfm_init_done && !ret) {
> +			ret = regulator_set_load(mmc->supply.vqmmc, 0);
> +			ret |= regulator_disable(mmc->supply.vqmmc);
> +			if (ret)
> +				pr_err("%s: vqmmc disabling failed: %d\n",
> +						mmc_hostname(mmc), ret);
> +		}
> +		if (!ret) {
> +			pwr_state = REQ_BUS_OFF;
> +			io_level = REQ_IO_LOW;
> +			irq_ack |= CORE_PWRCTL_BUS_SUCCESS;
> +		} else {
> +			pr_err("%s: BUS_ON req failed(%d). irq_status: 0x%08x\n",
> +					mmc_hostname(mmc), ret, irq_status);
> +			irq_ack |= CORE_PWRCTL_BUS_FAIL;
> +		}
>  	}
>  	/* Handle IO LOW/HIGH */
>  	if (irq_status & CORE_PWRCTL_IO_LOW) {
> @@ -1370,6 +1419,15 @@ static void sdhci_msm_handle_pwr_irq(struct sdhci_host *host, int irq)
>  		irq_ack |= CORE_PWRCTL_IO_SUCCESS;
>  	}
>  
> +	if (io_level && mmc->supply.vqmmc && !pwr_state) {
> +		ret = mmc_regulator_set_vqmmc(mmc, &mmc->ios);
> +		if (ret)
> +			pr_err("%s: IO_level setting failed(%d). signal_voltage: %d, vdd: %d irq_status: 0x%08x\n",
> +					mmc_hostname(mmc), ret,
> +					mmc->ios.signal_voltage, mmc->ios.vdd,
> +					irq_status);
> +	}
> +
>  	/*
>  	 * The driver has to acknowledge the interrupt, switch voltages and
>  	 * report back if it succeded or not to this register. The voltage
> @@ -1415,10 +1473,9 @@ static void sdhci_msm_handle_pwr_irq(struct sdhci_host *host, int irq)
>  		msm_host->curr_pwr_state = pwr_state;
>  	if (io_level)
>  		msm_host->curr_io_level = io_level;
> -
>  	pr_debug("%s: %s: Handled IRQ(%d), irq_status=0x%x, ack=0x%x\n",
> -		mmc_hostname(msm_host->mmc), __func__, irq, irq_status,
> -		irq_ack);
> +			mmc_hostname(msm_host->mmc), __func__,
> +			irq, irq_status, irq_ack);
>  }
>  
>  static irqreturn_t sdhci_msm_pwr_irq(int irq, void *data)
> @@ -1605,6 +1662,19 @@ static void sdhci_msm_set_regulator_caps(struct sdhci_msm_host *msm_host)
>  	pr_debug("%s: supported caps: 0x%08x\n", mmc_hostname(mmc), caps);
>  }
>  
> +static int sdhci_msm_register_vreg(struct sdhci_msm_host *msm_host)
> +{
> +	int ret = 0;
> +
> +	ret = mmc_regulator_get_supply(msm_host->mmc);
> +	if (ret)
> +		return ret;
> +	sdhci_msm_set_regulator_caps(msm_host);
> +
> +	return 0;
> +
> +}
> +
>  static const struct sdhci_msm_variant_ops mci_var_ops = {
>  	.msm_readl_relaxed = sdhci_msm_mci_variant_readl_relaxed,
>  	.msm_writel_relaxed = sdhci_msm_mci_variant_writel_relaxed,
> @@ -1650,7 +1720,8 @@ static void sdhci_msm_set_regulator_caps(struct sdhci_msm_host *msm_host)
>  	.quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION |
>  		  SDHCI_QUIRK_SINGLE_POWER_WRITE |
>  		  SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
> -	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
> +	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
> +		   SDHCI_QUIRK2_INTERNAL_PWR_CTL,
>  	.ops = &sdhci_msm_ops,
>  };
>  
> @@ -1819,6 +1890,10 @@ static int sdhci_msm_probe(struct platform_device *pdev)
>  				msm_offset->core_vendor_spec_capabilities0);
>  	}
>  
> +	ret = sdhci_msm_register_vreg(msm_host);
> +	if (ret == -EPROBE_DEFER)
> +		goto clk_disable;
> +
>  	/*
>  	 * Power on reset state may trigger power irq if previous status of
>  	 * PWRCTL was either BUS_ON or IO_HIGH_V. So before enabling pwr irq
> @@ -1867,7 +1942,7 @@ static int sdhci_msm_probe(struct platform_device *pdev)
>  	ret = sdhci_add_host(host);
>  	if (ret)
>  		goto pm_runtime_disable;
> -	sdhci_msm_set_regulator_caps(msm_host);
> +	msm_host->pltfm_init_done = true;
>  
>  	pm_runtime_mark_last_busy(&pdev->dev);
>  	pm_runtime_put_autosuspend(&pdev->dev);
> 


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH RFC 1/2] mmc: sdhci: Allow platform controlled voltage switching
  2018-07-10 11:07   ` Adrian Hunter
@ 2018-07-17  5:14     ` Vijay Viswanath
  2018-07-17  7:30       ` Adrian Hunter
  0 siblings, 1 reply; 12+ messages in thread
From: Vijay Viswanath @ 2018-07-17  5:14 UTC (permalink / raw)
  To: Adrian Hunter, ulf.hansson, robh+dt, mark.rutland
  Cc: linux-mmc, linux-kernel, shawn.lin, linux-arm-msm, georgi.djakov,
	devicetree, asutoshd, stummala, venkatg, jeremymc,
	bjorn.andersson, riteshh, vbadigan, dianders, sayalil,
	Evan Green



On 7/10/2018 4:37 PM, Adrian Hunter wrote:
> On 21/06/18 15:23, 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.
>>
>> Add a quirk, which can be used by drivers of such controllers.
>>
>> Signed-off-by: Vijay Viswanath <vviswana@codeaurora.org>
>> ---
>>   drivers/mmc/host/sdhci.c | 20 +++++++++++++++-----
>>   drivers/mmc/host/sdhci.h |  2 ++
>>   2 files changed, 17 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>> index 1c828e0..f0346d4 100644
>> --- a/drivers/mmc/host/sdhci.c
>> +++ b/drivers/mmc/host/sdhci.c
>> @@ -1615,7 +1615,8 @@ void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode,
>>   void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
>>   		     unsigned short vdd)
>>   {
>> -	if (IS_ERR(host->mmc->supply.vmmc))
>> +	if (IS_ERR(host->mmc->supply.vmmc) ||
>> +			(host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL))
> 
> I think you should provide your own ->set_power() instead of this
> 

will do

>>   		sdhci_set_power_noreg(host, mode, vdd);
>>   	else
>>   		sdhci_set_power_reg(host, mode, vdd);
>> @@ -2009,7 +2010,9 @@ int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
>>   		ctrl &= ~SDHCI_CTRL_VDD_180;
>>   		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
>>   
>> -		if (!IS_ERR(mmc->supply.vqmmc)) {
>> +		if (!IS_ERR(mmc->supply.vqmmc) &&
>> +				!(host->quirks2 &
>> +					SDHCI_QUIRK2_INTERNAL_PWR_CTL)) {
> 
> And your own ->start_signal_voltage_switch()
> 

sdhci_msm_start_signal_voltage_switch() would be an exact copy of 
sdhci_start_signal_voltage_switch()..... will incorporate this if not 
using quirk.

>>   			ret = mmc_regulator_set_vqmmc(mmc, ios);
>>   			if (ret) {
>>   				pr_warn("%s: Switching to 3.3V signalling voltage failed\n",
>> @@ -2032,7 +2035,8 @@ int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
>>   	case MMC_SIGNAL_VOLTAGE_180:
>>   		if (!(host->flags & SDHCI_SIGNALING_180))
>>   			return -EINVAL;
>> -		if (!IS_ERR(mmc->supply.vqmmc)) {
>> +		if (!IS_ERR(mmc->supply.vqmmc) &&
>> +			!(host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL)) {
>>   			ret = mmc_regulator_set_vqmmc(mmc, ios);
>>   			if (ret) {
>>   				pr_warn("%s: Switching to 1.8V signalling voltage failed\n",
>> @@ -3485,7 +3489,10 @@ 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 (!(host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL))
> 
> Since we expect mmc_regulator_get_supply() to have been called, this could be:
> 
> 	if (!mmc->supply.vmmc) {
> 		ret = mmc_regulator_get_supply(mmc);
> 		enable_vqmmc = true;
> 	} else {
> 		ret = 0;
> 	}
> >> +		ret = mmc_regulator_get_supply(mmc);
>> +	else
>> +		ret = 0;
>>   	if (ret)
>>   		return ret;
>>   
>> @@ -3736,7 +3743,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 (!(host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL))
> 
> And this could be:
> 
> 		if (enable_vqmmc)
> 			ret = regulator_enable(mmc->supply.vqmmc);
> 		else
> 			ret = 0;
>  > However, you still need to ensure regulator_disable(mmc->supply.vqmmc) is
> only called if regulator_enable() was called.
I missed this. Will cover it.

Also I missed one more place where we are doing regulator_disable. 
During sdhci-msm unbinding, we would end up doing an extra regulator 
disable (thanks Evan for pointing it out) in sdhci_remove_host.

To avoid the quirk( or having any flag), it would require copying the 
code of sdhci_start_signal_voltage_switch() and sdhci_remove_host() and 
creating 2 new functions in sdhci_msm layer which would do the exact 
same as above, with just the regulator parts removed.

This looks messy (considering any future changes to the 2 sdhci API will 
need to be copied to their duplicate sdhci_msm API) and a bit overkill 
to avoid quirk. At the same time, I don't know how useful such a quirk 
would be to other platform drivers.

Please let me know your view/suggestions.
> 
>> +			ret = regulator_enable(mmc->supply.vqmmc);
>> +		else
>> +			ret = 0;
>>   		if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 1700000,
>>   						    1950000))
>>   			host->caps1 &= ~(SDHCI_SUPPORT_SDR104 |
>> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
>> index 23966f8..3b0c97a 100644
>> --- a/drivers/mmc/host/sdhci.h
>> +++ b/drivers/mmc/host/sdhci.h
>> @@ -450,6 +450,8 @@ struct sdhci_host {
>>    * obtainable timeout.
>>    */
>>   #define SDHCI_QUIRK2_DISABLE_HW_TIMEOUT			(1<<17)
>> +/* Regulator voltage changes are being done from platform layer */
>> +#define SDHCI_QUIRK2_INTERNAL_PWR_CTL				(1<<18)
> 
> So maybe the quirk is not needed.
> 
>>   
>>   	int irq;		/* Device IRQ */
>>   	void __iomem *ioaddr;	/* Mapped address */
>>
> 

Thanks for the review & suggestions!
Vijay

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH RFC 1/2] mmc: sdhci: Allow platform controlled voltage switching
  2018-07-17  5:14     ` Vijay Viswanath
@ 2018-07-17  7:30       ` Adrian Hunter
  2018-07-17  8:40         ` Vijay Viswanath
  0 siblings, 1 reply; 12+ messages in thread
From: Adrian Hunter @ 2018-07-17  7:30 UTC (permalink / raw)
  To: Vijay Viswanath, ulf.hansson, robh+dt, mark.rutland
  Cc: linux-mmc, linux-kernel, shawn.lin, linux-arm-msm, georgi.djakov,
	devicetree, asutoshd, stummala, venkatg, jeremymc,
	bjorn.andersson, riteshh, vbadigan, dianders, sayalil,
	Evan Green

On 17/07/18 08:14, Vijay Viswanath wrote:
> 
> 
> On 7/10/2018 4:37 PM, Adrian Hunter wrote:
>> On 21/06/18 15:23, 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.
>>>
>>> Add a quirk, which can be used by drivers of such controllers.
>>>
>>> Signed-off-by: Vijay Viswanath <vviswana@codeaurora.org>
>>> ---
>>>   drivers/mmc/host/sdhci.c | 20 +++++++++++++++-----
>>>   drivers/mmc/host/sdhci.h |  2 ++
>>>   2 files changed, 17 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>>> index 1c828e0..f0346d4 100644
>>> --- a/drivers/mmc/host/sdhci.c
>>> +++ b/drivers/mmc/host/sdhci.c
>>> @@ -1615,7 +1615,8 @@ void sdhci_set_power_noreg(struct sdhci_host *host,
>>> unsigned char mode,
>>>   void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
>>>                unsigned short vdd)
>>>   {
>>> -    if (IS_ERR(host->mmc->supply.vmmc))
>>> +    if (IS_ERR(host->mmc->supply.vmmc) ||
>>> +            (host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL))
>>
>> I think you should provide your own ->set_power() instead of this
>>
> 
> will do
> 
>>>           sdhci_set_power_noreg(host, mode, vdd);
>>>       else
>>>           sdhci_set_power_reg(host, mode, vdd);
>>> @@ -2009,7 +2010,9 @@ int sdhci_start_signal_voltage_switch(struct
>>> mmc_host *mmc,
>>>           ctrl &= ~SDHCI_CTRL_VDD_180;
>>>           sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
>>>   -        if (!IS_ERR(mmc->supply.vqmmc)) {
>>> +        if (!IS_ERR(mmc->supply.vqmmc) &&
>>> +                !(host->quirks2 &
>>> +                    SDHCI_QUIRK2_INTERNAL_PWR_CTL)) {
>>
>> And your own ->start_signal_voltage_switch()
>>
> 
> sdhci_msm_start_signal_voltage_switch() would be an exact copy of
> sdhci_start_signal_voltage_switch()..... will incorporate this if not using
> quirk.
> 
>>>               ret = mmc_regulator_set_vqmmc(mmc, ios);
>>>               if (ret) {
>>>                   pr_warn("%s: Switching to 3.3V signalling voltage
>>> failed\n",
>>> @@ -2032,7 +2035,8 @@ int sdhci_start_signal_voltage_switch(struct
>>> mmc_host *mmc,
>>>       case MMC_SIGNAL_VOLTAGE_180:
>>>           if (!(host->flags & SDHCI_SIGNALING_180))
>>>               return -EINVAL;
>>> -        if (!IS_ERR(mmc->supply.vqmmc)) {
>>> +        if (!IS_ERR(mmc->supply.vqmmc) &&
>>> +            !(host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL)) {
>>>               ret = mmc_regulator_set_vqmmc(mmc, ios);
>>>               if (ret) {
>>>                   pr_warn("%s: Switching to 1.8V signalling voltage
>>> failed\n",
>>> @@ -3485,7 +3489,10 @@ 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 (!(host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL))
>>
>> Since we expect mmc_regulator_get_supply() to have been called, this could
>> be:
>>
>>     if (!mmc->supply.vmmc) {
>>         ret = mmc_regulator_get_supply(mmc);
>>         enable_vqmmc = true;
>>     } else {
>>         ret = 0;
>>     }
>> >> +        ret = mmc_regulator_get_supply(mmc);
>>> +    else
>>> +        ret = 0;
>>>       if (ret)
>>>           return ret;
>>>   @@ -3736,7 +3743,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 (!(host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL))
>>
>> And this could be:
>>
>>         if (enable_vqmmc)
>>             ret = regulator_enable(mmc->supply.vqmmc);
>>         else
>>             ret = 0;
>>  > However, you still need to ensure regulator_disable(mmc->supply.vqmmc) is
>> only called if regulator_enable() was called.
> I missed this. Will cover it.
> 
> Also I missed one more place where we are doing regulator_disable. During
> sdhci-msm unbinding, we would end up doing an extra regulator disable
> (thanks Evan for pointing it out) in sdhci_remove_host.
> 
> To avoid the quirk( or having any flag), it would require copying the code
> of sdhci_start_signal_voltage_switch() and sdhci_remove_host() and creating

You do not need to duplicate sdhci_remove_host(), just change it so that it
only  disables what was enabled i.e.

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

> 2 new functions in sdhci_msm layer which would do the exact same as above,
> with just the regulator parts removed.
> 
> This looks messy (considering any future changes to the 2 sdhci API will
> need to be copied to their duplicate sdhci_msm API) and a bit overkill to
> avoid quirk. At the same time, I don't know how useful such a quirk would be
> to other platform drivers.
> 
> Please let me know your view/suggestions.

Let's try without the quirk.

>>
>>> +            ret = regulator_enable(mmc->supply.vqmmc);
>>> +        else
>>> +            ret = 0;
>>>           if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 1700000,
>>>                               1950000))
>>>               host->caps1 &= ~(SDHCI_SUPPORT_SDR104 |
>>> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
>>> index 23966f8..3b0c97a 100644
>>> --- a/drivers/mmc/host/sdhci.h
>>> +++ b/drivers/mmc/host/sdhci.h
>>> @@ -450,6 +450,8 @@ struct sdhci_host {
>>>    * obtainable timeout.
>>>    */
>>>   #define SDHCI_QUIRK2_DISABLE_HW_TIMEOUT            (1<<17)
>>> +/* Regulator voltage changes are being done from platform layer */
>>> +#define SDHCI_QUIRK2_INTERNAL_PWR_CTL                (1<<18)
>>
>> So maybe the quirk is not needed.
>>
>>>         int irq;        /* Device IRQ */
>>>       void __iomem *ioaddr;    /* Mapped address */
>>>
>>
> 
> Thanks for the review & suggestions!
> Vijay
> 


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH RFC 1/2] mmc: sdhci: Allow platform controlled voltage switching
  2018-07-17  7:30       ` Adrian Hunter
@ 2018-07-17  8:40         ` Vijay Viswanath
  2018-07-17  8:42           ` Adrian Hunter
  0 siblings, 1 reply; 12+ messages in thread
From: Vijay Viswanath @ 2018-07-17  8:40 UTC (permalink / raw)
  To: Adrian Hunter, ulf.hansson, robh+dt, mark.rutland
  Cc: linux-mmc, linux-kernel, shawn.lin, linux-arm-msm, georgi.djakov,
	devicetree, asutoshd, stummala, venkatg, jeremymc,
	bjorn.andersson, riteshh, vbadigan, dianders, sayalil,
	Evan Green



On 7/17/2018 1:00 PM, Adrian Hunter wrote:
> On 17/07/18 08:14, Vijay Viswanath wrote:
>>
>>
>> On 7/10/2018 4:37 PM, Adrian Hunter wrote:
>>> On 21/06/18 15:23, 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.
>>>>
>>>> Add a quirk, which can be used by drivers of such controllers.
>>>>
>>>> Signed-off-by: Vijay Viswanath <vviswana@codeaurora.org>
>>>> ---
>>>>    drivers/mmc/host/sdhci.c | 20 +++++++++++++++-----
>>>>    drivers/mmc/host/sdhci.h |  2 ++
>>>>    2 files changed, 17 insertions(+), 5 deletions(-)
>>>>
>>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>>>> index 1c828e0..f0346d4 100644
>>>> --- a/drivers/mmc/host/sdhci.c
>>>> +++ b/drivers/mmc/host/sdhci.c
>>>> @@ -1615,7 +1615,8 @@ void sdhci_set_power_noreg(struct sdhci_host *host,
>>>> unsigned char mode,
>>>>    void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
>>>>                 unsigned short vdd)
>>>>    {
>>>> -    if (IS_ERR(host->mmc->supply.vmmc))
>>>> +    if (IS_ERR(host->mmc->supply.vmmc) ||
>>>> +            (host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL))
>>>
>>> I think you should provide your own ->set_power() instead of this
>>>
>>
>> will do
>>
>>>>            sdhci_set_power_noreg(host, mode, vdd);
>>>>        else
>>>>            sdhci_set_power_reg(host, mode, vdd);
>>>> @@ -2009,7 +2010,9 @@ int sdhci_start_signal_voltage_switch(struct
>>>> mmc_host *mmc,
>>>>            ctrl &= ~SDHCI_CTRL_VDD_180;
>>>>            sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
>>>>    -        if (!IS_ERR(mmc->supply.vqmmc)) {
>>>> +        if (!IS_ERR(mmc->supply.vqmmc) &&
>>>> +                !(host->quirks2 &
>>>> +                    SDHCI_QUIRK2_INTERNAL_PWR_CTL)) {
>>>
>>> And your own ->start_signal_voltage_switch()
>>>
>>
>> sdhci_msm_start_signal_voltage_switch() would be an exact copy of
>> sdhci_start_signal_voltage_switch()..... will incorporate this if not using
>> quirk.
>>
>>>>                ret = mmc_regulator_set_vqmmc(mmc, ios);
>>>>                if (ret) {
>>>>                    pr_warn("%s: Switching to 3.3V signalling voltage
>>>> failed\n",
>>>> @@ -2032,7 +2035,8 @@ int sdhci_start_signal_voltage_switch(struct
>>>> mmc_host *mmc,
>>>>        case MMC_SIGNAL_VOLTAGE_180:
>>>>            if (!(host->flags & SDHCI_SIGNALING_180))
>>>>                return -EINVAL;
>>>> -        if (!IS_ERR(mmc->supply.vqmmc)) {
>>>> +        if (!IS_ERR(mmc->supply.vqmmc) &&
>>>> +            !(host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL)) {
>>>>                ret = mmc_regulator_set_vqmmc(mmc, ios);
>>>>                if (ret) {
>>>>                    pr_warn("%s: Switching to 1.8V signalling voltage
>>>> failed\n",
>>>> @@ -3485,7 +3489,10 @@ 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 (!(host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL))
>>>
>>> Since we expect mmc_regulator_get_supply() to have been called, this could
>>> be:
>>>
>>>      if (!mmc->supply.vmmc) {
>>>          ret = mmc_regulator_get_supply(mmc);
>>>          enable_vqmmc = true;
>>>      } else {
>>>          ret = 0;
>>>      }
>>>>> +        ret = mmc_regulator_get_supply(mmc);
>>>> +    else
>>>> +        ret = 0;
>>>>        if (ret)
>>>>            return ret;
>>>>    @@ -3736,7 +3743,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 (!(host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL))
>>>
>>> And this could be:
>>>
>>>          if (enable_vqmmc)
>>>              ret = regulator_enable(mmc->supply.vqmmc);
>>>          else
>>>              ret = 0;
>>>   > However, you still need to ensure regulator_disable(mmc->supply.vqmmc) is
>>> only called if regulator_enable() was called.
>> I missed this. Will cover it.
>>
>> Also I missed one more place where we are doing regulator_disable. During
>> sdhci-msm unbinding, we would end up doing an extra regulator disable
>> (thanks Evan for pointing it out) in sdhci_remove_host.
>>
>> To avoid the quirk( or having any flag), it would require copying the code
>> of sdhci_start_signal_voltage_switch() and sdhci_remove_host() and creating
> 
> You do not need to duplicate sdhci_remove_host(), just change it so that it
> only  disables what was enabled i.e.
> 
> 	if (host->vqmmc_enabled)
> 		regulator_disable(mmc->supply.vqmmc);
> 

Ok, so we will be adding a new flag "vqmmc_enabled" in sdhci_host, ryt ?
Just wanted to clarify

>> 2 new functions in sdhci_msm layer which would do the exact same as above,
>> with just the regulator parts removed.
>>
>> This looks messy (considering any future changes to the 2 sdhci API will
>> need to be copied to their duplicate sdhci_msm API) and a bit overkill to
>> avoid quirk. At the same time, I don't know how useful such a quirk would be
>> to other platform drivers.
>>
>> Please let me know your view/suggestions.
> 
> Let's try without the quirk.
> 
>>>
>>>> +            ret = regulator_enable(mmc->supply.vqmmc);
>>>> +        else
>>>> +            ret = 0;
>>>>            if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 1700000,
>>>>                                1950000))
>>>>                host->caps1 &= ~(SDHCI_SUPPORT_SDR104 |
>>>> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
>>>> index 23966f8..3b0c97a 100644
>>>> --- a/drivers/mmc/host/sdhci.h
>>>> +++ b/drivers/mmc/host/sdhci.h
>>>> @@ -450,6 +450,8 @@ struct sdhci_host {
>>>>     * obtainable timeout.
>>>>     */
>>>>    #define SDHCI_QUIRK2_DISABLE_HW_TIMEOUT            (1<<17)
>>>> +/* Regulator voltage changes are being done from platform layer */
>>>> +#define SDHCI_QUIRK2_INTERNAL_PWR_CTL                (1<<18)
>>>
>>> So maybe the quirk is not needed.
>>>
>>>>          int irq;        /* Device IRQ */
>>>>        void __iomem *ioaddr;    /* Mapped address */
>>>>
>>>
>>
>> Thanks for the review & suggestions!
>> Vijay
>>
> 

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH RFC 1/2] mmc: sdhci: Allow platform controlled voltage switching
  2018-07-17  8:40         ` Vijay Viswanath
@ 2018-07-17  8:42           ` Adrian Hunter
  2018-07-17  9:45             ` Vijay Viswanath
  0 siblings, 1 reply; 12+ messages in thread
From: Adrian Hunter @ 2018-07-17  8:42 UTC (permalink / raw)
  To: Vijay Viswanath, ulf.hansson, robh+dt, mark.rutland
  Cc: linux-mmc, linux-kernel, shawn.lin, linux-arm-msm, georgi.djakov,
	devicetree, asutoshd, stummala, venkatg, jeremymc,
	bjorn.andersson, riteshh, vbadigan, dianders, sayalil,
	Evan Green

On 17/07/18 11:40, Vijay Viswanath wrote:
> 
> 
> On 7/17/2018 1:00 PM, Adrian Hunter wrote:
>> On 17/07/18 08:14, Vijay Viswanath wrote:
>>>
>>>
>>> On 7/10/2018 4:37 PM, Adrian Hunter wrote:
>>>> On 21/06/18 15:23, 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.
>>>>>
>>>>> Add a quirk, which can be used by drivers of such controllers.
>>>>>
>>>>> Signed-off-by: Vijay Viswanath <vviswana@codeaurora.org>
>>>>> ---
>>>>>    drivers/mmc/host/sdhci.c | 20 +++++++++++++++-----
>>>>>    drivers/mmc/host/sdhci.h |  2 ++
>>>>>    2 files changed, 17 insertions(+), 5 deletions(-)
>>>>>
>>>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>>>>> index 1c828e0..f0346d4 100644
>>>>> --- a/drivers/mmc/host/sdhci.c
>>>>> +++ b/drivers/mmc/host/sdhci.c
>>>>> @@ -1615,7 +1615,8 @@ void sdhci_set_power_noreg(struct sdhci_host *host,
>>>>> unsigned char mode,
>>>>>    void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
>>>>>                 unsigned short vdd)
>>>>>    {
>>>>> -    if (IS_ERR(host->mmc->supply.vmmc))
>>>>> +    if (IS_ERR(host->mmc->supply.vmmc) ||
>>>>> +            (host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL))
>>>>
>>>> I think you should provide your own ->set_power() instead of this
>>>>
>>>
>>> will do
>>>
>>>>>            sdhci_set_power_noreg(host, mode, vdd);
>>>>>        else
>>>>>            sdhci_set_power_reg(host, mode, vdd);
>>>>> @@ -2009,7 +2010,9 @@ int sdhci_start_signal_voltage_switch(struct
>>>>> mmc_host *mmc,
>>>>>            ctrl &= ~SDHCI_CTRL_VDD_180;
>>>>>            sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
>>>>>    -        if (!IS_ERR(mmc->supply.vqmmc)) {
>>>>> +        if (!IS_ERR(mmc->supply.vqmmc) &&
>>>>> +                !(host->quirks2 &
>>>>> +                    SDHCI_QUIRK2_INTERNAL_PWR_CTL)) {
>>>>
>>>> And your own ->start_signal_voltage_switch()
>>>>
>>>
>>> sdhci_msm_start_signal_voltage_switch() would be an exact copy of
>>> sdhci_start_signal_voltage_switch()..... will incorporate this if not using
>>> quirk.
>>>
>>>>>                ret = mmc_regulator_set_vqmmc(mmc, ios);
>>>>>                if (ret) {
>>>>>                    pr_warn("%s: Switching to 3.3V signalling voltage
>>>>> failed\n",
>>>>> @@ -2032,7 +2035,8 @@ int sdhci_start_signal_voltage_switch(struct
>>>>> mmc_host *mmc,
>>>>>        case MMC_SIGNAL_VOLTAGE_180:
>>>>>            if (!(host->flags & SDHCI_SIGNALING_180))
>>>>>                return -EINVAL;
>>>>> -        if (!IS_ERR(mmc->supply.vqmmc)) {
>>>>> +        if (!IS_ERR(mmc->supply.vqmmc) &&
>>>>> +            !(host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL)) {
>>>>>                ret = mmc_regulator_set_vqmmc(mmc, ios);
>>>>>                if (ret) {
>>>>>                    pr_warn("%s: Switching to 1.8V signalling voltage
>>>>> failed\n",
>>>>> @@ -3485,7 +3489,10 @@ 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 (!(host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL))
>>>>
>>>> Since we expect mmc_regulator_get_supply() to have been called, this could
>>>> be:
>>>>
>>>>      if (!mmc->supply.vmmc) {
>>>>          ret = mmc_regulator_get_supply(mmc);
>>>>          enable_vqmmc = true;
>>>>      } else {
>>>>          ret = 0;
>>>>      }
>>>>>> +        ret = mmc_regulator_get_supply(mmc);
>>>>> +    else
>>>>> +        ret = 0;
>>>>>        if (ret)
>>>>>            return ret;
>>>>>    @@ -3736,7 +3743,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 (!(host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL))
>>>>
>>>> And this could be:
>>>>
>>>>          if (enable_vqmmc)
>>>>              ret = regulator_enable(mmc->supply.vqmmc);
>>>>          else
>>>>              ret = 0;
>>>>   > However, you still need to ensure
>>>> regulator_disable(mmc->supply.vqmmc) is
>>>> only called if regulator_enable() was called.
>>> I missed this. Will cover it.
>>>
>>> Also I missed one more place where we are doing regulator_disable. During
>>> sdhci-msm unbinding, we would end up doing an extra regulator disable
>>> (thanks Evan for pointing it out) in sdhci_remove_host.
>>>
>>> To avoid the quirk( or having any flag), it would require copying the code
>>> of sdhci_start_signal_voltage_switch() and sdhci_remove_host() and creating
>>
>> You do not need to duplicate sdhci_remove_host(), just change it so that it
>> only  disables what was enabled i.e.
>>
>>     if (host->vqmmc_enabled)
>>         regulator_disable(mmc->supply.vqmmc);
>>
> 
> Ok, so we will be adding a new flag "vqmmc_enabled" in sdhci_host, ryt ?

Yes

> Just wanted to clarify
> 
>>> 2 new functions in sdhci_msm layer which would do the exact same as above,
>>> with just the regulator parts removed.
>>>
>>> This looks messy (considering any future changes to the 2 sdhci API will
>>> need to be copied to their duplicate sdhci_msm API) and a bit overkill to
>>> avoid quirk. At the same time, I don't know how useful such a quirk would be
>>> to other platform drivers.
>>>
>>> Please let me know your view/suggestions.
>>
>> Let's try without the quirk.
>>
>>>>
>>>>> +            ret = regulator_enable(mmc->supply.vqmmc);
>>>>> +        else
>>>>> +            ret = 0;
>>>>>            if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 1700000,
>>>>>                                1950000))
>>>>>                host->caps1 &= ~(SDHCI_SUPPORT_SDR104 |
>>>>> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
>>>>> index 23966f8..3b0c97a 100644
>>>>> --- a/drivers/mmc/host/sdhci.h
>>>>> +++ b/drivers/mmc/host/sdhci.h
>>>>> @@ -450,6 +450,8 @@ struct sdhci_host {
>>>>>     * obtainable timeout.
>>>>>     */
>>>>>    #define SDHCI_QUIRK2_DISABLE_HW_TIMEOUT            (1<<17)
>>>>> +/* Regulator voltage changes are being done from platform layer */
>>>>> +#define SDHCI_QUIRK2_INTERNAL_PWR_CTL                (1<<18)
>>>>
>>>> So maybe the quirk is not needed.
>>>>
>>>>>          int irq;        /* Device IRQ */
>>>>>        void __iomem *ioaddr;    /* Mapped address */
>>>>>
>>>>
>>>
>>> Thanks for the review & suggestions!
>>> Vijay
>>>
>>
> 


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH RFC 1/2] mmc: sdhci: Allow platform controlled voltage switching
  2018-07-17  8:42           ` Adrian Hunter
@ 2018-07-17  9:45             ` Vijay Viswanath
  2018-07-17  9:54               ` Adrian Hunter
  0 siblings, 1 reply; 12+ messages in thread
From: Vijay Viswanath @ 2018-07-17  9:45 UTC (permalink / raw)
  To: Adrian Hunter, ulf.hansson, robh+dt, mark.rutland
  Cc: linux-mmc, linux-kernel, shawn.lin, linux-arm-msm, georgi.djakov,
	devicetree, asutoshd, stummala, venkatg, jeremymc,
	bjorn.andersson, riteshh, vbadigan, dianders, sayalil,
	Evan Green



On 7/17/2018 2:12 PM, Adrian Hunter wrote:
> On 17/07/18 11:40, Vijay Viswanath wrote:
>>
>>
>> On 7/17/2018 1:00 PM, Adrian Hunter wrote:
>>> On 17/07/18 08:14, Vijay Viswanath wrote:
>>>>
>>>>
>>>> On 7/10/2018 4:37 PM, Adrian Hunter wrote:
>>>>> On 21/06/18 15:23, 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.
>>>>>>
>>>>>> Add a quirk, which can be used by drivers of such controllers.
>>>>>>
>>>>>> Signed-off-by: Vijay Viswanath <vviswana@codeaurora.org>
>>>>>> ---
>>>>>>     drivers/mmc/host/sdhci.c | 20 +++++++++++++++-----
>>>>>>     drivers/mmc/host/sdhci.h |  2 ++
>>>>>>     2 files changed, 17 insertions(+), 5 deletions(-)
>>>>>>
>>>>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>>>>>> index 1c828e0..f0346d4 100644
>>>>>> --- a/drivers/mmc/host/sdhci.c
>>>>>> +++ b/drivers/mmc/host/sdhci.c
>>>>>> @@ -1615,7 +1615,8 @@ void sdhci_set_power_noreg(struct sdhci_host *host,
>>>>>> unsigned char mode,
>>>>>>     void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
>>>>>>                  unsigned short vdd)
>>>>>>     {
>>>>>> -    if (IS_ERR(host->mmc->supply.vmmc))
>>>>>> +    if (IS_ERR(host->mmc->supply.vmmc) ||
>>>>>> +            (host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL))
>>>>>
>>>>> I think you should provide your own ->set_power() instead of this
>>>>>
>>>>
>>>> will do
>>>>
>>>>>>             sdhci_set_power_noreg(host, mode, vdd);
>>>>>>         else
>>>>>>             sdhci_set_power_reg(host, mode, vdd);
>>>>>> @@ -2009,7 +2010,9 @@ int sdhci_start_signal_voltage_switch(struct
>>>>>> mmc_host *mmc,
>>>>>>             ctrl &= ~SDHCI_CTRL_VDD_180;
>>>>>>             sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
>>>>>>     -        if (!IS_ERR(mmc->supply.vqmmc)) {
>>>>>> +        if (!IS_ERR(mmc->supply.vqmmc) &&
>>>>>> +                !(host->quirks2 &
>>>>>> +                    SDHCI_QUIRK2_INTERNAL_PWR_CTL)) {
>>>>>
>>>>> And your own ->start_signal_voltage_switch()
>>>>>
>>>>
>>>> sdhci_msm_start_signal_voltage_switch() would be an exact copy of
>>>> sdhci_start_signal_voltage_switch()..... will incorporate this if not using
>>>> quirk.
>>>>
>>>>>>                 ret = mmc_regulator_set_vqmmc(mmc, ios);
>>>>>>                 if (ret) {
>>>>>>                     pr_warn("%s: Switching to 3.3V signalling voltage
>>>>>> failed\n",
>>>>>> @@ -2032,7 +2035,8 @@ int sdhci_start_signal_voltage_switch(struct
>>>>>> mmc_host *mmc,
>>>>>>         case MMC_SIGNAL_VOLTAGE_180:
>>>>>>             if (!(host->flags & SDHCI_SIGNALING_180))
>>>>>>                 return -EINVAL;
>>>>>> -        if (!IS_ERR(mmc->supply.vqmmc)) {
>>>>>> +        if (!IS_ERR(mmc->supply.vqmmc) &&
>>>>>> +            !(host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL)) {
>>>>>>                 ret = mmc_regulator_set_vqmmc(mmc, ios);
>>>>>>                 if (ret) {
>>>>>>                     pr_warn("%s: Switching to 1.8V signalling voltage
>>>>>> failed\n",
>>>>>> @@ -3485,7 +3489,10 @@ 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 (!(host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL))
>>>>>
>>>>> Since we expect mmc_regulator_get_supply() to have been called, this could
>>>>> be:
>>>>>
>>>>>       if (!mmc->supply.vmmc) {
>>>>>           ret = mmc_regulator_get_supply(mmc);
>>>>>           enable_vqmmc = true;
>>>>>       } else {
>>>>>           ret = 0;
>>>>>       }
>>>>>>> +        ret = mmc_regulator_get_supply(mmc);
>>>>>> +    else
>>>>>> +        ret = 0;
>>>>>>         if (ret)
>>>>>>             return ret;
>>>>>>     @@ -3736,7 +3743,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 (!(host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL))
>>>>>
>>>>> And this could be:
>>>>>
>>>>>           if (enable_vqmmc)
>>>>>               ret = regulator_enable(mmc->supply.vqmmc);
>>>>>           else
>>>>>               ret = 0;
>>>>>    > However, you still need to ensure
>>>>> regulator_disable(mmc->supply.vqmmc) is
>>>>> only called if regulator_enable() was called.
>>>> I missed this. Will cover it.
>>>>
>>>> Also I missed one more place where we are doing regulator_disable. During
>>>> sdhci-msm unbinding, we would end up doing an extra regulator disable
>>>> (thanks Evan for pointing it out) in sdhci_remove_host.
>>>>
>>>> To avoid the quirk( or having any flag), it would require copying the code
>>>> of sdhci_start_signal_voltage_switch() and sdhci_remove_host() and creating
>>>
>>> You do not need to duplicate sdhci_remove_host(), just change it so that it
>>> only  disables what was enabled i.e.
>>>
>>>      if (host->vqmmc_enabled)
>>>          regulator_disable(mmc->supply.vqmmc);
>>>
>>
>> Ok, so we will be adding a new flag "vqmmc_enabled" in sdhci_host, ryt ?
> 
> Yes
> 

Ok.
Any particular reason why we are avoiding quirk and instead adding a new 
flag ?

>> Just wanted to clarify
>>
>>>> 2 new functions in sdhci_msm layer which would do the exact same as above,
>>>> with just the regulator parts removed.
>>>>
>>>> This looks messy (considering any future changes to the 2 sdhci API will
>>>> need to be copied to their duplicate sdhci_msm API) and a bit overkill to
>>>> avoid quirk. At the same time, I don't know how useful such a quirk would be
>>>> to other platform drivers.
>>>>
>>>> Please let me know your view/suggestions.
>>>
>>> Let's try without the quirk.
>>>
>>>>>
>>>>>> +            ret = regulator_enable(mmc->supply.vqmmc);
>>>>>> +        else
>>>>>> +            ret = 0;
>>>>>>             if (!regulator_is_supported_voltage(mmc->supply.vqmmc, 1700000,
>>>>>>                                 1950000))
>>>>>>                 host->caps1 &= ~(SDHCI_SUPPORT_SDR104 |
>>>>>> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
>>>>>> index 23966f8..3b0c97a 100644
>>>>>> --- a/drivers/mmc/host/sdhci.h
>>>>>> +++ b/drivers/mmc/host/sdhci.h
>>>>>> @@ -450,6 +450,8 @@ struct sdhci_host {
>>>>>>      * obtainable timeout.
>>>>>>      */
>>>>>>     #define SDHCI_QUIRK2_DISABLE_HW_TIMEOUT            (1<<17)
>>>>>> +/* Regulator voltage changes are being done from platform layer */
>>>>>> +#define SDHCI_QUIRK2_INTERNAL_PWR_CTL                (1<<18)
>>>>>
>>>>> So maybe the quirk is not needed.
>>>>>
>>>>>>           int irq;        /* Device IRQ */
>>>>>>         void __iomem *ioaddr;    /* Mapped address */
>>>>>>
>>>>>
>>>>
>>>> Thanks for the review & suggestions!
>>>> Vijay
>>>>
>>>
>>
> 
> --
> 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
> 

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH RFC 1/2] mmc: sdhci: Allow platform controlled voltage switching
  2018-07-17  9:45             ` Vijay Viswanath
@ 2018-07-17  9:54               ` Adrian Hunter
  2018-07-17 10:22                 ` Vijay Viswanath
  0 siblings, 1 reply; 12+ messages in thread
From: Adrian Hunter @ 2018-07-17  9:54 UTC (permalink / raw)
  To: Vijay Viswanath, ulf.hansson, robh+dt, mark.rutland
  Cc: linux-mmc, linux-kernel, shawn.lin, linux-arm-msm, georgi.djakov,
	devicetree, asutoshd, stummala, venkatg, jeremymc,
	bjorn.andersson, riteshh, vbadigan, dianders, sayalil,
	Evan Green

On 17/07/18 12:45, Vijay Viswanath wrote:
> 
> 
> On 7/17/2018 2:12 PM, Adrian Hunter wrote:
>> On 17/07/18 11:40, Vijay Viswanath wrote:
>>>
>>>
>>> On 7/17/2018 1:00 PM, Adrian Hunter wrote:
>>>> On 17/07/18 08:14, Vijay Viswanath wrote:
>>>>>
>>>>>
>>>>> On 7/10/2018 4:37 PM, Adrian Hunter wrote:
>>>>>> On 21/06/18 15:23, 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.
>>>>>>>
>>>>>>> Add a quirk, which can be used by drivers of such controllers.
>>>>>>>
>>>>>>> Signed-off-by: Vijay Viswanath <vviswana@codeaurora.org>
>>>>>>> ---
>>>>>>>     drivers/mmc/host/sdhci.c | 20 +++++++++++++++-----
>>>>>>>     drivers/mmc/host/sdhci.h |  2 ++
>>>>>>>     2 files changed, 17 insertions(+), 5 deletions(-)
>>>>>>>
>>>>>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>>>>>>> index 1c828e0..f0346d4 100644
>>>>>>> --- a/drivers/mmc/host/sdhci.c
>>>>>>> +++ b/drivers/mmc/host/sdhci.c
>>>>>>> @@ -1615,7 +1615,8 @@ void sdhci_set_power_noreg(struct sdhci_host
>>>>>>> *host,
>>>>>>> unsigned char mode,
>>>>>>>     void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
>>>>>>>                  unsigned short vdd)
>>>>>>>     {
>>>>>>> -    if (IS_ERR(host->mmc->supply.vmmc))
>>>>>>> +    if (IS_ERR(host->mmc->supply.vmmc) ||
>>>>>>> +            (host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL))
>>>>>>
>>>>>> I think you should provide your own ->set_power() instead of this
>>>>>>
>>>>>
>>>>> will do
>>>>>
>>>>>>>             sdhci_set_power_noreg(host, mode, vdd);
>>>>>>>         else
>>>>>>>             sdhci_set_power_reg(host, mode, vdd);
>>>>>>> @@ -2009,7 +2010,9 @@ int sdhci_start_signal_voltage_switch(struct
>>>>>>> mmc_host *mmc,
>>>>>>>             ctrl &= ~SDHCI_CTRL_VDD_180;
>>>>>>>             sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
>>>>>>>     -        if (!IS_ERR(mmc->supply.vqmmc)) {
>>>>>>> +        if (!IS_ERR(mmc->supply.vqmmc) &&
>>>>>>> +                !(host->quirks2 &
>>>>>>> +                    SDHCI_QUIRK2_INTERNAL_PWR_CTL)) {
>>>>>>
>>>>>> And your own ->start_signal_voltage_switch()
>>>>>>
>>>>>
>>>>> sdhci_msm_start_signal_voltage_switch() would be an exact copy of
>>>>> sdhci_start_signal_voltage_switch()..... will incorporate this if not
>>>>> using
>>>>> quirk.
>>>>>
>>>>>>>                 ret = mmc_regulator_set_vqmmc(mmc, ios);
>>>>>>>                 if (ret) {
>>>>>>>                     pr_warn("%s: Switching to 3.3V signalling voltage
>>>>>>> failed\n",
>>>>>>> @@ -2032,7 +2035,8 @@ int sdhci_start_signal_voltage_switch(struct
>>>>>>> mmc_host *mmc,
>>>>>>>         case MMC_SIGNAL_VOLTAGE_180:
>>>>>>>             if (!(host->flags & SDHCI_SIGNALING_180))
>>>>>>>                 return -EINVAL;
>>>>>>> -        if (!IS_ERR(mmc->supply.vqmmc)) {
>>>>>>> +        if (!IS_ERR(mmc->supply.vqmmc) &&
>>>>>>> +            !(host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL)) {
>>>>>>>                 ret = mmc_regulator_set_vqmmc(mmc, ios);
>>>>>>>                 if (ret) {
>>>>>>>                     pr_warn("%s: Switching to 1.8V signalling voltage
>>>>>>> failed\n",
>>>>>>> @@ -3485,7 +3489,10 @@ 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 (!(host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL))
>>>>>>
>>>>>> Since we expect mmc_regulator_get_supply() to have been called, this
>>>>>> could
>>>>>> be:
>>>>>>
>>>>>>       if (!mmc->supply.vmmc) {
>>>>>>           ret = mmc_regulator_get_supply(mmc);
>>>>>>           enable_vqmmc = true;
>>>>>>       } else {
>>>>>>           ret = 0;
>>>>>>       }
>>>>>>>> +        ret = mmc_regulator_get_supply(mmc);
>>>>>>> +    else
>>>>>>> +        ret = 0;
>>>>>>>         if (ret)
>>>>>>>             return ret;
>>>>>>>     @@ -3736,7 +3743,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 (!(host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL))
>>>>>>
>>>>>> And this could be:
>>>>>>
>>>>>>           if (enable_vqmmc)
>>>>>>               ret = regulator_enable(mmc->supply.vqmmc);
>>>>>>           else
>>>>>>               ret = 0;
>>>>>>    > However, you still need to ensure
>>>>>> regulator_disable(mmc->supply.vqmmc) is
>>>>>> only called if regulator_enable() was called.
>>>>> I missed this. Will cover it.
>>>>>
>>>>> Also I missed one more place where we are doing regulator_disable. During
>>>>> sdhci-msm unbinding, we would end up doing an extra regulator disable
>>>>> (thanks Evan for pointing it out) in sdhci_remove_host.
>>>>>
>>>>> To avoid the quirk( or having any flag), it would require copying the code
>>>>> of sdhci_start_signal_voltage_switch() and sdhci_remove_host() and
>>>>> creating
>>>>
>>>> You do not need to duplicate sdhci_remove_host(), just change it so that it
>>>> only  disables what was enabled i.e.
>>>>
>>>>      if (host->vqmmc_enabled)
>>>>          regulator_disable(mmc->supply.vqmmc);
>>>>
>>>
>>> Ok, so we will be adding a new flag "vqmmc_enabled" in sdhci_host, ryt ?
>>
>> Yes
>>
> 
> Ok.
> Any particular reason why we are avoiding quirk and instead adding a new flag ?

It moves more in the direction of letting drivers do what they want, rather
than trying to make making SDHCI do everything.

> 
>>> Just wanted to clarify
>>>
>>>>> 2 new functions in sdhci_msm layer which would do the exact same as above,
>>>>> with just the regulator parts removed.
>>>>>
>>>>> This looks messy (considering any future changes to the 2 sdhci API will
>>>>> need to be copied to their duplicate sdhci_msm API) and a bit overkill to
>>>>> avoid quirk. At the same time, I don't know how useful such a quirk
>>>>> would be
>>>>> to other platform drivers.
>>>>>
>>>>> Please let me know your view/suggestions.
>>>>
>>>> Let's try without the quirk.
>>>>
>>>>>>
>>>>>>> +            ret = regulator_enable(mmc->supply.vqmmc);
>>>>>>> +        else
>>>>>>> +            ret = 0;
>>>>>>>             if (!regulator_is_supported_voltage(mmc->supply.vqmmc,
>>>>>>> 1700000,
>>>>>>>                                 1950000))
>>>>>>>                 host->caps1 &= ~(SDHCI_SUPPORT_SDR104 |
>>>>>>> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
>>>>>>> index 23966f8..3b0c97a 100644
>>>>>>> --- a/drivers/mmc/host/sdhci.h
>>>>>>> +++ b/drivers/mmc/host/sdhci.h
>>>>>>> @@ -450,6 +450,8 @@ struct sdhci_host {
>>>>>>>      * obtainable timeout.
>>>>>>>      */
>>>>>>>     #define SDHCI_QUIRK2_DISABLE_HW_TIMEOUT            (1<<17)
>>>>>>> +/* Regulator voltage changes are being done from platform layer */
>>>>>>> +#define SDHCI_QUIRK2_INTERNAL_PWR_CTL                (1<<18)
>>>>>>
>>>>>> So maybe the quirk is not needed.
>>>>>>
>>>>>>>           int irq;        /* Device IRQ */
>>>>>>>         void __iomem *ioaddr;    /* Mapped address */
>>>>>>>
>>>>>>
>>>>>
>>>>> Thanks for the review & suggestions!
>>>>> Vijay
>>>>>
>>>>
>>>
>>
>> -- 
>> 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
>>
> 


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH RFC 1/2] mmc: sdhci: Allow platform controlled voltage switching
  2018-07-17  9:54               ` Adrian Hunter
@ 2018-07-17 10:22                 ` Vijay Viswanath
  0 siblings, 0 replies; 12+ messages in thread
From: Vijay Viswanath @ 2018-07-17 10:22 UTC (permalink / raw)
  To: Adrian Hunter, ulf.hansson, robh+dt, mark.rutland
  Cc: linux-mmc, linux-kernel, shawn.lin, linux-arm-msm, georgi.djakov,
	devicetree, asutoshd, stummala, venkatg, jeremymc,
	bjorn.andersson, riteshh, vbadigan, dianders, sayalil,
	Evan Green



On 7/17/2018 3:24 PM, Adrian Hunter wrote:
> On 17/07/18 12:45, Vijay Viswanath wrote:
>>
>>
>> On 7/17/2018 2:12 PM, Adrian Hunter wrote:
>>> On 17/07/18 11:40, Vijay Viswanath wrote:
>>>>
>>>>
>>>> On 7/17/2018 1:00 PM, Adrian Hunter wrote:
>>>>> On 17/07/18 08:14, Vijay Viswanath wrote:
>>>>>>
>>>>>>
>>>>>> On 7/10/2018 4:37 PM, Adrian Hunter wrote:
>>>>>>> On 21/06/18 15:23, 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.
>>>>>>>>
>>>>>>>> Add a quirk, which can be used by drivers of such controllers.
>>>>>>>>
>>>>>>>> Signed-off-by: Vijay Viswanath <vviswana@codeaurora.org>
>>>>>>>> ---
>>>>>>>>      drivers/mmc/host/sdhci.c | 20 +++++++++++++++-----
>>>>>>>>      drivers/mmc/host/sdhci.h |  2 ++
>>>>>>>>      2 files changed, 17 insertions(+), 5 deletions(-)
>>>>>>>>
>>>>>>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>>>>>>>> index 1c828e0..f0346d4 100644
>>>>>>>> --- a/drivers/mmc/host/sdhci.c
>>>>>>>> +++ b/drivers/mmc/host/sdhci.c
>>>>>>>> @@ -1615,7 +1615,8 @@ void sdhci_set_power_noreg(struct sdhci_host
>>>>>>>> *host,
>>>>>>>> unsigned char mode,
>>>>>>>>      void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
>>>>>>>>                   unsigned short vdd)
>>>>>>>>      {
>>>>>>>> -    if (IS_ERR(host->mmc->supply.vmmc))
>>>>>>>> +    if (IS_ERR(host->mmc->supply.vmmc) ||
>>>>>>>> +            (host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL))
>>>>>>>
>>>>>>> I think you should provide your own ->set_power() instead of this
>>>>>>>
>>>>>>
>>>>>> will do
>>>>>>
>>>>>>>>              sdhci_set_power_noreg(host, mode, vdd);
>>>>>>>>          else
>>>>>>>>              sdhci_set_power_reg(host, mode, vdd);
>>>>>>>> @@ -2009,7 +2010,9 @@ int sdhci_start_signal_voltage_switch(struct
>>>>>>>> mmc_host *mmc,
>>>>>>>>              ctrl &= ~SDHCI_CTRL_VDD_180;
>>>>>>>>              sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
>>>>>>>>      -        if (!IS_ERR(mmc->supply.vqmmc)) {
>>>>>>>> +        if (!IS_ERR(mmc->supply.vqmmc) &&
>>>>>>>> +                !(host->quirks2 &
>>>>>>>> +                    SDHCI_QUIRK2_INTERNAL_PWR_CTL)) {
>>>>>>>
>>>>>>> And your own ->start_signal_voltage_switch()
>>>>>>>
>>>>>>
>>>>>> sdhci_msm_start_signal_voltage_switch() would be an exact copy of
>>>>>> sdhci_start_signal_voltage_switch()..... will incorporate this if not
>>>>>> using
>>>>>> quirk.
>>>>>>
>>>>>>>>                  ret = mmc_regulator_set_vqmmc(mmc, ios);
>>>>>>>>                  if (ret) {
>>>>>>>>                      pr_warn("%s: Switching to 3.3V signalling voltage
>>>>>>>> failed\n",
>>>>>>>> @@ -2032,7 +2035,8 @@ int sdhci_start_signal_voltage_switch(struct
>>>>>>>> mmc_host *mmc,
>>>>>>>>          case MMC_SIGNAL_VOLTAGE_180:
>>>>>>>>              if (!(host->flags & SDHCI_SIGNALING_180))
>>>>>>>>                  return -EINVAL;
>>>>>>>> -        if (!IS_ERR(mmc->supply.vqmmc)) {
>>>>>>>> +        if (!IS_ERR(mmc->supply.vqmmc) &&
>>>>>>>> +            !(host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL)) {
>>>>>>>>                  ret = mmc_regulator_set_vqmmc(mmc, ios);
>>>>>>>>                  if (ret) {
>>>>>>>>                      pr_warn("%s: Switching to 1.8V signalling voltage
>>>>>>>> failed\n",
>>>>>>>> @@ -3485,7 +3489,10 @@ 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 (!(host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL))
>>>>>>>
>>>>>>> Since we expect mmc_regulator_get_supply() to have been called, this
>>>>>>> could
>>>>>>> be:
>>>>>>>
>>>>>>>        if (!mmc->supply.vmmc) {
>>>>>>>            ret = mmc_regulator_get_supply(mmc);
>>>>>>>            enable_vqmmc = true;
>>>>>>>        } else {
>>>>>>>            ret = 0;
>>>>>>>        }
>>>>>>>>> +        ret = mmc_regulator_get_supply(mmc);
>>>>>>>> +    else
>>>>>>>> +        ret = 0;
>>>>>>>>          if (ret)
>>>>>>>>              return ret;
>>>>>>>>      @@ -3736,7 +3743,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 (!(host->quirks2 & SDHCI_QUIRK2_INTERNAL_PWR_CTL))
>>>>>>>
>>>>>>> And this could be:
>>>>>>>
>>>>>>>            if (enable_vqmmc)
>>>>>>>                ret = regulator_enable(mmc->supply.vqmmc);
>>>>>>>            else
>>>>>>>                ret = 0;
>>>>>>>     > However, you still need to ensure
>>>>>>> regulator_disable(mmc->supply.vqmmc) is
>>>>>>> only called if regulator_enable() was called.
>>>>>> I missed this. Will cover it.
>>>>>>
>>>>>> Also I missed one more place where we are doing regulator_disable. During
>>>>>> sdhci-msm unbinding, we would end up doing an extra regulator disable
>>>>>> (thanks Evan for pointing it out) in sdhci_remove_host.
>>>>>>
>>>>>> To avoid the quirk( or having any flag), it would require copying the code
>>>>>> of sdhci_start_signal_voltage_switch() and sdhci_remove_host() and
>>>>>> creating
>>>>>
>>>>> You do not need to duplicate sdhci_remove_host(), just change it so that it
>>>>> only  disables what was enabled i.e.
>>>>>
>>>>>       if (host->vqmmc_enabled)
>>>>>           regulator_disable(mmc->supply.vqmmc);
>>>>>
>>>>
>>>> Ok, so we will be adding a new flag "vqmmc_enabled" in sdhci_host, ryt ?
>>>
>>> Yes
>>>
>>
>> Ok.
>> Any particular reason why we are avoiding quirk and instead adding a new flag ?
> 
> It moves more in the direction of letting drivers do what they want, rather
> than trying to make making SDHCI do everything.
> 

ok will incorporate the changes in next version.

>>
>>>> Just wanted to clarify
>>>>
>>>>>> 2 new functions in sdhci_msm layer which would do the exact same as above,
>>>>>> with just the regulator parts removed.
>>>>>>
>>>>>> This looks messy (considering any future changes to the 2 sdhci API will
>>>>>> need to be copied to their duplicate sdhci_msm API) and a bit overkill to
>>>>>> avoid quirk. At the same time, I don't know how useful such a quirk
>>>>>> would be
>>>>>> to other platform drivers.
>>>>>>
>>>>>> Please let me know your view/suggestions.
>>>>>
>>>>> Let's try without the quirk.
>>>>>
>>>>>>>
>>>>>>>> +            ret = regulator_enable(mmc->supply.vqmmc);
>>>>>>>> +        else
>>>>>>>> +            ret = 0;
>>>>>>>>              if (!regulator_is_supported_voltage(mmc->supply.vqmmc,
>>>>>>>> 1700000,
>>>>>>>>                                  1950000))
>>>>>>>>                  host->caps1 &= ~(SDHCI_SUPPORT_SDR104 |
>>>>>>>> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
>>>>>>>> index 23966f8..3b0c97a 100644
>>>>>>>> --- a/drivers/mmc/host/sdhci.h
>>>>>>>> +++ b/drivers/mmc/host/sdhci.h
>>>>>>>> @@ -450,6 +450,8 @@ struct sdhci_host {
>>>>>>>>       * obtainable timeout.
>>>>>>>>       */
>>>>>>>>      #define SDHCI_QUIRK2_DISABLE_HW_TIMEOUT            (1<<17)
>>>>>>>> +/* Regulator voltage changes are being done from platform layer */
>>>>>>>> +#define SDHCI_QUIRK2_INTERNAL_PWR_CTL                (1<<18)
>>>>>>>
>>>>>>> So maybe the quirk is not needed.
>>>>>>>
>>>>>>>>            int irq;        /* Device IRQ */
>>>>>>>>          void __iomem *ioaddr;    /* Mapped address */
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>> Thanks for the review & suggestions!
>>>>>> Vijay
>>>>>>
>>>>>
>>>>
>>>
>>> -- 
>>> 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

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2018-07-17 10:22 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-06-21 12:23 [PATCH RFC 0/2] Internal voltage control for platform drivers Vijay Viswanath
2018-06-21 12:23 ` [PATCH RFC 1/2] mmc: sdhci: Allow platform controlled voltage switching Vijay Viswanath
2018-07-10 11:07   ` Adrian Hunter
2018-07-17  5:14     ` Vijay Viswanath
2018-07-17  7:30       ` Adrian Hunter
2018-07-17  8:40         ` Vijay Viswanath
2018-07-17  8:42           ` Adrian Hunter
2018-07-17  9:45             ` Vijay Viswanath
2018-07-17  9:54               ` Adrian Hunter
2018-07-17 10:22                 ` Vijay Viswanath
2018-06-21 12:23 ` [PATCH RFC 2/2] mmc: sdhci-msm: Use internal voltage control Vijay Viswanath
2018-07-10 11:26   ` Adrian Hunter

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).