mmc: sdhci-msm: add SDR104 CRC workaround enablement control

On Certain chipsets, SDR104 mode might be unstable causing CRC error on
the interface. So we need a workaround which would skip printing register
dumps on CRC errors and also downgrade bus speed mode to SDR50/DDR50 in
case of continuous CRC errors. This patch adds "qcom,sdr104-wa" property
to enable this workaround if required.

Change-Id: I626d8ef45a97e8e6558e7f20be496de1f5a2a438
Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
[xiaonian@codeaurora.org: fixed trivial merge conflicts]
Signed-off-by: Xiaonian Wang <xiaonian@codeaurora.org>
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
index 95e6f6c..da9a632 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
@@ -72,6 +72,11 @@
 						during clock scaling. If this property is not
 						defined, then it falls back to the default HS
 						bus speed mode to maintain backward compatibility.
+	- qcom,sdr104-wa: On Certain chipsets, SDR104 mode might be unstable causing CRC errors
+			  on the interface. So there is a workaround implemented to skip printing
+			  register dumps on CRC errors and also downgrade bus speed mode to
+			  SDR50/DDR50 in case of continuous CRC errors. Set this flag to enable
+			  this workaround.
 
 In the following, <supply> can be vdd (flash core voltage) or vdd-io (I/O voltage).
 	- qcom,<supply>-always-on - specifies whether supply should be kept "on" always.
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 9650085..fe62b69 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -1939,6 +1939,8 @@
 	if (of_get_property(np, "qcom,core_3_0v_support", NULL))
 		pdata->core_3_0v_support = true;
 
+	pdata->sdr104_wa = of_property_read_bool(np, "qcom,sdr104-wa");
+
 	return pdata;
 out:
 	return NULL;
@@ -4422,6 +4424,8 @@
 	if (msm_host->pdata->nonhotplug)
 		msm_host->mmc->caps2 |= MMC_CAP2_NONHOTPLUG;
 
+	msm_host->mmc->sdr104_wa = msm_host->pdata->sdr104_wa;
+
 	init_completion(&msm_host->pwr_irq_completion);
 
 	if (gpio_is_valid(msm_host->pdata->status_gpio)) {
diff --git a/drivers/mmc/host/sdhci-msm.h b/drivers/mmc/host/sdhci-msm.h
index 533b241..53b1953 100644
--- a/drivers/mmc/host/sdhci-msm.h
+++ b/drivers/mmc/host/sdhci-msm.h
@@ -151,6 +151,7 @@
 	unsigned char sup_ice_clk_cnt;
 	struct sdhci_msm_pm_qos_data pm_qos_data;
 	bool core_3_0v_support;
+	bool sdr104_wa;
 };
 
 struct sdhci_msm_bus_vote {
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index ba1e826..48f3879 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -587,6 +587,8 @@
 	struct io_latency_state io_lat_s;
 #endif
 
+	bool sdr104_wa;
+
 	/*
 	 * Set to 1 to just stop the SDCLK to the card without
 	 * actually disabling the clock from it's source.