ehci: msm-hsic: Add support to disable transaction error counter

CERR is 2bit down error counter that keeps track of number of consecutive
errors detected on single usb transaction. When set to non zero value, hw
decrements the count and updates qTD when transaction fails. If counter
reaches zero, hw marks the qTD inactive and triggers the interrupt. When
CERR is programmed to zero, hw ignores transaction failures. EHCI stack
programs the CERR  to 3 by default. Some peripherals might not work
correctly when CERR is set to 3. Add support to disable CERR in such
platforms.

Change-Id: I750fbe13d70e5f7359c4e1ee1fb649ebe9ec9946
Signed-off-by: Vamsi Krishna <vskrishn@codeaurora.org>
diff --git a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
index 70bf993..e724c62 100644
--- a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
@@ -65,6 +65,14 @@
   5 (2^5 = 32)   32 micro frame interrupt threshold aka 4ms interrupt threshold
   6 (2^6 = 64)   64 micro frame interrupt threshold aka 8ms interrupt threshold
 
+- hsic,disable-cerr: CERR is 2bit down error counter that keeps track of number
+  of consecutive errors detected on single usb transaction. When set to non
+  zero value, hw decrements the count and updates qTD when transaction fails.
+  If counter reaches zero, hw marks the qTD inactive and triggers the interrupt.
+  When CERR is programmed to zero, hw ignores transaction failures. ECHI stack
+  programs the CERR  to 3 by default. When this flag is true, CERR is set to
+  zero and transaction errors are ignored.
+
 - Refer to "Documentation/devicetree/bindings/arm/msm/msm_bus.txt" for
   below optional properties:
     - qcom,msm_bus,name
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 14c3323..ef45d49 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -1895,6 +1895,8 @@
 				"hsic,consider-ipa-handshake"));
 	pdata->ahb_async_bridge_bypass = of_property_read_bool(node,
 				"qcom,ahb-async-bridge-bypass");
+	pdata->disable_cerr = of_property_read_bool(node,
+				"hsic,disable-cerr");
 
 	return pdata;
 }
@@ -1982,8 +1984,10 @@
 	mehci->ehci.pool_64_bit_align = pdata->pool_64_bit_align;
 	mehci->enable_hbm = pdata->enable_hbm;
 
-	if (pdata)
+	if (pdata) {
 		mehci->ehci.log2_irq_thresh = pdata->log2_irq_thresh;
+		mehci->ehci.disable_cerr = pdata->disable_cerr;
+	}
 
 	ret = msm_hsic_init_gdsc(mehci, 1);
 	if (ret) {
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index db49c07..b029be2 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -637,7 +637,8 @@
 	qtd->urb = urb;
 
 	token = QTD_STS_ACTIVE;
-	token |= (EHCI_TUNE_CERR << 10);
+	if (!ehci->disable_cerr)
+		token |= (EHCI_TUNE_CERR << 10);
 	/* for split transactions, SplitXState initialized to zero */
 
 	len = urb->transfer_buffer_length;
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index edf2a73..0498a6a 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -154,6 +154,7 @@
 	unsigned		susp_sof_bug:1; /*Chip Idea HC*/
 	unsigned		resume_sof_bug:1;/*Chip Idea HC*/
 	unsigned		reset_sof_bug:1; /*Chip Idea HC*/
+	bool			disable_cerr;
 
 	/* required for usb32 quirk */
 	#define OHCI_CTRL_HCFS          (3 << 6)
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 04b99b7..7bb0ffd 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -440,6 +440,7 @@
 	bool disable_park_mode;
 	bool consider_ipa_handshake;
 	bool ahb_async_bridge_bypass;
+	bool disable_cerr;
 };
 
 struct msm_usb_host_platform_data {