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

2018-07-25 Thread Vijay Viswanath

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 
---
  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, 170,
195))
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(>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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html



Thanks,
Vijay


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

2018-07-25 Thread Vijay Viswanath

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 
---
  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, 170,
195))
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(>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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html



Thanks,
Vijay


Re: [PATCH RFC 2/7] mmc: core: devfreq: Add devfreq based clock scaling support

2018-07-23 Thread Vijay Viswanath

Hi Sayali,

On 7/13/2018 3:22 PM, Sayali Lokhande wrote:

This change adds the use of devfreq to MMC.
Both eMMC and SD card will use it.
For some workloads, such as video playback, it isn't
necessary for these cards to run at high speed.
Running at lower frequency, for example 52MHz, in such
cases can still meet the deadlines for data transfers.
Scaling down the clock frequency dynamically has power
savings not only because the bus is running at lower frequency
but also has an advantage of scaling down the system core
voltage, if supported.
Provide an ondemand clock scaling support similar to the
cpufreq ondemand governor having two thresholds,
up_threshold and down_threshold to decide whether to
increase the frequency or scale it down respectively.
The sampling interval is in the order of milliseconds.
If sampling interval is too low, frequent switching of
frequencies can lead to high power consumption and if
sampling interval is too high, the clock scaling logic
would take long time to realize that the underlying
hardware (controller and card) is busy and scale up
the clocks.

Signed-off-by: Talel Shenhar 
Signed-off-by: Sayali Lokhande 
---
  .../devicetree/bindings/mmc/sdhci-msm.txt  |  10 +
  drivers/mmc/core/core.c| 560 +
  drivers/mmc/core/core.h|   7 +
  drivers/mmc/core/debugfs.c |  46 ++
  drivers/mmc/core/host.c|   8 +
  drivers/mmc/core/mmc.c | 200 +++-
  drivers/mmc/core/sd.c  |  72 ++-
  drivers/mmc/host/sdhci-msm.c   |  37 ++
  drivers/mmc/host/sdhci-pltfm.c |  11 +
  drivers/mmc/host/sdhci.c   |  27 +
  drivers/mmc/host/sdhci.h   |   8 +
  include/linux/mmc/card.h   |   5 +
  include/linux/mmc/host.h   |  70 +++
  13 files changed, 1059 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt 
b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
index 502b3b8..bd8470a 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
@@ -26,6 +26,15 @@ Required properties:
"cal" - reference clock for RCLK delay calibration (optional)
"sleep"   - sleep clock for RCLK delay calibration (optional)
  
+Optional Properties:

+- qcom,devfreq,freq-table - specifies supported frequencies for clock scaling.
+   Clock scaling logic shall toggle between 
these frequencies based
+   on card load. In case the defined 
frequencies are over or below
+   the supported card frequencies, they will 
be overridden
+   during card init. In case this entry is not 
supplied,
+   the driver will construct one based on the 
card
+   supported max and min frequencies.
+   The frequencies must be ordered from lowest 
to highest.
  Example:
  
  	sdhc_1: sdhci@f9824900 {

@@ -43,6 +52,7 @@ Example:
  
  		clocks = < GCC_SDCC1_APPS_CLK>, < GCC_SDCC1_AHB_CLK>;

clock-names = "core", "iface";
+   qcom,devfreq,freq-table = <5200 2>;
};
  
  	sdhc_2: sdhci@f98a4900 {

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 281826d..0eaee42 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -14,6 +14,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 
  #include 
@@ -112,6 +113,556 @@ static inline void mmc_should_fail_request(struct 
mmc_host *host,
  
  #endif /* CONFIG_FAIL_MMC_REQUEST */
  
+static bool mmc_is_data_request(struct mmc_request *mmc_request)

+{
+   switch (mmc_request->cmd->opcode) {
+   case MMC_READ_SINGLE_BLOCK:
+   case MMC_READ_MULTIPLE_BLOCK:
+   case MMC_WRITE_BLOCK:
+   case MMC_WRITE_MULTIPLE_BLOCK:
+   return true;
+   default:
+   return false;
+   }
+}
+
+static void mmc_clk_scaling_start_busy(struct mmc_host *host, bool lock_needed)
+{
+   struct mmc_devfeq_clk_scaling *clk_scaling = >clk_scaling;
+
+   if (!clk_scaling->enable)
+   return;
+
+   if (lock_needed)
+   spin_lock_bh(_scaling->lock);
+
+   clk_scaling->start_busy = ktime_get();
+   clk_scaling->is_busy_started = true;
+
+   if (lock_needed)
+   spin_unlock_bh(_scaling->lock);
+}
+
+static void mmc_clk_scaling_stop_busy(struct mmc_host *host, bool lock_needed)
+{
+   struct mmc_devfeq_clk_scaling *clk_scaling = >clk_scaling;
+
+   if (!clk_scaling->enable)
+   return;
+
+   if (lock_needed)
+   

Re: [PATCH RFC 2/7] mmc: core: devfreq: Add devfreq based clock scaling support

2018-07-23 Thread Vijay Viswanath

Hi Sayali,

On 7/13/2018 3:22 PM, Sayali Lokhande wrote:

This change adds the use of devfreq to MMC.
Both eMMC and SD card will use it.
For some workloads, such as video playback, it isn't
necessary for these cards to run at high speed.
Running at lower frequency, for example 52MHz, in such
cases can still meet the deadlines for data transfers.
Scaling down the clock frequency dynamically has power
savings not only because the bus is running at lower frequency
but also has an advantage of scaling down the system core
voltage, if supported.
Provide an ondemand clock scaling support similar to the
cpufreq ondemand governor having two thresholds,
up_threshold and down_threshold to decide whether to
increase the frequency or scale it down respectively.
The sampling interval is in the order of milliseconds.
If sampling interval is too low, frequent switching of
frequencies can lead to high power consumption and if
sampling interval is too high, the clock scaling logic
would take long time to realize that the underlying
hardware (controller and card) is busy and scale up
the clocks.

Signed-off-by: Talel Shenhar 
Signed-off-by: Sayali Lokhande 
---
  .../devicetree/bindings/mmc/sdhci-msm.txt  |  10 +
  drivers/mmc/core/core.c| 560 +
  drivers/mmc/core/core.h|   7 +
  drivers/mmc/core/debugfs.c |  46 ++
  drivers/mmc/core/host.c|   8 +
  drivers/mmc/core/mmc.c | 200 +++-
  drivers/mmc/core/sd.c  |  72 ++-
  drivers/mmc/host/sdhci-msm.c   |  37 ++
  drivers/mmc/host/sdhci-pltfm.c |  11 +
  drivers/mmc/host/sdhci.c   |  27 +
  drivers/mmc/host/sdhci.h   |   8 +
  include/linux/mmc/card.h   |   5 +
  include/linux/mmc/host.h   |  70 +++
  13 files changed, 1059 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt 
b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
index 502b3b8..bd8470a 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
@@ -26,6 +26,15 @@ Required properties:
"cal" - reference clock for RCLK delay calibration (optional)
"sleep"   - sleep clock for RCLK delay calibration (optional)
  
+Optional Properties:

+- qcom,devfreq,freq-table - specifies supported frequencies for clock scaling.
+   Clock scaling logic shall toggle between 
these frequencies based
+   on card load. In case the defined 
frequencies are over or below
+   the supported card frequencies, they will 
be overridden
+   during card init. In case this entry is not 
supplied,
+   the driver will construct one based on the 
card
+   supported max and min frequencies.
+   The frequencies must be ordered from lowest 
to highest.
  Example:
  
  	sdhc_1: sdhci@f9824900 {

@@ -43,6 +52,7 @@ Example:
  
  		clocks = < GCC_SDCC1_APPS_CLK>, < GCC_SDCC1_AHB_CLK>;

clock-names = "core", "iface";
+   qcom,devfreq,freq-table = <5200 2>;
};
  
  	sdhc_2: sdhci@f98a4900 {

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 281826d..0eaee42 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -14,6 +14,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 
  #include 
@@ -112,6 +113,556 @@ static inline void mmc_should_fail_request(struct 
mmc_host *host,
  
  #endif /* CONFIG_FAIL_MMC_REQUEST */
  
+static bool mmc_is_data_request(struct mmc_request *mmc_request)

+{
+   switch (mmc_request->cmd->opcode) {
+   case MMC_READ_SINGLE_BLOCK:
+   case MMC_READ_MULTIPLE_BLOCK:
+   case MMC_WRITE_BLOCK:
+   case MMC_WRITE_MULTIPLE_BLOCK:
+   return true;
+   default:
+   return false;
+   }
+}
+
+static void mmc_clk_scaling_start_busy(struct mmc_host *host, bool lock_needed)
+{
+   struct mmc_devfeq_clk_scaling *clk_scaling = >clk_scaling;
+
+   if (!clk_scaling->enable)
+   return;
+
+   if (lock_needed)
+   spin_lock_bh(_scaling->lock);
+
+   clk_scaling->start_busy = ktime_get();
+   clk_scaling->is_busy_started = true;
+
+   if (lock_needed)
+   spin_unlock_bh(_scaling->lock);
+}
+
+static void mmc_clk_scaling_stop_busy(struct mmc_host *host, bool lock_needed)
+{
+   struct mmc_devfeq_clk_scaling *clk_scaling = >clk_scaling;
+
+   if (!clk_scaling->enable)
+   return;
+
+   if (lock_needed)
+   

[PATCH V1 3/3] mmc: sdhci-msm: Use internal voltage control

2018-07-20 Thread Vijay Viswanath
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: Asutosh Das 
Signed-off-by: Venkat Gopalakrishnan 
Signed-off-by: Veerabhadrarao Badiganti 
Signed-off-by: Vijay Viswanath 
---
 drivers/mmc/host/sdhci-msm.c | 220 ---
 1 file changed, 209 insertions(+), 11 deletions(-)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index a0dc3e1..47732a2 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_HIGHBIT(3)
 #define CORE_PWRCTL_BUS_SUCCESS BIT(0)
+#define CORE_PWRCTL_BUS_FAILBIT(1)
 #define CORE_PWRCTL_IO_SUCCESS BIT(2)
+#define CORE_PWRCTL_IO_FAIL BIT(3)
 #define REQ_BUS_OFFBIT(0)
 #define REQ_BUS_ON BIT(1)
 #define REQ_IO_LOW BIT(2)
@@ -236,6 +238,14 @@ struct sdhci_msm_variant_info {
const struct sdhci_msm_offset *offset;
 };
 
+/* Holds voltage regulator information to be used by the driver*/
+struct sdhci_msm_vreg_info {
+   bool vmmc_load;
+   u32 vmmc_level[2];
+   bool vqmmc_load;
+   u32 vqmmc_level[2];
+};
+
 struct sdhci_msm_host {
struct platform_device *pdev;
void __iomem *core_mem; /* MSM SDCC mapped address */
@@ -258,6 +268,8 @@ struct sdhci_msm_host {
bool mci_removed;
const struct sdhci_msm_variant_ops *var_ops;
const struct sdhci_msm_offset *offset;
+   struct sdhci_msm_vreg_info vreg_info;
+   bool pltfm_init_done;
 };
 
 static const struct sdhci_msm_offset *sdhci_priv_msm_offset(struct sdhci_host 
*host)
@@ -1314,11 +1326,13 @@ 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;
+   struct sdhci_msm_vreg_info vreg_info = msm_host->vreg_info;
 
irq_status = msm_host_readl(msm_host, host,
msm_offset->core_pwrctl_status);
@@ -1351,14 +1365,91 @@ 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 (!IS_ERR(mmc->supply.vmmc)) {
+   if (vreg_info.vmmc_load)
+   ret = regulator_set_load(mmc->supply.vmmc,
+   vreg_info.vmmc_level[1]);
+   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 (!IS_ERR(mmc->supply.vqmmc) && !ret) {
+   struct mmc_ios ios;
+
+   if (vreg_info.vqmmc_load)
+   ret = regulator_set_load(mmc->supply.vqmmc,
+   vreg_info.vqmmc_level[1]);
+   /*
+* The IO voltage regulator maynot always support
+* a voltage close to vdd. Set IO voltage based on
+* capability of the regulator.
+*/
+   if (msm_host->caps_0 & CORE_3_0V_SUPPORT)
+   ios.signal_voltage = MMC_SIGNAL_VOLTAGE_330;
+   else if (msm_host->caps_0 & CORE_1_8V_SUPPORT)
+   ios.signal_voltage = MMC_SIGNAL_VOLTAGE_180;
+   if (msm_host->caps_0 & CORE_VOLT_SUPPORT) {
+   pr_err("%s: %s: setting signal voltage: %d\n",
+   mmc_hostname(mmc), __func__,
+   ios.signal_voltage);
+   ret |= mmc_regulator_set_vqmmc(mmc, );
+   }
+
+   if (!ret)
+   ret = regulator_enable(mmc->supply.vqmmc);
+   if (ret)
+   pr_err("%s: vqmmc e

[PATCH V1 3/3] mmc: sdhci-msm: Use internal voltage control

2018-07-20 Thread Vijay Viswanath
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: Asutosh Das 
Signed-off-by: Venkat Gopalakrishnan 
Signed-off-by: Veerabhadrarao Badiganti 
Signed-off-by: Vijay Viswanath 
---
 drivers/mmc/host/sdhci-msm.c | 220 ---
 1 file changed, 209 insertions(+), 11 deletions(-)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index a0dc3e1..47732a2 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_HIGHBIT(3)
 #define CORE_PWRCTL_BUS_SUCCESS BIT(0)
+#define CORE_PWRCTL_BUS_FAILBIT(1)
 #define CORE_PWRCTL_IO_SUCCESS BIT(2)
+#define CORE_PWRCTL_IO_FAIL BIT(3)
 #define REQ_BUS_OFFBIT(0)
 #define REQ_BUS_ON BIT(1)
 #define REQ_IO_LOW BIT(2)
@@ -236,6 +238,14 @@ struct sdhci_msm_variant_info {
const struct sdhci_msm_offset *offset;
 };
 
+/* Holds voltage regulator information to be used by the driver*/
+struct sdhci_msm_vreg_info {
+   bool vmmc_load;
+   u32 vmmc_level[2];
+   bool vqmmc_load;
+   u32 vqmmc_level[2];
+};
+
 struct sdhci_msm_host {
struct platform_device *pdev;
void __iomem *core_mem; /* MSM SDCC mapped address */
@@ -258,6 +268,8 @@ struct sdhci_msm_host {
bool mci_removed;
const struct sdhci_msm_variant_ops *var_ops;
const struct sdhci_msm_offset *offset;
+   struct sdhci_msm_vreg_info vreg_info;
+   bool pltfm_init_done;
 };
 
 static const struct sdhci_msm_offset *sdhci_priv_msm_offset(struct sdhci_host 
*host)
@@ -1314,11 +1326,13 @@ 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;
+   struct sdhci_msm_vreg_info vreg_info = msm_host->vreg_info;
 
irq_status = msm_host_readl(msm_host, host,
msm_offset->core_pwrctl_status);
@@ -1351,14 +1365,91 @@ 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 (!IS_ERR(mmc->supply.vmmc)) {
+   if (vreg_info.vmmc_load)
+   ret = regulator_set_load(mmc->supply.vmmc,
+   vreg_info.vmmc_level[1]);
+   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 (!IS_ERR(mmc->supply.vqmmc) && !ret) {
+   struct mmc_ios ios;
+
+   if (vreg_info.vqmmc_load)
+   ret = regulator_set_load(mmc->supply.vqmmc,
+   vreg_info.vqmmc_level[1]);
+   /*
+* The IO voltage regulator maynot always support
+* a voltage close to vdd. Set IO voltage based on
+* capability of the regulator.
+*/
+   if (msm_host->caps_0 & CORE_3_0V_SUPPORT)
+   ios.signal_voltage = MMC_SIGNAL_VOLTAGE_330;
+   else if (msm_host->caps_0 & CORE_1_8V_SUPPORT)
+   ios.signal_voltage = MMC_SIGNAL_VOLTAGE_180;
+   if (msm_host->caps_0 & CORE_VOLT_SUPPORT) {
+   pr_err("%s: %s: setting signal voltage: %d\n",
+   mmc_hostname(mmc), __func__,
+   ios.signal_voltage);
+   ret |= mmc_regulator_set_vqmmc(mmc, );
+   }
+
+   if (!ret)
+   ret = regulator_enable(mmc->supply.vqmmc);
+   if (ret)
+   pr_err("%s: vqmmc e

[PATCH V1 2/3] Documentation: sdhci-msm: Add entries for passing load values

2018-07-20 Thread Vijay Viswanath
The load a particular sdhc controller should request from a regulator
is device specific and hence each device should individually vote for
the required load.

Signed-off-by: Vijay Viswanath 
---
 Documentation/devicetree/bindings/mmc/sdhci-msm.txt | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt 
b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
index 502b3b8..ee34f28 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
@@ -26,6 +26,11 @@ Required properties:
"cal"   - reference clock for RCLK delay calibration (optional)
"sleep" - sleep clock for RCLK delay calibration (optional)
 
+Optional properties:
+- -current-level - specifies load levels for supply during BUS_ON
+   and BUS_OFF states in power irq. Should be specified in
+   pairs (lpm, hpm), for BUS_OFF and BUS_ON respectively.
+   Units uA.
 Example:
 
sdhc_1: sdhci@f9824900 {
@@ -37,6 +42,7 @@ Example:
 
vmmc-supply = <_l20>;
vqmmc-supply = <_s3>;
+   vqmmc-current-level = <200 22000>;
 
pinctrl-names = "default";
pinctrl-0 = <_clk _cmd _data>;
-- 
 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.



[PATCH V1 2/3] Documentation: sdhci-msm: Add entries for passing load values

2018-07-20 Thread Vijay Viswanath
The load a particular sdhc controller should request from a regulator
is device specific and hence each device should individually vote for
the required load.

Signed-off-by: Vijay Viswanath 
---
 Documentation/devicetree/bindings/mmc/sdhci-msm.txt | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt 
b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
index 502b3b8..ee34f28 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
@@ -26,6 +26,11 @@ Required properties:
"cal"   - reference clock for RCLK delay calibration (optional)
"sleep" - sleep clock for RCLK delay calibration (optional)
 
+Optional properties:
+- -current-level - specifies load levels for supply during BUS_ON
+   and BUS_OFF states in power irq. Should be specified in
+   pairs (lpm, hpm), for BUS_OFF and BUS_ON respectively.
+   Units uA.
 Example:
 
sdhc_1: sdhci@f9824900 {
@@ -37,6 +42,7 @@ Example:
 
vmmc-supply = <_l20>;
vqmmc-supply = <_s3>;
+   vqmmc-current-level = <200 22000>;
 
pinctrl-names = "default";
pinctrl-0 = <_clk _cmd _data>;
-- 
 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.



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

2018-07-20 Thread Vijay Viswanath
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 
---
 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;
 
@@ -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, 170,
195))
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(>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)
-- 
 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.



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

2018-07-20 Thread Vijay Viswanath
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 
---
 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;
 
@@ -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, 170,
195))
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(>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)
-- 
 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.



[PATCH V1 0/3] Internal voltage control for platform drivers

2018-07-20 Thread Vijay Viswanath
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.

Changes since RFC:
- Added DT option to pass regulator load values the sdhci-msm driver
should vote during BUS_ON and BUS_OFF power irq.
- Removed quirk and used local flags in sdhci_add_host to to avoid
scenario of both sdhci & sdhci-msm layer controlling the regulators.
- Introduced two sdhci msm layer APIs to replace the respective
sdhci layer APIs. This is again to stop sdhci layer from
controlling regulators if sdhci_msm layer is present.

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

Vijay Viswanath (3):
  mmc: sdhci: Allow platform controlled voltage switching
  Documentation: sdhci-msm: Add entries for passing load values
  mmc: sdhci-msm: Use internal voltage control

 .../devicetree/bindings/mmc/sdhci-msm.txt  |   6 +
 drivers/mmc/host/sdhci-msm.c   | 220 +++--
 drivers/mmc/host/sdhci.c   |  21 +-
 3 files changed, 231 insertions(+), 16 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.



[PATCH V1 0/3] Internal voltage control for platform drivers

2018-07-20 Thread Vijay Viswanath
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.

Changes since RFC:
- Added DT option to pass regulator load values the sdhci-msm driver
should vote during BUS_ON and BUS_OFF power irq.
- Removed quirk and used local flags in sdhci_add_host to to avoid
scenario of both sdhci & sdhci-msm layer controlling the regulators.
- Introduced two sdhci msm layer APIs to replace the respective
sdhci layer APIs. This is again to stop sdhci layer from
controlling regulators if sdhci_msm layer is present.

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

Vijay Viswanath (3):
  mmc: sdhci: Allow platform controlled voltage switching
  Documentation: sdhci-msm: Add entries for passing load values
  mmc: sdhci-msm: Use internal voltage control

 .../devicetree/bindings/mmc/sdhci-msm.txt  |   6 +
 drivers/mmc/host/sdhci-msm.c   | 220 +++--
 drivers/mmc/host/sdhci.c   |  21 +-
 3 files changed, 231 insertions(+), 16 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.



Re: [PATCH RFC 1/2] mmc: sdhci: Allow platform controlled voltage switching

2018-07-17 Thread Vijay Viswanath




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 
---
     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 mak

Re: [PATCH RFC 1/2] mmc: sdhci: Allow platform controlled voltage switching

2018-07-17 Thread Vijay Viswanath




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 
---
     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 mak

Re: [PATCH RFC 1/2] mmc: sdhci: Allow platform controlled voltage switching

2018-07-17 Thread Vijay Viswanath




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 
---
    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 co

Re: [PATCH RFC 1/2] mmc: sdhci: Allow platform controlled voltage switching

2018-07-17 Thread Vijay Viswanath




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 
---
    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 co

Re: [PATCH RFC 1/2] mmc: sdhci: Allow platform controlled voltage switching

2018-07-17 Thread Vijay Viswanath




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 
---
   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 yo

Re: [PATCH RFC 1/2] mmc: sdhci: Allow platform controlled voltage switching

2018-07-17 Thread Vijay Viswanath




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 
---
   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 yo

Re: [PATCH RFC 1/2] mmc: sdhci: Allow platform controlled voltage switching

2018-07-16 Thread Vijay Viswanath




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 
---
  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.v

Re: [PATCH RFC 1/2] mmc: sdhci: Allow platform controlled voltage switching

2018-07-16 Thread Vijay Viswanath




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 
---
  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.v

[PATCH RFC 2/2] mmc: sdhci-msm: Use internal voltage control

2018-06-21 Thread Vijay Viswanath
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 
---
 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_HIGHBIT(3)
 #define CORE_PWRCTL_BUS_SUCCESS BIT(0)
+#define CORE_PWRCTL_BUS_FAILBIT(1)
 #define CORE_PWRCTL_IO_SUCCESS BIT(2)
+#define CORE_PWRCTL_IO_FAIL BIT(3)
 #define REQ_BUS_OFFBIT(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, 80);
+   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;
+   } el

[PATCH RFC 2/2] mmc: sdhci-msm: Use internal voltage control

2018-06-21 Thread Vijay Viswanath
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 
---
 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_HIGHBIT(3)
 #define CORE_PWRCTL_BUS_SUCCESS BIT(0)
+#define CORE_PWRCTL_BUS_FAILBIT(1)
 #define CORE_PWRCTL_IO_SUCCESS BIT(2)
+#define CORE_PWRCTL_IO_FAIL BIT(3)
 #define REQ_BUS_OFFBIT(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, 80);
+   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;
+   } el

[PATCH RFC 0/2] Internal voltage control for platform drivers

2018-06-21 Thread Vijay Viswanath
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.



[PATCH RFC 1/2] mmc: sdhci: Allow platform controlled voltage switching

2018-06-21 Thread Vijay Viswanath
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 
---
 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, 170,
195))
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.



[PATCH RFC 0/2] Internal voltage control for platform drivers

2018-06-21 Thread Vijay Viswanath
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.



[PATCH RFC 1/2] mmc: sdhci: Allow platform controlled voltage switching

2018-06-21 Thread Vijay Viswanath
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 
---
 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, 170,
195))
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.



[PATCH V3 4/4] mmc: host: Register changes for sdcc V5

2018-06-18 Thread Vijay Viswanath
From: Sayali Lokhande 

Add support to use the new compatible string "qcom,sdhci-msm-v5".

Based on the msm variant, pick the relevant variant data and
use it for register read/write to msm specific registers.

Signed-off-by: Sayali Lokhande 
Signed-off-by: Vijay Viswanath 
Reviewed-by: Evan Green 
---
 drivers/mmc/host/sdhci-msm.c | 347 +++
 1 file changed, 221 insertions(+), 126 deletions(-)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 3d01bc2..418dbb0 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -33,16 +33,11 @@
 #define CORE_MCI_GENERICS  0x70
 #define SWITCHABLE_SIGNALING_VOLTAGE   BIT(29)
 
-#define CORE_HC_MODE   0x78
 #define HC_MODE_EN 0x1
 #define CORE_POWER 0x0
 #define CORE_SW_RSTBIT(7)
 #define FF_CLK_SW_RST_DIS  BIT(13)
 
-#define CORE_PWRCTL_STATUS 0xdc
-#define CORE_PWRCTL_MASK   0xe0
-#define CORE_PWRCTL_CLEAR  0xe4
-#define CORE_PWRCTL_CTL0xe8
 #define CORE_PWRCTL_BUS_OFFBIT(0)
 #define CORE_PWRCTL_BUS_ON BIT(1)
 #define CORE_PWRCTL_IO_LOW BIT(2)
@@ -63,17 +58,13 @@
 #define CORE_CDR_EXT_ENBIT(19)
 #define CORE_DLL_PDN   BIT(29)
 #define CORE_DLL_RST   BIT(30)
-#define CORE_DLL_CONFIG0x100
 #define CORE_CMD_DAT_TRACK_SEL BIT(0)
-#define CORE_DLL_STATUS0x108
 
-#define CORE_DLL_CONFIG_2  0x1b4
 #define CORE_DDR_CAL_ENBIT(0)
 #define CORE_FLL_CYCLE_CNT BIT(18)
 #define CORE_DLL_CLOCK_DISABLE BIT(21)
 
-#define CORE_VENDOR_SPEC   0x10c
-#define CORE_VENDOR_SPEC_POR_VAL   0xa1c
+#define CORE_VENDOR_SPEC_POR_VAL 0xa1c
 #define CORE_CLK_PWRSAVE   BIT(1)
 #define CORE_HC_MCLK_SEL_DFLT  (2 << 8)
 #define CORE_HC_MCLK_SEL_HS400 (3 << 8)
@@ -111,17 +102,14 @@
 #define CORE_CDC_SWITCH_BYPASS_OFF BIT(0)
 #define CORE_CDC_SWITCH_RC_EN  BIT(1)
 
-#define CORE_DDR_200_CFG   0x184
 #define CORE_CDC_T4_DLY_SELBIT(0)
 #define CORE_CMDIN_RCLK_EN BIT(1)
 #define CORE_START_CDC_TRAFFIC BIT(6)
-#define CORE_VENDOR_SPEC3  0x1b0
+
 #define CORE_PWRSAVE_DLL   BIT(3)
 
-#define CORE_DDR_CONFIG0x1b8
 #define DDR_CONFIG_POR_VAL 0x80040853
 
-#define CORE_VENDOR_SPEC_CAPABILITIES0 0x11c
 
 #define INVALID_TUNING_PHASE   -1
 #define SDHCI_MSM_MIN_CLOCK40
@@ -137,6 +125,12 @@
 /* Timeout value to avoid infinite waiting for pwr_irq */
 #define MSM_PWR_IRQ_TIMEOUT_MS 5000
 
+#define msm_host_readl(msm_host, host, offset) \
+   msm_host->var_ops->msm_readl_relaxed(host, offset)
+
+#define msm_host_writel(msm_host, val, host, offset) \
+   msm_host->var_ops->msm_writel_relaxed(val, host, offset)
+
 struct sdhci_msm_offset {
u32 core_hc_mode;
u32 core_mci_data_cnt;
@@ -266,6 +260,14 @@ struct sdhci_msm_host {
const struct sdhci_msm_offset *offset;
 };
 
+static const struct sdhci_msm_offset *sdhci_priv_msm_offset(struct sdhci_host 
*host)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+   return msm_host->offset;
+}
+
 /*
  * APIs to read/write to vendor specific registers which were there in the
  * core_mem region before MCI was removed.
@@ -347,10 +349,12 @@ static inline int msm_dll_poll_ck_out_en(struct 
sdhci_host *host, u8 poll)
u32 wait_cnt = 50;
u8 ck_out_en;
struct mmc_host *mmc = host->mmc;
+   const struct sdhci_msm_offset *msm_offset =
+   sdhci_priv_msm_offset(host);
 
/* Poll for CK_OUT_EN bit.  max. poll time = 50us */
-   ck_out_en = !!(readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) &
-   CORE_CK_OUT_EN);
+   ck_out_en = !!(readl_relaxed(host->ioaddr +
+   msm_offset->core_dll_config) & CORE_CK_OUT_EN);
 
while (ck_out_en != poll) {
if (--wait_cnt == 0) {
@@ -360,8 +364,8 @@ static inline int msm_dll_poll_ck_out_en(struct sdhci_host 
*host, u8 poll)
}
udelay(1);
 
-   ck_out_en = !!(readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) &
-   CORE_CK_OUT_EN);
+   ck_out_en = !!(readl_relaxed(host->ioaddr +
+   msm_offset->core_dll_config) & CORE_CK_OUT_EN);
}
 
return 0;
@@ -377,16 +381,18 @@ static int msm_config_cm_dll_phase(struct sdhci_host 
*host, u8 phase)
unsigned long flags;
u32 config;
struct mmc_host *mmc = host->mmc;
+   const struct sdhci_msm_offset *msm_offset =
+   sdhci_priv_msm_offset(host);
 
if (phase > 0xf)
return -EINVAL;
 
spin_lock_irqsav

[PATCH V3 4/4] mmc: host: Register changes for sdcc V5

2018-06-18 Thread Vijay Viswanath
From: Sayali Lokhande 

Add support to use the new compatible string "qcom,sdhci-msm-v5".

Based on the msm variant, pick the relevant variant data and
use it for register read/write to msm specific registers.

Signed-off-by: Sayali Lokhande 
Signed-off-by: Vijay Viswanath 
Reviewed-by: Evan Green 
---
 drivers/mmc/host/sdhci-msm.c | 347 +++
 1 file changed, 221 insertions(+), 126 deletions(-)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 3d01bc2..418dbb0 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -33,16 +33,11 @@
 #define CORE_MCI_GENERICS  0x70
 #define SWITCHABLE_SIGNALING_VOLTAGE   BIT(29)
 
-#define CORE_HC_MODE   0x78
 #define HC_MODE_EN 0x1
 #define CORE_POWER 0x0
 #define CORE_SW_RSTBIT(7)
 #define FF_CLK_SW_RST_DIS  BIT(13)
 
-#define CORE_PWRCTL_STATUS 0xdc
-#define CORE_PWRCTL_MASK   0xe0
-#define CORE_PWRCTL_CLEAR  0xe4
-#define CORE_PWRCTL_CTL0xe8
 #define CORE_PWRCTL_BUS_OFFBIT(0)
 #define CORE_PWRCTL_BUS_ON BIT(1)
 #define CORE_PWRCTL_IO_LOW BIT(2)
@@ -63,17 +58,13 @@
 #define CORE_CDR_EXT_ENBIT(19)
 #define CORE_DLL_PDN   BIT(29)
 #define CORE_DLL_RST   BIT(30)
-#define CORE_DLL_CONFIG0x100
 #define CORE_CMD_DAT_TRACK_SEL BIT(0)
-#define CORE_DLL_STATUS0x108
 
-#define CORE_DLL_CONFIG_2  0x1b4
 #define CORE_DDR_CAL_ENBIT(0)
 #define CORE_FLL_CYCLE_CNT BIT(18)
 #define CORE_DLL_CLOCK_DISABLE BIT(21)
 
-#define CORE_VENDOR_SPEC   0x10c
-#define CORE_VENDOR_SPEC_POR_VAL   0xa1c
+#define CORE_VENDOR_SPEC_POR_VAL 0xa1c
 #define CORE_CLK_PWRSAVE   BIT(1)
 #define CORE_HC_MCLK_SEL_DFLT  (2 << 8)
 #define CORE_HC_MCLK_SEL_HS400 (3 << 8)
@@ -111,17 +102,14 @@
 #define CORE_CDC_SWITCH_BYPASS_OFF BIT(0)
 #define CORE_CDC_SWITCH_RC_EN  BIT(1)
 
-#define CORE_DDR_200_CFG   0x184
 #define CORE_CDC_T4_DLY_SELBIT(0)
 #define CORE_CMDIN_RCLK_EN BIT(1)
 #define CORE_START_CDC_TRAFFIC BIT(6)
-#define CORE_VENDOR_SPEC3  0x1b0
+
 #define CORE_PWRSAVE_DLL   BIT(3)
 
-#define CORE_DDR_CONFIG0x1b8
 #define DDR_CONFIG_POR_VAL 0x80040853
 
-#define CORE_VENDOR_SPEC_CAPABILITIES0 0x11c
 
 #define INVALID_TUNING_PHASE   -1
 #define SDHCI_MSM_MIN_CLOCK40
@@ -137,6 +125,12 @@
 /* Timeout value to avoid infinite waiting for pwr_irq */
 #define MSM_PWR_IRQ_TIMEOUT_MS 5000
 
+#define msm_host_readl(msm_host, host, offset) \
+   msm_host->var_ops->msm_readl_relaxed(host, offset)
+
+#define msm_host_writel(msm_host, val, host, offset) \
+   msm_host->var_ops->msm_writel_relaxed(val, host, offset)
+
 struct sdhci_msm_offset {
u32 core_hc_mode;
u32 core_mci_data_cnt;
@@ -266,6 +260,14 @@ struct sdhci_msm_host {
const struct sdhci_msm_offset *offset;
 };
 
+static const struct sdhci_msm_offset *sdhci_priv_msm_offset(struct sdhci_host 
*host)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+   return msm_host->offset;
+}
+
 /*
  * APIs to read/write to vendor specific registers which were there in the
  * core_mem region before MCI was removed.
@@ -347,10 +349,12 @@ static inline int msm_dll_poll_ck_out_en(struct 
sdhci_host *host, u8 poll)
u32 wait_cnt = 50;
u8 ck_out_en;
struct mmc_host *mmc = host->mmc;
+   const struct sdhci_msm_offset *msm_offset =
+   sdhci_priv_msm_offset(host);
 
/* Poll for CK_OUT_EN bit.  max. poll time = 50us */
-   ck_out_en = !!(readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) &
-   CORE_CK_OUT_EN);
+   ck_out_en = !!(readl_relaxed(host->ioaddr +
+   msm_offset->core_dll_config) & CORE_CK_OUT_EN);
 
while (ck_out_en != poll) {
if (--wait_cnt == 0) {
@@ -360,8 +364,8 @@ static inline int msm_dll_poll_ck_out_en(struct sdhci_host 
*host, u8 poll)
}
udelay(1);
 
-   ck_out_en = !!(readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) &
-   CORE_CK_OUT_EN);
+   ck_out_en = !!(readl_relaxed(host->ioaddr +
+   msm_offset->core_dll_config) & CORE_CK_OUT_EN);
}
 
return 0;
@@ -377,16 +381,18 @@ static int msm_config_cm_dll_phase(struct sdhci_host 
*host, u8 phase)
unsigned long flags;
u32 config;
struct mmc_host *mmc = host->mmc;
+   const struct sdhci_msm_offset *msm_offset =
+   sdhci_priv_msm_offset(host);
 
if (phase > 0xf)
return -EINVAL;
 
spin_lock_irqsav

[PATCH V3 3/4] Documentation: sdhci-msm: Add new compatible string for SDCC v5

2018-06-18 Thread Vijay Viswanath
From: Sayali Lokhande 

For SDCC version 5.0.0 and higher, new compatible string
"qcom,sdhci-msm-v5" is added.

Signed-off-by: Sayali Lokhande 
Signed-off-by: Vijay Viswanath 
Acked-by: Rob Herring 
---
 Documentation/devicetree/bindings/mmc/sdhci-msm.txt | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt 
b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
index bfdcdc4..502b3b8 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
@@ -4,7 +4,12 @@ This file documents differences between the core properties in 
mmc.txt
 and the properties used by the sdhci-msm driver.
 
 Required properties:
-- compatible: Should contain "qcom,sdhci-msm-v4".
+- compatible: Should contain:
+   "qcom,sdhci-msm-v4" for sdcc versions less than 5.0
+   "qcom,sdhci-msm-v5" for sdcc versions >= 5.0
+   For SDCC version 5.0.0, MCI registers are removed from SDCC
+   interface and some registers are moved to HC. New compatible
+   string is added to support this change - "qcom,sdhci-msm-v5".
 - reg: Base address and length of the register in the following order:
- Host controller register map (required)
- SD Core register map (required)
-- 
 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.



[PATCH V3 3/4] Documentation: sdhci-msm: Add new compatible string for SDCC v5

2018-06-18 Thread Vijay Viswanath
From: Sayali Lokhande 

For SDCC version 5.0.0 and higher, new compatible string
"qcom,sdhci-msm-v5" is added.

Signed-off-by: Sayali Lokhande 
Signed-off-by: Vijay Viswanath 
Acked-by: Rob Herring 
---
 Documentation/devicetree/bindings/mmc/sdhci-msm.txt | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt 
b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
index bfdcdc4..502b3b8 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
@@ -4,7 +4,12 @@ This file documents differences between the core properties in 
mmc.txt
 and the properties used by the sdhci-msm driver.
 
 Required properties:
-- compatible: Should contain "qcom,sdhci-msm-v4".
+- compatible: Should contain:
+   "qcom,sdhci-msm-v4" for sdcc versions less than 5.0
+   "qcom,sdhci-msm-v5" for sdcc versions >= 5.0
+   For SDCC version 5.0.0, MCI registers are removed from SDCC
+   interface and some registers are moved to HC. New compatible
+   string is added to support this change - "qcom,sdhci-msm-v5".
 - reg: Base address and length of the register in the following order:
- Host controller register map (required)
- SD Core register map (required)
-- 
 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.



[PATCH V3 2/4] mmc: sdhci-msm: Add msm version specific ops and data structures

2018-06-18 Thread Vijay Viswanath
In addition to offsets of certain registers changing, the registers in
core_mem have been shifted to HC mem as well. To access these
registers, define msm version specific functions. These functions can
be loaded into the function pointers at the time of probe based on
the msm version detected.

Also defind new data structure to hold version specific Ops and
register addresses.

Signed-off-by: Sayali Lokhande 
Signed-off-by: Vijay Viswanath 
Reviewed-by: Evan Green 
---
 drivers/mmc/host/sdhci-msm.c | 75 
 1 file changed, 75 insertions(+)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 4050c99..3d01bc2 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -226,6 +226,22 @@ struct sdhci_msm_offset {
.core_ddr_config_2 = 0x1bc,
 };
 
+struct sdhci_msm_variant_ops {
+   u32 (*msm_readl_relaxed)(struct sdhci_host *host, u32 offset);
+   void (*msm_writel_relaxed)(u32 val, struct sdhci_host *host,
+   u32 offset);
+};
+
+/*
+ * From V5, register spaces have changed. Wrap this info in a structure
+ * and choose the data_structure based on version info mentioned in DT.
+ */
+struct sdhci_msm_variant_info {
+   bool mci_removed;
+   const struct sdhci_msm_variant_ops *var_ops;
+   const struct sdhci_msm_offset *offset;
+};
+
 struct sdhci_msm_host {
struct platform_device *pdev;
void __iomem *core_mem; /* MSM SDCC mapped address */
@@ -245,8 +261,45 @@ struct sdhci_msm_host {
wait_queue_head_t pwr_irq_wait;
bool pwr_irq_flag;
u32 caps_0;
+   bool mci_removed;
+   const struct sdhci_msm_variant_ops *var_ops;
+   const struct sdhci_msm_offset *offset;
 };
 
+/*
+ * APIs to read/write to vendor specific registers which were there in the
+ * core_mem region before MCI was removed.
+ */
+static u32 sdhci_msm_mci_variant_readl_relaxed(struct sdhci_host *host,
+   u32 offset)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+   return readl_relaxed(msm_host->core_mem + offset);
+}
+
+static u32 sdhci_msm_v5_variant_readl_relaxed(struct sdhci_host *host,
+   u32 offset)
+{
+   return readl_relaxed(host->ioaddr + offset);
+}
+
+static void sdhci_msm_mci_variant_writel_relaxed(u32 val,
+   struct sdhci_host *host, u32 offset)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+   writel_relaxed(val, msm_host->core_mem + offset);
+}
+
+static void sdhci_msm_v5_variant_writel_relaxed(u32 val,
+   struct sdhci_host *host, u32 offset)
+{
+   writel_relaxed(val, host->ioaddr + offset);
+}
+
 static unsigned int msm_get_clock_rate_for_bus_mode(struct sdhci_host *host,
unsigned int clock)
 {
@@ -1481,6 +1534,28 @@ 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 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,
+};
+
+static const struct sdhci_msm_variant_ops v5_var_ops = {
+   .msm_readl_relaxed = sdhci_msm_v5_variant_readl_relaxed,
+   .msm_writel_relaxed = sdhci_msm_v5_variant_writel_relaxed,
+};
+
+static const struct sdhci_msm_variant_info sdhci_msm_mci_var = {
+   .mci_removed = false,
+   .var_ops = _var_ops,
+   .offset = _msm_mci_offset,
+};
+
+static const struct sdhci_msm_variant_info sdhci_msm_v5_var = {
+   .mci_removed = true,
+   .var_ops = _var_ops,
+   .offset = _msm_v5_offset,
+};
+
 static const struct of_device_id sdhci_msm_dt_match[] = {
{ .compatible = "qcom,sdhci-msm-v4" },
{},
-- 
 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.



[PATCH V3 2/4] mmc: sdhci-msm: Add msm version specific ops and data structures

2018-06-18 Thread Vijay Viswanath
In addition to offsets of certain registers changing, the registers in
core_mem have been shifted to HC mem as well. To access these
registers, define msm version specific functions. These functions can
be loaded into the function pointers at the time of probe based on
the msm version detected.

Also defind new data structure to hold version specific Ops and
register addresses.

Signed-off-by: Sayali Lokhande 
Signed-off-by: Vijay Viswanath 
Reviewed-by: Evan Green 
---
 drivers/mmc/host/sdhci-msm.c | 75 
 1 file changed, 75 insertions(+)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 4050c99..3d01bc2 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -226,6 +226,22 @@ struct sdhci_msm_offset {
.core_ddr_config_2 = 0x1bc,
 };
 
+struct sdhci_msm_variant_ops {
+   u32 (*msm_readl_relaxed)(struct sdhci_host *host, u32 offset);
+   void (*msm_writel_relaxed)(u32 val, struct sdhci_host *host,
+   u32 offset);
+};
+
+/*
+ * From V5, register spaces have changed. Wrap this info in a structure
+ * and choose the data_structure based on version info mentioned in DT.
+ */
+struct sdhci_msm_variant_info {
+   bool mci_removed;
+   const struct sdhci_msm_variant_ops *var_ops;
+   const struct sdhci_msm_offset *offset;
+};
+
 struct sdhci_msm_host {
struct platform_device *pdev;
void __iomem *core_mem; /* MSM SDCC mapped address */
@@ -245,8 +261,45 @@ struct sdhci_msm_host {
wait_queue_head_t pwr_irq_wait;
bool pwr_irq_flag;
u32 caps_0;
+   bool mci_removed;
+   const struct sdhci_msm_variant_ops *var_ops;
+   const struct sdhci_msm_offset *offset;
 };
 
+/*
+ * APIs to read/write to vendor specific registers which were there in the
+ * core_mem region before MCI was removed.
+ */
+static u32 sdhci_msm_mci_variant_readl_relaxed(struct sdhci_host *host,
+   u32 offset)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+   return readl_relaxed(msm_host->core_mem + offset);
+}
+
+static u32 sdhci_msm_v5_variant_readl_relaxed(struct sdhci_host *host,
+   u32 offset)
+{
+   return readl_relaxed(host->ioaddr + offset);
+}
+
+static void sdhci_msm_mci_variant_writel_relaxed(u32 val,
+   struct sdhci_host *host, u32 offset)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+   writel_relaxed(val, msm_host->core_mem + offset);
+}
+
+static void sdhci_msm_v5_variant_writel_relaxed(u32 val,
+   struct sdhci_host *host, u32 offset)
+{
+   writel_relaxed(val, host->ioaddr + offset);
+}
+
 static unsigned int msm_get_clock_rate_for_bus_mode(struct sdhci_host *host,
unsigned int clock)
 {
@@ -1481,6 +1534,28 @@ 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 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,
+};
+
+static const struct sdhci_msm_variant_ops v5_var_ops = {
+   .msm_readl_relaxed = sdhci_msm_v5_variant_readl_relaxed,
+   .msm_writel_relaxed = sdhci_msm_v5_variant_writel_relaxed,
+};
+
+static const struct sdhci_msm_variant_info sdhci_msm_mci_var = {
+   .mci_removed = false,
+   .var_ops = _var_ops,
+   .offset = _msm_mci_offset,
+};
+
+static const struct sdhci_msm_variant_info sdhci_msm_v5_var = {
+   .mci_removed = true,
+   .var_ops = _var_ops,
+   .offset = _msm_v5_offset,
+};
+
 static const struct of_device_id sdhci_msm_dt_match[] = {
{ .compatible = "qcom,sdhci-msm-v4" },
{},
-- 
 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.



[PATCH V3 1/4] mmc: sdhci-msm: Define new Register address map

2018-06-18 Thread Vijay Viswanath
From: Sayali Lokhande 

For SDCC version 5.0.0, MCI registers are removed from SDCC
interface and some registers are moved to HC.
Define a new data structure where we can statically define
the address offsets for the registers in different SDCC versions.

Signed-off-by: Sayali Lokhande 
Signed-off-by: Vijay Viswanath 
Reviewed-by: Evan Green 
Acked-by: Adrian Hunter 
---
 drivers/mmc/host/sdhci-msm.c | 89 
 1 file changed, 89 insertions(+)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index bb11916..4050c99 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -137,6 +137,95 @@
 /* Timeout value to avoid infinite waiting for pwr_irq */
 #define MSM_PWR_IRQ_TIMEOUT_MS 5000
 
+struct sdhci_msm_offset {
+   u32 core_hc_mode;
+   u32 core_mci_data_cnt;
+   u32 core_mci_status;
+   u32 core_mci_fifo_cnt;
+   u32 core_mci_version;
+   u32 core_generics;
+   u32 core_testbus_config;
+   u32 core_testbus_sel2_bit;
+   u32 core_testbus_ena;
+   u32 core_testbus_sel2;
+   u32 core_pwrctl_status;
+   u32 core_pwrctl_mask;
+   u32 core_pwrctl_clear;
+   u32 core_pwrctl_ctl;
+   u32 core_sdcc_debug_reg;
+   u32 core_dll_config;
+   u32 core_dll_status;
+   u32 core_vendor_spec;
+   u32 core_vendor_spec_adma_err_addr0;
+   u32 core_vendor_spec_adma_err_addr1;
+   u32 core_vendor_spec_func2;
+   u32 core_vendor_spec_capabilities0;
+   u32 core_ddr_200_cfg;
+   u32 core_vendor_spec3;
+   u32 core_dll_config_2;
+   u32 core_ddr_config;
+   u32 core_ddr_config_2;
+};
+
+static const struct sdhci_msm_offset sdhci_msm_v5_offset = {
+   .core_mci_data_cnt = 0x35c,
+   .core_mci_status = 0x324,
+   .core_mci_fifo_cnt = 0x308,
+   .core_mci_version = 0x318,
+   .core_generics = 0x320,
+   .core_testbus_config = 0x32c,
+   .core_testbus_sel2_bit = 3,
+   .core_testbus_ena = (1 << 31),
+   .core_testbus_sel2 = (1 << 3),
+   .core_pwrctl_status = 0x240,
+   .core_pwrctl_mask = 0x244,
+   .core_pwrctl_clear = 0x248,
+   .core_pwrctl_ctl = 0x24c,
+   .core_sdcc_debug_reg = 0x358,
+   .core_dll_config = 0x200,
+   .core_dll_status = 0x208,
+   .core_vendor_spec = 0x20c,
+   .core_vendor_spec_adma_err_addr0 = 0x214,
+   .core_vendor_spec_adma_err_addr1 = 0x218,
+   .core_vendor_spec_func2 = 0x210,
+   .core_vendor_spec_capabilities0 = 0x21c,
+   .core_ddr_200_cfg = 0x224,
+   .core_vendor_spec3 = 0x250,
+   .core_dll_config_2 = 0x254,
+   .core_ddr_config = 0x258,
+   .core_ddr_config_2 = 0x25c,
+};
+
+static const struct sdhci_msm_offset sdhci_msm_mci_offset = {
+   .core_hc_mode = 0x78,
+   .core_mci_data_cnt = 0x30,
+   .core_mci_status = 0x34,
+   .core_mci_fifo_cnt = 0x44,
+   .core_mci_version = 0x050,
+   .core_generics = 0x70,
+   .core_testbus_config = 0x0cc,
+   .core_testbus_sel2_bit = 4,
+   .core_testbus_ena = (1 << 3),
+   .core_testbus_sel2 = (1 << 4),
+   .core_pwrctl_status = 0xdc,
+   .core_pwrctl_mask = 0xe0,
+   .core_pwrctl_clear = 0xe4,
+   .core_pwrctl_ctl = 0xe8,
+   .core_sdcc_debug_reg = 0x124,
+   .core_dll_config = 0x100,
+   .core_dll_status = 0x108,
+   .core_vendor_spec = 0x10c,
+   .core_vendor_spec_adma_err_addr0 = 0x114,
+   .core_vendor_spec_adma_err_addr1 = 0x118,
+   .core_vendor_spec_func2 = 0x110,
+   .core_vendor_spec_capabilities0 = 0x11c,
+   .core_ddr_200_cfg = 0x184,
+   .core_vendor_spec3 = 0x1b0,
+   .core_dll_config_2 = 0x1b4,
+   .core_ddr_config = 0x1b8,
+   .core_ddr_config_2 = 0x1bc,
+};
+
 struct sdhci_msm_host {
struct platform_device *pdev;
void __iomem *core_mem; /* MSM SDCC 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.



[PATCH V3 0/4] Changes for SDCC5 version

2018-06-18 Thread Vijay Viswanath
With SDCC5, the MCI register space got removed and the offset/order of
several registers have changed. Based on SDCC version used and the register,
we need to pick the base address and offset.

Depends on patch series: "[PATCH V5 0/2] mmc: sdhci-msm: Configuring IO_PAD 
support for sdhci-msm"

Changes since RFC:
Dropped voltage regulator changes in sdhci-msm
Split the "Register changes for sdcc V5" patch
Instead of checking mci removal for deciding which base addr to use,
new function pointers are defined for the 2 variants of sdcc: 
1) MCI present
2) V5 (mci removed)
Instead of string comparing with the compatible string from DT file,
the sdhci_msm_probe will now pick the data associated with the
compatible entry and use it to load variant specific address offsets
and msm variant specific read/write ops.

Changes since V1:
Removed unused msm_reab & msm_writeb APIs
Changed certain register addresses from uppercase to lowercase hex
letters
Removed extra lines and spaces
Split "[PATCH V1 0/3] Changes for SDCC5 version" patch into two,
one for Documentation and other for the driver changes.

Changes since V2:
Used lower case for macro function defenitions
Removed unused function pointers for msm_readb & msm_writeb


Sayali Lokhande (3):
  mmc: sdhci-msm: Define new Register address map
  Documentation: sdhci-msm: Add new compatible string for SDCC v5
  mmc: host: Register changes for sdcc V5

Vijay Viswanath (1):
  mmc: sdhci-msm: Add msm version specific ops and data structures

 .../devicetree/bindings/mmc/sdhci-msm.txt  |   7 +-
 drivers/mmc/host/sdhci-msm.c   | 511 -
 2 files changed, 391 insertions(+), 127 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.



[PATCH V3 1/4] mmc: sdhci-msm: Define new Register address map

2018-06-18 Thread Vijay Viswanath
From: Sayali Lokhande 

For SDCC version 5.0.0, MCI registers are removed from SDCC
interface and some registers are moved to HC.
Define a new data structure where we can statically define
the address offsets for the registers in different SDCC versions.

Signed-off-by: Sayali Lokhande 
Signed-off-by: Vijay Viswanath 
Reviewed-by: Evan Green 
Acked-by: Adrian Hunter 
---
 drivers/mmc/host/sdhci-msm.c | 89 
 1 file changed, 89 insertions(+)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index bb11916..4050c99 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -137,6 +137,95 @@
 /* Timeout value to avoid infinite waiting for pwr_irq */
 #define MSM_PWR_IRQ_TIMEOUT_MS 5000
 
+struct sdhci_msm_offset {
+   u32 core_hc_mode;
+   u32 core_mci_data_cnt;
+   u32 core_mci_status;
+   u32 core_mci_fifo_cnt;
+   u32 core_mci_version;
+   u32 core_generics;
+   u32 core_testbus_config;
+   u32 core_testbus_sel2_bit;
+   u32 core_testbus_ena;
+   u32 core_testbus_sel2;
+   u32 core_pwrctl_status;
+   u32 core_pwrctl_mask;
+   u32 core_pwrctl_clear;
+   u32 core_pwrctl_ctl;
+   u32 core_sdcc_debug_reg;
+   u32 core_dll_config;
+   u32 core_dll_status;
+   u32 core_vendor_spec;
+   u32 core_vendor_spec_adma_err_addr0;
+   u32 core_vendor_spec_adma_err_addr1;
+   u32 core_vendor_spec_func2;
+   u32 core_vendor_spec_capabilities0;
+   u32 core_ddr_200_cfg;
+   u32 core_vendor_spec3;
+   u32 core_dll_config_2;
+   u32 core_ddr_config;
+   u32 core_ddr_config_2;
+};
+
+static const struct sdhci_msm_offset sdhci_msm_v5_offset = {
+   .core_mci_data_cnt = 0x35c,
+   .core_mci_status = 0x324,
+   .core_mci_fifo_cnt = 0x308,
+   .core_mci_version = 0x318,
+   .core_generics = 0x320,
+   .core_testbus_config = 0x32c,
+   .core_testbus_sel2_bit = 3,
+   .core_testbus_ena = (1 << 31),
+   .core_testbus_sel2 = (1 << 3),
+   .core_pwrctl_status = 0x240,
+   .core_pwrctl_mask = 0x244,
+   .core_pwrctl_clear = 0x248,
+   .core_pwrctl_ctl = 0x24c,
+   .core_sdcc_debug_reg = 0x358,
+   .core_dll_config = 0x200,
+   .core_dll_status = 0x208,
+   .core_vendor_spec = 0x20c,
+   .core_vendor_spec_adma_err_addr0 = 0x214,
+   .core_vendor_spec_adma_err_addr1 = 0x218,
+   .core_vendor_spec_func2 = 0x210,
+   .core_vendor_spec_capabilities0 = 0x21c,
+   .core_ddr_200_cfg = 0x224,
+   .core_vendor_spec3 = 0x250,
+   .core_dll_config_2 = 0x254,
+   .core_ddr_config = 0x258,
+   .core_ddr_config_2 = 0x25c,
+};
+
+static const struct sdhci_msm_offset sdhci_msm_mci_offset = {
+   .core_hc_mode = 0x78,
+   .core_mci_data_cnt = 0x30,
+   .core_mci_status = 0x34,
+   .core_mci_fifo_cnt = 0x44,
+   .core_mci_version = 0x050,
+   .core_generics = 0x70,
+   .core_testbus_config = 0x0cc,
+   .core_testbus_sel2_bit = 4,
+   .core_testbus_ena = (1 << 3),
+   .core_testbus_sel2 = (1 << 4),
+   .core_pwrctl_status = 0xdc,
+   .core_pwrctl_mask = 0xe0,
+   .core_pwrctl_clear = 0xe4,
+   .core_pwrctl_ctl = 0xe8,
+   .core_sdcc_debug_reg = 0x124,
+   .core_dll_config = 0x100,
+   .core_dll_status = 0x108,
+   .core_vendor_spec = 0x10c,
+   .core_vendor_spec_adma_err_addr0 = 0x114,
+   .core_vendor_spec_adma_err_addr1 = 0x118,
+   .core_vendor_spec_func2 = 0x110,
+   .core_vendor_spec_capabilities0 = 0x11c,
+   .core_ddr_200_cfg = 0x184,
+   .core_vendor_spec3 = 0x1b0,
+   .core_dll_config_2 = 0x1b4,
+   .core_ddr_config = 0x1b8,
+   .core_ddr_config_2 = 0x1bc,
+};
+
 struct sdhci_msm_host {
struct platform_device *pdev;
void __iomem *core_mem; /* MSM SDCC 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.



[PATCH V3 0/4] Changes for SDCC5 version

2018-06-18 Thread Vijay Viswanath
With SDCC5, the MCI register space got removed and the offset/order of
several registers have changed. Based on SDCC version used and the register,
we need to pick the base address and offset.

Depends on patch series: "[PATCH V5 0/2] mmc: sdhci-msm: Configuring IO_PAD 
support for sdhci-msm"

Changes since RFC:
Dropped voltage regulator changes in sdhci-msm
Split the "Register changes for sdcc V5" patch
Instead of checking mci removal for deciding which base addr to use,
new function pointers are defined for the 2 variants of sdcc: 
1) MCI present
2) V5 (mci removed)
Instead of string comparing with the compatible string from DT file,
the sdhci_msm_probe will now pick the data associated with the
compatible entry and use it to load variant specific address offsets
and msm variant specific read/write ops.

Changes since V1:
Removed unused msm_reab & msm_writeb APIs
Changed certain register addresses from uppercase to lowercase hex
letters
Removed extra lines and spaces
Split "[PATCH V1 0/3] Changes for SDCC5 version" patch into two,
one for Documentation and other for the driver changes.

Changes since V2:
Used lower case for macro function defenitions
Removed unused function pointers for msm_readb & msm_writeb


Sayali Lokhande (3):
  mmc: sdhci-msm: Define new Register address map
  Documentation: sdhci-msm: Add new compatible string for SDCC v5
  mmc: host: Register changes for sdcc V5

Vijay Viswanath (1):
  mmc: sdhci-msm: Add msm version specific ops and data structures

 .../devicetree/bindings/mmc/sdhci-msm.txt  |   7 +-
 drivers/mmc/host/sdhci-msm.c   | 511 -
 2 files changed, 391 insertions(+), 127 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.



Re: [PATCH V2 4/4] mmc: host: Register changes for sdcc V5

2018-06-14 Thread Vijay Viswanath




On 6/13/2018 4:55 AM, Stephen Boyd wrote:

Quoting Vijay Viswanath (2018-05-29 02:52:41)

@@ -137,6 +125,12 @@
  /* Timeout value to avoid infinite waiting for pwr_irq */
  #define MSM_PWR_IRQ_TIMEOUT_MS 5000
  
+#define MSM_HOST_READL(msm_host, host, offset) \

+   msm_host->var_ops->msm_readl_relaxed(host, offset)
+
+#define MSM_HOST_WRITEL(msm_host, val, host, offset) \
+   msm_host->var_ops->msm_writel_relaxed(val, host, offset)


Is there a reason these macros are capitalized? We don't have READL and
WRITEL macros in the kernel because function-like macros are typically
lowercase.



will change them to lower case. Didn't notice that...


+
  struct sdhci_msm_offset {
 u32 core_hc_mode;
 u32 core_mci_data_cnt;
@@ -268,6 +262,14 @@ struct sdhci_msm_host {
 const struct sdhci_msm_offset *offset;
  };
  
+const struct sdhci_msm_offset *sdhci_priv_msm_offset(struct sdhci_host *host)


static?



will do


+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+   return msm_host->offset;
+}
+

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



Re: [PATCH V2 4/4] mmc: host: Register changes for sdcc V5

2018-06-14 Thread Vijay Viswanath




On 6/13/2018 4:55 AM, Stephen Boyd wrote:

Quoting Vijay Viswanath (2018-05-29 02:52:41)

@@ -137,6 +125,12 @@
  /* Timeout value to avoid infinite waiting for pwr_irq */
  #define MSM_PWR_IRQ_TIMEOUT_MS 5000
  
+#define MSM_HOST_READL(msm_host, host, offset) \

+   msm_host->var_ops->msm_readl_relaxed(host, offset)
+
+#define MSM_HOST_WRITEL(msm_host, val, host, offset) \
+   msm_host->var_ops->msm_writel_relaxed(val, host, offset)


Is there a reason these macros are capitalized? We don't have READL and
WRITEL macros in the kernel because function-like macros are typically
lowercase.



will change them to lower case. Didn't notice that...


+
  struct sdhci_msm_offset {
 u32 core_hc_mode;
 u32 core_mci_data_cnt;
@@ -268,6 +262,14 @@ struct sdhci_msm_host {
 const struct sdhci_msm_offset *offset;
  };
  
+const struct sdhci_msm_offset *sdhci_priv_msm_offset(struct sdhci_host *host)


static?



will do


+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+   return msm_host->offset;
+}
+

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



Re: [PATCH V2 2/4] mmc: sdhci-msm: Add msm version specific ops and data structures

2018-06-14 Thread Vijay Viswanath

Hi Stephen,

On 6/13/2018 5:06 AM, Stephen Boyd wrote:

Quoting Vijay Viswanath (2018-05-29 02:52:39)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 4050c99..2a66aa0 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -226,6 +226,24 @@ struct sdhci_msm_offset {
 .core_ddr_config_2 = 0x1bc,
  };
  
+struct sdhci_msm_variant_ops {

+   u8 (*msm_readb_relaxed)(struct sdhci_host *host, u32 offset);
+   u32 (*msm_readl_relaxed)(struct sdhci_host *host, u32 offset);
+   void (*msm_writeb_relaxed)(u8 val, struct sdhci_host *host, u32 offset);
+   void (*msm_writel_relaxed)(u32 val, struct sdhci_host *host,
+   u32 offset);
+};
+
+/*
+ * From V5, register spaces have changed. Wrap this info in a structure
+ * and choose the data_structure based on version info mentioned in DT.
+ */


This is sort of odd. Usually we have a read/write function that swizzles
based on register variants, and that's contained with that function. Now
it's the other way.


+struct sdhci_msm_variant_info {
+   bool mci_removed;
+   const struct sdhci_msm_variant_ops *var_ops;
+   const struct sdhci_msm_offset *offset;
+};
+
  struct sdhci_msm_host {
 struct platform_device *pdev;
 void __iomem *core_mem; /* MSM SDCC mapped address */
@@ -245,8 +263,45 @@ struct sdhci_msm_host {
 wait_queue_head_t pwr_irq_wait;
 bool pwr_irq_flag;
 u32 caps_0;
+   bool mci_removed;
+   const struct sdhci_msm_variant_ops *var_ops;
+   const struct sdhci_msm_offset *offset;
  };
  
+/*

+ * APIs to read/write to vendor specific registers which were there in the
+ * core_mem region before MCI was removed.
+ */
+static u32 sdhci_msm_mci_variant_readl_relaxed(struct sdhci_host *host,
+   u32 offset)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+   return readl_relaxed(msm_host->core_mem + offset);


Is core_mem assigned in the new hardware? Maybe that needs to be
'repurposed' for vendor specific registers on v5 and renamed to
something like msm_host::vendor_base or something like that.



There is no core_mem in the new hardware. We can assign hc_mem address 
to core_mem variable (if SDCC5) and do away with the need of special 
read/write functions, but I feel thats a bad approach and misleading.



+}
+
+static u32 sdhci_msm_v5_variant_readl_relaxed(struct sdhci_host *host,
+   u32 offset)
+{
+   return readl_relaxed(host->ioaddr + offset);
+}
+
+static void sdhci_msm_mci_variant_writel_relaxed(u32 val,
+   struct sdhci_host *host, u32 offset)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+   writel_relaxed(val, msm_host->core_mem + offset);
+}
+
+static void sdhci_msm_v5_variant_writel_relaxed(u32 val,
+   struct sdhci_host *host, u32 offset)
+{
+   writel_relaxed(val, host->ioaddr + offset);
+}
+
  static unsigned int msm_get_clock_rate_for_bus_mode(struct sdhci_host *host,
 unsigned int clock)
  {
@@ -1481,6 +1536,28 @@ 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 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,
+};
+
+static const struct sdhci_msm_variant_ops v5_var_ops = {
+   .msm_readl_relaxed = sdhci_msm_v5_variant_readl_relaxed,
+   .msm_writel_relaxed = sdhci_msm_v5_variant_writel_relaxed,
+};
+
+static const struct sdhci_msm_variant_info sdhci_msm_mci_var = {
+   .mci_removed = 0,


Please use true and false instead of 0 and 1 when the type is bool.



Will do


+   .var_ops = _var_ops,
+   .offset = _msm_mci_offset,
+};
+
+static const struct sdhci_msm_variant_info sdhci_msm_v5_var = {
+   .mci_removed = 1,
+   .var_ops = _var_ops,
+   .offset = _msm_v5_offset,
+};

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



Re: [PATCH V2 2/4] mmc: sdhci-msm: Add msm version specific ops and data structures

2018-06-14 Thread Vijay Viswanath

Hi Stephen,

On 6/13/2018 5:06 AM, Stephen Boyd wrote:

Quoting Vijay Viswanath (2018-05-29 02:52:39)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 4050c99..2a66aa0 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -226,6 +226,24 @@ struct sdhci_msm_offset {
 .core_ddr_config_2 = 0x1bc,
  };
  
+struct sdhci_msm_variant_ops {

+   u8 (*msm_readb_relaxed)(struct sdhci_host *host, u32 offset);
+   u32 (*msm_readl_relaxed)(struct sdhci_host *host, u32 offset);
+   void (*msm_writeb_relaxed)(u8 val, struct sdhci_host *host, u32 offset);
+   void (*msm_writel_relaxed)(u32 val, struct sdhci_host *host,
+   u32 offset);
+};
+
+/*
+ * From V5, register spaces have changed. Wrap this info in a structure
+ * and choose the data_structure based on version info mentioned in DT.
+ */


This is sort of odd. Usually we have a read/write function that swizzles
based on register variants, and that's contained with that function. Now
it's the other way.


+struct sdhci_msm_variant_info {
+   bool mci_removed;
+   const struct sdhci_msm_variant_ops *var_ops;
+   const struct sdhci_msm_offset *offset;
+};
+
  struct sdhci_msm_host {
 struct platform_device *pdev;
 void __iomem *core_mem; /* MSM SDCC mapped address */
@@ -245,8 +263,45 @@ struct sdhci_msm_host {
 wait_queue_head_t pwr_irq_wait;
 bool pwr_irq_flag;
 u32 caps_0;
+   bool mci_removed;
+   const struct sdhci_msm_variant_ops *var_ops;
+   const struct sdhci_msm_offset *offset;
  };
  
+/*

+ * APIs to read/write to vendor specific registers which were there in the
+ * core_mem region before MCI was removed.
+ */
+static u32 sdhci_msm_mci_variant_readl_relaxed(struct sdhci_host *host,
+   u32 offset)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+   return readl_relaxed(msm_host->core_mem + offset);


Is core_mem assigned in the new hardware? Maybe that needs to be
'repurposed' for vendor specific registers on v5 and renamed to
something like msm_host::vendor_base or something like that.



There is no core_mem in the new hardware. We can assign hc_mem address 
to core_mem variable (if SDCC5) and do away with the need of special 
read/write functions, but I feel thats a bad approach and misleading.



+}
+
+static u32 sdhci_msm_v5_variant_readl_relaxed(struct sdhci_host *host,
+   u32 offset)
+{
+   return readl_relaxed(host->ioaddr + offset);
+}
+
+static void sdhci_msm_mci_variant_writel_relaxed(u32 val,
+   struct sdhci_host *host, u32 offset)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+   writel_relaxed(val, msm_host->core_mem + offset);
+}
+
+static void sdhci_msm_v5_variant_writel_relaxed(u32 val,
+   struct sdhci_host *host, u32 offset)
+{
+   writel_relaxed(val, host->ioaddr + offset);
+}
+
  static unsigned int msm_get_clock_rate_for_bus_mode(struct sdhci_host *host,
 unsigned int clock)
  {
@@ -1481,6 +1536,28 @@ 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 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,
+};
+
+static const struct sdhci_msm_variant_ops v5_var_ops = {
+   .msm_readl_relaxed = sdhci_msm_v5_variant_readl_relaxed,
+   .msm_writel_relaxed = sdhci_msm_v5_variant_writel_relaxed,
+};
+
+static const struct sdhci_msm_variant_info sdhci_msm_mci_var = {
+   .mci_removed = 0,


Please use true and false instead of 0 and 1 when the type is bool.



Will do


+   .var_ops = _var_ops,
+   .offset = _msm_mci_offset,
+};
+
+static const struct sdhci_msm_variant_info sdhci_msm_v5_var = {
+   .mci_removed = 1,
+   .var_ops = _var_ops,
+   .offset = _msm_v5_offset,
+};

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



Re: [PATCH v2 4/4] mmc: sdhci-msm: Add sdhci msm register write APIs which wait for pwr irq

2018-05-30 Thread Vijay Viswanath

Hi Georgi,

Thanks for testing the patch on 8096 and pointing out this issue.
The issue is coming because, when card is removed, the HOST_CONTROL2 
register is retaining the 1.8V Signalling enable bit till SDHCI reset 
happens after a new card is inserted.


Adding the change you suggested can avoid this wait, but I feel a better 
solution is to clear the 1.8V signalling bit when the card is removed. 
When a new card is inserted, we shouldn't be keeping the 1.8V bit set 
until we send cmd11 to the SD card. A new SD card should start with 3V.


One solution is to explicitly clear the HOST_CONTROL2 register when card 
is removed.


Other way is to revert the commit: 
9718f84b85396e090ca42fafa730410d286d61e3 "mmc: sdhci-msm: Do not reset 
the controller if no card in the slot"


The sdhci-msm doesn't require "SDHCI_QUIRK_NO_CARD_NO_RESET". The issue 
which above commit is trying to avoid is fixed by the pwr-irq patches. 
Resetting the controller will clear the HOST_CONTROL2 register and avoid 
this issue.


Can you please try this ? I tested reverting the QUIRK on two platforms: 
db410c(8916) and sdm845. SD card insert/remove worked fine after that 
and I didn't get any "Reset 0x1 never completed" error during card 
insert/remove or shutdown.


Thanks,
Vijay

On 5/29/2018 5:49 PM, Georgi Djakov wrote:

Hello Vijay,

On 09/27/2017 08:34 AM, Vijay Viswanath wrote:

Register writes which change voltage of IO lines or turn the IO bus
on/off require controller to be ready before progressing further. When
the controller is ready, it will generate a power irq which needs to be
handled. The thread which initiated the register write should wait for
power irq to complete. This will be done through the new sdhc msm write
APIs which will check whether the particular write can trigger a power
irq and wait for it with a timeout if it is expected.
The SDHC core power control IRQ gets triggered when -
* There is a state change in power control bit (bit 0)
   of SDHCI_POWER_CONTROL register.
* There is a state change in 1.8V enable bit (bit 3) of
   SDHCI_HOST_CONTROL2 register.
* Bit 1 of SDHCI_SOFTWARE_RESET is set.

Also add support APIs which are used by sdhc msm write APIs to check
if power irq is expected to be generated and wait for the power irq
to come and complete if the irq is expected.

This patch requires CONFIG_MMC_SDHCI_IO_ACCESSORS to be enabled.

Signed-off-by: Sahitya Tummala 
Signed-off-by: Vijay Viswanath 
---
  drivers/mmc/host/sdhci-msm.c | 173 ++-
  1 file changed, 171 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c


[..]


+/*
+ * sdhci_msm_check_power_status API should be called when registers writes
+ * which can toggle sdhci IO bus ON/OFF or change IO lines HIGH/LOW happens.
+ * To what state the register writes will change the IO lines should be passed
+ * as the argument req_type. This API will check whether the IO line's state
+ * is already the expected state and will wait for power irq only if
+ * power irq is expected to be trigerred based on the current IO line state
+ * and expected IO line state.
+ */
+static void sdhci_msm_check_power_status(struct sdhci_host *host, u32 req_type)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+   bool done = false;
+
+   pr_debug("%s: %s: request %d curr_pwr_state %x curr_io_level %x\n",
+   mmc_hostname(host->mmc), __func__, req_type,
+   msm_host->curr_pwr_state, msm_host->curr_io_level);
+
+   /*
+* The IRQ for request type IO High/LOW will be generated when -
+* there is a state change in 1.8V enable bit (bit 3) of
+* SDHCI_HOST_CONTROL2 register. The reset state of that bit is 0
+* which indicates 3.3V IO voltage. So, when MMC core layer tries
+* to set it to 3.3V before card detection happens, the
+* IRQ doesn't get triggered as there is no state change in this bit.
+* The driver already handles this case by changing the IO voltage
+* level to high as part of controller power up sequence. Hence, check
+* for host->pwr to handle a case where IO voltage high request is
+* issued even before controller power up.
+*/
+   if ((req_type & REQ_IO_HIGH) && !host->pwr) {
+   pr_debug("%s: do not wait for power IRQ that never comes, req_type: 
%d\n",
+   mmc_hostname(host->mmc), req_type);
+   return;
+   }
+   if ((req_type & msm_host->curr_pwr_state) ||
+   (req_type & msm_host->curr_io_level))
+   done = true;
+   /*
+* This is needed here to handle cases where register writes will
+* not change the current bus state or io l

Re: [PATCH v2 4/4] mmc: sdhci-msm: Add sdhci msm register write APIs which wait for pwr irq

2018-05-30 Thread Vijay Viswanath

Hi Georgi,

Thanks for testing the patch on 8096 and pointing out this issue.
The issue is coming because, when card is removed, the HOST_CONTROL2 
register is retaining the 1.8V Signalling enable bit till SDHCI reset 
happens after a new card is inserted.


Adding the change you suggested can avoid this wait, but I feel a better 
solution is to clear the 1.8V signalling bit when the card is removed. 
When a new card is inserted, we shouldn't be keeping the 1.8V bit set 
until we send cmd11 to the SD card. A new SD card should start with 3V.


One solution is to explicitly clear the HOST_CONTROL2 register when card 
is removed.


Other way is to revert the commit: 
9718f84b85396e090ca42fafa730410d286d61e3 "mmc: sdhci-msm: Do not reset 
the controller if no card in the slot"


The sdhci-msm doesn't require "SDHCI_QUIRK_NO_CARD_NO_RESET". The issue 
which above commit is trying to avoid is fixed by the pwr-irq patches. 
Resetting the controller will clear the HOST_CONTROL2 register and avoid 
this issue.


Can you please try this ? I tested reverting the QUIRK on two platforms: 
db410c(8916) and sdm845. SD card insert/remove worked fine after that 
and I didn't get any "Reset 0x1 never completed" error during card 
insert/remove or shutdown.


Thanks,
Vijay

On 5/29/2018 5:49 PM, Georgi Djakov wrote:

Hello Vijay,

On 09/27/2017 08:34 AM, Vijay Viswanath wrote:

Register writes which change voltage of IO lines or turn the IO bus
on/off require controller to be ready before progressing further. When
the controller is ready, it will generate a power irq which needs to be
handled. The thread which initiated the register write should wait for
power irq to complete. This will be done through the new sdhc msm write
APIs which will check whether the particular write can trigger a power
irq and wait for it with a timeout if it is expected.
The SDHC core power control IRQ gets triggered when -
* There is a state change in power control bit (bit 0)
   of SDHCI_POWER_CONTROL register.
* There is a state change in 1.8V enable bit (bit 3) of
   SDHCI_HOST_CONTROL2 register.
* Bit 1 of SDHCI_SOFTWARE_RESET is set.

Also add support APIs which are used by sdhc msm write APIs to check
if power irq is expected to be generated and wait for the power irq
to come and complete if the irq is expected.

This patch requires CONFIG_MMC_SDHCI_IO_ACCESSORS to be enabled.

Signed-off-by: Sahitya Tummala 
Signed-off-by: Vijay Viswanath 
---
  drivers/mmc/host/sdhci-msm.c | 173 ++-
  1 file changed, 171 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c


[..]


+/*
+ * sdhci_msm_check_power_status API should be called when registers writes
+ * which can toggle sdhci IO bus ON/OFF or change IO lines HIGH/LOW happens.
+ * To what state the register writes will change the IO lines should be passed
+ * as the argument req_type. This API will check whether the IO line's state
+ * is already the expected state and will wait for power irq only if
+ * power irq is expected to be trigerred based on the current IO line state
+ * and expected IO line state.
+ */
+static void sdhci_msm_check_power_status(struct sdhci_host *host, u32 req_type)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+   bool done = false;
+
+   pr_debug("%s: %s: request %d curr_pwr_state %x curr_io_level %x\n",
+   mmc_hostname(host->mmc), __func__, req_type,
+   msm_host->curr_pwr_state, msm_host->curr_io_level);
+
+   /*
+* The IRQ for request type IO High/LOW will be generated when -
+* there is a state change in 1.8V enable bit (bit 3) of
+* SDHCI_HOST_CONTROL2 register. The reset state of that bit is 0
+* which indicates 3.3V IO voltage. So, when MMC core layer tries
+* to set it to 3.3V before card detection happens, the
+* IRQ doesn't get triggered as there is no state change in this bit.
+* The driver already handles this case by changing the IO voltage
+* level to high as part of controller power up sequence. Hence, check
+* for host->pwr to handle a case where IO voltage high request is
+* issued even before controller power up.
+*/
+   if ((req_type & REQ_IO_HIGH) && !host->pwr) {
+   pr_debug("%s: do not wait for power IRQ that never comes, req_type: 
%d\n",
+   mmc_hostname(host->mmc), req_type);
+   return;
+   }
+   if ((req_type & msm_host->curr_pwr_state) ||
+   (req_type & msm_host->curr_io_level))
+   done = true;
+   /*
+* This is needed here to handle cases where register writes will
+* not change the current bus state or io l

[PATCH V2 4/4] mmc: host: Register changes for sdcc V5

2018-05-29 Thread Vijay Viswanath
Add support to use the new compatible string "qcom,sdhci-msm-v5".

Based on the msm variant, pick the relevant variant data and
use it for register read/write to msm specific registers.

Signed-off-by: Sayali Lokhande 
Signed-off-by: Vijay Viswanath 
---
 drivers/mmc/host/sdhci-msm.c | 347 +++
 1 file changed, 221 insertions(+), 126 deletions(-)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 2a66aa0..4d0fd2d 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -33,16 +33,11 @@
 #define CORE_MCI_GENERICS  0x70
 #define SWITCHABLE_SIGNALING_VOLTAGE   BIT(29)
 
-#define CORE_HC_MODE   0x78
 #define HC_MODE_EN 0x1
 #define CORE_POWER 0x0
 #define CORE_SW_RSTBIT(7)
 #define FF_CLK_SW_RST_DIS  BIT(13)
 
-#define CORE_PWRCTL_STATUS 0xdc
-#define CORE_PWRCTL_MASK   0xe0
-#define CORE_PWRCTL_CLEAR  0xe4
-#define CORE_PWRCTL_CTL0xe8
 #define CORE_PWRCTL_BUS_OFFBIT(0)
 #define CORE_PWRCTL_BUS_ON BIT(1)
 #define CORE_PWRCTL_IO_LOW BIT(2)
@@ -63,17 +58,13 @@
 #define CORE_CDR_EXT_ENBIT(19)
 #define CORE_DLL_PDN   BIT(29)
 #define CORE_DLL_RST   BIT(30)
-#define CORE_DLL_CONFIG0x100
 #define CORE_CMD_DAT_TRACK_SEL BIT(0)
-#define CORE_DLL_STATUS0x108
 
-#define CORE_DLL_CONFIG_2  0x1b4
 #define CORE_DDR_CAL_ENBIT(0)
 #define CORE_FLL_CYCLE_CNT BIT(18)
 #define CORE_DLL_CLOCK_DISABLE BIT(21)
 
-#define CORE_VENDOR_SPEC   0x10c
-#define CORE_VENDOR_SPEC_POR_VAL   0xa1c
+#define CORE_VENDOR_SPEC_POR_VAL 0xa1c
 #define CORE_CLK_PWRSAVE   BIT(1)
 #define CORE_HC_MCLK_SEL_DFLT  (2 << 8)
 #define CORE_HC_MCLK_SEL_HS400 (3 << 8)
@@ -111,17 +102,14 @@
 #define CORE_CDC_SWITCH_BYPASS_OFF BIT(0)
 #define CORE_CDC_SWITCH_RC_EN  BIT(1)
 
-#define CORE_DDR_200_CFG   0x184
 #define CORE_CDC_T4_DLY_SELBIT(0)
 #define CORE_CMDIN_RCLK_EN BIT(1)
 #define CORE_START_CDC_TRAFFIC BIT(6)
-#define CORE_VENDOR_SPEC3  0x1b0
+
 #define CORE_PWRSAVE_DLL   BIT(3)
 
-#define CORE_DDR_CONFIG0x1b8
 #define DDR_CONFIG_POR_VAL 0x80040853
 
-#define CORE_VENDOR_SPEC_CAPABILITIES0 0x11c
 
 #define INVALID_TUNING_PHASE   -1
 #define SDHCI_MSM_MIN_CLOCK40
@@ -137,6 +125,12 @@
 /* Timeout value to avoid infinite waiting for pwr_irq */
 #define MSM_PWR_IRQ_TIMEOUT_MS 5000
 
+#define MSM_HOST_READL(msm_host, host, offset) \
+   msm_host->var_ops->msm_readl_relaxed(host, offset)
+
+#define MSM_HOST_WRITEL(msm_host, val, host, offset) \
+   msm_host->var_ops->msm_writel_relaxed(val, host, offset)
+
 struct sdhci_msm_offset {
u32 core_hc_mode;
u32 core_mci_data_cnt;
@@ -268,6 +262,14 @@ struct sdhci_msm_host {
const struct sdhci_msm_offset *offset;
 };
 
+const struct sdhci_msm_offset *sdhci_priv_msm_offset(struct sdhci_host *host)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+   return msm_host->offset;
+}
+
 /*
  * APIs to read/write to vendor specific registers which were there in the
  * core_mem region before MCI was removed.
@@ -349,10 +351,12 @@ static inline int msm_dll_poll_ck_out_en(struct 
sdhci_host *host, u8 poll)
u32 wait_cnt = 50;
u8 ck_out_en;
struct mmc_host *mmc = host->mmc;
+   const struct sdhci_msm_offset *msm_offset =
+   sdhci_priv_msm_offset(host);
 
/* Poll for CK_OUT_EN bit.  max. poll time = 50us */
-   ck_out_en = !!(readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) &
-   CORE_CK_OUT_EN);
+   ck_out_en = !!(readl_relaxed(host->ioaddr +
+   msm_offset->core_dll_config) & CORE_CK_OUT_EN);
 
while (ck_out_en != poll) {
if (--wait_cnt == 0) {
@@ -362,8 +366,8 @@ static inline int msm_dll_poll_ck_out_en(struct sdhci_host 
*host, u8 poll)
}
udelay(1);
 
-   ck_out_en = !!(readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) &
-   CORE_CK_OUT_EN);
+   ck_out_en = !!(readl_relaxed(host->ioaddr +
+   msm_offset->core_dll_config) & CORE_CK_OUT_EN);
}
 
return 0;
@@ -379,16 +383,18 @@ static int msm_config_cm_dll_phase(struct sdhci_host 
*host, u8 phase)
unsigned long flags;
u32 config;
struct mmc_host *mmc = host->mmc;
+   const struct sdhci_msm_offset *msm_offset =
+   sdhci_priv_msm_offset(host);
 
if (phase > 0xf)
return -EINVAL;
 
spin_lock_irqsave(>lock, flags);
 
-   config = readl_relaxed(host-&

[PATCH V2 4/4] mmc: host: Register changes for sdcc V5

2018-05-29 Thread Vijay Viswanath
Add support to use the new compatible string "qcom,sdhci-msm-v5".

Based on the msm variant, pick the relevant variant data and
use it for register read/write to msm specific registers.

Signed-off-by: Sayali Lokhande 
Signed-off-by: Vijay Viswanath 
---
 drivers/mmc/host/sdhci-msm.c | 347 +++
 1 file changed, 221 insertions(+), 126 deletions(-)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 2a66aa0..4d0fd2d 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -33,16 +33,11 @@
 #define CORE_MCI_GENERICS  0x70
 #define SWITCHABLE_SIGNALING_VOLTAGE   BIT(29)
 
-#define CORE_HC_MODE   0x78
 #define HC_MODE_EN 0x1
 #define CORE_POWER 0x0
 #define CORE_SW_RSTBIT(7)
 #define FF_CLK_SW_RST_DIS  BIT(13)
 
-#define CORE_PWRCTL_STATUS 0xdc
-#define CORE_PWRCTL_MASK   0xe0
-#define CORE_PWRCTL_CLEAR  0xe4
-#define CORE_PWRCTL_CTL0xe8
 #define CORE_PWRCTL_BUS_OFFBIT(0)
 #define CORE_PWRCTL_BUS_ON BIT(1)
 #define CORE_PWRCTL_IO_LOW BIT(2)
@@ -63,17 +58,13 @@
 #define CORE_CDR_EXT_ENBIT(19)
 #define CORE_DLL_PDN   BIT(29)
 #define CORE_DLL_RST   BIT(30)
-#define CORE_DLL_CONFIG0x100
 #define CORE_CMD_DAT_TRACK_SEL BIT(0)
-#define CORE_DLL_STATUS0x108
 
-#define CORE_DLL_CONFIG_2  0x1b4
 #define CORE_DDR_CAL_ENBIT(0)
 #define CORE_FLL_CYCLE_CNT BIT(18)
 #define CORE_DLL_CLOCK_DISABLE BIT(21)
 
-#define CORE_VENDOR_SPEC   0x10c
-#define CORE_VENDOR_SPEC_POR_VAL   0xa1c
+#define CORE_VENDOR_SPEC_POR_VAL 0xa1c
 #define CORE_CLK_PWRSAVE   BIT(1)
 #define CORE_HC_MCLK_SEL_DFLT  (2 << 8)
 #define CORE_HC_MCLK_SEL_HS400 (3 << 8)
@@ -111,17 +102,14 @@
 #define CORE_CDC_SWITCH_BYPASS_OFF BIT(0)
 #define CORE_CDC_SWITCH_RC_EN  BIT(1)
 
-#define CORE_DDR_200_CFG   0x184
 #define CORE_CDC_T4_DLY_SELBIT(0)
 #define CORE_CMDIN_RCLK_EN BIT(1)
 #define CORE_START_CDC_TRAFFIC BIT(6)
-#define CORE_VENDOR_SPEC3  0x1b0
+
 #define CORE_PWRSAVE_DLL   BIT(3)
 
-#define CORE_DDR_CONFIG0x1b8
 #define DDR_CONFIG_POR_VAL 0x80040853
 
-#define CORE_VENDOR_SPEC_CAPABILITIES0 0x11c
 
 #define INVALID_TUNING_PHASE   -1
 #define SDHCI_MSM_MIN_CLOCK40
@@ -137,6 +125,12 @@
 /* Timeout value to avoid infinite waiting for pwr_irq */
 #define MSM_PWR_IRQ_TIMEOUT_MS 5000
 
+#define MSM_HOST_READL(msm_host, host, offset) \
+   msm_host->var_ops->msm_readl_relaxed(host, offset)
+
+#define MSM_HOST_WRITEL(msm_host, val, host, offset) \
+   msm_host->var_ops->msm_writel_relaxed(val, host, offset)
+
 struct sdhci_msm_offset {
u32 core_hc_mode;
u32 core_mci_data_cnt;
@@ -268,6 +262,14 @@ struct sdhci_msm_host {
const struct sdhci_msm_offset *offset;
 };
 
+const struct sdhci_msm_offset *sdhci_priv_msm_offset(struct sdhci_host *host)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+   return msm_host->offset;
+}
+
 /*
  * APIs to read/write to vendor specific registers which were there in the
  * core_mem region before MCI was removed.
@@ -349,10 +351,12 @@ static inline int msm_dll_poll_ck_out_en(struct 
sdhci_host *host, u8 poll)
u32 wait_cnt = 50;
u8 ck_out_en;
struct mmc_host *mmc = host->mmc;
+   const struct sdhci_msm_offset *msm_offset =
+   sdhci_priv_msm_offset(host);
 
/* Poll for CK_OUT_EN bit.  max. poll time = 50us */
-   ck_out_en = !!(readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) &
-   CORE_CK_OUT_EN);
+   ck_out_en = !!(readl_relaxed(host->ioaddr +
+   msm_offset->core_dll_config) & CORE_CK_OUT_EN);
 
while (ck_out_en != poll) {
if (--wait_cnt == 0) {
@@ -362,8 +366,8 @@ static inline int msm_dll_poll_ck_out_en(struct sdhci_host 
*host, u8 poll)
}
udelay(1);
 
-   ck_out_en = !!(readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) &
-   CORE_CK_OUT_EN);
+   ck_out_en = !!(readl_relaxed(host->ioaddr +
+   msm_offset->core_dll_config) & CORE_CK_OUT_EN);
}
 
return 0;
@@ -379,16 +383,18 @@ static int msm_config_cm_dll_phase(struct sdhci_host 
*host, u8 phase)
unsigned long flags;
u32 config;
struct mmc_host *mmc = host->mmc;
+   const struct sdhci_msm_offset *msm_offset =
+   sdhci_priv_msm_offset(host);
 
if (phase > 0xf)
return -EINVAL;
 
spin_lock_irqsave(>lock, flags);
 
-   config = readl_relaxed(host-&

[PATCH V2 2/4] mmc: sdhci-msm: Add msm version specific ops and data structures

2018-05-29 Thread Vijay Viswanath
In addition to offsets of certain registers changing, the registers in
core_mem have been shifted to HC mem as well. To access these
registers, define msm version specific functions. These functions can
be loaded into the function pointers at the time of probe based on
the msm version detected.

Also defind new data structure to hold version specific Ops and
register addresses.

Signed-off-by: Sayali Lokhande 
Signed-off-by: Vijay Viswanath 
---
 drivers/mmc/host/sdhci-msm.c | 77 
 1 file changed, 77 insertions(+)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 4050c99..2a66aa0 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -226,6 +226,24 @@ struct sdhci_msm_offset {
.core_ddr_config_2 = 0x1bc,
 };
 
+struct sdhci_msm_variant_ops {
+   u8 (*msm_readb_relaxed)(struct sdhci_host *host, u32 offset);
+   u32 (*msm_readl_relaxed)(struct sdhci_host *host, u32 offset);
+   void (*msm_writeb_relaxed)(u8 val, struct sdhci_host *host, u32 offset);
+   void (*msm_writel_relaxed)(u32 val, struct sdhci_host *host,
+   u32 offset);
+};
+
+/*
+ * From V5, register spaces have changed. Wrap this info in a structure
+ * and choose the data_structure based on version info mentioned in DT.
+ */
+struct sdhci_msm_variant_info {
+   bool mci_removed;
+   const struct sdhci_msm_variant_ops *var_ops;
+   const struct sdhci_msm_offset *offset;
+};
+
 struct sdhci_msm_host {
struct platform_device *pdev;
void __iomem *core_mem; /* MSM SDCC mapped address */
@@ -245,8 +263,45 @@ struct sdhci_msm_host {
wait_queue_head_t pwr_irq_wait;
bool pwr_irq_flag;
u32 caps_0;
+   bool mci_removed;
+   const struct sdhci_msm_variant_ops *var_ops;
+   const struct sdhci_msm_offset *offset;
 };
 
+/*
+ * APIs to read/write to vendor specific registers which were there in the
+ * core_mem region before MCI was removed.
+ */
+static u32 sdhci_msm_mci_variant_readl_relaxed(struct sdhci_host *host,
+   u32 offset)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+   return readl_relaxed(msm_host->core_mem + offset);
+}
+
+static u32 sdhci_msm_v5_variant_readl_relaxed(struct sdhci_host *host,
+   u32 offset)
+{
+   return readl_relaxed(host->ioaddr + offset);
+}
+
+static void sdhci_msm_mci_variant_writel_relaxed(u32 val,
+   struct sdhci_host *host, u32 offset)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+   writel_relaxed(val, msm_host->core_mem + offset);
+}
+
+static void sdhci_msm_v5_variant_writel_relaxed(u32 val,
+   struct sdhci_host *host, u32 offset)
+{
+   writel_relaxed(val, host->ioaddr + offset);
+}
+
 static unsigned int msm_get_clock_rate_for_bus_mode(struct sdhci_host *host,
unsigned int clock)
 {
@@ -1481,6 +1536,28 @@ 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 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,
+};
+
+static const struct sdhci_msm_variant_ops v5_var_ops = {
+   .msm_readl_relaxed = sdhci_msm_v5_variant_readl_relaxed,
+   .msm_writel_relaxed = sdhci_msm_v5_variant_writel_relaxed,
+};
+
+static const struct sdhci_msm_variant_info sdhci_msm_mci_var = {
+   .mci_removed = 0,
+   .var_ops = _var_ops,
+   .offset = _msm_mci_offset,
+};
+
+static const struct sdhci_msm_variant_info sdhci_msm_v5_var = {
+   .mci_removed = 1,
+   .var_ops = _var_ops,
+   .offset = _msm_v5_offset,
+};
+
 static const struct of_device_id sdhci_msm_dt_match[] = {
{ .compatible = "qcom,sdhci-msm-v4" },
{},
-- 
 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.



[PATCH V2 3/4] Documentation: sdhci-msm: Add new compatible string for SDCC v5

2018-05-29 Thread Vijay Viswanath
From: Sayali Lokhande 

For SDCC version 5.0.0 and higher, new compatible string
"qcom,sdhci-msm-v5" is added.

Signed-off-by: Sayali Lokhande 
Signed-off-by: Vijay Viswanath 
---
 Documentation/devicetree/bindings/mmc/sdhci-msm.txt | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt 
b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
index bfdcdc4..502b3b8 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
@@ -4,7 +4,12 @@ This file documents differences between the core properties in 
mmc.txt
 and the properties used by the sdhci-msm driver.
 
 Required properties:
-- compatible: Should contain "qcom,sdhci-msm-v4".
+- compatible: Should contain:
+   "qcom,sdhci-msm-v4" for sdcc versions less than 5.0
+   "qcom,sdhci-msm-v5" for sdcc versions >= 5.0
+   For SDCC version 5.0.0, MCI registers are removed from SDCC
+   interface and some registers are moved to HC. New compatible
+   string is added to support this change - "qcom,sdhci-msm-v5".
 - reg: Base address and length of the register in the following order:
- Host controller register map (required)
- SD Core register map (required)
-- 
 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.



[PATCH V2 2/4] mmc: sdhci-msm: Add msm version specific ops and data structures

2018-05-29 Thread Vijay Viswanath
In addition to offsets of certain registers changing, the registers in
core_mem have been shifted to HC mem as well. To access these
registers, define msm version specific functions. These functions can
be loaded into the function pointers at the time of probe based on
the msm version detected.

Also defind new data structure to hold version specific Ops and
register addresses.

Signed-off-by: Sayali Lokhande 
Signed-off-by: Vijay Viswanath 
---
 drivers/mmc/host/sdhci-msm.c | 77 
 1 file changed, 77 insertions(+)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 4050c99..2a66aa0 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -226,6 +226,24 @@ struct sdhci_msm_offset {
.core_ddr_config_2 = 0x1bc,
 };
 
+struct sdhci_msm_variant_ops {
+   u8 (*msm_readb_relaxed)(struct sdhci_host *host, u32 offset);
+   u32 (*msm_readl_relaxed)(struct sdhci_host *host, u32 offset);
+   void (*msm_writeb_relaxed)(u8 val, struct sdhci_host *host, u32 offset);
+   void (*msm_writel_relaxed)(u32 val, struct sdhci_host *host,
+   u32 offset);
+};
+
+/*
+ * From V5, register spaces have changed. Wrap this info in a structure
+ * and choose the data_structure based on version info mentioned in DT.
+ */
+struct sdhci_msm_variant_info {
+   bool mci_removed;
+   const struct sdhci_msm_variant_ops *var_ops;
+   const struct sdhci_msm_offset *offset;
+};
+
 struct sdhci_msm_host {
struct platform_device *pdev;
void __iomem *core_mem; /* MSM SDCC mapped address */
@@ -245,8 +263,45 @@ struct sdhci_msm_host {
wait_queue_head_t pwr_irq_wait;
bool pwr_irq_flag;
u32 caps_0;
+   bool mci_removed;
+   const struct sdhci_msm_variant_ops *var_ops;
+   const struct sdhci_msm_offset *offset;
 };
 
+/*
+ * APIs to read/write to vendor specific registers which were there in the
+ * core_mem region before MCI was removed.
+ */
+static u32 sdhci_msm_mci_variant_readl_relaxed(struct sdhci_host *host,
+   u32 offset)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+   return readl_relaxed(msm_host->core_mem + offset);
+}
+
+static u32 sdhci_msm_v5_variant_readl_relaxed(struct sdhci_host *host,
+   u32 offset)
+{
+   return readl_relaxed(host->ioaddr + offset);
+}
+
+static void sdhci_msm_mci_variant_writel_relaxed(u32 val,
+   struct sdhci_host *host, u32 offset)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+   writel_relaxed(val, msm_host->core_mem + offset);
+}
+
+static void sdhci_msm_v5_variant_writel_relaxed(u32 val,
+   struct sdhci_host *host, u32 offset)
+{
+   writel_relaxed(val, host->ioaddr + offset);
+}
+
 static unsigned int msm_get_clock_rate_for_bus_mode(struct sdhci_host *host,
unsigned int clock)
 {
@@ -1481,6 +1536,28 @@ 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 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,
+};
+
+static const struct sdhci_msm_variant_ops v5_var_ops = {
+   .msm_readl_relaxed = sdhci_msm_v5_variant_readl_relaxed,
+   .msm_writel_relaxed = sdhci_msm_v5_variant_writel_relaxed,
+};
+
+static const struct sdhci_msm_variant_info sdhci_msm_mci_var = {
+   .mci_removed = 0,
+   .var_ops = _var_ops,
+   .offset = _msm_mci_offset,
+};
+
+static const struct sdhci_msm_variant_info sdhci_msm_v5_var = {
+   .mci_removed = 1,
+   .var_ops = _var_ops,
+   .offset = _msm_v5_offset,
+};
+
 static const struct of_device_id sdhci_msm_dt_match[] = {
{ .compatible = "qcom,sdhci-msm-v4" },
{},
-- 
 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.



[PATCH V2 3/4] Documentation: sdhci-msm: Add new compatible string for SDCC v5

2018-05-29 Thread Vijay Viswanath
From: Sayali Lokhande 

For SDCC version 5.0.0 and higher, new compatible string
"qcom,sdhci-msm-v5" is added.

Signed-off-by: Sayali Lokhande 
Signed-off-by: Vijay Viswanath 
---
 Documentation/devicetree/bindings/mmc/sdhci-msm.txt | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt 
b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
index bfdcdc4..502b3b8 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
@@ -4,7 +4,12 @@ This file documents differences between the core properties in 
mmc.txt
 and the properties used by the sdhci-msm driver.
 
 Required properties:
-- compatible: Should contain "qcom,sdhci-msm-v4".
+- compatible: Should contain:
+   "qcom,sdhci-msm-v4" for sdcc versions less than 5.0
+   "qcom,sdhci-msm-v5" for sdcc versions >= 5.0
+   For SDCC version 5.0.0, MCI registers are removed from SDCC
+   interface and some registers are moved to HC. New compatible
+   string is added to support this change - "qcom,sdhci-msm-v5".
 - reg: Base address and length of the register in the following order:
- Host controller register map (required)
- SD Core register map (required)
-- 
 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.



[PATCH V2 1/4] mmc: sdhci-msm: Define new Register address map

2018-05-29 Thread Vijay Viswanath
From: Sayali Lokhande 

For SDCC version 5.0.0, MCI registers are removed from SDCC
interface and some registers are moved to HC.
Define a new data structure where we can statically define
the address offsets for the registers in different SDCC versions.

Signed-off-by: Sayali Lokhande 
Signed-off-by: Vijay Viswanath 
---
 drivers/mmc/host/sdhci-msm.c | 89 
 1 file changed, 89 insertions(+)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index bb11916..4050c99 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -137,6 +137,95 @@
 /* Timeout value to avoid infinite waiting for pwr_irq */
 #define MSM_PWR_IRQ_TIMEOUT_MS 5000
 
+struct sdhci_msm_offset {
+   u32 core_hc_mode;
+   u32 core_mci_data_cnt;
+   u32 core_mci_status;
+   u32 core_mci_fifo_cnt;
+   u32 core_mci_version;
+   u32 core_generics;
+   u32 core_testbus_config;
+   u32 core_testbus_sel2_bit;
+   u32 core_testbus_ena;
+   u32 core_testbus_sel2;
+   u32 core_pwrctl_status;
+   u32 core_pwrctl_mask;
+   u32 core_pwrctl_clear;
+   u32 core_pwrctl_ctl;
+   u32 core_sdcc_debug_reg;
+   u32 core_dll_config;
+   u32 core_dll_status;
+   u32 core_vendor_spec;
+   u32 core_vendor_spec_adma_err_addr0;
+   u32 core_vendor_spec_adma_err_addr1;
+   u32 core_vendor_spec_func2;
+   u32 core_vendor_spec_capabilities0;
+   u32 core_ddr_200_cfg;
+   u32 core_vendor_spec3;
+   u32 core_dll_config_2;
+   u32 core_ddr_config;
+   u32 core_ddr_config_2;
+};
+
+static const struct sdhci_msm_offset sdhci_msm_v5_offset = {
+   .core_mci_data_cnt = 0x35c,
+   .core_mci_status = 0x324,
+   .core_mci_fifo_cnt = 0x308,
+   .core_mci_version = 0x318,
+   .core_generics = 0x320,
+   .core_testbus_config = 0x32c,
+   .core_testbus_sel2_bit = 3,
+   .core_testbus_ena = (1 << 31),
+   .core_testbus_sel2 = (1 << 3),
+   .core_pwrctl_status = 0x240,
+   .core_pwrctl_mask = 0x244,
+   .core_pwrctl_clear = 0x248,
+   .core_pwrctl_ctl = 0x24c,
+   .core_sdcc_debug_reg = 0x358,
+   .core_dll_config = 0x200,
+   .core_dll_status = 0x208,
+   .core_vendor_spec = 0x20c,
+   .core_vendor_spec_adma_err_addr0 = 0x214,
+   .core_vendor_spec_adma_err_addr1 = 0x218,
+   .core_vendor_spec_func2 = 0x210,
+   .core_vendor_spec_capabilities0 = 0x21c,
+   .core_ddr_200_cfg = 0x224,
+   .core_vendor_spec3 = 0x250,
+   .core_dll_config_2 = 0x254,
+   .core_ddr_config = 0x258,
+   .core_ddr_config_2 = 0x25c,
+};
+
+static const struct sdhci_msm_offset sdhci_msm_mci_offset = {
+   .core_hc_mode = 0x78,
+   .core_mci_data_cnt = 0x30,
+   .core_mci_status = 0x34,
+   .core_mci_fifo_cnt = 0x44,
+   .core_mci_version = 0x050,
+   .core_generics = 0x70,
+   .core_testbus_config = 0x0cc,
+   .core_testbus_sel2_bit = 4,
+   .core_testbus_ena = (1 << 3),
+   .core_testbus_sel2 = (1 << 4),
+   .core_pwrctl_status = 0xdc,
+   .core_pwrctl_mask = 0xe0,
+   .core_pwrctl_clear = 0xe4,
+   .core_pwrctl_ctl = 0xe8,
+   .core_sdcc_debug_reg = 0x124,
+   .core_dll_config = 0x100,
+   .core_dll_status = 0x108,
+   .core_vendor_spec = 0x10c,
+   .core_vendor_spec_adma_err_addr0 = 0x114,
+   .core_vendor_spec_adma_err_addr1 = 0x118,
+   .core_vendor_spec_func2 = 0x110,
+   .core_vendor_spec_capabilities0 = 0x11c,
+   .core_ddr_200_cfg = 0x184,
+   .core_vendor_spec3 = 0x1b0,
+   .core_dll_config_2 = 0x1b4,
+   .core_ddr_config = 0x1b8,
+   .core_ddr_config_2 = 0x1bc,
+};
+
 struct sdhci_msm_host {
struct platform_device *pdev;
void __iomem *core_mem; /* MSM SDCC 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.



[PATCH V2 1/4] mmc: sdhci-msm: Define new Register address map

2018-05-29 Thread Vijay Viswanath
From: Sayali Lokhande 

For SDCC version 5.0.0, MCI registers are removed from SDCC
interface and some registers are moved to HC.
Define a new data structure where we can statically define
the address offsets for the registers in different SDCC versions.

Signed-off-by: Sayali Lokhande 
Signed-off-by: Vijay Viswanath 
---
 drivers/mmc/host/sdhci-msm.c | 89 
 1 file changed, 89 insertions(+)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index bb11916..4050c99 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -137,6 +137,95 @@
 /* Timeout value to avoid infinite waiting for pwr_irq */
 #define MSM_PWR_IRQ_TIMEOUT_MS 5000
 
+struct sdhci_msm_offset {
+   u32 core_hc_mode;
+   u32 core_mci_data_cnt;
+   u32 core_mci_status;
+   u32 core_mci_fifo_cnt;
+   u32 core_mci_version;
+   u32 core_generics;
+   u32 core_testbus_config;
+   u32 core_testbus_sel2_bit;
+   u32 core_testbus_ena;
+   u32 core_testbus_sel2;
+   u32 core_pwrctl_status;
+   u32 core_pwrctl_mask;
+   u32 core_pwrctl_clear;
+   u32 core_pwrctl_ctl;
+   u32 core_sdcc_debug_reg;
+   u32 core_dll_config;
+   u32 core_dll_status;
+   u32 core_vendor_spec;
+   u32 core_vendor_spec_adma_err_addr0;
+   u32 core_vendor_spec_adma_err_addr1;
+   u32 core_vendor_spec_func2;
+   u32 core_vendor_spec_capabilities0;
+   u32 core_ddr_200_cfg;
+   u32 core_vendor_spec3;
+   u32 core_dll_config_2;
+   u32 core_ddr_config;
+   u32 core_ddr_config_2;
+};
+
+static const struct sdhci_msm_offset sdhci_msm_v5_offset = {
+   .core_mci_data_cnt = 0x35c,
+   .core_mci_status = 0x324,
+   .core_mci_fifo_cnt = 0x308,
+   .core_mci_version = 0x318,
+   .core_generics = 0x320,
+   .core_testbus_config = 0x32c,
+   .core_testbus_sel2_bit = 3,
+   .core_testbus_ena = (1 << 31),
+   .core_testbus_sel2 = (1 << 3),
+   .core_pwrctl_status = 0x240,
+   .core_pwrctl_mask = 0x244,
+   .core_pwrctl_clear = 0x248,
+   .core_pwrctl_ctl = 0x24c,
+   .core_sdcc_debug_reg = 0x358,
+   .core_dll_config = 0x200,
+   .core_dll_status = 0x208,
+   .core_vendor_spec = 0x20c,
+   .core_vendor_spec_adma_err_addr0 = 0x214,
+   .core_vendor_spec_adma_err_addr1 = 0x218,
+   .core_vendor_spec_func2 = 0x210,
+   .core_vendor_spec_capabilities0 = 0x21c,
+   .core_ddr_200_cfg = 0x224,
+   .core_vendor_spec3 = 0x250,
+   .core_dll_config_2 = 0x254,
+   .core_ddr_config = 0x258,
+   .core_ddr_config_2 = 0x25c,
+};
+
+static const struct sdhci_msm_offset sdhci_msm_mci_offset = {
+   .core_hc_mode = 0x78,
+   .core_mci_data_cnt = 0x30,
+   .core_mci_status = 0x34,
+   .core_mci_fifo_cnt = 0x44,
+   .core_mci_version = 0x050,
+   .core_generics = 0x70,
+   .core_testbus_config = 0x0cc,
+   .core_testbus_sel2_bit = 4,
+   .core_testbus_ena = (1 << 3),
+   .core_testbus_sel2 = (1 << 4),
+   .core_pwrctl_status = 0xdc,
+   .core_pwrctl_mask = 0xe0,
+   .core_pwrctl_clear = 0xe4,
+   .core_pwrctl_ctl = 0xe8,
+   .core_sdcc_debug_reg = 0x124,
+   .core_dll_config = 0x100,
+   .core_dll_status = 0x108,
+   .core_vendor_spec = 0x10c,
+   .core_vendor_spec_adma_err_addr0 = 0x114,
+   .core_vendor_spec_adma_err_addr1 = 0x118,
+   .core_vendor_spec_func2 = 0x110,
+   .core_vendor_spec_capabilities0 = 0x11c,
+   .core_ddr_200_cfg = 0x184,
+   .core_vendor_spec3 = 0x1b0,
+   .core_dll_config_2 = 0x1b4,
+   .core_ddr_config = 0x1b8,
+   .core_ddr_config_2 = 0x1bc,
+};
+
 struct sdhci_msm_host {
struct platform_device *pdev;
void __iomem *core_mem; /* MSM SDCC 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.



[PATCH V2 0/4] Changes for SDCC5 version

2018-05-29 Thread Vijay Viswanath
With SDCC5, the MCI register space got removed and the offset/order of
several registers have changed. Based on SDCC version used and the register,
we need to pick the base address and offset.

Changes since RFC:
Dropped voltage regulator changes in sdhci-msm
Split the "Register changes for sdcc V5" patch
Instead of checking mci removal for deciding which base addr to use,
new function pointers are defined for the 2 variants of sdcc: 
1) MCI present
2) V5 (mci removed)
Instead of string comparing with the compatible string from DT file,
the sdhci_msm_probe will now pick the data associated with the
compatible entry and use it to load variant specific address offsets
and msm variant specific read/write ops.

Changes since V1:
Removed unused msm_reab & msm_writeb APIs
Changed certain register addresses from uppercase to lowercase hex
letters
Removed extra lines and spaces
Split "[PATCH V1 0/3] Changes for SDCC5 version" patch into two,
one for Documentation and other for the driver changes.

Sayali Lokhande (2):
  mmc: sdhci-msm: Define new Register address map
  Documentation: sdhci-msm: Add new compatible string for SDCC v5

Vijay Viswanath (2):
  mmc: sdhci-msm: Add msm version specific ops and data structures
  mmc: host: Register changes for sdcc V5

 .../devicetree/bindings/mmc/sdhci-msm.txt  |   7 +-
 drivers/mmc/host/sdhci-msm.c   | 513 -
 2 files changed, 393 insertions(+), 127 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.



[PATCH V2 0/4] Changes for SDCC5 version

2018-05-29 Thread Vijay Viswanath
With SDCC5, the MCI register space got removed and the offset/order of
several registers have changed. Based on SDCC version used and the register,
we need to pick the base address and offset.

Changes since RFC:
Dropped voltage regulator changes in sdhci-msm
Split the "Register changes for sdcc V5" patch
Instead of checking mci removal for deciding which base addr to use,
new function pointers are defined for the 2 variants of sdcc: 
1) MCI present
2) V5 (mci removed)
Instead of string comparing with the compatible string from DT file,
the sdhci_msm_probe will now pick the data associated with the
compatible entry and use it to load variant specific address offsets
and msm variant specific read/write ops.

Changes since V1:
Removed unused msm_reab & msm_writeb APIs
Changed certain register addresses from uppercase to lowercase hex
letters
Removed extra lines and spaces
Split "[PATCH V1 0/3] Changes for SDCC5 version" patch into two,
one for Documentation and other for the driver changes.

Sayali Lokhande (2):
  mmc: sdhci-msm: Define new Register address map
  Documentation: sdhci-msm: Add new compatible string for SDCC v5

Vijay Viswanath (2):
  mmc: sdhci-msm: Add msm version specific ops and data structures
  mmc: host: Register changes for sdcc V5

 .../devicetree/bindings/mmc/sdhci-msm.txt  |   7 +-
 drivers/mmc/host/sdhci-msm.c   | 513 -
 2 files changed, 393 insertions(+), 127 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.



Re: [PATCH V1 3/3] mmc: host: Register changes for sdcc V5

2018-05-24 Thread Vijay Viswanath



On 5/22/2018 11:42 PM, Evan Green wrote:

Hi Vijay. Thanks for this patch.

On Thu, May 17, 2018 at 3:30 AM Vijay Viswanath <vvisw...@codeaurora.org>
wrote:


From: Sayali Lokhande <saya...@codeaurora.org>



For SDCC version 5.0.0 and higher, new compatible string
"qcom,sdhci-msm-v5" is added.



Based on the msm variant, pick the relevant variant data and
use it for register read/write to msm specific registers.



Signed-off-by: Sayali Lokhande <saya...@codeaurora.org>
Signed-off-by: Vijay Viswanath <vvisw...@codeaurora.org>
---
   .../devicetree/bindings/mmc/sdhci-msm.txt  |   5 +-
   drivers/mmc/host/sdhci-msm.c   | 344

+

   2 files changed, 222 insertions(+), 127 deletions(-)



diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt

b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt

index bfdcdc4..c2b7b2b 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
@@ -4,7 +4,10 @@ This file documents differences between the core

properties in mmc.txt

   and the properties used by the sdhci-msm driver.



   Required properties:
-- compatible: Should contain "qcom,sdhci-msm-v4".
+- compatible: Should contain "qcom,sdhci-msm-v4" or "qcom,sdhci-msm-v5".
+For SDCC version 5.0.0, MCI registers are removed from

SDCC

+interface and some registers are moved to HC. New

compatible

+string is added to support this change -

"qcom,sdhci-msm-v5".

   - reg: Base address and length of the register in the following order:
  - Host controller register map (required)
  - SD Core register map (required)
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index bb2bb59..408e6b2 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -33,16 +33,11 @@
   #define CORE_MCI_GENERICS  0x70
   #define SWITCHABLE_SIGNALING_VOLTAGE   BIT(29)



-#define CORE_HC_MODE   0x78


Remove CORE_MCI_VERSION as well.



Missed it. Will remove


   #define HC_MODE_EN 0x1
   #define CORE_POWER 0x0
   #define CORE_SW_RSTBIT(7)
   #define FF_CLK_SW_RST_DIS  BIT(13)



-#define CORE_PWRCTL_STATUS 0xdc
-#define CORE_PWRCTL_MASK   0xe0
-#define CORE_PWRCTL_CLEAR  0xe4
-#define CORE_PWRCTL_CTL0xe8
   #define CORE_PWRCTL_BUS_OFFBIT(0)
   #define CORE_PWRCTL_BUS_ON BIT(1)
   #define CORE_PWRCTL_IO_LOW BIT(2)
@@ -63,17 +58,13 @@
   #define CORE_CDR_EXT_ENBIT(19)
   #define CORE_DLL_PDN   BIT(29)
   #define CORE_DLL_RST   BIT(30)
-#define CORE_DLL_CONFIG0x100
   #define CORE_CMD_DAT_TRACK_SEL BIT(0)
-#define CORE_DLL_STATUS0x108



-#define CORE_DLL_CONFIG_2  0x1b4
   #define CORE_DDR_CAL_ENBIT(0)
   #define CORE_FLL_CYCLE_CNT BIT(18)
   #define CORE_DLL_CLOCK_DISABLE BIT(21)



-#define CORE_VENDOR_SPEC   0x10c
-#define CORE_VENDOR_SPEC_POR_VAL   0xa1c
+#define CORE_VENDOR_SPEC_POR_VAL 0xa1c
   #define CORE_CLK_PWRSAVE   BIT(1)
   #define CORE_HC_MCLK_SEL_DFLT  (2 << 8)
   #define CORE_HC_MCLK_SEL_HS400 (3 << 8)
@@ -111,17 +102,14 @@
   #define CORE_CDC_SWITCH_BYPASS_OFF BIT(0)
   #define CORE_CDC_SWITCH_RC_EN  BIT(1)



-#define CORE_DDR_200_CFG   0x184
   #define CORE_CDC_T4_DLY_SELBIT(0)
   #define CORE_CMDIN_RCLK_EN BIT(1)
   #define CORE_START_CDC_TRAFFIC BIT(6)
-#define CORE_VENDOR_SPEC3  0x1b0
+
   #define CORE_PWRSAVE_DLL   BIT(3)



-#define CORE_DDR_CONFIG0x1b8
   #define DDR_CONFIG_POR_VAL 0x80040853



-#define CORE_VENDOR_SPEC_CAPABILITIES0 0x11c



   #define INVALID_TUNING_PHASE   -1
   #define SDHCI_MSM_MIN_CLOCK40
@@ -380,10 +368,14 @@ static inline int msm_dll_poll_ck_out_en(struct

sdhci_host *host, u8 poll)

  u32 wait_cnt = 50;
  u8 ck_out_en;
  struct mmc_host *mmc = host->mmc;
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+   const struct sdhci_msm_offset *msm_offset =
+   msm_host->offset;


I notice this pattern is pasted all over the place in order to get to the
offsets. Maybe a macro or inlined function would be cleaner to get you to
directly to the sdhci_msm_offset struct from sdhci_host, rather than this
blob of paste soup everywhere. In some places you do seem to use the
intermediate locals, so those cases wouldn't need to use the new helper.



  /* Poll for CK_OUT_EN bit.  max. poll time = 50us */
-   ck_out_en = !!(readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) &
-   CORE_CK_OUT_EN);
+   ck_out_en = !!

Re: [PATCH V1 3/3] mmc: host: Register changes for sdcc V5

2018-05-24 Thread Vijay Viswanath



On 5/22/2018 11:42 PM, Evan Green wrote:

Hi Vijay. Thanks for this patch.

On Thu, May 17, 2018 at 3:30 AM Vijay Viswanath 
wrote:


From: Sayali Lokhande 



For SDCC version 5.0.0 and higher, new compatible string
"qcom,sdhci-msm-v5" is added.



Based on the msm variant, pick the relevant variant data and
use it for register read/write to msm specific registers.



Signed-off-by: Sayali Lokhande 
Signed-off-by: Vijay Viswanath 
---
   .../devicetree/bindings/mmc/sdhci-msm.txt  |   5 +-
   drivers/mmc/host/sdhci-msm.c   | 344

+

   2 files changed, 222 insertions(+), 127 deletions(-)



diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt

b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt

index bfdcdc4..c2b7b2b 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
@@ -4,7 +4,10 @@ This file documents differences between the core

properties in mmc.txt

   and the properties used by the sdhci-msm driver.



   Required properties:
-- compatible: Should contain "qcom,sdhci-msm-v4".
+- compatible: Should contain "qcom,sdhci-msm-v4" or "qcom,sdhci-msm-v5".
+For SDCC version 5.0.0, MCI registers are removed from

SDCC

+interface and some registers are moved to HC. New

compatible

+string is added to support this change -

"qcom,sdhci-msm-v5".

   - reg: Base address and length of the register in the following order:
  - Host controller register map (required)
  - SD Core register map (required)
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index bb2bb59..408e6b2 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -33,16 +33,11 @@
   #define CORE_MCI_GENERICS  0x70
   #define SWITCHABLE_SIGNALING_VOLTAGE   BIT(29)



-#define CORE_HC_MODE   0x78


Remove CORE_MCI_VERSION as well.



Missed it. Will remove


   #define HC_MODE_EN 0x1
   #define CORE_POWER 0x0
   #define CORE_SW_RSTBIT(7)
   #define FF_CLK_SW_RST_DIS  BIT(13)



-#define CORE_PWRCTL_STATUS 0xdc
-#define CORE_PWRCTL_MASK   0xe0
-#define CORE_PWRCTL_CLEAR  0xe4
-#define CORE_PWRCTL_CTL0xe8
   #define CORE_PWRCTL_BUS_OFFBIT(0)
   #define CORE_PWRCTL_BUS_ON BIT(1)
   #define CORE_PWRCTL_IO_LOW BIT(2)
@@ -63,17 +58,13 @@
   #define CORE_CDR_EXT_ENBIT(19)
   #define CORE_DLL_PDN   BIT(29)
   #define CORE_DLL_RST   BIT(30)
-#define CORE_DLL_CONFIG0x100
   #define CORE_CMD_DAT_TRACK_SEL BIT(0)
-#define CORE_DLL_STATUS0x108



-#define CORE_DLL_CONFIG_2  0x1b4
   #define CORE_DDR_CAL_ENBIT(0)
   #define CORE_FLL_CYCLE_CNT BIT(18)
   #define CORE_DLL_CLOCK_DISABLE BIT(21)



-#define CORE_VENDOR_SPEC   0x10c
-#define CORE_VENDOR_SPEC_POR_VAL   0xa1c
+#define CORE_VENDOR_SPEC_POR_VAL 0xa1c
   #define CORE_CLK_PWRSAVE   BIT(1)
   #define CORE_HC_MCLK_SEL_DFLT  (2 << 8)
   #define CORE_HC_MCLK_SEL_HS400 (3 << 8)
@@ -111,17 +102,14 @@
   #define CORE_CDC_SWITCH_BYPASS_OFF BIT(0)
   #define CORE_CDC_SWITCH_RC_EN  BIT(1)



-#define CORE_DDR_200_CFG   0x184
   #define CORE_CDC_T4_DLY_SELBIT(0)
   #define CORE_CMDIN_RCLK_EN BIT(1)
   #define CORE_START_CDC_TRAFFIC BIT(6)
-#define CORE_VENDOR_SPEC3  0x1b0
+
   #define CORE_PWRSAVE_DLL   BIT(3)



-#define CORE_DDR_CONFIG0x1b8
   #define DDR_CONFIG_POR_VAL 0x80040853



-#define CORE_VENDOR_SPEC_CAPABILITIES0 0x11c



   #define INVALID_TUNING_PHASE   -1
   #define SDHCI_MSM_MIN_CLOCK40
@@ -380,10 +368,14 @@ static inline int msm_dll_poll_ck_out_en(struct

sdhci_host *host, u8 poll)

  u32 wait_cnt = 50;
  u8 ck_out_en;
  struct mmc_host *mmc = host->mmc;
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+   const struct sdhci_msm_offset *msm_offset =
+   msm_host->offset;


I notice this pattern is pasted all over the place in order to get to the
offsets. Maybe a macro or inlined function would be cleaner to get you to
directly to the sdhci_msm_offset struct from sdhci_host, rather than this
blob of paste soup everywhere. In some places you do seem to use the
intermediate locals, so those cases wouldn't need to use the new helper.



  /* Poll for CK_OUT_EN bit.  max. poll time = 50us */
-   ck_out_en = !!(readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) &
-   CORE_CK_OUT_EN);
+   ck_out_en = !!(readl_relaxed(host->ioaddr +
+   msm_offset->core_dll_config) & CORE_CK_OUT_EN);



  

Re: [PATCH V1 2/3] mmc: sdhci-msm: Add msm version specific ops and data structures

2018-05-24 Thread Vijay Viswanath



On 5/22/2018 11:40 PM, Evan Green wrote:

On Thu, May 17, 2018 at 3:30 AM Vijay Viswanath <vvisw...@codeaurora.org>
wrote:


In addition to offsets of certain registers changing, the registers in
core_mem have been shifted to HC mem as well. To access these registers,
define msm version specific functions. These functions can be loaded
into the function pointers at the time of probe based on the msm version
detected.



Also defind new data structure to hold version specific Ops and register
addresses.



Signed-off-by: Sayali Lokhande <saya...@codeaurora.org>
Signed-off-by: Vijay Viswanath <vvisw...@codeaurora.org>
---
   drivers/mmc/host/sdhci-msm.c | 112

+++

   1 file changed, 112 insertions(+)



diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 2524455..bb2bb59 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -226,6 +226,25 @@ struct sdhci_msm_offset {
  .core_ddr_config_2 = 0x1BC,
   };



+struct sdhci_msm_variant_ops {
+   u8 (*msm_readb_relaxed)(struct sdhci_host *host, u32 offset);


I don't see any uses of msm_readb_relaxed or msm_writeb_relaxed in this
patch or the next one. Are these needed?


They are not used as of now. Kept them since they can have use later. 
Felt it better to define base functions and addresses now itself.





+   u32 (*msm_readl_relaxed)(struct sdhci_host *host, u32 offset);
+   void (*msm_writeb_relaxed)(u8 val, struct sdhci_host *host, u32

offset);

+   void (*msm_writel_relaxed)(u32 val, struct sdhci_host *host,
+   u32 offset);
+};
+
+/*
+ * From V5, register spaces have changed. Wrap this info in a structure
+ * and choose the data_structure based on version info mentioned in DT.
+ */
+struct sdhci_msm_variant_info {
+   bool mci_removed;
+   const struct sdhci_msm_variant_ops *var_ops;
+   const struct sdhci_msm_offset *offset;
+};
+
+


Remove extra blank line.


   struct sdhci_msm_host {
  struct platform_device *pdev;
  void __iomem *core_mem; /* MSM SDCC mapped address */
@@ -245,8 +264,75 @@ struct sdhci_msm_host {
  wait_queue_head_t pwr_irq_wait;
  bool pwr_irq_flag;
  u32 caps_0;
+   bool mci_removed;
+   const struct sdhci_msm_variant_ops *var_ops;
+   const struct sdhci_msm_offset *offset;
   };



+/*
+ * APIs to read/write to vendor specific registers which were there in

the

+ * core_mem region before MCI was removed.
+ */
+static u8 sdhci_msm_mci_variant_readb_relaxed(struct sdhci_host *host,
+   u32 offset)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+   return readb_relaxed(msm_host->core_mem + offset);
+}
+
+static u8 sdhci_msm_v5_variant_readb_relaxed(struct sdhci_host *host,
+   u32 offset)
+{
+   return readb_relaxed(host->ioaddr + offset);
+}
+
+static u32 sdhci_msm_mci_variant_readl_relaxed(struct sdhci_host *host,
+   u32 offset)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+   return readl_relaxed(msm_host->core_mem + offset);
+}
+
+static u32 sdhci_msm_v5_variant_readl_relaxed(struct sdhci_host *host,
+   u32 offset)
+{
+   return readl_relaxed(host->ioaddr + offset);
+}
+
+static void sdhci_msm_mci_variant_writeb_relaxed(u8 val,
+   struct sdhci_host *host, u32 offset)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+   writeb_relaxed(val, msm_host->core_mem + offset);
+}
+
+static void sdhci_msm_v5_variant_writeb_relaxed(u8 val, struct

sdhci_host *host,

+   u32 offset)
+{
+   writeb_relaxed(val, host->ioaddr + offset);
+}
+
+static void sdhci_msm_mci_variant_writel_relaxed(u32 val,
+   struct sdhci_host *host, u32 offset)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+   writel_relaxed(val, msm_host->core_mem + offset);
+}
+
+static void sdhci_msm_v5_variant_writel_relaxed(u32 val, struct

sdhci_host *host,

You squeaked over 80 characters here. Move the second parameter down with
the third.

-Evan



Thanks for going through the patch thoroughly. Will address the comments.

Thanks,
Vijay


Re: [PATCH V1 2/3] mmc: sdhci-msm: Add msm version specific ops and data structures

2018-05-24 Thread Vijay Viswanath



On 5/22/2018 11:40 PM, Evan Green wrote:

On Thu, May 17, 2018 at 3:30 AM Vijay Viswanath 
wrote:


In addition to offsets of certain registers changing, the registers in
core_mem have been shifted to HC mem as well. To access these registers,
define msm version specific functions. These functions can be loaded
into the function pointers at the time of probe based on the msm version
detected.



Also defind new data structure to hold version specific Ops and register
addresses.



Signed-off-by: Sayali Lokhande 
Signed-off-by: Vijay Viswanath 
---
   drivers/mmc/host/sdhci-msm.c | 112

+++

   1 file changed, 112 insertions(+)



diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 2524455..bb2bb59 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -226,6 +226,25 @@ struct sdhci_msm_offset {
  .core_ddr_config_2 = 0x1BC,
   };



+struct sdhci_msm_variant_ops {
+   u8 (*msm_readb_relaxed)(struct sdhci_host *host, u32 offset);


I don't see any uses of msm_readb_relaxed or msm_writeb_relaxed in this
patch or the next one. Are these needed?


They are not used as of now. Kept them since they can have use later. 
Felt it better to define base functions and addresses now itself.





+   u32 (*msm_readl_relaxed)(struct sdhci_host *host, u32 offset);
+   void (*msm_writeb_relaxed)(u8 val, struct sdhci_host *host, u32

offset);

+   void (*msm_writel_relaxed)(u32 val, struct sdhci_host *host,
+   u32 offset);
+};
+
+/*
+ * From V5, register spaces have changed. Wrap this info in a structure
+ * and choose the data_structure based on version info mentioned in DT.
+ */
+struct sdhci_msm_variant_info {
+   bool mci_removed;
+   const struct sdhci_msm_variant_ops *var_ops;
+   const struct sdhci_msm_offset *offset;
+};
+
+


Remove extra blank line.


   struct sdhci_msm_host {
  struct platform_device *pdev;
  void __iomem *core_mem; /* MSM SDCC mapped address */
@@ -245,8 +264,75 @@ struct sdhci_msm_host {
  wait_queue_head_t pwr_irq_wait;
  bool pwr_irq_flag;
  u32 caps_0;
+   bool mci_removed;
+   const struct sdhci_msm_variant_ops *var_ops;
+   const struct sdhci_msm_offset *offset;
   };



+/*
+ * APIs to read/write to vendor specific registers which were there in

the

+ * core_mem region before MCI was removed.
+ */
+static u8 sdhci_msm_mci_variant_readb_relaxed(struct sdhci_host *host,
+   u32 offset)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+   return readb_relaxed(msm_host->core_mem + offset);
+}
+
+static u8 sdhci_msm_v5_variant_readb_relaxed(struct sdhci_host *host,
+   u32 offset)
+{
+   return readb_relaxed(host->ioaddr + offset);
+}
+
+static u32 sdhci_msm_mci_variant_readl_relaxed(struct sdhci_host *host,
+   u32 offset)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+   return readl_relaxed(msm_host->core_mem + offset);
+}
+
+static u32 sdhci_msm_v5_variant_readl_relaxed(struct sdhci_host *host,
+   u32 offset)
+{
+   return readl_relaxed(host->ioaddr + offset);
+}
+
+static void sdhci_msm_mci_variant_writeb_relaxed(u8 val,
+   struct sdhci_host *host, u32 offset)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+   writeb_relaxed(val, msm_host->core_mem + offset);
+}
+
+static void sdhci_msm_v5_variant_writeb_relaxed(u8 val, struct

sdhci_host *host,

+   u32 offset)
+{
+   writeb_relaxed(val, host->ioaddr + offset);
+}
+
+static void sdhci_msm_mci_variant_writel_relaxed(u32 val,
+   struct sdhci_host *host, u32 offset)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+   writel_relaxed(val, msm_host->core_mem + offset);
+}
+
+static void sdhci_msm_v5_variant_writel_relaxed(u32 val, struct

sdhci_host *host,

You squeaked over 80 characters here. Move the second parameter down with
the third.

-Evan



Thanks for going through the patch thoroughly. Will address the comments.

Thanks,
Vijay


Re: [PATCH V1 1/3] mmc: sdhci-msm: Define new Register address map

2018-05-24 Thread Vijay Viswanath



On 5/22/2018 11:39 PM, Evan Green wrote:

Hi Vijay,
On Thu, May 17, 2018 at 3:30 AM Vijay Viswanath <vvisw...@codeaurora.org>
wrote:


From: Sayali Lokhande <saya...@codeaurora.org>



For SDCC version 5.0.0, MCI registers are removed from SDCC
interface and some registers are moved to HC.
Define a new data structure where we can statically define
the address offsets for the registers in different SDCC versions.



Signed-off-by: Sayali Lokhande <saya...@codeaurora.org>
Signed-off-by: Vijay Viswanath <vvisw...@codeaurora.org>
---
   drivers/mmc/host/sdhci-msm.c | 89



   1 file changed, 89 insertions(+)



diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index bb11916..2524455 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -137,6 +137,95 @@
   /* Timeout value to avoid infinite waiting for pwr_irq */
   #define MSM_PWR_IRQ_TIMEOUT_MS 5000



+struct sdhci_msm_offset {
+   u32 core_hc_mode;
+   u32 core_mci_data_cnt;
+   u32 core_mci_status;
+   u32 core_mci_fifo_cnt;
+   u32 core_mci_version;
+   u32 core_generics;
+   u32 core_testbus_config;
+   u32 core_testbus_sel2_bit;
+   u32 core_testbus_ena;
+   u32 core_testbus_sel2;
+   u32 core_pwrctl_status;
+   u32 core_pwrctl_mask;
+   u32 core_pwrctl_clear;
+   u32 core_pwrctl_ctl;
+   u32 core_sdcc_debug_reg;
+   u32 core_dll_config;
+   u32 core_dll_status;
+   u32 core_vendor_spec;
+   u32 core_vendor_spec_adma_err_addr0;
+   u32 core_vendor_spec_adma_err_addr1;
+   u32 core_vendor_spec_func2;
+   u32 core_vendor_spec_capabilities0;
+   u32 core_ddr_200_cfg;
+   u32 core_vendor_spec3;
+   u32 core_dll_config_2;
+   u32 core_ddr_config;
+   u32 core_ddr_config_2;
+};
+
+static const struct sdhci_msm_offset sdhci_msm_v5_offset = {
+   .core_mci_data_cnt = 0x35c,
+   .core_mci_status = 0x324,
+   .core_mci_fifo_cnt = 0x308,
+   .core_mci_version = 0x318,
+   .core_generics = 0x320,
+   .core_testbus_config = 0x32c,
+   .core_testbus_sel2_bit = 3,
+   .core_testbus_ena = (1 << 31),
+   .core_testbus_sel2 = (1 << 3),
+   .core_pwrctl_status = 0x240,
+   .core_pwrctl_mask = 0x244,
+   .core_pwrctl_clear = 0x248,
+   .core_pwrctl_ctl = 0x24c,
+   .core_sdcc_debug_reg = 0x358,
+   .core_dll_config = 0x200,
+   .core_dll_status = 0x208,
+   .core_vendor_spec = 0x20c,
+   .core_vendor_spec_adma_err_addr0 = 0x214,
+   .core_vendor_spec_adma_err_addr1 = 0x218,
+   .core_vendor_spec_func2 = 0x210,
+   .core_vendor_spec_capabilities0 = 0x21c,
+   .core_ddr_200_cfg = 0x224,
+   .core_vendor_spec3 = 0x250,
+   .core_dll_config_2 = 0x254,
+   .core_ddr_config = 0x258,
+   .core_ddr_config_2 = 0x25c,
+};
+
+static const struct sdhci_msm_offset sdhci_msm_mci_offset = {
+   .core_hc_mode = 0x78,
+   .core_mci_data_cnt = 0x30,
+   .core_mci_status = 0x34,
+   .core_mci_fifo_cnt = 0x44,
+   .core_mci_version = 0x050,
+   .core_generics = 0x70,
+   .core_testbus_config = 0x0CC,
+   .core_testbus_sel2_bit = 4,
+   .core_testbus_ena = (1 << 3),
+   .core_testbus_sel2 = (1 << 4),
+   .core_pwrctl_status = 0xDC,
+   .core_pwrctl_mask = 0xE0,
+   .core_pwrctl_clear = 0xE4,
+   .core_pwrctl_ctl = 0xE8,
+   .core_sdcc_debug_reg = 0x124,
+   .core_dll_config = 0x100,
+   .core_dll_status = 0x108,
+   .core_vendor_spec = 0x10C,
+   .core_vendor_spec_adma_err_addr0 = 0x114,
+   .core_vendor_spec_adma_err_addr1 = 0x118,
+   .core_vendor_spec_func2 = 0x110,
+   .core_vendor_spec_capabilities0 = 0x11C,
+   .core_ddr_200_cfg = 0x184,
+   .core_vendor_spec3 = 0x1B0,
+   .core_dll_config_2 = 0x1B4,
+   .core_ddr_config = 0x1B8,
+   .core_ddr_config_2 = 0x1BC,
+};
+


I notice a lot of these are never used in the subsequent patches of this
series. I guess more register definitions are always better than fewer,
it's just a shame that they take up space now. Did you just add everything
that was different between v4 and v5, or how did you come up with this set?

Also, I think lowercase hex letters are preferred.

I verified that the v5 register offsets look good, at least for the
registers I have documentation for.

Yeah, felt it better to include all registers even they are not used 
currently.


Will change to use  lowercase hex letters


-Evan



Re: [PATCH V1 1/3] mmc: sdhci-msm: Define new Register address map

2018-05-24 Thread Vijay Viswanath



On 5/22/2018 11:39 PM, Evan Green wrote:

Hi Vijay,
On Thu, May 17, 2018 at 3:30 AM Vijay Viswanath 
wrote:


From: Sayali Lokhande 



For SDCC version 5.0.0, MCI registers are removed from SDCC
interface and some registers are moved to HC.
Define a new data structure where we can statically define
the address offsets for the registers in different SDCC versions.



Signed-off-by: Sayali Lokhande 
Signed-off-by: Vijay Viswanath 
---
   drivers/mmc/host/sdhci-msm.c | 89



   1 file changed, 89 insertions(+)



diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index bb11916..2524455 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -137,6 +137,95 @@
   /* Timeout value to avoid infinite waiting for pwr_irq */
   #define MSM_PWR_IRQ_TIMEOUT_MS 5000



+struct sdhci_msm_offset {
+   u32 core_hc_mode;
+   u32 core_mci_data_cnt;
+   u32 core_mci_status;
+   u32 core_mci_fifo_cnt;
+   u32 core_mci_version;
+   u32 core_generics;
+   u32 core_testbus_config;
+   u32 core_testbus_sel2_bit;
+   u32 core_testbus_ena;
+   u32 core_testbus_sel2;
+   u32 core_pwrctl_status;
+   u32 core_pwrctl_mask;
+   u32 core_pwrctl_clear;
+   u32 core_pwrctl_ctl;
+   u32 core_sdcc_debug_reg;
+   u32 core_dll_config;
+   u32 core_dll_status;
+   u32 core_vendor_spec;
+   u32 core_vendor_spec_adma_err_addr0;
+   u32 core_vendor_spec_adma_err_addr1;
+   u32 core_vendor_spec_func2;
+   u32 core_vendor_spec_capabilities0;
+   u32 core_ddr_200_cfg;
+   u32 core_vendor_spec3;
+   u32 core_dll_config_2;
+   u32 core_ddr_config;
+   u32 core_ddr_config_2;
+};
+
+static const struct sdhci_msm_offset sdhci_msm_v5_offset = {
+   .core_mci_data_cnt = 0x35c,
+   .core_mci_status = 0x324,
+   .core_mci_fifo_cnt = 0x308,
+   .core_mci_version = 0x318,
+   .core_generics = 0x320,
+   .core_testbus_config = 0x32c,
+   .core_testbus_sel2_bit = 3,
+   .core_testbus_ena = (1 << 31),
+   .core_testbus_sel2 = (1 << 3),
+   .core_pwrctl_status = 0x240,
+   .core_pwrctl_mask = 0x244,
+   .core_pwrctl_clear = 0x248,
+   .core_pwrctl_ctl = 0x24c,
+   .core_sdcc_debug_reg = 0x358,
+   .core_dll_config = 0x200,
+   .core_dll_status = 0x208,
+   .core_vendor_spec = 0x20c,
+   .core_vendor_spec_adma_err_addr0 = 0x214,
+   .core_vendor_spec_adma_err_addr1 = 0x218,
+   .core_vendor_spec_func2 = 0x210,
+   .core_vendor_spec_capabilities0 = 0x21c,
+   .core_ddr_200_cfg = 0x224,
+   .core_vendor_spec3 = 0x250,
+   .core_dll_config_2 = 0x254,
+   .core_ddr_config = 0x258,
+   .core_ddr_config_2 = 0x25c,
+};
+
+static const struct sdhci_msm_offset sdhci_msm_mci_offset = {
+   .core_hc_mode = 0x78,
+   .core_mci_data_cnt = 0x30,
+   .core_mci_status = 0x34,
+   .core_mci_fifo_cnt = 0x44,
+   .core_mci_version = 0x050,
+   .core_generics = 0x70,
+   .core_testbus_config = 0x0CC,
+   .core_testbus_sel2_bit = 4,
+   .core_testbus_ena = (1 << 3),
+   .core_testbus_sel2 = (1 << 4),
+   .core_pwrctl_status = 0xDC,
+   .core_pwrctl_mask = 0xE0,
+   .core_pwrctl_clear = 0xE4,
+   .core_pwrctl_ctl = 0xE8,
+   .core_sdcc_debug_reg = 0x124,
+   .core_dll_config = 0x100,
+   .core_dll_status = 0x108,
+   .core_vendor_spec = 0x10C,
+   .core_vendor_spec_adma_err_addr0 = 0x114,
+   .core_vendor_spec_adma_err_addr1 = 0x118,
+   .core_vendor_spec_func2 = 0x110,
+   .core_vendor_spec_capabilities0 = 0x11C,
+   .core_ddr_200_cfg = 0x184,
+   .core_vendor_spec3 = 0x1B0,
+   .core_dll_config_2 = 0x1B4,
+   .core_ddr_config = 0x1B8,
+   .core_ddr_config_2 = 0x1BC,
+};
+


I notice a lot of these are never used in the subsequent patches of this
series. I guess more register definitions are always better than fewer,
it's just a shame that they take up space now. Did you just add everything
that was different between v4 and v5, or how did you come up with this set?

Also, I think lowercase hex letters are preferred.

I verified that the v5 register offsets look good, at least for the
registers I have documentation for.

Yeah, felt it better to include all registers even they are not used 
currently.


Will change to use  lowercase hex letters


-Evan



[PATCH V1 2/3] mmc: sdhci-msm: Add msm version specific ops and data structures

2018-05-17 Thread Vijay Viswanath
In addition to offsets of certain registers changing, the registers in
core_mem have been shifted to HC mem as well. To access these registers,
define msm version specific functions. These functions can be loaded
into the function pointers at the time of probe based on the msm version
detected.

Also defind new data structure to hold version specific Ops and register
addresses.

Signed-off-by: Sayali Lokhande <saya...@codeaurora.org>
Signed-off-by: Vijay Viswanath <vvisw...@codeaurora.org>
---
 drivers/mmc/host/sdhci-msm.c | 112 +++
 1 file changed, 112 insertions(+)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 2524455..bb2bb59 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -226,6 +226,25 @@ struct sdhci_msm_offset {
.core_ddr_config_2 = 0x1BC,
 };
 
+struct sdhci_msm_variant_ops {
+   u8 (*msm_readb_relaxed)(struct sdhci_host *host, u32 offset);
+   u32 (*msm_readl_relaxed)(struct sdhci_host *host, u32 offset);
+   void (*msm_writeb_relaxed)(u8 val, struct sdhci_host *host, u32 offset);
+   void (*msm_writel_relaxed)(u32 val, struct sdhci_host *host,
+   u32 offset);
+};
+
+/*
+ * From V5, register spaces have changed. Wrap this info in a structure
+ * and choose the data_structure based on version info mentioned in DT.
+ */
+struct sdhci_msm_variant_info {
+   bool mci_removed;
+   const struct sdhci_msm_variant_ops *var_ops;
+   const struct sdhci_msm_offset *offset;
+};
+
+
 struct sdhci_msm_host {
struct platform_device *pdev;
void __iomem *core_mem; /* MSM SDCC mapped address */
@@ -245,8 +264,75 @@ struct sdhci_msm_host {
wait_queue_head_t pwr_irq_wait;
bool pwr_irq_flag;
u32 caps_0;
+   bool mci_removed;
+   const struct sdhci_msm_variant_ops *var_ops;
+   const struct sdhci_msm_offset *offset;
 };
 
+/*
+ * APIs to read/write to vendor specific registers which were there in the
+ * core_mem region before MCI was removed.
+ */
+static u8 sdhci_msm_mci_variant_readb_relaxed(struct sdhci_host *host,
+   u32 offset)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+   return readb_relaxed(msm_host->core_mem + offset);
+}
+
+static u8 sdhci_msm_v5_variant_readb_relaxed(struct sdhci_host *host,
+   u32 offset)
+{
+   return readb_relaxed(host->ioaddr + offset);
+}
+
+static u32 sdhci_msm_mci_variant_readl_relaxed(struct sdhci_host *host,
+   u32 offset)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+   return readl_relaxed(msm_host->core_mem + offset);
+}
+
+static u32 sdhci_msm_v5_variant_readl_relaxed(struct sdhci_host *host,
+   u32 offset)
+{
+   return readl_relaxed(host->ioaddr + offset);
+}
+
+static void sdhci_msm_mci_variant_writeb_relaxed(u8 val,
+   struct sdhci_host *host, u32 offset)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+   writeb_relaxed(val, msm_host->core_mem + offset);
+}
+
+static void sdhci_msm_v5_variant_writeb_relaxed(u8 val, struct sdhci_host 
*host,
+   u32 offset)
+{
+   writeb_relaxed(val, host->ioaddr + offset);
+}
+
+static void sdhci_msm_mci_variant_writel_relaxed(u32 val,
+   struct sdhci_host *host, u32 offset)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+   writel_relaxed(val, msm_host->core_mem + offset);
+}
+
+static void sdhci_msm_v5_variant_writel_relaxed(u32 val, struct sdhci_host 
*host,
+   u32 offset)
+{
+   writel_relaxed(val, host->ioaddr + offset);
+}
+
 static unsigned int msm_get_clock_rate_for_bus_mode(struct sdhci_host *host,
unsigned int clock)
 {
@@ -1481,6 +1567,32 @@ 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 const struct sdhci_msm_variant_ops mci_var_ops = {
+   .msm_readb_relaxed = sdhci_msm_mci_variant_readb_relaxed,
+   .msm_readl_relaxed = sdhci_msm_mci_variant_readl_relaxed,
+   .msm_writeb_relaxed = sdhci_msm_mci_variant_writeb_relaxed,
+   .msm_writel_relaxed = sdhci_msm_mci_variant_writel_relaxed,
+};
+
+static const struct sdhci_msm_variant_ops v5_var_ops = {
+   .msm_readb_relaxed = sdhci_msm_v5_variant_readb_relaxed,
+   .msm_readl_relaxed = sdhci_msm_v5_variant_readl_relaxed,
+   .msm_writeb_relaxed = sdhci_msm_v5_variant_writeb_relaxed,
+   .msm_writel_relaxed = sdhci_msm_

[PATCH V1 2/3] mmc: sdhci-msm: Add msm version specific ops and data structures

2018-05-17 Thread Vijay Viswanath
In addition to offsets of certain registers changing, the registers in
core_mem have been shifted to HC mem as well. To access these registers,
define msm version specific functions. These functions can be loaded
into the function pointers at the time of probe based on the msm version
detected.

Also defind new data structure to hold version specific Ops and register
addresses.

Signed-off-by: Sayali Lokhande 
Signed-off-by: Vijay Viswanath 
---
 drivers/mmc/host/sdhci-msm.c | 112 +++
 1 file changed, 112 insertions(+)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 2524455..bb2bb59 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -226,6 +226,25 @@ struct sdhci_msm_offset {
.core_ddr_config_2 = 0x1BC,
 };
 
+struct sdhci_msm_variant_ops {
+   u8 (*msm_readb_relaxed)(struct sdhci_host *host, u32 offset);
+   u32 (*msm_readl_relaxed)(struct sdhci_host *host, u32 offset);
+   void (*msm_writeb_relaxed)(u8 val, struct sdhci_host *host, u32 offset);
+   void (*msm_writel_relaxed)(u32 val, struct sdhci_host *host,
+   u32 offset);
+};
+
+/*
+ * From V5, register spaces have changed. Wrap this info in a structure
+ * and choose the data_structure based on version info mentioned in DT.
+ */
+struct sdhci_msm_variant_info {
+   bool mci_removed;
+   const struct sdhci_msm_variant_ops *var_ops;
+   const struct sdhci_msm_offset *offset;
+};
+
+
 struct sdhci_msm_host {
struct platform_device *pdev;
void __iomem *core_mem; /* MSM SDCC mapped address */
@@ -245,8 +264,75 @@ struct sdhci_msm_host {
wait_queue_head_t pwr_irq_wait;
bool pwr_irq_flag;
u32 caps_0;
+   bool mci_removed;
+   const struct sdhci_msm_variant_ops *var_ops;
+   const struct sdhci_msm_offset *offset;
 };
 
+/*
+ * APIs to read/write to vendor specific registers which were there in the
+ * core_mem region before MCI was removed.
+ */
+static u8 sdhci_msm_mci_variant_readb_relaxed(struct sdhci_host *host,
+   u32 offset)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+   return readb_relaxed(msm_host->core_mem + offset);
+}
+
+static u8 sdhci_msm_v5_variant_readb_relaxed(struct sdhci_host *host,
+   u32 offset)
+{
+   return readb_relaxed(host->ioaddr + offset);
+}
+
+static u32 sdhci_msm_mci_variant_readl_relaxed(struct sdhci_host *host,
+   u32 offset)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+   return readl_relaxed(msm_host->core_mem + offset);
+}
+
+static u32 sdhci_msm_v5_variant_readl_relaxed(struct sdhci_host *host,
+   u32 offset)
+{
+   return readl_relaxed(host->ioaddr + offset);
+}
+
+static void sdhci_msm_mci_variant_writeb_relaxed(u8 val,
+   struct sdhci_host *host, u32 offset)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+   writeb_relaxed(val, msm_host->core_mem + offset);
+}
+
+static void sdhci_msm_v5_variant_writeb_relaxed(u8 val, struct sdhci_host 
*host,
+   u32 offset)
+{
+   writeb_relaxed(val, host->ioaddr + offset);
+}
+
+static void sdhci_msm_mci_variant_writel_relaxed(u32 val,
+   struct sdhci_host *host, u32 offset)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+   writel_relaxed(val, msm_host->core_mem + offset);
+}
+
+static void sdhci_msm_v5_variant_writel_relaxed(u32 val, struct sdhci_host 
*host,
+   u32 offset)
+{
+   writel_relaxed(val, host->ioaddr + offset);
+}
+
 static unsigned int msm_get_clock_rate_for_bus_mode(struct sdhci_host *host,
unsigned int clock)
 {
@@ -1481,6 +1567,32 @@ 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 const struct sdhci_msm_variant_ops mci_var_ops = {
+   .msm_readb_relaxed = sdhci_msm_mci_variant_readb_relaxed,
+   .msm_readl_relaxed = sdhci_msm_mci_variant_readl_relaxed,
+   .msm_writeb_relaxed = sdhci_msm_mci_variant_writeb_relaxed,
+   .msm_writel_relaxed = sdhci_msm_mci_variant_writel_relaxed,
+};
+
+static const struct sdhci_msm_variant_ops v5_var_ops = {
+   .msm_readb_relaxed = sdhci_msm_v5_variant_readb_relaxed,
+   .msm_readl_relaxed = sdhci_msm_v5_variant_readl_relaxed,
+   .msm_writeb_relaxed = sdhci_msm_v5_variant_writeb_relaxed,
+   .msm_writel_relaxed = sdhci_msm_v5_variant_writel_relaxed,
+};
+
+static const struct sdhci_

[PATCH V1 0/3] Changes for SDCC5 version

2018-05-17 Thread Vijay Viswanath
With SDCC5, the MCI register space got removed and the offset/order of
several registers have changed. Based on SDCC version used and the register,
we need to pick the base address and offset.

Changes since RFC:
Dropped voltage regulator changes in sdhci-msm
Split the "Register changes for sdcc V5" patch
Instead of checking mci removal for deciding which base addr to use,
new function pointers are defined for the 2 variants of sdcc: 
1) MCI present
2) V5 (mci removed)
Instead of string comparing with the compatible string from DT file,
the sdhci_msm_probe will now pick the data associated with the
compatible entry and use it to load variant specific address offsets
and msm variant specific read/write ops. 

Sayali Lokhande (2):
  mmc: sdhci-msm: Define new Register address map
  mmc: host: Register changes for sdcc V5

Vijay Viswanath (1):
  mmc: sdhci-msm: Add msm version specific ops and data structures

 .../devicetree/bindings/mmc/sdhci-msm.txt  |   5 +-
 drivers/mmc/host/sdhci-msm.c   | 545 -
 2 files changed, 423 insertions(+), 127 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.



[PATCH V1 0/3] Changes for SDCC5 version

2018-05-17 Thread Vijay Viswanath
With SDCC5, the MCI register space got removed and the offset/order of
several registers have changed. Based on SDCC version used and the register,
we need to pick the base address and offset.

Changes since RFC:
Dropped voltage regulator changes in sdhci-msm
Split the "Register changes for sdcc V5" patch
Instead of checking mci removal for deciding which base addr to use,
new function pointers are defined for the 2 variants of sdcc: 
1) MCI present
2) V5 (mci removed)
Instead of string comparing with the compatible string from DT file,
the sdhci_msm_probe will now pick the data associated with the
compatible entry and use it to load variant specific address offsets
and msm variant specific read/write ops. 

Sayali Lokhande (2):
  mmc: sdhci-msm: Define new Register address map
  mmc: host: Register changes for sdcc V5

Vijay Viswanath (1):
  mmc: sdhci-msm: Add msm version specific ops and data structures

 .../devicetree/bindings/mmc/sdhci-msm.txt  |   5 +-
 drivers/mmc/host/sdhci-msm.c   | 545 -
 2 files changed, 423 insertions(+), 127 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.



[PATCH V1 1/3] mmc: sdhci-msm: Define new Register address map

2018-05-17 Thread Vijay Viswanath
From: Sayali Lokhande <saya...@codeaurora.org>

For SDCC version 5.0.0, MCI registers are removed from SDCC
interface and some registers are moved to HC.
Define a new data structure where we can statically define
the address offsets for the registers in different SDCC versions.

Signed-off-by: Sayali Lokhande <saya...@codeaurora.org>
Signed-off-by: Vijay Viswanath <vvisw...@codeaurora.org>
---
 drivers/mmc/host/sdhci-msm.c | 89 
 1 file changed, 89 insertions(+)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index bb11916..2524455 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -137,6 +137,95 @@
 /* Timeout value to avoid infinite waiting for pwr_irq */
 #define MSM_PWR_IRQ_TIMEOUT_MS 5000
 
+struct sdhci_msm_offset {
+   u32 core_hc_mode;
+   u32 core_mci_data_cnt;
+   u32 core_mci_status;
+   u32 core_mci_fifo_cnt;
+   u32 core_mci_version;
+   u32 core_generics;
+   u32 core_testbus_config;
+   u32 core_testbus_sel2_bit;
+   u32 core_testbus_ena;
+   u32 core_testbus_sel2;
+   u32 core_pwrctl_status;
+   u32 core_pwrctl_mask;
+   u32 core_pwrctl_clear;
+   u32 core_pwrctl_ctl;
+   u32 core_sdcc_debug_reg;
+   u32 core_dll_config;
+   u32 core_dll_status;
+   u32 core_vendor_spec;
+   u32 core_vendor_spec_adma_err_addr0;
+   u32 core_vendor_spec_adma_err_addr1;
+   u32 core_vendor_spec_func2;
+   u32 core_vendor_spec_capabilities0;
+   u32 core_ddr_200_cfg;
+   u32 core_vendor_spec3;
+   u32 core_dll_config_2;
+   u32 core_ddr_config;
+   u32 core_ddr_config_2;
+};
+
+static const struct sdhci_msm_offset sdhci_msm_v5_offset = {
+   .core_mci_data_cnt = 0x35c,
+   .core_mci_status = 0x324,
+   .core_mci_fifo_cnt = 0x308,
+   .core_mci_version = 0x318,
+   .core_generics = 0x320,
+   .core_testbus_config = 0x32c,
+   .core_testbus_sel2_bit = 3,
+   .core_testbus_ena = (1 << 31),
+   .core_testbus_sel2 = (1 << 3),
+   .core_pwrctl_status = 0x240,
+   .core_pwrctl_mask = 0x244,
+   .core_pwrctl_clear = 0x248,
+   .core_pwrctl_ctl = 0x24c,
+   .core_sdcc_debug_reg = 0x358,
+   .core_dll_config = 0x200,
+   .core_dll_status = 0x208,
+   .core_vendor_spec = 0x20c,
+   .core_vendor_spec_adma_err_addr0 = 0x214,
+   .core_vendor_spec_adma_err_addr1 = 0x218,
+   .core_vendor_spec_func2 = 0x210,
+   .core_vendor_spec_capabilities0 = 0x21c,
+   .core_ddr_200_cfg = 0x224,
+   .core_vendor_spec3 = 0x250,
+   .core_dll_config_2 = 0x254,
+   .core_ddr_config = 0x258,
+   .core_ddr_config_2 = 0x25c,
+};
+
+static const struct sdhci_msm_offset sdhci_msm_mci_offset = {
+   .core_hc_mode = 0x78,
+   .core_mci_data_cnt = 0x30,
+   .core_mci_status = 0x34,
+   .core_mci_fifo_cnt = 0x44,
+   .core_mci_version = 0x050,
+   .core_generics = 0x70,
+   .core_testbus_config = 0x0CC,
+   .core_testbus_sel2_bit = 4,
+   .core_testbus_ena = (1 << 3),
+   .core_testbus_sel2 = (1 << 4),
+   .core_pwrctl_status = 0xDC,
+   .core_pwrctl_mask = 0xE0,
+   .core_pwrctl_clear = 0xE4,
+   .core_pwrctl_ctl = 0xE8,
+   .core_sdcc_debug_reg = 0x124,
+   .core_dll_config = 0x100,
+   .core_dll_status = 0x108,
+   .core_vendor_spec = 0x10C,
+   .core_vendor_spec_adma_err_addr0 = 0x114,
+   .core_vendor_spec_adma_err_addr1 = 0x118,
+   .core_vendor_spec_func2 = 0x110,
+   .core_vendor_spec_capabilities0 = 0x11C,
+   .core_ddr_200_cfg = 0x184,
+   .core_vendor_spec3 = 0x1B0,
+   .core_dll_config_2 = 0x1B4,
+   .core_ddr_config = 0x1B8,
+   .core_ddr_config_2 = 0x1BC,
+};
+
 struct sdhci_msm_host {
struct platform_device *pdev;
void __iomem *core_mem; /* MSM SDCC 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.



[PATCH V1 3/3] mmc: host: Register changes for sdcc V5

2018-05-17 Thread Vijay Viswanath
From: Sayali Lokhande <saya...@codeaurora.org>

For SDCC version 5.0.0 and higher, new compatible string
"qcom,sdhci-msm-v5" is added.

Based on the msm variant, pick the relevant variant data and
use it for register read/write to msm specific registers.

Signed-off-by: Sayali Lokhande <saya...@codeaurora.org>
Signed-off-by: Vijay Viswanath <vvisw...@codeaurora.org>
---
 .../devicetree/bindings/mmc/sdhci-msm.txt  |   5 +-
 drivers/mmc/host/sdhci-msm.c   | 344 +
 2 files changed, 222 insertions(+), 127 deletions(-)

diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt 
b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
index bfdcdc4..c2b7b2b 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
@@ -4,7 +4,10 @@ This file documents differences between the core properties in 
mmc.txt
 and the properties used by the sdhci-msm driver.
 
 Required properties:
-- compatible: Should contain "qcom,sdhci-msm-v4".
+- compatible: Should contain "qcom,sdhci-msm-v4" or "qcom,sdhci-msm-v5".
+For SDCC version 5.0.0, MCI registers are removed from SDCC
+interface and some registers are moved to HC. New compatible
+string is added to support this change - "qcom,sdhci-msm-v5".
 - reg: Base address and length of the register in the following order:
- Host controller register map (required)
- SD Core register map (required)
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index bb2bb59..408e6b2 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -33,16 +33,11 @@
 #define CORE_MCI_GENERICS  0x70
 #define SWITCHABLE_SIGNALING_VOLTAGE   BIT(29)
 
-#define CORE_HC_MODE   0x78
 #define HC_MODE_EN 0x1
 #define CORE_POWER 0x0
 #define CORE_SW_RSTBIT(7)
 #define FF_CLK_SW_RST_DIS  BIT(13)
 
-#define CORE_PWRCTL_STATUS 0xdc
-#define CORE_PWRCTL_MASK   0xe0
-#define CORE_PWRCTL_CLEAR  0xe4
-#define CORE_PWRCTL_CTL0xe8
 #define CORE_PWRCTL_BUS_OFFBIT(0)
 #define CORE_PWRCTL_BUS_ON BIT(1)
 #define CORE_PWRCTL_IO_LOW BIT(2)
@@ -63,17 +58,13 @@
 #define CORE_CDR_EXT_ENBIT(19)
 #define CORE_DLL_PDN   BIT(29)
 #define CORE_DLL_RST   BIT(30)
-#define CORE_DLL_CONFIG0x100
 #define CORE_CMD_DAT_TRACK_SEL BIT(0)
-#define CORE_DLL_STATUS0x108
 
-#define CORE_DLL_CONFIG_2  0x1b4
 #define CORE_DDR_CAL_ENBIT(0)
 #define CORE_FLL_CYCLE_CNT BIT(18)
 #define CORE_DLL_CLOCK_DISABLE BIT(21)
 
-#define CORE_VENDOR_SPEC   0x10c
-#define CORE_VENDOR_SPEC_POR_VAL   0xa1c
+#define CORE_VENDOR_SPEC_POR_VAL 0xa1c
 #define CORE_CLK_PWRSAVE   BIT(1)
 #define CORE_HC_MCLK_SEL_DFLT  (2 << 8)
 #define CORE_HC_MCLK_SEL_HS400 (3 << 8)
@@ -111,17 +102,14 @@
 #define CORE_CDC_SWITCH_BYPASS_OFF BIT(0)
 #define CORE_CDC_SWITCH_RC_EN  BIT(1)
 
-#define CORE_DDR_200_CFG   0x184
 #define CORE_CDC_T4_DLY_SELBIT(0)
 #define CORE_CMDIN_RCLK_EN BIT(1)
 #define CORE_START_CDC_TRAFFIC BIT(6)
-#define CORE_VENDOR_SPEC3  0x1b0
+
 #define CORE_PWRSAVE_DLL   BIT(3)
 
-#define CORE_DDR_CONFIG0x1b8
 #define DDR_CONFIG_POR_VAL 0x80040853
 
-#define CORE_VENDOR_SPEC_CAPABILITIES0 0x11c
 
 #define INVALID_TUNING_PHASE   -1
 #define SDHCI_MSM_MIN_CLOCK40
@@ -380,10 +368,14 @@ static inline int msm_dll_poll_ck_out_en(struct 
sdhci_host *host, u8 poll)
u32 wait_cnt = 50;
u8 ck_out_en;
struct mmc_host *mmc = host->mmc;
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+   const struct sdhci_msm_offset *msm_offset =
+   msm_host->offset;
 
/* Poll for CK_OUT_EN bit.  max. poll time = 50us */
-   ck_out_en = !!(readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) &
-   CORE_CK_OUT_EN);
+   ck_out_en = !!(readl_relaxed(host->ioaddr +
+   msm_offset->core_dll_config) & CORE_CK_OUT_EN);
 
while (ck_out_en != poll) {
if (--wait_cnt == 0) {
@@ -393,8 +385,8 @@ static inline int msm_dll_poll_ck_out_en(struct sdhci_host 
*host, u8 poll)
}
udelay(1);
 
-   ck_out_en = !!(readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) &
-   CORE_CK_OUT_EN);
+   ck_out_en = !!(readl_relaxed(host->ioaddr +
+   msm_offset->core_dll_config) & CORE_CK_OUT_EN);
}
 
return 0;
@@ -410,16 +402,20 @@ static int msm_config_cm_dll_phase(struc

[PATCH V1 1/3] mmc: sdhci-msm: Define new Register address map

2018-05-17 Thread Vijay Viswanath
From: Sayali Lokhande 

For SDCC version 5.0.0, MCI registers are removed from SDCC
interface and some registers are moved to HC.
Define a new data structure where we can statically define
the address offsets for the registers in different SDCC versions.

Signed-off-by: Sayali Lokhande 
Signed-off-by: Vijay Viswanath 
---
 drivers/mmc/host/sdhci-msm.c | 89 
 1 file changed, 89 insertions(+)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index bb11916..2524455 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -137,6 +137,95 @@
 /* Timeout value to avoid infinite waiting for pwr_irq */
 #define MSM_PWR_IRQ_TIMEOUT_MS 5000
 
+struct sdhci_msm_offset {
+   u32 core_hc_mode;
+   u32 core_mci_data_cnt;
+   u32 core_mci_status;
+   u32 core_mci_fifo_cnt;
+   u32 core_mci_version;
+   u32 core_generics;
+   u32 core_testbus_config;
+   u32 core_testbus_sel2_bit;
+   u32 core_testbus_ena;
+   u32 core_testbus_sel2;
+   u32 core_pwrctl_status;
+   u32 core_pwrctl_mask;
+   u32 core_pwrctl_clear;
+   u32 core_pwrctl_ctl;
+   u32 core_sdcc_debug_reg;
+   u32 core_dll_config;
+   u32 core_dll_status;
+   u32 core_vendor_spec;
+   u32 core_vendor_spec_adma_err_addr0;
+   u32 core_vendor_spec_adma_err_addr1;
+   u32 core_vendor_spec_func2;
+   u32 core_vendor_spec_capabilities0;
+   u32 core_ddr_200_cfg;
+   u32 core_vendor_spec3;
+   u32 core_dll_config_2;
+   u32 core_ddr_config;
+   u32 core_ddr_config_2;
+};
+
+static const struct sdhci_msm_offset sdhci_msm_v5_offset = {
+   .core_mci_data_cnt = 0x35c,
+   .core_mci_status = 0x324,
+   .core_mci_fifo_cnt = 0x308,
+   .core_mci_version = 0x318,
+   .core_generics = 0x320,
+   .core_testbus_config = 0x32c,
+   .core_testbus_sel2_bit = 3,
+   .core_testbus_ena = (1 << 31),
+   .core_testbus_sel2 = (1 << 3),
+   .core_pwrctl_status = 0x240,
+   .core_pwrctl_mask = 0x244,
+   .core_pwrctl_clear = 0x248,
+   .core_pwrctl_ctl = 0x24c,
+   .core_sdcc_debug_reg = 0x358,
+   .core_dll_config = 0x200,
+   .core_dll_status = 0x208,
+   .core_vendor_spec = 0x20c,
+   .core_vendor_spec_adma_err_addr0 = 0x214,
+   .core_vendor_spec_adma_err_addr1 = 0x218,
+   .core_vendor_spec_func2 = 0x210,
+   .core_vendor_spec_capabilities0 = 0x21c,
+   .core_ddr_200_cfg = 0x224,
+   .core_vendor_spec3 = 0x250,
+   .core_dll_config_2 = 0x254,
+   .core_ddr_config = 0x258,
+   .core_ddr_config_2 = 0x25c,
+};
+
+static const struct sdhci_msm_offset sdhci_msm_mci_offset = {
+   .core_hc_mode = 0x78,
+   .core_mci_data_cnt = 0x30,
+   .core_mci_status = 0x34,
+   .core_mci_fifo_cnt = 0x44,
+   .core_mci_version = 0x050,
+   .core_generics = 0x70,
+   .core_testbus_config = 0x0CC,
+   .core_testbus_sel2_bit = 4,
+   .core_testbus_ena = (1 << 3),
+   .core_testbus_sel2 = (1 << 4),
+   .core_pwrctl_status = 0xDC,
+   .core_pwrctl_mask = 0xE0,
+   .core_pwrctl_clear = 0xE4,
+   .core_pwrctl_ctl = 0xE8,
+   .core_sdcc_debug_reg = 0x124,
+   .core_dll_config = 0x100,
+   .core_dll_status = 0x108,
+   .core_vendor_spec = 0x10C,
+   .core_vendor_spec_adma_err_addr0 = 0x114,
+   .core_vendor_spec_adma_err_addr1 = 0x118,
+   .core_vendor_spec_func2 = 0x110,
+   .core_vendor_spec_capabilities0 = 0x11C,
+   .core_ddr_200_cfg = 0x184,
+   .core_vendor_spec3 = 0x1B0,
+   .core_dll_config_2 = 0x1B4,
+   .core_ddr_config = 0x1B8,
+   .core_ddr_config_2 = 0x1BC,
+};
+
 struct sdhci_msm_host {
struct platform_device *pdev;
void __iomem *core_mem; /* MSM SDCC 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.



[PATCH V1 3/3] mmc: host: Register changes for sdcc V5

2018-05-17 Thread Vijay Viswanath
From: Sayali Lokhande 

For SDCC version 5.0.0 and higher, new compatible string
"qcom,sdhci-msm-v5" is added.

Based on the msm variant, pick the relevant variant data and
use it for register read/write to msm specific registers.

Signed-off-by: Sayali Lokhande 
Signed-off-by: Vijay Viswanath 
---
 .../devicetree/bindings/mmc/sdhci-msm.txt  |   5 +-
 drivers/mmc/host/sdhci-msm.c   | 344 +
 2 files changed, 222 insertions(+), 127 deletions(-)

diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt 
b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
index bfdcdc4..c2b7b2b 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
@@ -4,7 +4,10 @@ This file documents differences between the core properties in 
mmc.txt
 and the properties used by the sdhci-msm driver.
 
 Required properties:
-- compatible: Should contain "qcom,sdhci-msm-v4".
+- compatible: Should contain "qcom,sdhci-msm-v4" or "qcom,sdhci-msm-v5".
+For SDCC version 5.0.0, MCI registers are removed from SDCC
+interface and some registers are moved to HC. New compatible
+string is added to support this change - "qcom,sdhci-msm-v5".
 - reg: Base address and length of the register in the following order:
- Host controller register map (required)
- SD Core register map (required)
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index bb2bb59..408e6b2 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -33,16 +33,11 @@
 #define CORE_MCI_GENERICS  0x70
 #define SWITCHABLE_SIGNALING_VOLTAGE   BIT(29)
 
-#define CORE_HC_MODE   0x78
 #define HC_MODE_EN 0x1
 #define CORE_POWER 0x0
 #define CORE_SW_RSTBIT(7)
 #define FF_CLK_SW_RST_DIS  BIT(13)
 
-#define CORE_PWRCTL_STATUS 0xdc
-#define CORE_PWRCTL_MASK   0xe0
-#define CORE_PWRCTL_CLEAR  0xe4
-#define CORE_PWRCTL_CTL0xe8
 #define CORE_PWRCTL_BUS_OFFBIT(0)
 #define CORE_PWRCTL_BUS_ON BIT(1)
 #define CORE_PWRCTL_IO_LOW BIT(2)
@@ -63,17 +58,13 @@
 #define CORE_CDR_EXT_ENBIT(19)
 #define CORE_DLL_PDN   BIT(29)
 #define CORE_DLL_RST   BIT(30)
-#define CORE_DLL_CONFIG0x100
 #define CORE_CMD_DAT_TRACK_SEL BIT(0)
-#define CORE_DLL_STATUS0x108
 
-#define CORE_DLL_CONFIG_2  0x1b4
 #define CORE_DDR_CAL_ENBIT(0)
 #define CORE_FLL_CYCLE_CNT BIT(18)
 #define CORE_DLL_CLOCK_DISABLE BIT(21)
 
-#define CORE_VENDOR_SPEC   0x10c
-#define CORE_VENDOR_SPEC_POR_VAL   0xa1c
+#define CORE_VENDOR_SPEC_POR_VAL 0xa1c
 #define CORE_CLK_PWRSAVE   BIT(1)
 #define CORE_HC_MCLK_SEL_DFLT  (2 << 8)
 #define CORE_HC_MCLK_SEL_HS400 (3 << 8)
@@ -111,17 +102,14 @@
 #define CORE_CDC_SWITCH_BYPASS_OFF BIT(0)
 #define CORE_CDC_SWITCH_RC_EN  BIT(1)
 
-#define CORE_DDR_200_CFG   0x184
 #define CORE_CDC_T4_DLY_SELBIT(0)
 #define CORE_CMDIN_RCLK_EN BIT(1)
 #define CORE_START_CDC_TRAFFIC BIT(6)
-#define CORE_VENDOR_SPEC3  0x1b0
+
 #define CORE_PWRSAVE_DLL   BIT(3)
 
-#define CORE_DDR_CONFIG0x1b8
 #define DDR_CONFIG_POR_VAL 0x80040853
 
-#define CORE_VENDOR_SPEC_CAPABILITIES0 0x11c
 
 #define INVALID_TUNING_PHASE   -1
 #define SDHCI_MSM_MIN_CLOCK40
@@ -380,10 +368,14 @@ static inline int msm_dll_poll_ck_out_en(struct 
sdhci_host *host, u8 poll)
u32 wait_cnt = 50;
u8 ck_out_en;
struct mmc_host *mmc = host->mmc;
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+   const struct sdhci_msm_offset *msm_offset =
+   msm_host->offset;
 
/* Poll for CK_OUT_EN bit.  max. poll time = 50us */
-   ck_out_en = !!(readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) &
-   CORE_CK_OUT_EN);
+   ck_out_en = !!(readl_relaxed(host->ioaddr +
+   msm_offset->core_dll_config) & CORE_CK_OUT_EN);
 
while (ck_out_en != poll) {
if (--wait_cnt == 0) {
@@ -393,8 +385,8 @@ static inline int msm_dll_poll_ck_out_en(struct sdhci_host 
*host, u8 poll)
}
udelay(1);
 
-   ck_out_en = !!(readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) &
-   CORE_CK_OUT_EN);
+   ck_out_en = !!(readl_relaxed(host->ioaddr +
+   msm_offset->core_dll_config) & CORE_CK_OUT_EN);
}
 
return 0;
@@ -410,16 +402,20 @@ static int msm_config_cm_dll_phase(struct sdhci_host 
*host, u8 phase)
unsigned long flags;
u32 config;
struct mmc

Re: [PATCH RFC 2/4] mmc: sdhci-msm: Add and use voltage regulator related APIs

2018-05-03 Thread Vijay Viswanath



On 5/2/2018 2:19 PM, Ulf Hansson wrote:

On 1 May 2018 at 12:39, Vijay Viswanath <vvisw...@codeaurora.org> wrote:

From: Asutosh Das <asuto...@codeaurora.org>

Some platforms require that the voltage switching happen only after
the register write occurs and controller is ready for the switch. When
the controller is ready, it will inform through power irq.

Add voltage regulator APIs and use them during power irq to switch
voltage instead of relying on core layer voltage switching.


This is way to simplified. 529 lines of new code deserves some more
explanations.



Change-Id: Iaa98686e71a5bfe0092c68e9ffa563b060c5ac60


Remove this.


Signed-off-by: Asutosh Das <asuto...@codeaurora.org>
Signed-off-by: Venkat Gopalakrishnan <venk...@codeaurora.org>
Signed-off-by: Subhash Jadavani <subha...@codeaurora.org>
Signed-off-by: Vijay Viswanath <vvisw...@codeaurora.org>
---
  .../devicetree/bindings/mmc/sdhci-msm.txt  |  27 +-


Split DT changes and add DT maintainers.



Will do


  drivers/mmc/host/sdhci-msm.c   | 537 +++--
  2 files changed, 529 insertions(+), 35 deletions(-)

diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt 
b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
index c2b7b2b..c454046 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
@@ -23,6 +23,22 @@ Required properties:
 "xo"- TCXO clock (optional)
 "cal"   - reference clock for RCLK delay calibration (optional)
 "sleep" - sleep clock for RCLK delay calibration (optional)
+- -supply: phandle to the regulator device tree node if voltage
+   regulators needs to be handled from within sdhci-msm layer.
+   Supported "supply-name" are "vdd" and "vdd-io".
+
+Optional Properties:
+   - qcom,-always-on - specifies whether supply should be kept
+   "on" always.
+   - qcom,-lpm_sup - specifies whether supply can be kept in low
+   power mode (lpm).
+   - qcom,-voltage_level - specifies voltage levels for supply.
+   Should be specified in pairs (min, max), units uV.
+   - qcom,-current_level - specifies load levels for supply in lpm
+   or high power mode (hpm). Should be specified in
+   pairs (lpm, hpm), units uA.
+
+


This looks really weird.

What's so special here that requires you to have your own specific
regulator bindings?



  Example:

@@ -33,8 +49,15 @@ Example:
 bus-width = <8>;
 non-removable;

-   vmmc-supply = <_l20>;
-   vqmmc-supply = <_s3>;
+   vdd-supply = <_l20>;
+   qcom,vdd-voltage-level = <295 295>;
+   qcom,vdd-current-level = <9000 80>;
+
+   vdd-io-supply = <_s3>;
+   qcom,vdd-io-always-on;
+   qcom,vdd-io-lpm-sup;
+   qcom,vdd-io-voltage-level = <180 295>;
+   qcom,vdd-io-current-level = <6 22000>;

 pinctrl-names = "default";
 pinctrl-0 = <_clk _cmd _data>;
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index d4d432b..0e0f12d 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -213,6 +213,33 @@ struct sdhci_msm_offset sdhci_msm_offset_mci_present = {
 .core_ddr_config_2 = 0x1BC,
  };

+/* This structure keeps information per regulator */
+struct sdhci_msm_reg_data {
+   /* voltage regulator handle */
+   struct regulator *reg;
+   /* regulator name */
+   const char *name;
+   /* voltage level to be set */
+   u32 low_vol_level;
+   u32 high_vol_level;
+   /* Load values for low power and high power mode */
+   u32 lpm_uA;
+   u32 hpm_uA;
+   /* is this regulator enabled? */
+   bool is_enabled;
+   /* is this regulator needs to be always on? */
+   bool is_always_on;
+   /* is low power mode setting required for this regulator? */
+   bool lpm_sup;
+   bool set_voltage_sup;
+};
+
+struct sdhci_msm_pltfm_data {
+   /* Change-Id: Ide3a658ad51a3c3d4a05c47c0e8f013f647c9516 */
+   struct sdhci_msm_reg_data *vdd_data;
+   struct sdhci_msm_reg_data *vdd_io_data;
+};
+
  struct sdhci_msm_host {
 struct platform_device *pdev;
 void __iomem *core_mem; /* MSM SDCC mapped address */
@@ -234,6 +261,8 @@ struct sdhci_msm_host {
 u32 caps_0;
 bool mci_removed;
 const struct sdhci_msm_offset *offset;
+   bool pltfm_init_done;
+   struct sdhci_msm_pltfm_data pdata;
  };

  /*
@@ -298,6 +327,336 @@ void sdhci_msm_vendor_writel_relaxed(u32 val, struct 
sdhci_host *host,
 writel_relaxed(val, b

Re: [PATCH RFC 2/4] mmc: sdhci-msm: Add and use voltage regulator related APIs

2018-05-03 Thread Vijay Viswanath



On 5/2/2018 2:19 PM, Ulf Hansson wrote:

On 1 May 2018 at 12:39, Vijay Viswanath  wrote:

From: Asutosh Das 

Some platforms require that the voltage switching happen only after
the register write occurs and controller is ready for the switch. When
the controller is ready, it will inform through power irq.

Add voltage regulator APIs and use them during power irq to switch
voltage instead of relying on core layer voltage switching.


This is way to simplified. 529 lines of new code deserves some more
explanations.



Change-Id: Iaa98686e71a5bfe0092c68e9ffa563b060c5ac60


Remove this.


Signed-off-by: Asutosh Das 
Signed-off-by: Venkat Gopalakrishnan 
Signed-off-by: Subhash Jadavani 
Signed-off-by: Vijay Viswanath 
---
  .../devicetree/bindings/mmc/sdhci-msm.txt  |  27 +-


Split DT changes and add DT maintainers.



Will do


  drivers/mmc/host/sdhci-msm.c   | 537 +++--
  2 files changed, 529 insertions(+), 35 deletions(-)

diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt 
b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
index c2b7b2b..c454046 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
@@ -23,6 +23,22 @@ Required properties:
 "xo"- TCXO clock (optional)
 "cal"   - reference clock for RCLK delay calibration (optional)
 "sleep" - sleep clock for RCLK delay calibration (optional)
+- -supply: phandle to the regulator device tree node if voltage
+   regulators needs to be handled from within sdhci-msm layer.
+   Supported "supply-name" are "vdd" and "vdd-io".
+
+Optional Properties:
+   - qcom,-always-on - specifies whether supply should be kept
+   "on" always.
+   - qcom,-lpm_sup - specifies whether supply can be kept in low
+   power mode (lpm).
+   - qcom,-voltage_level - specifies voltage levels for supply.
+   Should be specified in pairs (min, max), units uV.
+   - qcom,-current_level - specifies load levels for supply in lpm
+   or high power mode (hpm). Should be specified in
+   pairs (lpm, hpm), units uA.
+
+


This looks really weird.

What's so special here that requires you to have your own specific
regulator bindings?



  Example:

@@ -33,8 +49,15 @@ Example:
 bus-width = <8>;
 non-removable;

-   vmmc-supply = <_l20>;
-   vqmmc-supply = <_s3>;
+   vdd-supply = <_l20>;
+   qcom,vdd-voltage-level = <295 295>;
+   qcom,vdd-current-level = <9000 80>;
+
+   vdd-io-supply = <_s3>;
+   qcom,vdd-io-always-on;
+   qcom,vdd-io-lpm-sup;
+   qcom,vdd-io-voltage-level = <180 295>;
+   qcom,vdd-io-current-level = <6 22000>;

 pinctrl-names = "default";
 pinctrl-0 = <_clk _cmd _data>;
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index d4d432b..0e0f12d 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -213,6 +213,33 @@ struct sdhci_msm_offset sdhci_msm_offset_mci_present = {
 .core_ddr_config_2 = 0x1BC,
  };

+/* This structure keeps information per regulator */
+struct sdhci_msm_reg_data {
+   /* voltage regulator handle */
+   struct regulator *reg;
+   /* regulator name */
+   const char *name;
+   /* voltage level to be set */
+   u32 low_vol_level;
+   u32 high_vol_level;
+   /* Load values for low power and high power mode */
+   u32 lpm_uA;
+   u32 hpm_uA;
+   /* is this regulator enabled? */
+   bool is_enabled;
+   /* is this regulator needs to be always on? */
+   bool is_always_on;
+   /* is low power mode setting required for this regulator? */
+   bool lpm_sup;
+   bool set_voltage_sup;
+};
+
+struct sdhci_msm_pltfm_data {
+   /* Change-Id: Ide3a658ad51a3c3d4a05c47c0e8f013f647c9516 */
+   struct sdhci_msm_reg_data *vdd_data;
+   struct sdhci_msm_reg_data *vdd_io_data;
+};
+
  struct sdhci_msm_host {
 struct platform_device *pdev;
 void __iomem *core_mem; /* MSM SDCC mapped address */
@@ -234,6 +261,8 @@ struct sdhci_msm_host {
 u32 caps_0;
 bool mci_removed;
 const struct sdhci_msm_offset *offset;
+   bool pltfm_init_done;
+   struct sdhci_msm_pltfm_data pdata;
  };

  /*
@@ -298,6 +327,336 @@ void sdhci_msm_vendor_writel_relaxed(u32 val, struct 
sdhci_host *host,
 writel_relaxed(val, base_addr + offset);
  }

+enum vdd_io_level {
+   /* set vdd_io_data->low_vol_level */
+   VDD_IO_LOW,
+   /* set vdd_io_data->high_vol_level */
+   VDD_IO_HIGH,
+   /*
+

Re: [PATCH RFC 1/4] mmc: host: Register changes for sdcc V5

2018-05-03 Thread Vijay Viswanath



On 5/2/2018 1:58 PM, Ulf Hansson wrote:

On 1 May 2018 at 12:39, Vijay Viswanath <vvisw...@codeaurora.org> wrote:

From: Sayali Lokhande <saya...@codeaurora.org>

For SDCC version 5.0.0, MCI registers are removed from SDCC
interface and some registers are moved to HC. This change is
to support MCI register removal for msmfalcon. New compatible
string "qcom,sdhci-msm-v5" is added for msmfalcon to support
this change.


To simplify review, I would recommend to split this up in a few more
pieces, a few re-factoring while the final change adds the
qcom,sdhci-msm-v5 support.



Will do



Change-Id: I0febfd9bb436a8eff20c20107dd4180c9781
Signed-off-by: Sayali Lokhande <saya...@codeaurora.org>
Signed-off-by: Vijay Viswanath <vvisw...@codeaurora.org>
---
  .../devicetree/bindings/mmc/sdhci-msm.txt  |   5 +-


Please move DT changes into separate patches and make sure to sent it
to DT maintainers as well.


  drivers/mmc/host/sdhci-msm.c   | 485 +++--
  2 files changed, 365 insertions(+), 125 deletions(-)

diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt 
b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
index bfdcdc4..c2b7b2b 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
@@ -4,7 +4,10 @@ This file documents differences between the core properties in 
mmc.txt
  and the properties used by the sdhci-msm driver.

  Required properties:
-- compatible: Should contain "qcom,sdhci-msm-v4".
+- compatible: Should contain "qcom,sdhci-msm-v4" or "qcom,sdhci-msm-v5".
+For SDCC version 5.0.0, MCI registers are removed from SDCC
+interface and some registers are moved to HC. New compatible
+string is added to support this change - "qcom,sdhci-msm-v5".
  - reg: Base address and length of the register in the following order:
 - Host controller register map (required)
 - SD Core register map (required)
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index bb11916..d4d432b 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c


[...]



+struct sdhci_msm_offset {


I think a better idea is to create a struct sdhci_msm_variant and make
it contain all the variant specific data. So, not only the offsets,
but other variant data as well.

More comments below.


+   u32 core_mci_data_cnt;
+   u32 core_mci_status;
+   u32 core_mci_fifo_cnt;
+   u32 core_mci_version;
+   u32 core_generics;
+   u32 core_testbus_config;
+   u32 core_testbus_sel2_bit;
+   u32 core_testbus_ena;
+   u32 core_testbus_sel2;
+   u32 core_pwrctl_status;
+   u32 core_pwrctl_mask;
+   u32 core_pwrctl_clear;
+   u32 core_pwrctl_ctl;
+   u32 core_sdcc_debug_reg;
+   u32 core_dll_config;
+   u32 core_dll_status;
+   u32 core_vendor_spec;
+   u32 core_vendor_spec_adma_err_addr0;
+   u32 core_vendor_spec_adma_err_addr1;
+   u32 core_vendor_spec_func2;
+   u32 core_vendor_spec_capabilities0;
+   u32 core_ddr_200_cfg;
+   u32 core_vendor_spec3;
+   u32 core_dll_config_2;
+   u32 core_ddr_config;
+   u32 core_ddr_config_2;
+};
+
+struct sdhci_msm_offset sdhci_msm_offset_mci_removed = {
+   .core_mci_data_cnt = 0x35c,
+   .core_mci_status = 0x324,
+   .core_mci_fifo_cnt = 0x308,
+   .core_mci_version = 0x318,
+   .core_generics = 0x320,
+   .core_testbus_config = 0x32c,
+   .core_testbus_sel2_bit = 3,
+   .core_testbus_ena = (1 << 31),
+   .core_testbus_sel2 = (1 << 3),
+   .core_pwrctl_status = 0x240,
+   .core_pwrctl_mask = 0x244,
+   .core_pwrctl_clear = 0x248,
+   .core_pwrctl_ctl = 0x24c,
+   .core_sdcc_debug_reg = 0x358,
+   .core_dll_config = 0x200,
+   .core_dll_status = 0x208,
+   .core_vendor_spec = 0x20c,
+   .core_vendor_spec_adma_err_addr0 = 0x214,
+   .core_vendor_spec_adma_err_addr1 = 0x218,
+   .core_vendor_spec_func2 = 0x210,
+   .core_vendor_spec_capabilities0 = 0x21c,
+   .core_ddr_200_cfg = 0x224,
+   .core_vendor_spec3 = 0x250,
+   .core_dll_config_2 = 0x254,
+   .core_ddr_config = 0x258,
+   .core_ddr_config_2 = 0x25c,
+};
+
+struct sdhci_msm_offset sdhci_msm_offset_mci_present = {
+   .core_mci_data_cnt = 0x30,
+   .core_mci_status = 0x34,
+   .core_mci_fifo_cnt = 0x44,
+   .core_mci_version = 0x050,
+   .core_generics = 0x70,
+   .core_testbus_config = 0x0CC,
+   .core_testbus_sel2_bit = 4,
+   .core_testbus_ena = (1 << 3),
+   .core_testbus_sel2 = (1 << 4),
+   .core_pwrctl_status = 0xDC,
+   .core_pwrctl_mask = 0xE0,
+   .core_pwrctl_clear = 0xE4,
+   .core_pwrctl_ctl = 0xE8,
+   .core_sdcc_debug_reg = 0x124,
+  

Re: [PATCH RFC 1/4] mmc: host: Register changes for sdcc V5

2018-05-03 Thread Vijay Viswanath



On 5/2/2018 1:58 PM, Ulf Hansson wrote:

On 1 May 2018 at 12:39, Vijay Viswanath  wrote:

From: Sayali Lokhande 

For SDCC version 5.0.0, MCI registers are removed from SDCC
interface and some registers are moved to HC. This change is
to support MCI register removal for msmfalcon. New compatible
string "qcom,sdhci-msm-v5" is added for msmfalcon to support
this change.


To simplify review, I would recommend to split this up in a few more
pieces, a few re-factoring while the final change adds the
qcom,sdhci-msm-v5 support.



Will do



Change-Id: I0febfd9bb436a8eff20c20107dd4180c9781
Signed-off-by: Sayali Lokhande 
Signed-off-by: Vijay Viswanath 
---
  .../devicetree/bindings/mmc/sdhci-msm.txt  |   5 +-


Please move DT changes into separate patches and make sure to sent it
to DT maintainers as well.


  drivers/mmc/host/sdhci-msm.c   | 485 +++--
  2 files changed, 365 insertions(+), 125 deletions(-)

diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt 
b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
index bfdcdc4..c2b7b2b 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
@@ -4,7 +4,10 @@ This file documents differences between the core properties in 
mmc.txt
  and the properties used by the sdhci-msm driver.

  Required properties:
-- compatible: Should contain "qcom,sdhci-msm-v4".
+- compatible: Should contain "qcom,sdhci-msm-v4" or "qcom,sdhci-msm-v5".
+For SDCC version 5.0.0, MCI registers are removed from SDCC
+interface and some registers are moved to HC. New compatible
+string is added to support this change - "qcom,sdhci-msm-v5".
  - reg: Base address and length of the register in the following order:
 - Host controller register map (required)
 - SD Core register map (required)
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index bb11916..d4d432b 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c


[...]



+struct sdhci_msm_offset {


I think a better idea is to create a struct sdhci_msm_variant and make
it contain all the variant specific data. So, not only the offsets,
but other variant data as well.

More comments below.


+   u32 core_mci_data_cnt;
+   u32 core_mci_status;
+   u32 core_mci_fifo_cnt;
+   u32 core_mci_version;
+   u32 core_generics;
+   u32 core_testbus_config;
+   u32 core_testbus_sel2_bit;
+   u32 core_testbus_ena;
+   u32 core_testbus_sel2;
+   u32 core_pwrctl_status;
+   u32 core_pwrctl_mask;
+   u32 core_pwrctl_clear;
+   u32 core_pwrctl_ctl;
+   u32 core_sdcc_debug_reg;
+   u32 core_dll_config;
+   u32 core_dll_status;
+   u32 core_vendor_spec;
+   u32 core_vendor_spec_adma_err_addr0;
+   u32 core_vendor_spec_adma_err_addr1;
+   u32 core_vendor_spec_func2;
+   u32 core_vendor_spec_capabilities0;
+   u32 core_ddr_200_cfg;
+   u32 core_vendor_spec3;
+   u32 core_dll_config_2;
+   u32 core_ddr_config;
+   u32 core_ddr_config_2;
+};
+
+struct sdhci_msm_offset sdhci_msm_offset_mci_removed = {
+   .core_mci_data_cnt = 0x35c,
+   .core_mci_status = 0x324,
+   .core_mci_fifo_cnt = 0x308,
+   .core_mci_version = 0x318,
+   .core_generics = 0x320,
+   .core_testbus_config = 0x32c,
+   .core_testbus_sel2_bit = 3,
+   .core_testbus_ena = (1 << 31),
+   .core_testbus_sel2 = (1 << 3),
+   .core_pwrctl_status = 0x240,
+   .core_pwrctl_mask = 0x244,
+   .core_pwrctl_clear = 0x248,
+   .core_pwrctl_ctl = 0x24c,
+   .core_sdcc_debug_reg = 0x358,
+   .core_dll_config = 0x200,
+   .core_dll_status = 0x208,
+   .core_vendor_spec = 0x20c,
+   .core_vendor_spec_adma_err_addr0 = 0x214,
+   .core_vendor_spec_adma_err_addr1 = 0x218,
+   .core_vendor_spec_func2 = 0x210,
+   .core_vendor_spec_capabilities0 = 0x21c,
+   .core_ddr_200_cfg = 0x224,
+   .core_vendor_spec3 = 0x250,
+   .core_dll_config_2 = 0x254,
+   .core_ddr_config = 0x258,
+   .core_ddr_config_2 = 0x25c,
+};
+
+struct sdhci_msm_offset sdhci_msm_offset_mci_present = {
+   .core_mci_data_cnt = 0x30,
+   .core_mci_status = 0x34,
+   .core_mci_fifo_cnt = 0x44,
+   .core_mci_version = 0x050,
+   .core_generics = 0x70,
+   .core_testbus_config = 0x0CC,
+   .core_testbus_sel2_bit = 4,
+   .core_testbus_ena = (1 << 3),
+   .core_testbus_sel2 = (1 << 4),
+   .core_pwrctl_status = 0xDC,
+   .core_pwrctl_mask = 0xE0,
+   .core_pwrctl_clear = 0xE4,
+   .core_pwrctl_ctl = 0xE8,
+   .core_sdcc_debug_reg = 0x124,
+   .core_dll_config = 0x100,
+   .core_dll_status = 0x108,
+   .core_vendor_spec = 0x10C,
+   .core_vendor_spe

[PATCH RFC 2/4] mmc: sdhci-msm: Add and use voltage regulator related APIs

2018-05-01 Thread Vijay Viswanath
From: Asutosh Das <asuto...@codeaurora.org>

Some platforms require that the voltage switching happen only after
the register write occurs and controller is ready for the switch. When
the controller is ready, it will inform through power irq.

Add voltage regulator APIs and use them during power irq to switch
voltage instead of relying on core layer voltage switching.

Change-Id: Iaa98686e71a5bfe0092c68e9ffa563b060c5ac60
Signed-off-by: Asutosh Das <asuto...@codeaurora.org>
Signed-off-by: Venkat Gopalakrishnan <venk...@codeaurora.org>
Signed-off-by: Subhash Jadavani <subha...@codeaurora.org>
Signed-off-by: Vijay Viswanath <vvisw...@codeaurora.org>
---
 .../devicetree/bindings/mmc/sdhci-msm.txt  |  27 +-
 drivers/mmc/host/sdhci-msm.c   | 537 +++--
 2 files changed, 529 insertions(+), 35 deletions(-)

diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt 
b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
index c2b7b2b..c454046 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
@@ -23,6 +23,22 @@ Required properties:
"xo"- TCXO clock (optional)
"cal"   - reference clock for RCLK delay calibration (optional)
"sleep" - sleep clock for RCLK delay calibration (optional)
+- -supply: phandle to the regulator device tree node if voltage
+   regulators needs to be handled from within sdhci-msm layer.
+   Supported "supply-name" are "vdd" and "vdd-io".
+
+Optional Properties:
+   - qcom,-always-on - specifies whether supply should be kept
+   "on" always.
+   - qcom,-lpm_sup - specifies whether supply can be kept in low
+   power mode (lpm).
+   - qcom,-voltage_level - specifies voltage levels for supply.
+   Should be specified in pairs (min, max), units uV.
+   - qcom,-current_level - specifies load levels for supply in lpm
+   or high power mode (hpm). Should be specified in
+   pairs (lpm, hpm), units uA.
+
+
 
 Example:
 
@@ -33,8 +49,15 @@ Example:
bus-width = <8>;
non-removable;
 
-   vmmc-supply = <_l20>;
-   vqmmc-supply = <_s3>;
+   vdd-supply = <_l20>;
+   qcom,vdd-voltage-level = <295 295>;
+   qcom,vdd-current-level = <9000 80>;
+
+   vdd-io-supply = <_s3>;
+   qcom,vdd-io-always-on;
+   qcom,vdd-io-lpm-sup;
+   qcom,vdd-io-voltage-level = <180 295>;
+   qcom,vdd-io-current-level = <6 22000>;
 
pinctrl-names = "default";
pinctrl-0 = <_clk _cmd _data>;
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index d4d432b..0e0f12d 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -213,6 +213,33 @@ struct sdhci_msm_offset sdhci_msm_offset_mci_present = {
.core_ddr_config_2 = 0x1BC,
 };
 
+/* This structure keeps information per regulator */
+struct sdhci_msm_reg_data {
+   /* voltage regulator handle */
+   struct regulator *reg;
+   /* regulator name */
+   const char *name;
+   /* voltage level to be set */
+   u32 low_vol_level;
+   u32 high_vol_level;
+   /* Load values for low power and high power mode */
+   u32 lpm_uA;
+   u32 hpm_uA;
+   /* is this regulator enabled? */
+   bool is_enabled;
+   /* is this regulator needs to be always on? */
+   bool is_always_on;
+   /* is low power mode setting required for this regulator? */
+   bool lpm_sup;
+   bool set_voltage_sup;
+};
+
+struct sdhci_msm_pltfm_data {
+   /* Change-Id: Ide3a658ad51a3c3d4a05c47c0e8f013f647c9516 */
+   struct sdhci_msm_reg_data *vdd_data;
+   struct sdhci_msm_reg_data *vdd_io_data;
+};
+
 struct sdhci_msm_host {
struct platform_device *pdev;
void __iomem *core_mem; /* MSM SDCC mapped address */
@@ -234,6 +261,8 @@ struct sdhci_msm_host {
u32 caps_0;
bool mci_removed;
const struct sdhci_msm_offset *offset;
+   bool pltfm_init_done;
+   struct sdhci_msm_pltfm_data pdata;
 };
 
 /*
@@ -298,6 +327,336 @@ void sdhci_msm_vendor_writel_relaxed(u32 val, struct 
sdhci_host *host,
writel_relaxed(val, base_addr + offset);
 }
 
+enum vdd_io_level {
+   /* set vdd_io_data->low_vol_level */
+   VDD_IO_LOW,
+   /* set vdd_io_data->high_vol_level */
+   VDD_IO_HIGH,
+   /*
+* set whatever there in voltage_level (third argument) of
+* sdhci_msm_set_vdd_io_vol() function.
+*/
+   VDD_IO_SET_LEVEL,
+};
+
+#define MAX_PROP_SIZE 32
+static int sdhci_msm_dt_parse_vreg_info(struct device *

[PATCH RFC 4/4] host: sdhci-msm: implement get_current_limit() host op

2018-05-01 Thread Vijay Viswanath
From: Sahitya Tummala <stumm...@codeaurora.org>

This is needed to get the current capabilities of vdd
regulator that is not managed by SDHCI driver.

Change-Id: I927c14b9890f1d672fe8a3e89d0b334f43463b36
Signed-off-by: Sahitya Tummala <stumm...@codeaurora.org>
Signed-off-by: Sayali Lokhande <saya...@codeaurora.org>
Signed-off-by: Vijay Viswanath <vvisw...@codeaurora.org>
---
 drivers/mmc/host/sdhci-msm.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 0e0f12d..083b4a5 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -2079,6 +2079,18 @@ static void sdhci_msm_set_default_hw_caps(struct device 
*dev,
{},
 };
 
+static unsigned int sdhci_msm_get_current_limit(struct sdhci_host *host)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+   struct sdhci_msm_reg_data *vdd_data = msm_host->pdata.vdd_data;
+   u32 max_curr = 0;
+
+   if (vdd_data)
+   max_curr = vdd_data->hpm_uA;
+   return max_curr;
+}
+
 MODULE_DEVICE_TABLE(of, sdhci_msm_dt_match);
 
 static const struct sdhci_ops sdhci_msm_ops = {
@@ -2090,6 +2102,7 @@ static void sdhci_msm_set_default_hw_caps(struct device 
*dev,
.set_uhs_signaling = sdhci_msm_set_uhs_signaling,
.write_w = sdhci_msm_writew,
.write_b = sdhci_msm_writeb,
+   .get_current_limit = sdhci_msm_get_current_limit,
 };
 
 static const struct sdhci_pltfm_data sdhci_msm_pdata = {
-- 
 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.



[PATCH RFC 3/4] host: sdhci: fix current caps when there is no host->vmmc

2018-05-01 Thread Vijay Viswanath
From: Sahitya Tummala <stumm...@codeaurora.org>

When the regulators are not managed by SDHCI host driver (i.e.,
when host->vmmc and host->vmmcq are absent), get the regulator
current capabilities through a new host op get_current_limit().

Signed-off-by: Sahitya Tummala <stumm...@codeaurora.org>
Signed-off-by: Sayali Lokhande <saya...@codeaurora.org>
[vvisw...@codeaurora.org: fixed trivial merge conflicts]
Signed-off-by: Vijay Viswanath <vvisw...@codeaurora.org>

Change-Id: I3370a2411beec1f03cc5f102bf95cd816c60351e
---
 drivers/mmc/host/sdhci.c | 11 ---
 drivers/mmc/host/sdhci.h |  1 +
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 0d5fcca..edc2ccd 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -3570,10 +3570,15 @@ int sdhci_setup_host(struct sdhci_host *host)
 * value.
 */
max_current_caps = sdhci_readl(host, SDHCI_MAX_CURRENT);
-   if (!max_current_caps && !IS_ERR(mmc->supply.vmmc)) {
-   int curr = regulator_get_current_limit(mmc->supply.vmmc);
-   if (curr > 0) {
+   if (!max_current_caps) {
+   u32 curr = 0;
+
+   if (!IS_ERR(mmc->supply.vmmc))
+   curr = regulator_get_current_limit(mmc->supply.vmmc);
+   else if (host->ops->get_current_limit)
+   curr = host->ops->get_current_limit(host);
 
+   if (curr > 0) {
/* convert to SDHCI_MAX_CURRENT format */
curr = curr/1000;  /* convert to mA */
curr = curr/SDHCI_MAX_CURRENT_MULTIPLIER;
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 54bc444..a01af78 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -584,6 +584,7 @@ struct sdhci_ops {
void(*adma_workaround)(struct sdhci_host *host, u32 intmask);
void(*card_event)(struct sdhci_host *host);
void(*voltage_switch)(struct sdhci_host *host);
+   unsigned int(*get_current_limit)(struct sdhci_host *host);
 };
 
 #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
-- 
 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.



[PATCH RFC 3/4] host: sdhci: fix current caps when there is no host->vmmc

2018-05-01 Thread Vijay Viswanath
From: Sahitya Tummala 

When the regulators are not managed by SDHCI host driver (i.e.,
when host->vmmc and host->vmmcq are absent), get the regulator
current capabilities through a new host op get_current_limit().

Signed-off-by: Sahitya Tummala 
Signed-off-by: Sayali Lokhande 
[vvisw...@codeaurora.org: fixed trivial merge conflicts]
Signed-off-by: Vijay Viswanath 

Change-Id: I3370a2411beec1f03cc5f102bf95cd816c60351e
---
 drivers/mmc/host/sdhci.c | 11 ---
 drivers/mmc/host/sdhci.h |  1 +
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 0d5fcca..edc2ccd 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -3570,10 +3570,15 @@ int sdhci_setup_host(struct sdhci_host *host)
 * value.
 */
max_current_caps = sdhci_readl(host, SDHCI_MAX_CURRENT);
-   if (!max_current_caps && !IS_ERR(mmc->supply.vmmc)) {
-   int curr = regulator_get_current_limit(mmc->supply.vmmc);
-   if (curr > 0) {
+   if (!max_current_caps) {
+   u32 curr = 0;
+
+   if (!IS_ERR(mmc->supply.vmmc))
+   curr = regulator_get_current_limit(mmc->supply.vmmc);
+   else if (host->ops->get_current_limit)
+   curr = host->ops->get_current_limit(host);
 
+   if (curr > 0) {
/* convert to SDHCI_MAX_CURRENT format */
curr = curr/1000;  /* convert to mA */
curr = curr/SDHCI_MAX_CURRENT_MULTIPLIER;
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 54bc444..a01af78 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -584,6 +584,7 @@ struct sdhci_ops {
void(*adma_workaround)(struct sdhci_host *host, u32 intmask);
void(*card_event)(struct sdhci_host *host);
void(*voltage_switch)(struct sdhci_host *host);
+   unsigned int(*get_current_limit)(struct sdhci_host *host);
 };
 
 #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
-- 
 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.



[PATCH RFC 4/4] host: sdhci-msm: implement get_current_limit() host op

2018-05-01 Thread Vijay Viswanath
From: Sahitya Tummala 

This is needed to get the current capabilities of vdd
regulator that is not managed by SDHCI driver.

Change-Id: I927c14b9890f1d672fe8a3e89d0b334f43463b36
Signed-off-by: Sahitya Tummala 
Signed-off-by: Sayali Lokhande 
Signed-off-by: Vijay Viswanath 
---
 drivers/mmc/host/sdhci-msm.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 0e0f12d..083b4a5 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -2079,6 +2079,18 @@ static void sdhci_msm_set_default_hw_caps(struct device 
*dev,
{},
 };
 
+static unsigned int sdhci_msm_get_current_limit(struct sdhci_host *host)
+{
+   struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+   struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+   struct sdhci_msm_reg_data *vdd_data = msm_host->pdata.vdd_data;
+   u32 max_curr = 0;
+
+   if (vdd_data)
+   max_curr = vdd_data->hpm_uA;
+   return max_curr;
+}
+
 MODULE_DEVICE_TABLE(of, sdhci_msm_dt_match);
 
 static const struct sdhci_ops sdhci_msm_ops = {
@@ -2090,6 +2102,7 @@ static void sdhci_msm_set_default_hw_caps(struct device 
*dev,
.set_uhs_signaling = sdhci_msm_set_uhs_signaling,
.write_w = sdhci_msm_writew,
.write_b = sdhci_msm_writeb,
+   .get_current_limit = sdhci_msm_get_current_limit,
 };
 
 static const struct sdhci_pltfm_data sdhci_msm_pdata = {
-- 
 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.



[PATCH RFC 2/4] mmc: sdhci-msm: Add and use voltage regulator related APIs

2018-05-01 Thread Vijay Viswanath
From: Asutosh Das 

Some platforms require that the voltage switching happen only after
the register write occurs and controller is ready for the switch. When
the controller is ready, it will inform through power irq.

Add voltage regulator APIs and use them during power irq to switch
voltage instead of relying on core layer voltage switching.

Change-Id: Iaa98686e71a5bfe0092c68e9ffa563b060c5ac60
Signed-off-by: Asutosh Das 
Signed-off-by: Venkat Gopalakrishnan 
Signed-off-by: Subhash Jadavani 
Signed-off-by: Vijay Viswanath 
---
 .../devicetree/bindings/mmc/sdhci-msm.txt  |  27 +-
 drivers/mmc/host/sdhci-msm.c   | 537 +++--
 2 files changed, 529 insertions(+), 35 deletions(-)

diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt 
b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
index c2b7b2b..c454046 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
@@ -23,6 +23,22 @@ Required properties:
"xo"- TCXO clock (optional)
"cal"   - reference clock for RCLK delay calibration (optional)
"sleep" - sleep clock for RCLK delay calibration (optional)
+- -supply: phandle to the regulator device tree node if voltage
+   regulators needs to be handled from within sdhci-msm layer.
+   Supported "supply-name" are "vdd" and "vdd-io".
+
+Optional Properties:
+   - qcom,-always-on - specifies whether supply should be kept
+   "on" always.
+   - qcom,-lpm_sup - specifies whether supply can be kept in low
+   power mode (lpm).
+   - qcom,-voltage_level - specifies voltage levels for supply.
+   Should be specified in pairs (min, max), units uV.
+   - qcom,-current_level - specifies load levels for supply in lpm
+   or high power mode (hpm). Should be specified in
+   pairs (lpm, hpm), units uA.
+
+
 
 Example:
 
@@ -33,8 +49,15 @@ Example:
bus-width = <8>;
non-removable;
 
-   vmmc-supply = <_l20>;
-   vqmmc-supply = <_s3>;
+   vdd-supply = <_l20>;
+   qcom,vdd-voltage-level = <295 295>;
+   qcom,vdd-current-level = <9000 80>;
+
+   vdd-io-supply = <_s3>;
+   qcom,vdd-io-always-on;
+   qcom,vdd-io-lpm-sup;
+   qcom,vdd-io-voltage-level = <180 295>;
+   qcom,vdd-io-current-level = <6 22000>;
 
pinctrl-names = "default";
pinctrl-0 = <_clk _cmd _data>;
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index d4d432b..0e0f12d 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -213,6 +213,33 @@ struct sdhci_msm_offset sdhci_msm_offset_mci_present = {
.core_ddr_config_2 = 0x1BC,
 };
 
+/* This structure keeps information per regulator */
+struct sdhci_msm_reg_data {
+   /* voltage regulator handle */
+   struct regulator *reg;
+   /* regulator name */
+   const char *name;
+   /* voltage level to be set */
+   u32 low_vol_level;
+   u32 high_vol_level;
+   /* Load values for low power and high power mode */
+   u32 lpm_uA;
+   u32 hpm_uA;
+   /* is this regulator enabled? */
+   bool is_enabled;
+   /* is this regulator needs to be always on? */
+   bool is_always_on;
+   /* is low power mode setting required for this regulator? */
+   bool lpm_sup;
+   bool set_voltage_sup;
+};
+
+struct sdhci_msm_pltfm_data {
+   /* Change-Id: Ide3a658ad51a3c3d4a05c47c0e8f013f647c9516 */
+   struct sdhci_msm_reg_data *vdd_data;
+   struct sdhci_msm_reg_data *vdd_io_data;
+};
+
 struct sdhci_msm_host {
struct platform_device *pdev;
void __iomem *core_mem; /* MSM SDCC mapped address */
@@ -234,6 +261,8 @@ struct sdhci_msm_host {
u32 caps_0;
bool mci_removed;
const struct sdhci_msm_offset *offset;
+   bool pltfm_init_done;
+   struct sdhci_msm_pltfm_data pdata;
 };
 
 /*
@@ -298,6 +327,336 @@ void sdhci_msm_vendor_writel_relaxed(u32 val, struct 
sdhci_host *host,
writel_relaxed(val, base_addr + offset);
 }
 
+enum vdd_io_level {
+   /* set vdd_io_data->low_vol_level */
+   VDD_IO_LOW,
+   /* set vdd_io_data->high_vol_level */
+   VDD_IO_HIGH,
+   /*
+* set whatever there in voltage_level (third argument) of
+* sdhci_msm_set_vdd_io_vol() function.
+*/
+   VDD_IO_SET_LEVEL,
+};
+
+#define MAX_PROP_SIZE 32
+static int sdhci_msm_dt_parse_vreg_info(struct device *dev,
+   struct sdhci_msm_reg_data **vreg_data, const char *vreg_name)
+{
+   int len, ret = 0;
+   const __be32 *prop;
+   c

[PATCH RFC 1/4] mmc: host: Register changes for sdcc V5

2018-05-01 Thread Vijay Viswanath
From: Sayali Lokhande <saya...@codeaurora.org>

For SDCC version 5.0.0, MCI registers are removed from SDCC
interface and some registers are moved to HC. This change is
to support MCI register removal for msmfalcon. New compatible
string "qcom,sdhci-msm-v5" is added for msmfalcon to support
this change.

Change-Id: I0febfd9bb436a8eff20c20107dd4180c9781
Signed-off-by: Sayali Lokhande <saya...@codeaurora.org>
Signed-off-by: Vijay Viswanath <vvisw...@codeaurora.org>
---
 .../devicetree/bindings/mmc/sdhci-msm.txt  |   5 +-
 drivers/mmc/host/sdhci-msm.c   | 485 +++--
 2 files changed, 365 insertions(+), 125 deletions(-)

diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt 
b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
index bfdcdc4..c2b7b2b 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
@@ -4,7 +4,10 @@ This file documents differences between the core properties in 
mmc.txt
 and the properties used by the sdhci-msm driver.
 
 Required properties:
-- compatible: Should contain "qcom,sdhci-msm-v4".
+- compatible: Should contain "qcom,sdhci-msm-v4" or "qcom,sdhci-msm-v5".
+For SDCC version 5.0.0, MCI registers are removed from SDCC
+interface and some registers are moved to HC. New compatible
+string is added to support this change - "qcom,sdhci-msm-v5".
 - reg: Base address and length of the register in the following order:
- Host controller register map (required)
- SD Core register map (required)
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index bb11916..d4d432b 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -39,10 +39,6 @@
 #define CORE_SW_RSTBIT(7)
 #define FF_CLK_SW_RST_DIS  BIT(13)
 
-#define CORE_PWRCTL_STATUS 0xdc
-#define CORE_PWRCTL_MASK   0xe0
-#define CORE_PWRCTL_CLEAR  0xe4
-#define CORE_PWRCTL_CTL0xe8
 #define CORE_PWRCTL_BUS_OFFBIT(0)
 #define CORE_PWRCTL_BUS_ON BIT(1)
 #define CORE_PWRCTL_IO_LOW BIT(2)
@@ -63,17 +59,13 @@
 #define CORE_CDR_EXT_ENBIT(19)
 #define CORE_DLL_PDN   BIT(29)
 #define CORE_DLL_RST   BIT(30)
-#define CORE_DLL_CONFIG0x100
 #define CORE_CMD_DAT_TRACK_SEL BIT(0)
-#define CORE_DLL_STATUS0x108
 
-#define CORE_DLL_CONFIG_2  0x1b4
 #define CORE_DDR_CAL_ENBIT(0)
 #define CORE_FLL_CYCLE_CNT BIT(18)
 #define CORE_DLL_CLOCK_DISABLE BIT(21)
 
-#define CORE_VENDOR_SPEC   0x10c
-#define CORE_VENDOR_SPEC_POR_VAL   0xa1c
+#define CORE_VENDOR_SPEC_POR_VAL 0xa1c
 #define CORE_CLK_PWRSAVE   BIT(1)
 #define CORE_HC_MCLK_SEL_DFLT  (2 << 8)
 #define CORE_HC_MCLK_SEL_HS400 (3 << 8)
@@ -111,17 +103,14 @@
 #define CORE_CDC_SWITCH_BYPASS_OFF BIT(0)
 #define CORE_CDC_SWITCH_RC_EN  BIT(1)
 
-#define CORE_DDR_200_CFG   0x184
 #define CORE_CDC_T4_DLY_SELBIT(0)
 #define CORE_CMDIN_RCLK_EN BIT(1)
 #define CORE_START_CDC_TRAFFIC BIT(6)
-#define CORE_VENDOR_SPEC3  0x1b0
+
 #define CORE_PWRSAVE_DLL   BIT(3)
 
-#define CORE_DDR_CONFIG0x1b8
 #define DDR_CONFIG_POR_VAL 0x80040853
 
-#define CORE_VENDOR_SPEC_CAPABILITIES0 0x11c
 
 #define INVALID_TUNING_PHASE   -1
 #define SDHCI_MSM_MIN_CLOCK40
@@ -137,6 +126,93 @@
 /* Timeout value to avoid infinite waiting for pwr_irq */
 #define MSM_PWR_IRQ_TIMEOUT_MS 5000
 
+struct sdhci_msm_offset {
+   u32 core_mci_data_cnt;
+   u32 core_mci_status;
+   u32 core_mci_fifo_cnt;
+   u32 core_mci_version;
+   u32 core_generics;
+   u32 core_testbus_config;
+   u32 core_testbus_sel2_bit;
+   u32 core_testbus_ena;
+   u32 core_testbus_sel2;
+   u32 core_pwrctl_status;
+   u32 core_pwrctl_mask;
+   u32 core_pwrctl_clear;
+   u32 core_pwrctl_ctl;
+   u32 core_sdcc_debug_reg;
+   u32 core_dll_config;
+   u32 core_dll_status;
+   u32 core_vendor_spec;
+   u32 core_vendor_spec_adma_err_addr0;
+   u32 core_vendor_spec_adma_err_addr1;
+   u32 core_vendor_spec_func2;
+   u32 core_vendor_spec_capabilities0;
+   u32 core_ddr_200_cfg;
+   u32 core_vendor_spec3;
+   u32 core_dll_config_2;
+   u32 core_ddr_config;
+   u32 core_ddr_config_2;
+};
+
+struct sdhci_msm_offset sdhci_msm_offset_mci_removed = {
+   .core_mci_data_cnt = 0x35c,
+   .core_mci_status = 0x324,
+   .core_mci_fifo_cnt = 0x308,
+   .core_mci_version = 0x318,
+   .core_generics = 0x320,
+   .core_testbus_config = 0x32c,
+   .core_testbus_sel2_bit = 3,
+   .core_testbus_ena = (1 << 31),
+   .core_testbus_sel2 = (1 << 3),
+   .core_pwrctl_status = 0x240,
+   .co

[PATCH RFC 1/4] mmc: host: Register changes for sdcc V5

2018-05-01 Thread Vijay Viswanath
From: Sayali Lokhande 

For SDCC version 5.0.0, MCI registers are removed from SDCC
interface and some registers are moved to HC. This change is
to support MCI register removal for msmfalcon. New compatible
string "qcom,sdhci-msm-v5" is added for msmfalcon to support
this change.

Change-Id: I0febfd9bb436a8eff20c20107dd4180c9781
Signed-off-by: Sayali Lokhande 
Signed-off-by: Vijay Viswanath 
---
 .../devicetree/bindings/mmc/sdhci-msm.txt  |   5 +-
 drivers/mmc/host/sdhci-msm.c   | 485 +++--
 2 files changed, 365 insertions(+), 125 deletions(-)

diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt 
b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
index bfdcdc4..c2b7b2b 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
@@ -4,7 +4,10 @@ This file documents differences between the core properties in 
mmc.txt
 and the properties used by the sdhci-msm driver.
 
 Required properties:
-- compatible: Should contain "qcom,sdhci-msm-v4".
+- compatible: Should contain "qcom,sdhci-msm-v4" or "qcom,sdhci-msm-v5".
+For SDCC version 5.0.0, MCI registers are removed from SDCC
+interface and some registers are moved to HC. New compatible
+string is added to support this change - "qcom,sdhci-msm-v5".
 - reg: Base address and length of the register in the following order:
- Host controller register map (required)
- SD Core register map (required)
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index bb11916..d4d432b 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -39,10 +39,6 @@
 #define CORE_SW_RSTBIT(7)
 #define FF_CLK_SW_RST_DIS  BIT(13)
 
-#define CORE_PWRCTL_STATUS 0xdc
-#define CORE_PWRCTL_MASK   0xe0
-#define CORE_PWRCTL_CLEAR  0xe4
-#define CORE_PWRCTL_CTL0xe8
 #define CORE_PWRCTL_BUS_OFFBIT(0)
 #define CORE_PWRCTL_BUS_ON BIT(1)
 #define CORE_PWRCTL_IO_LOW BIT(2)
@@ -63,17 +59,13 @@
 #define CORE_CDR_EXT_ENBIT(19)
 #define CORE_DLL_PDN   BIT(29)
 #define CORE_DLL_RST   BIT(30)
-#define CORE_DLL_CONFIG0x100
 #define CORE_CMD_DAT_TRACK_SEL BIT(0)
-#define CORE_DLL_STATUS0x108
 
-#define CORE_DLL_CONFIG_2  0x1b4
 #define CORE_DDR_CAL_ENBIT(0)
 #define CORE_FLL_CYCLE_CNT BIT(18)
 #define CORE_DLL_CLOCK_DISABLE BIT(21)
 
-#define CORE_VENDOR_SPEC   0x10c
-#define CORE_VENDOR_SPEC_POR_VAL   0xa1c
+#define CORE_VENDOR_SPEC_POR_VAL 0xa1c
 #define CORE_CLK_PWRSAVE   BIT(1)
 #define CORE_HC_MCLK_SEL_DFLT  (2 << 8)
 #define CORE_HC_MCLK_SEL_HS400 (3 << 8)
@@ -111,17 +103,14 @@
 #define CORE_CDC_SWITCH_BYPASS_OFF BIT(0)
 #define CORE_CDC_SWITCH_RC_EN  BIT(1)
 
-#define CORE_DDR_200_CFG   0x184
 #define CORE_CDC_T4_DLY_SELBIT(0)
 #define CORE_CMDIN_RCLK_EN BIT(1)
 #define CORE_START_CDC_TRAFFIC BIT(6)
-#define CORE_VENDOR_SPEC3  0x1b0
+
 #define CORE_PWRSAVE_DLL   BIT(3)
 
-#define CORE_DDR_CONFIG0x1b8
 #define DDR_CONFIG_POR_VAL 0x80040853
 
-#define CORE_VENDOR_SPEC_CAPABILITIES0 0x11c
 
 #define INVALID_TUNING_PHASE   -1
 #define SDHCI_MSM_MIN_CLOCK40
@@ -137,6 +126,93 @@
 /* Timeout value to avoid infinite waiting for pwr_irq */
 #define MSM_PWR_IRQ_TIMEOUT_MS 5000
 
+struct sdhci_msm_offset {
+   u32 core_mci_data_cnt;
+   u32 core_mci_status;
+   u32 core_mci_fifo_cnt;
+   u32 core_mci_version;
+   u32 core_generics;
+   u32 core_testbus_config;
+   u32 core_testbus_sel2_bit;
+   u32 core_testbus_ena;
+   u32 core_testbus_sel2;
+   u32 core_pwrctl_status;
+   u32 core_pwrctl_mask;
+   u32 core_pwrctl_clear;
+   u32 core_pwrctl_ctl;
+   u32 core_sdcc_debug_reg;
+   u32 core_dll_config;
+   u32 core_dll_status;
+   u32 core_vendor_spec;
+   u32 core_vendor_spec_adma_err_addr0;
+   u32 core_vendor_spec_adma_err_addr1;
+   u32 core_vendor_spec_func2;
+   u32 core_vendor_spec_capabilities0;
+   u32 core_ddr_200_cfg;
+   u32 core_vendor_spec3;
+   u32 core_dll_config_2;
+   u32 core_ddr_config;
+   u32 core_ddr_config_2;
+};
+
+struct sdhci_msm_offset sdhci_msm_offset_mci_removed = {
+   .core_mci_data_cnt = 0x35c,
+   .core_mci_status = 0x324,
+   .core_mci_fifo_cnt = 0x308,
+   .core_mci_version = 0x318,
+   .core_generics = 0x320,
+   .core_testbus_config = 0x32c,
+   .core_testbus_sel2_bit = 3,
+   .core_testbus_ena = (1 << 31),
+   .core_testbus_sel2 = (1 << 3),
+   .core_pwrctl_status = 0x240,
+   .core_pwrctl_mask = 0x244,
+   .core_pwrctl_clear = 0x248,
+   .core_pwrctl_ctl = 0x2

[PATCH RFC 0/4] Changes for SDCC5 version

2018-05-01 Thread Vijay Viswanath
With SDCC5, the MCI register space got removed and the offset/order of
several registers have changed. Based on SDCC version used and the register,
we need to pick the base address and offset.
Also power irq is a signal from controller to SW that it is ready for
voltage switch. So added support to register voltage regulators in the
msm driver and use them. With this core layer will not have to take care of
voltage regulators. Chips which are currently using core layer regulator APIs
can continue to do so, while newer chips can utilize power irq for voltage
switch.

Depends on patch series:
[PATCH V5 0/2] mmc: sdhci-msm: Configuring IO_PAD support for sdhci-msm
https://lkml.org/lkml/2018/4/20/370

Asutosh Das (1):
  mmc: sdhci-msm: Add and use voltage regulator related APIs

Sahitya Tummala (2):
  host: sdhci: fix current caps when there is no host->vmmc
  host: sdhci-msm: implement get_current_limit() host op

Sayali Lokhande (1):
  mmc: host: Register changes for sdcc V5

 .../devicetree/bindings/mmc/sdhci-msm.txt  |   32 +-
 drivers/mmc/host/sdhci-msm.c   | 1027 +---
 drivers/mmc/host/sdhci.c   |   11 +-
 drivers/mmc/host/sdhci.h   |1 +
 4 files changed, 912 insertions(+), 159 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.



[PATCH RFC 0/4] Changes for SDCC5 version

2018-05-01 Thread Vijay Viswanath
With SDCC5, the MCI register space got removed and the offset/order of
several registers have changed. Based on SDCC version used and the register,
we need to pick the base address and offset.
Also power irq is a signal from controller to SW that it is ready for
voltage switch. So added support to register voltage regulators in the
msm driver and use them. With this core layer will not have to take care of
voltage regulators. Chips which are currently using core layer regulator APIs
can continue to do so, while newer chips can utilize power irq for voltage
switch.

Depends on patch series:
[PATCH V5 0/2] mmc: sdhci-msm: Configuring IO_PAD support for sdhci-msm
https://lkml.org/lkml/2018/4/20/370

Asutosh Das (1):
  mmc: sdhci-msm: Add and use voltage regulator related APIs

Sahitya Tummala (2):
  host: sdhci: fix current caps when there is no host->vmmc
  host: sdhci-msm: implement get_current_limit() host op

Sayali Lokhande (1):
  mmc: host: Register changes for sdcc V5

 .../devicetree/bindings/mmc/sdhci-msm.txt  |   32 +-
 drivers/mmc/host/sdhci-msm.c   | 1027 +---
 drivers/mmc/host/sdhci.c   |   11 +-
 drivers/mmc/host/sdhci.h   |1 +
 4 files changed, 912 insertions(+), 159 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.



[PATCH V5 1/2] mmc: sdhci-msm: Add support to store supported vdd-io voltages

2018-04-20 Thread Vijay Viswanath
During probe check whether the vdd-io regulator of sdhc platform device
can support 1.8V and 3V and store this information as a capability of
platform device.

Signed-off-by: Vijay Viswanath <vvisw...@codeaurora.org>
Reviewed-by: Douglas Anderson <diand...@chromium.org>
---
 drivers/mmc/host/sdhci-msm.c | 29 -
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index c283291..edd30a2 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -21,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "sdhci-pltfm.h"
 
@@ -81,6 +82,9 @@
 #define CORE_HC_SELECT_IN_HS400(6 << 19)
 #define CORE_HC_SELECT_IN_MASK (7 << 19)
 
+#define CORE_3_0V_SUPPORT  (1 << 25)
+#define CORE_1_8V_SUPPORT  (1 << 26)
+
 #define CORE_CSR_CDC_CTLR_CFG0 0x130
 #define CORE_SW_TRIG_FULL_CALIBBIT(16)
 #define CORE_HW_AUTOCAL_ENABIT(17)
@@ -148,6 +152,7 @@ struct sdhci_msm_host {
u32 curr_io_level;
wait_queue_head_t pwr_irq_wait;
bool pwr_irq_flag;
+   u32 caps_0;
 };
 
 static unsigned int msm_get_clock_rate_for_bus_mode(struct sdhci_host *host,
@@ -1103,7 +1108,7 @@ static void sdhci_msm_handle_pwr_irq(struct sdhci_host 
*host, int irq)
struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
u32 irq_status, irq_ack = 0;
int retry = 10;
-   int pwr_state = 0, io_level = 0;
+   u32 pwr_state = 0, io_level = 0;
 
 
irq_status = readl_relaxed(msm_host->core_mem + CORE_PWRCTL_STATUS);
@@ -1313,6 +1318,27 @@ static void sdhci_msm_writeb(struct sdhci_host *host, u8 
val, int reg)
sdhci_msm_check_power_status(host, req_type);
 }
 
+static void sdhci_msm_set_regulator_caps(struct sdhci_msm_host *msm_host)
+{
+   struct mmc_host *mmc = msm_host->mmc;
+   struct regulator *supply = mmc->supply.vqmmc;
+   u32 caps = 0;
+
+   if (!IS_ERR(mmc->supply.vqmmc)) {
+   if (regulator_is_supported_voltage(supply, 170, 195))
+   caps |= CORE_1_8V_SUPPORT;
+   if (regulator_is_supported_voltage(supply, 270, 360))
+   caps |= CORE_3_0V_SUPPORT;
+
+   if (!caps)
+   pr_warn("%s: 1.8/3V not supported for vqmmc\n",
+   mmc_hostname(mmc));
+   }
+
+   msm_host->caps_0 |= caps;
+   pr_debug("%s: supported caps: 0x%08x\n", mmc_hostname(mmc), caps);
+}
+
 static const struct of_device_id sdhci_msm_dt_match[] = {
{ .compatible = "qcom,sdhci-msm-v4" },
{},
@@ -1530,6 +1556,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);
 
pm_runtime_mark_last_busy(>dev);
pm_runtime_put_autosuspend(>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.



[PATCH V5 1/2] mmc: sdhci-msm: Add support to store supported vdd-io voltages

2018-04-20 Thread Vijay Viswanath
During probe check whether the vdd-io regulator of sdhc platform device
can support 1.8V and 3V and store this information as a capability of
platform device.

Signed-off-by: Vijay Viswanath 
Reviewed-by: Douglas Anderson 
---
 drivers/mmc/host/sdhci-msm.c | 29 -
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index c283291..edd30a2 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -21,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "sdhci-pltfm.h"
 
@@ -81,6 +82,9 @@
 #define CORE_HC_SELECT_IN_HS400(6 << 19)
 #define CORE_HC_SELECT_IN_MASK (7 << 19)
 
+#define CORE_3_0V_SUPPORT  (1 << 25)
+#define CORE_1_8V_SUPPORT  (1 << 26)
+
 #define CORE_CSR_CDC_CTLR_CFG0 0x130
 #define CORE_SW_TRIG_FULL_CALIBBIT(16)
 #define CORE_HW_AUTOCAL_ENABIT(17)
@@ -148,6 +152,7 @@ struct sdhci_msm_host {
u32 curr_io_level;
wait_queue_head_t pwr_irq_wait;
bool pwr_irq_flag;
+   u32 caps_0;
 };
 
 static unsigned int msm_get_clock_rate_for_bus_mode(struct sdhci_host *host,
@@ -1103,7 +1108,7 @@ static void sdhci_msm_handle_pwr_irq(struct sdhci_host 
*host, int irq)
struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
u32 irq_status, irq_ack = 0;
int retry = 10;
-   int pwr_state = 0, io_level = 0;
+   u32 pwr_state = 0, io_level = 0;
 
 
irq_status = readl_relaxed(msm_host->core_mem + CORE_PWRCTL_STATUS);
@@ -1313,6 +1318,27 @@ static void sdhci_msm_writeb(struct sdhci_host *host, u8 
val, int reg)
sdhci_msm_check_power_status(host, req_type);
 }
 
+static void sdhci_msm_set_regulator_caps(struct sdhci_msm_host *msm_host)
+{
+   struct mmc_host *mmc = msm_host->mmc;
+   struct regulator *supply = mmc->supply.vqmmc;
+   u32 caps = 0;
+
+   if (!IS_ERR(mmc->supply.vqmmc)) {
+   if (regulator_is_supported_voltage(supply, 170, 195))
+   caps |= CORE_1_8V_SUPPORT;
+   if (regulator_is_supported_voltage(supply, 270, 360))
+   caps |= CORE_3_0V_SUPPORT;
+
+   if (!caps)
+   pr_warn("%s: 1.8/3V not supported for vqmmc\n",
+   mmc_hostname(mmc));
+   }
+
+   msm_host->caps_0 |= caps;
+   pr_debug("%s: supported caps: 0x%08x\n", mmc_hostname(mmc), caps);
+}
+
 static const struct of_device_id sdhci_msm_dt_match[] = {
{ .compatible = "qcom,sdhci-msm-v4" },
{},
@@ -1530,6 +1556,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);
 
pm_runtime_mark_last_busy(>dev);
pm_runtime_put_autosuspend(>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.



[PATCH V5 2/2] mmc: sdhci-msm: support voltage pad switching

2018-04-20 Thread Vijay Viswanath
The PADs for SD card are dual-voltage that support 3v/1.8v. Those PADs
have a control signal  (io_pad_pwr_switch/mode18 ) that indicates
whether the PAD works in 3v or 1.8v.

SDHC core on msm platforms should have IO_PAD_PWR_SWITCH bit set/unset
based on actual voltage used for IO lines. So when power irq is
triggered for io high or io low, the driver should check the voltages
supported and set the pad accordingly.

Signed-off-by: Krishna Konda <kko...@codeaurora.org>
Signed-off-by: Venkat Gopalakrishnan <venk...@codeaurora.org>
Signed-off-by: Vijay Viswanath <vvisw...@codeaurora.org>
Reviewed-by: Douglas Anderson <diand...@chromium.org>
---
 drivers/mmc/host/sdhci-msm.c | 57 ++--
 1 file changed, 55 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index edd30a2..bb11916 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -78,12 +78,15 @@
 #define CORE_HC_MCLK_SEL_DFLT  (2 << 8)
 #define CORE_HC_MCLK_SEL_HS400 (3 << 8)
 #define CORE_HC_MCLK_SEL_MASK  (3 << 8)
+#define CORE_IO_PAD_PWR_SWITCH_EN  (1 << 15)
+#define CORE_IO_PAD_PWR_SWITCH  (1 << 16)
 #define CORE_HC_SELECT_IN_EN   BIT(18)
 #define CORE_HC_SELECT_IN_HS400(6 << 19)
 #define CORE_HC_SELECT_IN_MASK (7 << 19)
 
 #define CORE_3_0V_SUPPORT  (1 << 25)
 #define CORE_1_8V_SUPPORT  (1 << 26)
+#define CORE_VOLT_SUPPORT  (CORE_3_0V_SUPPORT | CORE_1_8V_SUPPORT)
 
 #define CORE_CSR_CDC_CTLR_CFG0 0x130
 #define CORE_SW_TRIG_FULL_CALIBBIT(16)
@@ -1109,7 +1112,7 @@ static void sdhci_msm_handle_pwr_irq(struct sdhci_host 
*host, int irq)
u32 irq_status, irq_ack = 0;
int retry = 10;
u32 pwr_state = 0, io_level = 0;
-
+   u32 config;
 
irq_status = readl_relaxed(msm_host->core_mem + CORE_PWRCTL_STATUS);
irq_status &= INT_MASK;
@@ -1166,6 +1169,38 @@ static void sdhci_msm_handle_pwr_irq(struct sdhci_host 
*host, int irq)
 */
writel_relaxed(irq_ack, msm_host->core_mem + CORE_PWRCTL_CTL);
 
+   /*
+* If we don't have info regarding the voltage levels supported by
+* regulators, don't change the IO PAD PWR SWITCH.
+*/
+   if (msm_host->caps_0 & CORE_VOLT_SUPPORT) {
+   u32 new_config;
+   /*
+* We should unset IO PAD PWR switch only if the register write
+* can set IO lines high and the regulator also switches to 3 V.
+* Else, we should keep the IO PAD PWR switch set.
+* This is applicable to certain targets where eMMC vccq supply
+* is only 1.8V. In such targets, even during REQ_IO_HIGH, the
+* IO PAD PWR switch must be kept set to reflect actual
+* regulator voltage. This way, during initialization of
+* controllers with only 1.8V, we will set the IO PAD bit
+* without waiting for a REQ_IO_LOW.
+*/
+   config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+   new_config = config;
+
+   if ((io_level & REQ_IO_HIGH) &&
+   (msm_host->caps_0 & CORE_3_0V_SUPPORT))
+   new_config &= ~CORE_IO_PAD_PWR_SWITCH;
+   else if ((io_level & REQ_IO_LOW) ||
+   (msm_host->caps_0 & CORE_1_8V_SUPPORT))
+   new_config |= CORE_IO_PAD_PWR_SWITCH;
+
+   if (config ^ new_config)
+   writel_relaxed(new_config,
+   host->ioaddr + CORE_VENDOR_SPEC);
+   }
+
if (pwr_state)
msm_host->curr_pwr_state = pwr_state;
if (io_level)
@@ -1322,7 +1357,8 @@ static void sdhci_msm_set_regulator_caps(struct 
sdhci_msm_host *msm_host)
 {
struct mmc_host *mmc = msm_host->mmc;
struct regulator *supply = mmc->supply.vqmmc;
-   u32 caps = 0;
+   u32 caps = 0, config;
+   struct sdhci_host *host = mmc_priv(mmc);
 
if (!IS_ERR(mmc->supply.vqmmc)) {
if (regulator_is_supported_voltage(supply, 170, 195))
@@ -1335,6 +1371,23 @@ static void sdhci_msm_set_regulator_caps(struct 
sdhci_msm_host *msm_host)
mmc_hostname(mmc));
}
 
+   if (caps) {
+   /*
+* Set the PAD_PWR_SWITCH_EN bit so that the PAD_PWR_SWITCH
+* bit can be used as required later on.
+*/
+   u32 io_level = msm_host->curr_io_level;
+
+   config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+   config |= CORE_IO_PAD_PWR_SWITCH_EN;
+
+   if ((io_level & REQ_IO_HIGH) &&

[PATCH V5 2/2] mmc: sdhci-msm: support voltage pad switching

2018-04-20 Thread Vijay Viswanath
The PADs for SD card are dual-voltage that support 3v/1.8v. Those PADs
have a control signal  (io_pad_pwr_switch/mode18 ) that indicates
whether the PAD works in 3v or 1.8v.

SDHC core on msm platforms should have IO_PAD_PWR_SWITCH bit set/unset
based on actual voltage used for IO lines. So when power irq is
triggered for io high or io low, the driver should check the voltages
supported and set the pad accordingly.

Signed-off-by: Krishna Konda 
Signed-off-by: Venkat Gopalakrishnan 
Signed-off-by: Vijay Viswanath 
Reviewed-by: Douglas Anderson 
---
 drivers/mmc/host/sdhci-msm.c | 57 ++--
 1 file changed, 55 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index edd30a2..bb11916 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -78,12 +78,15 @@
 #define CORE_HC_MCLK_SEL_DFLT  (2 << 8)
 #define CORE_HC_MCLK_SEL_HS400 (3 << 8)
 #define CORE_HC_MCLK_SEL_MASK  (3 << 8)
+#define CORE_IO_PAD_PWR_SWITCH_EN  (1 << 15)
+#define CORE_IO_PAD_PWR_SWITCH  (1 << 16)
 #define CORE_HC_SELECT_IN_EN   BIT(18)
 #define CORE_HC_SELECT_IN_HS400(6 << 19)
 #define CORE_HC_SELECT_IN_MASK (7 << 19)
 
 #define CORE_3_0V_SUPPORT  (1 << 25)
 #define CORE_1_8V_SUPPORT  (1 << 26)
+#define CORE_VOLT_SUPPORT  (CORE_3_0V_SUPPORT | CORE_1_8V_SUPPORT)
 
 #define CORE_CSR_CDC_CTLR_CFG0 0x130
 #define CORE_SW_TRIG_FULL_CALIBBIT(16)
@@ -1109,7 +1112,7 @@ static void sdhci_msm_handle_pwr_irq(struct sdhci_host 
*host, int irq)
u32 irq_status, irq_ack = 0;
int retry = 10;
u32 pwr_state = 0, io_level = 0;
-
+   u32 config;
 
irq_status = readl_relaxed(msm_host->core_mem + CORE_PWRCTL_STATUS);
irq_status &= INT_MASK;
@@ -1166,6 +1169,38 @@ static void sdhci_msm_handle_pwr_irq(struct sdhci_host 
*host, int irq)
 */
writel_relaxed(irq_ack, msm_host->core_mem + CORE_PWRCTL_CTL);
 
+   /*
+* If we don't have info regarding the voltage levels supported by
+* regulators, don't change the IO PAD PWR SWITCH.
+*/
+   if (msm_host->caps_0 & CORE_VOLT_SUPPORT) {
+   u32 new_config;
+   /*
+* We should unset IO PAD PWR switch only if the register write
+* can set IO lines high and the regulator also switches to 3 V.
+* Else, we should keep the IO PAD PWR switch set.
+* This is applicable to certain targets where eMMC vccq supply
+* is only 1.8V. In such targets, even during REQ_IO_HIGH, the
+* IO PAD PWR switch must be kept set to reflect actual
+* regulator voltage. This way, during initialization of
+* controllers with only 1.8V, we will set the IO PAD bit
+* without waiting for a REQ_IO_LOW.
+*/
+   config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+   new_config = config;
+
+   if ((io_level & REQ_IO_HIGH) &&
+   (msm_host->caps_0 & CORE_3_0V_SUPPORT))
+   new_config &= ~CORE_IO_PAD_PWR_SWITCH;
+   else if ((io_level & REQ_IO_LOW) ||
+   (msm_host->caps_0 & CORE_1_8V_SUPPORT))
+   new_config |= CORE_IO_PAD_PWR_SWITCH;
+
+   if (config ^ new_config)
+   writel_relaxed(new_config,
+   host->ioaddr + CORE_VENDOR_SPEC);
+   }
+
if (pwr_state)
msm_host->curr_pwr_state = pwr_state;
if (io_level)
@@ -1322,7 +1357,8 @@ static void sdhci_msm_set_regulator_caps(struct 
sdhci_msm_host *msm_host)
 {
struct mmc_host *mmc = msm_host->mmc;
struct regulator *supply = mmc->supply.vqmmc;
-   u32 caps = 0;
+   u32 caps = 0, config;
+   struct sdhci_host *host = mmc_priv(mmc);
 
if (!IS_ERR(mmc->supply.vqmmc)) {
if (regulator_is_supported_voltage(supply, 170, 195))
@@ -1335,6 +1371,23 @@ static void sdhci_msm_set_regulator_caps(struct 
sdhci_msm_host *msm_host)
mmc_hostname(mmc));
}
 
+   if (caps) {
+   /*
+* Set the PAD_PWR_SWITCH_EN bit so that the PAD_PWR_SWITCH
+* bit can be used as required later on.
+*/
+   u32 io_level = msm_host->curr_io_level;
+
+   config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+   config |= CORE_IO_PAD_PWR_SWITCH_EN;
+
+   if ((io_level & REQ_IO_HIGH) && (caps & CORE_3_0V_SUPPORT))
+   config &= ~CORE_IO_PAD_PWR_SWITCH;
+   else if ((io_level & R

[PATCH V5 0/2] mmc: sdhci-msm: Configuring IO_PAD support for sdhci-msm

2018-04-20 Thread Vijay Viswanath
>From the HPG:
In some platform, SDCC controller can be connected to either an eMMC device or
an SD card. The PADs for SD card are dual-voltage that support 3v/1.8v. Those
PADs have a control signal  (io_pad_pwr_switch/mode18 ) that indicates whether
the PAD works in 3v or 1.8v.

For SD usage the default value of this signal is ???0???, and SD driver changes 
it
to ???1??? as a part of voltage switching sequence.
For eMMC usage, SW should configure this signal to ???1??? and supply 1.8v to 
PADs
before starting any activity on the eMMC BUS.

To set this signal, write the following in the
SDC1_SDCC_HC_VENDOR_SPECIFIC_FUNC register:
HC_IO_PAD_PWR_SWITCH: bit 16
HC_IO_PAD_PWR_SWITCH_EN: bit 15

Changes since v1:
Modified comments on io_pad related changes.
Split some read+modify+write commands to multiple lines

Changes since v2:
IO_PAD_PWR_SWITCH_EN will be set only if we have info regarding what
voltage is supported by the regulators.
Replaced regulator_list_voltage() API with
regulator_is_supported_voltage().

Changes since v3:
Removed unnecessary prints and extra lines.

Changes since v4:
Removed unnecessary mb() within sdhci_msm_handle_pwr_irq() since
wakeup calls have implicit write barriers.

Krishna Konda (1):
  mmc: sdhci-msm: support voltage pad switching

Vijay Viswanath (1):
  mmc: sdhci-msm: Add support to store supported vdd-io voltages

 drivers/mmc/host/sdhci-msm.c | 99 +++-
 1 file changed, 97 insertions(+), 2 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.



[PATCH V5 0/2] mmc: sdhci-msm: Configuring IO_PAD support for sdhci-msm

2018-04-20 Thread Vijay Viswanath
>From the HPG:
In some platform, SDCC controller can be connected to either an eMMC device or
an SD card. The PADs for SD card are dual-voltage that support 3v/1.8v. Those
PADs have a control signal  (io_pad_pwr_switch/mode18 ) that indicates whether
the PAD works in 3v or 1.8v.

For SD usage the default value of this signal is ???0???, and SD driver changes 
it
to ???1??? as a part of voltage switching sequence.
For eMMC usage, SW should configure this signal to ???1??? and supply 1.8v to 
PADs
before starting any activity on the eMMC BUS.

To set this signal, write the following in the
SDC1_SDCC_HC_VENDOR_SPECIFIC_FUNC register:
HC_IO_PAD_PWR_SWITCH: bit 16
HC_IO_PAD_PWR_SWITCH_EN: bit 15

Changes since v1:
Modified comments on io_pad related changes.
Split some read+modify+write commands to multiple lines

Changes since v2:
IO_PAD_PWR_SWITCH_EN will be set only if we have info regarding what
voltage is supported by the regulators.
Replaced regulator_list_voltage() API with
regulator_is_supported_voltage().

Changes since v3:
Removed unnecessary prints and extra lines.

Changes since v4:
Removed unnecessary mb() within sdhci_msm_handle_pwr_irq() since
wakeup calls have implicit write barriers.

Krishna Konda (1):
  mmc: sdhci-msm: support voltage pad switching

Vijay Viswanath (1):
  mmc: sdhci-msm: Add support to store supported vdd-io voltages

 drivers/mmc/host/sdhci-msm.c | 99 +++-
 1 file changed, 97 insertions(+), 2 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.



Re: [PATCH V4 2/2] mmc: sdhci-msm: support voltage pad switching

2018-04-18 Thread Vijay Viswanath



On 4/13/2018 10:38 PM, Doug Anderson wrote:

Hi,

On Fri, Apr 6, 2018 at 2:48 AM, Vijay Viswanath <vvisw...@codeaurora.org> wrote:



On 3/29/2018 4:23 AM, Doug Anderson wrote:


Hi,

On Wed, Mar 28, 2018 at 6:08 AM, Vijay Viswanath
<vvisw...@codeaurora.org> wrote:


From: Krishna Konda <kko...@codeaurora.org>

The PADs for SD card are dual-voltage that support 3v/1.8v. Those PADs
have a control signal  (io_pad_pwr_switch/mode18 ) that indicates
whether the PAD works in 3v or 1.8v.

SDHC core on msm platforms should have IO_PAD_PWR_SWITCH bit set/unset
based on actual voltage used for IO lines. So when power irq is
triggered for io high or io low, the driver should check the voltages
supported and set the pad accordingly.

Signed-off-by: Krishna Konda <kko...@codeaurora.org>
Signed-off-by: Venkat Gopalakrishnan <venk...@codeaurora.org>
Signed-off-by: Vijay Viswanath <vvisw...@codeaurora.org>
---
   drivers/mmc/host/sdhci-msm.c | 64
++--
   1 file changed, 62 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 2fcd9010..bbf9626 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -78,12 +78,15 @@
   #define CORE_HC_MCLK_SEL_DFLT  (2 << 8)
   #define CORE_HC_MCLK_SEL_HS400 (3 << 8)
   #define CORE_HC_MCLK_SEL_MASK  (3 << 8)
+#define CORE_IO_PAD_PWR_SWITCH_EN  (1 << 15)
+#define CORE_IO_PAD_PWR_SWITCH  (1 << 16)
   #define CORE_HC_SELECT_IN_EN   BIT(18)
   #define CORE_HC_SELECT_IN_HS400(6 << 19)
   #define CORE_HC_SELECT_IN_MASK (7 << 19)

   #define CORE_3_0V_SUPPORT  (1 << 25)
   #define CORE_1_8V_SUPPORT  (1 << 26)
+#define CORE_VOLT_SUPPORT  (CORE_3_0V_SUPPORT | CORE_1_8V_SUPPORT)

   #define CORE_CSR_CDC_CTLR_CFG0 0x130
   #define CORE_SW_TRIG_FULL_CALIBBIT(16)
@@ -1109,7 +1112,7 @@ static void sdhci_msm_handle_pwr_irq(struct
sdhci_host *host, int irq)
  u32 irq_status, irq_ack = 0;
  int retry = 10;
  u32 pwr_state = 0, io_level = 0;
-
+   u32 config;

  irq_status = readl_relaxed(msm_host->core_mem +
CORE_PWRCTL_STATUS);
  irq_status &= INT_MASK;
@@ -1166,6 +1169,45 @@ static void sdhci_msm_handle_pwr_irq(struct
sdhci_host *host, int irq)
   */
  writel_relaxed(irq_ack, msm_host->core_mem + CORE_PWRCTL_CTL);

+   /*
+* If we don't have info regarding the voltage levels supported
by
+* regulators, don't change the IO PAD PWR SWITCH.
+*/
+   if (msm_host->caps_0 & CORE_VOLT_SUPPORT) {
+   /* Ensure order between core_mem and hc_mem */
+   mb();



Like in v2, I don't understand why you need a mb() before the read
from CORE_VENDOR_SPEC.  No reads or writes to the core_mem will affect
the value you're reading here, so you need no barrier.

If you need a barrier before the _write_ to CORE_VENDOR_SPEC then add
it below.  Then in the case where the config doesn't change you have
no barriers.



+   /*
+* We should unset IO PAD PWR switch only if the register
write
+* can set IO lines high and the regulator also switches
to 3 V.
+* Else, we should keep the IO PAD PWR switch set.
+* This is applicable to certain targets where eMMC vccq
supply
+* is only 1.8V. In such targets, even during
REQ_IO_HIGH, the
+* IO PAD PWR switch must be kept set to reflect actual
+* regulator voltage. This way, during initialization of
+* controllers with only 1.8V, we will set the IO PAD bit
+* without waiting for a REQ_IO_LOW.
+*/



For the above comment, what about just:

new_config = config
if (msm_host->caps_0 == CORE_1_8V_SUPPORT) {
new_config |= CORE_IO_PAD_PWR_SWITCH;
} else if (msm_host->caps_0 == CORE_3_3V_SUPPORT) {
new_config &= ~CORE_IO_PAD_PWR_SWITCH;
} else if (msm_host->caps_0 & CORE_VOLT_SUPPORT) {
if (io_level & REQ_IO_HIGH)
  new_config &= ~CORE_IO_PAD_PWR_SWITCH;
else if (io_level & REQ_IO_LOW)
  new_config |= CORE_IO_PAD_PWR_SWITCH;
}



This looks a big mess of if/else. Does the above implementation have better
performance compared to having two if/else with bit operations inside ? The
latter looks much cleaner and faster.

If regulator only supports 3V and we get a io_low from BUS_OFF ( REQ_IO_LOW
should never come if we don't support 1.8V), it is ok to set io pad.


Yeah, I think it's ugly no matter what.  Personally I find the
if/then/else easier to follow than the complicated conditions split
across multiple lines.  I seem to remember there was something that my
version did differently than yours too (hence the "this might be more
important if you get rid of the initial setting"

Re: [PATCH V4 2/2] mmc: sdhci-msm: support voltage pad switching

2018-04-18 Thread Vijay Viswanath



On 4/13/2018 10:38 PM, Doug Anderson wrote:

Hi,

On Fri, Apr 6, 2018 at 2:48 AM, Vijay Viswanath  wrote:



On 3/29/2018 4:23 AM, Doug Anderson wrote:


Hi,

On Wed, Mar 28, 2018 at 6:08 AM, Vijay Viswanath
 wrote:


From: Krishna Konda 

The PADs for SD card are dual-voltage that support 3v/1.8v. Those PADs
have a control signal  (io_pad_pwr_switch/mode18 ) that indicates
whether the PAD works in 3v or 1.8v.

SDHC core on msm platforms should have IO_PAD_PWR_SWITCH bit set/unset
based on actual voltage used for IO lines. So when power irq is
triggered for io high or io low, the driver should check the voltages
supported and set the pad accordingly.

Signed-off-by: Krishna Konda 
Signed-off-by: Venkat Gopalakrishnan 
Signed-off-by: Vijay Viswanath 
---
   drivers/mmc/host/sdhci-msm.c | 64
++--
   1 file changed, 62 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 2fcd9010..bbf9626 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -78,12 +78,15 @@
   #define CORE_HC_MCLK_SEL_DFLT  (2 << 8)
   #define CORE_HC_MCLK_SEL_HS400 (3 << 8)
   #define CORE_HC_MCLK_SEL_MASK  (3 << 8)
+#define CORE_IO_PAD_PWR_SWITCH_EN  (1 << 15)
+#define CORE_IO_PAD_PWR_SWITCH  (1 << 16)
   #define CORE_HC_SELECT_IN_EN   BIT(18)
   #define CORE_HC_SELECT_IN_HS400(6 << 19)
   #define CORE_HC_SELECT_IN_MASK (7 << 19)

   #define CORE_3_0V_SUPPORT  (1 << 25)
   #define CORE_1_8V_SUPPORT  (1 << 26)
+#define CORE_VOLT_SUPPORT  (CORE_3_0V_SUPPORT | CORE_1_8V_SUPPORT)

   #define CORE_CSR_CDC_CTLR_CFG0 0x130
   #define CORE_SW_TRIG_FULL_CALIBBIT(16)
@@ -1109,7 +1112,7 @@ static void sdhci_msm_handle_pwr_irq(struct
sdhci_host *host, int irq)
  u32 irq_status, irq_ack = 0;
  int retry = 10;
  u32 pwr_state = 0, io_level = 0;
-
+   u32 config;

  irq_status = readl_relaxed(msm_host->core_mem +
CORE_PWRCTL_STATUS);
  irq_status &= INT_MASK;
@@ -1166,6 +1169,45 @@ static void sdhci_msm_handle_pwr_irq(struct
sdhci_host *host, int irq)
   */
  writel_relaxed(irq_ack, msm_host->core_mem + CORE_PWRCTL_CTL);

+   /*
+* If we don't have info regarding the voltage levels supported
by
+* regulators, don't change the IO PAD PWR SWITCH.
+*/
+   if (msm_host->caps_0 & CORE_VOLT_SUPPORT) {
+   /* Ensure order between core_mem and hc_mem */
+   mb();



Like in v2, I don't understand why you need a mb() before the read
from CORE_VENDOR_SPEC.  No reads or writes to the core_mem will affect
the value you're reading here, so you need no barrier.

If you need a barrier before the _write_ to CORE_VENDOR_SPEC then add
it below.  Then in the case where the config doesn't change you have
no barriers.



+   /*
+* We should unset IO PAD PWR switch only if the register
write
+* can set IO lines high and the regulator also switches
to 3 V.
+* Else, we should keep the IO PAD PWR switch set.
+* This is applicable to certain targets where eMMC vccq
supply
+* is only 1.8V. In such targets, even during
REQ_IO_HIGH, the
+* IO PAD PWR switch must be kept set to reflect actual
+* regulator voltage. This way, during initialization of
+* controllers with only 1.8V, we will set the IO PAD bit
+* without waiting for a REQ_IO_LOW.
+*/



For the above comment, what about just:

new_config = config
if (msm_host->caps_0 == CORE_1_8V_SUPPORT) {
new_config |= CORE_IO_PAD_PWR_SWITCH;
} else if (msm_host->caps_0 == CORE_3_3V_SUPPORT) {
new_config &= ~CORE_IO_PAD_PWR_SWITCH;
} else if (msm_host->caps_0 & CORE_VOLT_SUPPORT) {
if (io_level & REQ_IO_HIGH)
  new_config &= ~CORE_IO_PAD_PWR_SWITCH;
else if (io_level & REQ_IO_LOW)
  new_config |= CORE_IO_PAD_PWR_SWITCH;
}



This looks a big mess of if/else. Does the above implementation have better
performance compared to having two if/else with bit operations inside ? The
latter looks much cleaner and faster.

If regulator only supports 3V and we get a io_low from BUS_OFF ( REQ_IO_LOW
should never come if we don't support 1.8V), it is ok to set io pad.


Yeah, I think it's ugly no matter what.  Personally I find the
if/then/else easier to follow than the complicated conditions split
across multiple lines.  I seem to remember there was something that my
version did differently than yours too (hence the "this might be more
important if you get rid of the initial setting"), let's see if I can
figure it out again.

Mine says:
- if it has exactly 1.8 or 3.3 support: set that.
- else if it supports both: set whatever is requested
- else (it support neith

Re: [PATCH V4 2/2] mmc: sdhci-msm: support voltage pad switching

2018-04-06 Thread Vijay Viswanath



On 3/29/2018 4:23 AM, Doug Anderson wrote:

Hi,

On Wed, Mar 28, 2018 at 6:08 AM, Vijay Viswanath
<vvisw...@codeaurora.org> wrote:

From: Krishna Konda <kko...@codeaurora.org>

The PADs for SD card are dual-voltage that support 3v/1.8v. Those PADs
have a control signal  (io_pad_pwr_switch/mode18 ) that indicates
whether the PAD works in 3v or 1.8v.

SDHC core on msm platforms should have IO_PAD_PWR_SWITCH bit set/unset
based on actual voltage used for IO lines. So when power irq is
triggered for io high or io low, the driver should check the voltages
supported and set the pad accordingly.

Signed-off-by: Krishna Konda <kko...@codeaurora.org>
Signed-off-by: Venkat Gopalakrishnan <venk...@codeaurora.org>
Signed-off-by: Vijay Viswanath <vvisw...@codeaurora.org>
---
  drivers/mmc/host/sdhci-msm.c | 64 ++--
  1 file changed, 62 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 2fcd9010..bbf9626 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -78,12 +78,15 @@
  #define CORE_HC_MCLK_SEL_DFLT  (2 << 8)
  #define CORE_HC_MCLK_SEL_HS400 (3 << 8)
  #define CORE_HC_MCLK_SEL_MASK  (3 << 8)
+#define CORE_IO_PAD_PWR_SWITCH_EN  (1 << 15)
+#define CORE_IO_PAD_PWR_SWITCH  (1 << 16)
  #define CORE_HC_SELECT_IN_EN   BIT(18)
  #define CORE_HC_SELECT_IN_HS400(6 << 19)
  #define CORE_HC_SELECT_IN_MASK (7 << 19)

  #define CORE_3_0V_SUPPORT  (1 << 25)
  #define CORE_1_8V_SUPPORT  (1 << 26)
+#define CORE_VOLT_SUPPORT  (CORE_3_0V_SUPPORT | CORE_1_8V_SUPPORT)

  #define CORE_CSR_CDC_CTLR_CFG0 0x130
  #define CORE_SW_TRIG_FULL_CALIBBIT(16)
@@ -1109,7 +1112,7 @@ static void sdhci_msm_handle_pwr_irq(struct sdhci_host 
*host, int irq)
 u32 irq_status, irq_ack = 0;
 int retry = 10;
 u32 pwr_state = 0, io_level = 0;
-
+   u32 config;

 irq_status = readl_relaxed(msm_host->core_mem + CORE_PWRCTL_STATUS);
 irq_status &= INT_MASK;
@@ -1166,6 +1169,45 @@ static void sdhci_msm_handle_pwr_irq(struct sdhci_host 
*host, int irq)
  */
 writel_relaxed(irq_ack, msm_host->core_mem + CORE_PWRCTL_CTL);

+   /*
+* If we don't have info regarding the voltage levels supported by
+* regulators, don't change the IO PAD PWR SWITCH.
+*/
+   if (msm_host->caps_0 & CORE_VOLT_SUPPORT) {
+   /* Ensure order between core_mem and hc_mem */
+   mb();


Like in v2, I don't understand why you need a mb() before the read
from CORE_VENDOR_SPEC.  No reads or writes to the core_mem will affect
the value you're reading here, so you need no barrier.

If you need a barrier before the _write_ to CORE_VENDOR_SPEC then add
it below.  Then in the case where the config doesn't change you have
no barriers.



+   /*
+* We should unset IO PAD PWR switch only if the register write
+* can set IO lines high and the regulator also switches to 3 V.
+* Else, we should keep the IO PAD PWR switch set.
+* This is applicable to certain targets where eMMC vccq supply
+* is only 1.8V. In such targets, even during REQ_IO_HIGH, the
+* IO PAD PWR switch must be kept set to reflect actual
+* regulator voltage. This way, during initialization of
+* controllers with only 1.8V, we will set the IO PAD bit
+* without waiting for a REQ_IO_LOW.
+*/


For the above comment, what about just:

new_config = config
if (msm_host->caps_0 == CORE_1_8V_SUPPORT) {
   new_config |= CORE_IO_PAD_PWR_SWITCH;
} else if (msm_host->caps_0 == CORE_3_3V_SUPPORT) {
   new_config &= ~CORE_IO_PAD_PWR_SWITCH;
} else if (msm_host->caps_0 & CORE_VOLT_SUPPORT) {
   if (io_level & REQ_IO_HIGH)
 new_config &= ~CORE_IO_PAD_PWR_SWITCH;
   else if (io_level & REQ_IO_LOW)
 new_config |= CORE_IO_PAD_PWR_SWITCH;
}


This looks a big mess of if/else. Does the above implementation have 
better performance compared to having two if/else with bit operations 
inside ? The latter looks much cleaner and faster.


If regulator only supports 3V and we get a io_low from BUS_OFF ( 
REQ_IO_LOW should never come if we don't support 1.8V), it is ok to set 
io pad.



if (config != new_config) {
  ...
}

AKA: first check if it only supports one voltage and pick that one.
Else if it supports both you can use the request.  This might be more
important if you get rid of the initial setting in
sdhci_msm_set_regulator_caps() as I'm suggesting.



+   config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+
+   if (((io_level & REQ_IO_HIGH) && (msm_host->caps_0 &
+

Re: [PATCH V4 2/2] mmc: sdhci-msm: support voltage pad switching

2018-04-06 Thread Vijay Viswanath



On 3/29/2018 4:23 AM, Doug Anderson wrote:

Hi,

On Wed, Mar 28, 2018 at 6:08 AM, Vijay Viswanath
 wrote:

From: Krishna Konda 

The PADs for SD card are dual-voltage that support 3v/1.8v. Those PADs
have a control signal  (io_pad_pwr_switch/mode18 ) that indicates
whether the PAD works in 3v or 1.8v.

SDHC core on msm platforms should have IO_PAD_PWR_SWITCH bit set/unset
based on actual voltage used for IO lines. So when power irq is
triggered for io high or io low, the driver should check the voltages
supported and set the pad accordingly.

Signed-off-by: Krishna Konda 
Signed-off-by: Venkat Gopalakrishnan 
Signed-off-by: Vijay Viswanath 
---
  drivers/mmc/host/sdhci-msm.c | 64 ++--
  1 file changed, 62 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 2fcd9010..bbf9626 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -78,12 +78,15 @@
  #define CORE_HC_MCLK_SEL_DFLT  (2 << 8)
  #define CORE_HC_MCLK_SEL_HS400 (3 << 8)
  #define CORE_HC_MCLK_SEL_MASK  (3 << 8)
+#define CORE_IO_PAD_PWR_SWITCH_EN  (1 << 15)
+#define CORE_IO_PAD_PWR_SWITCH  (1 << 16)
  #define CORE_HC_SELECT_IN_EN   BIT(18)
  #define CORE_HC_SELECT_IN_HS400(6 << 19)
  #define CORE_HC_SELECT_IN_MASK (7 << 19)

  #define CORE_3_0V_SUPPORT  (1 << 25)
  #define CORE_1_8V_SUPPORT  (1 << 26)
+#define CORE_VOLT_SUPPORT  (CORE_3_0V_SUPPORT | CORE_1_8V_SUPPORT)

  #define CORE_CSR_CDC_CTLR_CFG0 0x130
  #define CORE_SW_TRIG_FULL_CALIBBIT(16)
@@ -1109,7 +1112,7 @@ static void sdhci_msm_handle_pwr_irq(struct sdhci_host 
*host, int irq)
 u32 irq_status, irq_ack = 0;
 int retry = 10;
 u32 pwr_state = 0, io_level = 0;
-
+   u32 config;

 irq_status = readl_relaxed(msm_host->core_mem + CORE_PWRCTL_STATUS);
 irq_status &= INT_MASK;
@@ -1166,6 +1169,45 @@ static void sdhci_msm_handle_pwr_irq(struct sdhci_host 
*host, int irq)
  */
 writel_relaxed(irq_ack, msm_host->core_mem + CORE_PWRCTL_CTL);

+   /*
+* If we don't have info regarding the voltage levels supported by
+* regulators, don't change the IO PAD PWR SWITCH.
+*/
+   if (msm_host->caps_0 & CORE_VOLT_SUPPORT) {
+   /* Ensure order between core_mem and hc_mem */
+   mb();


Like in v2, I don't understand why you need a mb() before the read
from CORE_VENDOR_SPEC.  No reads or writes to the core_mem will affect
the value you're reading here, so you need no barrier.

If you need a barrier before the _write_ to CORE_VENDOR_SPEC then add
it below.  Then in the case where the config doesn't change you have
no barriers.



+   /*
+* We should unset IO PAD PWR switch only if the register write
+* can set IO lines high and the regulator also switches to 3 V.
+* Else, we should keep the IO PAD PWR switch set.
+* This is applicable to certain targets where eMMC vccq supply
+* is only 1.8V. In such targets, even during REQ_IO_HIGH, the
+* IO PAD PWR switch must be kept set to reflect actual
+* regulator voltage. This way, during initialization of
+* controllers with only 1.8V, we will set the IO PAD bit
+* without waiting for a REQ_IO_LOW.
+*/


For the above comment, what about just:

new_config = config
if (msm_host->caps_0 == CORE_1_8V_SUPPORT) {
   new_config |= CORE_IO_PAD_PWR_SWITCH;
} else if (msm_host->caps_0 == CORE_3_3V_SUPPORT) {
   new_config &= ~CORE_IO_PAD_PWR_SWITCH;
} else if (msm_host->caps_0 & CORE_VOLT_SUPPORT) {
   if (io_level & REQ_IO_HIGH)
 new_config &= ~CORE_IO_PAD_PWR_SWITCH;
   else if (io_level & REQ_IO_LOW)
 new_config |= CORE_IO_PAD_PWR_SWITCH;
}


This looks a big mess of if/else. Does the above implementation have 
better performance compared to having two if/else with bit operations 
inside ? The latter looks much cleaner and faster.


If regulator only supports 3V and we get a io_low from BUS_OFF ( 
REQ_IO_LOW should never come if we don't support 1.8V), it is ok to set 
io pad.



if (config != new_config) {
  ...
}

AKA: first check if it only supports one voltage and pick that one.
Else if it supports both you can use the request.  This might be more
important if you get rid of the initial setting in
sdhci_msm_set_regulator_caps() as I'm suggesting.



+   config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+
+   if (((io_level & REQ_IO_HIGH) && (msm_host->caps_0 &
+   CORE_3_0V_SUPPORT)) &&
+   (config & CORE_IO_PAD_PWR_SWITCH)) {
+   config &= ~CORE

Re: [PATCH V4 1/2] mmc: sdhci-msm: Add support to store supported vdd-io voltages

2018-04-01 Thread Vijay Viswanath



On 3/29/2018 4:22 AM, Doug Anderson wrote:

Hi,

On Wed, Mar 28, 2018 at 6:08 AM, Vijay Viswanath
<vvisw...@codeaurora.org> wrote:

During probe check whether the vdd-io regulator of sdhc platform device
can support 1.8V and 3V and store this information as a capability of
platform device.

Signed-off-by: Vijay Viswanath <vvisw...@codeaurora.org>
---
  drivers/mmc/host/sdhci-msm.c | 35 ++-
  1 file changed, 34 insertions(+), 1 deletion(-)


Since I commented on v2, please copy me for this series going forward.  Thanks.




Will do. Sorry I missed.


diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index c283291..2fcd9010 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -21,6 +21,7 @@
  #include 
  #include 
  #include 
+#include 

  #include "sdhci-pltfm.h"

@@ -81,6 +82,9 @@
  #define CORE_HC_SELECT_IN_HS400(6 << 19)
  #define CORE_HC_SELECT_IN_MASK (7 << 19)

+#define CORE_3_0V_SUPPORT  (1 << 25)
+#define CORE_1_8V_SUPPORT  (1 << 26)
+
  #define CORE_CSR_CDC_CTLR_CFG0 0x130
  #define CORE_SW_TRIG_FULL_CALIBBIT(16)
  #define CORE_HW_AUTOCAL_ENABIT(17)
@@ -148,6 +152,7 @@ struct sdhci_msm_host {
 u32 curr_io_level;
 wait_queue_head_t pwr_irq_wait;
 bool pwr_irq_flag;
+   u32 caps_0;
  };

  static unsigned int msm_get_clock_rate_for_bus_mode(struct sdhci_host *host,
@@ -1103,7 +1108,7 @@ static void sdhci_msm_handle_pwr_irq(struct sdhci_host 
*host, int irq)
 struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
 u32 irq_status, irq_ack = 0;
 int retry = 10;
-   int pwr_state = 0, io_level = 0;
+   u32 pwr_state = 0, io_level = 0;


 irq_status = readl_relaxed(msm_host->core_mem + CORE_PWRCTL_STATUS);
@@ -1313,6 +1318,30 @@ static void sdhci_msm_writeb(struct sdhci_host *host, u8 
val, int reg)
 sdhci_msm_check_power_status(host, req_type);
  }

+static int sdhci_msm_set_regulator_caps(struct sdhci_msm_host *msm_host)


This function always returns 0.  Make it void.



+{
+   struct mmc_host *mmc = msm_host->mmc;
+   struct regulator *supply = mmc->supply.vqmmc;
+   u32 caps = 0;
+
+   if (!IS_ERR(mmc->supply.vqmmc)) {
+   if (regulator_is_supported_voltage(supply, 170, 195))
+   caps |= CORE_1_8V_SUPPORT;
+   if (regulator_is_supported_voltage(supply, 270, 360))
+   caps |= CORE_3_0V_SUPPORT;
+
+   if (!caps)
+   pr_warn("%s: %s: 1.8/3V not supported for vqmmc\n",
+   mmc_hostname(mmc), __func__);


Please remove __func__.  You already have the unique thing to find the
right driver (AKA mmc_hostname(mmc)) and the string itself should be
enough from there.



+   }
+
+   msm_host->caps_0 |= caps;
+   pr_debug("%s: %s: supported caps: 0x%08x\n", mmc_hostname(mmc),
+   __func__, caps);


Same, no need for __func__.




will remove all unnecessary __func__ references.


+
+   return 0;
+}
+
  static const struct of_device_id sdhci_msm_dt_match[] = {
 { .compatible = "qcom,sdhci-msm-v4" },
 {},
@@ -1530,6 +1559,10 @@ static int sdhci_msm_probe(struct platform_device *pdev)
 ret = sdhci_add_host(host);
 if (ret)
 goto pm_runtime_disable;
+   ret = sdhci_msm_set_regulator_caps(msm_host);
+   if (ret)
+   dev_err(>dev, "Failed to set regulator caps: %d\n",
+   ret);


If you find some reason _not_ to make sdhci_msm_set_regulator_caps()
return "void" as per above, you should actually do something about
this error.  You've used "dev_err" which makes me feel like you
consider this a serious error.  Presumably it should cause the probe
to fail?
>
-Doug



yeah, we don't need to print anything here as a warning is printed in 
sdhci_msm_set_regulator_caps() anyway.


Re: [PATCH V4 1/2] mmc: sdhci-msm: Add support to store supported vdd-io voltages

2018-04-01 Thread Vijay Viswanath



On 3/29/2018 4:22 AM, Doug Anderson wrote:

Hi,

On Wed, Mar 28, 2018 at 6:08 AM, Vijay Viswanath
 wrote:

During probe check whether the vdd-io regulator of sdhc platform device
can support 1.8V and 3V and store this information as a capability of
platform device.

Signed-off-by: Vijay Viswanath 
---
  drivers/mmc/host/sdhci-msm.c | 35 ++-
  1 file changed, 34 insertions(+), 1 deletion(-)


Since I commented on v2, please copy me for this series going forward.  Thanks.




Will do. Sorry I missed.


diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index c283291..2fcd9010 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -21,6 +21,7 @@
  #include 
  #include 
  #include 
+#include 

  #include "sdhci-pltfm.h"

@@ -81,6 +82,9 @@
  #define CORE_HC_SELECT_IN_HS400(6 << 19)
  #define CORE_HC_SELECT_IN_MASK (7 << 19)

+#define CORE_3_0V_SUPPORT  (1 << 25)
+#define CORE_1_8V_SUPPORT  (1 << 26)
+
  #define CORE_CSR_CDC_CTLR_CFG0 0x130
  #define CORE_SW_TRIG_FULL_CALIBBIT(16)
  #define CORE_HW_AUTOCAL_ENABIT(17)
@@ -148,6 +152,7 @@ struct sdhci_msm_host {
 u32 curr_io_level;
 wait_queue_head_t pwr_irq_wait;
 bool pwr_irq_flag;
+   u32 caps_0;
  };

  static unsigned int msm_get_clock_rate_for_bus_mode(struct sdhci_host *host,
@@ -1103,7 +1108,7 @@ static void sdhci_msm_handle_pwr_irq(struct sdhci_host 
*host, int irq)
 struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
 u32 irq_status, irq_ack = 0;
 int retry = 10;
-   int pwr_state = 0, io_level = 0;
+   u32 pwr_state = 0, io_level = 0;


 irq_status = readl_relaxed(msm_host->core_mem + CORE_PWRCTL_STATUS);
@@ -1313,6 +1318,30 @@ static void sdhci_msm_writeb(struct sdhci_host *host, u8 
val, int reg)
 sdhci_msm_check_power_status(host, req_type);
  }

+static int sdhci_msm_set_regulator_caps(struct sdhci_msm_host *msm_host)


This function always returns 0.  Make it void.



+{
+   struct mmc_host *mmc = msm_host->mmc;
+   struct regulator *supply = mmc->supply.vqmmc;
+   u32 caps = 0;
+
+   if (!IS_ERR(mmc->supply.vqmmc)) {
+   if (regulator_is_supported_voltage(supply, 170, 195))
+   caps |= CORE_1_8V_SUPPORT;
+   if (regulator_is_supported_voltage(supply, 270, 360))
+   caps |= CORE_3_0V_SUPPORT;
+
+   if (!caps)
+   pr_warn("%s: %s: 1.8/3V not supported for vqmmc\n",
+   mmc_hostname(mmc), __func__);


Please remove __func__.  You already have the unique thing to find the
right driver (AKA mmc_hostname(mmc)) and the string itself should be
enough from there.



+   }
+
+   msm_host->caps_0 |= caps;
+   pr_debug("%s: %s: supported caps: 0x%08x\n", mmc_hostname(mmc),
+   __func__, caps);


Same, no need for __func__.




will remove all unnecessary __func__ references.


+
+   return 0;
+}
+
  static const struct of_device_id sdhci_msm_dt_match[] = {
 { .compatible = "qcom,sdhci-msm-v4" },
 {},
@@ -1530,6 +1559,10 @@ static int sdhci_msm_probe(struct platform_device *pdev)
 ret = sdhci_add_host(host);
 if (ret)
 goto pm_runtime_disable;
+   ret = sdhci_msm_set_regulator_caps(msm_host);
+   if (ret)
+   dev_err(>dev, "Failed to set regulator caps: %d\n",
+   ret);


If you find some reason _not_ to make sdhci_msm_set_regulator_caps()
return "void" as per above, you should actually do something about
this error.  You've used "dev_err" which makes me feel like you
consider this a serious error.  Presumably it should cause the probe
to fail?
>
-Doug



yeah, we don't need to print anything here as a warning is printed in 
sdhci_msm_set_regulator_caps() anyway.


[PATCH V4 2/2] mmc: sdhci-msm: support voltage pad switching

2018-03-28 Thread Vijay Viswanath
From: Krishna Konda <kko...@codeaurora.org>

The PADs for SD card are dual-voltage that support 3v/1.8v. Those PADs
have a control signal  (io_pad_pwr_switch/mode18 ) that indicates
whether the PAD works in 3v or 1.8v.

SDHC core on msm platforms should have IO_PAD_PWR_SWITCH bit set/unset
based on actual voltage used for IO lines. So when power irq is
triggered for io high or io low, the driver should check the voltages
supported and set the pad accordingly.

Signed-off-by: Krishna Konda <kko...@codeaurora.org>
Signed-off-by: Venkat Gopalakrishnan <venk...@codeaurora.org>
Signed-off-by: Vijay Viswanath <vvisw...@codeaurora.org>
---
 drivers/mmc/host/sdhci-msm.c | 64 ++--
 1 file changed, 62 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 2fcd9010..bbf9626 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -78,12 +78,15 @@
 #define CORE_HC_MCLK_SEL_DFLT  (2 << 8)
 #define CORE_HC_MCLK_SEL_HS400 (3 << 8)
 #define CORE_HC_MCLK_SEL_MASK  (3 << 8)
+#define CORE_IO_PAD_PWR_SWITCH_EN  (1 << 15)
+#define CORE_IO_PAD_PWR_SWITCH  (1 << 16)
 #define CORE_HC_SELECT_IN_EN   BIT(18)
 #define CORE_HC_SELECT_IN_HS400(6 << 19)
 #define CORE_HC_SELECT_IN_MASK (7 << 19)
 
 #define CORE_3_0V_SUPPORT  (1 << 25)
 #define CORE_1_8V_SUPPORT  (1 << 26)
+#define CORE_VOLT_SUPPORT  (CORE_3_0V_SUPPORT | CORE_1_8V_SUPPORT)
 
 #define CORE_CSR_CDC_CTLR_CFG0 0x130
 #define CORE_SW_TRIG_FULL_CALIBBIT(16)
@@ -1109,7 +1112,7 @@ static void sdhci_msm_handle_pwr_irq(struct sdhci_host 
*host, int irq)
u32 irq_status, irq_ack = 0;
int retry = 10;
u32 pwr_state = 0, io_level = 0;
-
+   u32 config;
 
irq_status = readl_relaxed(msm_host->core_mem + CORE_PWRCTL_STATUS);
irq_status &= INT_MASK;
@@ -1166,6 +1169,45 @@ static void sdhci_msm_handle_pwr_irq(struct sdhci_host 
*host, int irq)
 */
writel_relaxed(irq_ack, msm_host->core_mem + CORE_PWRCTL_CTL);
 
+   /*
+* If we don't have info regarding the voltage levels supported by
+* regulators, don't change the IO PAD PWR SWITCH.
+*/
+   if (msm_host->caps_0 & CORE_VOLT_SUPPORT) {
+   /* Ensure order between core_mem and hc_mem */
+   mb();
+   /*
+* We should unset IO PAD PWR switch only if the register write
+* can set IO lines high and the regulator also switches to 3 V.
+* Else, we should keep the IO PAD PWR switch set.
+* This is applicable to certain targets where eMMC vccq supply
+* is only 1.8V. In such targets, even during REQ_IO_HIGH, the
+* IO PAD PWR switch must be kept set to reflect actual
+* regulator voltage. This way, during initialization of
+* controllers with only 1.8V, we will set the IO PAD bit
+* without waiting for a REQ_IO_LOW.
+*/
+   config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+
+   if (((io_level & REQ_IO_HIGH) && (msm_host->caps_0 &
+   CORE_3_0V_SUPPORT)) &&
+   (config & CORE_IO_PAD_PWR_SWITCH)) {
+   config &= ~CORE_IO_PAD_PWR_SWITCH;
+   writel_relaxed(config,
+   host->ioaddr + CORE_VENDOR_SPEC);
+   /* IO PAD register is in different memory space */
+   mb();
+   } else if (((io_level & REQ_IO_LOW) ||
+   (msm_host->caps_0 & CORE_1_8V_SUPPORT)) &&
+   !(config & CORE_IO_PAD_PWR_SWITCH)) {
+   config |= CORE_IO_PAD_PWR_SWITCH;
+   writel_relaxed(config,
+   host->ioaddr + CORE_VENDOR_SPEC);
+   /* IO PAD bit is in different memory space */
+   mb();
+   }
+   }
+
if (pwr_state)
msm_host->curr_pwr_state = pwr_state;
if (io_level)
@@ -1322,7 +1364,8 @@ static int sdhci_msm_set_regulator_caps(struct 
sdhci_msm_host *msm_host)
 {
struct mmc_host *mmc = msm_host->mmc;
struct regulator *supply = mmc->supply.vqmmc;
-   u32 caps = 0;
+   u32 caps = 0, config;
+   struct sdhci_host *host = mmc_priv(mmc);
 
if (!IS_ERR(mmc->supply.vqmmc)) {
if (regulator_is_supported_voltage(supply, 170, 195))
@@ -1335,6 +1378,23 @@ static int sdhci_msm_set_regulator_caps(struct 
sdhci_msm_host *msm_host)
mmc_hostname(mmc)

[PATCH V4 2/2] mmc: sdhci-msm: support voltage pad switching

2018-03-28 Thread Vijay Viswanath
From: Krishna Konda 

The PADs for SD card are dual-voltage that support 3v/1.8v. Those PADs
have a control signal  (io_pad_pwr_switch/mode18 ) that indicates
whether the PAD works in 3v or 1.8v.

SDHC core on msm platforms should have IO_PAD_PWR_SWITCH bit set/unset
based on actual voltage used for IO lines. So when power irq is
triggered for io high or io low, the driver should check the voltages
supported and set the pad accordingly.

Signed-off-by: Krishna Konda 
Signed-off-by: Venkat Gopalakrishnan 
Signed-off-by: Vijay Viswanath 
---
 drivers/mmc/host/sdhci-msm.c | 64 ++--
 1 file changed, 62 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 2fcd9010..bbf9626 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -78,12 +78,15 @@
 #define CORE_HC_MCLK_SEL_DFLT  (2 << 8)
 #define CORE_HC_MCLK_SEL_HS400 (3 << 8)
 #define CORE_HC_MCLK_SEL_MASK  (3 << 8)
+#define CORE_IO_PAD_PWR_SWITCH_EN  (1 << 15)
+#define CORE_IO_PAD_PWR_SWITCH  (1 << 16)
 #define CORE_HC_SELECT_IN_EN   BIT(18)
 #define CORE_HC_SELECT_IN_HS400(6 << 19)
 #define CORE_HC_SELECT_IN_MASK (7 << 19)
 
 #define CORE_3_0V_SUPPORT  (1 << 25)
 #define CORE_1_8V_SUPPORT  (1 << 26)
+#define CORE_VOLT_SUPPORT  (CORE_3_0V_SUPPORT | CORE_1_8V_SUPPORT)
 
 #define CORE_CSR_CDC_CTLR_CFG0 0x130
 #define CORE_SW_TRIG_FULL_CALIBBIT(16)
@@ -1109,7 +1112,7 @@ static void sdhci_msm_handle_pwr_irq(struct sdhci_host 
*host, int irq)
u32 irq_status, irq_ack = 0;
int retry = 10;
u32 pwr_state = 0, io_level = 0;
-
+   u32 config;
 
irq_status = readl_relaxed(msm_host->core_mem + CORE_PWRCTL_STATUS);
irq_status &= INT_MASK;
@@ -1166,6 +1169,45 @@ static void sdhci_msm_handle_pwr_irq(struct sdhci_host 
*host, int irq)
 */
writel_relaxed(irq_ack, msm_host->core_mem + CORE_PWRCTL_CTL);
 
+   /*
+* If we don't have info regarding the voltage levels supported by
+* regulators, don't change the IO PAD PWR SWITCH.
+*/
+   if (msm_host->caps_0 & CORE_VOLT_SUPPORT) {
+   /* Ensure order between core_mem and hc_mem */
+   mb();
+   /*
+* We should unset IO PAD PWR switch only if the register write
+* can set IO lines high and the regulator also switches to 3 V.
+* Else, we should keep the IO PAD PWR switch set.
+* This is applicable to certain targets where eMMC vccq supply
+* is only 1.8V. In such targets, even during REQ_IO_HIGH, the
+* IO PAD PWR switch must be kept set to reflect actual
+* regulator voltage. This way, during initialization of
+* controllers with only 1.8V, we will set the IO PAD bit
+* without waiting for a REQ_IO_LOW.
+*/
+   config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+
+   if (((io_level & REQ_IO_HIGH) && (msm_host->caps_0 &
+   CORE_3_0V_SUPPORT)) &&
+   (config & CORE_IO_PAD_PWR_SWITCH)) {
+   config &= ~CORE_IO_PAD_PWR_SWITCH;
+   writel_relaxed(config,
+   host->ioaddr + CORE_VENDOR_SPEC);
+   /* IO PAD register is in different memory space */
+   mb();
+   } else if (((io_level & REQ_IO_LOW) ||
+   (msm_host->caps_0 & CORE_1_8V_SUPPORT)) &&
+   !(config & CORE_IO_PAD_PWR_SWITCH)) {
+   config |= CORE_IO_PAD_PWR_SWITCH;
+   writel_relaxed(config,
+   host->ioaddr + CORE_VENDOR_SPEC);
+   /* IO PAD bit is in different memory space */
+   mb();
+   }
+   }
+
if (pwr_state)
msm_host->curr_pwr_state = pwr_state;
if (io_level)
@@ -1322,7 +1364,8 @@ static int sdhci_msm_set_regulator_caps(struct 
sdhci_msm_host *msm_host)
 {
struct mmc_host *mmc = msm_host->mmc;
struct regulator *supply = mmc->supply.vqmmc;
-   u32 caps = 0;
+   u32 caps = 0, config;
+   struct sdhci_host *host = mmc_priv(mmc);
 
if (!IS_ERR(mmc->supply.vqmmc)) {
if (regulator_is_supported_voltage(supply, 170, 195))
@@ -1335,6 +1378,23 @@ static int sdhci_msm_set_regulator_caps(struct 
sdhci_msm_host *msm_host)
mmc_hostname(mmc), __func__);
}
 
+   if (caps) {
+   /*
+* Set the PAD_PWR_SWITCH_EN bit so that 

[PATCH V4 1/2] mmc: sdhci-msm: Add support to store supported vdd-io voltages

2018-03-28 Thread Vijay Viswanath
During probe check whether the vdd-io regulator of sdhc platform device
can support 1.8V and 3V and store this information as a capability of
platform device.

Signed-off-by: Vijay Viswanath <vvisw...@codeaurora.org>
---
 drivers/mmc/host/sdhci-msm.c | 35 ++-
 1 file changed, 34 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index c283291..2fcd9010 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -21,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "sdhci-pltfm.h"
 
@@ -81,6 +82,9 @@
 #define CORE_HC_SELECT_IN_HS400(6 << 19)
 #define CORE_HC_SELECT_IN_MASK (7 << 19)
 
+#define CORE_3_0V_SUPPORT  (1 << 25)
+#define CORE_1_8V_SUPPORT  (1 << 26)
+
 #define CORE_CSR_CDC_CTLR_CFG0 0x130
 #define CORE_SW_TRIG_FULL_CALIBBIT(16)
 #define CORE_HW_AUTOCAL_ENABIT(17)
@@ -148,6 +152,7 @@ struct sdhci_msm_host {
u32 curr_io_level;
wait_queue_head_t pwr_irq_wait;
bool pwr_irq_flag;
+   u32 caps_0;
 };
 
 static unsigned int msm_get_clock_rate_for_bus_mode(struct sdhci_host *host,
@@ -1103,7 +1108,7 @@ static void sdhci_msm_handle_pwr_irq(struct sdhci_host 
*host, int irq)
struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
u32 irq_status, irq_ack = 0;
int retry = 10;
-   int pwr_state = 0, io_level = 0;
+   u32 pwr_state = 0, io_level = 0;
 
 
irq_status = readl_relaxed(msm_host->core_mem + CORE_PWRCTL_STATUS);
@@ -1313,6 +1318,30 @@ static void sdhci_msm_writeb(struct sdhci_host *host, u8 
val, int reg)
sdhci_msm_check_power_status(host, req_type);
 }
 
+static int sdhci_msm_set_regulator_caps(struct sdhci_msm_host *msm_host)
+{
+   struct mmc_host *mmc = msm_host->mmc;
+   struct regulator *supply = mmc->supply.vqmmc;
+   u32 caps = 0;
+
+   if (!IS_ERR(mmc->supply.vqmmc)) {
+   if (regulator_is_supported_voltage(supply, 170, 195))
+   caps |= CORE_1_8V_SUPPORT;
+   if (regulator_is_supported_voltage(supply, 270, 360))
+   caps |= CORE_3_0V_SUPPORT;
+
+   if (!caps)
+   pr_warn("%s: %s: 1.8/3V not supported for vqmmc\n",
+   mmc_hostname(mmc), __func__);
+   }
+
+   msm_host->caps_0 |= caps;
+   pr_debug("%s: %s: supported caps: 0x%08x\n", mmc_hostname(mmc),
+   __func__, caps);
+
+   return 0;
+}
+
 static const struct of_device_id sdhci_msm_dt_match[] = {
{ .compatible = "qcom,sdhci-msm-v4" },
{},
@@ -1530,6 +1559,10 @@ static int sdhci_msm_probe(struct platform_device *pdev)
ret = sdhci_add_host(host);
if (ret)
goto pm_runtime_disable;
+   ret = sdhci_msm_set_regulator_caps(msm_host);
+   if (ret)
+   dev_err(>dev, "Failed to set regulator caps: %d\n",
+   ret);
 
pm_runtime_mark_last_busy(>dev);
pm_runtime_put_autosuspend(>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.



[PATCH V4 1/2] mmc: sdhci-msm: Add support to store supported vdd-io voltages

2018-03-28 Thread Vijay Viswanath
During probe check whether the vdd-io regulator of sdhc platform device
can support 1.8V and 3V and store this information as a capability of
platform device.

Signed-off-by: Vijay Viswanath 
---
 drivers/mmc/host/sdhci-msm.c | 35 ++-
 1 file changed, 34 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index c283291..2fcd9010 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -21,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "sdhci-pltfm.h"
 
@@ -81,6 +82,9 @@
 #define CORE_HC_SELECT_IN_HS400(6 << 19)
 #define CORE_HC_SELECT_IN_MASK (7 << 19)
 
+#define CORE_3_0V_SUPPORT  (1 << 25)
+#define CORE_1_8V_SUPPORT  (1 << 26)
+
 #define CORE_CSR_CDC_CTLR_CFG0 0x130
 #define CORE_SW_TRIG_FULL_CALIBBIT(16)
 #define CORE_HW_AUTOCAL_ENABIT(17)
@@ -148,6 +152,7 @@ struct sdhci_msm_host {
u32 curr_io_level;
wait_queue_head_t pwr_irq_wait;
bool pwr_irq_flag;
+   u32 caps_0;
 };
 
 static unsigned int msm_get_clock_rate_for_bus_mode(struct sdhci_host *host,
@@ -1103,7 +1108,7 @@ static void sdhci_msm_handle_pwr_irq(struct sdhci_host 
*host, int irq)
struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
u32 irq_status, irq_ack = 0;
int retry = 10;
-   int pwr_state = 0, io_level = 0;
+   u32 pwr_state = 0, io_level = 0;
 
 
irq_status = readl_relaxed(msm_host->core_mem + CORE_PWRCTL_STATUS);
@@ -1313,6 +1318,30 @@ static void sdhci_msm_writeb(struct sdhci_host *host, u8 
val, int reg)
sdhci_msm_check_power_status(host, req_type);
 }
 
+static int sdhci_msm_set_regulator_caps(struct sdhci_msm_host *msm_host)
+{
+   struct mmc_host *mmc = msm_host->mmc;
+   struct regulator *supply = mmc->supply.vqmmc;
+   u32 caps = 0;
+
+   if (!IS_ERR(mmc->supply.vqmmc)) {
+   if (regulator_is_supported_voltage(supply, 170, 195))
+   caps |= CORE_1_8V_SUPPORT;
+   if (regulator_is_supported_voltage(supply, 270, 360))
+   caps |= CORE_3_0V_SUPPORT;
+
+   if (!caps)
+   pr_warn("%s: %s: 1.8/3V not supported for vqmmc\n",
+   mmc_hostname(mmc), __func__);
+   }
+
+   msm_host->caps_0 |= caps;
+   pr_debug("%s: %s: supported caps: 0x%08x\n", mmc_hostname(mmc),
+   __func__, caps);
+
+   return 0;
+}
+
 static const struct of_device_id sdhci_msm_dt_match[] = {
{ .compatible = "qcom,sdhci-msm-v4" },
{},
@@ -1530,6 +1559,10 @@ static int sdhci_msm_probe(struct platform_device *pdev)
ret = sdhci_add_host(host);
if (ret)
goto pm_runtime_disable;
+   ret = sdhci_msm_set_regulator_caps(msm_host);
+   if (ret)
+   dev_err(>dev, "Failed to set regulator caps: %d\n",
+   ret);
 
pm_runtime_mark_last_busy(>dev);
pm_runtime_put_autosuspend(>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.



[PATCH V4 0/2] mmc: sdhci-msm: Configuring IO_PAD support for sdhci-msm

2018-03-28 Thread Vijay Viswanath
>From the HPG:
In some platform, SDCC controller can be connected to either an eMMC device or
an SD card. The PADs for SD card are dual-voltage that support 3v/1.8v. Those
PADs have a control signal  (io_pad_pwr_switch/mode18 ) that indicates whether
the PAD works in 3v or 1.8v.

For SD usage the default value of this signal is ???0???, and SD driver changes 
it
to ???1??? as a part of voltage switching sequence.
For eMMC usage, SW should configure this signal to ???1??? and supply 1.8v to 
PADs
before starting any activity on the eMMC BUS.

To set this signal, write the following in the
SDC1_SDCC_HC_VENDOR_SPECIFIC_FUNC register:
HC_IO_PAD_PWR_SWITCH: bit 16
HC_IO_PAD_PWR_SWITCH_EN: bit 15

Changes since v1:
Modified comments on io_pad related changes.
Split some read+modify+write commands to multiple lines

Changes since v2:
IO_PAD_PWR_SWITCH_EN will be set only if we have info regarding what
voltage is supported by the regulators.
Replaced regulator_list_voltage() API with
regulator_is_supported_voltage().

Changes since v3:
Removed unnecessary prints and extra lines.

Krishna Konda (1):
  mmc: sdhci-msm: support voltage pad switching

Vijay Viswanath (1):
  mmc: sdhci-msm: Add support to store supported vdd-io voltages

 drivers/mmc/host/sdhci-msm.c | 99 +++-
 1 file changed, 97 insertions(+), 2 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.



[PATCH V4 0/2] mmc: sdhci-msm: Configuring IO_PAD support for sdhci-msm

2018-03-28 Thread Vijay Viswanath
>From the HPG:
In some platform, SDCC controller can be connected to either an eMMC device or
an SD card. The PADs for SD card are dual-voltage that support 3v/1.8v. Those
PADs have a control signal  (io_pad_pwr_switch/mode18 ) that indicates whether
the PAD works in 3v or 1.8v.

For SD usage the default value of this signal is ???0???, and SD driver changes 
it
to ???1??? as a part of voltage switching sequence.
For eMMC usage, SW should configure this signal to ???1??? and supply 1.8v to 
PADs
before starting any activity on the eMMC BUS.

To set this signal, write the following in the
SDC1_SDCC_HC_VENDOR_SPECIFIC_FUNC register:
HC_IO_PAD_PWR_SWITCH: bit 16
HC_IO_PAD_PWR_SWITCH_EN: bit 15

Changes since v1:
Modified comments on io_pad related changes.
Split some read+modify+write commands to multiple lines

Changes since v2:
IO_PAD_PWR_SWITCH_EN will be set only if we have info regarding what
voltage is supported by the regulators.
Replaced regulator_list_voltage() API with
regulator_is_supported_voltage().

Changes since v3:
Removed unnecessary prints and extra lines.

Krishna Konda (1):
  mmc: sdhci-msm: support voltage pad switching

Vijay Viswanath (1):
  mmc: sdhci-msm: Add support to store supported vdd-io voltages

 drivers/mmc/host/sdhci-msm.c | 99 +++-
 1 file changed, 97 insertions(+), 2 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.



[PATCH V3 0/2] mmc: sdhci-msm: Configuring IO_PAD support for sdhci-msm

2018-03-28 Thread Vijay Viswanath
>From the HPG:
In some platform, SDCC controller can be connected to either an eMMC device or
an SD card. The PADs for SD card are dual-voltage that support 3v/1.8v. Those
PADs have a control signal  (io_pad_pwr_switch/mode18 ) that indicates whether
the PAD works in 3v or 1.8v.

For SD usage the default value of this signal is ???0???, and SD driver changes 
it
to ???1??? as a part of voltage switching sequence.
For eMMC usage, SW should configure this signal to ???1??? and supply 1.8v to 
PADs
before starting any activity on the eMMC BUS.

To set this signal, write the following in the
SDC1_SDCC_HC_VENDOR_SPECIFIC_FUNC register:
HC_IO_PAD_PWR_SWITCH: bit 16
HC_IO_PAD_PWR_SWITCH_EN: bit 15

Changes since v1:
Modified comments on io_pad related changes.
Split some read+modify+write commands to multiple lines

Changes since v2:
IO_PAD_PWR_SWITCH_EN will be set only if we have info regarding what
voltage is suported by the regulators.
Replaced regulator_list_voltage() API with
regulator_is_supported_voltage().


Krishna Konda (1):
  mmc: sdhci-msm: support voltage pad switching

Vijay Viswanath (1):
  mmc: sdhci-msm: Add support to store supported vdd-io voltages

 drivers/mmc/host/sdhci-msm.c | 99 +++-
 1 file changed, 97 insertions(+), 2 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.



[PATCH V3 2/2] mmc: sdhci-msm: support voltage pad switching

2018-03-28 Thread Vijay Viswanath
From: Krishna Konda <kko...@codeaurora.org>

The PADs for SD card are dual-voltage that support 3v/1.8v. Those PADs
have a control signal  (io_pad_pwr_switch/mode18 ) that indicates
whether the PAD works in 3v or 1.8v.

SDHC core on msm platforms should have IO_PAD_PWR_SWITCH bit set/unset
based on actual voltage used for IO lines. So when power irq is
triggered for io high or io low, the driver should check the voltages
supported and set the pad accordingly.

Signed-off-by: Krishna Konda <kko...@codeaurora.org>
Signed-off-by: Venkat Gopalakrishnan <venk...@codeaurora.org>
Signed-off-by: Vijay Viswanath <vvisw...@codeaurora.org>
---
 drivers/mmc/host/sdhci-msm.c | 65 ++--
 1 file changed, 63 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index a822f10..2ffb7bb 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -78,12 +78,15 @@
 #define CORE_HC_MCLK_SEL_DFLT  (2 << 8)
 #define CORE_HC_MCLK_SEL_HS400 (3 << 8)
 #define CORE_HC_MCLK_SEL_MASK  (3 << 8)
+#define CORE_IO_PAD_PWR_SWITCH_EN  (1 << 15)
+#define CORE_IO_PAD_PWR_SWITCH  (1 << 16)
 #define CORE_HC_SELECT_IN_EN   BIT(18)
 #define CORE_HC_SELECT_IN_HS400(6 << 19)
 #define CORE_HC_SELECT_IN_MASK (7 << 19)
 
 #define CORE_3_0V_SUPPORT  (1 << 25)
 #define CORE_1_8V_SUPPORT  (1 << 26)
+#define CORE_VOLT_SUPPORT  (CORE_3_0V_SUPPORT | CORE_1_8V_SUPPORT)
 
 #define CORE_CSR_CDC_CTLR_CFG0 0x130
 #define CORE_SW_TRIG_FULL_CALIBBIT(16)
@@ -1109,7 +1112,7 @@ static void sdhci_msm_handle_pwr_irq(struct sdhci_host 
*host, int irq)
u32 irq_status, irq_ack = 0;
int retry = 10;
u32 pwr_state = 0, io_level = 0;
-
+   u32 config;
 
irq_status = readl_relaxed(msm_host->core_mem + CORE_PWRCTL_STATUS);
irq_status &= INT_MASK;
@@ -1166,11 +1169,51 @@ static void sdhci_msm_handle_pwr_irq(struct sdhci_host 
*host, int irq)
 */
writel_relaxed(irq_ack, msm_host->core_mem + CORE_PWRCTL_CTL);
 
+   /*
+* If we don't have info regarding the voltage levels supported by
+* regulators, don't change the IO PAD PWR SWITCH.
+*/
+   if (msm_host->caps_0 & CORE_VOLT_SUPPORT) {
+   /* Ensure order between core_mem and hc_mem */
+   mb();
+   /*
+* We should unset IO PAD PWR switch only if the register write
+* can set IO lines high and the regulator also switches to 3 V.
+* Else, we should keep the IO PAD PWR switch set.
+* This is applicable to certain targets where eMMC vccq supply
+* is only 1.8V. In such targets, even during REQ_IO_HIGH, the
+* IO PAD PWR switch must be kept set to reflect actual
+* regulator voltage. This way, during initialization of
+* controllers with only 1.8V, we will set the IO PAD bit
+* without waiting for a REQ_IO_LOW.
+*/
+   config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+
+   if (((io_level & REQ_IO_HIGH) && (msm_host->caps_0 &
+   CORE_3_0V_SUPPORT)) &&
+   (config & CORE_IO_PAD_PWR_SWITCH)) {
+   config &= ~CORE_IO_PAD_PWR_SWITCH;
+   writel_relaxed(config,
+   host->ioaddr + CORE_VENDOR_SPEC);
+   /* IO PAD register is in different memory space */
+   mb();
+   } else if (((io_level & REQ_IO_LOW) ||
+   (msm_host->caps_0 & CORE_1_8V_SUPPORT)) &&
+   !(config & CORE_IO_PAD_PWR_SWITCH)) {
+   config |= CORE_IO_PAD_PWR_SWITCH;
+   writel_relaxed(config,
+   host->ioaddr + CORE_VENDOR_SPEC);
+   /* IO PAD bit is in different memory space */
+   mb();
+   }
+   }
+
if (pwr_state)
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);
@@ -1322,7 +1365,8 @@ static int sdhci_msm_set_regulator_caps(struct 
sdhci_msm_host *msm_host)
 {
struct mmc_host *mmc = msm_host->mmc;
struct regulator *supply = mmc->supply.vqmmc;
-   u32 caps = 0;
+   u32 caps = 0, config;
+   struct sdhci_host *host = mmc_priv(mmc);
 
if (!IS_ERR(mmc->

  1   2   >