Merge "msm: ipa: Fix the format string vulnerability."
diff --git a/Documentation/devicetree/bindings/arm/msm/clock-krait-8974.txt b/Documentation/devicetree/bindings/arm/msm/clock-krait-8974.txt
index ee9a286..d9ccb09 100644
--- a/Documentation/devicetree/bindings/arm/msm/clock-krait-8974.txt
+++ b/Documentation/devicetree/bindings/arm/msm/clock-krait-8974.txt
@@ -41,6 +41,8 @@
 - qcom,hfpll-user-vco-mask:
 			The mask to be used when programming the VCO selection
 			bits in the user control register.
+- qcom,pvs-config-ver:
+			The version of the data in qcom,speedX-pvsY-bin-vZ.
 
 Example:
 	qcom,clock-krait@f9016000 {
diff --git a/Documentation/devicetree/bindings/fb/mdss-mdp.txt b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
index 9530c62..191db07 100644
--- a/Documentation/devicetree/bindings/fb/mdss-mdp.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
@@ -23,6 +23,10 @@
 				previous property, the amount of fetch ids
 				defined should match the number of offsets
 				defined in property: qcom,mdss-pipe-vig-off
+- qcom,mdss-pipe-vig-xin-id:	Array of VBIF clients ids (xins) corresponding
+				to the respective VIG pipes. Number of xin ids
+				defined should match the number of offsets
+				defined in property: qcom,mdss-pipe-vig-off
 - qcom,mdss-pipe-rgb-off:	Array of offsets for MDP source surface pipes of
 				type RGB, the offsets are calculated from
 				register "mdp_phys" defined in reg property.
@@ -34,6 +38,10 @@
 				previous property, the amount of fetch ids
 				defined should match the number of offsets
 				defined in property: qcom,mdss-pipe-rgb-off
+- qcom,mdss-pipe-rgb-xin-id:	Array of VBIF clients ids (xins) corresponding
+				to the respective RGB pipes. Number of xin ids
+				defined should match the number of offsets
+				defined in property: qcom,mdss-pipe-rgb-off
 - qcom,mdss-pipe-dma-off:	Array of offsets for MDP source surface pipes of
 				type DMA, the offsets are calculated from
 				register "mdp_phys" defined in reg property.
@@ -45,6 +53,10 @@
 				previous property, the amount of fetch ids
 				defined should match the number of offsets
 				defined in property: qcom,mdss-pipe-dma-off
+- qcom,mdss-pipe-dma-xin-id:	Array of VBIF clients ids (xins) corresponding
+				to the respective DMA pipes. Number of xin ids
+				defined should match the number of offsets
+				defined in property: qcom,mdss-pipe-dma-off
 - qcom,mdss-smp-data:		Array of shared memory pool data. There should
 				be only two values in this property. The first
 				value corresponds to the number of smp blocks
@@ -218,6 +230,11 @@
 						<2 2 3>,
 						<2 4 5>,
 						<2 6 7>;
+
+		qcom,mdss-pipe-vig-xin-id = <0 4 8>;
+		qcom,mdss-pipe-rgb-xin-id = <1 5 9>;
+		qcom,mdss-pipe-dma-xin-id = <2 10>;
+
 		qcom,mdss-smp-data = <22 4096>;
 		qcom,mdss-rot-block-size = <64>;
 		qcom,mdss-smp-mb-per-pipe = <2>;
diff --git a/Documentation/usb/uicc.txt b/Documentation/usb/uicc.txt
new file mode 100644
index 0000000..7bf4d86
--- /dev/null
+++ b/Documentation/usb/uicc.txt
@@ -0,0 +1,161 @@
+Introduction
+============
+
+This feature requires supporting Mass Storage and Integrated Circuit Card
+interfaces exposed by the UICC (Universal Integrated Circuit Card) device.
+The MSM acts as a USB host and UICC acts as a peripheral. The UICC device
+that is used here is also referred to as Mega-SIM. This feature will be
+supported on MSM8x26.
+
+Hardware description
+====================
+
+The USB3503 HSIC (High Speed Inter Chip) hub's down stream port is modified
+to support Inter-Chip USB for connecting the UICC device. The USB3503 is
+connected to MSM via HSIC interface. The UICC device operates in Full Speed
+mode.
+
+The UICC device will support CCID (Integrated Circuit Card interface Device)
+specification. This interface supports 1 Bulk In, 1 Bulk Out and 1 Interrupt
+endpoint. The Interrupt endpoint is used by the device to send asynchronous
+notifications like card insertion/removal and hardware error events.
+The Bulk endpoints are used for the data communication.
+
+The UICC device will support the Mass Storage Bulk Only 1.0 specification.
+It supports SCSI Transparent subclass '06', corresponding to support of the
+SCSI Primary Command set. It implements SCSI Peripheral Device Type '00'
+(TYPE_DISK) corresponding to a direct access SCSI block device.
+
+Software description
+====================
+
+The MSM HSIC controller driver(drivers/usb/host/ehci-msm-hsic.c)  takes care
+of HSIC PHY and link management. The USB3503 HSIC hub is managed by the SMSC
+hub driver(drivers/misc/smsc_hubc.c). Both these drivers are well tested on
+APQ8074 dragon board and are re-used to support this feature.
+
+The mass storage interface is managed by the standard Linux USB storage driver.
+This driver interfaces with SCSI and block layers to export the disk to
+user space.
+
+A new USB driver is implemented to manage the CCID interface. This driver is
+referred to as USB CCID driver in this document. This driver is implemented
+as a pass-through module and provides the character device interface to
+user space. The CCID specification is implemented in the user space.
+
+The CCID command and responses are exchanged over the Bulk endpoints. The
+user space application uses write() and read() calls to send commands and
+receive responses.
+
+The CCID class specific requests are sent over the control endpoint. As
+control requests have a specific format, ioctls are implemented.
+
+The UICC device sends asynchronous notifications over the interrupt endpoint.
+The card insertion/removal and hardware error events are sent to user space
+via an ioctl().
+
+Design Goals:
+============
+
+1. Re-use the existing services available in user space. This is achieved
+by implementing the kernel USB CCID driver as a pass-through module.
+
+2. Support runtime card insertion/removal.
+
+3. Support runtime power management.
+
+4. Support Multiple card configuration. More than 1 IC can be connected to
+the USB UICC device.
+
+Power Management
+================
+
+The USB core uses the runtime PM framework to auto suspend the USB devices that
+are not in use. The Auto-suspend is forbidden for all devices except hub class
+devices. The USB CCID driver enables auto-suspend for the UICC device.
+
+An USB device can be suspended only when all of its interfaces are suspended.
+The USB storage interface device acts as a parent device to the underlying
+SCSI host, target and block devices. Runtime PM must be enabled for the
+SCSI device to allow USB storage interface suspend. The SCSI device runtime
+suspend and auto-suspend timeout will be configured from user space via sysfs
+files.
+
+The HSIC platform device and USB3503 HUB device will be runtime suspended
+only after the USB UICC device is suspended.
+
+SMP/multi-core
+==============
+
+The USB CCID driver does not allow multiple clients to open the device file
+concurrently. -EBUSY will be returned if open() is attempted when the
+file is already opened.
+
+The write() and read() methods are implemented synchronously. If another
+write() is called when a previous write() is in progress, -EBUSY is
+returned. The same is applicable to read().
+
+Mutexes will be used to prevent concurrent open(), read() and write() access.
+
+Interface
+=========
+
+A character device file (/dev/ccid_bridge) will be exposed by the USB CCID
+driver. open(), read(), write(), ioctl() and close() methods are implemented.
+This device node is accessible only to the root by default.  User space init
+or udev scripts should change the permissions of this device file if it needs
+to be accessed by non-root applications.
+
+open(): The open() is blocked until the UICC device is detected and the CCID
+interface probe is completed. Returns the appropriate error code in case of
+failure.
+
+read(): An URB is submitted on the Bulk In endpoint. The read() is blocked
+until the URB is completed and the data is copied to the user space buffer
+upon success. An appropriate error code is returned in case of failure.
+-ENODEV must be treated as a serious error and no further I/O will be
+attempted.
+
+write(): An URB is submitted on the Bulk Out endpoint. The write() is blocked
+until the URB is completed. An appropriate error code is returned in case of
+failure. -ENODEV must be treated as a serious error and no further I/O will be
+attempted.
+
+ioctl(): The ioctl() method is required for facilitating Control transfers and
+Interrupt transfers.
+
+USB_CCID_GET_CLASS_DESC: This read-only ioctl returns the smart card class
+descriptor as described in the 5.1 section of USB smart card class spec.
+
+USB_CCID_ABORT: This write-only ioctl sends A ABORT class specific request on
+control endpoint. The class request details are mentioned in section 5.3.1.
+
+USB_CCID_GET_CLOCK_FREQUENCIES: This read and write ioctl returns the clock
+frequencies supported by the CCID device. A GET_CLOCK_FREQUENCIES class request
+is sent on the control endpoint. The class request details are mentioned in
+section 5.3.2.
+
+USB_CCID_GET_DATA_RATES: This read and write ioctl returns the data rates
+supported by the CCID device. A GET_DATA_RATES class request is sent on the
+control endpoint. The class request details are mentioned in section 5.3.3.
+
+USB_CCID_GET_EVENT: This read-only ioctl returns the asynchronous event sent
+by the UICC device. The ioctl() is blocked until such event is received from
+the UICC device. This ioctl() returns -ENOENT error code when the device
+does not have an interrupt endpoint and does not support remote wakeup
+capability.
+
+close(): Cancels any ongoing I/O before it returns.
+
+Config options
+==============
+
+Turn on USB_EHCI_MSM_HSIC, USB_HSIC_SMSC_HUB and USB_CCID_BRIDGE configs to
+enable this feature.
+
+References
+==========
+
+Specification for Integrated Circuit(s) Cards Interface Devices
+
+Smart Cards; UICC-Terminal interface; Physical and logical characteristics
diff --git a/arch/arm/boot/dts/apq8084-mdss.dtsi b/arch/arm/boot/dts/apq8084-mdss.dtsi
index 15d5018..0e771ce 100644
--- a/arch/arm/boot/dts/apq8084-mdss.dtsi
+++ b/arch/arm/boot/dts/apq8084-mdss.dtsi
@@ -36,6 +36,10 @@
 		qcom,mdss-pipe-rgb-fetch-id = <16 17 18 22>;
 		qcom,mdss-pipe-dma-fetch-id = <10 13>;
 
+		qcom,mdss-pipe-vig-xin-id = <0 4 8 12>;
+		qcom,mdss-pipe-rgb-xin-id = <1 5 9 13>;
+		qcom,mdss-pipe-dma-xin-id = <2 10>;
+
 		qcom,mdss-smp-data = <44 8192>;
 
 		qcom,mdss-ctl-off = <0x00000600 0x00000700 0x00000800
diff --git a/arch/arm/boot/dts/msm-pm8226.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
index 6d506cc..a13e66a 100644
--- a/arch/arm/boot/dts/msm-pm8226.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226.dtsi
@@ -860,22 +860,6 @@
 				qcom,current = <625>;
 			};
 
-			pm8226_flash1: qcom,flash_1 {
-				qcom,max-current = <1000>;
-				qcom,default-state = "off";
-				qcom,headroom = <3>;
-				qcom,duration = <1280>;
-				qcom,clamp-curr = <200>;
-				qcom,startup-dly = <3>;
-				qcom,safety-timer;
-				linux,default-trigger =
-						"flash1_trigger";
-				label = "flash";
-				qcom,id = <2>;
-				linux,name = "led:flash_1";
-				qcom,current = <625>;
-			};
-
 			pm8226_torch: qcom,flash_torch {
 				qcom,max-current = <200>;
 				qcom,default-state = "off";
diff --git a/arch/arm/boot/dts/msm8226-mdss.dtsi b/arch/arm/boot/dts/msm8226-mdss.dtsi
index 38cfe66..84bb234 100644
--- a/arch/arm/boot/dts/msm8226-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8226-mdss.dtsi
@@ -28,6 +28,11 @@
 		qcom,mdss-pipe-vig-fetch-id = <1>;
 		qcom,mdss-pipe-rgb-fetch-id = <7>;
 		qcom,mdss-pipe-dma-fetch-id = <4>;
+
+		qcom,mdss-pipe-vig-xin-id = <0>;
+		qcom,mdss-pipe-rgb-xin-id = <1>;
+		qcom,mdss-pipe-dma-xin-id = <2>;
+
 		qcom,mdss-smp-data = <7 4096>;
 
 		qcom,mdss-ctl-off = <0x00000600 0x00000700>;
diff --git a/arch/arm/boot/dts/msm8226-qrd-skuf.dtsi b/arch/arm/boot/dts/msm8226-qrd-skuf.dtsi
index 2e32ac4..c3fcedb 100755
--- a/arch/arm/boot/dts/msm8226-qrd-skuf.dtsi
+++ b/arch/arm/boot/dts/msm8226-qrd-skuf.dtsi
@@ -82,7 +82,7 @@
 			avdd-supply = <&tp_power>;
 			goodix,panel-coords = <0 0 720 1200>;
 			goodix,display-coords = <0 0 720 1080>;
-			goodix,button-map= <158 102 139>;
+			goodix,button-map= <139 172 158>;
 			goodix,product-id = "915";
 			goodix,cfg-data0 = [
 				41 D0 02 00 05 05 35 11 01 0F
diff --git a/arch/arm/boot/dts/msm8226-qrd.dtsi b/arch/arm/boot/dts/msm8226-qrd.dtsi
index 7ff97f6..84e46ea 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-qrd.dtsi
@@ -17,6 +17,20 @@
 		status = "ok";
 	};
 
+        i2c@f9925000 { /* BLSP1 QUP3 */
+                nfc-nci@0e {
+                        compatible = "qcom,nfc-nci";
+                        reg = <0x0e>;
+                        qcom,irq-gpio = <&msmgpio 21 0x00>;
+                        qcom,dis-gpio = <&msmgpio 20 0x00>;
+                        qcom,clk-src = "BBCLK2";
+                        qcom,clk-en-gpio = <&msmgpio 0 0x00>;
+                        interrupt-parent = <&msmgpio>;
+                        interrupts = <21 0>;
+                        qcom,clk-gpio = <&pm8226_gpios 3 0>;
+                };
+        };
+
 	i2c@f9927000 { /* BLSP1 QUP5 */
 		synaptics@20 {
 			compatible = "synaptics,rmi4";
diff --git a/arch/arm/boot/dts/msm8610-qrd-skuab.dtsi b/arch/arm/boot/dts/msm8610-qrd-skuab.dtsi
index a22958a..943a333 100644
--- a/arch/arm/boot/dts/msm8610-qrd-skuab.dtsi
+++ b/arch/arm/boot/dts/msm8610-qrd-skuab.dtsi
@@ -101,6 +101,20 @@
 		qcom,y-offset = <0>;
 	};
 
+	i2c@f9924000 { /* BLSP-1 QUP-2 */
+		nfc-nci@e {
+			compatible = "qcom,nfc-nci";
+			reg = <0x0e>;
+			qcom,irq-gpio = <&msmgpio 77 0x00>;
+			qcom,dis-gpio = <&msmgpio 93 0x00>;
+			qcom,clk-en-gpio = <&msmgpio 78 0x00>;
+			qcom,clk-src = "GPCLK2";
+			interrupt-parent = <&msmgpio>;
+			interrupts = <77 0>;
+			qcom,clk-gpio = <&msmgpio 75 0x00>;
+		};
+	};
+
     i2c@f9925000 {
 		fsl@1c {
 			compatible = "fsl,mma8x5x";
diff --git a/arch/arm/boot/dts/msm8974-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
index 9e7b2e6..27536db 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -757,3 +757,11 @@
 &dsi_tosh_720_vid {
        qcom,cont-splash-enabled;
 };
+
+&dsi_generic_720p_cmd {
+       qcom,cont-splash-enabled;
+};
+
+&dsi_jdi_1080_vid {
+       qcom,cont-splash-enabled;
+};
diff --git a/arch/arm/boot/dts/msm8974-mdss.dtsi b/arch/arm/boot/dts/msm8974-mdss.dtsi
index e409c94..bf330f3 100644
--- a/arch/arm/boot/dts/msm8974-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8974-mdss.dtsi
@@ -30,6 +30,11 @@
 		qcom,mdss-pipe-vig-fetch-id = <1 4 7>;
 		qcom,mdss-pipe-rgb-fetch-id = <16 17 18>;
 		qcom,mdss-pipe-dma-fetch-id = <10 13>;
+
+		qcom,mdss-pipe-vig-xin-id = <0 4 8>;
+		qcom,mdss-pipe-rgb-xin-id = <1 5 9>;
+		qcom,mdss-pipe-dma-xin-id = <2 10>;
+
 		qcom,mdss-smp-data = <22 4096>;
 
 		qcom,mdss-ctl-off = <0x00000600 0x00000700 0x00000800
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index f73bcdc..6cc49c4 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -733,3 +733,11 @@
 &dsi_tosh_720_vid {
        qcom,cont-splash-enabled;
 };
+
+&dsi_generic_720p_cmd {
+       qcom,cont-splash-enabled;
+};
+
+&dsi_jdi_1080_vid {
+       qcom,cont-splash-enabled;
+};
diff --git a/arch/arm/boot/dts/msm8974-v2-pm.dtsi b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
index e2d40f7..cdd5fde 100644
--- a/arch/arm/boot/dts/msm8974-v2-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
@@ -212,6 +212,7 @@
 			<50 172>, /* usb1_hs_async_wakeup_irq */
 			<53 104>, /* mdss_irq */
 			<62 222>, /* ee0_krait_hlos_spmi_periph_irq */
+			<0xff 33>,  /* APCC_qgicL2PerfMonIrptReq */
 			<0xff 34>,  /* APCC_qgicL2ErrorIrptReq */
 			<0xff 35>,  /* WDT_barkInt */
 			<0xff 40>,  /* qtimer_phy_irq */
diff --git a/arch/arm/boot/dts/msm8974-v2.dtsi b/arch/arm/boot/dts/msm8974-v2.dtsi
index 9176117..5607257 100644
--- a/arch/arm/boot/dts/msm8974-v2.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2.dtsi
@@ -122,7 +122,7 @@
 	qcom,dec-ocmem-ab-ib = <0 0>,
 		<176000 519000>,
 		<456000 519000>,
-		<864000 519000>,
+		<864000 629000>,
 		<1728000 1038000>,
 		<2766000 1661000>,
 		<3456000 2076000>,
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 4babf11..8b52a3f 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -911,7 +911,8 @@
 		hfpll-dig-supply = <&pm8841_s2_corner_ao>;
 		hfpll-analog-supply = <&pm8941_l12_ao>;
 		qcom,hfpll-config-val = <0x04D0405D>;
-                qcom,hfpll-user-vco-mask = <0x00100000>;
+		qcom,hfpll-user-vco-mask = <0x00100000>;
+		qcom,pvs-config-ver = <1>;
 
 		qcom,l2-fmax =
 			<          0 0			 >,
diff --git a/arch/arm/boot/dts/msm8974pro-pm.dtsi b/arch/arm/boot/dts/msm8974pro-pm.dtsi
index 63cb68b..29aeccd 100644
--- a/arch/arm/boot/dts/msm8974pro-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-pm.dtsi
@@ -217,7 +217,7 @@
 			<0xff 18>,  /* APCx_qgicQTmrSecPhysIrptReq */
 			<0xff 19>,  /* APCx_qgicQTmrSecPhysIrptReq */
 			<0xff 25>,  /* APCx_qgicExtFaultIrptReq */
-			<0xff 33>, /*l2_perf_mon*/
+			<0xff 33>,  /* APCC_qgicL2PerfMonIrptReq */
 			<0xff 34>,  /* APCC_qgicL2ErrorIrptReq */
 			<0xff 35>,  /* WDT_barkInt */
 			<0xff 40>,  /* qtimer_phy_irq */
diff --git a/arch/arm/boot/dts/msm8974pro.dtsi b/arch/arm/boot/dts/msm8974pro.dtsi
index b670cfd..874ce05 100755
--- a/arch/arm/boot/dts/msm8974pro.dtsi
+++ b/arch/arm/boot/dts/msm8974pro.dtsi
@@ -699,17 +699,17 @@
 			<  345600000  775000   87 >,
 			<  422400000  775000  108 >,
 			<  499200000  775000  129 >,
-			<  576000000  780000  150 >,
-			<  652800000  790000  171 >,
-			<  729600000  800000  193 >,
-			<  806400000  810000  215 >,
-			<  883200000  820000  237 >,
-			<  960000000  830000  260 >,
-			< 1036800000  840000  282 >,
-			< 1113600000  850000  306 >,
-			< 1190400000  860000  330 >,
-			< 1267200000  870000  354 >,
-			< 1344000000  880000  378 >,
+			<  576000000  785000  150 >,
+			<  652800000  795000  171 >,
+			<  729600000  805000  193 >,
+			<  806400000  815000  215 >,
+			<  883200000  825000  237 >,
+			<  960000000  835000  260 >,
+			< 1036800000  845000  282 >,
+			< 1113600000  855000  306 >,
+			< 1190400000  865000  330 >,
+			< 1267200000  875000  354 >,
+			< 1344000000  885000  378 >,
 			< 1420800000  895000  404 >,
 			< 1497600000  910000  431 >,
 			< 1574400000  925000  458 >,
@@ -730,18 +730,18 @@
 			<  345600000  775000   87 >,
 			<  422400000  775000  108 >,
 			<  499200000  775000  129 >,
-			<  576000000  775000  150 >,
-			<  652800000  780000  171 >,
-			<  729600000  790000  193 >,
-			<  806400000  800000  215 >,
-			<  883200000  810000  237 >,
-			<  960000000  820000  260 >,
-			< 1036800000  830000  282 >,
-			< 1113600000  840000  306 >,
-			< 1190400000  850000  330 >,
-			< 1267200000  860000  354 >,
-			< 1344000000  870000  378 >,
-			< 1420800000  885000  404 >,
+			<  576000000  780000  150 >,
+			<  652800000  790000  171 >,
+			<  729600000  800000  193 >,
+			<  806400000  810000  215 >,
+			<  883200000  820000  237 >,
+			<  960000000  830000  260 >,
+			< 1036800000  840000  282 >,
+			< 1113600000  850000  306 >,
+			< 1190400000  860000  330 >,
+			< 1267200000  870000  354 >,
+			< 1344000000  880000  378 >,
+			< 1420800000  890000  404 >,
 			< 1497600000  900000  431 >,
 			< 1574400000  915000  458 >,
 			< 1651200000  930000  486 >,
@@ -762,17 +762,17 @@
 			<  422400000  775000  108 >,
 			<  499200000  775000  129 >,
 			<  576000000  775000  150 >,
-			<  652800000  775000  171 >,
-			<  729600000  780000  193 >,
-			<  806400000  790000  215 >,
-			<  883200000  800000  237 >,
-			<  960000000  810000  260 >,
-			< 1036800000  820000  282 >,
-			< 1113600000  830000  306 >,
-			< 1190400000  840000  330 >,
-			< 1267200000  850000  354 >,
-			< 1344000000  860000  378 >,
-			< 1420800000  875000  404 >,
+			<  652800000  780000  171 >,
+			<  729600000  790000  193 >,
+			<  806400000  800000  215 >,
+			<  883200000  810000  237 >,
+			<  960000000  820000  260 >,
+			< 1036800000  830000  282 >,
+			< 1113600000  840000  306 >,
+			< 1190400000  850000  330 >,
+			< 1267200000  860000  354 >,
+			< 1344000000  870000  378 >,
+			< 1420800000  880000  404 >,
 			< 1497600000  890000  431 >,
 			< 1574400000  905000  458 >,
 			< 1651200000  920000  486 >,
@@ -794,17 +794,17 @@
 			<  499200000  775000  129 >,
 			<  576000000  775000  150 >,
 			<  652800000  775000  171 >,
-			<  729600000  775000  193 >,
-			<  806400000  780000  215 >,
-			<  883200000  790000  237 >,
-			<  960000000  800000  260 >,
-			< 1036800000  810000  282 >,
-			< 1113600000  820000  306 >,
-			< 1190400000  830000  330 >,
-			< 1267200000  840000  354 >,
-			< 1344000000  850000  378 >,
-			< 1420800000  865000  404 >,
-			< 1497600000  880000  431 >,
+			<  729600000  785000  193 >,
+			<  806400000  795000  215 >,
+			<  883200000  805000  237 >,
+			<  960000000  815000  260 >,
+			< 1036800000  825000  282 >,
+			< 1113600000  835000  306 >,
+			< 1190400000  845000  330 >,
+			< 1267200000  855000  354 >,
+			< 1344000000  865000  378 >,
+			< 1420800000  875000  404 >,
+			< 1497600000  885000  431 >,
 			< 1574400000  895000  458 >,
 			< 1651200000  910000  486 >,
 			< 1728000000  925000  515 >,
@@ -825,18 +825,18 @@
 			<  499200000  775000  129 >,
 			<  576000000  775000  150 >,
 			<  652800000  775000  171 >,
-			<  729600000  775000  193 >,
-			<  806400000  775000  215 >,
-			<  883200000  780000  237 >,
-			<  960000000  790000  260 >,
-			< 1036800000  800000  282 >,
-			< 1113600000  810000  306 >,
-			< 1190400000  820000  330 >,
-			< 1267200000  830000  354 >,
-			< 1344000000  840000  378 >,
-			< 1420800000  855000  404 >,
-			< 1497600000  870000  431 >,
-			< 1574400000  885000  458 >,
+			<  729600000  780000  193 >,
+			<  806400000  790000  215 >,
+			<  883200000  800000  237 >,
+			<  960000000  810000  260 >,
+			< 1036800000  820000  282 >,
+			< 1113600000  830000  306 >,
+			< 1190400000  840000  330 >,
+			< 1267200000  850000  354 >,
+			< 1344000000  860000  378 >,
+			< 1420800000  870000  404 >,
+			< 1497600000  880000  431 >,
+			< 1574400000  890000  458 >,
 			< 1651200000  900000  486 >,
 			< 1728000000  915000  515 >,
 			< 1804800000  930000  543 >,
@@ -857,18 +857,18 @@
 			<  576000000  775000  150 >,
 			<  652800000  775000  171 >,
 			<  729600000  775000  193 >,
-			<  806400000  775000  215 >,
-			<  883200000  775000  237 >,
-			<  960000000  780000  260 >,
-			< 1036800000  790000  282 >,
-			< 1113600000  800000  306 >,
-			< 1190400000  810000  330 >,
-			< 1267200000  820000  354 >,
-			< 1344000000  830000  378 >,
-			< 1420800000  845000  404 >,
-			< 1497600000  860000  431 >,
-			< 1574400000  875000  458 >,
-			< 1651200000  890000  486 >,
+			<  806400000  785000  215 >,
+			<  883200000  795000  237 >,
+			<  960000000  805000  260 >,
+			< 1036800000  815000  282 >,
+			< 1113600000  825000  306 >,
+			< 1190400000  835000  330 >,
+			< 1267200000  845000  354 >,
+			< 1344000000  855000  378 >,
+			< 1420800000  865000  404 >,
+			< 1497600000  875000  431 >,
+			< 1574400000  885000  458 >,
+			< 1651200000  895000  486 >,
 			< 1728000000  905000  515 >,
 			< 1804800000  920000  543 >,
 			< 1881600000  935000  572 >,
@@ -888,19 +888,19 @@
 			<  576000000  775000  150 >,
 			<  652800000  775000  171 >,
 			<  729600000  775000  193 >,
-			<  806400000  775000  215 >,
-			<  883200000  775000  237 >,
-			<  960000000  775000  260 >,
-			< 1036800000  780000  282 >,
-			< 1113600000  790000  306 >,
-			< 1190400000  800000  330 >,
-			< 1267200000  810000  354 >,
-			< 1344000000  820000  378 >,
-			< 1420800000  835000  404 >,
-			< 1497600000  850000  431 >,
-			< 1574400000  865000  458 >,
-			< 1651200000  880000  486 >,
-			< 1728000000  895000  515 >,
+			<  806400000  780000  215 >,
+			<  883200000  790000  237 >,
+			<  960000000  800000  260 >,
+			< 1036800000  810000  282 >,
+			< 1113600000  820000  306 >,
+			< 1190400000  830000  330 >,
+			< 1267200000  840000  354 >,
+			< 1344000000  850000  378 >,
+			< 1420800000  860000  404 >,
+			< 1497600000  870000  431 >,
+			< 1574400000  880000  458 >,
+			< 1651200000  890000  486 >,
+			< 1728000000  900000  515 >,
 			< 1804800000  910000  543 >,
 			< 1881600000  925000  572 >,
 			< 1958400000  940000  604 >,
@@ -920,19 +920,19 @@
 			<  652800000  775000  171 >,
 			<  729600000  775000  193 >,
 			<  806400000  775000  215 >,
-			<  883200000  775000  237 >,
-			<  960000000  775000  260 >,
-			< 1036800000  775000  282 >,
-			< 1113600000  780000  306 >,
-			< 1190400000  790000  330 >,
-			< 1267200000  800000  354 >,
-			< 1344000000  810000  378 >,
-			< 1420800000  825000  404 >,
-			< 1497600000  840000  431 >,
-			< 1574400000  855000  458 >,
-			< 1651200000  870000  486 >,
-			< 1728000000  885000  515 >,
-			< 1804800000  900000  543 >,
+			<  883200000  785000  237 >,
+			<  960000000  795000  260 >,
+			< 1036800000  805000  282 >,
+			< 1113600000  815000  306 >,
+			< 1190400000  825000  330 >,
+			< 1267200000  835000  354 >,
+			< 1344000000  845000  378 >,
+			< 1420800000  855000  404 >,
+			< 1497600000  865000  431 >,
+			< 1574400000  875000  458 >,
+			< 1651200000  885000  486 >,
+			< 1728000000  895000  515 >,
+			< 1804800000  905000  543 >,
 			< 1881600000  915000  572 >,
 			< 1958400000  930000  604 >,
 			< 2035200000  945000  636 >,
@@ -949,22 +949,22 @@
 			<  499200000  750000  129 >,
 			<  576000000  750000  150 >,
 			<  652800000  750000  171 >,
-			<  729600000  750000  193 >,
-			<  806400000  750000  215 >,
-			<  883200000  750000  237 >,
-			<  960000000  750000  260 >,
-			< 1036800000  760000  282 >,
-			< 1113600000  770000  306 >,
-			< 1190400000  780000  330 >,
-			< 1267200000  790000  354 >,
-			< 1344000000  800000  378 >,
-			< 1420800000  815000  404 >,
-			< 1497600000  830000  431 >,
-			< 1574400000  845000  458 >,
-			< 1651200000  860000  486 >,
-			< 1728000000  875000  515 >,
-			< 1804800000  890000  543 >,
-			< 1881600000  905000  572 >,
+			<  729600000  760000  193 >,
+			<  806400000  770000  215 >,
+			<  883200000  780000  237 >,
+			<  960000000  790000  260 >,
+			< 1036800000  800000  282 >,
+			< 1113600000  810000  306 >,
+			< 1190400000  820000  330 >,
+			< 1267200000  830000  354 >,
+			< 1344000000  840000  378 >,
+			< 1420800000  850000  404 >,
+			< 1497600000  860000  431 >,
+			< 1574400000  870000  458 >,
+			< 1651200000  880000  486 >,
+			< 1728000000  890000  515 >,
+			< 1804800000  900000  543 >,
+			< 1881600000  910000  572 >,
 			< 1958400000  920000  604 >,
 			< 2035200000  935000  636 >,
 			< 2112000000  950000  669 >,
@@ -980,23 +980,23 @@
 			<  499200000  750000  129 >,
 			<  576000000  750000  150 >,
 			<  652800000  750000  171 >,
-			<  729600000  750000  193 >,
-			<  806400000  750000  215 >,
-			<  883200000  750000  237 >,
-			<  960000000  750000  260 >,
-			< 1036800000  750000  282 >,
-			< 1113600000  760000  306 >,
-			< 1190400000  770000  330 >,
-			< 1267200000  780000  354 >,
-			< 1344000000  790000  378 >,
-			< 1420800000  805000  404 >,
-			< 1497600000  820000  431 >,
-			< 1574400000  835000  458 >,
-			< 1651200000  850000  486 >,
-			< 1728000000  865000  515 >,
-			< 1804800000  880000  543 >,
-			< 1881600000  895000  572 >,
-			< 1958400000  910000  604 >,
+			<  729600000  755000  193 >,
+			<  806400000  765000  215 >,
+			<  883200000  775000  237 >,
+			<  960000000  785000  260 >,
+			< 1036800000  795000  282 >,
+			< 1113600000  805000  306 >,
+			< 1190400000  815000  330 >,
+			< 1267200000  825000  354 >,
+			< 1344000000  835000  378 >,
+			< 1420800000  845000  404 >,
+			< 1497600000  855000  431 >,
+			< 1574400000  865000  458 >,
+			< 1651200000  875000  486 >,
+			< 1728000000  885000  515 >,
+			< 1804800000  895000  543 >,
+			< 1881600000  905000  572 >,
+			< 1958400000  915000  604 >,
 			< 2035200000  925000  636 >,
 			< 2112000000  940000  669 >,
 			< 2150400000  955000  703 >,
@@ -1249,18 +1249,18 @@
 			<  499200000  775000  126 >,
 			<  576000000  775000  147 >,
 			<  652800000  775000  168 >,
-			<  729600000  775000  189 >,
-			<  806400000  780000  211 >,
-			<  883200000  790000  233 >,
-			<  960000000  800000  256 >,
-			< 1036800000  810000  278 >,
-			< 1113600000  820000  301 >,
-			< 1190400000  830000  324 >,
-			< 1267200000  840000  348 >,
-			< 1344000000  850000  372 >,
-			< 1420800000  860000  396 >,
-			< 1497600000  870000  421 >,
-			< 1574400000  880000  446 >,
+			<  729600000  780000  189 >,
+			<  806400000  785000  211 >,
+			<  883200000  795000  233 >,
+			<  960000000  805000  256 >,
+			< 1036800000  815000  278 >,
+			< 1113600000  825000  301 >,
+			< 1190400000  835000  324 >,
+			< 1267200000  845000  348 >,
+			< 1344000000  855000  372 >,
+			< 1420800000  865000  396 >,
+			< 1497600000  875000  421 >,
+			< 1574400000  885000  446 >,
 			< 1651200000  895000  473 >,
 			< 1728000000  910000  501 >,
 			< 1804800000  925000  529 >,
@@ -1284,17 +1284,17 @@
 			<  576000000  775000  147 >,
 			<  652800000  775000  168 >,
 			<  729600000  775000  189 >,
-			<  806400000  775000  211 >,
-			<  883200000  780000  233 >,
-			<  960000000  790000  256 >,
-			< 1036800000  800000  278 >,
-			< 1113600000  810000  301 >,
-			< 1190400000  820000  324 >,
-			< 1267200000  830000  348 >,
-			< 1344000000  840000  372 >,
-			< 1420800000  850000  396 >,
-			< 1497600000  860000  421 >,
-			< 1574400000  870000  446 >,
+			<  806400000  780000  211 >,
+			<  883200000  785000  233 >,
+			<  960000000  795000  256 >,
+			< 1036800000  805000  278 >,
+			< 1113600000  815000  301 >,
+			< 1190400000  825000  324 >,
+			< 1267200000  835000  348 >,
+			< 1344000000  845000  372 >,
+			< 1420800000  855000  396 >,
+			< 1497600000  865000  421 >,
+			< 1574400000  875000  446 >,
 			< 1651200000  885000  473 >,
 			< 1728000000  900000  501 >,
 			< 1804800000  915000  529 >,
@@ -1319,17 +1319,17 @@
 			<  652800000  775000  168 >,
 			<  729600000  775000  189 >,
 			<  806400000  775000  211 >,
-			<  883200000  775000  233 >,
-			<  960000000  780000  256 >,
-			< 1036800000  790000  278 >,
-			< 1113600000  800000  301 >,
-			< 1190400000  810000  324 >,
-			< 1267200000  820000  348 >,
-			< 1344000000  830000  372 >,
-			< 1420800000  840000  396 >,
-			< 1497600000  850000  421 >,
-			< 1574400000  860000  446 >,
-			< 1651200000  875000  473 >,
+			<  883200000  780000  233 >,
+			<  960000000  790000  256 >,
+			< 1036800000  800000  278 >,
+			< 1113600000  810000  301 >,
+			< 1190400000  820000  324 >,
+			< 1267200000  830000  348 >,
+			< 1344000000  840000  372 >,
+			< 1420800000  850000  396 >,
+			< 1497600000  860000  421 >,
+			< 1574400000  870000  446 >,
+			< 1651200000  880000  473 >,
 			< 1728000000  890000  501 >,
 			< 1804800000  905000  529 >,
 			< 1881600000  920000  558 >,
@@ -1353,18 +1353,18 @@
 			<  652800000  775000  168 >,
 			<  729600000  775000  189 >,
 			<  806400000  775000  211 >,
-			<  883200000  775000  233 >,
-			<  960000000  775000  256 >,
-			< 1036800000  780000  278 >,
-			< 1113600000  790000  301 >,
-			< 1190400000  800000  324 >,
-			< 1267200000  810000  348 >,
-			< 1344000000  820000  372 >,
-			< 1420800000  830000  396 >,
-			< 1497600000  840000  421 >,
-			< 1574400000  850000  446 >,
-			< 1651200000  865000  473 >,
-			< 1728000000  880000  501 >,
+			<  883200000  780000  233 >,
+			<  960000000  785000  256 >,
+			< 1036800000  795000  278 >,
+			< 1113600000  805000  301 >,
+			< 1190400000  815000  324 >,
+			< 1267200000  825000  348 >,
+			< 1344000000  835000  372 >,
+			< 1420800000  845000  396 >,
+			< 1497600000  855000  421 >,
+			< 1574400000  865000  446 >,
+			< 1651200000  875000  473 >,
+			< 1728000000  885000  501 >,
 			< 1804800000  895000  529 >,
 			< 1881600000  910000  558 >,
 			< 1958400000  925000  588 >,
@@ -1388,18 +1388,18 @@
 			<  729600000  775000  189 >,
 			<  806400000  775000  211 >,
 			<  883200000  775000  233 >,
-			<  960000000  775000  256 >,
-			< 1036800000  775000  278 >,
-			< 1113600000  780000  301 >,
-			< 1190400000  790000  324 >,
-			< 1267200000  800000  348 >,
-			< 1344000000  810000  372 >,
-			< 1420800000  820000  396 >,
-			< 1497600000  830000  421 >,
-			< 1574400000  840000  446 >,
-			< 1651200000  855000  473 >,
-			< 1728000000  870000  501 >,
-			< 1804800000  885000  529 >,
+			<  960000000  780000  256 >,
+			< 1036800000  790000  278 >,
+			< 1113600000  800000  301 >,
+			< 1190400000  810000  324 >,
+			< 1267200000  820000  348 >,
+			< 1344000000  830000  372 >,
+			< 1420800000  840000  396 >,
+			< 1497600000  850000  421 >,
+			< 1574400000  860000  446 >,
+			< 1651200000  870000  473 >,
+			< 1728000000  880000  501 >,
+			< 1804800000  890000  529 >,
 			< 1881600000  900000  558 >,
 			< 1958400000  915000  588 >,
 			< 2035200000  930000  617 >,
@@ -1422,19 +1422,19 @@
 			<  729600000  775000  189 >,
 			<  806400000  775000  211 >,
 			<  883200000  775000  233 >,
-			<  960000000  775000  256 >,
-			< 1036800000  775000  278 >,
-			< 1113600000  775000  301 >,
-			< 1190400000  780000  324 >,
-			< 1267200000  790000  348 >,
-			< 1344000000  800000  372 >,
-			< 1420800000  810000  396 >,
-			< 1497600000  820000  421 >,
-			< 1574400000  830000  446 >,
-			< 1651200000  845000  473 >,
-			< 1728000000  860000  501 >,
-			< 1804800000  875000  529 >,
-			< 1881600000  890000  558 >,
+			<  960000000  780000  256 >,
+			< 1036800000  785000  278 >,
+			< 1113600000  795000  301 >,
+			< 1190400000  805000  324 >,
+			< 1267200000  815000  348 >,
+			< 1344000000  825000  372 >,
+			< 1420800000  835000  396 >,
+			< 1497600000  845000  421 >,
+			< 1574400000  855000  446 >,
+			< 1651200000  865000  473 >,
+			< 1728000000  875000  501 >,
+			< 1804800000  885000  529 >,
+			< 1881600000  895000  558 >,
 			< 1958400000  905000  588 >,
 			< 2035200000  920000  617 >,
 			< 2112000000  935000  649 >,
@@ -1457,19 +1457,19 @@
 			<  806400000  775000  211 >,
 			<  883200000  775000  233 >,
 			<  960000000  775000  256 >,
-			< 1036800000  775000  278 >,
-			< 1113600000  775000  301 >,
-			< 1190400000  775000  324 >,
-			< 1267200000  780000  348 >,
-			< 1344000000  790000  372 >,
-			< 1420800000  800000  396 >,
-			< 1497600000  810000  421 >,
-			< 1574400000  820000  446 >,
-			< 1651200000  835000  473 >,
-			< 1728000000  850000  501 >,
-			< 1804800000  865000  529 >,
-			< 1881600000  880000  558 >,
-			< 1958400000  895000  588 >,
+			< 1036800000  780000  278 >,
+			< 1113600000  790000  301 >,
+			< 1190400000  800000  324 >,
+			< 1267200000  810000  348 >,
+			< 1344000000  820000  372 >,
+			< 1420800000  830000  396 >,
+			< 1497600000  840000  421 >,
+			< 1574400000  850000  446 >,
+			< 1651200000  860000  473 >,
+			< 1728000000  870000  501 >,
+			< 1804800000  880000  529 >,
+			< 1881600000  890000  558 >,
+			< 1958400000  900000  588 >,
 			< 2035200000  910000  617 >,
 			< 2112000000  925000  649 >,
 			< 2150400000  940000  682 >,
@@ -1489,22 +1489,22 @@
 			<  652800000  750000  168 >,
 			<  729600000  750000  189 >,
 			<  806400000  750000  211 >,
-			<  883200000  750000  233 >,
-			<  960000000  750000  256 >,
-			< 1036800000  750000  278 >,
-			< 1113600000  750000  301 >,
-			< 1190400000  760000  324 >,
-			< 1267200000  770000  348 >,
-			< 1344000000  780000  372 >,
-			< 1420800000  790000  396 >,
-			< 1497600000  800000  421 >,
-			< 1574400000  810000  446 >,
-			< 1651200000  825000  473 >,
-			< 1728000000  840000  501 >,
-			< 1804800000  855000  529 >,
-			< 1881600000  870000  558 >,
-			< 1958400000  885000  588 >,
-			< 2035200000  900000  617 >,
+			<  883200000  755000  233 >,
+			<  960000000  765000  256 >,
+			< 1036800000  775000  278 >,
+			< 1113600000  785000  301 >,
+			< 1190400000  795000  324 >,
+			< 1267200000  805000  348 >,
+			< 1344000000  815000  372 >,
+			< 1420800000  825000  396 >,
+			< 1497600000  835000  421 >,
+			< 1574400000  845000  446 >,
+			< 1651200000  855000  473 >,
+			< 1728000000  865000  501 >,
+			< 1804800000  875000  529 >,
+			< 1881600000  885000  558 >,
+			< 1958400000  895000  588 >,
+			< 2035200000  905000  617 >,
 			< 2112000000  915000  649 >,
 			< 2150400000  930000  682 >,
 			< 2188800000  930000  682 >,
@@ -1523,23 +1523,23 @@
 			<  652800000  750000  168 >,
 			<  729600000  750000  189 >,
 			<  806400000  750000  211 >,
-			<  883200000  750000  233 >,
-			<  960000000  750000  256 >,
-			< 1036800000  750000  278 >,
-			< 1113600000  750000  301 >,
-			< 1190400000  750000  324 >,
-			< 1267200000  760000  348 >,
-			< 1344000000  770000  372 >,
-			< 1420800000  780000  396 >,
-			< 1497600000  790000  421 >,
-			< 1574400000  800000  446 >,
-			< 1651200000  815000  473 >,
-			< 1728000000  830000  501 >,
-			< 1804800000  845000  529 >,
-			< 1881600000  860000  558 >,
-			< 1958400000  875000  588 >,
-			< 2035200000  890000  617 >,
-			< 2112000000  905000  649 >,
+			<  883200000  755000  233 >,
+			<  960000000  760000  256 >,
+			< 1036800000  770000  278 >,
+			< 1113600000  780000  301 >,
+			< 1190400000  790000  324 >,
+			< 1267200000  800000  348 >,
+			< 1344000000  810000  372 >,
+			< 1420800000  820000  396 >,
+			< 1497600000  830000  421 >,
+			< 1574400000  840000  446 >,
+			< 1651200000  850000  473 >,
+			< 1728000000  860000  501 >,
+			< 1804800000  870000  529 >,
+			< 1881600000  880000  558 >,
+			< 1958400000  890000  588 >,
+			< 2035200000  900000  617 >,
+			< 2112000000  910000  649 >,
 			< 2150400000  920000  682 >,
 			< 2188800000  920000  682 >,
 			< 2265600000  935000  716 >,
@@ -1616,42 +1616,42 @@
                        reg = <0>;
                        qcom,gpu-freq = <578000000>;
                        qcom,bus-freq = <14>;
-                       qcom,io-fraction = <33>;
+                       qcom,io-fraction = <101>;
                };
 
                qcom,gpu-pwrlevel@1 {
                        reg = <1>;
                        qcom,gpu-freq = <462400000>;
                        qcom,bus-freq = <11>;
-                       qcom,io-fraction = <66>;
+                       qcom,io-fraction = <101>;
                };
 
                qcom,gpu-pwrlevel@2 {
                        reg = <2>;
                        qcom,gpu-freq = <389000000>;
                        qcom,bus-freq = <8>;
-                       qcom,io-fraction = <66>;
+                       qcom,io-fraction = <101>;
                };
 
                qcom,gpu-pwrlevel@3 {
                        reg = <3>;
-                       qcom,gpu-freq = <320000000>;
+                       qcom,gpu-freq = <330000000>;
                        qcom,bus-freq = <5>;
-                       qcom,io-fraction = <100>;
+                       qcom,io-fraction = <101>;
                };
 
                qcom,gpu-pwrlevel@4 {
                        reg = <4>;
                        qcom,gpu-freq = <200000000>;
                        qcom,bus-freq = <2>;
-                       qcom,io-fraction = <100>;
+                       qcom,io-fraction = <101>;
                };
 
                qcom,gpu-pwrlevel@5 {
                        reg = <5>;
                        qcom,gpu-freq = <27000000>;
                        qcom,bus-freq = <0>;
-                       qcom,io-fraction = <0>;
+                       qcom,io-fraction = <101>;
                };
        };
 };
diff --git a/arch/arm/configs/msm8226-perf_defconfig b/arch/arm/configs/msm8226-perf_defconfig
index 6b1f88d..18402ad 100644
--- a/arch/arm/configs/msm8226-perf_defconfig
+++ b/arch/arm/configs/msm8226-perf_defconfig
@@ -251,6 +251,7 @@
 CONFIG_WCNSS_CORE=y
 CONFIG_WCNSS_CORE_PRONTO=y
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
 CONFIG_KEYBOARD_GPIO=y
@@ -261,6 +262,10 @@
 CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y
+CONFIG_TOUCHSCREEN_GT9XX=y
+CONFIG_GT9XX_TOUCHPANEL_DRIVER=y
+CONFIG_GT9XX_TOUCHPANEL_UPDATE=y
+CONFIG_GT9XX_TOUCHPANEL_DEBUG=y
 CONFIG_TOUCHSCREEN_FT5X06=y
 CONFIG_TOUCHSCREEN_GEN_VKEYS=y
 CONFIG_INPUT_MISC=y
@@ -359,6 +364,7 @@
 CONFIG_USB_EHCI_MSM=y
 CONFIG_USB_EHCI_MSM_HSIC=y
 CONFIG_USB_ACM=y
+CONFIG_USB_CCID_BRIDGE=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_STORAGE_DATAFAB=y
 CONFIG_USB_STORAGE_FREECOM=y
@@ -458,8 +464,6 @@
 CONFIG_MOBICORE_SUPPORT=m
 CONFIG_MOBICORE_API=m
 CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
-CONFIG_TOUCHSCREEN_GT9XX=y
-CONFIG_GT9XX_TOUCHPANEL_DRIVER=y
 CONFIG_MSM_RDBG=m
 CONFIG_DEVMEM=n
 CONFIG_DEVKMEM=n
diff --git a/arch/arm/configs/msm8226_defconfig b/arch/arm/configs/msm8226_defconfig
index 2d54549..bfe05c0 100644
--- a/arch/arm/configs/msm8226_defconfig
+++ b/arch/arm/configs/msm8226_defconfig
@@ -251,6 +251,7 @@
 CONFIG_WCNSS_CORE=y
 CONFIG_WCNSS_CORE_PRONTO=y
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
 CONFIG_KEYBOARD_GPIO=y
@@ -261,6 +262,10 @@
 CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y
+CONFIG_TOUCHSCREEN_GT9XX=y
+CONFIG_GT9XX_TOUCHPANEL_DRIVER=y
+CONFIG_GT9XX_TOUCHPANEL_UPDATE=y
+CONFIG_GT9XX_TOUCHPANEL_DEBUG=y
 CONFIG_TOUCHSCREEN_FT5X06=y
 CONFIG_TOUCHSCREEN_GEN_VKEYS=y
 CONFIG_INPUT_MISC=y
@@ -383,6 +388,7 @@
 CONFIG_USB_EHCI_MSM=y
 CONFIG_USB_EHCI_MSM_HSIC=y
 CONFIG_USB_ACM=y
+CONFIG_USB_CCID_BRIDGE=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_STORAGE_DATAFAB=y
 CONFIG_USB_STORAGE_FREECOM=y
@@ -511,6 +517,4 @@
 CONFIG_MOBICORE_SUPPORT=m
 CONFIG_MOBICORE_API=m
 CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
-CONFIG_TOUCHSCREEN_GT9XX=y
-CONFIG_GT9XX_TOUCHPANEL_DRIVER=y
 CONFIG_MSM_RDBG=m
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index b5119b7..c7abf42 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -223,6 +223,9 @@
 CONFIG_WCNSS_CORE=y
 CONFIG_WCNSS_CORE_PRONTO=y
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
+# CONFIG_INPUT_MOUSEDEV is not set
+>>>>>>> 3e5f4f6... defconfig: Enable WCNSS register dump on WCNSS bite
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
 CONFIG_KEYBOARD_GPIO=y
@@ -235,6 +238,8 @@
 CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y
 CONFIG_TOUCHSCREEN_GT9XX=y
 CONFIG_GT9XX_TOUCHPANEL_DRIVER=y
+CONFIG_GT9XX_TOUCHPANEL_UPDATE=y
+CONFIG_GT9XX_TOUCHPANEL_DEBUG=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 CONFIG_INPUT_GPIO=m
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 165b841..fe84f96 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -224,6 +224,9 @@
 CONFIG_WCNSS_CORE=y
 CONFIG_WCNSS_CORE_PRONTO=y
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
+# CONFIG_INPUT_MOUSEDEV is not set
+>>>>>>> 3e5f4f6... defconfig: Enable WCNSS register dump on WCNSS bite
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
 CONFIG_KEYBOARD_GPIO=y
@@ -236,6 +239,8 @@
 CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y
 CONFIG_TOUCHSCREEN_GT9XX=y
 CONFIG_GT9XX_TOUCHPANEL_DRIVER=y
+CONFIG_GT9XX_TOUCHPANEL_UPDATE=y
+CONFIG_GT9XX_TOUCHPANEL_DEBUG=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 CONFIG_INPUT_GPIO=m
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index 737d98d..5904aea 100755
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -283,6 +283,7 @@
 CONFIG_WCNSS_CORE=y
 CONFIG_WCNSS_CORE_PRONTO=y
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
 CONFIG_KEYBOARD_GPIO=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index e5be6d5..1f7eb49 100755
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -289,6 +289,7 @@
 CONFIG_WCNSS_CORE=y
 CONFIG_WCNSS_CORE_PRONTO=y
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
 CONFIG_KEYBOARD_GPIO=y
diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h
index e1fc42f..d3e2eb6 100644
--- a/arch/arm/include/asm/pmu.h
+++ b/arch/arm/include/asm/pmu.h
@@ -141,6 +141,8 @@
 	struct pmu_hw_events	*(*get_hw_events)(void);
 	int	(*test_set_event_constraints)(struct perf_event *event);
 	int	(*clear_event_constraints)(struct perf_event *event);
+	void		(*save_pm_registers)(void *hcpu);
+	void		(*restore_pm_registers)(void *hcpu);
 };
 
 #define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu))
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index 2a3ab6e..7814288 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -197,6 +197,9 @@
 	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
 	u64 delta, prev_raw_count, new_raw_count;
 
+	if (event->state <= PERF_EVENT_STATE_OFF)
+		return 0;
+
 again:
 	prev_raw_count = local64_read(&hwc->prev_count);
 	new_raw_count = armpmu->read_counter(idx);
@@ -425,15 +428,37 @@
 	return err;
 }
 
-void
+#ifdef CONFIG_SMP
+static __ref int armpmu_cpu_up(int cpu)
+{
+	int ret = 0;
+
+	if (!cpumask_test_cpu(cpu, cpu_online_mask)) {
+		ret = cpu_up(cpu);
+		if (ret)
+			pr_err("Failed to bring up CPU: %d, ret: %d\n",
+			       cpu, ret);
+	}
+	return ret;
+}
+#else
+static inline int armpmu_cpu_up(int cpu)
+{
+	return 0;
+}
+#endif
+
+void __ref
 multicore_free_irq(int irq)
 {
 	int cpu;
+	struct irq_desc *desc = irq_to_desc(irq);
 
 	if (irq >= 0) {
-		for_each_cpu(cpu, cpu_online_mask) {
-			smp_call_function_single(cpu,
-					disable_irq_callback, &irq, 1);
+		for_each_cpu(cpu, desc->percpu_enabled) {
+			if (!armpmu_cpu_up(cpu))
+				smp_call_function_single(cpu,
+						disable_irq_callback, &irq, 1);
 		}
 		free_percpu_irq(irq, &pmu_irq_cookie);
 	}
@@ -716,6 +741,7 @@
 	armpmu->pmu.start = armpmu_start;
 	armpmu->pmu.stop = armpmu_stop;
 	armpmu->pmu.read = armpmu_read;
+	armpmu->pmu.events_across_hotplug = 1;
 }
 
 int armpmu_register(struct arm_pmu *armpmu, char *name, int type)
@@ -826,62 +852,6 @@
 	return 0;
 }
 
-/*
- * PMU hardware loses all context when a CPU goes offline.
- * When a CPU is hotplugged back in, since some hardware registers are
- * UNKNOWN at reset, the PMU must be explicitly reset to avoid reading
- * junk values out of them.
- */
-static int __cpuinit pmu_cpu_notify(struct notifier_block *b,
-					unsigned long action, void *hcpu)
-{
-	int irq;
-
-	if (cpu_has_active_perf((int)hcpu)) {
-		switch ((action & ~CPU_TASKS_FROZEN)) {
-
-		case CPU_DOWN_PREPARE:
-			/*
-			 * If this is on a multicore CPU, we need
-			 * to disarm the PMU IRQ before disappearing.
-			 */
-			if (cpu_pmu &&
-				cpu_pmu->plat_device->dev.platform_data) {
-				irq = platform_get_irq(cpu_pmu->plat_device, 0);
-				smp_call_function_single((int)hcpu,
-						disable_irq_callback, &irq, 1);
-			}
-			return NOTIFY_DONE;
-
-		case CPU_UP_PREPARE:
-			/*
-			 * If this is on a multicore CPU, we need
-			 * to arm the PMU IRQ before appearing.
-			 */
-			if (cpu_pmu &&
-				cpu_pmu->plat_device->dev.platform_data) {
-				irq = platform_get_irq(cpu_pmu->plat_device, 0);
-				smp_call_function_single((int)hcpu,
-						enable_irq_callback, &irq, 1);
-			}
-			return NOTIFY_DONE;
-
-		case CPU_STARTING:
-			if (cpu_pmu && cpu_pmu->reset) {
-				cpu_pmu->reset(NULL);
-				return NOTIFY_OK;
-			}
-		default:
-			return NOTIFY_DONE;
-		}
-	}
-
-	if ((action & ~CPU_TASKS_FROZEN) != CPU_STARTING)
-		return NOTIFY_DONE;
-
-	return NOTIFY_OK;
-}
-
 static void armpmu_update_counters(void)
 {
 	struct pmu_hw_events *hw_events;
@@ -902,6 +872,79 @@
 	}
 }
 
+/*
+ * PMU hardware loses all context when a CPU goes offline.
+ * When a CPU is hotplugged back in, since some hardware registers are
+ * UNKNOWN at reset, the PMU must be explicitly reset to avoid reading
+ * junk values out of them.
+ */
+static int __cpuinit pmu_cpu_notify(struct notifier_block *b,
+					unsigned long action, void *hcpu)
+{
+	int irq;
+	struct pmu *pmu;
+	int cpu = (int)hcpu;
+
+	switch ((action & ~CPU_TASKS_FROZEN)) {
+	case CPU_DOWN_PREPARE:
+		if (cpu_pmu && cpu_pmu->save_pm_registers)
+			smp_call_function_single(cpu,
+						 cpu_pmu->save_pm_registers,
+						 hcpu, 1);
+		break;
+	case CPU_STARTING:
+		if (cpu_pmu && cpu_pmu->restore_pm_registers)
+			smp_call_function_single(cpu,
+						 cpu_pmu->restore_pm_registers,
+						 hcpu, 1);
+	}
+
+	if (cpu_has_active_perf((int)hcpu)) {
+		switch ((action & ~CPU_TASKS_FROZEN)) {
+
+		case CPU_DOWN_PREPARE:
+			armpmu_update_counters();
+			/*
+			 * If this is on a multicore CPU, we need
+			 * to disarm the PMU IRQ before disappearing.
+			 */
+			if (cpu_pmu &&
+				cpu_pmu->plat_device->dev.platform_data) {
+				irq = platform_get_irq(cpu_pmu->plat_device, 0);
+				smp_call_function_single((int)hcpu,
+						disable_irq_callback, &irq, 1);
+			}
+			return NOTIFY_DONE;
+
+		case CPU_STARTING:
+			/*
+			 * If this is on a multicore CPU, we need
+			 * to arm the PMU IRQ before appearing.
+			 */
+			if (cpu_pmu &&
+				cpu_pmu->plat_device->dev.platform_data) {
+				irq = platform_get_irq(cpu_pmu->plat_device, 0);
+				enable_irq_callback(&irq);
+			}
+
+			if (cpu_pmu && cpu_pmu->reset) {
+				__get_cpu_var(from_idle) = 1;
+				cpu_pmu->reset(NULL);
+				pmu = &cpu_pmu->pmu;
+				pmu->pmu_enable(pmu);
+				return NOTIFY_OK;
+			}
+		default:
+			return NOTIFY_DONE;
+		}
+	}
+
+	if ((action & ~CPU_TASKS_FROZEN) != CPU_STARTING)
+		return NOTIFY_DONE;
+
+	return NOTIFY_OK;
+}
+
 static struct notifier_block __cpuinitdata pmu_cpu_notifier = {
 	.notifier_call = pmu_cpu_notify,
 };
@@ -913,6 +956,8 @@
 	struct pmu *pmu;
 	switch (cmd) {
 	case CPU_PM_ENTER:
+		if (cpu_pmu && cpu_pmu->save_pm_registers)
+			cpu_pmu->save_pm_registers((void *)smp_processor_id());
 		if (cpu_has_active_perf((int)v)) {
 			armpmu_update_counters();
 			pmu = &cpu_pmu->pmu;
@@ -922,6 +967,9 @@
 
 	case CPU_PM_ENTER_FAILED:
 	case CPU_PM_EXIT:
+		if (cpu_pmu && cpu_pmu->restore_pm_registers)
+			cpu_pmu->restore_pm_registers(
+				(void *)smp_processor_id());
 		if (cpu_has_active_perf((int)v) && cpu_pmu->reset) {
 			/*
 			 * Flip this bit so armpmu_enable knows it needs
diff --git a/arch/arm/kernel/perf_event_msm_krait.c b/arch/arm/kernel/perf_event_msm_krait.c
index 5708d74..1fb5fd3 100644
--- a/arch/arm/kernel/perf_event_msm_krait.c
+++ b/arch/arm/kernel/perf_event_msm_krait.c
@@ -572,6 +572,33 @@
 	return 1;
 }
 
+static DEFINE_PER_CPU(u32, krait_pm_pmactlr);
+
+static void krait_save_pm_registers(void *hcpu)
+{
+	u32 val;
+	u32 cpu = (int)hcpu;
+
+	/* Read PMACTLR */
+	asm volatile("mrc p15, 0, %0, c9, c15, 5" : "=r" (val));
+	per_cpu(krait_pm_pmactlr, cpu) = val;
+
+	armv7pmu_save_pm_registers(hcpu);
+}
+
+static void krait_restore_pm_registers(void *hcpu)
+{
+	u32 val;
+	u32 cpu = (int)hcpu;
+
+	val = per_cpu(krait_pm_pmactlr, cpu);
+	if (val != 0)
+		/* Restore PMACTLR */
+		asm volatile("mcr p15, 0, %0, c9, c15, 5" : : "r" (val));
+
+	armv7pmu_restore_pm_registers(hcpu);
+}
+
 static struct arm_pmu krait_pmu = {
 	.handle_irq		= armv7pmu_handle_irq,
 	.enable			= krait_pmu_enable_event,
@@ -585,6 +612,8 @@
 	.test_set_event_constraints	= msm_test_set_ev_constraint,
 	.clear_event_constraints	= msm_clear_ev_constraint,
 	.max_period		= (1LLU << 32) - 1,
+	.save_pm_registers	= krait_save_pm_registers,
+	.restore_pm_registers	= krait_restore_pm_registers,
 };
 
 /* NRCCG format for perf RAW codes. */
diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c
index 58e9068..7c7a9d1 100644
--- a/arch/arm/kernel/perf_event_v7.c
+++ b/arch/arm/kernel/perf_event_v7.c
@@ -1238,6 +1238,29 @@
 				&armv7_a7_perf_cache_map, 0xFF);
 }
 
+static DEFINE_PER_CPU(u32, armv7_pm_pmuserenr);
+
+static void armv7pmu_save_pm_registers(void *hcpu)
+{
+	u32 val;
+	u32 cpu = (int)hcpu;
+
+	/* Read PMUSERENR */
+	asm volatile("mrc p15, 0, %0, c9, c14, 0" : "=r" (val));
+	per_cpu(armv7_pm_pmuserenr, cpu) = val;
+}
+
+static void armv7pmu_restore_pm_registers(void *hcpu)
+{
+	u32 val;
+	u32 cpu = (int)hcpu;
+
+	val = per_cpu(armv7_pm_pmuserenr, cpu);
+	if (val != 0)
+		/* Restore PMUSERENR */
+		asm volatile("mcr p15, 0, %0, c9, c14, 0" : : "r" (val));
+}
+
 static struct arm_pmu armv7pmu = {
 	.handle_irq		= armv7pmu_handle_irq,
 	.enable			= armv7pmu_enable_event,
@@ -1249,6 +1272,8 @@
 	.stop			= armv7pmu_stop,
 	.reset			= armv7pmu_reset,
 	.max_period		= (1LLU << 32) - 1,
+	.save_pm_registers	= armv7pmu_save_pm_registers,
+	.restore_pm_registers	= armv7pmu_restore_pm_registers,
 };
 
 static u32 __init armv7_read_num_pmnc_events(void)
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index 3c5ddc5..1336ec3 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -1555,6 +1555,8 @@
 	},
 };
 
+static DEFINE_CLK_MEASURE(wcnss_m_clk);
+
 #ifdef CONFIG_DEBUG_FS
 struct measure_mux_entry {
 	struct clk *c;
@@ -1610,6 +1612,7 @@
 	{ &pnoc_clk.c, GCC_BASE, 0x010},
 	{ &snoc_clk.c, GCC_BASE, 0x000},
 	{ &cnoc_clk.c, GCC_BASE, 0x008},
+	{ &wcnss_m_clk, GCC_BASE, 0x0198},
 	/*
 	 * measure the gcc_bimc_kpss_axi_clk instead to account for the DDR
 	 * rate being gcc_bimc_clk/2.
@@ -3134,6 +3137,10 @@
 	CLK_LOOKUP("apc3_m_clk", apc3_m_clk, ""),
 	CLK_LOOKUP("l2_m_clk", l2_m_clk, ""),
 
+	/* Measure clocks for WCNSS */
+	CLK_LOOKUP("measure",   measure_clk.c, "fb000000.qcom,wcnss-wlan"),
+	CLK_LOOKUP("wcnss_debug", wcnss_m_clk, "fb000000.qcom,wcnss-wlan"),
+
 	/* LPM Resources */
 	CLK_LOOKUP("xo",          cxo_lpm_clk.c, "fc4281d0.qcom,mpm"),
 
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index c7bf92c..d327d25 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -527,6 +527,7 @@
 static DEFINE_CLK_MEASURE(apc2_m_clk);
 static DEFINE_CLK_MEASURE(apc3_m_clk);
 static DEFINE_CLK_MEASURE(l2_m_clk);
+static DEFINE_CLK_MEASURE(wcnss_m_clk);
 
 #define APCS_SH_PLL_MODE        0x000
 #define APCS_SH_PLL_L_VAL       0x004
@@ -2509,6 +2510,7 @@
 	{                   &bimc_clk.c, GCC_BASE, 0x0155},
 	{          &gcc_bimc_smmu_clk.c, GCC_BASE, 0x015e},
 	{       &gcc_lpass_q6_axi_clk.c, GCC_BASE, 0x0160},
+	{                  &wcnss_m_clk, GCC_BASE, 0x0198},
 
 	{     &mmssnoc_ahb_clk.c, MMSS_BASE, 0x0001},
 	{   &mmss_misc_ahb_clk.c, MMSS_BASE, 0x0003},
@@ -3118,6 +3120,9 @@
 	CLK_LOOKUP("measure_clk", apc3_m_clk, ""),
 	CLK_LOOKUP("measure_clk",   l2_m_clk, ""),
 
+	CLK_LOOKUP("measure",   measure_clk.c, "fb000000.qcom,wcnss-wlan"),
+	CLK_LOOKUP("wcnss_debug", wcnss_m_clk, "fb000000.qcom,wcnss-wlan"),
+
 	CLK_LOOKUP("xo",     cxo_wlan_clk.c, "fb000000.qcom,wcnss-wlan"),
 	CLK_LOOKUP("rf_clk",       cxo_a1.c, "fb000000.qcom,wcnss-wlan"),
 
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 6ae909b..5ef31c3 100755
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -4438,6 +4438,7 @@
 static DEFINE_CLK_MEASURE(krait1_m_clk);
 static DEFINE_CLK_MEASURE(krait2_m_clk);
 static DEFINE_CLK_MEASURE(krait3_m_clk);
+static DEFINE_CLK_MEASURE(wcnss_m_clk);
 
 #ifdef CONFIG_DEBUG_FS
 
@@ -4538,6 +4539,7 @@
 	{&pnoc_clk.c,                           GCC_BASE, 0x0010},
 	{&snoc_clk.c,                           GCC_BASE, 0x0000},
 	{&bimc_clk.c,                           GCC_BASE, 0x0155},
+	{&wcnss_m_clk,                          GCC_BASE, 0x0198},
 	{&mmss_mmssnoc_axi_clk.c,		MMSS_BASE, 0x0004},
 	{&ocmemnoc_clk.c,			MMSS_BASE, 0x0007},
 	{&ocmemcx_ocmemnoc_clk.c,		MMSS_BASE, 0x0009},
@@ -5054,6 +5056,9 @@
 	CLK_LOOKUP("sleep_clk", gcc_usb2b_phy_sleep_clk.c, "msm_ehci_host"),
 	CLK_LOOKUP("pwm_clk", div_clk2.c, "0-0048"),
 
+	CLK_LOOKUP("measure",   measure_clk.c, "fb000000.qcom,wcnss-wlan"),
+	CLK_LOOKUP("wcnss_debug", wcnss_m_clk, "fb000000.qcom,wcnss-wlan"),
+
 	/* Multimedia clocks */
 	CLK_LOOKUP("bus_clk_src", axi_clk_src.c, ""),
 	CLK_LOOKUP("bus_clk", mmss_mmssnoc_axi_clk.c, ""),
diff --git a/arch/arm/mach-msm/clock-krait-8974.c b/arch/arm/mach-msm/clock-krait-8974.c
index 24fe303..4f133fc 100644
--- a/arch/arm/mach-msm/clock-krait-8974.c
+++ b/arch/arm/mach-msm/clock-krait-8974.c
@@ -414,7 +414,7 @@
 };
 
 static void get_krait_bin_format_b(struct platform_device *pdev,
-					int *speed, int *pvs, int *ver)
+					int *speed, int *pvs, int *pvs_ver)
 {
 	u32 pte_efuse, redundant_sel;
 	struct resource *res;
@@ -422,7 +422,7 @@
 
 	*speed = 0;
 	*pvs = 0;
-	*ver = 0;
+	*pvs_ver = 0;
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "efuse");
 	if (!res) {
@@ -443,7 +443,7 @@
 	*speed = pte_efuse & 0x7;
 	/* 4 bits of PVS are in efuse register bits 31, 8-6. */
 	*pvs = ((pte_efuse >> 28) & 0x8) | ((pte_efuse >> 6) & 0x7);
-	*ver = (pte_efuse >> 4) & 0x3;
+	*pvs_ver = (pte_efuse >> 4) & 0x3;
 
 	switch (redundant_sel) {
 	case 1:
@@ -471,7 +471,7 @@
 		*pvs = 0;
 	}
 
-	dev_info(&pdev->dev, "PVS version: %d\n", *ver);
+	dev_info(&pdev->dev, "PVS version: %d\n", *pvs_ver);
 
 	devm_iounmap(&pdev->dev, base);
 }
@@ -585,12 +585,16 @@
 	}
 }
 
+static char table_name[] = "qcom,speedXX-pvsXX-bin-vXX";
+module_param_string(table_name, table_name, sizeof(table_name), S_IRUGO);
+static unsigned int pvs_config_ver;
+module_param(pvs_config_ver, uint, S_IRUGO);
+
 static int clock_krait_8974_driver_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct clk *c;
-	int speed, pvs, ver, rows, cpu;
-	char prop_name[] = "qcom,speedXX-pvsXX-bin-vXX";
+	int speed, pvs, pvs_ver, config_ver, rows, cpu;
 	unsigned long *freq, cur_rate, aux_rate;
 	int *uv, *ua;
 	u32 *dscr, vco_mask, config_val;
@@ -673,15 +677,22 @@
 	if (!ret)
 		hdata.user_vco_mask = vco_mask;
 
-	get_krait_bin_format_b(pdev, &speed, &pvs, &ver);
-	snprintf(prop_name, ARRAY_SIZE(prop_name),
-			"qcom,speed%d-pvs%d-bin-v%d", speed, pvs, ver);
+	ret = of_property_read_u32(dev->of_node, "qcom,pvs-config-ver",
+			&config_ver);
+	if (!ret) {
+		pvs_config_ver = config_ver;
+		dev_info(&pdev->dev, "PVS config version: %d\n", config_ver);
+	}
 
-	rows = parse_tbl(dev, prop_name, 3,
+	get_krait_bin_format_b(pdev, &speed, &pvs, &pvs_ver);
+	snprintf(table_name, ARRAY_SIZE(table_name),
+			"qcom,speed%d-pvs%d-bin-v%d", speed, pvs, pvs_ver);
+
+	rows = parse_tbl(dev, table_name, 3,
 			(u32 **) &freq, (u32 **) &uv, (u32 **) &ua);
 	if (rows < 0) {
 		/* Fall back to most conservative PVS table */
-		dev_err(dev, "Unable to load voltage plan %s!\n", prop_name);
+		dev_err(dev, "Unable to load voltage plan %s!\n", table_name);
 		ret = parse_tbl(dev, "qcom,speed0-pvs0-bin-v0", 3,
 				(u32 **) &freq, (u32 **) &uv, (u32 **) &ua);
 		if (ret < 0) {
diff --git a/arch/arm/mach-msm/clock-mdss-8974.c b/arch/arm/mach-msm/clock-mdss-8974.c
index d1b1885..3ea719f 100644
--- a/arch/arm/mach-msm/clock-mdss-8974.c
+++ b/arch/arm/mach-msm/clock-mdss-8974.c
@@ -151,6 +151,7 @@
 
 #define PLL_POLL_MAX_READS	10
 #define PLL_POLL_TIMEOUT_US	50
+#define SEQ_M_MAX_COUNTER	7
 
 static long vco_cached_rate;
 static unsigned char *mdss_dsi_base;
@@ -1034,12 +1035,12 @@
 static void dsi_pll_toggle_lock_detect(void)
 {
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_LKDET_CFG2,
-		0x05);
+		0x0d);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_LKDET_CFG2,
-		0x04);
+		0x0c);
 	udelay(1);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_LKDET_CFG2,
-		0x05);
+		0x0d);
 }
 
 static int dsi_pll_lock_status(void)
@@ -1093,24 +1094,25 @@
 	 * the updates to take effect. These delays are necessary for the
 	 * PLL to successfully lock
 	 */
+	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_CAL_CFG1, 0x34);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01);
 	udelay(200);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05);
 	udelay(200);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
-	udelay(1000);
+	udelay(600);
 
 	pll_locked = dsi_pll_toggle_lock_detect_and_check_status();
-	for (i = 0; (i < 4) && !pll_locked; i++) {
+	for (i = 0; (i < SEQ_M_MAX_COUNTER) && !pll_locked; i++) {
+		DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_PWRGEN_CFG,
+			0x00);
+		udelay(50);
 		DSS_REG_W(mdss_dsi_base,
-			DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x07);
-		if (i != 0)
-			DSS_REG_W(mdss_dsi_base,
-				DSI_0_PHY_PLL_UNIPHY_PLL_CAL_CFG1, 0x34);
-		udelay(1);
+			DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05);
+		udelay(100);
 		DSS_REG_W(mdss_dsi_base,
 			DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
-		udelay(1000);
+		udelay(600);
 		pll_locked = dsi_pll_toggle_lock_detect_and_check_status();
 	}
 
@@ -1134,6 +1136,8 @@
 	 * the updates to take effect. These delays are necessary for the
 	 * PLL to successfully lock
 	 */
+	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_PWRGEN_CFG, 0x00);
+	udelay(50);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01);
 	udelay(200);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05);
@@ -1145,7 +1149,7 @@
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x07);
 	udelay(200);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
-	udelay(1000);
+	udelay(600);
 
 	pll_locked = dsi_pll_toggle_lock_detect_and_check_status();
 	pr_debug("%s: PLL status = %s\n", __func__,
@@ -1165,6 +1169,8 @@
 	 * the updates to take effect. These delays are necessary for the
 	 * PLL to successfully lock
 	 */
+	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_PWRGEN_CFG, 0x00);
+	udelay(50);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01);
 	udelay(200);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05);
@@ -1174,7 +1180,7 @@
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0d);
 	udelay(200);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
-	udelay(1000);
+	udelay(600);
 
 	pll_locked = dsi_pll_toggle_lock_detect_and_check_status();
 	pr_debug("%s: PLL status = %s\n", __func__,
@@ -1194,12 +1200,14 @@
 	 * the updates to take effect. These delays are necessary for the
 	 * PLL to successfully lock
 	 */
+	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_PWRGEN_CFG, 0x00);
+	udelay(50);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01);
 	udelay(200);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05);
 	udelay(200);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
-	udelay(1000);
+	udelay(600);
 
 	pll_locked = dsi_pll_toggle_lock_detect_and_check_status();
 	pr_debug("%s: PLL status = %s\n", __func__,
@@ -1219,6 +1227,8 @@
 	 * the updates to take effect. These delays are necessary for the
 	 * PLL to successfully lock
 	 */
+	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_PWRGEN_CFG, 0x00);
+	udelay(50);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01);
 	udelay(200);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05);
@@ -1226,7 +1236,7 @@
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0d);
 	udelay(1);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
-	udelay(1000);
+	udelay(600);
 
 	pll_locked = dsi_pll_toggle_lock_detect_and_check_status();
 	pr_debug("%s: PLL status = %s\n", __func__,
@@ -1258,10 +1268,10 @@
 	for (i = 0; i < 3; i++) {
 		/* DSI Uniphy lock detect setting */
 		DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_LKDET_CFG2,
-			0x04);
+			0x0c);
 		udelay(100);
 		DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_LKDET_CFG2,
-			0x05);
+			0x0d);
 		udelay(500);
 		/* poll for PLL ready status */
 		max_reads = 5;
@@ -1459,7 +1469,7 @@
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_CHGPUMP_CFG, 0x02);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_CAL_CFG3, 0x2b);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_CAL_CFG4, 0x66);
-	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_LKDET_CFG2, 0x05);
+	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_LKDET_CFG2, 0x0d);
 
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_SDM_CFG1,
 		(u32)(sdm_cfg1 & 0xff));
@@ -1478,7 +1488,7 @@
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_VCOLPF_CFG, 0x71);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_SDM_CFG0,
 		(u32)sdm_cfg0);
-	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_CAL_CFG0, 0x0a);
+	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_CAL_CFG0, 0x12);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_CAL_CFG6, 0x30);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_CAL_CFG7, 0x00);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_CAL_CFG8, 0x60);
@@ -1640,13 +1650,14 @@
 	.ref_clk_rate = 19200000,
 	.min_rate = 350000000,
 	.max_rate = 750000000,
-	.pll_en_seq_cnt = 6,
+	.pll_en_seq_cnt = 7,
 	.pll_enable_seqs[0] = dsi_pll_enable_seq_m,
-	.pll_enable_seqs[1] = dsi_pll_enable_seq_d,
+	.pll_enable_seqs[1] = dsi_pll_enable_seq_m,
 	.pll_enable_seqs[2] = dsi_pll_enable_seq_d,
-	.pll_enable_seqs[3] = dsi_pll_enable_seq_f1,
-	.pll_enable_seqs[4] = dsi_pll_enable_seq_c,
-	.pll_enable_seqs[5] = dsi_pll_enable_seq_e,
+	.pll_enable_seqs[3] = dsi_pll_enable_seq_d,
+	.pll_enable_seqs[4] = dsi_pll_enable_seq_f1,
+	.pll_enable_seqs[5] = dsi_pll_enable_seq_c,
+	.pll_enable_seqs[6] = dsi_pll_enable_seq_e,
 	.lpfr_lut_size = 10,
 	.lpfr_lut = (struct lpfr_cfg[]){
 		{479500000, 8},
diff --git a/arch/arm/mach-msm/include/mach/msm-krait-l2-accessors.h b/arch/arm/mach-msm/include/mach/msm-krait-l2-accessors.h
index a35ff4d..45d000b 100644
--- a/arch/arm/mach-msm/include/mach/msm-krait-l2-accessors.h
+++ b/arch/arm/mach-msm/include/mach/msm-krait-l2-accessors.h
@@ -2,7 +2,7 @@
 #define __ASM_ARCH_MSM_MSM_KRAIT_L2_ACCESSORS_H
 
 /*
- * Copyright (c) 2011,2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2013 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -14,6 +14,55 @@
  * GNU General Public License for more details.
  */
 
+#define MAX_L2_PERIOD		((1ULL << 32) - 1)
+#define MAX_KRAIT_L2_CTRS	10
+
+#define PMCR_NUM_EV_SHIFT	11
+#define PMCR_NUM_EV_MASK	0x1f
+
+#define L2_EVT_MASK		0xfffff
+
+#define L2_SLAVE_EV_PREFIX	4
+#define L2_TRACECTR_PREFIX	5
+
+#define L2PMCCNTR		0x409
+#define L2PMCCNTCR		0x408
+#define L2PMCCNTSR		0x40A
+#define L2CYCLE_CTR_BIT		31
+#define L2CYCLE_CTR_RAW_CODE	0xfe
+
+#define L2PMOVSR	0x406
+
+#define L2PMCR			0x400
+#define L2PMCR_RESET_ALL	0x6
+#define L2PMCR_GLOBAL_ENABLE	0x1
+#define L2PMCR_GLOBAL_DISABLE	0x0
+
+#define L2PMCNTENSET	0x403
+#define L2PMCNTENCLR	0x402
+
+#define L2PMINTENSET	0x405
+#define L2PMINTENCLR	0x404
+
+#define IA_L2PMXEVCNTCR_BASE	0x420
+#define IA_L2PMXEVTYPER_BASE	0x424
+#define IA_L2PMRESX_BASE	0x410
+#define IA_L2PMXEVFILTER_BASE	0x423
+#define IA_L2PMXEVCNTR_BASE	0x421
+
+/* event format is -e rsRCCG See get_event_desc() */
+
+#define EVENT_PREFIX_MASK	0xf0000
+#define EVENT_REG_MASK		0x0f000
+#define EVENT_GROUPSEL_MASK	0x0000f
+#define EVENT_GROUPCODE_MASK	0x00ff0
+
+#define EVENT_PREFIX_SHIFT		16
+#define EVENT_REG_SHIFT			12
+#define EVENT_GROUPCODE_SHIFT		4
+
+#define RESRX_VALUE_EN	0x80000000
+
 #ifdef CONFIG_ARCH_MSM_KRAIT
 extern void set_l2_indirect_reg(u32 reg_addr, u32 val);
 extern u32 get_l2_indirect_reg(u32 reg_addr);
diff --git a/arch/arm/mach-msm/include/mach/qseecomi.h b/arch/arm/mach-msm/include/mach/qseecomi.h
index 688dea0..222a171 100644
--- a/arch/arm/mach-msm/include/mach/qseecomi.h
+++ b/arch/arm/mach-msm/include/mach/qseecomi.h
@@ -18,13 +18,15 @@
 
 #define QSEECOM_KEY_ID_SIZE   32
 
-#define	QSEOS_RESULT_FAIL_LOAD_KS         -57
-#define	QSEOS_RESULT_FAIL_SAVE_KS         -58
-#define	QSEOS_RESULT_FAIL_MAX_KEYS        -59
-#define	QSEOS_RESULT_FAIL_KEY_ID_EXISTS   -60
-#define	QSEOS_RESULT_FAIL_KEY_ID_DNE      -61
-#define	QSEOS_RESULT_FAIL_KS_OP           -62
-#define	QSEOS_RESULT_FAIL_CE_PIPE_INVALID -63
+#define QSEOS_RESULT_FAIL_UNSUPPORTED_CE_PIPE -63
+#define QSEOS_RESULT_FAIL_KS_OP               -64
+#define QSEOS_RESULT_FAIL_KEY_ID_EXISTS       -65
+#define QSEOS_RESULT_FAIL_MAX_KEYS            -66
+#define QSEOS_RESULT_FAIL_SAVE_KS             -67
+#define QSEOS_RESULT_FAIL_LOAD_KS             -68
+#define QSEOS_RESULT_FAIL_KS_ALREADY_DONE     -69
+#define QSEOS_RESULT_FAIL_KEY_ID_DNE          -70
+#define QSEOS_RESULT_FAIL_INCORRECT_PSWD      -71
 
 enum qseecom_command_scm_resp_type {
 	QSEOS_APP_ID = 0xEE01,
@@ -52,6 +54,7 @@
 	QSEOS_DELETE_KEY,
 	QSEOS_MAX_KEY_COUNT,
 	QSEOS_SET_KEY,
+	QSEOS_UPDATE_KEY_USERINFO,
 	QSEOS_CMD_MAX     = 0xEFFFFFFF
 };
 
@@ -166,6 +169,7 @@
 	uint32_t qsee_command_id;
 	uint32_t flags;
 	uint8_t key_id[QSEECOM_KEY_ID_SIZE];
+	uint8_t hash32[QSEECOM_HASH_SIZE];
 };
 
 __packed struct qseecom_key_select_ireq {
@@ -175,13 +179,23 @@
 	uint32_t pipe_type;
 	uint32_t flags;
 	uint8_t key_id[QSEECOM_KEY_ID_SIZE];
-	unsigned char hash[QSEECOM_HASH_SIZE];
+	uint8_t hash32[QSEECOM_HASH_SIZE];
 };
 
 __packed struct qseecom_key_delete_ireq {
 	uint32_t qsee_command_id;
 	uint32_t flags;
 	uint8_t key_id[QSEECOM_KEY_ID_SIZE];
+	uint8_t hash32[QSEECOM_HASH_SIZE];
+
+};
+
+__packed struct qseecom_key_userinfo_update_ireq {
+	uint32_t qsee_command_id;
+	uint32_t flags;
+	uint8_t key_id[QSEECOM_KEY_ID_SIZE];
+	uint8_t current_hash32[QSEECOM_HASH_SIZE];
+	uint8_t new_hash32[QSEECOM_HASH_SIZE];
 };
 
 __packed struct qseecom_key_max_count_query_ireq {
@@ -192,10 +206,5 @@
 	uint32_t max_key_count;
 };
 
-struct key_id_info {
-	uint32_t	ce_hw;
-	uint32_t	pipe;
-	bool		flags;
-};
 
 #endif /* __QSEECOMI_H_ */
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index 6b3d590..aeb32f8 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -44,6 +44,7 @@
 #define of_board_is_qrd()	of_machine_is_compatible("qcom,qrd")
 #define of_board_is_xpm()	of_machine_is_compatible("qcom,xpm")
 #define of_board_is_skuf()	of_machine_is_compatible("qcom,skuf")
+#define of_board_is_sbc()	of_machine_is_compatible("qcom,sbc")
 
 #define machine_is_msm8974()	of_machine_is_compatible("qcom,msm8974")
 #define machine_is_msm9625()	of_machine_is_compatible("qcom,msm9625")
@@ -75,6 +76,7 @@
 #define of_board_is_qrd()		0
 #define of_board_is_xpm()		0
 #define of_board_is_skuf()		0
+#define of_board_is_sbc()		0
 
 #define machine_is_msm8974()		0
 #define machine_is_msm9625()		0
diff --git a/arch/arm/mach-msm/msm-pm.c b/arch/arm/mach-msm/msm-pm.c
index fab86d3..865cd0a 100644
--- a/arch/arm/mach-msm/msm-pm.c
+++ b/arch/arm/mach-msm/msm-pm.c
@@ -777,7 +777,7 @@
 		return 0;
 	if (!msm_pm_slp_sts[cpu].base_addr)
 		return 0;
-	while (timeout--) {
+	while (1) {
 		/*
 		 * Check for the SPM of the core being hotplugged to set
 		 * its sleep state.The SPM sleep state indicates that the
@@ -788,10 +788,9 @@
 		if (acc_sts & msm_pm_slp_sts[cpu].mask)
 			return 0;
 		udelay(100);
+		WARN(++timeout == 20, "CPU%u didn't collapse in 2 ms\n", cpu);
 	}
 
-	pr_info("%s(): Timed out waiting for CPU %u SPM to enter sleep state",
-		__func__, cpu);
 	return -EBUSY;
 }
 
diff --git a/arch/arm/mach-msm/perf_debug.c b/arch/arm/mach-msm/perf_debug.c
index 28d8e42..d493e8b 100644
--- a/arch/arm/mach-msm/perf_debug.c
+++ b/arch/arm/mach-msm/perf_debug.c
@@ -35,6 +35,16 @@
 	"10 Perf: Fix counts across power collapse\n"
 	"11 ARM: dts: msm: add perf-events support for msm8x10, msm8x12\n"
 	"12 Perf: Make per-process counters configurable\n"
+	"13 msm: perf: Add L2 support for tracecounters\n"
+	"14 Perf: keep events across hotplug\n"
+	"15 Perf: bring CPU online if needed when disabling irq\n"
+	"16 Perf: Support sw events across hotplug\n"
+	"17 msm: perf: initialise krait perf L2 counter enables\n"
+	"18 msm: perf: clean up duplicate constraint events\n"
+	"19 Perf: Make per-process counters cumulative\n"
+	"20 Perf: Fix PID for tracepoints\n"
+	"21 Perf: preserve registers across hotplug\n"
+	"22 msm: perf: fix formatting of trace entry\n"
 ;
 
 static ssize_t desc_read(struct file *fp, char __user *buf,
diff --git a/arch/arm/mach-msm/perf_event_msm_krait_l2.c b/arch/arm/mach-msm/perf_event_msm_krait_l2.c
index ad34457..c9e2b8f 100644
--- a/arch/arm/mach-msm/perf_event_msm_krait_l2.c
+++ b/arch/arm/mach-msm/perf_event_msm_krait_l2.c
@@ -18,54 +18,6 @@
 
 #include <mach/msm-krait-l2-accessors.h>
 
-#define MAX_L2_PERIOD	((1ULL << 32) - 1)
-#define MAX_KRAIT_L2_CTRS 10
-
-#define PMCR_NUM_EV_SHIFT 11
-#define PMCR_NUM_EV_MASK 0x1f
-
-#define L2_EVT_MASK 0xfffff
-
-#define L2_SLAVE_EV_PREFIX 4
-
-#define L2PMCCNTR 0x409
-#define L2PMCCNTCR 0x408
-#define L2PMCCNTSR 0x40A
-#define L2CYCLE_CTR_BIT 31
-#define L2CYCLE_CTR_RAW_CODE 0xfe
-
-#define L2PMOVSR	0x406
-
-#define L2PMCR	0x400
-#define L2PMCR_RESET_ALL	0x6
-#define L2PMCR_GLOBAL_ENABLE	0x1
-#define L2PMCR_GLOBAL_DISABLE	0x0
-
-#define L2PMCNTENSET	0x403
-#define L2PMCNTENCLR	0x402
-
-#define L2PMINTENSET	0x405
-#define L2PMINTENCLR	0x404
-
-#define IA_L2PMXEVCNTCR_BASE	0x420
-#define IA_L2PMXEVTYPER_BASE	0x424
-#define IA_L2PMRESX_BASE	0x410
-#define IA_L2PMXEVFILTER_BASE	0x423
-#define IA_L2PMXEVCNTR_BASE	0x421
-
-/* event format is -e rsRCCG See get_event_desc() */
-
-#define EVENT_PREFIX_MASK	0xf0000
-#define EVENT_REG_MASK		0x0f000
-#define EVENT_GROUPSEL_MASK	0x0000f
-#define	EVENT_GROUPCODE_MASK	0x00ff0
-
-#define EVENT_PREFIX_SHIFT	16
-#define EVENT_REG_SHIFT		12
-#define EVENT_GROUPCODE_SHIFT	4
-
-#define	RESRX_VALUE_EN	0x80000000
-
 /*
  * The L2 PMU is shared between all CPU's, so protect
  * its bitmap access.
@@ -197,13 +149,16 @@
 	set_l2_indirect_reg(filter_reg, filter_val);
 }
 
-static void set_evfilter_sys_mode(int ctr, unsigned int is_slv)
+static void set_evfilter_sys_mode(int ctr, unsigned int is_slv, int cpu,
+		unsigned int is_tracectr)
 {
 	u32 filter_reg = (ctr * 16) + IA_L2PMXEVFILTER_BASE;
 	u32 filter_val = l2_orig_filter_prefix | 0xf;
 
-	if (is_slv)
+	if (is_slv == 1)
 		filter_val = l2_slv_filter_prefix;
+	if (is_tracectr == 1)
+		filter_val = l2_orig_filter_prefix | 1 << cpu;
 
 	set_l2_indirect_reg(filter_reg, filter_val);
 }
@@ -277,6 +232,7 @@
 	struct event_desc evdesc;
 	unsigned long iflags;
 	unsigned int is_slv = 0;
+	unsigned int is_tracectr = 0;
 	unsigned int evt_prefix;
 
 	raw_spin_lock_irqsave(&krait_l2_pmu_hw_events.pmu_lock, iflags);
@@ -290,6 +246,8 @@
 
 	if (evt_prefix == L2_SLAVE_EV_PREFIX)
 		is_slv = 1;
+	else if (evt_prefix == L2_TRACECTR_PREFIX)
+		is_tracectr = 1;
 
 	set_evcntcr(idx);
 
@@ -305,7 +263,7 @@
 	if (cpu < 0)
 		set_evfilter_task_mode(idx, is_slv);
 	else
-		set_evfilter_sys_mode(idx, is_slv);
+		set_evfilter_sys_mode(idx, is_slv, cpu, is_tracectr);
 
 out:
 	enable_intenset(idx);
@@ -456,6 +414,7 @@
 static int msm_l2_test_set_ev_constraint(struct perf_event *event)
 {
 	u32 evt_type = event->attr.config & L2_EVT_MASK;
+	u8 evt_prefix = (evt_type & EVENT_PREFIX_MASK) >> EVENT_PREFIX_SHIFT;
 	u8 reg   = (evt_type & 0x0F000) >> 12;
 	u8 group = evt_type & 0x0000F;
 	u8 code = (evt_type & 0x00FF0) >> 4;
@@ -464,6 +423,8 @@
 	u64 bitmap_t;
 	u32 shift_idx;
 
+	if (evt_prefix == L2_TRACECTR_PREFIX)
+		return err;
 	/*
 	 * Cycle counter collision is detected in
 	 * get_event_idx().
@@ -496,8 +457,10 @@
 			 * This sets the event OFF on all but one
 			 * CPU.
 			 */
-			if (!(event->cpu < 0))
+			if (!(event->cpu < 0)) {
 				event->state = PERF_EVENT_STATE_OFF;
+				event->attr.constraint_duplicate = 1;
+			}
 	}
 out:
 	raw_spin_unlock_irqrestore(&l2_pmu_constraints.lock, flags);
@@ -507,12 +470,15 @@
 static int msm_l2_clear_ev_constraint(struct perf_event *event)
 {
 	u32 evt_type = event->attr.config & L2_EVT_MASK;
+	u8 evt_prefix = (evt_type & EVENT_PREFIX_MASK) >> EVENT_PREFIX_SHIFT;
 	u8 reg   = (evt_type & 0x0F000) >> 12;
 	u8 group =  evt_type & 0x0000F;
 	unsigned long flags;
 	u64 bitmap_t;
 	u32 shift_idx;
 
+	if (evt_prefix == L2_TRACECTR_PREFIX)
+		return 1;
 	raw_spin_lock_irqsave(&l2_pmu_constraints.lock, flags);
 
 	shift_idx = ((reg * 4) + group);
@@ -592,6 +558,8 @@
 
 static int __init register_krait_l2_pmu_driver(void)
 {
+	int i;
+
 	/* Reset all ctrs */
 	set_l2_indirect_reg(L2PMCR, L2PMCR_RESET_ALL);
 
@@ -613,6 +581,11 @@
 	/* Avoid spurious interrupt if any */
 	get_reset_pmovsr();
 
+	/* Clear counter enables */
+	disable_counter(l2_cycle_ctr_idx);
+	for (i = 0; i < total_l2_ctrs; i++)
+		disable_counter(i);
+
 	return platform_driver_register(&krait_l2_pmu_driver);
 }
 device_initcall(register_krait_l2_pmu_driver);
diff --git a/arch/arm/mach-msm/perf_trace_counters.c b/arch/arm/mach-msm/perf_trace_counters.c
index 8fa73ae..f847b5d 100644
--- a/arch/arm/mach-msm/perf_trace_counters.c
+++ b/arch/arm/mach-msm/perf_trace_counters.c
@@ -17,21 +17,48 @@
 
 static unsigned int tp_pid_state;
 
+DEFINE_PER_CPU(u32, previous_ccnt);
+DEFINE_PER_CPU(u32[NUM_L1_CTRS], previous_l1_cnts);
+DEFINE_PER_CPU(u32[NUM_L2_PERCPU], previous_l2_cnts);
+DEFINE_PER_CPU(u32, old_pid);
+/* Reset per_cpu variables that store counter values uppn CPU hotplug */
+static int tracectr_cpu_hotplug_notifier(struct notifier_block *self,
+				    unsigned long action, void *hcpu)
+{
+	int ret = NOTIFY_OK;
+	int cpu = (int)hcpu;
+	int i;
+
+	if ((action & (~CPU_TASKS_FROZEN)) == CPU_UP_PREPARE) {
+		per_cpu(previous_ccnt, cpu) = 0;
+		for (i = 0; i < NUM_L1_CTRS; i++)
+			per_cpu(previous_l1_cnts[i], cpu) = 0;
+		for (i = 0; i < NUM_L2_PERCPU; i++)
+			per_cpu(previous_l2_cnts[i], cpu) = 0;
+	}
+	return ret;
+}
+
+static struct notifier_block tracectr_cpu_hotplug_notifier_block = {
+	.notifier_call = tracectr_cpu_hotplug_notifier,
+};
+
 static int tracectr_notifier(struct notifier_block *self, unsigned long cmd,
 		void *v)
 {
-	static int old_pid = -1;
 	struct thread_info *thread = v;
 	int current_pid;
+	u32 cpu = smp_processor_id();
 
 	if (cmd != THREAD_NOTIFY_SWITCH)
-		return old_pid;
+		return -EFAULT;
 
 	current_pid = thread->task->pid;
-	if (old_pid != -1)
-		trace_sched_switch_with_ctrs(old_pid, current_pid);
-	old_pid = current_pid;
-	return old_pid;
+	if (per_cpu(old_pid, cpu) != -1)
+		trace_sched_switch_with_ctrs(per_cpu(old_pid, cpu),
+						current_pid);
+	per_cpu(old_pid, cpu) = current_pid;
+	return NOTIFY_OK;
 }
 
 static struct notifier_block tracectr_notifier_block = {
@@ -102,6 +129,7 @@
 	struct dentry *dir;
 	struct dentry *file;
 	unsigned int value = 1;
+	int cpu;
 
 	dir = debugfs_create_dir("perf_debug_tp", NULL);
 	if (!dir)
@@ -112,6 +140,15 @@
 		debugfs_remove(dir);
 		return -ENOMEM;
 	}
+	register_cpu_notifier(&tracectr_cpu_hotplug_notifier_block);
+	for_each_possible_cpu(cpu)
+		per_cpu(old_pid, cpu) = -1;
+	return 0;
+}
+
+int __exit exit_tracecounters(void)
+{
+	unregister_cpu_notifier(&tracectr_cpu_hotplug_notifier_block);
 	return 0;
 }
 late_initcall(init_tracecounters);
diff --git a/arch/arm/mach-msm/perf_trace_counters.h b/arch/arm/mach-msm/perf_trace_counters.h
index 8f77bad..fce176e 100644
--- a/arch/arm/mach-msm/perf_trace_counters.h
+++ b/arch/arm/mach-msm/perf_trace_counters.h
@@ -19,14 +19,21 @@
 /* Ctr index for PMCNTENSET/CLR */
 #define CC 0x80000000
 #define C0 0x1
-#define C1 0x10
-#define C2 0x100
-#define C3 0x1000
-
+#define C1 0x2
+#define C2 0x4
+#define C3 0x8
+#define C_ALL (CC | C0 | C1 | C2 | C3)
+#define NUM_L1_CTRS 4
+#define NUM_L2_PERCPU 2
 
 #include <linux/sched.h>
+#include <linux/cpumask.h>
 #include <linux/tracepoint.h>
+#include <mach/msm-krait-l2-accessors.h>
 
+DECLARE_PER_CPU(u32, previous_ccnt);
+DECLARE_PER_CPU(u32[NUM_L1_CTRS], previous_l1_cnts);
+DECLARE_PER_CPU(u32[NUM_L2_PERCPU], previous_l2_cnts);
 TRACE_EVENT(sched_switch_with_ctrs,
 
 		TP_PROTO(pid_t prev, pid_t next),
@@ -41,82 +48,112 @@
 			__field(u32, ctr1)
 			__field(u32, ctr2)
 			__field(u32, ctr3)
+			__field(u32, lctr0)
+			__field(u32, lctr1)
 		),
 
 		TP_fast_assign(
+			u32 cpu = smp_processor_id();
+			u32 idx;
+			u32 i;
+			u32 counter_reg;
+			u32 val;
+			u32 cnten_val;
+			u32 num_l2ctrs;
+			u32 num_cores = nr_cpu_ids;
+			u32 total_ccnt = 0;
+			u32 total_cnt = 0;
+			u32 delta_l1_cnts[NUM_L1_CTRS];
+			u32 delta_l2_cnts[NUM_L2_PERCPU];
 			__entry->old_pid	= prev;
 			__entry->new_pid	= next;
 
-			/* cycle counter */
-			/* Disable */
-			asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r"(CC));
-			/* Read value */
-			asm volatile("mrc p15, 0, %0, c9, c13, 0"
-				: "=r"(__entry->cctr));
-			/* Reset */
-			asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r"(0));
-			/* Enable */
-			asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r"(CC));
+			val = get_l2_indirect_reg(L2PMCR);
+			num_l2ctrs = ((val >> 11) & 0x1f) + 1;
 
-			/* ctr 0 */
-			/* Disable */
-			asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r"(C0));
-			/* Select */
-			asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r"(0));
-			/* Read value */
-			asm volatile("mrc p15, 0, %0, c9, c13, 2"
-					: "=r"(__entry->ctr0));
-			/* Reset */
-			asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r"(0));
-			/* Enable */
-			asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r"(C0));
+			/* Read PMCNTENSET */
+			asm volatile("mrc p15, 0, %0, c9, c12, 1"
+						: "=r"(cnten_val));
+			/* Disable all the counters that were enabled */
+			asm volatile("mcr p15, 0, %0, c9, c12, 2"
+					: : "r"(cnten_val));
+			if (cnten_val & CC) {
+				/* Read value */
+				asm volatile("mrc p15, 0, %0, c9, c13, 0"
+					: "=r"(total_ccnt));
+				__entry->cctr = total_ccnt -
+					per_cpu(previous_ccnt, cpu);
+				per_cpu(previous_ccnt, cpu) = total_ccnt;
+			}
+			for (i = 0; i < NUM_L1_CTRS; i++) {
+				if (cnten_val & (1 << i)) {
+					/* Select */
+					asm volatile(
+						"mcr p15, 0, %0, c9, c12, 5"
+						: : "r"(i));
+					/* Read value */
+					asm volatile(
+						"mrc p15, 0, %0, c9, c13, 2"
+						: "=r"(total_cnt));
 
-			/* ctr 1 */
-			/* Disable */
-			asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r"(C1));
-			/* Select */
-			asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r"(1));
-			/* Read value */
-			asm volatile("mrc p15, 0, %0, c9, c13, 2"
-					: "=r"(__entry->ctr1));
-			/* Reset */
-			asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r"(0));
-			/* Enable */
-			asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r"(C1));
+					delta_l1_cnts[i] = total_cnt -
+					  per_cpu(previous_l1_cnts[i], cpu);
+					per_cpu(previous_l1_cnts[i], cpu) =
+						total_cnt;
+				} else
+					delta_l1_cnts[i] = 0;
+			}
+			/* Enable all the counters that were disabled */
+			asm volatile("mcr p15, 0, %0, c9, c12, 1"
+					: : "r"(cnten_val));
 
-			/* ctr 2 */
-			/* Disable */
-			asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r"(C2));
-			/* Select */
-			asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r"(2));
-			/* Read value */
-			asm volatile("mrc p15, 0, %0, c9, c13, 2"
-					: "=r"(__entry->ctr2));
-			/* Reset */
-			asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r"(0));
-			/* Enable */
-			asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r"(C2));
-
-			/* ctr 3 */
-			/* Disable */
-			asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r"(C3));
-			/* Select */
-			asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r"(3));
-			/* Read value */
-			asm volatile("mrc p15, 0, %0, c9, c13, 2"
-					: "=r"(__entry->ctr3));
-			/* Reset */
-			asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r"(0));
-			/* Enable */
-			asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r"(C3));
-
+			/* L2 counters */
+			/* Assign L2 counters to cores sequentially starting
+			 * from zero. A core could have multiple L2 counters
+			 * allocated if # L2 counters is more than the # cores
+			 */
+			cnten_val = get_l2_indirect_reg(L2PMCNTENSET);
+			for (i = 0; i < NUM_L2_PERCPU; i++) {
+				idx = cpu + (num_cores * i);
+				if (idx < num_l2ctrs &&
+						(cnten_val & (1 << idx))) {
+					/* Disable */
+					set_l2_indirect_reg(L2PMCNTENCLR,
+						(1 << idx));
+					/* L2PMEVCNTR values go from 0x421,
+					 * 0x431..
+					 * So we multiply idx by 16 to get the
+					 * counter reg value
+					 */
+					counter_reg = (idx * 16) +
+						IA_L2PMXEVCNTR_BASE;
+					total_cnt =
+					  get_l2_indirect_reg(counter_reg);
+					/* Enable */
+					set_l2_indirect_reg(L2PMCNTENSET,
+						(1 << idx));
+					delta_l2_cnts[i] = total_cnt -
+					  per_cpu(previous_l2_cnts[i], cpu);
+					per_cpu(previous_l2_cnts[i], cpu) =
+						total_cnt;
+				} else
+					delta_l2_cnts[i] = 0;
+			}
+			__entry->ctr0 = delta_l1_cnts[0];
+			__entry->ctr1 = delta_l1_cnts[1];
+			__entry->ctr2 = delta_l1_cnts[2];
+			__entry->ctr3 = delta_l1_cnts[3];
+			__entry->lctr0 = delta_l2_cnts[0];
+			__entry->lctr1 = delta_l2_cnts[1];
 		),
 
 		TP_printk("prev_pid=%d, next_pid=%d, CCNTR: %u, CTR0: %u," \
-				" CTR1: %u, CTR2: %u, CTR3: %u",
+				" CTR1: %u, CTR2: %u, CTR3: %u," \
+				" L2CTR0: %u, L2CTR1: %u",
 				__entry->old_pid, __entry->new_pid,
 				__entry->cctr, __entry->ctr0, __entry->ctr1,
-				__entry->ctr2, __entry->ctr3)
+				__entry->ctr2, __entry->ctr3,
+				__entry->lctr0, __entry->lctr1)
 );
 
 #endif
diff --git a/arch/arm/mach-msm/rpm-smd.c b/arch/arm/mach-msm/rpm-smd.c
index 54576a9..2a01a36 100644
--- a/arch/arm/mach-msm/rpm-smd.c
+++ b/arch/arm/mach-msm/rpm-smd.c
@@ -130,8 +130,7 @@
 	bool valid;
 };
 static struct rb_root tr_root = RB_ROOT;
-
-static int msm_rpm_send_smd_buffer(char *buf, int size, bool noirq);
+static int msm_rpm_send_smd_buffer(char *buf, uint32_t size, bool noirq);
 static uint32_t msm_rpm_get_next_msg_id(void);
 
 static inline unsigned int get_rsc_type(char *buf)
@@ -187,7 +186,8 @@
 static void delete_kvp(char *msg, struct kvp *d)
 {
 	struct kvp *n;
-	int dec, size;
+	int dec;
+	uint32_t size;
 
 	n = get_next_kvp(d);
 	dec = (void *)n - (void *)d;
@@ -206,7 +206,7 @@
 
 static void add_kvp(char *buf, struct kvp *n)
 {
-	int inc = sizeof(*n) + n->s;
+	uint32_t inc = sizeof(*n) + n->s;
 	BUG_ON((get_req_len(buf) + inc) > MAX_SLEEP_BUFFER);
 
 	memcpy(buf + get_buf_len(buf), n, inc);
@@ -311,7 +311,7 @@
 	}
 }
 
-int msm_rpm_smd_buffer_request(char *buf, int size, gfp_t flag)
+int msm_rpm_smd_buffer_request(char *buf, uint32_t size, gfp_t flag)
 {
 	struct slp_buf *slp;
 	static DEFINE_SPINLOCK(slp_buffer_lock);
@@ -367,7 +367,7 @@
 	pos += scnprintf(buf + pos, buflen - pos, " id = 0%x",
 			get_rsc_id(s->buf));
 	for_each_kvp(s->buf, e) {
-		int i;
+		uint32_t i;
 		char *data = get_data(e);
 
 		memcpy(ch, &e->k, sizeof(u32));
@@ -482,14 +482,17 @@
 static int msm_rpm_add_kvp_data_common(struct msm_rpm_request *handle,
 		uint32_t key, const uint8_t *data, int size, bool noirq)
 {
-	int i;
-	int data_size, msg_size;
+	uint32_t i;
+	uint32_t data_size, msg_size;
 
 	if (!handle) {
 		pr_err("%s(): Invalid handle\n", __func__);
 		return -EINVAL;
 	}
 
+	if (size < 0)
+		return  -EINVAL;
+
 	data_size = ALIGN(size, SZ_4);
 	msg_size = data_size + sizeof(struct rpm_request_header);
 
@@ -813,7 +816,7 @@
 
 static int msm_rpm_read_smd_data(char *buf)
 {
-	int pkt_sz;
+	uint32_t pkt_sz;
 	int bytes_read = 0;
 
 	pkt_sz = smd_cur_packet_size(msm_rpm_data.ch_info);
@@ -867,7 +870,8 @@
 	size_t buflen = DEBUG_PRINT_BUFFER_SIZE;
 	char name[5];
 	u32 value;
-	int i, j, prev_valid;
+	uint32_t i;
+	int j, prev_valid;
 	int valid_count = 0;
 	int pos = 0;
 
@@ -992,7 +996,7 @@
 	pos += scnprintf(buf + pos, buflen - pos, "\n");
 	printk(buf);
 }
-static int msm_rpm_send_smd_buffer(char *buf, int size, bool noirq)
+static int msm_rpm_send_smd_buffer(char *buf, uint32_t size, bool noirq)
 {
 	unsigned long flags;
 	int ret;
@@ -1027,8 +1031,9 @@
 		int msg_type, bool noirq)
 {
 	uint8_t *tmpbuff;
-	int i, ret, msg_size;
-
+	int ret;
+	uint32_t i;
+	uint32_t msg_size;
 	int req_hdr_sz, msg_hdr_sz;
 
 	if (!cdata->msg_hdr.data_len)
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index d3c311d..53e8e72 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -349,10 +349,19 @@
 	int wr_size = -ENOMEM, retry_count = 0, timer;
 	struct diag_smd_info *data = NULL;
 
-	/* For now only allow the modem to receive the message */
-	if (!smd_info || smd_info->type != SMD_CNTL_TYPE ||
-		(smd_info->peripheral != MODEM_DATA))
+	if (!smd_info || smd_info->type != SMD_CNTL_TYPE) {
+		pr_err("diag: In %s, invalid channel info, smd_info: %p type: %d\n",
+					__func__, smd_info,
+					((smd_info) ? smd_info->type : -1));
 		return;
+	}
+
+	if (smd_info->peripheral < MODEM_DATA ||
+					smd_info->peripheral > WCNSS_DATA) {
+		pr_err("diag: In %s, invalid peripheral %d\n", __func__,
+							smd_info->peripheral);
+		return;
+	}
 
 	data = &driver->smd_data[smd_info->peripheral];
 	if (!data)
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 975a42f..4605685 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1726,7 +1726,8 @@
 	memcpy(&policy->cpuinfo, &data->cpuinfo,
 				sizeof(struct cpufreq_cpuinfo));
 
-	if (policy->min > data->max || policy->max < data->min) {
+	if (policy->min > data->user_policy.max
+		|| policy->max < data->user_policy.min) {
 		ret = -EINVAL;
 		goto error_out;
 	}
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 8f7d39c..7f8b4cd 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -978,14 +978,8 @@
 			dbs_info->sample_type = DBS_SUB_SAMPLE;
 			delay = dbs_info->freq_hi_jiffies;
 		} else {
-			/* We want all CPUs to do sampling nearly on
-			 * same jiffy
-			 */
 			delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate
 				* dbs_info->rate_mult);
-
-			if (num_online_cpus() > 1)
-				delay -= jiffies % delay;
 		}
 	} else {
 		__cpufreq_driver_target(dbs_info->cur_policy,
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index a4154c1..7f6498a 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -2195,8 +2195,8 @@
 	list_del(&pbam->qlist);
 	kfree(pbam);
 
-	pce_dev->pbam = NULL;
 ret:
+	pce_dev->pbam = NULL;
 	mutex_unlock(&bam_register_lock);
 }
 
diff --git a/drivers/devfreq/governor_performance.c b/drivers/devfreq/governor_performance.c
index af2edc2..74ae3bb 100644
--- a/drivers/devfreq/governor_performance.c
+++ b/drivers/devfreq/governor_performance.c
@@ -32,13 +32,26 @@
 				unsigned int event, void *data)
 {
 	int ret = 0;
+	unsigned long freq;
 
-	if (event == DEVFREQ_GOV_START || event == DEVFREQ_GOV_RESUME) {
-		mutex_lock(&devfreq->lock);
+	mutex_lock(&devfreq->lock);
+	freq = devfreq->previous_freq;
+	switch (event) {
+	case DEVFREQ_GOV_START:
+		devfreq->profile->target(devfreq->dev.parent,
+				&freq,
+				DEVFREQ_FLAG_WAKEUP_MAXFREQ);
+		/* fall through */
+	case DEVFREQ_GOV_RESUME:
 		ret = update_devfreq(devfreq);
-		mutex_unlock(&devfreq->lock);
+		break;
+	case DEVFREQ_GOV_SUSPEND:
+		devfreq->profile->target(devfreq->dev.parent,
+				&freq,
+				DEVFREQ_FLAG_WAKEUP_MAXFREQ);
+		break;
 	}
-
+	mutex_unlock(&devfreq->lock);
 	return ret;
 }
 
diff --git a/drivers/gpu/ion/ion_heap.c b/drivers/gpu/ion/ion_heap.c
index 9d33bf4..73dd868 100644
--- a/drivers/gpu/ion/ion_heap.c
+++ b/drivers/gpu/ion/ion_heap.c
@@ -108,8 +108,7 @@
  *
  * Note that the `pages' array should be composed of all 4K pages.
  */
-int ion_heap_pages_zero(struct page **pages, int num_pages,
-				bool should_invalidate)
+int ion_heap_pages_zero(struct page **pages, int num_pages)
 {
 	int i, j, k, npages_to_vmap;
 	void *ptr = NULL;
@@ -143,19 +142,17 @@
 			return -ENOMEM;
 
 		memset(ptr, 0, npages_to_vmap * PAGE_SIZE);
-		if (should_invalidate) {
-			/*
-			 * invalidate the cache to pick up the zeroing
-			 */
-			for (k = 0; k < npages_to_vmap; k++) {
-				void *p = kmap_atomic(pages[i + k]);
-				phys_addr_t phys = page_to_phys(
-							pages[i + k]);
+		/*
+		 * invalidate the cache to pick up the zeroing
+		 */
+		for (k = 0; k < npages_to_vmap; k++) {
+			void *p = kmap_atomic(pages[i + k]);
+			phys_addr_t phys = page_to_phys(
+				pages[i + k]);
 
-				dmac_inv_range(p, p + PAGE_SIZE);
-				outer_inv_range(phys, phys + PAGE_SIZE);
-				kunmap_atomic(p);
-			}
+			dmac_inv_range(p, p + PAGE_SIZE);
+			outer_inv_range(phys, phys + PAGE_SIZE);
+			kunmap_atomic(p);
 		}
 		vunmap(ptr);
 	}
@@ -196,8 +193,7 @@
 	pages_mem->free_fn(pages_mem->pages);
 }
 
-int ion_heap_high_order_page_zero(struct page *page,
-				int order, bool should_invalidate)
+int ion_heap_high_order_page_zero(struct page *page, int order)
 {
 	int i, ret;
 	struct pages_mem pages_mem;
@@ -210,8 +206,7 @@
 	for (i = 0; i < (1 << order); ++i)
 		pages_mem.pages[i] = page + i;
 
-	ret = ion_heap_pages_zero(pages_mem.pages, npages,
-				should_invalidate);
+	ret = ion_heap_pages_zero(pages_mem.pages, npages);
 	ion_heap_free_pages_mem(&pages_mem);
 	return ret;
 }
@@ -240,8 +235,7 @@
 			pages_mem.pages[npages++] = page + j;
 	}
 
-	ret = ion_heap_pages_zero(pages_mem.pages, npages,
-				ion_buffer_cached(buffer));
+	ret = ion_heap_pages_zero(pages_mem.pages, npages);
 	ion_heap_free_pages_mem(&pages_mem);
 	return ret;
 }
diff --git a/drivers/gpu/ion/ion_page_pool.c b/drivers/gpu/ion/ion_page_pool.c
index 94f9445..cc2a36d 100644
--- a/drivers/gpu/ion/ion_page_pool.c
+++ b/drivers/gpu/ion/ion_page_pool.c
@@ -40,8 +40,7 @@
 		return NULL;
 
 	if (pool->gfp_mask & __GFP_ZERO)
-		if (ion_heap_high_order_page_zero(
-				page, pool->order, pool->should_invalidate))
+		if (ion_heap_high_order_page_zero(page, pool->order))
 			goto error_free_pages;
 
 	sg_init_table(&sg, 1);
@@ -175,8 +174,7 @@
 	return nr_freed;
 }
 
-struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order,
-	bool should_invalidate)
+struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order)
 {
 	struct ion_page_pool *pool = kmalloc(sizeof(struct ion_page_pool),
 					     GFP_KERNEL);
@@ -188,7 +186,6 @@
 	INIT_LIST_HEAD(&pool->high_items);
 	pool->gfp_mask = gfp_mask;
 	pool->order = order;
-	pool->should_invalidate = should_invalidate;
 	mutex_init(&pool->mutex);
 	plist_node_init(&pool->list, order);
 
diff --git a/drivers/gpu/ion/ion_priv.h b/drivers/gpu/ion/ion_priv.h
index aa0a9e2..c57efc1 100644
--- a/drivers/gpu/ion/ion_priv.h
+++ b/drivers/gpu/ion/ion_priv.h
@@ -234,11 +234,9 @@
 void ion_heap_unmap_kernel(struct ion_heap *, struct ion_buffer *);
 int ion_heap_map_user(struct ion_heap *, struct ion_buffer *,
 			struct vm_area_struct *);
-int ion_heap_pages_zero(struct page **pages, int num_pages,
-			bool should_invalidate);
+int ion_heap_pages_zero(struct page **pages, int num_pages);
 int ion_heap_buffer_zero(struct ion_buffer *buffer);
-int ion_heap_high_order_page_zero(struct page *page,
-				int order, bool should_invalidate);
+int ion_heap_high_order_page_zero(struct page *page, int order);
 
 /**
  * ion_heap_init_deferred_free -- initialize deferred free functionality
@@ -357,8 +355,6 @@
  * @gfp_mask:		gfp_mask to use from alloc
  * @order:		order of pages in the pool
  * @list:		plist node for list of pools
- * @should_invalidate:	whether or not the cache needs to be invalidated at
- *			page allocation time.
  *
  * Allows you to keep a pool of pre allocated pages to use from your heap.
  * Keeping a pool of pages that is ready for dma, ie any cached mapping have
@@ -374,11 +370,9 @@
 	gfp_t gfp_mask;
 	unsigned int order;
 	struct plist_node list;
-	bool should_invalidate;
 };
 
-struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order,
-	bool should_invalidate);
+struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order);
 void ion_page_pool_destroy(struct ion_page_pool *);
 void *ion_page_pool_alloc(struct ion_page_pool *);
 void ion_page_pool_free(struct ion_page_pool *, struct page *);
diff --git a/drivers/gpu/ion/ion_system_heap.c b/drivers/gpu/ion/ion_system_heap.c
index 8e885b2..be1a89c 100644
--- a/drivers/gpu/ion/ion_system_heap.c
+++ b/drivers/gpu/ion/ion_system_heap.c
@@ -355,8 +355,7 @@
  * nothing. If it succeeds you'll eventually need to use
  * ion_system_heap_destroy_pools to destroy the pools.
  */
-static int ion_system_heap_create_pools(struct ion_page_pool **pools,
-					bool should_invalidate)
+static int ion_system_heap_create_pools(struct ion_page_pool **pools)
 {
 	int i;
 	for (i = 0; i < num_orders; i++) {
@@ -365,8 +364,7 @@
 
 		if (orders[i] > 4)
 			gfp_flags = high_order_gfp_flags;
-		pool = ion_page_pool_create(gfp_flags, orders[i],
-					should_invalidate);
+		pool = ion_page_pool_create(gfp_flags, orders[i]);
 		if (!pool)
 			goto err_create_pool;
 		pools[i] = pool;
@@ -397,10 +395,10 @@
 	if (!heap->cached_pools)
 		goto err_alloc_cached_pools;
 
-	if (ion_system_heap_create_pools(heap->uncached_pools, false))
+	if (ion_system_heap_create_pools(heap->uncached_pools))
 		goto err_create_uncached_pools;
 
-	if (ion_system_heap_create_pools(heap->cached_pools, true))
+	if (ion_system_heap_create_pools(heap->cached_pools))
 		goto err_create_cached_pools;
 
 	heap->heap.shrinker.shrink = ion_system_heap_shrink;
diff --git a/drivers/gpu/msm/adreno_coresight.c b/drivers/gpu/msm/adreno_coresight.c
index 1b827ff..d0ba145 100644
--- a/drivers/gpu/msm/adreno_coresight.c
+++ b/drivers/gpu/msm/adreno_coresight.c
@@ -55,7 +55,12 @@
 int adreno_coresight_enable(struct coresight_device *csdev)
 {
 	struct kgsl_device *device = dev_get_drvdata(csdev->dev.parent);
-	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+	struct adreno_device *adreno_dev;
+
+	if (device == NULL)
+		return -ENODEV;
+
+	adreno_dev = ADRENO_DEVICE(device);
 
 	/* Check if coresight compatible device, return error otherwise */
 	if (adreno_dev->gpudev->coresight_enable)
@@ -80,7 +85,12 @@
 void adreno_coresight_disable(struct coresight_device *csdev)
 {
 	struct kgsl_device *device = dev_get_drvdata(csdev->dev.parent);
-	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+	struct adreno_device *adreno_dev;
+
+	if (device == NULL)
+		return;
+
+	adreno_dev = ADRENO_DEVICE(device);
 
 	/* Check if coresight compatible device, bail otherwise */
 	if (adreno_dev->gpudev->coresight_disable)
@@ -134,6 +144,10 @@
 	struct kgsl_device *device = dev_get_drvdata(dev->parent);
 	struct coresight_attr *csight_attr = container_of(attr,
 			struct coresight_attr, attr);
+
+	if (device == NULL)
+		return -ENODEV;
+
 	return coresight_read_reg(device, csight_attr->regname, buf);
 }
 
@@ -142,11 +156,16 @@
 		const char *buf, size_t size)
 {
 	struct kgsl_device *device = dev_get_drvdata(dev->parent);
-	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+	struct adreno_device *adreno_dev;
 	struct coresight_attr *csight_attr = container_of(attr,
 			struct coresight_attr, attr);
 	unsigned int regval = 0;
 
+	if (device == NULL)
+		return -ENODEV;
+
+	adreno_dev = ADRENO_DEVICE(device);
+
 	regval = coresight_convert_reg(buf);
 
 	if (adreno_dev->gpudev->coresight_config_debug_reg)
diff --git a/drivers/gpu/msm/adreno_profile.c b/drivers/gpu/msm/adreno_profile.c
index 28fd6d6..079e120 100644
--- a/drivers/gpu/msm/adreno_profile.c
+++ b/drivers/gpu/msm/adreno_profile.c
@@ -1106,7 +1106,7 @@
 	if (SIZE_SHARED_ENTRY(count) >= shared_buf_available(profile))
 		goto done;
 
-	if (entry_head + SIZE_SHARED_ENTRY(count) > profile->shared_size) {
+	if (entry_head + SIZE_SHARED_ENTRY(count) >= profile->shared_size) {
 		/* entry_head would wrap, start entry_head at 0 in buffer */
 		entry_head = 0;
 		profile->shared_size = profile->shared_head;
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
old mode 100644
new mode 100755
index 246295b..8453b9d
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -72,6 +72,11 @@
 
 static struct iommu_access_ops *iommu_access_ops;
 
+static int kgsl_iommu_default_setstate(struct kgsl_mmu *mmu,
+		uint32_t flags);
+static phys_addr_t
+kgsl_iommu_get_current_ptbase(struct kgsl_mmu *mmu);
+
 static void _iommu_lock(struct kgsl_iommu const *iommu)
 {
 	if (iommu_access_ops && iommu_access_ops->iommu_lock_acquire)
@@ -1739,9 +1744,11 @@
 		struct kgsl_memdesc *memdesc,
 		unsigned int *tlb_flags)
 {
-	int ret;
+	int ret = 0, lock_taken = 0;
 	unsigned int range = memdesc->size;
 	struct kgsl_iommu_pt *iommu_pt = pt->priv;
+	struct kgsl_device *device = pt->mmu->device;
+	struct kgsl_iommu *iommu = pt->mmu->priv;
 
 	/* All GPU addresses as assigned are page aligned, but some
 	   functions purturb the gpuaddr with an offset, so apply the
@@ -1756,18 +1763,38 @@
 		range += PAGE_SIZE;
 
 	ret = iommu_unmap_range(iommu_pt->domain, gpuaddr, range);
-	if (ret)
+	if (ret) {
 		KGSL_CORE_ERR("iommu_unmap_range(%p, %x, %d) failed "
 			"with err: %d\n", iommu_pt->domain, gpuaddr,
 			range, ret);
+		return ret;
+	}
 
 	/*
-	 * Flushing only required if per process pagetables are used. With
-	 * global case, flushing will happen inside iommu_map function
+	 * Check to see if the current thread already holds the device mutex.
+	 * If it does not, then take the device mutex which is required for
+	 * flushing the tlb
 	 */
-	if (!ret && kgsl_mmu_is_perprocess(pt->mmu))
-		*tlb_flags = UINT_MAX;
-	return 0;
+	if (!mutex_is_locked(&device->mutex) ||
+		device->mutex.owner != current) {
+		mutex_lock(&device->mutex);
+		lock_taken = 1;
+	}
+
+	/*
+	 * Flush the tlb only if the iommu device is attached and the pagetable
+	 * hasn't been switched yet
+	 */
+	if (kgsl_mmu_is_perprocess(pt->mmu) &&
+		iommu->iommu_units[0].dev[KGSL_IOMMU_CONTEXT_USER].attached &&
+		kgsl_iommu_pt_equal(pt->mmu, pt,
+		kgsl_iommu_get_current_ptbase(pt->mmu)))
+		kgsl_iommu_default_setstate(pt->mmu, KGSL_MMUFLAGS_TLBFLUSH);
+
+	if (lock_taken)
+		mutex_unlock(&device->mutex);
+
+	return ret;
 }
 
 static int
diff --git a/drivers/input/misc/cm36283.c b/drivers/input/misc/cm36283.c
index 5f08da4..a7b4735 100644
--- a/drivers/input/misc/cm36283.c
+++ b/drivers/input/misc/cm36283.c
@@ -3,7 +3,7 @@
  * Copyright (C) 2012 Capella Microsystems Inc.
  * Author: Frank Hsieh <pengyueh@gmail.com>
  *
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -75,6 +75,10 @@
 	.min_delay = 0,
 	.fifo_reserved_event_count = 0,
 	.fifo_max_event_count = 0,
+	.enabled = 0,
+	.delay_msec = CM36283_LS_DEFAULT_POLL_DELAY,
+	.sensors_enable = NULL,
+	.sensors_poll_delay = NULL,
 };
 
 static struct sensors_classdev sensors_proximity_cdev = {
@@ -89,6 +93,10 @@
 	.min_delay = 0,
 	.fifo_reserved_event_count = 0,
 	.fifo_max_event_count = 0,
+	.enabled = 0,
+	.delay_msec = CM36283_PS_DEFAULT_POLL_DELAY,
+	.sensors_enable = NULL,
+	.sensors_poll_delay = NULL,
 };
 
 
@@ -159,6 +167,8 @@
 	struct regulator *vio;
 	struct delayed_work ldwork;
 	struct delayed_work pdwork;
+	struct sensors_classdev als_cdev;
+	struct sensors_classdev ps_cdev;
 };
 struct cm36283_info *lp_info;
 int fLevel=-1;
@@ -806,6 +816,21 @@
 	return ret;
 }
 
+static int ps_enable_set(struct sensors_classdev *sensors_cdev,
+		unsigned int enable)
+{
+	struct cm36283_info *lpi = container_of(sensors_cdev,
+			struct cm36283_info, ps_cdev);
+	int ret;
+
+	if (enable)
+		ret = psensor_enable(lpi);
+	else
+		ret = psensor_disable(lpi);
+
+	return ret;
+}
+
 static ssize_t ps_enable_store(struct device *dev,
 				struct device_attribute *attr,
 				const char *buf, size_t count)
@@ -962,6 +987,27 @@
 	return ret;
 }
 
+static int ls_enable_set(struct sensors_classdev *sensors_cdev,
+		unsigned int enable)
+{
+	struct cm36283_info *lpi = container_of(sensors_cdev,
+			struct cm36283_info, als_cdev);
+	int ret;
+
+	if (enable)
+		ret = lightsensor_enable(lpi);
+	else
+		ret = lightsensor_disable(lpi);
+
+	if (ret < 0) {
+		dev_err(&lpi->i2c_client->dev, "%s: set auto light sensor fail\n",
+				__func__);
+		return -EIO;
+	}
+
+	return 0;
+}
+
 static ssize_t ls_enable_show(struct device *dev,
 				  struct device_attribute *attr, char *buf)
 {
@@ -1003,9 +1049,11 @@
 			lpi->ls_calibrate);
 	dev_dbg(&lpi->i2c_client->dev, "ls_auto:0x%x\n", ls_auto);
 
-	if (ret < 0)
+	if (ret < 0) {
 		dev_err(&lpi->i2c_client->dev, "%s: set auto light sensor fail\n",
 		__func__);
+		return ret;
+	}
 
 	return count;
 }
@@ -1188,6 +1236,21 @@
 	return count;
 }
 
+static int ls_poll_delay_set(struct sensors_classdev *sensors_cdev,
+		unsigned int delay_msec)
+{
+	struct cm36283_info *lpi = container_of(sensors_cdev,
+			struct cm36283_info, als_cdev);
+
+	if ((delay_msec < CM36283_LS_MIN_POLL_DELAY) ||
+			(delay_msec > CM36283_LS_MAX_POLL_DELAY))
+		return -EINVAL;
+
+	atomic_set(&lpi->ls_poll_delay, delay_msec);
+
+	return 0;
+}
+
 static ssize_t ps_poll_delay_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -1213,6 +1276,20 @@
 	return count;
 }
 
+static int ps_poll_delay_set(struct sensors_classdev *sensors_cdev,
+		unsigned int delay_msec)
+{
+	struct cm36283_info *lpi = container_of(sensors_cdev,
+			struct cm36283_info, als_cdev);
+
+	if ((delay_msec < CM36283_PS_MIN_POLL_DELAY) ||
+			(delay_msec > CM36283_PS_MAX_POLL_DELAY))
+		return -EINVAL;
+
+	atomic_set(&lpi->ps_poll_delay, delay_msec);
+	return 0;
+}
+
 static ssize_t ls_fLevel_show(struct device *dev,
 				  struct device_attribute *attr, char *buf)
 {
@@ -1645,12 +1722,21 @@
 		goto err_light_sysfs_cleanup;
 	}
 
+	lpi->als_cdev = sensors_light_cdev;
+	lpi->als_cdev.sensors_enable = ls_enable_set;
+	lpi->als_cdev.sensors_poll_delay = ls_poll_delay_set;
+	lpi->als_cdev.min_delay = CM36283_LS_MIN_POLL_DELAY * 1000;
 
-	ret = sensors_classdev_register(&client->dev, &sensors_light_cdev);
+	lpi->ps_cdev = sensors_proximity_cdev;
+	lpi->ps_cdev.sensors_enable = ps_enable_set;
+	lpi->ps_cdev.sensors_poll_delay = ps_poll_delay_set;
+	lpi->ps_cdev.min_delay = CM36283_PS_MIN_POLL_DELAY * 1000;
+
+	ret = sensors_classdev_register(&client->dev, &lpi->als_cdev);
 	if (ret)
 		goto err_proximity_sysfs_cleanup;
 
-	ret = sensors_classdev_register(&client->dev, &sensors_proximity_cdev);
+	ret = sensors_classdev_register(&client->dev, &lpi->ps_cdev);
 	if (ret)
 		goto err_create_class_sysfs;
 
@@ -1661,7 +1747,7 @@
 
 	return ret;
 err_create_class_sysfs:
-	sensors_classdev_unregister(&sensors_light_cdev);
+	sensors_classdev_unregister(&lpi->als_cdev);
 err_proximity_sysfs_cleanup:
 	remove_sysfs_interfaces(&lpi->ps_input_dev->dev, proximity_attr,
 			ARRAY_SIZE(proximity_attr));
diff --git a/drivers/input/misc/mpu3050.c b/drivers/input/misc/mpu3050.c
index 039e078..9629aae 100644
--- a/drivers/input/misc/mpu3050.c
+++ b/drivers/input/misc/mpu3050.c
@@ -709,7 +709,7 @@
 	}
 
 	sensor->cdev = sensors_cdev;
-	sensor->cdev.min_delay = MPU3050_MIN_POLL_INTERVAL;
+	sensor->cdev.min_delay = MPU3050_MIN_POLL_INTERVAL * 1000;
 	sensor->cdev.delay_msec = sensor->poll_interval;
 	sensor->cdev.sensors_enable = mpu3050_enable_set;
 	sensor->cdev.sensors_poll_delay = mpu3050_poll_delay_set;
diff --git a/drivers/input/touchscreen/gt9xx/goodix_tool.c b/drivers/input/touchscreen/gt9xx/goodix_tool.c
index aa8159f..521599a 100644
--- a/drivers/input/touchscreen/gt9xx/goodix_tool.c
+++ b/drivers/input/touchscreen/gt9xx/goodix_tool.c
@@ -23,16 +23,15 @@
 
 #include "gt9xx.h"
 #include <linux/mutex.h>
+#include <linux/proc_fs.h>
+#include <linux/debugfs.h>
 
 #define DATA_LENGTH_UINT    512
-#define CMD_HEAD_LENGTH     (sizeof(st_cmd_head) - sizeof(u8 *))
+#define CMD_HEAD_LENGTH     (sizeof(struct st_cmd_head) - sizeof(u8 *))
 static char procname[20] = {0};
 
-#define UPDATE_FUNCTIONS
-
-#pragma pack(1)
-struct {
-	u8  wr;		/* write read flag£¬0:R  1:W  2:PID 3: */
+struct st_cmd_head {
+	u8  wr;		/* write read flag 0:R 1:W 2:PID 3: */
 	u8  flag;	/* 0:no need flag/int 1: need flag  2:need int */
 	u8 flag_addr[2];/* flag address */
 	u8  flag_val;	/* flag val */
@@ -46,9 +45,9 @@
 	u8  addr[2];	/* address */
 	u8  res[3];	/* reserved */
 	u8  *data;	/* data pointer */
-} st_cmd_head;
-#pragma pack()
-st_cmd_head cmd_head;
+} __packed;
+
+static struct st_cmd_head cmd_head;
 
 static struct i2c_client *gt_client;
 
@@ -56,15 +55,11 @@
 
 static struct mutex lock;
 
-static s32 goodix_tool_write(struct file *filp, const char __user *buff,
-						unsigned long len, void *data);
-static s32 goodix_tool_read(char *page, char **start, off_t off, int count,
-							int *eof, void *data);
 static s32 (*tool_i2c_read)(u8 *, u16);
 static s32 (*tool_i2c_write)(u8 *, u16);
 
-s32 DATA_LENGTH;
-s8 IC_TYPE[16] = {0};
+s32 data_length;
+s8 ic_type[16] = {0};
 
 static void tool_set_proc_name(char *procname)
 {
@@ -75,7 +70,7 @@
 	int i = 0, n_month = 1, n_day = 0, n_year = 0;
 	snprintf(date, 20, "%s", __DATE__);
 
-	/* GTP_DEBUG("compile date: %s", date); */
+	/* pr_debug("compile date: %s", date); */
 
 	sscanf(date, "%s %d %d", month, &n_day, &n_year);
 
@@ -87,24 +82,27 @@
 	}
 
 	snprintf(procname, 20, "gmnode%04d%02d%02d", n_year, n_month, n_day);
-	/* GTP_DEBUG("procname = %s", procname); */
+	/* pr_debug("procname = %s", procname); */
 }
 
 static s32 tool_i2c_read_no_extra(u8 *buf, u16 len)
 {
 	s32 ret = -1;
-	s32 i = 0;
-	struct i2c_msg msgs[2];
-
-	msgs[0].flags = !I2C_M_RD;
-	msgs[0].addr  = gt_client->addr;
-	msgs[0].len   = cmd_head.addr_len;
-	msgs[0].buf   = &buf[0];
-
-	msgs[1].flags = I2C_M_RD;
-	msgs[1].addr  = gt_client->addr;
-	msgs[1].len   = len;
-	msgs[1].buf   = &buf[GTP_ADDR_LENGTH];
+	u8 i = 0;
+	struct i2c_msg msgs[2] = {
+		{
+			.flags = !I2C_M_RD,
+			.addr  = gt_client->addr,
+			.len   = cmd_head.addr_len,
+			.buf   = &buf[0],
+		},
+		{
+			.flags = I2C_M_RD,
+			.addr  = gt_client->addr,
+			.len   = len,
+			.buf   = &buf[GTP_ADDR_LENGTH],
+		},
+	};
 
 	for (i = 0; i < cmd_head.retry; i++) {
 		ret = i2c_transfer(gt_client->adapter, msgs, 2);
@@ -112,25 +110,35 @@
 			break;
 	}
 
+	if (i == cmd_head.retry) {
+		dev_err(&gt_client->dev, "I2C read retry limit over.\n");
+		ret = -EIO;
+	}
+
 	return ret;
 }
 
 static s32 tool_i2c_write_no_extra(u8 *buf, u16 len)
 {
 	s32 ret = -1;
-	s32 i = 0;
-	struct i2c_msg msg;
-
-	msg.flags = !I2C_M_RD;
-	msg.addr  = gt_client->addr;
-	msg.len   = len;
-	msg.buf   = buf;
+	u8 i = 0;
+	struct i2c_msg msg = {
+		.flags = !I2C_M_RD,
+		.addr  = gt_client->addr,
+		.len   = len,
+		.buf   = buf,
+	};
 
 	for (i = 0; i < cmd_head.retry; i++) {
 		ret = i2c_transfer(gt_client->adapter, &msg, 1);
 		if (ret > 0)
 			break;
-		}
+	}
+
+	if (i == cmd_head.retry) {
+		dev_err(&gt_client->dev, "I2C write retry limit over.\n");
+		ret = -EIO;
+	}
 
 	return ret;
 }
@@ -163,22 +171,17 @@
 
 static void register_i2c_func(void)
 {
-	/* if (!strncmp(IC_TYPE, "GT818", 5) || !strncmp(IC_TYPE, "GT816", 5)
-	|| !strncmp(IC_TYPE, "GT811", 5) || !strncmp(IC_TYPE, "GT818F", 6)
-	|| !strncmp(IC_TYPE, "GT827", 5) || !strncmp(IC_TYPE,"GT828", 5)
-	|| !strncmp(IC_TYPE, "GT813", 5)) */
-
-	if (strncmp(IC_TYPE, "GT8110", 6) && strncmp(IC_TYPE, "GT8105", 6)
-	&& strncmp(IC_TYPE, "GT801", 5) && strncmp(IC_TYPE, "GT800", 5)
-	&& strncmp(IC_TYPE, "GT801PLUS", 9) && strncmp(IC_TYPE, "GT811", 5)
-	&& strncmp(IC_TYPE, "GTxxx", 5)) {
+	if (strcmp(ic_type, "GT8110") && strcmp(ic_type, "GT8105")
+	&& strcmp(ic_type, "GT801") && strcmp(ic_type, "GT800")
+	&& strcmp(ic_type, "GT801PLUS") && strcmp(ic_type, "GT811")
+	&& strcmp(ic_type, "GTxxx")) {
 		tool_i2c_read = tool_i2c_read_with_extra;
 		tool_i2c_write = tool_i2c_write_with_extra;
-		GTP_DEBUG("I2C function: with pre and end cmd!");
+		pr_debug("I2C function: with pre and end cmd!");
 	} else {
 		tool_i2c_read = tool_i2c_read_no_extra;
 		tool_i2c_write = tool_i2c_write_no_extra;
-		GTP_INFO("I2C function: without pre and end cmd!");
+		pr_info("I2C function: without pre and end cmd!");
 	}
 }
 
@@ -186,55 +189,11 @@
 {
 	tool_i2c_read = NULL;
 	tool_i2c_write = NULL;
-	GTP_INFO("I2C function: unregister i2c transfer function!");
-}
-
-s32 init_wr_node(struct i2c_client *client)
-{
-	u8 i;
-
-	gt_client = client;
-	memset(&cmd_head, 0, sizeof(cmd_head));
-	cmd_head.data = NULL;
-
-	i = 5;
-	while ((!cmd_head.data) && i) {
-		cmd_head.data = kzalloc(i * DATA_LENGTH_UINT, GFP_KERNEL);
-		if (NULL != cmd_head.data)
-			break;
-		i--;
-	}
-	if (i) {
-		DATA_LENGTH = i * DATA_LENGTH_UINT;
-		dev_dbg(&client->dev, "Applied memory size:%d.", DATA_LENGTH);
-	} else {
-		GTP_ERROR("Apply for memory failed.");
-		return FAIL;
-	}
-
-	cmd_head.addr_len = 2;
-	cmd_head.retry = 5;
-
-	register_i2c_func();
-
-	mutex_init(&lock);
-	tool_set_proc_name(procname);
-	goodix_proc_entry = create_proc_entry(procname, 0660, NULL);
-	if (goodix_proc_entry == NULL) {
-		GTP_ERROR("Couldn't create proc entry!");
-		return FAIL;
-	} else {
-		GTP_INFO("Create proc entry success!");
-		goodix_proc_entry->write_proc = goodix_tool_write;
-		dix_proc_entry->read_proc = goodix_tool_read;
-	}
-
-	return SUCCESS;
+	pr_info("I2C function: unregister i2c transfer function!");
 }
 
 void uninit_wr_node(void)
 {
-	kfree(cmd_head.data);
 	cmd_head.data = NULL;
 	unregister_i2c_func();
 	remove_proc_entry(procname, NULL);
@@ -252,7 +211,7 @@
 
 	case 1:
 		ret = (src == dst) ? true : false;
-		GTP_DEBUG("equal:src:0x%02x   dst:0x%02x  ret:%d.",
+		pr_debug("equal:src:0x%02x   dst:0x%02x  ret:%d.",
 					src, dst, (s32)ret);
 		break;
 
@@ -293,22 +252,18 @@
 	s32 i = 0;
 	u8 buf[32];
 
-/*    memcpy(&buf[GTP_ADDR_LENGTH - cmd_head.addr_len],
-			&cmd_head.flag_addr, cmd_head.addr_len);
-    memcpy(buf, &cmd_head.flag_addr, cmd_head.addr_len);
-		//Modified by Scott, 2012-02-17 */
 	memcpy(buf, cmd_head.flag_addr, cmd_head.addr_len);
 
 	for (i = 0; i < cmd_head.times; i++) {
 		if (tool_i2c_read(buf, 1) <= 0) {
-			GTP_ERROR("Read flag data failed!");
+			dev_err(&gt_client->dev, "Read flag data failed!");
 			return FAIL;
 		}
 		if (true == relation(buf[GTP_ADDR_LENGTH], cmd_head.flag_val,
 						cmd_head.flag_relation)) {
-			GTP_DEBUG("value at flag addr:0x%02x.",
+			pr_debug("value at flag addr:0x%02x.",
 						buf[GTP_ADDR_LENGTH]);
-			GTP_DEBUG("flag value:0x%02x.", cmd_head.flag_val);
+			pr_debug("flag value:0x%02x.", cmd_head.flag_val);
 			break;
 		}
 
@@ -316,13 +271,34 @@
 	}
 
 	if (i >= cmd_head.times) {
-		GTP_ERROR("Didn't get the flag to continue!");
+		dev_err(&gt_client->dev, "Didn't get the flag to continue!");
 		return FAIL;
 	}
 
 	return SUCCESS;
 }
 
+#ifdef CONFIG_GT9XX_TOUCHPANEL_UPDATE
+static s32 fill_update_info(char __user *user_buf,
+				    size_t count, loff_t *ppos)
+{
+	u8 buf[4];
+
+	buf[0] = show_len >> 8;
+	buf[1] = show_len & 0xff;
+	buf[2] = total_len >> 8;
+	buf[3] = total_len & 0xff;
+	return simple_read_from_buffer(user_buf, count, ppos,
+			buf, sizeof(buf));
+}
+#else
+static s32 fill_update_info(char __user *user_buf,
+				    size_t count, loff_t *ppos)
+{
+	return -ENODEV;
+}
+#endif
+
 /********************************************************
 Function:
     Goodix tool write function.
@@ -331,117 +307,99 @@
 Output:
     Return write length.
 ********************************************************/
-static s32 goodix_tool_write(struct file *filp, const char __user *buff,
-						unsigned long len, void *data)
+static s32 goodix_tool_write(struct file *filp, const char __user *userbuf,
+						size_t count, loff_t *ppos)
 {
 	s32 ret = 0;
-	GTP_DEBUG_FUNC();
-	GTP_DEBUG_ARRAY((u8 *)buff, len);
 
 	mutex_lock(&lock);
-	ret = copy_from_user(&cmd_head, buff, CMD_HEAD_LENGTH);
+	ret = copy_from_user(&cmd_head, userbuf, CMD_HEAD_LENGTH);
 	if (ret) {
-		GTP_ERROR("copy_from_user failed.");
+		dev_err(&gt_client->dev, "copy_from_user failed.");
 		ret = -EACCES;
 		goto exit;
 	}
 
-	GTP_DEBUG("wr  :0x%02x.", cmd_head.wr);
-	GTP_DEBUG("flag:0x%02x.", cmd_head.flag);
-	GTP_DEBUG("flag addr:0x%02x%02x.", cmd_head.flag_addr[0],
-						cmd_head.flag_addr[1]);
-	GTP_DEBUG("flag val:0x%02x.", cmd_head.flag_val);
-	GTP_DEBUG("flag rel:0x%02x.", cmd_head.flag_relation);
-	GTP_DEBUG("circle  :%d.", (s32)cmd_head.circle);
-	GTP_DEBUG("times   :%d.", (s32)cmd_head.times);
-	GTP_DEBUG("retry   :%d.", (s32)cmd_head.retry);
-	GTP_DEBUG("delay   :%d.", (s32)cmd_head.delay);
-	GTP_DEBUG("data len:%d.", (s32)cmd_head.data_len);
-	GTP_DEBUG("addr len:%d.", (s32)cmd_head.addr_len);
-	GTP_DEBUG("addr:0x%02x%02x.", cmd_head.addr[0], cmd_head.addr[1]);
-	GTP_DEBUG("len:%d.", (s32)len);
-	GTP_DEBUG("buf[20]:0x%02x.", buff[CMD_HEAD_LENGTH]);
+	dev_dbg(&gt_client->dev, "wr:0x%02x, flag:0x%02x, flag addr:0x%02x%02x, flag val:0x%02x, flag rel:0x%02x, circle:%d, times:%d, retry:%d, delay:%d, data len:%d, addr len:%d, addr:0x%02x%02x, write len: %d.",
+		cmd_head.wr, cmd_head.flag, cmd_head.flag_addr[0],
+		cmd_head.flag_addr[1], cmd_head.flag_val,
+		cmd_head.flag_relation,	(s32)cmd_head.circle,
+		(s32)cmd_head.times, (s32)cmd_head.retry, (s32)cmd_head.delay,
+		(s32)cmd_head.data_len, (s32)cmd_head.addr_len,
+		cmd_head.addr[0], cmd_head.addr[1], (s32)count);
 
-	if (cmd_head.data_len > (DATA_LENGTH - GTP_ADDR_LENGTH)) {
-		pr_err("data len %d > data buff %d, rejected!\n",
-			cmd_head.data_len, (DATA_LENGTH - GTP_ADDR_LENGTH));
+	if (cmd_head.data_len > (data_length - GTP_ADDR_LENGTH)) {
+		dev_err(&gt_client->dev, "data len %d > data buff %d, rejected!\n",
+			cmd_head.data_len, (data_length - GTP_ADDR_LENGTH));
 		ret = -EINVAL;
 		goto exit;
 	}
 	if (cmd_head.addr_len > GTP_ADDR_LENGTH) {
-		pr_err(" addr len %d > data buff %d, rejected!\n",
+		dev_err(&gt_client->dev, "addr len %d > data buff %d, rejected!\n",
 			cmd_head.addr_len, GTP_ADDR_LENGTH);
 		ret = -EINVAL;
 		goto exit;
 	}
 
-	if (cmd_head.wr == 1) {
-		/*  copy_from_user(&cmd_head.data[cmd_head.addr_len],
-				&buff[CMD_HEAD_LENGTH], cmd_head.data_len); */
+	if (cmd_head.wr == GTP_RW_WRITE) {
 		ret = copy_from_user(&cmd_head.data[GTP_ADDR_LENGTH],
-				&buff[CMD_HEAD_LENGTH], cmd_head.data_len);
-		if (ret)
-			GTP_ERROR("copy_from_user failed.");
+				&userbuf[CMD_HEAD_LENGTH], cmd_head.data_len);
+		if (ret) {
+			dev_err(&gt_client->dev, "copy_from_user failed.");
+			goto exit;
+		}
 
 		memcpy(&cmd_head.data[GTP_ADDR_LENGTH - cmd_head.addr_len],
 					cmd_head.addr, cmd_head.addr_len);
 
-		GTP_DEBUG_ARRAY(cmd_head.data,
-				cmd_head.data_len + cmd_head.addr_len);
-		GTP_DEBUG_ARRAY((u8 *)&buff[CMD_HEAD_LENGTH],
-							cmd_head.data_len);
-
-		if (cmd_head.flag == 1) {
-			if (FAIL == comfirm()) {
-				GTP_ERROR("[WRITE]Comfirm fail!");
+		if (cmd_head.flag == GTP_NEED_FLAG) {
+			if (comfirm() ==  FAIL) {
+				dev_err(&gt_client->dev, "Comfirm fail!");
 				ret = -EINVAL;
 				goto exit;
 			}
-		} else if (cmd_head.flag == 2) {
+		} else if (cmd_head.flag == GTP_NEED_INTERRUPT) {
 			/* Need interrupt! */
 		}
 		if (tool_i2c_write(
 		&cmd_head.data[GTP_ADDR_LENGTH - cmd_head.addr_len],
 		cmd_head.data_len + cmd_head.addr_len) <= 0) {
-			GTP_ERROR("[WRITE]Write data failed!");
+			dev_err(&gt_client->dev, "Write data failed!");
 			ret = -EIO;
 			goto exit;
 		}
 
-		GTP_DEBUG_ARRAY(
-			&cmd_head.data[GTP_ADDR_LENGTH - cmd_head.addr_len],
-			cmd_head.data_len + cmd_head.addr_len);
 		if (cmd_head.delay)
 			msleep(cmd_head.delay);
 
 		ret = cmd_head.data_len + CMD_HEAD_LENGTH;
 		goto exit;
-	} else if (cmd_head.wr == 3) {  /* Write ic type */
-
-		ret = copy_from_user(&cmd_head.data[0], &buff[CMD_HEAD_LENGTH],
+	} else if (cmd_head.wr == GTP_RW_WRITE_IC_TYPE) {  /* Write ic type */
+		ret = copy_from_user(&cmd_head.data[0],
+				&userbuf[CMD_HEAD_LENGTH],
 				cmd_head.data_len);
-		if (ret)
-			GTP_ERROR("copy_from_user failed.");
+		if (ret) {
+			dev_err(&gt_client->dev, "copy_from_user failed.");
+			goto exit;
+		}
 
-		if (cmd_head.data_len > sizeof(IC_TYPE)) {
-			pr_err("<<-GTP->> data len %d > data buff %d, rejected!\n",
-			cmd_head.data_len, sizeof(IC_TYPE));
+		if (cmd_head.data_len > sizeof(ic_type)) {
+			dev_err(&gt_client->dev,
+				"data len %d > data buff %d, rejected!\n",
+				cmd_head.data_len, sizeof(ic_type));
 			ret = -EINVAL;
 			goto exit;
 		}
-		memcpy(IC_TYPE, cmd_head.data, cmd_head.data_len);
+		memcpy(ic_type, cmd_head.data, cmd_head.data_len);
 
 		register_i2c_func();
 
 		ret = cmd_head.data_len + CMD_HEAD_LENGTH;
 		goto exit;
-	} else if (cmd_head.wr == 5) {
-
-		/* memcpy(IC_TYPE, cmd_head.data, cmd_head.data_len); */
-
+	} else if (cmd_head.wr == GTP_RW_NO_WRITE) {
 		ret = cmd_head.data_len + CMD_HEAD_LENGTH;
 		goto exit;
-	} else if (cmd_head.wr == 7) { /* disable irq! */
+	} else if (cmd_head.wr == GTP_RW_DISABLE_IRQ) { /* disable irq! */
 		gtp_irq_disable(i2c_get_clientdata(gt_client));
 
 		#if GTP_ESD_PROTECT
@@ -449,7 +407,7 @@
 		#endif
 		ret = CMD_HEAD_LENGTH;
 		goto exit;
-	} else if (cmd_head.wr == 9) { /* enable irq! */
+	} else if (cmd_head.wr == GTP_RW_ENABLE_IRQ) { /* enable irq! */
 		gtp_irq_enable(i2c_get_clientdata(gt_client));
 
 		#if GTP_ESD_PROTECT
@@ -457,49 +415,51 @@
 		#endif
 		ret = CMD_HEAD_LENGTH;
 		goto exit;
-	} else if (cmd_head.wr == 17) {
+	} else if (cmd_head.wr == GTP_RW_CHECK_RAWDIFF_MODE) {
 		struct goodix_ts_data *ts = i2c_get_clientdata(gt_client);
 		ret = copy_from_user(&cmd_head.data[GTP_ADDR_LENGTH],
-				&buff[CMD_HEAD_LENGTH], cmd_head.data_len);
-		if (ret)
-			GTP_DEBUG("copy_from_user failed.");
+				&userbuf[CMD_HEAD_LENGTH], cmd_head.data_len);
+		if (ret) {
+			pr_debug("copy_from_user failed.");
+			goto exit;
+		}
 		if (cmd_head.data[GTP_ADDR_LENGTH]) {
-			GTP_DEBUG("gtp enter rawdiff.");
+			pr_debug("gtp enter rawdiff.");
 			ts->gtp_rawdiff_mode = true;
 		} else {
 			ts->gtp_rawdiff_mode = false;
-			GTP_DEBUG("gtp leave rawdiff.");
+			pr_debug("gtp leave rawdiff.");
 		}
 		ret = CMD_HEAD_LENGTH;
 		goto exit;
-	}
-#ifdef UPDATE_FUNCTIONS
-	else if (cmd_head.wr == 11) { /* Enter update mode! */
-		if (FAIL == gup_enter_update_mode(gt_client)) {
+	} else if (cmd_head.wr == GTP_RW_ENTER_UPDATE_MODE) {
+		/* Enter update mode! */
+		if (gup_enter_update_mode(gt_client) ==  FAIL) {
 			ret = -EBUSY;
 			goto exit;
 		}
-	} else if (cmd_head.wr == 13) { /* Leave update mode! */
-		gup_leave_update_mode();
-	} else if (cmd_head.wr == 15) { /* Update firmware! */
+	} else if (cmd_head.wr == GTP_RW_LEAVE_UPDATE_MODE) {
+		/* Leave update mode! */
+		gup_leave_update_mode(gt_client);
+	} else if (cmd_head.wr == GTP_RW_UPDATE_FW) {
+		/* Update firmware! */
 		show_len = 0;
 		total_len = 0;
-		if (cmd_head.data_len + 1 > DATA_LENGTH) {
-			pr_err("<<-GTP->> data len %d > data buff %d, rejected!\n",
-			cmd_head.data_len + 1, DATA_LENGTH);
+		if (cmd_head.data_len + 1 > data_length) {
+			dev_err(&gt_client->dev, "data len %d > data buff %d, rejected!\n",
+			cmd_head.data_len + 1, data_length);
 			ret = -EINVAL;
 			goto exit;
 		}
 		memset(cmd_head.data, 0, cmd_head.data_len + 1);
-		memcpy(cmd_head.data, &buff[CMD_HEAD_LENGTH],
+		memcpy(cmd_head.data, &userbuf[CMD_HEAD_LENGTH],
 					cmd_head.data_len);
 
-		if (FAIL == gup_update_proc((void *)cmd_head.data)) {
+		if (gup_update_proc((void *)cmd_head.data) == FAIL) {
 			ret = -EBUSY;
 			goto exit;
 		}
 	}
-#endif
 	ret = CMD_HEAD_LENGTH;
 
 exit:
@@ -511,95 +471,130 @@
 Function:
     Goodix tool read function.
 Input:
-  standard proc read function param.
+  standard seq file read function param.
 Output:
     Return read length.
 ********************************************************/
-static s32 goodix_tool_read(char *page, char **start, off_t off, int count,
-							int *eof, void *data)
+static s32 goodix_tool_read(struct file *file, char __user *user_buf,
+					size_t count, loff_t *ppos)
 {
+	u16 data_len = 0;
 	s32 ret;
-	GTP_DEBUG_FUNC();
+	u8 buf[32];
 
 	mutex_lock(&lock);
-	if (cmd_head.wr % 2) {
-		pr_err("<< [READ]command head wrong\n");
+	if (cmd_head.wr & 0x1) {
+		dev_err(&gt_client->dev, "command head wrong\n");
 		ret = -EINVAL;
 		goto exit;
-	} else if (!cmd_head.wr) {
-		u16 len = 0;
-		s16 data_len = 0;
-		u16 loc = 0;
+	}
 
-		if (cmd_head.flag == 1) {
-			if (FAIL == comfirm()) {
-				GTP_ERROR("[READ]Comfirm fail!");
+	switch (cmd_head.wr) {
+	case GTP_RW_READ:
+		if (cmd_head.flag == GTP_NEED_FLAG) {
+			if (comfirm() == FAIL) {
+				dev_err(&gt_client->dev, "Comfirm fail!");
 				ret = -EINVAL;
 				goto exit;
 			}
-		} else if (cmd_head.flag == 2) {
+		} else if (cmd_head.flag == GTP_NEED_INTERRUPT) {
 			/* Need interrupt! */
 		}
 
 		memcpy(cmd_head.data, cmd_head.addr, cmd_head.addr_len);
 
-		GTP_DEBUG("[CMD HEAD DATA] ADDR:0x%02x%02x.", cmd_head.data[0],
+		pr_debug("[CMD HEAD DATA] ADDR:0x%02x%02x.", cmd_head.data[0],
 							cmd_head.data[1]);
-		GTP_DEBUG("[CMD HEAD ADDR] ADDR:0x%02x%02x.", cmd_head.addr[0],
+		pr_debug("[CMD HEAD ADDR] ADDR:0x%02x%02x.", cmd_head.addr[0],
 							cmd_head.addr[1]);
 
 		if (cmd_head.delay)
 			msleep(cmd_head.delay);
 
 		data_len = cmd_head.data_len;
-		while (data_len > 0) {
-			if (data_len > DATA_LENGTH)
-				len = DATA_LENGTH;
-			else
-				len = data_len;
-
-			data_len -= len;
-
-			if (tool_i2c_read(cmd_head.data, len) <= 0) {
-				GTP_ERROR("[READ]Read data failed!");
-				ret = -EINVAL;
-				goto exit;
-			}
-			memcpy(&page[loc], &cmd_head.data[GTP_ADDR_LENGTH],
-									len);
-			loc += len;
-
-			GTP_DEBUG_ARRAY(&cmd_head.data[GTP_ADDR_LENGTH], len);
-			GTP_DEBUG_ARRAY(page, len);
+		if (data_len <= 0 || (data_len > data_length)) {
+			dev_err(&gt_client->dev, "Invalid data length %d\n",
+				data_len);
+			ret = -EINVAL;
+			goto exit;
 		}
-	} else if (cmd_head.wr == 2) {
-		/* memcpy(page, "gt8", cmd_head.data_len);
-		memcpy(page, "GT818", 5);
-		page[5] = 0; */
+		if (data_len > count)
+			data_len = count;
 
-		GTP_DEBUG("Return ic type:%s len:%d.", page,
-						(s32)cmd_head.data_len);
-		ret = cmd_head.data_len;
-		goto exit;
-		/* return sizeof(IC_TYPE_NAME); */
-	} else if (cmd_head.wr == 4) {
-		page[0] = show_len >> 8;
-		page[1] = show_len & 0xff;
-		page[2] = total_len >> 8;
-		page[3] = total_len & 0xff;
-	} else if (6 == cmd_head.wr) {
-		/* Read error code! */
-	} else if (8 == cmd_head.wr) { /*Read driver version */
-		/* memcpy(page, GTP_DRIVER_VERSION,
-				strlen(GTP_DRIVER_VERSION)); */
-		s32 tmp_len;
-		tmp_len = strlen(GTP_DRIVER_VERSION);
-		memcpy(page, GTP_DRIVER_VERSION, tmp_len);
-		page[tmp_len] = 0;
+		if (tool_i2c_read(cmd_head.data, data_len) <= 0) {
+			dev_err(&gt_client->dev, "Read data failed!\n");
+			ret = -EIO;
+			goto exit;
+		}
+		ret = simple_read_from_buffer(user_buf, count, ppos,
+			&cmd_head.data[GTP_ADDR_LENGTH], data_len);
+		break;
+	case GTP_RW_FILL_INFO:
+		ret = fill_update_info(user_buf, count, ppos);
+		break;
+	case GTP_RW_READ_VERSION:
+		/* Read driver version */
+		data_len = scnprintf(buf, sizeof(buf), "%s\n",
+			GTP_DRIVER_VERSION);
+		ret = simple_read_from_buffer(user_buf, count, ppos,
+			buf, data_len);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
 	}
-	ret = cmd_head.data_len;
 
 exit:
 	mutex_unlock(&lock);
 	return ret;
 }
+
+static const struct file_operations goodix_proc_fops = {
+	.write = goodix_tool_write,
+	.read = goodix_tool_read,
+	.open = simple_open,
+	.owner = THIS_MODULE,
+};
+
+s32 init_wr_node(struct i2c_client *client)
+{
+	u8 i;
+
+	gt_client = client;
+	memset(&cmd_head, 0, sizeof(cmd_head));
+	cmd_head.data = NULL;
+
+	i = GTP_I2C_RETRY_5;
+	while ((!cmd_head.data) && i) {
+		cmd_head.data = devm_kzalloc(&client->dev,
+				i * DATA_LENGTH_UINT, GFP_KERNEL);
+		if (cmd_head.data)
+			break;
+		i--;
+	}
+	if (i) {
+		data_length = i * DATA_LENGTH_UINT;
+		dev_dbg(&client->dev, "Applied memory size:%d.", data_length);
+	} else {
+		dev_err(&client->dev, "Apply for memory failed.");
+		return FAIL;
+	}
+
+	cmd_head.addr_len = 2;
+	cmd_head.retry = GTP_I2C_RETRY_5;
+
+	register_i2c_func();
+
+	mutex_init(&lock);
+	tool_set_proc_name(procname);
+	goodix_proc_entry = proc_create(procname,
+			S_IWUSR | S_IWGRP | S_IRUSR | S_IRGRP,
+			goodix_proc_entry,
+			&goodix_proc_fops);
+	if (goodix_proc_entry == NULL) {
+		dev_err(&client->dev, "Couldn't create proc entry!");
+		return FAIL;
+	}
+
+	return SUCCESS;
+}
diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.c b/drivers/input/touchscreen/gt9xx/gt9xx.c
index 6d4c638..a71526a 100644
--- a/drivers/input/touchscreen/gt9xx/gt9xx.c
+++ b/drivers/input/touchscreen/gt9xx/gt9xx.c
@@ -47,17 +47,16 @@
 #include "gt9xx.h"
 
 #include <linux/of_gpio.h>
-
+#include <linux/irq.h>
+#include <linux/module.h>
 #include <linux/input/mt.h>
+#include <linux/debugfs.h>
 
 #define GOODIX_DEV_NAME	"Goodix-CTP"
 #define CFG_MAX_TOUCH_POINTS	5
 #define GOODIX_COORDS_ARR_SIZE	4
 #define MAX_BUTTONS		4
 
-/* HIGH: 0x28/0x29, LOW: 0xBA/0xBB */
-#define GTP_I2C_ADDRESS_HIGH	0x14
-#define GTP_I2C_ADDRESS_LOW	0x5D
 #define CFG_GROUP_LEN(p_cfg_grp)  (sizeof(p_cfg_grp) / sizeof(p_cfg_grp[0]))
 
 #define GOODIX_VTG_MIN_UV	2600000
@@ -82,17 +81,8 @@
 static const u16 touch_key_array[] = {KEY_MENU, KEY_HOMEPAGE, KEY_BACK};
 #define GTP_MAX_KEY_NUM  (sizeof(touch_key_array)/sizeof(touch_key_array[0]))
 
-#if GTP_DEBUG_ON
-static const int  key_codes[] = {
-	KEY_HOME, KEY_BACK, KEY_MENU, KEY_SEARCH
-};
-static const char *const key_names[] = {
-	"Key_Home", "Key_Back", "Key_Menu", "Key_Search"
-};
-#endif
 #endif
 
-static void gtp_reset_guitar(struct goodix_ts_data *ts, int ms);
 static void gtp_int_sync(struct goodix_ts_data *ts, int ms);
 static int gtp_i2c_test(struct i2c_client *client);
 static int goodix_power_off(struct goodix_ts_data *ts);
@@ -100,7 +90,9 @@
 
 #if defined(CONFIG_FB)
 static int fb_notifier_callback(struct notifier_block *self,
-				 unsigned long event, void *data);
+				unsigned long event, void *data);
+static int goodix_ts_suspend(struct device *dev);
+static int goodix_ts_resume(struct device *dev);
 #elif defined(CONFIG_HAS_EARLYSUSPEND)
 static void goodix_ts_early_suspend(struct early_suspend *h);
 static void goodix_ts_late_resume(struct early_suspend *h);
@@ -111,7 +103,6 @@
 static struct workqueue_struct *gtp_esd_check_workqueue;
 static void gtp_esd_check_func(struct work_struct *work);
 static int gtp_init_ext_watchdog(struct i2c_client *client);
-struct i2c_client  *i2c_connect_client;
 #endif
 
 #if GTP_SLIDE_WAKEUP
@@ -126,6 +117,10 @@
 bool init_done;
 static u8 chip_gt9xxs;  /* true if ic is gt9xxs, like gt915s */
 u8 grp_cfg_version;
+struct i2c_client  *i2c_connect_client;
+
+#define GTP_DEBUGFS_DIR			"ts_debug"
+#define GTP_DEBUGFS_FILE_SUSPEND	"suspend"
 
 /*******************************************************
 Function:
@@ -142,27 +137,30 @@
 int gtp_i2c_read(struct i2c_client *client, u8 *buf, int len)
 {
 	struct goodix_ts_data *ts = i2c_get_clientdata(client);
-	struct i2c_msg msgs[2];
 	int ret = -EIO;
-	int retries = 0;
+	u8 retries;
+	struct i2c_msg msgs[2] = {
+		{
+			.flags	= !I2C_M_RD,
+			.addr	= client->addr,
+			.len	= GTP_ADDR_LENGTH,
+			.buf	= &buf[0],
+		},
+		{
+			.flags	= I2C_M_RD,
+			.addr	= client->addr,
+			.len	= len - GTP_ADDR_LENGTH,
+			.buf	= &buf[GTP_ADDR_LENGTH],
+		},
+	};
 
-	msgs[0].flags = !I2C_M_RD;
-	msgs[0].addr = client->addr;
-	msgs[0].len = GTP_ADDR_LENGTH;
-	msgs[0].buf = &buf[0];
-
-	msgs[1].flags = I2C_M_RD;
-	msgs[1].addr = client->addr;
-	msgs[1].len = len - GTP_ADDR_LENGTH;
-	msgs[1].buf = &buf[GTP_ADDR_LENGTH];
-
-	while (retries < 5) {
+	for (retries = 0; retries < GTP_I2C_RETRY_5; retries++) {
 		ret = i2c_transfer(client->adapter, msgs, 2);
 		if (ret == 2)
 			break;
-		retries++;
+		dev_err(&client->dev, "I2C retry: %d\n", retries + 1);
 	}
-	if (retries >= 5) {
+	if (retries == GTP_I2C_RETRY_5) {
 #if GTP_SLIDE_WAKEUP
 		/* reset chip would quit doze mode */
 		if (DOZE_ENABLED == doze_status)
@@ -172,7 +170,7 @@
 			gtp_reset_guitar(ts, 10);
 		else
 			dev_warn(&client->dev,
-				"<GTP> gtp_reset_guitar exit init_done=%d:\n",
+				"gtp_reset_guitar exit init_done=%d:\n",
 				init_done);
 	}
 	return ret;
@@ -193,22 +191,22 @@
 int gtp_i2c_write(struct i2c_client *client, u8 *buf, int len)
 {
 	struct goodix_ts_data *ts = i2c_get_clientdata(client);
-	struct i2c_msg msg;
 	int ret = -EIO;
-	int retries = 0;
+	u8 retries;
+	struct i2c_msg msg = {
+		.flags = !I2C_M_RD,
+		.addr = client->addr,
+		.len = len,
+		.buf = buf,
+	};
 
-	msg.flags = !I2C_M_RD;
-	msg.addr = client->addr;
-	msg.len = len;
-	msg.buf = buf;
-
-	while (retries < 5) {
+	for (retries = 0; retries < GTP_I2C_RETRY_5; retries++) {
 		ret = i2c_transfer(client->adapter, &msg, 1);
 		if (ret == 1)
 			break;
-		retries++;
+		dev_err(&client->dev, "I2C retry: %d\n", retries + 1);
 	}
-	if ((retries >= 5)) {
+	if ((retries == GTP_I2C_RETRY_5)) {
 #if GTP_SLIDE_WAKEUP
 		if (DOZE_ENABLED == doze_status)
 			return ret;
@@ -217,11 +215,12 @@
 			gtp_reset_guitar(ts, 10);
 		else
 			dev_warn(&client->dev,
-				"<GTP> gtp_reset_guitar exit init_done=%d:\n",
+				"gtp_reset_guitar exit init_done=%d:\n",
 				init_done);
 	}
 	return ret;
 }
+
 /*******************************************************
 Function:
 	i2c read twice, compare the results
@@ -241,7 +240,7 @@
 	u8 confirm_buf[16] = {0};
 	u8 retry = 0;
 
-	while (retry++ < 3) {
+	while (retry++ < GTP_I2C_RETRY_3) {
 		memset(buf, 0xAA, 16);
 		buf[0] = (u8)(addr >> 8);
 		buf[1] = (u8)(addr & 0xFF);
@@ -255,7 +254,7 @@
 		if (!memcmp(buf, confirm_buf, len + 2))
 			break;
 	}
-	if (retry < 3) {
+	if (retry < GTP_I2C_RETRY_3) {
 		memcpy(rxbuf, confirm_buf + 2, len);
 		return SUCCESS;
 	} else {
@@ -275,7 +274,7 @@
 	result of i2c write operation.
 	> 0: succeed, otherwise: failed
 *********************************************************/
-static int gtp_send_cfg(struct goodix_ts_data *ts)
+int gtp_send_cfg(struct goodix_ts_data *ts)
 {
 	int ret;
 #if GTP_DRIVER_SEND_CFG
@@ -286,7 +285,7 @@
 			"Ic fixed config, no config sent!");
 		ret = 2;
 	} else {
-		for (retry = 0; retry < 5; retry++) {
+		for (retry = 0; retry < GTP_I2C_RETRY_5; retry++) {
 			ret = gtp_i2c_write(ts->client,
 				ts->config_data,
 				GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH);
@@ -498,31 +497,19 @@
 		memcpy(&point_data[12], &buf[2], 8 * (touch_num - 1));
 	}
 
-#if GTP_HAVE_TOUCH_KEY
+
 	key_value = point_data[3 + 8 * touch_num];
 
 	if (key_value || pre_key) {
-		for (i = 0; i < GTP_MAX_KEY_NUM; i++) {
-
-#if GTP_DEBUG_ON
-			for (ret = 0; ret < 4; ++ret) {
-				if (key_codes[ret] == touch_key_array[i]) {
-					GTP_DEBUG("Key: %s %s",
-						key_names[ret],
-						(key_value & (0x01 << i))
-						? "Down" : "Up");
-					break;
-				}
-			}
-#endif
-
+		for (i = 0; i < ts->pdata->num_button; i++) {
 			input_report_key(ts->input_dev,
-				touch_key_array[i], key_value & (0x01<<i));
+				ts->pdata->button_map[i],
+				key_value & (0x01<<i));
 		}
 		touch_num = 0;
 		pre_touch = 0;
 	}
-#endif
+
 	pre_key = key_value;
 
 #if GTP_WITH_PEN
@@ -618,26 +605,6 @@
 
 /*******************************************************
 Function:
-	Timer interrupt service routine for polling mode.
-Input:
-	timer: timer struct pointer
-Output:
-	Timer work mode.
-	HRTIMER_NORESTART: no restart mode
-*********************************************************/
-static enum hrtimer_restart goodix_ts_timer_handler(struct hrtimer *timer)
-{
-	struct goodix_ts_data
-		*ts = container_of(timer, struct goodix_ts_data, timer);
-
-	queue_work(ts->goodix_wq, &ts->work);
-	hrtimer_start(&ts->timer, ktime_set(0, (GTP_POLL_TIME + 6) * 1000000),
-			HRTIMER_MODE_REL);
-	return HRTIMER_NORESTART;
-}
-
-/*******************************************************
-Function:
 	External interrupt service routine for interrupt mode.
 Input:
 	irq:  interrupt number.
@@ -679,7 +646,7 @@
 Output:
 	None.
 *******************************************************/
-static void gtp_reset_guitar(struct goodix_ts_data *ts, int ms)
+void gtp_reset_guitar(struct goodix_ts_data *ts, int ms)
 {
 	/* This reset sequence will selcet I2C slave address */
 	gpio_direction_output(ts->pdata->reset_gpio, 0);
@@ -726,7 +693,7 @@
 #endif
 	gtp_irq_disable(ts);
 
-	while (retry++ < 5) {
+	while (retry++ < GTP_I2C_RETRY_3) {
 		i2c_control_buf[0] = 0x80;
 		i2c_control_buf[1] = 0x46;
 		ret = gtp_i2c_write(ts->client, i2c_control_buf, 3);
@@ -786,7 +753,7 @@
 		return 0;
 	} else {
 		usleep(5000);
-		while (retry++ < 5) {
+		while (retry++ < GTP_I2C_RETRY_5) {
 			ret = gtp_i2c_write(ts->client, i2c_control_buf, 3);
 			if (ret == 1) {
 				dev_dbg(&ts->client->dev, "GTP enter sleep!");
@@ -1074,7 +1041,7 @@
 
 	ret = gtp_i2c_read(client, buf, sizeof(buf));
 	if (ret < 0) {
-		dev_err(&client->dev, "GTP read version failed.\n");
+		dev_err(&client->dev, "GTP read product_id failed.\n");
 		return -EIO;
 	}
 
@@ -1109,7 +1076,7 @@
 static int gtp_i2c_test(struct i2c_client *client)
 {
 	u8 buf[3] = { GTP_REG_CONFIG_DATA >> 8, GTP_REG_CONFIG_DATA & 0xff };
-	int retry = 5;
+	int retry = GTP_I2C_RETRY_5;
 	int ret = -EIO;
 
 	while (retry--) {
@@ -1214,7 +1181,7 @@
 *******************************************************/
 static int gtp_request_irq(struct goodix_ts_data *ts)
 {
-	int ret;
+	int ret = 0;
 	const u8 irq_table[] = GTP_IRQ_TAB;
 
 	ret = request_threaded_irq(ts->client->irq, NULL,
@@ -1222,21 +1189,12 @@
 			irq_table[ts->int_trigger_type],
 			ts->client->name, ts);
 	if (ret) {
-		dev_err(&ts->client->dev, "Request IRQ failed!ERRNO:%d.\n",
-				ret);
-		gpio_direction_input(ts->pdata->irq_gpio);
-
-		hrtimer_init(&ts->timer, CLOCK_MONOTONIC,
-				HRTIMER_MODE_REL);
-		ts->timer.function = goodix_ts_timer_handler;
-		hrtimer_start(&ts->timer, ktime_set(1, 0),
-				HRTIMER_MODE_REL);
 		ts->use_irq = false;
 		return ret;
 	} else {
 		gtp_irq_disable(ts);
 		ts->use_irq = true;
-		return 0;
+		return ret;
 	}
 }
 
@@ -1270,12 +1228,12 @@
 	__set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit);
 	input_mt_init_slots(ts->input_dev, 10);/* in case of "out of memory" */
 
-#if GTP_HAVE_TOUCH_KEY
-	for (index = 0; index < GTP_MAX_KEY_NUM; index++) {
+
+	for (index = 0; index < ts->pdata->num_button; index++) {
 		input_set_capability(ts->input_dev,
-				EV_KEY, touch_key_array[index]);
+				EV_KEY, ts->pdata->button_map[index]);
 	}
-#endif
+
 
 #if GTP_SLIDE_WAKEUP
 	input_set_capability(ts->input_dev, EV_KEY, KEY_POWER);
@@ -1583,6 +1541,56 @@
 	.attrs = gtp_attrs,
 };
 
+static int gtp_debug_suspend_set(void *_data, u64 val)
+{
+	struct goodix_ts_data *ts = _data;
+
+	mutex_lock(&ts->input_dev->mutex);
+	if (val)
+		goodix_ts_suspend(&ts->client->dev);
+	else
+		goodix_ts_resume(&ts->client->dev);
+	mutex_unlock(&ts->input_dev->mutex);
+
+	return 0;
+}
+
+static int gtp_debug_suspend_get(void *_data, u64 *val)
+{
+	struct goodix_ts_data *ts = _data;
+
+	mutex_lock(&ts->input_dev->mutex);
+	*val = ts->gtp_is_suspend;
+	mutex_unlock(&ts->input_dev->mutex);
+
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, gtp_debug_suspend_get,
+			gtp_debug_suspend_set, "%lld\n");
+
+static int gtp_debugfs_init(struct goodix_ts_data *data)
+{
+	data->debug_base = debugfs_create_dir(GTP_DEBUGFS_DIR, NULL);
+
+	if (IS_ERR_OR_NULL(data->debug_base)) {
+		pr_err("Failed to create debugfs dir.\n");
+			return -EINVAL;
+	}
+
+	if ((IS_ERR_OR_NULL(debugfs_create_file(GTP_DEBUGFS_FILE_SUSPEND,
+					S_IWUSR | S_IWGRP | S_IRUSR | S_IRGRP,
+					data->debug_base,
+					data,
+					&debug_suspend_fops)))) {
+		pr_err("Failed to create suspend file.\n");
+		debugfs_remove_recursive(data->debug_base);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static int goodix_ts_get_dt_coords(struct device *dev, char *name,
 				struct goodix_ts_platform_data *pdata)
 {
@@ -1687,6 +1695,9 @@
 			dev_err(dev, "Unable to read key codes\n");
 			return rc;
 		}
+		pdata->num_button = num_buttons;
+		memcpy(pdata->button_map, button_map,
+			pdata->num_button * sizeof(u32));
 	}
 
 	read_cfg_num = 0;
@@ -1769,7 +1780,7 @@
 		return -ENODEV;
 	}
 
-	ts = kzalloc(sizeof(*ts), GFP_KERNEL);
+	ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL);
 	if (!ts) {
 		dev_err(&client->dev, "GTP not enough memory for ts\n");
 		return -ENOMEM;
@@ -1816,7 +1827,7 @@
 		strlcpy(ts->fw_name, pdata->fw_name,
 						strlen(pdata->fw_name) + 1);
 
-#if GTP_AUTO_UPDATE
+#ifdef CONFIG_GT9XX_TOUCHPANEL_UPDATE
 	ret = gup_init_update_proc(ts);
 	if (ret < 0) {
 		dev_err(&client->dev,
@@ -1859,13 +1870,13 @@
 	INIT_WORK(&ts->work, goodix_ts_work_func);
 
 	ret = gtp_request_irq(ts);
-	if (ret < 0)
-		dev_info(&client->dev, "GTP works in polling mode.\n");
+	if (ret)
+		dev_info(&client->dev, "GTP request irq failed %d.\n", ret);
 	else
 		dev_info(&client->dev, "GTP works in interrupt mode.\n");
 
 	ret = gtp_read_fw_version(client, &version_info);
-	if (ret != 0)
+	if (ret != 2)
 		dev_err(&client->dev, "GTP firmware version read failed.\n");
 
 	ret = gtp_check_product_id(client);
@@ -1876,7 +1887,7 @@
 	if (ts->use_irq)
 		gtp_irq_enable(ts);
 
-#if GTP_CREATE_WR_NODE
+#ifdef CONFIG_GT9XX_TOUCHPANEL_DEBUG
 	init_wr_node(client);
 #endif
 
@@ -1889,6 +1900,13 @@
 		goto exit_free_irq;
 	}
 
+	ret = gtp_debugfs_init(ts);
+	if (ret != 0) {
+		dev_err(&client->dev, "Failed to create debugfs entries, %d\n",
+						ret);
+		goto exit_remove_sysfs;
+	}
+
 	init_done = true;
 	return 0;
 exit_free_irq:
@@ -1913,6 +1931,8 @@
 		input_free_device(ts->input_dev);
 		ts->input_dev = NULL;
 	}
+exit_remove_sysfs:
+	sysfs_remove_group(&ts->input_dev->dev.kobj, &gtp_attr_grp);
 exit_free_inputdev:
 	kfree(ts->config_data);
 exit_power_off:
@@ -1926,7 +1946,6 @@
 		gpio_free(pdata->irq_gpio);
 exit_free_client_data:
 	i2c_set_clientdata(client, NULL);
-	kfree(ts);
 	return ret;
 }
 
@@ -1953,7 +1972,7 @@
 #endif
 	mutex_destroy(&ts->lock);
 
-#if GTP_CREATE_WR_NODE
+#ifdef CONFIG_GT9XX_TOUCHPANEL_DEBUG
 	uninit_wr_node();
 #endif
 
@@ -1978,7 +1997,6 @@
 			input_free_device(ts->input_dev);
 			ts->input_dev = NULL;
 		}
-		kfree(ts->config_data);
 
 		if (gpio_is_valid(ts->pdata->reset_gpio))
 			gpio_free(ts->pdata->reset_gpio);
@@ -1988,8 +2006,8 @@
 		goodix_power_off(ts);
 		goodix_power_deinit(ts);
 		i2c_set_clientdata(client, NULL);
-		kfree(ts);
 	}
+	debugfs_remove_recursive(ts->debug_base);
 
 	return 0;
 }
@@ -2008,9 +2026,13 @@
 	struct goodix_ts_data *ts = dev_get_drvdata(dev);
 	int ret = 0, i;
 
+	if (ts->gtp_is_suspend) {
+		dev_dbg(&ts->client->dev, "Already in suspend state.\n");
+		return 0;
+	}
+
 	mutex_lock(&ts->lock);
 #if GTP_ESD_PROTECT
-	ts->gtp_is_suspend = 1;
 	gtp_esd_switch(ts->client, SWITCH_OFF);
 #endif
 
@@ -2036,6 +2058,7 @@
 	 */
 	msleep(58);
 	mutex_unlock(&ts->lock);
+	ts->gtp_is_suspend = 1;
 
 	return ret;
 }
@@ -2053,6 +2076,11 @@
 	struct goodix_ts_data *ts = dev_get_drvdata(dev);
 	int ret = 0;
 
+	if (!ts->gtp_is_suspend) {
+		dev_dbg(&ts->client->dev, "Already in awake state.\n");
+		return 0;
+	}
+
 	mutex_lock(&ts->lock);
 	ret = gtp_wakeup_sleep(ts);
 
@@ -2070,10 +2098,10 @@
 			ktime_set(1, 0), HRTIMER_MODE_REL);
 
 #if GTP_ESD_PROTECT
-	ts->gtp_is_suspend = 0;
 	gtp_esd_switch(ts->client, SWITCH_ON);
 #endif
 	mutex_unlock(&ts->lock);
+	ts->gtp_is_suspend = 0;
 
 	return ret;
 }
@@ -2190,13 +2218,13 @@
 	msg.len   = 4;
 	msg.buf   = opr_buffer;
 
-	while (retries < 5) {
+	while (retries < GTP_I2C_RETRY_5) {
 		ret = i2c_transfer(client->adapter, &msg, 1);
 		if (ret == 1)
 			return 1;
 		retries++;
 	}
-	if (retries >= 5)
+	if (retries == GTP_I2C_RETRY_5)
 		dev_err(&client->dev, "init external watchdog failed!");
 	return 0;
 }
@@ -2212,7 +2240,7 @@
 *******************************************************/
 static void gtp_esd_check_func(struct work_struct *work)
 {
-	s32 i;
+	s32 retry;
 	s32 ret = -1;
 	struct goodix_ts_data *ts = NULL;
 	u8 test[4] = {0x80, 0x40};
@@ -2229,7 +2257,7 @@
 		return;
 #endif
 
-	for (i = 0; i < 3; i++) {
+	for (retry = 0; retry < GTP_I2C_RETRY_3; retry++) {
 		ret = gtp_i2c_read(ts->client, test, 4);
 
 		if ((ret < 0)) {
@@ -2238,7 +2266,7 @@
 		} else {
 			if ((test[2] == 0xAA) || (test[3] != 0xAA)) {
 				/* IC works abnormally..*/
-				i = 3;
+				retry = GTP_I2C_RETRY_3;
 				break;
 			} else {
 				/* IC works normally, Write 0x8040 0xAA*/
@@ -2248,7 +2276,7 @@
 			}
 		}
 	}
-	if (i >= 3) {
+	if (retry == GTP_I2C_RETRY_3) {
 		dev_err(&ts->client->dev,
 			"IC Working ABNORMALLY, Resetting Guitar...\n");
 		gtp_reset_guitar(ts, 50);
diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.h b/drivers/input/touchscreen/gt9xx/gt9xx.h
index 1d31f2a..6e59b29 100644
--- a/drivers/input/touchscreen/gt9xx/gt9xx.h
+++ b/drivers/input/touchscreen/gt9xx/gt9xx.h
@@ -25,18 +25,9 @@
 
 #include <linux/kernel.h>
 #include <linux/i2c.h>
-#include <linux/irq.h>
-#include <linux/input.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
 #include <linux/delay.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/gpio.h>
-#include <linux/regulator/consumer.h>
-#include <linux/firmware.h>
-#include <linux/debugfs.h>
-#include <linux/mutex.h>
+#include <linux/uaccess.h>
 
 #if defined(CONFIG_FB)
 #include <linux/notifier.h>
@@ -46,6 +37,7 @@
 #define GOODIX_SUSPEND_LEVEL 1
 #endif
 
+#define MAX_BUTTONS 4
 #define GOODIX_MAX_CFG_GROUP	6
 #define GTP_FW_NAME_MAXSIZE	50
 
@@ -69,6 +61,8 @@
 	bool enable_power_off;
 	size_t config_data_len[GOODIX_MAX_CFG_GROUP];
 	u8 *config_data[GOODIX_MAX_CFG_GROUP];
+	u32 button_map[MAX_BUTTONS];
+	u8 num_button;
 };
 struct goodix_ts_data {
 	spinlock_t irq_lock;
@@ -79,6 +73,7 @@
 	struct workqueue_struct *goodix_wq;
 	struct work_struct	work;
 	char fw_name[GTP_FW_NAME_MAXSIZE];
+	struct delayed_work goodix_update_work;
 	s32 irq_is_disabled;
 	s32 use_irq;
 	u16 abs_x_max;
@@ -105,6 +100,7 @@
 #elif defined(CONFIG_HAS_EARLYSUSPEND)
 	struct early_suspend early_suspend;
 #endif
+	struct dentry *debug_base;
 };
 
 extern u16 show_len;
@@ -116,13 +112,10 @@
 #define GTP_DRIVER_SEND_CFG		1
 #define GTP_HAVE_TOUCH_KEY		1
 
-/* auto updated by .bin file as default */
-#define GTP_AUTO_UPDATE			0
 /* auto updated by head_fw_array in gt9xx_firmware.h,
- * function together with GTP_AUTO_UPDATE */
+ * function together with CONFIG_GT9XX_TOUCHPANEL_UPDATE */
 #define GTP_HEADER_FW_UPDATE	0
 
-#define GTP_CREATE_WR_NODE		0
 #define GTP_ESD_PROTECT			0
 #define GTP_WITH_PEN			0
 
@@ -131,30 +124,14 @@
 /* double-click wakeup, function together with GTP_SLIDE_WAKEUP */
 #define GTP_DBL_CLK_WAKEUP		0
 
-#define GTP_DEBUG_ON			0
-#define GTP_DEBUG_ARRAY_ON		0
-#define GTP_DEBUG_FUNC_ON		0
-
-/*************************** PART2:TODO define *******************************/
-/* STEP_1(REQUIRED): Define Configuration Information Group(s) */
-/* Sensor_ID Map: */
-/* sensor_opt1 sensor_opt2 Sensor_ID
- *	GND			GND			0
- *	VDDIO		GND			1
- *	NC			GND			2
- *	GND			NC/300K		3
- *	VDDIO		NC/300K		4
- *	NC			NC/300K		5
-*/
-
-#define GTP_IRQ_TAB		{\
+#define GTP_IRQ_TAB            {\
 				IRQ_TYPE_EDGE_RISING,\
 				IRQ_TYPE_EDGE_FALLING,\
 				IRQ_TYPE_LEVEL_LOW,\
 				IRQ_TYPE_LEVEL_HIGH\
 				}
 
-/* STEP_3(optional): Specify your special config info if needed */
+
 #define GTP_IRQ_TAB_RISING	0
 #define GTP_IRQ_TAB_FALLING	1
 #if GTP_CUSTOM_CFG
@@ -193,53 +170,61 @@
 #define GTP_REG_FW_VERSION	0x8144
 #define GTP_REG_PRODUCT_ID	0x8140
 
+#define GTP_I2C_RETRY_3		3
+#define GTP_I2C_RETRY_5		5
+#define GTP_I2C_RETRY_10	10
+
 #define RESOLUTION_LOC		3
 #define TRIGGER_LOC		8
 
+/* HIGH: 0x28/0x29, LOW: 0xBA/0xBB */
+#define GTP_I2C_ADDRESS_HIGH	0x14
+#define GTP_I2C_ADDRESS_LOW	0x5D
+
 #define CFG_GROUP_LEN(p_cfg_grp) (sizeof(p_cfg_grp) / sizeof(p_cfg_grp[0]))
-/* Log define */
-#define GTP_DEBUG(fmt, arg...)	do {\
-		if (GTP_DEBUG_ON) {\
-			pr_debug("<<-GTP-DEBUG->> [%d]"fmt"\n",\
-				__LINE__, ##arg); } \
-		} while (0)
 
-#define GTP_DEBUG_ARRAY(array, num)    do {\
-		s32 i; \
-		u8 *a = array; \
-		if (GTP_DEBUG_ARRAY_ON) {\
-			pr_debug("<<-GTP-DEBUG-ARRAY->>\n");\
-			for (i = 0; i < (num); i++) { \
-				pr_debug("%02x   ", (a)[i]);\
-				if ((i + 1) % 10 == 0) { \
-					pr_debug("\n");\
-				} \
-			} \
-			pr_debug("\n");\
-		} \
-	} while (0)
+/* GTP CM_HEAD RW flags */
+#define GTP_RW_READ			0
+#define GTP_RW_WRITE			1
+#define GTP_RW_READ_IC_TYPE		2
+#define GTP_RW_WRITE_IC_TYPE		3
+#define GTP_RW_FILL_INFO		4
+#define GTP_RW_NO_WRITE			5
+#define GTP_RW_READ_ERROR		6
+#define GTP_RW_DISABLE_IRQ		7
+#define GTP_RW_READ_VERSION		8
+#define GTP_RW_ENABLE_IRQ		9
+#define GTP_RW_ENTER_UPDATE_MODE	11
+#define GTP_RW_LEAVE_UPDATE_MODE	13
+#define GTP_RW_UPDATE_FW		15
+#define GTP_RW_CHECK_RAWDIFF_MODE	17
 
-#define GTP_DEBUG_FUNC()	do {\
-	if (GTP_DEBUG_FUNC_ON)\
-		pr_debug("<<-GTP-FUNC->> Func:%s@Line:%d\n",\
-					__func__, __LINE__);\
-	} while (0)
+/* GTP need flag or interrupt */
+#define GTP_NO_NEED			0
+#define GTP_NEED_FLAG			1
+#define GTP_NEED_INTERRUPT		2
 
-#define GTP_SWAP(x, y)		do {\
-					typeof(x) z = x;\
-					x = y;\
-					y = z;\
-				} while (0)
 /*****************************End of Part III********************************/
 
 void gtp_esd_switch(struct i2c_client *client, int on);
 
-#if GTP_CREATE_WR_NODE
-extern s32 init_wr_node(struct i2c_client *client);
-extern void uninit_wr_node(void);
+int gtp_i2c_read_dbl_check(struct i2c_client *client, u16 addr,
+					u8 *rxbuf, int len);
+int gtp_send_cfg(struct goodix_ts_data *ts);
+void gtp_reset_guitar(struct goodix_ts_data *ts, int ms);
+void gtp_irq_disable(struct goodix_ts_data *ts);
+void gtp_irq_enable(struct goodix_ts_data *ts);
+
+#ifdef CONFIG_GT9XX_TOUCHPANEL_DEBUG
+s32 init_wr_node(struct i2c_client *client);
+void uninit_wr_node(void);
 #endif
 
-#if GTP_AUTO_UPDATE
+#ifdef CONFIG_GT9XX_TOUCHPANEL_UPDATE
 extern u8 gup_init_update_proc(struct goodix_ts_data *ts);
+s32 gup_enter_update_mode(struct i2c_client *client);
+void gup_leave_update_mode(struct i2c_client *client);
+s32 gup_update_proc(void *dir);
+extern struct i2c_client  *i2c_connect_client;
 #endif
 #endif /* _GOODIX_GT9XX_H_ */
diff --git a/drivers/input/touchscreen/gt9xx/gt9xx_update.c b/drivers/input/touchscreen/gt9xx/gt9xx_update.c
index cf83154..6d30f0c 100644
--- a/drivers/input/touchscreen/gt9xx/gt9xx_update.c
+++ b/drivers/input/touchscreen/gt9xx/gt9xx_update.c
@@ -31,8 +31,10 @@
  *          2. support firmware header array update.
  *                          By Meta, 2013/03/11
  */
-#include <linux/kthread.h>
 #include "gt9xx.h"
+#include <linux/firmware.h>
+#include <linux/workqueue.h>
+#include <linux/kernel.h>
 
 #if GTP_HEADER_FW_UPDATE
 #include <linux/namei.h>
@@ -40,16 +42,14 @@
 #include "gt9xx_firmware.h"
 #endif
 
+#define FIRMWARE_NAME_LEN_MAX		256
+
 #define GUP_REG_HW_INFO             0x4220
 #define GUP_REG_FW_MSG              0x41E4
 #define GUP_REG_PID_VID             0x8140
 
-#define GUP_SEARCH_FILE_TIMES       50
-#define UPDATE_FILE_PATH_2          "/data/_goodix_update_.bin"
-#define UPDATE_FILE_PATH_1          "/sdcard/_goodix_update_.bin"
-
-#define CONFIG_FILE_PATH_1          "/data/_goodix_config_.cfg"
-#define CONFIG_FILE_PATH_2          "/sdcard/_goodix_config_.cfg"
+#define GOODIX_FIRMWARE_FILE_NAME	"_goodix_update_.bin"
+#define GOODIX_CONFIG_FILE_NAME		"_goodix_config_.cfg"
 
 #define FW_HEAD_LENGTH               14
 #define FW_SECTION_LENGTH            0x2000
@@ -73,24 +73,22 @@
 #define FAIL    0
 #define SUCCESS 1
 
-#pragma pack(1)
-struct {
+struct st_fw_head {
 	u8  hw_info[4];		/* hardware info */
 	u8  pid[8];		/* product id   */
 	u16 vid;		/* version id   */
-} st_fw_head;
-#pragma pack()
+} __packed;
 
-struct {
+struct st_update_msg {
 	u8 force_update;
 	u8 fw_flag;
-	struct file *file;
-	struct file *cfg_file;
-	st_fw_head  ic_fw_msg;
-	mm_segment_t old_fs;
-} st_update_msg;
+	bool need_free;
+	u8 *fw_data;
+	u32 fw_len;
+	struct st_fw_head  ic_fw_msg;
+};
 
-st_update_msg update_msg;
+static struct st_update_msg update_msg;
 u16 show_len;
 u16 total_len;
 u8 got_file_flag;
@@ -107,25 +105,24 @@
     numbers of i2c_msgs to transfer:
       2: succeed, otherwise: failed
 *********************************************************/
-s32 gup_i2c_read(struct i2c_client *client, u8 *buf, s32 len)
+static s32 gup_i2c_read(struct i2c_client *client, u8 *buf, s32 len)
 {
-	struct i2c_msg msgs[2];
 	s32 ret = -1;
-	s32 retries = 0;
-
-	GTP_DEBUG_FUNC();
-
-	msgs[0].flags = !I2C_M_RD;
-	msgs[0].addr  = client->addr;
-	msgs[0].len   = GTP_ADDR_LENGTH;
-	msgs[0].buf   = &buf[0];
-	/* msgs[0].scl_rate = 300 * 1000;  (for Rockchip) */
-
-	msgs[1].flags = I2C_M_RD;
-	msgs[1].addr  = client->addr;
-	msgs[1].len   = len - GTP_ADDR_LENGTH;
-	msgs[1].buf   = &buf[GTP_ADDR_LENGTH];
-	/* msgs[1].scl_rate = 300 * 1000; */
+	u8 retries = 0;
+	struct i2c_msg msgs[2] = {
+		{
+			.flags = !I2C_M_RD,
+			.addr  = client->addr,
+			.len   = GTP_ADDR_LENGTH,
+			.buf   = &buf[0],
+		},
+		{
+			.flags = I2C_M_RD,
+			.addr  = client->addr,
+			.len   = len - GTP_ADDR_LENGTH,
+			.buf   = &buf[GTP_ADDR_LENGTH],
+		},
+	};
 
 	while (retries < 5) {
 		ret = i2c_transfer(client->adapter, msgs, 2);
@@ -134,6 +131,11 @@
 		retries++;
 	}
 
+	if (retries == 5) {
+		dev_err(&client->dev, "I2C read retry limit over.\n");
+		ret = -EIO;
+	}
+
 	return ret;
 }
 
@@ -151,17 +153,14 @@
 *********************************************************/
 s32 gup_i2c_write(struct i2c_client *client, u8 *buf, s32 len)
 {
-	struct i2c_msg msg;
 	s32 ret = -1;
-	s32 retries = 0;
-
-	GTP_DEBUG_FUNC();
-
-	msg.flags = !I2C_M_RD;
-	msg.addr  = client->addr;
-	msg.len   = len;
-	msg.buf   = buf;
-	/* msg.scl_rate = 300 * 1000;    (for Rockchip) */
+	u8 retries = 0;
+	struct i2c_msg msg = {
+		.flags = !I2C_M_RD,
+		.addr  = client->addr,
+		.len   = len,
+		.buf   = buf,
+	};
 
 	while (retries < 5) {
 		ret = i2c_transfer(client->adapter, &msg, 1);
@@ -170,123 +169,105 @@
 		retries++;
 	}
 
+	if (retries == 5) {
+		dev_err(&client->dev, "I2C write retry limit over.\n");
+		ret = -EIO;
+	}
+
 	return ret;
 }
 
 static s32 gup_init_panel(struct goodix_ts_data *ts)
 {
+	struct i2c_client *client = ts->client;
+	u8 *config_data;
 	s32 ret = 0;
 	s32 i = 0;
 	u8 check_sum = 0;
 	u8 opr_buf[16];
 	u8 sensor_id = 0;
 
-	u8 cfg_info_group1[] = CTP_CFG_GROUP1;
-	u8 cfg_info_group2[] = CTP_CFG_GROUP2;
-	u8 cfg_info_group3[] = CTP_CFG_GROUP3;
-	u8 cfg_info_group4[] = CTP_CFG_GROUP4;
-	u8 cfg_info_group5[] = CTP_CFG_GROUP5;
-	u8 cfg_info_group6[] = CTP_CFG_GROUP6;
-	u8 *send_cfg_buf[] = {cfg_info_group1, cfg_info_group2, cfg_info_group3,
-			cfg_info_group4, cfg_info_group5, cfg_info_group6};
-	u8 cfg_info_len[] = { CFG_GROUP_LEN(cfg_info_group1),
-			CFG_GROUP_LEN(cfg_info_group2),
-			CFG_GROUP_LEN(cfg_info_group3),
-			CFG_GROUP_LEN(cfg_info_group4),
-			CFG_GROUP_LEN(cfg_info_group5),
-			CFG_GROUP_LEN(cfg_info_group6)};
+	for (i = 0; i < GOODIX_MAX_CFG_GROUP; i++)
+		if (ts->pdata->config_data_len[i])
+			break;
 
-	if ((!cfg_info_len[1]) && (!cfg_info_len[2]) &&
-	(!cfg_info_len[3]) && (!cfg_info_len[4]) &&
-	(!cfg_info_len[5])) {
+	if (i == GOODIX_MAX_CFG_GROUP) {
 		sensor_id = 0;
 	} else {
-		ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_SENSOR_ID,
+		ret = gtp_i2c_read_dbl_check(client, GTP_REG_SENSOR_ID,
 							&sensor_id, 1);
 		if (SUCCESS == ret) {
-			if (sensor_id >= 0x06) {
-				GTP_ERROR("Invalid sensor_id(0x%02X), " \
-					"No Config Sent!", sensor_id);
+			if (sensor_id >= GOODIX_MAX_CFG_GROUP) {
+				pr_err("Invalid sensor_id(0x%02X), No Config Sent!",
+					sensor_id);
 				return -EINVAL;
 			}
 		} else {
-			GTP_ERROR("Failed to get sensor_id, No config sent!");
+			pr_err("Failed to get sensor_id, No config sent!");
 			return -EINVAL;
 		}
 	}
 
-	GTP_DEBUG("Sensor_ID: %d", sensor_id);
+	pr_debug("Sensor ID selected: %d", sensor_id);
 
-	ts->gtp_cfg_len = cfg_info_len[sensor_id];
-
-	if (ts->gtp_cfg_len < GTP_CONFIG_MIN_LENGTH) {
-		GTP_ERROR("Sensor_ID(%d) matches with NULL or INVALID CONFIG" \
-			" GROUP! NO Config Sent! You need to check you header" \
-			"  file CFG_GROUP section!", sensor_id);
+	if (ts->pdata->config_data_len[sensor_id] < GTP_CONFIG_MIN_LENGTH ||
+		!ts->pdata->config_data_len[sensor_id]) {
+		pr_err("Sensor_ID(%d) matches with NULL or INVALID CONFIG GROUP!",
+				sensor_id);
 		return -EINVAL;
 	}
 
-	ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_CONFIG_DATA,
+	ret = gtp_i2c_read_dbl_check(client, GTP_REG_CONFIG_DATA,
 					&opr_buf[0], 1);
-
 	if (ret == SUCCESS) {
-		GTP_DEBUG("CFG_GROUP%d Config Version: %d, IC Config Version:" \
-		" %d", sensor_id+1, send_cfg_buf[sensor_id][0],	opr_buf[0]);
+		pr_debug("CFG_GROUP%d Config Version: %d, IC Config Version: %d",
+			sensor_id + 1,
+			ts->pdata->config_data[sensor_id][0],
+			opr_buf[0]);
 
-		send_cfg_buf[sensor_id][0] = opr_buf[0];
+		ts->pdata->config_data[sensor_id][0] = opr_buf[0];
 		ts->fixed_cfg = 0;
-		/*
-		if (opr_buf[0] < 90) {
-			grp_cfg_version = send_cfg_buf[sensor_id][0];
-				*** backup group config version ***
-			send_cfg_buf[sensor_id][0] = 0x00;
-			ts->fixed_cfg = 0;
-		} else { *** treated as fixed config, not send config ***
-			GTP_INFO("Ic fixed config with config version(%d)",
-							opr_buf[0]);
-			ts->fixed_cfg = 1;
-		}*/
 	} else {
-		GTP_ERROR("Failed to get ic config version!No config sent!");
+		pr_err("Failed to get ic config version!No config sent!");
 		return -EINVAL;
 	}
 
-	memset(&config[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH);
-	memcpy(&config[GTP_ADDR_LENGTH], send_cfg_buf[sensor_id],
-						ts->gtp_cfg_len);
+	config_data = ts->pdata->config_data[sensor_id];
+	ts->config_data = ts->pdata->config_data[sensor_id];
+	ts->gtp_cfg_len = ts->pdata->config_data_len[sensor_id];
 
-	GTP_DEBUG("X_MAX = %d, Y_MAX = %d, TRIGGER = 0x%02x",
+	pr_debug("X_MAX = %d, Y_MAX = %d, TRIGGER = 0x%02x",
 	ts->abs_x_max, ts->abs_y_max, ts->int_trigger_type);
 
-	config[RESOLUTION_LOC]     = (u8)GTP_MAX_WIDTH;
-	config[RESOLUTION_LOC + 1] = (u8)(GTP_MAX_WIDTH>>8);
-	config[RESOLUTION_LOC + 2] = (u8)GTP_MAX_HEIGHT;
-	config[RESOLUTION_LOC + 3] = (u8)(GTP_MAX_HEIGHT>>8);
+	config_data[RESOLUTION_LOC]     = (u8)GTP_MAX_WIDTH;
+	config_data[RESOLUTION_LOC + 1] = (u8)(GTP_MAX_WIDTH>>8);
+	config_data[RESOLUTION_LOC + 2] = (u8)GTP_MAX_HEIGHT;
+	config_data[RESOLUTION_LOC + 3] = (u8)(GTP_MAX_HEIGHT>>8);
 
 	if (GTP_INT_TRIGGER == 0)  /* RISING */
-		config[TRIGGER_LOC] &= 0xfe;
+		config_data[TRIGGER_LOC] &= 0xfe;
 	else if (GTP_INT_TRIGGER == 1)  /* FALLING */
-		config[TRIGGER_LOC] |= 0x01;
+		config_data[TRIGGER_LOC] |= 0x01;
 
 	check_sum = 0;
 	for (i = GTP_ADDR_LENGTH; i < ts->gtp_cfg_len; i++)
-		check_sum += config[i];
+		check_sum += config_data[i];
 
-	config[ts->gtp_cfg_len] = (~check_sum) + 1;
+	config_data[ts->gtp_cfg_len] = (~check_sum) + 1;
 
-	GTP_DEBUG_FUNC();
-	ret = gtp_send_cfg(ts->client);
+	ret = gtp_send_cfg(ts);
 	if (ret < 0)
-		GTP_ERROR("Send config error.");
+		pr_err("Send config error.");
 
+	ts->config_data = NULL;
+	ts->gtp_cfg_len = 0;
 	msleep(20);
 	return 0;
 }
 
-
 static u8 gup_get_ic_msg(struct i2c_client *client, u16 addr, u8 *msg, s32 len)
 {
-	s32 i = 0;
+	u8 i = 0;
 
 	msg[0] = (addr >> 8) & 0xff;
 	msg[1] = addr & 0xff;
@@ -296,7 +277,7 @@
 			break;
 
 	if (i >= 5) {
-		GTP_ERROR("Read data from 0x%02x%02x failed!", msg[0], msg[1]);
+		pr_err("Read data from 0x%02x%02x failed!", msg[0], msg[1]);
 		return FAIL;
 	}
 
@@ -305,19 +286,19 @@
 
 static u8 gup_set_ic_msg(struct i2c_client *client, u16 addr, u8 val)
 {
-	s32 i = 0;
-	u8 msg[3];
-
-	msg[0] = (addr >> 8) & 0xff;
-	msg[1] = addr & 0xff;
-	msg[2] = val;
+	u8 i = 0;
+	u8 msg[3] = {
+		(addr >> 8) & 0xff,
+		addr & 0xff,
+		val,
+	};
 
 	for (i = 0; i < 5; i++)
 		if (gup_i2c_write(client, msg, GTP_ADDR_LENGTH + 1) > 0)
 			break;
 
 	if (i >= 5) {
-		GTP_ERROR("Set data to 0x%02x%02x failed!", msg[0], msg[1]);
+		pr_err("Set data to 0x%02x%02x failed!", msg[0], msg[1]);
 		return FAIL;
 	}
 
@@ -335,7 +316,7 @@
 	ret = gtp_i2c_read_dbl_check(client, GUP_REG_HW_INFO,
 					&buf[GTP_ADDR_LENGTH], 4);
 	if (ret == FAIL) {
-		GTP_ERROR("[get_ic_fw_msg]get hw_info failed,exit");
+		pr_err("get hw_info failed,exit");
 		return FAIL;
 	}
 
@@ -344,7 +325,7 @@
 	for (i = 0; i < 4; i++)
 		update_msg.ic_fw_msg.hw_info[i] = buf[GTP_ADDR_LENGTH + 3 - i];
 
-	GTP_DEBUG("IC Hardware info:%02x%02x%02x%02x",
+	pr_debug("IC Hardware info:%02x%02x%02x%02x",
 		update_msg.ic_fw_msg.hw_info[0],
 		update_msg.ic_fw_msg.hw_info[1],
 		update_msg.ic_fw_msg.hw_info[2],
@@ -354,31 +335,31 @@
 	for (retry = 0; retry < 2; retry++) {
 		ret = gup_get_ic_msg(client, GUP_REG_FW_MSG, buf, 1);
 		if (ret == FAIL) {
-			GTP_ERROR("Read firmware message fail.");
+			pr_err("Read firmware message fail.");
 			return ret;
 		}
 
 		update_msg.force_update = buf[GTP_ADDR_LENGTH];
 		if ((0xBE != update_msg.force_update) && (!retry)) {
-			GTP_INFO("The check sum in ic is error.");
-			GTP_INFO("The IC will be updated by force.");
+			pr_info("The check sum in ic is error.");
+			pr_info("The IC will be updated by force.");
 			continue;
 		}
 		break;
 	}
-	GTP_DEBUG("IC force update flag:0x%x", update_msg.force_update);
+	pr_debug("IC force update flag:0x%x", update_msg.force_update);
 
 	/*  step3:get pid & vid */
 	ret = gtp_i2c_read_dbl_check(client, GUP_REG_PID_VID,
 						&buf[GTP_ADDR_LENGTH], 6);
-	if (FAIL == ret) {
-		GTP_ERROR("[get_ic_fw_msg]get pid & vid failed,exit");
+	if (ret == FAIL) {
+		pr_err("get pid & vid failed,exit");
 		return FAIL;
 	}
 
 	memset(update_msg.ic_fw_msg.pid, 0, sizeof(update_msg.ic_fw_msg.pid));
 	memcpy(update_msg.ic_fw_msg.pid, &buf[GTP_ADDR_LENGTH], 4);
-	GTP_DEBUG("IC Product id:%s", update_msg.ic_fw_msg.pid);
+	pr_debug("IC Product id:%s", update_msg.ic_fw_msg.pid);
 
 	/* GT9XX PID MAPPING
 	|-----FLASH-----RAM-----|
@@ -392,7 +373,7 @@
 	|------9110P----9111----|*/
 	if (update_msg.ic_fw_msg.pid[0] != 0) {
 		if (!memcmp(update_msg.ic_fw_msg.pid, "9111", 4)) {
-			GTP_DEBUG("IC Mapping Product id:%s",
+			pr_debug("IC Mapping Product id:%s",
 					update_msg.ic_fw_msg.pid);
 			memcpy(update_msg.ic_fw_msg.pid, "9110P", 5);
 		}
@@ -400,7 +381,7 @@
 
 	update_msg.ic_fw_msg.vid = buf[GTP_ADDR_LENGTH + 4] +
 				(buf[GTP_ADDR_LENGTH + 5] << 8);
-	GTP_DEBUG("IC version id:%04x", update_msg.ic_fw_msg.vid);
+	pr_debug("IC version id:%04x", update_msg.ic_fw_msg.vid);
 
 	return SUCCESS;
 }
@@ -408,19 +389,21 @@
 s32 gup_enter_update_mode(struct i2c_client *client)
 {
 	s32 ret = -1;
-	s32 retry = 0;
+	u8 retry = 0;
 	u8 rd_buf[3];
+	struct goodix_ts_data *ts = i2c_get_clientdata(client);
 
 	/* step1:RST output low last at least 2ms */
-	GTP_GPIO_OUTPUT(GTP_RST_PORT, 0);
-	msleep(20);
+	gpio_direction_output(ts->pdata->reset_gpio, 0);
+	usleep(20000);
 
 	/* step2:select I2C slave addr,INT:0--0xBA;1--0x28. */
-	GTP_GPIO_OUTPUT(GTP_INT_PORT, (client->addr == 0x14));
+	gpio_direction_output(ts->pdata->irq_gpio,
+			(client->addr == GTP_I2C_ADDRESS_HIGH));
 	msleep(20);
 
 	/* step3:RST output high reset guitar */
-	GTP_GPIO_OUTPUT(GTP_RST_PORT, 1);
+	gpio_direction_output(ts->pdata->reset_gpio, 1);
 
 	/* 20121211 modify start */
 	msleep(20);
@@ -428,25 +411,25 @@
 		/* step4:Hold ss51 & dsp */
 		ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C);
 		if (ret <= 0) {
-			GTP_DEBUG("Hold ss51 & dsp I2C error,retry:%d", retry);
+			pr_debug("Hold ss51 & dsp I2C error,retry:%d", retry);
 			continue;
 		}
 
 		/* step5:Confirm hold */
 		ret = gup_get_ic_msg(client, _rRW_MISCTL__SWRST_B0_, rd_buf, 1);
 		if (ret <= 0) {
-			GTP_DEBUG("Hold ss51 & dsp I2C error,retry:%d", retry);
+			pr_debug("Hold ss51 & dsp I2C error,retry:%d", retry);
 			continue;
 		}
 		if (rd_buf[GTP_ADDR_LENGTH] == 0x0C) {
-			GTP_DEBUG("Hold ss51 & dsp confirm SUCCESS");
+			pr_debug("Hold ss51 & dsp confirm SUCCESS");
 			break;
 		}
-		GTP_DEBUG("Hold ss51 & dsp confirm 0x4180 failed,value:%d",
+		pr_debug("Hold ss51 & dsp confirm 0x4180 failed,value:%d",
 					rd_buf[GTP_ADDR_LENGTH]);
 	}
 	if (retry >= 200) {
-		GTP_ERROR("Enter update Hold ss51 failed.");
+		pr_err("Enter update Hold ss51 failed.");
 		return FAIL;
 	}
 
@@ -457,12 +440,13 @@
 	return ret;
 }
 
-void gup_leave_update_mode(void)
+void gup_leave_update_mode(struct i2c_client *client)
 {
-	GTP_GPIO_AS_INT(GTP_INT_PORT);
+	struct goodix_ts_data *ts = i2c_get_clientdata(client);
 
-	GTP_DEBUG("[leave_update_mode]reset chip.");
-	gtp_reset_guitar(i2c_connect_client, 20);
+	gpio_direction_input(ts->pdata->irq_gpio);
+	pr_debug("reset chip.");
+	gtp_reset_guitar(ts, 20);
 }
 
 /*	Get the correct nvram data
@@ -483,7 +467,8 @@
 	3. IC PID == 91XX || File PID == 91XX
 */
 
-static u8 gup_enter_update_judge(st_fw_head *fw_head)
+static u8 gup_enter_update_judge(struct i2c_client *client,
+					struct st_fw_head *fw_head)
 {
 	u16 u16_tmp;
 	s32 i = 0;
@@ -491,38 +476,37 @@
 	u16_tmp = fw_head->vid;
 	fw_head->vid = (u16)(u16_tmp>>8) + (u16)(u16_tmp<<8);
 
-	GTP_DEBUG("FILE HARDWARE INFO:%02x%02x%02x%02x", fw_head->hw_info[0],
+	pr_debug("FILE HARDWARE INFO:%02x%02x%02x%02x", fw_head->hw_info[0],
 		fw_head->hw_info[1], fw_head->hw_info[2], fw_head->hw_info[3]);
-	TP_DEBUG("FILE PID:%s", fw_head->pid);
-	TP_DEBUG("FILE VID:%04x", fw_head->vid);
+	pr_debug("FILE PID:%s", fw_head->pid);
+	pr_debug("FILE VID:%04x", fw_head->vid);
 
-	TP_DEBUG("IC HARDWARE INFO:%02x%02x%02x%02x",
+	pr_debug("IC HARDWARE INFO:%02x%02x%02x%02x",
 		update_msg.ic_fw_msg.hw_info[0],
 		update_msg.ic_fw_msg.hw_info[1],
 		update_msg.ic_fw_msg.hw_info[2],
 		update_msg.ic_fw_msg.hw_info[3]);
-	TP_DEBUG("IC PID:%s", update_msg.ic_fw_msg.pid);
-	TP_DEBUG("IC VID:%04x", update_msg.ic_fw_msg.vid);
+	pr_debug("IC PID:%s", update_msg.ic_fw_msg.pid);
+	pr_debug("IC VID:%04x", update_msg.ic_fw_msg.vid);
 
 	/* First two conditions */
 	if (!memcmp(fw_head->hw_info, update_msg.ic_fw_msg.hw_info,
 			sizeof(update_msg.ic_fw_msg.hw_info))) {
-		GTP_DEBUG("Get the same hardware info.");
+		pr_debug("Get the same hardware info.");
 		if (update_msg.force_update != 0xBE) {
-			GTP_INFO("FW chksum error,need enter update.");
+			pr_info("FW chksum error,need enter update.");
 			return SUCCESS;
 		}
 
 		/* 20130523 start */
 		if (strlen(update_msg.ic_fw_msg.pid) < 3) {
-			GTP_INFO("Illegal IC pid, need enter update");
+			pr_info("Illegal IC pid, need enter update");
 			return SUCCESS;
 		} else {
 			for (i = 0; i < 3; i++) {
 				if ((update_msg.ic_fw_msg.pid[i] < 0x30) ||
 					(update_msg.ic_fw_msg.pid[i] > 0x39)) {
-					GTP_INFO("Illegal IC pid, out of " \
-					"bound, need enter update");
+					pr_info("Illegal IC pid, out of bound, need enter update");
 					return SUCCESS;
 				}
 			}
@@ -534,398 +518,264 @@
 		(!memcmp(update_msg.ic_fw_msg.pid, "91XX", 4)) ||
 		(!memcmp(fw_head->pid, "91XX", 4))) {
 			if (!memcmp(fw_head->pid, "91XX", 4))
-				GTP_DEBUG("Force none same pid update mode.");
+				pr_debug("Force none same pid update mode.");
 			else
-				GTP_DEBUG("Get the same pid.");
+				pr_debug("Get the same pid.");
 
 			/* The third condition */
 			if (fw_head->vid > update_msg.ic_fw_msg.vid) {
-				GTP_INFO("Need enter update.");
+				pr_info("Need enter update.");
 				return SUCCESS;
 			}
-			GTP_ERROR("Don't meet the third condition.");
-			GTP_ERROR("File VID <= Ic VID, update aborted!");
+			pr_err("Don't meet the third condition.");
+			pr_err("File VID <= Ic VID, update aborted!");
 		} else {
-			GTP_ERROR("File PID != Ic PID, update aborted!");
+			pr_err("File PID != Ic PID, update aborted!");
 		}
 	} else {
-		GTP_ERROR("Different Hardware, update aborted!");
+		pr_err("Different Hardware, update aborted!");
 	}
 
 	return FAIL;
 }
 
-static u8 ascii2hex(u8 a)
+static s8 gup_update_config(struct i2c_client *client,
+					const struct firmware *cfg)
 {
-	s8 value = 0;
-
-	if (a >= '0' && a <= '9')
-		value = a - '0';
-	else if (a >= 'A' && a <= 'F')
-		value = a - 'A' + 0x0A;
-	else if (a >= 'a' && a <= 'f')
-		value = a - 'a' + 0x0A;
-	else
-		value = 0xff;
-
-	return value;
-}
-
-static s8 gup_update_config(struct i2c_client *client)
-{
-	s32 file_len = 0;
 	s32 ret = 0;
 	s32 i = 0;
 	s32 file_cfg_len = 0;
-	s32 chip_cfg_len = 0;
+	u32 chip_cfg_len = 0;
 	s32 count = 0;
 	u8 *buf;
-	u8 *pre_buf;
 	u8 *file_config;
-	/* u8 checksum = 0; */
 	u8 pid[8];
+	u8 high, low;
 
-	if (update_msg.cfg_file == NULL) {
-		GTP_ERROR("[update_cfg]No need to upgrade config!");
+	if (!cfg || !cfg->data) {
+		pr_err("No need to upgrade config!");
 		return FAIL;
 	}
-	file_len = update_msg.cfg_file->f_op->llseek(update_msg.cfg_file,
-							0, SEEK_END);
 
 	ret = gup_get_ic_msg(client, GUP_REG_PID_VID, pid, 6);
 	if (ret == FAIL) {
-		GTP_ERROR("[update_cfg]Read product id & version id fail.");
+		pr_err("Read product id & version id fail.");
 		return FAIL;
 	}
 	pid[5] = '\0';
-	GTP_DEBUG("update cfg get pid:%s", &pid[GTP_ADDR_LENGTH]);
+	pr_debug("update cfg get pid:%s", &pid[GTP_ADDR_LENGTH]);
 
 	chip_cfg_len = 186;
 	if (!memcmp(&pid[GTP_ADDR_LENGTH], "968", 3) ||
-	!memcmp(&pid[GTP_ADDR_LENGTH], "910", 3) ||
-	!memcmp(&pid[GTP_ADDR_LENGTH], "960", 3)) {
+		!memcmp(&pid[GTP_ADDR_LENGTH], "910", 3) ||
+		!memcmp(&pid[GTP_ADDR_LENGTH], "960", 3)) {
 		chip_cfg_len = 228;
 	}
-	GTP_DEBUG("[update_cfg]config file len:%d", file_len);
-	GTP_DEBUG("[update_cfg]need config len:%d", chip_cfg_len);
-	if ((file_len+5) < chip_cfg_len*5) {
-		GTP_ERROR("Config length error");
+	pr_debug("config file ASCII len:%d", cfg->size);
+	pr_debug("need config binary len:%d", chip_cfg_len);
+	if ((cfg->size + 5) < chip_cfg_len * 5) {
+		pr_err("Config length error");
 		return -EINVAL;
 	}
 
-	buf = kzalloc(file_len, GFP_KERNEL);
-	pre_buf = kzalloc(file_len, GFP_KERNEL);
-	file_config = kzalloc(chip_cfg_len + GTP_ADDR_LENGTH, GFP_KERNEL);
-	update_msg.cfg_file->f_op->llseek(update_msg.cfg_file, 0, SEEK_SET);
-
-	GTP_DEBUG("[update_cfg]Read config from file.");
-	ret = update_msg.cfg_file->f_op->read(update_msg.cfg_file,
-			(char *)pre_buf, file_len, &update_msg.cfg_file->f_pos);
-	if (ret < 0) {
-		GTP_ERROR("[update_cfg]Read config file failed.");
-		goto update_cfg_file_failed;
+	buf = devm_kzalloc(&client->dev, cfg->size, GFP_KERNEL);
+	if (!buf) {
+		dev_err(&client->dev, "Memory allocation failed for buf.");
+		return -ENOMEM;
 	}
 
-	GTP_DEBUG("[update_cfg]Delete illgal charactor.");
-	for (i = 0, count = 0; i < file_len; i++) {
-		if (pre_buf[i] == ' ' || pre_buf[i] == '\r'
-					|| pre_buf[i] == '\n')
+	file_config = devm_kzalloc(&client->dev, chip_cfg_len + GTP_ADDR_LENGTH,
+								GFP_KERNEL);
+	if (!file_config) {
+		dev_err(&client->dev, "Memory allocation failed.");
+		return -ENOMEM;
+	}
+
+	pr_debug("Delete illgal charactor.");
+	for (i = 0, count = 0; i < cfg->size; i++) {
+		if (cfg->data[i] == ' ' || cfg->data[i] == '\r'
+					|| cfg->data[i] == '\n')
 			continue;
-		buf[count++] = pre_buf[i];
+		buf[count++] = cfg->data[i];
 	}
 
-	GTP_DEBUG("[update_cfg]Ascii to hex.");
+	pr_debug("Ascii to hex.");
 	file_config[0] = GTP_REG_CONFIG_DATA >> 8;
 	file_config[1] = GTP_REG_CONFIG_DATA & 0xff;
-	for (i = 0, file_cfg_len = GTP_ADDR_LENGTH; i < count; i + = 5) {
-		if ((buf[i] == '0') && ((buf[i+1] == 'x') ||
-						(buf[i+1] == 'X'))) {
-			u8 high, low;
-			high = ascii2hex(buf[i+2]);
-			low = ascii2hex(buf[i+3]);
+	for (i = 0, file_cfg_len = GTP_ADDR_LENGTH; i < count; i = i + 5) {
+		if ((buf[i] == '0') && ((buf[i + 1] == 'x') ||
+						(buf[i + 1] == 'X'))) {
+			ret = hex2bin(&high, &buf[i + 2], 1);
+			if (ret) {
+				pr_err("Failed to convert high address from hex2bin");
+				return ret;
+			}
+			ret = hex2bin(&low, &buf[i + 3], 1);
+			if (ret) {
+				pr_err("Failed to convert low address from hex2bin");
+				return ret;
+			}
 
 			if ((high == 0xFF) || (low == 0xFF)) {
 				ret = 0;
-				GTP_ERROR("[update_cfg]Illegal config file.");
-				goto update_cfg_file_failed;
+				pr_err("Illegal config file.");
+				return ret;
 			}
 			file_config[file_cfg_len++] = (high<<4) + low;
 		} else {
 			ret = 0;
-			GTP_ERROR("[update_cfg]Illegal config file.");
-			goto update_cfg_file_failed;
+			pr_err("Illegal config file.");
+			return ret;
 		}
 	}
 
-	/* cal checksum */
-	/* for(i=GTP_ADDR_LENGTH; i<chip_cfg_len; i++)
-		checksum += file_config[i];
-	file_config[chip_cfg_len] = (~checksum) + 1;
-	file_config[chip_cfg_len+1] = 0x01; */
-
-	GTP_DEBUG("config:");
-	GTP_DEBUG_ARRAY(file_config+2, file_cfg_len);
-
 	i = 0;
 	while (i++ < 5) {
 		ret = gup_i2c_write(client, file_config, file_cfg_len);
 		if (ret > 0) {
-			GTP_INFO("[update_cfg]Send config SUCCESS.");
+			pr_info("Send config SUCCESS.");
 			break;
 		}
-		GTP_ERROR("[update_cfg]Send config i2c error.");
+		pr_err("Send config i2c error.");
 	}
 
-update_cfg_file_failed:
-	kfree(pre_buf);
-	kfree(buf);
-	kfree(file_config);
 	return ret;
 }
 
 #if GTP_HEADER_FW_UPDATE
-static u8 gup_check_fs_mounted(char *path_name)
+static u32 gup_get firmware_file(struct i2c_client,
+		struct st_update_msg *msg, u8 *path)
 {
-	struct path root_path;
-	struct path path;
-	int err;
-	err = kern_path("/", LOOKUP_FOLLOW, &root_path);
-
-	if (err) {
-		GTP_DEBUG("\"/\" NOT Mounted: %d", err);
-		return FAIL;
+	if (sizeiof(header_fw_array) < (FW_HEAD_LENGTH +
+				FW_SECTION_LENGTH * 4 +
+				FW_DSP_ISP_LENGTH +
+				FW_DSP_LENGTH +
+				FW_BOOT_LENGTH)) {
+		dev_err(&client->dev,
+			"INVALID header_fw_array!");
+		return -EINVAL;
 	}
-	err = kern_path(path_name, LOOKUP_FOLLOW, &path);
+	msg->fw_data = (u8 *)header_fw_array;
+	msg->fw_len = sizeof(header_fw_array);
+	dev_dbg(&client->dev, "Found firmware from header file, len=%d",
+		msg->fw_len);
+	return 0;
+}
+#else
+static s32 gup_get_firmware_file(struct i2c_client *client,
+		struct st_update_msg *msg, u8 *path)
+{
+	s32 ret;
+	const struct firmware *fw = NULL;
 
-	if (err) {
-		GTP_DEBUG("/data/ NOT Mounted: %d", err);
-		return FAIL;
+	ret = request_firmware(&fw, path, &client->dev);
+	if (ret < 0) {
+		dev_info(&client->dev, "Cannot get firmware - %s (%d)\n",
+					path, ret);
+		return -EEXIST;
 	}
 
-	return SUCCESS;
+	dev_dbg(&client->dev, "Config File: %s size=%d", path, fw->size);
+	msg->fw_data =
+		devm_kzalloc(&client->dev, fw->size, GFP_KERNEL);
+	if (!msg->fw_data) {
+		dev_err(&client->dev,
+			"Not enough memory for firmware data.");
+		release_firmware(fw);
+		return -ENOMEM;
+	}
 
-	/* if (path.mnt->mnt_sb == root_path.mnt->mnt_sb)
-		return FAIL;
-	else
-		return SUCCESS; */
+	memcpy(msg->fw_data, fw->data, fw->size);
+	msg->fw_len = fw->size;
+	msg->need_free = true;
+	release_firmware(fw);
+	return 0;
 }
 #endif
 
-static u8 gup_check_update_file(struct i2c_client *client, st_fw_head *fw_head,
-								u8 *path)
+static u8 gup_check_firmware_name(struct i2c_client *client,
+					u8 **path_p)
+{
+	u8 len;
+	u8 *fname;
+
+	if (!(*path_p)) {
+		*path_p = GOODIX_FIRMWARE_FILE_NAME;
+		return 0;
+	}
+
+	len = strnlen(*path_p, FIRMWARE_NAME_LEN_MAX);
+	if (len >= FIRMWARE_NAME_LEN_MAX) {
+		dev_err(&client->dev, "firmware name too long!");
+		return -EINVAL;
+	}
+
+	fname = strrchr(*path_p, '/');
+	if (fname) {
+		fname = fname + 1;
+		*path_p = fname;
+	}
+	return 0;
+}
+
+static u8 gup_check_update_file(struct i2c_client *client,
+			struct st_fw_head *fw_head, u8 *path)
 {
 	s32 ret = 0;
 	s32 i = 0;
 	s32 fw_checksum = 0;
-	u8 buf[FW_HEAD_LENGTH];
+	u16 temp;
+	const struct firmware *fw = NULL;
 
-	if (path) {
-		GTP_DEBUG("Update File path:%s, %d", path, strlen(path));
-		update_msg.file = file_open(path, O_RDONLY, 0);
-
-		if (IS_ERR(update_msg.file)) {
-			GTP_ERROR("Open update file(%s) error!", path);
-			return FAIL;
-		}
-	} else {
-#if GTP_HEADER_FW_UPDATE
-		for (i = 0; i < (GUP_SEARCH_FILE_TIMES); i++) {
-			GTP_DEBUG("Waiting for /data mounted [%d]", i);
-
-			if (gup_check_fs_mounted("/data") == SUCCESS) {
-				GTP_DEBUG("/data Mounted!");
-				break;
-			}
-			msleep(3000);
-		}
-		if (i >= (GUP_SEARCH_FILE_TIMES)) {
-			GTP_ERROR("Wait for /data mounted timeout!");
-			return FAIL;
-		}
-
-		/* update config */
-		update_msg.cfg_file = file_open(CONFIG_FILE_PATH_1,
-							O_RDONLY, 0);
-
-		if (IS_ERR(update_msg.cfg_file)) {
-			GTP_DEBUG("%s is unavailable", CONFIG_FILE_PATH_1);
-		} else {
-			GTP_INFO("Update Config File: %s", CONFIG_FILE_PATH_1);
-			ret = gup_update_config(client);
-			if (ret <= 0)
-				GTP_ERROR("Update config failed.");
-			filp_close(update_msg.cfg_file, NULL);
-		}
-
-		if (sizeof(header_fw_array) < (FW_HEAD_LENGTH+FW_SECTION_LENGTH
-		*4 + FW_DSP_ISP_LENGTH+FW_DSP_LENGTH + FW_BOOT_LENGTH)) {
-			GTP_ERROR("INVALID header_fw_array, check your " \
-				"gt9xx_firmware.h file!");
-			return FAIL;
-		}
-		update_msg.file = file_open(UPDATE_FILE_PATH_2, O_CREAT |
-								O_RDWR, 0666);
-		if ((IS_ERR(update_msg.file))) {
-			GTP_ERROR("Failed to Create file: %s for fw_header!",
-							UPDATE_FILE_PATH_2);
-			return FAIL;
-		}
-		update_msg.file->f_op->llseek(update_msg.file, 0, SEEK_SET);
-		update_msg.file->f_op->write(update_msg.file,
-			(char *)header_fw_array, sizeof(header_fw_array),
-			&update_msg.file->f_pos);
-		file_close(update_msg.file, NULL);
-		update_msg.file = file_open(UPDATE_FILE_PATH_2, O_RDONLY, 0);
-#else
-		u8 fp_len = max(sizeof(UPDATE_FILE_PATH_1),
-						sizeof(UPDATE_FILE_PATH_2));
-		u8 cfp_len = max(sizeof(CONFIG_FILE_PATH_1),
-						sizeof(CONFIG_FILE_PATH_2));
-		u8 *search_update_path = kzalloc(fp_len, GFP_KERNEL);
-		u8 *search_cfg_path = kzalloc(cfp_len, GFP_KERNEL);
-		/* Begin to search update file,the config file & firmware
-			file must be in the same path,single or double. */
-		searching_file = 1;
-		for (i = 0; i < GUP_SEARCH_FILE_TIMES; i++) {
-			if (searching_file == 0) {
-				kfree(search_update_path);
-				kfree(search_cfg_path);
-				GTP_INFO(".bin/.cfg update file search " \
-						"forcely terminated!");
-				return FAIL;
-			}
-			if (i % 2) {
-				memcpy(search_update_path, UPDATE_FILE_PATH_1,
-						sizeof(UPDATE_FILE_PATH_1));
-				memcpy(search_cfg_path, CONFIG_FILE_PATH_1,
-						sizeof(CONFIG_FILE_PATH_1));
-			} else {
-				memcpy(search_update_path, UPDATE_FILE_PATH_2,
-						sizeof(UPDATE_FILE_PATH_2));
-				memcpy(search_cfg_path, CONFIG_FILE_PATH_2,
-						sizeof(CONFIG_FILE_PATH_2));
-			}
-
-			if (!(got_file_flag&0x0F)) {
-				update_msg.file = file_open(search_update_path,
-						O_RDONLY, 0);
-				if (!IS_ERR(update_msg.file)) {
-					GTP_DEBUG("Find the bin file");
-					got_file_flag |= 0x0F;
-				}
-			}
-			if (!(got_file_flag & 0xF0)) {
-				update_msg.cfg_file = file_open(search_cfg_path,
-						O_RDONLY, 0);
-				if (!IS_ERR(update_msg.cfg_file)) {
-					GTP_DEBUG("Find the cfg file");
-					got_file_flag |= 0xF0;
-				}
-			}
-
-			if (got_file_flag) {
-				if (got_file_flag == 0xFF)
-					break;
-				else
-					i += 4;
-			}
-			GTP_DEBUG("%3d:Searching %s %s file...", i,
-			(got_file_flag & 0x0F) ? "" : "bin",
-			(got_file_flag & 0xF0) ? "" : "cfg");
-
-			msleep(3000);
-		}
-
-		searching_file = 0;
-		kfree(search_update_path);
-		kfree(search_cfg_path);
-
-		if (!got_file_flag) {
-			GTP_ERROR("Can't find update file.");
-			goto load_failed;
-		}
-
-		if (got_file_flag & 0xF0) {
-			GTP_DEBUG("Got the update config file.");
-			ret = gup_update_config(client);
-			if (ret <= 0)
-				GTP_ERROR("Update config failed.");
-			filp_close(update_msg.cfg_file, NULL);
-			msleep(500); /* waiting config to be stored in FLASH. */
-		}
-		if (got_file_flag & 0x0F) {
-			GTP_DEBUG("Got the update firmware file.");
-		} else {
-			GTP_ERROR("No need to upgrade firmware.");
-			goto load_failed;
-		}
-#endif
-	}
-
-	update_msg.old_fs = get_fs();
-	set_fs(KERNEL_DS);
-
-	update_msg.file->f_op->llseek(update_msg.file, 0, SEEK_SET);
-	/* update_msg.file->f_pos = 0; */
-
-	ret = update_msg.file->f_op->read(update_msg.file, (char *)buf,
-				FW_HEAD_LENGTH, &update_msg.file->f_pos);
+	ret = request_firmware(&fw, GOODIX_CONFIG_FILE_NAME, &client->dev);
 	if (ret < 0) {
-		GTP_ERROR("Read firmware head in update file error.");
-		goto load_failed;
+		dev_info(&client->dev, "Cannot get config file - %s (%d)\n",
+						GOODIX_CONFIG_FILE_NAME, ret);
+	} else {
+		dev_dbg(&client->dev,
+			"Update config File: %s", GOODIX_CONFIG_FILE_NAME);
+		ret = gup_update_config(client, fw);
+		if (ret <= 0)
+			dev_err(&client->dev, "Update config failed.");
+		release_firmware(fw);
 	}
-	memcpy(fw_head, buf, FW_HEAD_LENGTH);
+
+	update_msg.need_free = false;
+	update_msg.fw_len = 0;
+
+	if (gup_check_firmware_name(client, &path))
+		goto load_failed;
+
+	if (gup_get_firmware_file(client, &update_msg, path))
+		goto load_failed;
+
+	memcpy(fw_head, update_msg.fw_data, FW_HEAD_LENGTH);
 
 	/* check firmware legality */
 	fw_checksum = 0;
 	for (i = 0; i < FW_SECTION_LENGTH * 4 + FW_DSP_ISP_LENGTH +
-			FW_DSP_LENGTH + FW_BOOT_LENGTH; i + = 2) {
-		u16 temp;
-		ret = update_msg.file->f_op->read(update_msg.file, (char *)buf,
-						2, &update_msg.file->f_pos);
-		if (ret < 0) {
-			GTP_ERROR("Read firmware file error.");
-			goto load_failed;
-		}
-		/* GTP_DEBUG("BUF[0]:%x", buf[0]); */
-		temp = (buf[0]<<8) + buf[1];
+			FW_DSP_LENGTH + FW_BOOT_LENGTH; i += 2) {
+		temp = (update_msg.fw_data[FW_HEAD_LENGTH + i] << 8) +
+			update_msg.fw_data[FW_HEAD_LENGTH + i + 1];
 		fw_checksum += temp;
 	}
 
-	GTP_DEBUG("firmware checksum:%x", fw_checksum&0xFFFF);
+	pr_debug("firmware checksum:%x", fw_checksum & 0xFFFF);
 	if (fw_checksum & 0xFFFF) {
-		GTP_ERROR("Illegal firmware file.");
+		dev_err(&client->dev, "Illegal firmware file.");
 		goto load_failed;
 	}
 
 	return SUCCESS;
 
 load_failed:
-	set_fs(update_msg.old_fs);
+	if (update_msg.need_free) {
+		devm_kfree(&client->dev, update_msg.fw_data);
+		update_msg.need_free = false;
+	}
 	return FAIL;
 }
 
-#if 0
-static u8 gup_check_update_header(struct i2c_client *client,
-			st_fw_head *fw_head)
-{
-	const u8 *pos;
-	int i = 0;
-	u8 mask_num = 0;
-	s32 ret = 0;
-
-	pos = HEADER_UPDATE_DATA;
-
-	memcpy(fw_head, pos, FW_HEAD_LENGTH);
-	pos += FW_HEAD_LENGTH;
-
-	ret = gup_enter_update_judge(fw_head);
-	if (SUCCESS == ret)
-		return SUCCESS;
-	return FAIL;
-}
-#endif
-
 static u8 gup_burn_proc(struct i2c_client *client, u8 *burn_buf, u16 start_addr,
 							u16 total_length)
 {
@@ -937,10 +787,10 @@
 	u8  rd_buf[PACK_SIZE + GTP_ADDR_LENGTH];
 	u8  retry = 0;
 
-	GTP_DEBUG("Begin burn %dk data to addr 0x%x", (total_length/1024),
+	pr_debug("Begin burn %dk data to addr 0x%x", (total_length / 1024),
 								start_addr);
 	while (burn_length < total_length) {
-		GTP_DEBUG("B/T:%04d/%04d", burn_length, total_length);
+		pr_debug("B/T:%04d/%04d", burn_length, total_length);
 		frame_length = ((total_length - burn_length) > PACK_SIZE)
 				? PACK_SIZE : (total_length - burn_length);
 		wr_buf[0] = (u8)(burn_addr>>8);
@@ -954,33 +804,26 @@
 			ret = gup_i2c_write(client, wr_buf,
 					GTP_ADDR_LENGTH + frame_length);
 			if (ret <= 0) {
-				GTP_ERROR("Write frame data i2c error.");
+				pr_err("Write frame data i2c error.");
 				continue;
 			}
 			ret = gup_i2c_read(client, rd_buf, GTP_ADDR_LENGTH +
 							frame_length);
 			if (ret <= 0) {
-				GTP_ERROR("Read back frame data i2c error.");
+				pr_err("Read back frame data i2c error.");
 				continue;
 			}
 
 			if (memcmp(&wr_buf[GTP_ADDR_LENGTH],
 				&rd_buf[GTP_ADDR_LENGTH], frame_length)) {
-				GTP_ERROR("Check frame data fail,not equal.");
-				GTP_DEBUG("write array:");
-				GTP_DEBUG_ARRAY(&wr_buf[GTP_ADDR_LENGTH],
-								frame_length);
-				GTP_DEBUG("read array:");
-				GTP_DEBUG_ARRAY(&rd_buf[GTP_ADDR_LENGTH],
-								frame_length);
+				pr_err("Check frame data fail,not equal.");
 				continue;
 			} else {
-				/* GTP_DEBUG("Check frame data success."); */
 				break;
 			}
 		}
 		if (retry >= MAX_FRAME_CHECK_TIME) {
-			GTP_ERROR("Burn frame data time out,exit.");
+			pr_err("Burn frame data time out,exit.");
 			return FAIL;
 		}
 		burn_length += frame_length;
@@ -991,20 +834,15 @@
 
 static u8 gup_load_section_file(u8 *buf, u16 offset, u16 length)
 {
-	s32 ret = 0;
-
-	if (update_msg.file == NULL) {
-		GTP_ERROR("cannot find update file,load section file fail.");
+	if (!update_msg.fw_data ||
+		update_msg.fw_len < FW_HEAD_LENGTH + offset + length) {
+		pr_err(
+			"<<-GTP->> cannot load section data. fw_len=%d read end=%d\n",
+			update_msg.fw_len ,
+			FW_HEAD_LENGTH + offset + length);
 		return FAIL;
 	}
-	update_msg.file->f_pos = FW_HEAD_LENGTH + offset;
-
-	ret = update_msg.file->f_op->read(update_msg.file, (char *)buf, length,
-						&update_msg.file->f_pos);
-	if (ret < 0) {
-		GTP_ERROR("Read update file fail.");
-		return FAIL;
-	}
+	memcpy(buf, &update_msg.fw_data[FW_HEAD_LENGTH + offset], length);
 
 	return SUCCESS;
 }
@@ -1023,30 +861,26 @@
 				? PACK_SIZE : (chk_length - recall_length);
 		ret = gup_get_ic_msg(client, recall_addr, rd_buf, frame_length);
 		if (ret <= 0) {
-			GTP_ERROR("recall i2c error,exit");
+			pr_err("recall i2c error,exit");
 			return FAIL;
 		}
 
 		if (memcmp(&rd_buf[GTP_ADDR_LENGTH], &chk_src[recall_length],
 			frame_length)) {
-			GTP_ERROR("Recall frame data fail,not equal.");
-			GTP_DEBUG("chk_src array:");
-			GTP_DEBUG_ARRAY(&chk_src[recall_length], frame_length);
-			GTP_DEBUG("recall array:");
-			GTP_DEBUG_ARRAY(&rd_buf[GTP_ADDR_LENGTH], frame_length);
+			pr_err("Recall frame data fail,not equal.");
 			return FAIL;
 		}
 
 		recall_length += frame_length;
 		recall_addr += frame_length;
 	}
-	GTP_DEBUG("Recall check %dk firmware success.", (chk_length/1024));
+	pr_debug("Recall check %dk firmware success.", (chk_length/1024));
 
 	return SUCCESS;
 }
 
 static u8 gup_burn_fw_section(struct i2c_client *client, u8 *fw_section,
-					u16 start_addr, u8 bank_cmdi)
+					u16 start_addr, u8 bank_cmd)
 {
 	s32 ret = 0;
 	u8  rd_buf[5];
@@ -1054,14 +888,14 @@
 	/* step1:hold ss51 & dsp */
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_section]hold ss51 & dsp fail.");
+		pr_err("hold ss51 & dsp fail.");
 		return FAIL;
 	}
 
 	 /* step2:set scramble */
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_section]set scramble fail.");
+		pr_err("set scramble fail.");
 		return FAIL;
 	}
 
@@ -1069,7 +903,7 @@
 	ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK,
 						(bank_cmd >> 4)&0x0F);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_section]select bank %d fail.",
+		pr_err("select bank %d fail.",
 					(bank_cmd >> 4)&0x0F);
 		return FAIL;
 	}
@@ -1077,21 +911,21 @@
 	/* step4:enable accessing code */
 	ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x01);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_section]enable accessing code fail.");
+		pr_err("enable accessing code fail.");
 		return FAIL;
 	}
 
 	/* step5:burn 8k fw section */
 	ret = gup_burn_proc(client, fw_section, start_addr, FW_SECTION_LENGTH);
 	if (ret == FAIL)  {
-		GTP_ERROR("[burn_fw_section]burn fw_section fail.");
+		pr_err("burn fw_section fail.");
 		return FAIL;
 	}
 
 	/* step6:hold ss51 & release dsp */
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_section]hold ss51 & release dsp fail.");
+		pr_err("hold ss51 & release dsp fail.");
 		return FAIL;
 	}
 	/* must delay */
@@ -1100,26 +934,24 @@
 	/* step7:send burn cmd to move data to flash from sram */
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, bank_cmd&0x0f);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_section]send burn cmd fail.");
+		pr_err("send burn cmd fail.");
 		return FAIL;
 	}
-	GTP_DEBUG("[burn_fw_section]Wait for the burn is complete......");
+	pr_debug("Wait for the burn is complete.");
 	do {
 		ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1);
 		if (ret <= 0) {
-			GTP_ERROR("[burn_fw_section]Get burn state fail");
+			pr_err("Get burn state fail");
 			return FAIL;
 		}
 		msleep(20);
-		/* GTP_DEBUG("[burn_fw_section]Get burn state:%d.",
-						rd_buf[GTP_ADDR_LENGTH]); */
 	} while (rd_buf[GTP_ADDR_LENGTH]);
 
 	/* step8:select bank */
 	ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK,
 							(bank_cmd >> 4)&0x0F);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_section]select bank %d fail.",
+		pr_err("select bank %d fail.",
 							(bank_cmd >> 4)&0x0F);
 		return FAIL;
 	}
@@ -1127,7 +959,7 @@
 	/* step9:enable accessing code */
 	ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x01);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_section]enable accessing code fail.");
+		pr_err("enable accessing code fail.");
 		return FAIL;
 	}
 
@@ -1135,14 +967,14 @@
 	ret = gup_recall_check(client, fw_section, start_addr,
 							FW_SECTION_LENGTH);
 	if (ret == FAIL) {
-		GTP_ERROR("[burn_fw_section]recall check 8k firmware fail.");
+		pr_err("recall check 8k firmware fail.");
 		return FAIL;
 	}
 
 	/* step11:disable accessing code */
 	ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x00);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_section]disable accessing code fail.");
+		pr_err("disable accessing code fail.");
 		return FAIL;
 	}
 
@@ -1155,115 +987,105 @@
 	u8 *fw_dsp_isp = NULL;
 	u8  retry = 0;
 
-	GTP_DEBUG("[burn_dsp_isp]Begin burn dsp isp---->>");
+	pr_debug("Begin burn dsp isp.");
 
 	/* step1:alloc memory */
-	GTP_DEBUG("[burn_dsp_isp]step1:alloc memory");
+	pr_debug("step1:alloc memory");
 	while (retry++ < 5) {
-		fw_dsp_isp = kzalloc(FW_DSP_ISP_LENGTH, GFP_KERNEL);
+		fw_dsp_isp = devm_kzalloc(&client->dev, FW_DSP_ISP_LENGTH,
+								GFP_KERNEL);
 		if (fw_dsp_isp == NULL) {
 			continue;
 		} else {
-			GTP_INFO("[burn_dsp_isp]Alloc %dk byte memory success.",
+			pr_info("Alloc %dk byte memory success.",
 					(FW_DSP_ISP_LENGTH/1024));
 			break;
 		}
 	}
-	if (retry >= 5) {
-		GTP_ERROR("[burn_dsp_isp]Alloc memory fail,exit.");
+	if (retry == 5) {
+		pr_err("Alloc memory fail,exit.");
 		return FAIL;
 	}
 
 	/* step2:load dsp isp file data */
-	GTP_DEBUG("[burn_dsp_isp]step2:load dsp isp file data");
+	pr_debug("step2:load dsp isp file data");
 	ret = gup_load_section_file(fw_dsp_isp, (4 * FW_SECTION_LENGTH +
 		FW_DSP_LENGTH + FW_BOOT_LENGTH), FW_DSP_ISP_LENGTH);
 	if (ret == FAIL) {
-		GTP_ERROR("[burn_dsp_isp]load firmware dsp_isp fail.");
-		goto exit_burn_dsp_isp;
+		pr_err("load firmware dsp_isp fail.");
+		return FAIL;
 	}
 
 	/* step3:disable wdt,clear cache enable */
-	GTP_DEBUG("[burn_dsp_isp]step3:disable wdt,clear cache enable");
+	pr_debug("step3:disable wdt,clear cache enable");
 	ret = gup_set_ic_msg(client, _bRW_MISCTL__TMR0_EN, 0x00);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_dsp_isp]disable wdt fail.");
-		ret = FAIL;
-		goto exit_burn_dsp_isp;
+		pr_err("disable wdt fail.");
+		return FAIL;
 	}
 	ret = gup_set_ic_msg(client, _bRW_MISCTL__CACHE_EN, 0x00);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_dsp_isp]clear cache enable fail.");
-		ret = FAIL;
-		goto exit_burn_dsp_isp;
+		pr_err("clear cache enable fail.");
+		return FAIL;
 	}
 
 	/* step4:hold ss51 & dsp */
-	GTP_DEBUG("[burn_dsp_isp]step4:hold ss51 & dsp");
+	pr_debug("step4:hold ss51 & dsp");
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_dsp_isp]hold ss51 & dsp fail.");
-		ret = FAIL;
-		goto exit_burn_dsp_isp;
+		pr_err("hold ss51 & dsp fail.");
+		return FAIL;
 	}
 
 	/* step5:set boot from sram */
-	GTP_DEBUG("[burn_dsp_isp]step5:set boot from sram");
+	pr_debug("step5:set boot from sram");
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOTCTL_B0_, 0x02);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_dsp_isp]set boot from sram fail.");
-		ret = FAIL;
-		goto exit_burn_dsp_isp;
+		pr_err("set boot from sram fail.");
+		return FAIL;
 	}
 
 	/* step6:software reboot */
-	GTP_DEBUG("[burn_dsp_isp]step6:software reboot");
+	pr_debug("step6:software reboot");
 	ret = gup_set_ic_msg(client, _bWO_MISCTL__CPU_SWRST_PULSE, 0x01);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_dsp_isp]software reboot fail.");
-		ret = FAIL;
-		goto exit_burn_dsp_isp;
+		pr_err("software reboot fail.");
+		return FAIL;
 	}
 
 	/* step7:select bank2 */
-	GTP_DEBUG("[burn_dsp_isp]step7:select bank2");
+	pr_debug("step7:select bank2");
 	ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x02);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_dsp_isp]select bank2 fail.");
-		ret = FAIL;
-		goto exit_burn_dsp_isp;
+		pr_err("select bank2 fail.");
+		return FAIL;
 	}
 
 	/* step8:enable accessing code */
-	GTP_DEBUG("[burn_dsp_isp]step8:enable accessing code");
+	pr_debug("step8:enable accessing code");
 	ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x01);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_dsp_isp]enable accessing code fail.");
-		ret = FAIL;
-		goto exit_burn_dsp_isp;
+		pr_err("enable accessing code fail.");
+		return FAIL;
 	}
 
 	/* step9:burn 4k dsp_isp */
-	GTP_DEBUG("[burn_dsp_isp]step9:burn 4k dsp_isp");
+	pr_debug("step9:burn 4k dsp_isp");
 	ret = gup_burn_proc(client, fw_dsp_isp, 0xC000, FW_DSP_ISP_LENGTH);
 	if (ret == FAIL) {
-		GTP_ERROR("[burn_dsp_isp]burn dsp_isp fail.");
-		goto exit_burn_dsp_isp;
+		pr_err("burn dsp_isp fail.");
+		return FAIL;
 	}
 
 	/* step10:set scramble */
-	GTP_DEBUG("[burn_dsp_isp]step10:set scramble");
+	pr_debug("step10:set scramble");
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_dsp_isp]set scramble fail.");
-		ret = FAIL;
-		goto exit_burn_dsp_isp;
+		pr_err("set scramble fail.");
+		return FAIL;
 	}
-	ret = SUCCESS;
 
-exit_burn_dsp_isp:
-	kfree(fw_dsp_isp);
-	return ret;
+	return SUCCESS;
 }
 
 static u8 gup_burn_fw_ss51(struct i2c_client *client)
@@ -1272,106 +1094,102 @@
 	u8  retry = 0;
 	s32 ret = 0;
 
-	GTP_DEBUG("[burn_fw_ss51]Begin burn ss51 firmware---->>");
+	pr_debug("Begin burn ss51 firmware.");
 
 	/* step1:alloc memory */
-	GTP_DEBUG("[burn_fw_ss51]step1:alloc memory");
+	pr_debug("step1:alloc memory");
 	while (retry++ < 5) {
-		fw_ss51 = kzalloc(FW_SECTION_LENGTH, GFP_KERNEL);
+		fw_ss51 = devm_kzalloc(&client->dev, FW_SECTION_LENGTH,
+							GFP_KERNEL);
 		if (fw_ss51 == NULL) {
 			continue;
 		} else {
-			GTP_INFO("[burn_fw_ss51]Alloc %dk byte memory success.",
+			pr_info("Alloc %dk byte memory success.",
 						(FW_SECTION_LENGTH/1024));
 			break;
 		}
 	}
-	if (retry >= 5) {
-		GTP_ERROR("[burn_fw_ss51]Alloc memory fail,exit.");
+	if (retry == 5) {
+		pr_err("Alloc memory fail,exit.");
 		return FAIL;
 	}
 
 	/* step2:load ss51 firmware section 1 file data */
-	GTP_DEBUG("[burn_fw_ss51]step2:load ss51 firmware section 1 file data");
+	pr_debug("step2:load ss51 firmware section 1 file data");
 	ret = gup_load_section_file(fw_ss51, 0, FW_SECTION_LENGTH);
 	if (ret == FAIL) {
-		GTP_ERROR("[burn_fw_ss51]load ss51 firmware section 1 fail.");
-		goto exit_burn_fw_ss51;
+		pr_err("load ss51 firmware section 1 fail.");
+		return FAIL;
 	}
 
 	/* step3:clear control flag */
-	GTP_DEBUG("[burn_fw_ss51]step3:clear control flag");
+	pr_debug("step3:clear control flag");
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x00);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_ss51]clear control flag fail.");
-		ret = FAIL;
-		goto exit_burn_fw_ss51;
+		pr_err("clear control flag fail.");
+		return FAIL;
 	}
 
 	/* step4:burn ss51 firmware section 1 */
-	GTP_DEBUG("[burn_fw_ss51]step4:burn ss51 firmware section 1");
+	pr_debug("step4:burn ss51 firmware section 1");
 	ret = gup_burn_fw_section(client, fw_ss51, 0xC000, 0x01);
 	if (ret == FAIL) {
-		GTP_ERROR("[burn_fw_ss51]burn ss51 firmware section 1 fail.");
-		goto exit_burn_fw_ss51;
+		pr_err("burn ss51 firmware section 1 fail.");
+		return FAIL;
 	}
 
 	/* step5:load ss51 firmware section 2 file data */
-	GTP_DEBUG("[burn_fw_ss51]step5:load ss51 firmware section 2 file data");
+	pr_debug("step5:load ss51 firmware section 2 file data");
 	ret = gup_load_section_file(fw_ss51, FW_SECTION_LENGTH,
 							FW_SECTION_LENGTH);
 	if (ret == FAIL) {
-		GTP_ERROR("[burn_fw_ss51]load ss51 firmware section 2 fail.");
-		goto exit_burn_fw_ss51;
+		pr_err("[burn_fw_ss51]load ss51 firmware section 2 fail.");
+		return FAIL;
 	}
 
 	/* step6:burn ss51 firmware section 2 */
-	GTP_DEBUG("[burn_fw_ss51]step6:burn ss51 firmware section 2");
+	pr_debug("step6:burn ss51 firmware section 2");
 	ret = gup_burn_fw_section(client, fw_ss51, 0xE000, 0x02);
 	if (ret == FAIL) {
-		GTP_ERROR("[burn_fw_ss51]burn ss51 firmware section 2 fail.");
-		goto exit_burn_fw_ss51;
+		pr_err("burn ss51 firmware section 2 fail.");
+		return FAIL;
 	}
 
 	/* step7:load ss51 firmware section 3 file data */
-	GTP_DEBUG("[burn_fw_ss51]step7:load ss51 firmware section 3 file data");
+	pr_debug("step7:load ss51 firmware section 3 file data");
 	ret = gup_load_section_file(fw_ss51, 2*FW_SECTION_LENGTH,
 							FW_SECTION_LENGTH);
 	if (ret == FAIL) {
-		GTP_ERROR("[burn_fw_ss51]load ss51 firmware section 3 fail.");
-		goto exit_burn_fw_ss51;
+		pr_err("load ss51 firmware section 3 fail.");
+		return FAIL;
 	}
 
 	/* step8:burn ss51 firmware section 3 */
-	GTP_DEBUG("[burn_fw_ss51]step8:burn ss51 firmware section 3");
+	pr_debug("step8:burn ss51 firmware section 3");
 	ret = gup_burn_fw_section(client, fw_ss51, 0xC000, 0x13);
 	if (ret == FAIL) {
-		GTP_ERROR("[burn_fw_ss51]burn ss51 firmware section 3 fail.");
-		goto exit_burn_fw_ss51;
+		pr_err("burn ss51 firmware section 3 fail.");
+		return FAIL;
 	}
 
 	/* step9:load ss51 firmware section 4 file data */
-	GTP_DEBUG("[burn_fw_ss51]step9:load ss51 firmware section 4 file data");
+	pr_debug("step9:load ss51 firmware section 4 file data");
 	ret = gup_load_section_file(fw_ss51, 3*FW_SECTION_LENGTH,
 							FW_SECTION_LENGTH);
 	if (ret == FAIL) {
-		GTP_ERROR("[burn_fw_ss51]load ss51 firmware section 4 fail.");
-		goto exit_burn_fw_ss51;
+		pr_err("load ss51 firmware section 4 fail.");
+		return FAIL;
 	}
 
 	/* step10:burn ss51 firmware section 4 */
-	GTP_DEBUG("[burn_fw_ss51]step10:burn ss51 firmware section 4");
+	pr_debug("step10:burn ss51 firmware section 4");
 	ret = gup_burn_fw_section(client, fw_ss51, 0xE000, 0x14);
 	if (ret == FAIL) {
-		GTP_ERROR("[burn_fw_ss51]burn ss51 firmware section 4 fail.");
-		goto exit_burn_fw_ss51;
+		pr_err("burn ss51 firmware section 4 fail.");
+		return FAIL;
 	}
 
-	ret = SUCCESS;
-
-exit_burn_fw_ss51:
-	kfree(fw_ss51);
-	return ret;
+	return SUCCESS;
 }
 
 static u8 gup_burn_fw_dsp(struct i2c_client *client)
@@ -1381,111 +1199,101 @@
 	u8  retry = 0;
 	u8  rd_buf[5];
 
-	GTP_DEBUG("[burn_fw_dsp]Begin burn dsp firmware---->>");
+	pr_debug("Begin burn dsp firmware.");
 	/* step1:alloc memory */
-	GTP_DEBUG("[burn_fw_dsp]step1:alloc memory");
+	pr_debug("step1:alloc memory");
 	while (retry++ < 5) {
-		fw_dsp = kzalloc(FW_DSP_LENGTH, GFP_KERNEL);
+		fw_dsp = devm_kzalloc(&client->dev, FW_DSP_LENGTH,
+							GFP_KERNEL);
 		if (fw_dsp == NULL) {
 			continue;
 		} else  {
-			GTP_INFO("[burn_fw_dsp]Alloc %dk byte memory success.",
+			pr_info("Alloc %dk byte memory success.",
 					(FW_SECTION_LENGTH/1024));
 			break;
 		}
 	}
-	if (retry >= 5) {
-		GTP_ERROR("[burn_fw_dsp]Alloc memory fail,exit.");
+	if (retry == 5) {
+		pr_err("Alloc memory fail,exit.");
 		return FAIL;
 	}
 
 	/* step2:load firmware dsp */
-	GTP_DEBUG("[burn_fw_dsp]step2:load firmware dsp");
+	pr_debug("step2:load firmware dsp");
 	ret = gup_load_section_file(fw_dsp, 4*FW_SECTION_LENGTH, FW_DSP_LENGTH);
 	if (ret == FAIL) {
-		GTP_ERROR("[burn_fw_dsp]load firmware dsp fail.");
-		goto exit_burn_fw_dsp;
+		pr_err("load firmware dsp fail.");
+		return ret;
 	}
 
 	/* step3:select bank3 */
-	GTP_DEBUG("[burn_fw_dsp]step3:select bank3");
+	pr_debug("step3:select bank3");
 	ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x03);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_dsp]select bank3 fail.");
-		ret = FAIL;
-		goto exit_burn_fw_dsp;
+		pr_err("select bank3 fail.");
+		return FAIL;
 	}
 
 	/* Step4:hold ss51 & dsp */
-	GTP_DEBUG("[burn_fw_dsp]step4:hold ss51 & dsp");
+	pr_debug("step4:hold ss51 & dsp");
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_dsp]hold ss51 & dsp fail.");
-		ret = FAIL;
-		goto exit_burn_fw_dsp;
+		pr_err("hold ss51 & dsp fail.");
+		return FAIL;
 	}
 
 	/* step5:set scramble */
-	GTP_DEBUG("[burn_fw_dsp]step5:set scramble");
+	pr_debug("step5:set scramble");
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_dsp]set scramble fail.");
-		ret = FAIL;
-		goto exit_burn_fw_dsp;
+		pr_err("set scramble fail.");
+		return FAIL;
 	}
 
 	/* step6:release ss51 & dsp */
-	GTP_DEBUG("[burn_fw_dsp]step6:release ss51 & dsp");
+	pr_debug("step6:release ss51 & dsp");
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_dsp]release ss51 & dsp fail.");
-		ret = FAIL;
-		goto exit_burn_fw_dsp;
+		pr_err("release ss51 & dsp fail.");
+		return FAIL;
 	}
 	/* must delay */
 	msleep(20);
 
 	/* step7:burn 4k dsp firmware */
-	GTP_DEBUG("[burn_fw_dsp]step7:burn 4k dsp firmware");
+	pr_debug("step7:burn 4k dsp firmware");
 	ret = gup_burn_proc(client, fw_dsp, 0x9000, FW_DSP_LENGTH);
-	if (FAIL == ret) {
-		GTP_ERROR("[burn_fw_dsp]burn fw_section fail.");
-		goto exit_burn_fw_dsp;
+	if (ret == FAIL) {
+		pr_err("[burn_fw_dsp]burn fw_section fail.");
+		return ret;
 	}
 
 	/* step8:send burn cmd to move data to flash from sram */
-	GTP_DEBUG("[burn_fw_dsp]step8:send burn cmd to move data to flash" \
-						"from sram");
+	pr_debug("step8:send burn cmd to move data to flash from sram");
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x05);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_dsp]send burn cmd fail.");
-		goto exit_burn_fw_dsp;
+		pr_err("send burn cmd fail.");
+		return ret;
 	}
-	GTP_DEBUG("[burn_fw_dsp]Wait for the burn is complete......");
+	pr_debug("Wait for the burn is complete.");
 	do {
 		ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1);
 		if (ret <= 0) {
-			GTP_ERROR("[burn_fw_dsp]Get burn state fail");
-			goto exit_burn_fw_dsp;
+			pr_err("Get burn state fail");
+			return ret;
 		}
 		msleep(20);
-		/* GTP_DEBUG("[burn_fw_dsp]Get burn state:%d.",
-						rd_buf[GTP_ADDR_LENGTH]); */
 	} while (rd_buf[GTP_ADDR_LENGTH]);
 
 	/* step9:recall check 4k dsp firmware */
-	GTP_DEBUG("[burn_fw_dsp]step9:recall check 4k dsp firmware");
+	pr_debug("step9:recall check 4k dsp firmware");
 	ret = gup_recall_check(client, fw_dsp, 0x9000, FW_DSP_LENGTH);
 	if (ret == FAIL) {
-		GTP_ERROR("[burn_fw_dsp]recall check 4k dsp firmware fail.");
-		goto exit_burn_fw_dsp;
+		pr_err("recall check 4k dsp firmware fail.");
+		return ret;
 	}
 
-	ret = SUCCESS;
-
-exit_burn_fw_dsp:
-	kfree(fw_dsp);
-	return ret;
+	return SUCCESS;
 }
 
 static u8 gup_burn_fw_boot(struct i2c_client *client)
@@ -1495,176 +1303,165 @@
 	u8  retry = 0;
 	u8  rd_buf[5];
 
-	GTP_DEBUG("[burn_fw_boot]Begin burn bootloader firmware---->>");
+	pr_debug("Begin burn bootloader firmware.");
 
 	/* step1:Alloc memory */
-	GTP_DEBUG("[burn_fw_boot]step1:Alloc memory");
+	pr_debug("step1:Alloc memory");
 	while (retry++ < 5) {
-		fw_boot = kzalloc(FW_BOOT_LENGTH, GFP_KERNEL);
+		fw_boot = devm_kzalloc(&client->dev, FW_BOOT_LENGTH,
+							GFP_KERNEL);
 		if (fw_boot == NULL) {
 			continue;
 		} else {
-			GTP_INFO("[burn_fw_boot]Alloc %dk byte memory success.",
+			pr_info("Alloc %dk byte memory success.",
 						(FW_BOOT_LENGTH/1024));
 			break;
 		}
 	}
-	if (retry >= 5) {
-		GTP_ERROR("[burn_fw_boot]Alloc memory fail,exit.");
+	if (retry == 5) {
+		pr_err("Alloc memory fail,exit.");
 		return FAIL;
 	}
 
 	/* step2:load firmware bootloader */
-	GTP_DEBUG("[burn_fw_boot]step2:load firmware bootloader");
+	pr_debug("step2:load firmware bootloader");
 	ret = gup_load_section_file(fw_boot, (4 * FW_SECTION_LENGTH +
 				FW_DSP_LENGTH), FW_BOOT_LENGTH);
 	if (ret == FAIL) {
-		GTP_ERROR("[burn_fw_boot]load firmware dsp fail.");
-		goto exit_burn_fw_boot;
+		pr_err("load firmware dsp fail.");
+		return ret;
 	}
 
 	/* step3:hold ss51 & dsp */
-	GTP_DEBUG("[burn_fw_boot]step3:hold ss51 & dsp");
+	pr_debug("step3:hold ss51 & dsp");
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_boot]hold ss51 & dsp fail.");
-		ret = FAIL;
-		goto exit_burn_fw_boot;
+		pr_err("hold ss51 & dsp fail.");
+		return FAIL;
 	}
 
 	/* step4:set scramble */
-	GTP_DEBUG("[burn_fw_boot]step4:set scramble");
+	pr_debug("step4:set scramble");
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_boot]set scramble fail.");
-		ret = FAIL;
-		goto exit_burn_fw_boot;
+		pr_err("set scramble fail.");
+		return FAIL;
 	}
 
 	/* step5:release ss51 & dsp */
-	GTP_DEBUG("[burn_fw_boot]step5:release ss51 & dsp");
+	pr_debug("step5:release ss51 & dsp");
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_boot]release ss51 & dsp fail.");
-		ret = FAIL;
-		goto exit_burn_fw_boot;
+		pr_err("release ss51 & dsp fail.");
+		return FAIL;
 	}
 	/* must delay */
 	msleep(20);
 
 	/* step6:select bank3 */
-	GTP_DEBUG("[burn_fw_boot]step6:select bank3");
+	pr_debug("step6:select bank3");
 	ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x03);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_boot]select bank3 fail.");
-		ret = FAIL;
-		goto exit_burn_fw_boot;
+		pr_err("select bank3 fail.");
+		return FAIL;
 	}
 
 	/* step7:burn 2k bootloader firmware */
-	GTP_DEBUG("[burn_fw_boot]step7:burn 2k bootloader firmware");
+	pr_debug("step7:burn 2k bootloader firmware");
 	ret = gup_burn_proc(client, fw_boot, 0x9000, FW_BOOT_LENGTH);
 	if (ret == FAIL) {
-		GTP_ERROR("[burn_fw_boot]burn fw_section fail.");
-		goto exit_burn_fw_boot;
+		pr_err("burn fw_section fail.");
+		return ret;
 	}
 
 	/* step7:send burn cmd to move data to flash from sram */
-	GTP_DEBUG("[burn_fw_boot]step7:send burn cmd to move data to" \
-				"flash from sram");
+	pr_debug("step7:send burn cmd to flash data from sram");
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x06);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_boot]send burn cmd fail.");
-		goto exit_burn_fw_boot;
+		pr_err("send burn cmd fail.");
+		return ret;
 	}
-	GTP_DEBUG("[burn_fw_boot]Wait for the burn is complete......");
+	pr_debug("Wait for the burn is complete.");
 	do {
 		ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1);
 		if (ret <= 0) {
-			GTP_ERROR("[burn_fw_boot]Get burn state fail");
-			goto exit_burn_fw_boot;
+			pr_err("Get burn state fail");
+			return ret;
 		}
 		msleep(20);
-		/* GTP_DEBUG("[burn_fw_boot]Get burn state:%d.",
-						rd_buf[GTP_ADDR_LENGTH]); */
 	} while (rd_buf[GTP_ADDR_LENGTH]);
 
 	/* step8:recall check 2k bootloader firmware */
-	GTP_DEBUG("[burn_fw_boot]step8:recall check 2k bootloader firmware");
+	pr_debug("step8:recall check 2k bootloader firmware");
 	ret = gup_recall_check(client, fw_boot, 0x9000, FW_BOOT_LENGTH);
 	if (ret == FAIL) {
-		GTP_ERROR("[burn_fw_boot]recall check 4k dsp firmware fail.");
-		goto exit_burn_fw_boot;
+		pr_err("recall check 4k dsp firmware fail.");
+		return ret;
 	}
 
 	/* step9:enable download DSP code  */
-	GTP_DEBUG("[burn_fw_boot]step9:enable download DSP code ");
+	pr_debug("step9:enable download DSP code ");
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x99);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_boot]enable download DSP code fail.");
-		ret = FAIL;
-		goto exit_burn_fw_boot;
+		pr_err("enable download DSP code fail.");
+		return FAIL;
 	}
 
 	/* step10:release ss51 & hold dsp */
-	GTP_DEBUG("[burn_fw_boot]step10:release ss51 & hold dsp");
+	pr_debug("step10:release ss51 & hold dsp");
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x08);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_boot]release ss51 & hold dsp fail.");
-		ret = FAIL;
-		goto exit_burn_fw_boot;
+		pr_err("release ss51 & hold dsp fail.");
+		return FAIL;
 	}
 
-	ret = SUCCESS;
-
-exit_burn_fw_boot:
-	kfree(fw_boot);
-	return ret;
+	return SUCCESS;
 }
 
 s32 gup_update_proc(void *dir)
 {
 	s32 ret = 0;
-	u8  retry = 0;
-	st_fw_head fw_head;
+	u8 retry = 0;
+	struct st_fw_head fw_head;
 	struct goodix_ts_data *ts = NULL;
 
-	GTP_DEBUG("[update_proc]Begin update ......");
+	pr_debug("Begin update.");
+
+	if (!i2c_connect_client) {
+		pr_err("No i2c connect client for %s\n", __func__);
+		return -EIO;
+	}
 
 	show_len = 1;
 	total_len = 100;
-	if (dir == NULL)
-		/* wait main thread to be completed */
-	msleep(3000);
 
 	ts = i2c_get_clientdata(i2c_connect_client);
 
 	if (searching_file) {
 		/* exit .bin update file searching  */
 		searching_file = 0;
-		GTP_INFO("Exiting searching .bin update file...");
+		pr_info("Exiting searching .bin update file.");
 		/* wait for auto update quitted completely */
 		while ((show_len != 200) && (show_len != 100))
 			msleep(100);
 	}
 
-	update_msg.file = NULL;
 	ret = gup_check_update_file(i2c_connect_client, &fw_head, (u8 *)dir);
 	if (ret == FAIL) {
-		GTP_ERROR("[update_proc]check update file fail.");
+		pr_err("check update file fail.");
 		goto file_fail;
 	}
 
 	/* gtp_reset_guitar(i2c_connect_client, 20); */
 	ret = gup_get_ic_fw_msg(i2c_connect_client);
 	if (ret == FAIL) {
-		GTP_ERROR("[update_proc]get ic message fail.");
+		pr_err("get ic message fail.");
 		goto file_fail;
 	}
 
-	ret = gup_enter_update_judge(&fw_head);
+	ret = gup_enter_update_judge(ts->client, &fw_head);
 	if (ret == FAIL) {
-		GTP_ERROR("[update_proc]Check *.bin file fail.");
+		pr_err("Check *.bin file fail.");
 		goto file_fail;
 	}
 
@@ -1675,7 +1472,7 @@
 #endif
 	ret = gup_enter_update_mode(i2c_connect_client);
 	if (ret == FAIL) {
-		GTP_ERROR("[update_proc]enter update mode fail.");
+		pr_err("enter update mode fail.");
 		goto update_fail;
 	}
 
@@ -1684,52 +1481,46 @@
 		total_len = 100;
 		ret = gup_burn_dsp_isp(i2c_connect_client);
 		if (ret == FAIL) {
-			GTP_ERROR("[update_proc]burn dsp isp fail.");
+			pr_err("burn dsp isp fail.");
 			continue;
 		}
 
 		show_len += 10;
 		ret = gup_burn_fw_ss51(i2c_connect_client);
 		if (ret == FAIL) {
-			GTP_ERROR("[update_proc]burn ss51 firmware fail.");
+			pr_err("burn ss51 firmware fail.");
 			continue;
 		}
 
 		show_len += 40;
 		ret = gup_burn_fw_dsp(i2c_connect_client);
 		if (ret == FAIL) {
-			GTP_ERROR("[update_proc]burn dsp firmware fail.");
+			pr_err("burn dsp firmware fail.");
 			continue;
 		}
 
 		show_len += 20;
 		ret = gup_burn_fw_boot(i2c_connect_client);
 		if (ret == FAIL) {
-			GTP_ERROR("[update_proc]burn bootloader fw fail.");
+			pr_err("burn bootloader fw fail.");
 			continue;
 		}
 		show_len += 10;
-		GTP_INFO("[update_proc]UPDATE SUCCESS.");
+		pr_info("UPDATE SUCCESS.");
 		break;
 	}
 	if (retry >= 5) {
-		GTP_ERROR("[update_proc]retry timeout,UPDATE FAIL.");
+		pr_err("retry timeout,UPDATE FAIL.");
 		goto update_fail;
 	}
 
-	GTP_DEBUG("[update_proc]leave update mode.");
-	gup_leave_update_mode();
+	pr_debug("leave update mode.");
+	gup_leave_update_mode(i2c_connect_client);
 
 	msleep(100);
 
-	/* GTP_DEBUG("[update_proc]send config.");
-	ret = gtp_send_cfg(i2c_connect_client);
-	if(ret < 0) {
-		GTP_ERROR("[update_proc]send config fail.");
-	} */
-
 	if (ts->fw_error) {
-		GTP_INFO("firmware error auto update, resent config!");
+		pr_info("firmware error auto update, resent config!");
 		gup_init_panel(ts);
 	}
 	show_len = 100;
@@ -1740,7 +1531,11 @@
 #if GTP_ESD_PROTECT
 	gtp_esd_switch(ts->client, SWITCH_ON);
 #endif
-	filp_close(update_msg.file, NULL);
+	if (update_msg.need_free) {
+		devm_kfree(&ts->client->dev, update_msg.fw_data);
+		update_msg.need_free = false;
+	}
+
 	return SUCCESS;
 
 update_fail:
@@ -1752,26 +1547,28 @@
 #endif
 
 file_fail:
-	if (update_msg.file && !IS_ERR(update_msg.file))
-		filp_close(update_msg.file, NULL);
-
 	show_len = 200;
 	total_len = 100;
+	if (update_msg.need_free) {
+		devm_kfree(&ts->client->dev, update_msg.fw_data);
+		update_msg.need_free = false;
+	}
 	return FAIL;
 }
 
-#if GTP_AUTO_UPDATE
+static void gup_update_work(struct work_struct *work)
+{
+	if (gup_update_proc(NULL) == FAIL)
+		pr_err("Goodix update work fail!\n");
+}
+
 u8 gup_init_update_proc(struct goodix_ts_data *ts)
 {
-	struct task_struct *thread = NULL;
+	dev_dbg(&ts->client->dev, "Ready to run update work.");
 
-	GTP_INFO("Ready to run update thread.");
-	thread = kthread_run(gup_update_proc, (void *)NULL, "guitar_update");
-	if (IS_ERR(thread)) {
-		GTP_ERROR("Failed to create update thread.\n");
-		return -EINVAL;
-	}
+	INIT_DELAYED_WORK(&ts->goodix_update_work, gup_update_work);
+	schedule_delayed_work(&ts->goodix_update_work,
+		msecs_to_jiffies(3000));
 
 	return 0;
 }
-#endif
diff --git a/drivers/iommu/msm_iommu_sec.c b/drivers/iommu/msm_iommu_sec.c
index 5a1806e..e293279 100644
--- a/drivers/iommu/msm_iommu_sec.c
+++ b/drivers/iommu/msm_iommu_sec.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -43,6 +43,7 @@
 #define IOMMU_SECURE_CFG	2
 #define IOMMU_SECURE_PTBL_SIZE  3
 #define IOMMU_SECURE_PTBL_INIT  4
+#define IOMMU_SET_CP_POOL_SIZE	5
 #define IOMMU_SECURE_MAP	6
 #define IOMMU_SECURE_UNMAP      7
 #define IOMMU_SECURE_MAP2 0x0B
@@ -51,6 +52,12 @@
 
 /* commands for SCM_SVC_UTIL */
 #define IOMMU_DUMP_SMMU_FAULT_REGS 0X0C
+#define MAXIMUM_VIRT_SIZE	(300*SZ_1M)
+
+
+#define MAKE_CP_VERSION(major, minor, patch) \
+	(((major & 0x3FF) << 22) | ((minor & 0x3FF) << 12) | (patch & 0xFFF))
+
 
 static struct iommu_access_ops *iommu_access_ops;
 
@@ -78,6 +85,11 @@
 	unsigned int flags;
 };
 
+struct msm_cp_pool_size {
+	uint32_t size;
+	uint32_t spare;
+};
+
 #define NUM_DUMP_REGS 14
 /*
  * some space to allow the number of registers returned by the secure
@@ -282,6 +294,7 @@
 	int psize[2] = {0, 0};
 	unsigned int spare;
 	int ret, ptbl_ret = 0;
+	int version;
 
 	for_each_compatible_node(np, NULL, "qcom,msm-smmu-v1")
 		if (of_find_property(np, "qcom,iommu-secure-id", NULL))
@@ -291,6 +304,26 @@
 		return 0;
 
 	of_node_put(np);
+
+	version = scm_get_feat_version(SCM_SVC_MP);
+
+	if (version >= MAKE_CP_VERSION(1, 1, 1)) {
+		struct msm_cp_pool_size psize;
+		int retval;
+
+		psize.size = MAXIMUM_VIRT_SIZE;
+		psize.spare = 0;
+
+		ret = scm_call(SCM_SVC_MP, IOMMU_SET_CP_POOL_SIZE, &psize,
+				sizeof(psize), &retval, sizeof(retval));
+
+		if (ret) {
+			pr_err("scm call IOMMU_SET_CP_POOL_SIZE failed\n");
+			goto fail;
+		}
+
+	}
+
 	ret = scm_call(SCM_SVC_MP, IOMMU_SECURE_PTBL_SIZE, &spare,
 			sizeof(spare), psize, sizeof(psize));
 	if (ret) {
diff --git a/drivers/media/platform/msm/camera_v2/camera/camera.c b/drivers/media/platform/msm/camera_v2/camera/camera.c
index eda6150..3f7ba6b 100644
--- a/drivers/media/platform/msm/camera_v2/camera/camera.c
+++ b/drivers/media/platform/msm/camera_v2/camera/camera.c
@@ -64,9 +64,13 @@
 	struct msm_v4l2_event_data *event_data =
 		(struct msm_v4l2_event_data *)&event->u.data[0];
 
-	if (event_data->status > MSM_CAMERA_ERR_EVT_BASE)
+	if (event_data->status > MSM_CAMERA_ERR_EVT_BASE) {
+		pr_err("%s : event_data status out of bounds\n",
+				__func__);
+		pr_err("%s : Line %d event_data->status 0X%x\n",
+				__func__, __LINE__, event_data->status);
 		return -EFAULT;
-
+	}
 	return 0;
 }
 
@@ -461,9 +465,11 @@
 	struct camera_v4l2_private *sp;
 
 	sp = kzalloc(sizeof(*sp), GFP_KERNEL);
-	if (!sp)
-		return -ENOMEM;
 
+	if (!sp) {
+		pr_err("%s : memory not available\n", __func__);
+		return -ENOMEM;
+	}
 	filep->private_data = &sp->fh;
 
 	/* stream_id = open id */
@@ -498,9 +504,10 @@
 	/* free up this buffer when stream is done */
 	q->drv_priv =
 		kzalloc(sizeof(struct msm_v4l2_format_data), GFP_KERNEL);
-	if (!q->drv_priv)
+	if (!q->drv_priv) {
+		pr_err("%s : memory not available\n", __func__);
 		return -ENOMEM;
-
+	}
 	q->mem_ops = msm_vb2_get_q_mem_ops();
 	q->ops = msm_vb2_get_q_ops();
 
@@ -530,38 +537,60 @@
 	BUG_ON(!pvdev);
 
 	rc = camera_v4l2_fh_open(filep);
-	if (rc < 0)
-		goto fh_open_fail;
 
+	if (rc < 0) {
+		pr_err("%s : camera_v4l2_fh_open failed Line %d rc %d\n",
+				__func__, __LINE__, rc);
+		goto fh_open_fail;
+	}
 	/* every stream has a vb2 queue */
 	rc = camera_v4l2_vb2_q_init(filep);
-	if (rc < 0)
-		goto vb2_q_fail;
 
+	if (rc < 0) {
+		pr_err("%s : vb2 queue init fails Line %d rc %d\n",
+				__func__, __LINE__, rc);
+		goto vb2_q_fail;
+	}
 	if (!atomic_read(&pvdev->opened)) {
 		pm_stay_awake(&pvdev->vdev->dev);
 
 		/* create a new session when first opened */
 		rc = msm_create_session(pvdev->vdev->num, pvdev->vdev);
-		if (rc < 0)
+		if (rc < 0) {
+			pr_err("%s : session creation failed Line %d rc %d\n",
+					__func__, __LINE__, rc);
 			goto session_fail;
+		}
 		rc = msm_create_command_ack_q(pvdev->vdev->num, 0);
-		if (rc < 0)
-			goto command_ack_q_fail;
 
+		if (rc < 0) {
+			pr_err("%s : creation of command_ack queue failed\n",
+					__func__);
+			pr_err("%s : Line %d rc %d\n", __func__, __LINE__, rc);
+			goto command_ack_q_fail;
+		}
 		camera_pack_event(filep, MSM_CAMERA_NEW_SESSION, 0, -1, &event);
 		rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
-		if (rc < 0)
+		if (rc < 0) {
+			pr_err("%s : posting of NEW_SESSION event failed\n",
+					__func__);
+			pr_err("%s : Line %d rc %d\n", __func__, __LINE__, rc);
 			goto post_fail;
-
+		}
 		rc = camera_check_event_status(&event);
-		if (rc < 0)
+		if (rc < 0) {
+			pr_err("%s : checking event status fails Line %d rc %d\n",
+					__func__, __LINE__, rc);
 			goto post_fail;
+		}
 	} else {
 		rc = msm_create_command_ack_q(pvdev->vdev->num,
 			atomic_read(&pvdev->stream_cnt));
-		if (rc < 0)
+		if (rc < 0) {
+			pr_err("%s : creation of command_ack queue failed Line %d rc %d\n",
+					__func__, __LINE__, rc);
 			goto session_fail;
+		}
 	}
 
 	atomic_add(1, &pvdev->opened);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
index 59b648d..a85f853 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
@@ -374,11 +374,14 @@
 		if (bufq->buf_type == ISP_SHARE_BUF) {
 			temp_buf_info = kzalloc(
 			   sizeof(struct msm_isp_buffer), GFP_ATOMIC);
-			temp_buf_info->buf_reuse_flag = 1;
-			temp_buf_info->buf_used[id] = 1;
-			temp_buf_info->buf_get_count = 1;
-			list_add_tail(&temp_buf_info->share_list,
-						  &bufq->share_head);
+			if (temp_buf_info) {
+				temp_buf_info->buf_reuse_flag = 1;
+				temp_buf_info->buf_used[id] = 1;
+				temp_buf_info->buf_get_count = 1;
+				list_add_tail(&temp_buf_info->share_list,
+							  &bufq->share_head);
+			} else
+				rc = -ENOMEM;
 		}
 	} else {
 		(*buf_info)->state = MSM_ISP_BUFFER_STATE_DEQUEUED;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
index 9dd0085..95673d5 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
@@ -71,6 +71,12 @@
 	DISABLE_CAMIF_IMMEDIATELY
 };
 
+enum msm_isp_reset_type {
+	ISP_RST_HARD,
+	ISP_RST_SOFT,
+	ISP_RST_MAX
+};
+
 struct msm_isp_timestamp {
 	/*Monotonic clock for v4l2 buffer*/
 	struct timeval buf_time;
@@ -147,7 +153,8 @@
 
 struct msm_vfe_core_ops {
 	void (*reg_update) (struct vfe_device *vfe_dev);
-	long (*reset_hw) (struct vfe_device *vfe_dev);
+	long (*reset_hw) (struct vfe_device *vfe_dev,
+		enum msm_isp_reset_type reset_type);
 	int (*init_hw) (struct vfe_device *vfe_dev);
 	void (*init_hw_reg) (struct vfe_device *vfe_dev);
 	void (*release_hw) (struct vfe_device *vfe_dev);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
index 410fe8f..044f6f1 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
@@ -152,6 +152,11 @@
 	msm_camera_io_w_mb(0x1CFFFFFF, vfe_dev->vfe_base + 0x20);
 	msm_camera_io_w(0xFFFFFFFF, vfe_dev->vfe_base + 0x24);
 	msm_camera_io_w_mb(0x1FFFFFFF, vfe_dev->vfe_base + 0x28);
+	msm_camera_io_w(0x0, vfe_dev->vfe_base+0x6FC);
+	msm_camera_io_w( 0x10000000,vfe_dev->vfe_base + VFE32_RDI_BASE(1));
+	msm_camera_io_w( 0x10000000,vfe_dev->vfe_base + VFE32_RDI_BASE(2));
+	msm_camera_io_w(0x0, vfe_dev->vfe_base + VFE32_XBAR_BASE(0));
+	msm_camera_io_w(0x0, vfe_dev->vfe_base + VFE32_XBAR_BASE(4));
 
 }
 
@@ -322,7 +327,6 @@
 	uint32_t irq_status0, uint32_t irq_status1,
 	struct msm_isp_timestamp *ts)
 {
-	uint32_t rdi_status;
 	if (!(irq_status0 & 0x20) && !(irq_status1 & 0x1C000000))
 		return;
 
@@ -335,18 +339,6 @@
 	if (irq_status1 & BIT(28))
 		msm_isp_sof_notify(vfe_dev, VFE_RAW_2, ts);
 
-	if (vfe_dev->axi_data.stream_update) {
-		rdi_status = msm_camera_io_r(vfe_dev->vfe_base +
-						VFE32_XBAR_BASE(0));
-		rdi_status |= msm_camera_io_r(vfe_dev->vfe_base +
-						VFE32_XBAR_BASE(4));
-
-		if (((rdi_status & BIT(7)) || (rdi_status & BIT(7)) ||
-			(rdi_status & BIT(7)) || (rdi_status & BIT(7))) &&
-			(!(irq_status0 & 0x20)))
-			return;
-	}
-
 	if (vfe_dev->axi_data.stream_update)
 		msm_isp_axi_stream_update(vfe_dev);
 	if (atomic_read(&vfe_dev->stats_data.stats_update))
@@ -365,10 +357,24 @@
 	msm_camera_io_w_mb(0xF, vfe_dev->vfe_base + 0x260);
 }
 
-static long msm_vfe32_reset_hardware(struct vfe_device *vfe_dev)
+static uint32_t msm_vfe32_reset_values[ISP_RST_MAX] =
 {
+	0x3FF, /* ISP_RST_HARD reset everything */
+	0x3EF /* ISP_RST_SOFT same as HARD RESET */
+};
+
+static long msm_vfe32_reset_hardware(struct vfe_device *vfe_dev ,
+				enum msm_isp_reset_type reset_type)
+{
+
+	uint32_t rst_val;
+	if (reset_type >= ISP_RST_MAX) {
+		pr_err("%s: Error Invalid parameter\n", __func__);
+		reset_type = ISP_RST_HARD;
+	}
+	rst_val = msm_vfe32_reset_values[reset_type];
 	init_completion(&vfe_dev->reset_complete);
-	msm_camera_io_w_mb(0x3FF, vfe_dev->vfe_base + 0x4);
+	msm_camera_io_w_mb(rst_val, vfe_dev->vfe_base + 0x4);
 	return wait_for_completion_interruptible_timeout(
 	   &vfe_dev->reset_complete, msecs_to_jiffies(50));
 }
@@ -381,9 +387,8 @@
 		msm_camera_io_w_mb(reload_mask, vfe_dev->vfe_base + 0x38);
 	} else {
 		/*vfe32 B-family: 8610*/
-		msm_camera_io_w(0x0, vfe_dev->vfe_base + 0x24);
 		msm_camera_io_w(0x0, vfe_dev->vfe_base + 0x28);
-		msm_camera_io_w(0x0, vfe_dev->vfe_base + 0x20);
+		msm_camera_io_w(0x1C800000, vfe_dev->vfe_base + 0x20);
 		msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x18);
 		msm_camera_io_w(0x9AAAAAAA , vfe_dev->vfe_base + 0x600);
 		msm_camera_io_w(reload_mask, vfe_dev->vfe_base + 0x38);
@@ -632,9 +637,6 @@
 		vfe_dev->axi_data.src_info[VFE_PIX_0].active = 0;
 	} else if (update_state == DISABLE_CAMIF_IMMEDIATELY) {
 		msm_camera_io_w_mb(0x6, vfe_dev->vfe_base + 0x1E0);
-		vfe_dev->hw_info->vfe_ops.axi_ops.halt(vfe_dev);
-		vfe_dev->hw_info->vfe_ops.core_ops.reset_hw(vfe_dev);
-		vfe_dev->hw_info->vfe_ops.core_ops.init_hw_reg(vfe_dev);
 		vfe_dev->axi_data.src_info[VFE_PIX_0].active = 0;
 	}
 }
@@ -708,6 +710,8 @@
 {
 	uint32_t val = 0;
 	uint32_t wm_base = VFE32_WM_BASE(stream_info->wm[plane_idx]);
+	/* FRAME BASED */
+	msm_camera_io_w(val, vfe_dev->vfe_base + wm_base);
 	/*WR_IMAGE_SIZE*/
 	msm_camera_io_w(val, vfe_dev->vfe_base + wm_base + 0x10);
 	/*WR_BUFFER_CFG*/
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
index 8c7890d..d53d7f6 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -581,10 +581,24 @@
 	msm_camera_io_w_mb(0xF, vfe_dev->vfe_base + 0x378);
 }
 
-static long msm_vfe40_reset_hardware(struct vfe_device *vfe_dev)
+static uint32_t msm_vfe40_reset_values[ISP_RST_MAX] =
 {
+	0x1FF, /* ISP_RST_HARD reset everything */
+	0x1EF /* ISP_RST_SOFT all modules without registers */
+};
+
+
+static long msm_vfe40_reset_hardware(struct vfe_device *vfe_dev ,
+				enum msm_isp_reset_type reset_type)
+{
+	uint32_t rst_val;
+	if (reset_type >= ISP_RST_MAX) {
+		pr_err("%s: Error Invalid parameter\n", __func__);
+		reset_type = ISP_RST_HARD;
+	}
+	rst_val = msm_vfe40_reset_values[reset_type];
 	init_completion(&vfe_dev->reset_complete);
-	msm_camera_io_w_mb(0x1FF, vfe_dev->vfe_base + 0xC);
+	msm_camera_io_w_mb(rst_val, vfe_dev->vfe_base + 0xC);
 	return wait_for_completion_interruptible_timeout(
 		&vfe_dev->reset_complete, msecs_to_jiffies(50));
 }
@@ -886,9 +900,6 @@
 		vfe_dev->axi_data.src_info[VFE_PIX_0].active = 0;
 	} else if (update_state == DISABLE_CAMIF_IMMEDIATELY) {
 		msm_camera_io_w_mb(0x6, vfe_dev->vfe_base + 0x2F4);
-		vfe_dev->hw_info->vfe_ops.axi_ops.halt(vfe_dev);
-		vfe_dev->hw_info->vfe_ops.core_ops.reset_hw(vfe_dev);
-		vfe_dev->hw_info->vfe_ops.core_ops.init_hw_reg(vfe_dev);
 		vfe_dev->axi_data.src_info[VFE_PIX_0].active = 0;
 	}
 }
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
index 97b6347..8c02bc7 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -947,6 +947,68 @@
 	}
 }
 
+static void msm_isp_update_rdi_output_count(
+	  struct vfe_device *vfe_dev,
+	  struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd)
+{
+	int i;
+	struct msm_vfe_axi_stream *stream_info;
+	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
+
+	if (stream_cfg_cmd->num_streams > MAX_NUM_STREAM) {
+		return;
+	}
+
+	for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
+		if (HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i])
+		> MAX_NUM_STREAM) {
+			return;
+		}
+		stream_info =
+			&axi_data->stream_info[
+			HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i])];
+		if (stream_info->stream_src < RDI_INTF_0)
+			continue;
+		if (stream_info->stream_src == RDI_INTF_0) {
+			if (stream_cfg_cmd->cmd == START_STREAM)
+				vfe_dev->axi_data.src_info[VFE_RAW_0].
+					raw_stream_count++;
+			else
+				vfe_dev->axi_data.src_info[VFE_RAW_0].
+					raw_stream_count--;
+		} else if (stream_info->stream_src == RDI_INTF_1) {
+			if (stream_cfg_cmd->cmd == START_STREAM)
+				vfe_dev->axi_data.src_info[VFE_RAW_1].
+					raw_stream_count++;
+			else
+				vfe_dev->axi_data.src_info[VFE_RAW_1].
+					raw_stream_count--;
+		} else if (stream_info->stream_src == RDI_INTF_2) {
+		       if (stream_cfg_cmd->cmd == START_STREAM)
+				vfe_dev->axi_data.src_info[VFE_RAW_2].
+					raw_stream_count++;
+			else
+				vfe_dev->axi_data.src_info[VFE_RAW_2].
+					raw_stream_count--;
+		}
+
+	}
+}
+
+static uint8_t msm_isp_get_curr_stream_cnt(
+	  struct vfe_device *vfe_dev)
+{
+         uint8_t curr_stream_cnt = 0;
+	  curr_stream_cnt = vfe_dev->axi_data.src_info[VFE_RAW_0].
+					raw_stream_count + vfe_dev->axi_data.src_info[VFE_RAW_1].
+					raw_stream_count + vfe_dev->axi_data.src_info[VFE_RAW_2].
+					raw_stream_count + vfe_dev->axi_data.src_info[VFE_PIX_0].
+					pix_stream_count  + vfe_dev->axi_data.src_info[VFE_PIX_0].
+					raw_stream_count;
+
+	  return curr_stream_cnt;
+}
+
 void msm_camera_io_dump_2(void __iomem *addr, int size)
 {
 	char line_str[128], *p_str;
@@ -1144,11 +1206,23 @@
 	vfe_dev->hw_info->vfe_ops.core_ops.reg_update(vfe_dev);
 
 	msm_isp_update_camif_output_count(vfe_dev, stream_cfg_cmd);
+	msm_isp_update_rdi_output_count(vfe_dev, stream_cfg_cmd);
 	if (camif_update == ENABLE_CAMIF) {
 		vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id = 0;
 		vfe_dev->hw_info->vfe_ops.core_ops.
 			update_camif_state(vfe_dev, camif_update);
 	}
+
+	if (vfe_dev->axi_data.src_info[VFE_RAW_0].raw_stream_count > 0) {
+		vfe_dev->axi_data.src_info[VFE_RAW_0].frame_id = 0;
+	}
+	else if (vfe_dev->axi_data.src_info[VFE_RAW_1].raw_stream_count > 0) {
+		vfe_dev->axi_data.src_info[VFE_RAW_1].frame_id = 0;
+	}
+	else if (vfe_dev->axi_data.src_info[VFE_RAW_2].raw_stream_count > 0) {
+		vfe_dev->axi_data.src_info[VFE_RAW_2].frame_id = 0;
+	}
+
 	if (wait_for_complete)
 		rc = msm_isp_axi_wait_for_cfg_done(vfe_dev, camif_update);
 
@@ -1160,7 +1234,7 @@
 			enum msm_isp_camif_update_state camif_update)
 {
 	int i, rc = 0;
-	uint8_t wait_for_complete = 0;
+	uint8_t wait_for_complete = 0, cur_stream_cnt = 0;
 	struct msm_vfe_axi_stream *stream_info;
 	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
 
@@ -1216,6 +1290,15 @@
 		vfe_dev->hw_info->vfe_ops.core_ops.
 			update_camif_state(vfe_dev, DISABLE_CAMIF_IMMEDIATELY);
 	msm_isp_update_camif_output_count(vfe_dev, stream_cfg_cmd);
+	msm_isp_update_rdi_output_count(vfe_dev, stream_cfg_cmd);
+	cur_stream_cnt = msm_isp_get_curr_stream_cnt(vfe_dev);
+	if (cur_stream_cnt == 0) {
+		if (camif_update == DISABLE_CAMIF_IMMEDIATELY) {
+			vfe_dev->hw_info->vfe_ops.axi_ops.halt(vfe_dev);
+		}
+		vfe_dev->hw_info->vfe_ops.core_ops.reset_hw(vfe_dev, ISP_RST_SOFT);
+		vfe_dev->hw_info->vfe_ops.core_ops.init_hw_reg(vfe_dev);
+	}
 
 	for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
 		stream_info = &axi_data->stream_info[
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
index a12c692..7347251 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
@@ -1102,7 +1102,7 @@
 		return -EBUSY;
 	}
 
-	rc = vfe_dev->hw_info->vfe_ops.core_ops.reset_hw(vfe_dev);
+	rc = vfe_dev->hw_info->vfe_ops.core_ops.reset_hw(vfe_dev, ISP_RST_HARD);
 	if (rc <= 0) {
 		pr_err("%s: reset timeout\n", __func__);
 		mutex_unlock(&vfe_dev->core_mutex);
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.c
index 5cc51ff..4331f95 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.c
@@ -16,6 +16,7 @@
 #include <linux/list.h>
 #include <linux/uaccess.h>
 #include <linux/slab.h>
+#include <linux/ratelimit.h>
 #include <media/msm_jpeg.h>
 #include "msm_jpeg_sync.h"
 #include "msm_jpeg_core.h"
@@ -909,7 +910,7 @@
 		rc = msm_jpeg_ioctl_set_clk_rate(pgmn_dev, arg);
 		break;
 	default:
-		JPEG_PR_ERR(KERN_INFO "%s:%d] cmd = %d not supported\n",
+		pr_err_ratelimited("%s:%d] cmd = %d not supported\n",
 			__func__, __LINE__, _IOC_NR(cmd));
 		rc = -EINVAL;
 		break;
diff --git a/drivers/media/platform/msm/camera_v2/msm.c b/drivers/media/platform/msm/camera_v2/msm.c
index 8a2c8e5..b1a23b4 100644
--- a/drivers/media/platform/msm/camera_v2/msm.c
+++ b/drivers/media/platform/msm/camera_v2/msm.c
@@ -341,17 +341,26 @@
 {
 	struct msm_session *session = NULL;
 
-	if (!msm_session_q)
+	if (!msm_session_q) {
+		pr_err("%s : session queue not available Line %d\n",
+				__func__, __LINE__);
 		return -ENODEV;
+	}
 
 	session = msm_queue_find(msm_session_q, struct msm_session,
 		list, __msm_queue_find_session, &session_id);
-	if (session)
+	if (session) {
+		pr_err("%s : Session not found Line %d\n",
+				__func__, __LINE__);
 		return -EINVAL;
+	}
 
 	session = kzalloc(sizeof(*session), GFP_KERNEL);
-	if (!session)
+	if (!session) {
+		pr_err("%s : Memory not available Line %d\n",
+				__func__, __LINE__);
 		return -ENOMEM;
+	}
 
 	session->session_id = session_id;
 	session->event_q.vdev = vdev;
@@ -367,17 +376,25 @@
 	struct msm_session *session;
 	struct msm_command_ack *cmd_ack;
 
-	if (!msm_session_q)
+	if (!msm_session_q) {
+		pr_err("%s : Session queue not available Line %d\n",
+				__func__, __LINE__);
 		return -ENODEV;
+	}
 
 	session = msm_queue_find(msm_session_q, struct msm_session,
 		list, __msm_queue_find_session, &session_id);
-	if (!session)
+	if (!session) {
+		pr_err("%s : Session not found Line %d\n",
+				__func__, __LINE__);
 		return -EINVAL;
+	}
 	mutex_lock(&session->lock);
 	cmd_ack = kzalloc(sizeof(*cmd_ack), GFP_KERNEL);
 	if (!cmd_ack) {
 		mutex_unlock(&session->lock);
+		pr_err("%s : memory not available Line %d\n",
+				__func__, __LINE__);
 		return -ENOMEM;
 	}
 
@@ -652,6 +669,8 @@
 	spin_lock_irqsave(&msm_eventq_lock, flags);
 	if (!msm_eventq) {
 		spin_unlock_irqrestore(&msm_eventq_lock, flags);
+		pr_err("%s : msm event queue not available Line %d\n",
+				__func__, __LINE__);
 		return -ENODEV;
 	}
 	spin_unlock_irqrestore(&msm_eventq_lock, flags);
@@ -661,14 +680,19 @@
 	/* send to imaging server and wait for ACK */
 	session = msm_queue_find(msm_session_q, struct msm_session,
 		list, __msm_queue_find_session, &session_id);
-	if (WARN_ON(!session))
+	if (WARN_ON(!session)) {
+		pr_err("%s : session not found Line %d\n",
+				__func__, __LINE__);
 		return -EIO;
+	}
 	mutex_lock(&session->lock);
 	cmd_ack = msm_queue_find(&session->command_ack_q,
 		struct msm_command_ack, list,
 		__msm_queue_find_command_ack_q, &stream_id);
 	if (WARN_ON(!cmd_ack)) {
 		mutex_unlock(&session->lock);
+		pr_err("%s : cmd_ack not found Line %d\n",
+				__func__, __LINE__);
 		return -EIO;
 	}
 
@@ -676,6 +700,8 @@
 
 	if (timeout < 0) {
 		mutex_unlock(&session->lock);
+		pr_err("%s : timeout cannot be negative Line %d\n",
+				__func__, __LINE__);
 		return rc;
 	}
 
@@ -704,6 +730,8 @@
 		struct msm_command, list);
 	if (!cmd) {
 		mutex_unlock(&session->lock);
+		pr_err("%s : cmd dequeue failed Line %d\n",
+				__func__, __LINE__);
 		return -EINVAL;
 	}
 
@@ -711,9 +739,15 @@
 
 	/* compare cmd_ret and event */
 	if (WARN_ON(event->type != cmd->event.type) ||
-			WARN_ON(event->id != cmd->event.id))
+			WARN_ON(event->id != cmd->event.id)) {
+		pr_err("%s : Either event type or id didnot match Line %d\n",
+				__func__, __LINE__);
+		pr_err("%s : event->type %d event->id %d\n", __func__,
+				event->type, event->id);
+		pr_err("%s : cmd->event.type %d cmd->event.id %d\n", __func__,
+				cmd->event.type, cmd->event.id);
 		rc = -EINVAL;
-
+	}
 	*event = cmd->event;
 
 	kzfree(cmd);
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
index e50e8c5..10a0085 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
@@ -1208,7 +1208,7 @@
 	uint32_t *cpp_frame_msg;
 	unsigned long in_phyaddr, out_phyaddr0, out_phyaddr1;
 	uint16_t num_stripes = 0;
-	struct msm_buf_mngr_info buff_mgr_info;
+	struct msm_buf_mngr_info buff_mgr_info, dup_buff_mgr_info;
 	struct msm_cpp_frame_info_t *u_frame_info =
 		(struct msm_cpp_frame_info_t *)ioctl_ptr->ioctl_ptr;
 	int32_t status = 0;
@@ -1295,19 +1295,20 @@
 			new_frame->duplicate_identity);
 		memset(&new_frame->output_buffer_info[1], 0,
 			sizeof(struct msm_cpp_buffer_info_t));
-		memset(&buff_mgr_info, 0, sizeof(struct msm_buf_mngr_info));
-		buff_mgr_info.session_id =
+		memset(&dup_buff_mgr_info, 0, sizeof(struct msm_buf_mngr_info));
+		dup_buff_mgr_info.session_id =
 			((new_frame->duplicate_identity >> 16) & 0xFFFF);
-		buff_mgr_info.stream_id =
+		dup_buff_mgr_info.stream_id =
 			(new_frame->duplicate_identity & 0xFFFF);
 		rc = msm_cpp_buffer_ops(cpp_dev, VIDIOC_MSM_BUF_MNGR_GET_BUF,
-			&buff_mgr_info);
+			&dup_buff_mgr_info);
 		if (rc < 0) {
 			rc = -EAGAIN;
 			pr_debug("error getting buffer rc:%d\n", rc);
-			goto ERROR2;
+			goto ERROR3;
 		}
-		new_frame->output_buffer_info[1].index = buff_mgr_info.index;
+		new_frame->output_buffer_info[1].index =
+			dup_buff_mgr_info.index;
 		out_phyaddr1 = msm_cpp_fetch_buffer_info(cpp_dev,
 			&new_frame->output_buffer_info[1],
 			((new_frame->duplicate_identity >> 16) & 0xFFFF),
@@ -1316,6 +1317,8 @@
 		if (!out_phyaddr1) {
 			pr_err("error gettting output physical address\n");
 			rc = -EINVAL;
+			msm_cpp_buffer_ops(cpp_dev, VIDIOC_MSM_BUF_MNGR_PUT_BUF,
+				&dup_buff_mgr_info);
 			goto ERROR3;
 		}
 		/* set duplicate enable bit */
diff --git a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
index 468ba74..3fc3634 100644
--- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
@@ -389,18 +389,22 @@
 	rc = msm_vidc_initialize_core(pdev, core);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to init core\n");
-		goto err_v4l2_register;
+		goto err_core_init;
 	}
 	rc = device_create_file(&pdev->dev, &dev_attr_pwr_collapse_delay);
 	if (rc) {
 		dprintk(VIDC_ERR,
 				"Failed to create pwr_collapse_delay sysfs node");
-		goto err_v4l2_register;
+		goto err_core_init;
 	}
 	if (core->hfi_type == VIDC_HFI_Q6) {
 		dprintk(VIDC_ERR, "Q6 hfi device probe called\n");
 		nr += MSM_VIDC_MAX_DEVICES;
+		core->id = MSM_VIDC_CORE_Q6;
+	} else {
+		core->id = MSM_VIDC_CORE_VENUS;
 	}
+
 	rc = v4l2_device_register(&pdev->dev, &core->v4l2_dev);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to register v4l2 device\n");
@@ -453,16 +457,20 @@
 				vidc_driver->num_cores);
 		goto err_cores_exceeded;
 	}
-	core->id = vidc_driver->num_cores++;
+	vidc_driver->num_cores++;
 	mutex_unlock(&vidc_driver->lock);
 
 	core->device = vidc_hfi_initialize(core->hfi_type, core->id,
 				&core->resources, &handle_cmd_response);
-	if (!core->device) {
-		dprintk(VIDC_ERR, "Failed to create HFI device\n");
+	if (IS_ERR_OR_NULL(core->device)) {
 		mutex_lock(&vidc_driver->lock);
 		vidc_driver->num_cores--;
 		mutex_unlock(&vidc_driver->lock);
+		rc = PTR_ERR(core->device);
+		if (rc != -EPROBE_DEFER)
+			dprintk(VIDC_ERR, "Failed to create HFI device\n");
+		else
+			dprintk(VIDC_DBG, "msm_vidc: request probe defer\n");
 		goto err_cores_exceeded;
 	}
 
@@ -487,6 +495,8 @@
 err_dec_register:
 	v4l2_device_unregister(&core->v4l2_dev);
 err_v4l2_register:
+	device_remove_file(&pdev->dev, &dev_attr_pwr_collapse_delay);
+err_core_init:
 	kfree(core);
 err_no_mem:
 	return rc;
diff --git a/drivers/media/platform/msm/vidc/q6_hfi.c b/drivers/media/platform/msm/vidc/q6_hfi.c
index 8e91f34..e70635d 100644
--- a/drivers/media/platform/msm/vidc/q6_hfi.c
+++ b/drivers/media/platform/msm/vidc/q6_hfi.c
@@ -210,8 +210,9 @@
 		iommu_map = &iommu_group_set->iommu_maps[i];
 		iommu_map->group = iommu_group_find(iommu_map->name);
 		if (!iommu_map->group) {
-			dprintk(VIDC_ERR, "Failed to find group :%s\n",
+			dprintk(VIDC_DBG, "Failed to find group :%s\n",
 					iommu_map->name);
+			rc = -EPROBE_DEFER;
 			goto fail_group;
 		}
 		domain = iommu_group_get_iommudata(iommu_map->group);
@@ -219,6 +220,7 @@
 			dprintk(VIDC_ERR,
 					"Failed to get domain data for group %p",
 					iommu_map->group);
+			rc = -EINVAL;
 			goto fail_group;
 		}
 		iommu_map->domain = msm_find_domain_no(domain);
@@ -226,6 +228,7 @@
 			dprintk(VIDC_ERR,
 					"Failed to get domain index for domain %p",
 					domain);
+			rc = -EINVAL;
 			goto fail_group;
 		}
 	}
@@ -239,7 +242,7 @@
 		iommu_map->group = NULL;
 		iommu_map->domain = -1;
 	}
-	return -EINVAL;
+	return rc;
 }
 
 static void q6_hfi_deregister_iommu_domains(struct q6_hfi_device *device)
@@ -275,8 +278,12 @@
 
 	device->res = res;
 	rc = q6_hfi_register_iommu_domains(device);
-	if (rc)
-		dprintk(VIDC_ERR, "Failed to register iommu domains: %d\n", rc);
+	if (rc) {
+		if (rc != -EPROBE_DEFER) {
+			dprintk(VIDC_ERR,
+				"Failed to register iommu domains: %d\n", rc);
+		}
+	}
 
 	return rc;
 }
@@ -351,14 +358,15 @@
 
 	rc = q6_hfi_init_resources(device, res);
 	if (rc) {
-		dprintk(VIDC_ERR, "Failed to init resources: %d\n", rc);
+		if (rc != -EPROBE_DEFER)
+			dprintk(VIDC_ERR, "Failed to init resources: %d\n", rc);
 		goto err_fail_init_res;
 	}
 	return device;
 
 err_fail_init_res:
 	q6_hfi_delete_device(device);
-	return NULL;
+	return ERR_PTR(rc);
 }
 
 void q6_hfi_delete_device(void *device)
@@ -1379,6 +1387,12 @@
 	}
 	hdev->hfi_device_data = q6_hfi_get_device(device_id, res, callback);
 
+	if (IS_ERR_OR_NULL(hdev->hfi_device_data)) {
+		rc = PTR_ERR(hdev->hfi_device_data);
+		rc = !rc ? -EINVAL : rc;
+		goto err_hfi_init;
+	}
+
 	q6_init_hfi_callbacks(hdev);
 
 err_hfi_init:
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 7f09b24..6d51c96 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -85,6 +85,9 @@
 
 static int venus_hfi_power_enable(void *dev);
 
+static unsigned long venus_hfi_get_clock_rate(struct venus_core_clock *clock,
+		int num_mbs_per_sec);
+
 static void venus_hfi_dump_packet(u8 *packet)
 {
 	u32 c = 0, packet_size = *(u32 *)packet;
@@ -861,7 +864,7 @@
 /*Calling function is responsible to acquire device->clk_pwr_lock*/
 static inline void venus_hfi_clk_disable(struct venus_hfi_device *device)
 {
-	int i;
+	int i, rc = 0;
 	struct venus_core_clock *cl;
 
 	if (!device) {
@@ -873,6 +876,14 @@
 		return;
 	}
 
+	/* We get better power savings if we lower the venus core clock to the
+	 * lowest level before disabling it. */
+	rc = clk_set_rate(device->resources.clock[VCODEC_CLK].clk,
+			venus_hfi_get_clock_rate(
+			&device->resources.clock[VCODEC_CLK], 0));
+	if (rc)
+		dprintk(VIDC_WARN, "Failed to set clock rate to min: %d\n", rc);
+
 	for (i = 0; i <= device->clk_gating_level; i++) {
 		cl = &device->resources.clock[i];
 		clk_disable(cl->clk);
@@ -1523,11 +1534,16 @@
 	int enable)
 {
 	u8 packet[VIDC_IFACEQ_VAR_SMALL_PKT_SIZE];
+	u32 hw_version;
 	struct hfi_cmd_sys_set_property_packet *pkt =
 		(struct hfi_cmd_sys_set_property_packet *) &packet;
-	create_pkt_cmd_sys_idle_indicator(pkt, enable);
-	if (venus_hfi_iface_cmdq_write(device, pkt))
-		return -ENOTEMPTY;
+	hw_version = venus_hfi_read_register(device, VIDC_WRAPPER_HW_VERSION);
+	dprintk(VIDC_DBG, "Venus HW version: 0x%x\n", hw_version);
+	if ((hw_version & 0xFFFF0000) != 0x10030000) {
+		create_pkt_cmd_sys_idle_indicator(pkt, enable);
+		if (venus_hfi_iface_cmdq_write(device, pkt))
+			return -ENOTEMPTY;
+	}
 	return 0;
 }
 
@@ -2788,6 +2804,8 @@
 	mutex_lock(&device->clk_pwr_lock);
 	if (device->clocks_enabled) {
 		for (i = VCODEC_CLK; i < VCODEC_MAX_CLKS; i++) {
+			if (i == VCODEC_OCMEM_CLK && !device->res->has_ocmem)
+				continue;
 			cl = &device->resources.clock[i];
 			clk_disable(cl->clk);
 		}
@@ -2859,8 +2877,9 @@
 		iommu_map = &iommu_group_set->iommu_maps[i];
 		iommu_map->group = iommu_group_find(iommu_map->name);
 		if (!iommu_map->group) {
-			dprintk(VIDC_ERR, "Failed to find group :%s\n",
+			dprintk(VIDC_DBG, "Failed to find group :%s\n",
 				iommu_map->name);
+			rc = -EPROBE_DEFER;
 			goto fail_group;
 		}
 		domain = iommu_group_get_iommudata(iommu_map->group);
@@ -2868,6 +2887,7 @@
 			dprintk(VIDC_ERR,
 				"Failed to get domain data for group %p",
 				iommu_map->group);
+			rc = -EINVAL;
 			goto fail_group;
 		}
 		iommu_map->domain = msm_find_domain_no(domain);
@@ -2875,6 +2895,7 @@
 			dprintk(VIDC_ERR,
 				"Failed to get domain index for domain %p",
 				domain);
+			rc = -EINVAL;
 			goto fail_group;
 		}
 	}
@@ -2888,7 +2909,7 @@
 		iommu_map->group = NULL;
 		iommu_map->domain = -1;
 	}
-	return -EINVAL;
+	return rc;
 }
 
 static void venus_hfi_deregister_iommu_domains(struct venus_hfi_device *device)
@@ -3175,7 +3196,10 @@
 
 	rc = venus_hfi_register_iommu_domains(device, res);
 	if (rc) {
-		dprintk(VIDC_ERR, "Failed to register iommu domains: %d\n", rc);
+		if (rc != -EPROBE_DEFER) {
+			dprintk(VIDC_ERR,
+				"Failed to register iommu domains: %d\n", rc);
+		}
 		goto err_register_iommu_domain;
 	}
 
@@ -3506,7 +3530,7 @@
 	struct venus_hfi_device *hdevice = NULL;
 	int rc = 0;
 
-	if (device_id || !res || !callback) {
+	if (!res || !callback) {
 		dprintk(VIDC_ERR, "Invalid Paramters");
 		return NULL;
 	}
@@ -3581,14 +3605,15 @@
 
 	rc = venus_hfi_init_resources(device, res);
 	if (rc) {
-		dprintk(VIDC_ERR, "Failed to init resources: %d\n", rc);
+		if (rc != -EPROBE_DEFER)
+			dprintk(VIDC_ERR, "Failed to init resources: %d\n", rc);
 		goto err_fail_init_res;
 	}
 	return device;
 
 err_fail_init_res:
 	venus_hfi_delete_device(device);
-	return NULL;
+	return ERR_PTR(rc);
 }
 
 void venus_hfi_delete_device(void *device)
@@ -3672,6 +3697,12 @@
 	}
 	hdev->hfi_device_data = venus_hfi_get_device(device_id, res, callback);
 
+	if (IS_ERR_OR_NULL(hdev->hfi_device_data)) {
+		rc = PTR_ERR(hdev->hfi_device_data);
+		rc = !rc ? -EINVAL : rc;
+		goto err_venus_hfi_init;
+	}
+
 	venus_init_hfi_callbacks(hdev);
 
 err_venus_hfi_init:
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi.c b/drivers/media/platform/msm/vidc/vidc_hfi.c
index 46293a6..ef0de37 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi.c
+++ b/drivers/media/platform/msm/vidc/vidc_hfi.c
@@ -44,7 +44,8 @@
 	}
 
 	if (rc) {
-		dprintk(VIDC_ERR, "%s device init failed rc = %d",
+		if (rc != -EPROBE_DEFER)
+			dprintk(VIDC_ERR, "%s device init failed rc = %d",
 				__func__, rc);
 		goto err_hfi_init;
 	}
@@ -53,7 +54,7 @@
 
 err_hfi_init:
 	kfree(hdev);
-	return NULL;
+	return ERR_PTR(rc);
 }
 
 void vidc_hfi_deinitialize(enum msm_vidc_hfi_type hfi_type,
diff --git a/drivers/media/platform/msm/wfd/enc-venus-subdev.c b/drivers/media/platform/msm/wfd/enc-venus-subdev.c
index 9cd199b..7e64714 100644
--- a/drivers/media/platform/msm/wfd/enc-venus-subdev.c
+++ b/drivers/media/platform/msm/wfd/enc-venus-subdev.c
@@ -377,7 +377,8 @@
 		goto vidc_wq_create_fail;
 	}
 
-	inst->vidc_context = msm_vidc_open(MSM_VIDC_CORE_0, MSM_VIDC_ENCODER);
+	inst->vidc_context = msm_vidc_open(MSM_VIDC_CORE_VENUS,
+				MSM_VIDC_ENCODER);
 	if (!inst->vidc_context) {
 		WFD_MSG_ERR("Failed to create vidc context\n");
 		rc = -ENXIO;
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index c5c0ce8..d242e3f 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -212,6 +212,10 @@
 	uint32_t len;
 };
 
+uint8_t *key_id_array[QSEECOM_KEY_ID_SIZE] = {
+	"Disk Encryption"
+};
+
 /* Function proto types */
 static int qsee_vote_for_clock(struct qseecom_dev_handle *, int32_t);
 static void qsee_disable_clock_vote(struct qseecom_dev_handle *, int32_t);
@@ -2459,25 +2463,20 @@
 
 static int __qseecom_generate_and_save_key(struct qseecom_dev_handle *data,
 			enum qseecom_key_management_usage_type usage,
-			uint8_t *key_id, uint32_t flags)
+			struct qseecom_key_generate_ireq *ireq)
 {
-	struct qseecom_key_generate_ireq ireq;
 	struct qseecom_command_scm_resp resp;
 	int ret;
 
-	if (usage != QSEOS_KM_USAGE_DISK_ENCRYPTION) {
+	if (usage < QSEOS_KM_USAGE_DISK_ENCRYPTION ||
+		usage >= QSEOS_KM_USAGE_MAX) {
 		pr_err("Error:: unsupported usage %d\n", usage);
 		return -EFAULT;
 	}
-
-	memcpy(ireq.key_id, key_id, QSEECOM_KEY_ID_SIZE);
-	ireq.flags = flags;
-	ireq.qsee_command_id = QSEOS_GENERATE_KEY;
-
 	__qseecom_enable_clk(CLK_QSEE);
 
 	ret = scm_call(SCM_SVC_TZSCHEDULER, 1,
-				&ireq, sizeof(struct qseecom_key_generate_ireq),
+				ireq, sizeof(struct qseecom_key_generate_ireq),
 				&resp, sizeof(resp));
 	if (ret) {
 		pr_err("scm call to generate key failed : %d\n", ret);
@@ -2515,9 +2514,8 @@
 
 static int __qseecom_delete_saved_key(struct qseecom_dev_handle *data,
 			enum qseecom_key_management_usage_type usage,
-			uint8_t *key_id, uint32_t flags)
+			struct qseecom_key_delete_ireq *ireq)
 {
-	struct qseecom_key_delete_ireq ireq;
 	struct qseecom_command_scm_resp resp;
 	int ret;
 
@@ -2526,14 +2524,10 @@
 		return -EFAULT;
 	}
 
-	memcpy(ireq.key_id, key_id, QSEECOM_KEY_ID_SIZE);
-	ireq.flags = flags;
-	ireq.qsee_command_id = QSEOS_DELETE_KEY;
-
 	__qseecom_enable_clk(CLK_QSEE);
 
 	ret = scm_call(SCM_SVC_TZSCHEDULER, 1,
-				&ireq, sizeof(struct qseecom_key_delete_ireq),
+				ireq, sizeof(struct qseecom_key_delete_ireq),
 				&resp, sizeof(struct qseecom_command_scm_resp));
 	if (ret) {
 		pr_err("scm call to delete key failed : %d\n", ret);
@@ -2563,13 +2557,13 @@
 
 static int __qseecom_set_clear_ce_key(struct qseecom_dev_handle *data,
 			enum qseecom_key_management_usage_type usage,
-			struct qseecom_set_key_parameter *set_key_para)
+			struct qseecom_key_select_ireq *ireq)
 {
-	struct qseecom_key_select_ireq ireq;
 	struct qseecom_command_scm_resp resp;
 	int ret;
 
-	if (usage != QSEOS_KM_USAGE_DISK_ENCRYPTION) {
+	if (usage < QSEOS_KM_USAGE_DISK_ENCRYPTION ||
+		usage >= QSEOS_KM_USAGE_MAX) {
 			pr_err("Error:: unsupported usage %d\n", usage);
 			return -EFAULT;
 	}
@@ -2578,24 +2572,8 @@
 	if (qseecom.qsee.instance != qseecom.ce_drv.instance)
 		__qseecom_enable_clk(CLK_CE_DRV);
 
-	memcpy(ireq.key_id, set_key_para->key_id, QSEECOM_KEY_ID_SIZE);
-	ireq.qsee_command_id = QSEOS_SET_KEY;
-	ireq.ce = set_key_para->ce_hw;
-	ireq.pipe = set_key_para->pipe;
-	ireq.flags = set_key_para->flags;
-
-	/* set both PIPE_ENC and PIPE_ENC_XTS*/
-	ireq.pipe_type = QSEOS_PIPE_ENC|QSEOS_PIPE_ENC_XTS;
-
-	if (set_key_para->set_clear_key_flag ==
-			QSEECOM_SET_CE_KEY_CMD)
-		memcpy((void *)ireq.hash, (void *)set_key_para->hash32,
-				QSEECOM_HASH_SIZE);
-	else
-		memset((void *)ireq.hash, 0, QSEECOM_HASH_SIZE);
-
 	ret = scm_call(SCM_SVC_TZSCHEDULER, 1,
-				&ireq, sizeof(struct qseecom_key_select_ireq),
+				ireq, sizeof(struct qseecom_key_select_ireq),
 				&resp, sizeof(struct qseecom_command_scm_resp));
 	if (ret) {
 		pr_err("scm call to set QSEOS_PIPE_ENC key failed : %d\n", ret);
@@ -2628,16 +2606,63 @@
 	return ret;
 }
 
+static int __qseecom_update_current_key_user_info(
+			struct qseecom_dev_handle *data,
+			enum qseecom_key_management_usage_type usage,
+			struct qseecom_key_userinfo_update_ireq *ireq)
+{
+	struct qseecom_command_scm_resp resp;
+	int ret;
+
+	if (usage < QSEOS_KM_USAGE_DISK_ENCRYPTION ||
+		usage >= QSEOS_KM_USAGE_MAX) {
+			pr_err("Error:: unsupported usage %d\n", usage);
+			return -EFAULT;
+	}
+
+	__qseecom_enable_clk(CLK_QSEE);
+
+	ret = scm_call(SCM_SVC_TZSCHEDULER, 1,
+		ireq, sizeof(struct qseecom_key_userinfo_update_ireq),
+		&resp, sizeof(struct qseecom_command_scm_resp));
+	if (ret) {
+		pr_err("scm call to update key userinfo failed : %d\n", ret);
+		__qseecom_disable_clk(CLK_QSEE);
+		if (qseecom.qsee.instance != qseecom.ce_drv.instance)
+			__qseecom_disable_clk(CLK_CE_DRV);
+		return ret;
+	}
+
+	switch (resp.result) {
+	case QSEOS_RESULT_SUCCESS:
+		break;
+	case QSEOS_RESULT_INCOMPLETE:
+		ret = __qseecom_process_incomplete_cmd(data, &resp);
+		if (ret)
+			pr_err("process_incomplete_cmd FAILED, resp.result %d\n",
+					resp.result);
+		break;
+	case QSEOS_RESULT_FAILURE:
+	default:
+		pr_err("Set key scm call failed resp.result %d\n", resp.result);
+		ret = -EINVAL;
+		break;
+	}
+
+	__qseecom_disable_clk(CLK_QSEE);
+	return ret;
+}
+
 static int qseecom_create_key(struct qseecom_dev_handle *data,
 			void __user *argp)
 {
 	uint32_t ce_hw = 0;
 	uint32_t pipe = 0;
-	uint8_t key_id[QSEECOM_KEY_ID_SIZE] = {0};
 	int ret = 0;
 	uint32_t flags = 0;
-	struct qseecom_set_key_parameter set_key_para;
 	struct qseecom_create_key_req create_key_req;
+	struct qseecom_key_generate_ireq generate_key_ireq;
+	struct qseecom_key_select_ireq set_key_ireq;
 
 	ret = copy_from_user(&create_key_req, argp, sizeof(create_key_req));
 	if (ret) {
@@ -2645,7 +2670,8 @@
 		return ret;
 	}
 
-	if (create_key_req.usage != QSEOS_KM_USAGE_DISK_ENCRYPTION) {
+	if (create_key_req.usage < QSEOS_KM_USAGE_DISK_ENCRYPTION ||
+		create_key_req.usage >= QSEOS_KM_USAGE_MAX) {
 		pr_err("Error:: unsupported usage %d\n", create_key_req.usage);
 		return -EFAULT;
 	}
@@ -2656,23 +2682,40 @@
 		return -EINVAL;
 	}
 
+	generate_key_ireq.flags = flags;
+	generate_key_ireq.qsee_command_id = QSEOS_GENERATE_KEY;
+	memset((void *)generate_key_ireq.key_id, 0, QSEECOM_KEY_ID_SIZE);
+	memset((void *)generate_key_ireq.hash32, 0, QSEECOM_HASH_SIZE);
+	memcpy((void *)generate_key_ireq.key_id,
+			(void *)key_id_array[create_key_req.usage - 1],
+			QSEECOM_KEY_ID_SIZE);
+	memcpy((void *)generate_key_ireq.hash32,
+			(void *)create_key_req.hash32, QSEECOM_HASH_SIZE);
+
 	ret = __qseecom_generate_and_save_key(data, create_key_req.usage,
-								key_id, flags);
+					&generate_key_ireq);
 	if (ret) {
 		pr_err("Failed to generate key on storage: %d\n", ret);
 		return -EFAULT;
 	}
 
-	set_key_para.ce_hw = ce_hw;
-	set_key_para.pipe = pipe;
-	memcpy(set_key_para.key_id, key_id, QSEECOM_KEY_ID_SIZE);
-	set_key_para.flags = flags;
-	set_key_para.set_clear_key_flag = QSEECOM_SET_CE_KEY_CMD;
-	memcpy((void *)set_key_para.hash32, (void *)create_key_req.hash32,
+	set_key_ireq.qsee_command_id = QSEOS_SET_KEY;
+	set_key_ireq.ce = ce_hw;
+	set_key_ireq.pipe = pipe;
+	set_key_ireq.flags = flags;
+
+	/* set both PIPE_ENC and PIPE_ENC_XTS*/
+	set_key_ireq.pipe_type = QSEOS_PIPE_ENC|QSEOS_PIPE_ENC_XTS;
+	memset((void *)set_key_ireq.key_id, 0, QSEECOM_KEY_ID_SIZE);
+	memset((void *)set_key_ireq.hash32, 0, QSEECOM_HASH_SIZE);
+	memcpy((void *)set_key_ireq.key_id,
+			(void *)key_id_array[create_key_req.usage - 1],
+				QSEECOM_KEY_ID_SIZE);
+	memcpy((void *)set_key_ireq.hash32, (void *)create_key_req.hash32,
 				QSEECOM_HASH_SIZE);
 
 	ret = __qseecom_set_clear_ce_key(data, create_key_req.usage,
-								&set_key_para);
+								&set_key_ireq);
 	if (ret) {
 		pr_err("Failed to create key: pipe %d, ce %d: %d\n",
 			pipe, ce_hw, ret);
@@ -2687,12 +2730,12 @@
 {
 	uint32_t ce_hw = 0;
 	uint32_t pipe = 0;
-	uint8_t key_id[QSEECOM_KEY_ID_SIZE] = {0};
 	int ret = 0;
 	uint32_t flags = 0;
 	int i;
 	struct qseecom_wipe_key_req wipe_key_req;
-	struct qseecom_set_key_parameter clear_key_para;
+	struct qseecom_key_delete_ireq delete_key_ireq;
+	struct qseecom_key_select_ireq clear_key_ireq;
 
 	ret = copy_from_user(&wipe_key_req, argp, sizeof(wipe_key_req));
 	if (ret) {
@@ -2700,7 +2743,8 @@
 		return ret;
 	}
 
-	if (wipe_key_req.usage != QSEOS_KM_USAGE_DISK_ENCRYPTION) {
+	if (wipe_key_req.usage < QSEOS_KM_USAGE_DISK_ENCRYPTION ||
+		wipe_key_req.usage >= QSEOS_KM_USAGE_MAX) {
 		pr_err("Error:: unsupported usage %d\n", wipe_key_req.usage);
 		return -EFAULT;
 	}
@@ -2711,22 +2755,32 @@
 		return -EINVAL;
 	}
 
-	ret = __qseecom_delete_saved_key(data, wipe_key_req.usage, key_id,
-									flags);
+	delete_key_ireq.flags = flags;
+	delete_key_ireq.qsee_command_id = QSEOS_DELETE_KEY;
+	memset((void *)delete_key_ireq.key_id, 0, QSEECOM_KEY_ID_SIZE);
+	memcpy((void *)delete_key_ireq.key_id,
+			(void *)key_id_array[wipe_key_req.usage - 1],
+			QSEECOM_KEY_ID_SIZE);
+	memset((void *)delete_key_ireq.hash32, 0, QSEECOM_HASH_SIZE);
+
+	ret = __qseecom_delete_saved_key(data, wipe_key_req.usage,
+					&delete_key_ireq);
 	if (ret) {
 		pr_err("Failed to delete key from ssd storage: %d\n", ret);
 		return -EFAULT;
 	}
 
-	/* an invalid key_id 0xff is used to indicate clear key*/
+	clear_key_ireq.qsee_command_id = QSEOS_SET_KEY;
+	clear_key_ireq.ce = ce_hw;
+	clear_key_ireq.pipe = pipe;
+	clear_key_ireq.flags = flags;
+	clear_key_ireq.pipe_type = QSEOS_PIPE_ENC|QSEOS_PIPE_ENC_XTS;
 	for (i = 0; i < QSEECOM_KEY_ID_SIZE; i++)
-		clear_key_para.key_id[i] = 0xff;
-	clear_key_para.ce_hw = ce_hw;
-	clear_key_para.pipe = pipe;
-	clear_key_para.flags = flags;
-	clear_key_para.set_clear_key_flag = QSEECOM_CLEAR_CE_KEY_CMD;
+			clear_key_ireq.key_id[i] = 0xff;
+	memset((void *)clear_key_ireq.hash32, 0, QSEECOM_HASH_SIZE);
+
 	ret = __qseecom_set_clear_ce_key(data, wipe_key_req.usage,
-							&clear_key_para);
+							&clear_key_ireq);
 	if (ret) {
 		pr_err("Failed to wipe key: pipe %d, ce %d: %d\n",
 			pipe, ce_hw, ret);
@@ -2736,6 +2790,48 @@
 	return ret;
 }
 
+static int qseecom_update_key_user_info(struct qseecom_dev_handle *data,
+			void __user *argp)
+{
+	int ret = 0;
+	uint32_t flags = 0;
+	struct qseecom_update_key_userinfo_req update_key_req;
+	struct qseecom_key_userinfo_update_ireq ireq;
+
+	ret = copy_from_user(&update_key_req, argp, sizeof(update_key_req));
+	if (ret) {
+		pr_err("copy_from_user failed\n");
+		return ret;
+	}
+
+	if (update_key_req.usage < QSEOS_KM_USAGE_DISK_ENCRYPTION ||
+		update_key_req.usage >= QSEOS_KM_USAGE_MAX) {
+		pr_err("Error:: unsupported usage %d\n", update_key_req.usage);
+		return -EFAULT;
+	}
+
+	ireq.qsee_command_id = QSEOS_UPDATE_KEY_USERINFO;
+	ireq.flags = flags;
+	memset(ireq.key_id, 0, QSEECOM_KEY_ID_SIZE);
+	memset((void *)ireq.current_hash32, 0, QSEECOM_HASH_SIZE);
+	memset((void *)ireq.new_hash32, 0, QSEECOM_HASH_SIZE);
+	memcpy(ireq.key_id, key_id_array[update_key_req.usage - 1],
+						QSEECOM_KEY_ID_SIZE);
+	memcpy((void *)ireq.current_hash32,
+		(void *)update_key_req.current_hash32, QSEECOM_HASH_SIZE);
+	memcpy((void *)ireq.new_hash32,
+		(void *)update_key_req.new_hash32, QSEECOM_HASH_SIZE);
+
+	ret = __qseecom_update_current_key_user_info(data, update_key_req.usage,
+						&ireq);
+	if (ret) {
+		pr_err("Failed to update key info: %d\n", ret);
+		return -EFAULT;
+	}
+	return ret;
+
+}
+
 static int qseecom_is_es_activated(void __user *argp)
 {
 	struct qseecom_is_es_activated_req req;
@@ -3115,14 +3211,12 @@
 			return -EINVAL;
 		}
 		data->released = true;
-		mutex_lock(&app_access_lock);
 		atomic_inc(&data->ioctl_count);
 		ret = qseecom_create_key(data, argp);
 		if (ret)
 			pr_err("failed to create encryption key: %d\n", ret);
 
 		atomic_dec(&data->ioctl_count);
-		mutex_unlock(&app_access_lock);
 		break;
 	}
 	case QSEECOM_IOCTL_WIPE_KEY_REQ: {
@@ -3138,13 +3232,31 @@
 			return -EINVAL;
 		}
 		data->released = true;
-		mutex_lock(&app_access_lock);
 		atomic_inc(&data->ioctl_count);
 		ret = qseecom_wipe_key(data, argp);
 		if (ret)
 			pr_err("failed to wipe encryption key: %d\n", ret);
 		atomic_dec(&data->ioctl_count);
-		mutex_unlock(&app_access_lock);
+		break;
+	}
+	case QSEECOM_IOCTL_UPDATE_KEY_USER_INFO_REQ: {
+		if (data->type != QSEECOM_GENERIC) {
+			pr_err("update key req: invalid handle (%d)\n",
+								data->type);
+			ret = -EINVAL;
+			break;
+		}
+		if (qseecom.qsee_version < QSEE_VERSION_05) {
+			pr_err("Update Key feature unsupported in qsee ver %u\n",
+				qseecom.qsee_version);
+			return -EINVAL;
+		}
+		data->released = true;
+		atomic_inc(&data->ioctl_count);
+		ret = qseecom_update_key_user_info(data, argp);
+		if (ret)
+			pr_err("failed to update key user info: %d\n", ret);
+		atomic_dec(&data->ioctl_count);
 		break;
 	}
 	case QSEECOM_IOCTL_SAVE_PARTITION_HASH_REQ: {
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index f288231..94a13f9 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -895,7 +895,9 @@
 			mmc_post_req(host, host->areq->mrq, 0);
 			host->areq = NULL;
 			if (areq) {
-				if (!(areq->cmd_flags & REQ_URGENT)) {
+				if (!(areq->cmd_flags & (REQ_URGENT
+							 | REQ_FUA
+							 | REQ_FLUSH))) {
 					areq->reinsert_req(areq);
 					mmc_post_req(host, areq->mrq, 0);
 				} else {
@@ -3146,6 +3148,7 @@
 		return;
 
 	mmc_bus_get(host);
+	mmc_rpm_hold(host, &host->class_dev);
 
 	/*
 	 * if there is a _removable_ card registered, check whether it is
@@ -3178,10 +3181,13 @@
 
 	/* if there still is a card present, stop here */
 	if (host->bus_ops != NULL) {
+		mmc_rpm_release(host, &host->class_dev);
 		mmc_bus_put(host);
 		goto out;
 	}
 
+	mmc_rpm_release(host, &host->class_dev);
+
 	/*
 	 * Only we can add a new handler, so it's safe to
 	 * release the lock here.
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 24b7d04..32f5220 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1492,6 +1492,7 @@
 	struct sdhci_host *host;
 	bool present;
 	unsigned long flags;
+	u32 tuning_opcode;
 
 	host = mmc_priv(mmc);
 
@@ -1546,14 +1547,25 @@
 		 * is no on-going data transfer. If so, we need to execute
 		 * tuning procedure before sending command.
 		 */
-		if ((host->flags & SDHCI_NEEDS_RETUNING) &&
+		if ((mrq->cmd->opcode != MMC_SEND_TUNING_BLOCK) &&
+		    (mrq->cmd->opcode != MMC_SEND_TUNING_BLOCK_HS400) &&
+		    (mrq->cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200) &&
+		    (host->flags & SDHCI_NEEDS_RETUNING) &&
 		    !(present_state & (SDHCI_DOING_WRITE | SDHCI_DOING_READ))) {
-			spin_unlock_irqrestore(&host->lock, flags);
-			sdhci_execute_tuning(mmc, mrq->cmd->opcode);
-			spin_lock_irqsave(&host->lock, flags);
+			if (mmc->card) {
+				/* eMMC uses cmd21 but sd and sdio use cmd19 */
+				tuning_opcode =
+					mmc->card->type == MMC_TYPE_MMC ?
+					MMC_SEND_TUNING_BLOCK_HS200 :
+					MMC_SEND_TUNING_BLOCK;
+				host->mrq = NULL;
+				spin_unlock_irqrestore(&host->lock, flags);
+				sdhci_execute_tuning(mmc, tuning_opcode);
+				spin_lock_irqsave(&host->lock, flags);
 
-			/* Restore original mmc_request structure */
-			host->mrq = mrq;
+				/* Restore original mmc_request structure */
+				host->mrq = mrq;
+			}
 		}
 
 		if (mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23))
@@ -2521,6 +2533,8 @@
 	}
 
 	if (host->cmd->error) {
+		if (host->cmd->error == -EILSEQ)
+			host->flags |= SDHCI_NEEDS_RETUNING;
 		tasklet_schedule(&host->finish_tasklet);
 		return;
 	}
@@ -2649,8 +2663,11 @@
 							    SDHCI_COMMAND));
 			if ((command != MMC_SEND_TUNING_BLOCK_HS400) &&
 			    (command != MMC_SEND_TUNING_BLOCK_HS200) &&
-			    (command != MMC_SEND_TUNING_BLOCK))
+			    (command != MMC_SEND_TUNING_BLOCK)) {
 				pr_msg = true;
+				if (intmask & SDHCI_INT_DATA_CRC)
+					host->flags |= SDHCI_NEEDS_RETUNING;
+			}
 		} else {
 			pr_msg = true;
 		}
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index 8e695c3..11800ac 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -148,6 +148,9 @@
 #define MSM_PRONTO_TXP_PHY_ABORT        0xfb080488
 #define MSM_PRONTO_BRDG_ERR_SRC         0xfb080fb0
 
+#define MSM_PRONTO_ALARMS_TXCTL         0xfb0120a8
+#define MSM_PRONTO_ALARMS_TACTL         0xfb012448
+
 #define WCNSS_DEF_WLAN_RX_BUFF_COUNT		1024
 #define WCNSS_VBATT_THRESHOLD		3500000
 #define WCNSS_VBATT_GUARD		200
@@ -181,6 +184,8 @@
 #define	WCNSS_BUILD_VER_REQ           (WCNSS_CTRL_MSG_START + 9)
 #define	WCNSS_BUILD_VER_RSP           (WCNSS_CTRL_MSG_START + 10)
 
+/* max 20mhz channel count */
+#define WCNSS_MAX_CH_NUM			45
 
 #define VALID_VERSION(version) \
 	((strncmp(version, "INVALID", WCNSS_VERSION_LEN)) ? 1 : 0)
@@ -356,6 +361,8 @@
 	void __iomem *wlan_tx_status;
 	void __iomem *wlan_tx_phy_aborts;
 	void __iomem *wlan_brdg_err_source;
+	void __iomem *alarms_txctl;
+	void __iomem *alarms_tactl;
 	void __iomem *fiq_reg;
 	int	nv_downloaded;
 	unsigned char *fw_cal_data;
@@ -377,6 +384,8 @@
 	struct qpnp_adc_tm_btm_param vbat_monitor_params;
 	struct qpnp_adc_tm_chip *adc_tm_dev;
 	struct mutex vbat_monitor_mutex;
+	u16 unsafe_ch_count;
+	u16 unsafe_ch_list[WCNSS_MAX_CH_NUM];
 } *penv = NULL;
 
 static ssize_t wcnss_serial_number_show(struct device *dev,
@@ -682,6 +691,12 @@
 
 	reg = readl_relaxed(penv->wlan_tx_status);
 	pr_info_ratelimited("%s: WLAN_TX_STATUS %08x\n", __func__, reg);
+
+	reg = readl_relaxed(penv->alarms_txctl);
+	pr_err("ALARMS_TXCTL %08x\n", reg);
+
+	reg = readl_relaxed(penv->alarms_tactl);
+	pr_err("ALARMS_TACTL %08x\n", reg);
 }
 EXPORT_SYMBOL(wcnss_pronto_log_debug_regs);
 
@@ -1177,6 +1192,35 @@
 }
 EXPORT_SYMBOL(wcnss_get_wlan_rx_buff_count);
 
+int wcnss_set_wlan_unsafe_channel(u16 *unsafe_ch_list, u16 ch_count)
+{
+	if (penv && unsafe_ch_list &&
+		(ch_count <= WCNSS_MAX_CH_NUM)) {
+		memcpy((char *)penv->unsafe_ch_list,
+			(char *)unsafe_ch_list, ch_count * sizeof(u16));
+		penv->unsafe_ch_count = ch_count;
+		return 0;
+	} else
+		return -ENODEV;
+}
+EXPORT_SYMBOL(wcnss_set_wlan_unsafe_channel);
+
+int wcnss_get_wlan_unsafe_channel(u16 *unsafe_ch_list, u16 buffer_size,
+					u16 *ch_count)
+{
+	if (penv) {
+		if (buffer_size < penv->unsafe_ch_count * sizeof(u16))
+			return -ENODEV;
+		memcpy((char *)unsafe_ch_list,
+			(char *)penv->unsafe_ch_list,
+			penv->unsafe_ch_count * sizeof(u16));
+		*ch_count = penv->unsafe_ch_count;
+		return 0;
+	} else
+		return -ENODEV;
+}
+EXPORT_SYMBOL(wcnss_get_wlan_unsafe_channel);
+
 static int wcnss_smd_tx(void *data, int len)
 {
 	int ret = 0;
@@ -2085,6 +2129,18 @@
 			pr_err("%s: ioremap wlan TX STATUS failed\n", __func__);
 			goto fail_ioremap9;
 		}
+		penv->alarms_txctl = ioremap(MSM_PRONTO_ALARMS_TXCTL, SZ_8);
+		if (!penv->alarms_txctl) {
+			ret = -ENOMEM;
+			pr_err("%s: ioremap alarms TXCTL failed\n", __func__);
+			goto fail_ioremap10;
+		}
+		penv->alarms_tactl = ioremap(MSM_PRONTO_ALARMS_TACTL, SZ_8);
+		if (!penv->alarms_tactl) {
+			ret = -ENOMEM;
+			pr_err("%s: ioremap alarms TACTL failed\n", __func__);
+			goto fail_ioremap11;
+		}
 	}
 	penv->adc_tm_dev = qpnp_get_adc_tm(&penv->pdev->dev, "wcnss");
 	if (IS_ERR(penv->adc_tm_dev)) {
@@ -2110,6 +2166,12 @@
 fail_pil:
 	if (penv->riva_ccu_base)
 		iounmap(penv->riva_ccu_base);
+	if (penv->alarms_tactl)
+		iounmap(penv->alarms_tactl);
+fail_ioremap11:
+	if (penv->alarms_txctl)
+		iounmap(penv->alarms_txctl);
+fail_ioremap10:
 	if (penv->wlan_tx_status)
 		iounmap(penv->wlan_tx_status);
 fail_ioremap9:
diff --git a/drivers/nfc/nfc-nci.c b/drivers/nfc/nfc-nci.c
index 99e17a6..b808f97 100644
--- a/drivers/nfc/nfc-nci.c
+++ b/drivers/nfc/nfc-nci.c
@@ -33,7 +33,7 @@
 	unsigned int dis_gpio;
 	unsigned int ven_gpio;
 	unsigned int reg;
-	const char *clk_src;
+	const char *clk_src_name;
 	unsigned int clk_src_gpio;
 };
 
@@ -44,15 +44,19 @@
 
 MODULE_DEVICE_TABLE(of, msm_match_table);
 
-#define MAX_BUFFER_SIZE		(780)
+#define MAX_BUFFER_SIZE			(780)
+#define PACKET_MAX_LENGTH			(258)
 /* Read data */
 #define PACKET_HEADER_SIZE_NCI	(4)
-#define PACKET_TYPE_NCI		(16)
-#define MAX_PACKET_SIZE		(PACKET_HEADER_SIZE_NCI + 255)
-#define MAX_QCA_REG		(116)
+#define PACKET_TYPE_NCI			(16)
+#define MAX_PACKET_SIZE			(PACKET_HEADER_SIZE_NCI + 255)
+#define MAX_QCA_REG				(116)
+/* will timeout in approx. 100ms as 10us steps */
+#define NTF_TIMEOUT				(10000)
+#define	CORE_RESET_RSP_GID		(0x60)
+#define	CORE_RESET_OID			(0x00)
+#define CORE_RST_NTF_LENGTH			(0x02)
 
-static int nfc_i2c_write(struct i2c_client *client, u8 *buf, int len);
-static int nfcc_initialise(struct i2c_client *client, unsigned short curr_addr);
 
 struct qca199x_dev {
 	wait_queue_head_t read_wq;
@@ -63,11 +67,23 @@
 	unsigned int dis_gpio;
 	unsigned int ven_gpio;
 	bool irq_enabled;
+	bool sent_first_nci_write;
 	spinlock_t irq_enabled_lock;
 	unsigned int count_irq;
 	enum	nfcc_state	state;
+	unsigned int clk_src_gpio;
+	const char *clk_src_name;
+	struct clk *s_clk;
+	bool clk_run;
 };
 
+static int nfc_i2c_write(struct i2c_client *client, u8 *buf, int len);
+static int nfcc_initialise(struct i2c_client *client, unsigned short curr_addr);
+static int qca199x_clock_select(struct qca199x_dev *qca199x_dev);
+static int qca199x_clock_deselect(struct qca199x_dev *qca199x_dev);
+
+
+
 /*
  * To allow filtering of nfc logging from user. This is set via
  * IOCTL NFC_KERNEL_LOGGING_MODE.
@@ -205,23 +221,33 @@
 	/* NORMAL NCI Behaviour */
 	/* Read the header */
 	ret = i2c_master_recv(qca199x_dev->client, len, PAYLOAD_HEADER_LENGTH);
+	/*
+		We ignore all packets of length PAYLOAD_HEADER_LENGTH
+		or less (i.e <=3). In this case return a total length
+		of ZERO. So ALL PACKETS MUST HAVE A PAYLOAD.
+		If ret < 0 then this is an error code.
+	*/
 	if (ret != PAYLOAD_HEADER_LENGTH) {
-		total = 0;
+		if (ret < 0)
+			total = ret;
+		else
+			total = 0;
 		goto err;
 	}
 	length = len[PAYLOAD_HEADER_LENGTH - 1];
-	if (length == 0)
-		total = 0;
+	if (length == 0) {
+		ret = 0;
+		total = ret;
+		goto err;
+	}
 	/** make sure full packet fits in the buffer **/
 	if ((length > 0) && ((length + PAYLOAD_HEADER_LENGTH) <= count)) {
 		/* Read the packet */
 		ret = i2c_master_recv(qca199x_dev->client, tmp, (length +
 			PAYLOAD_HEADER_LENGTH));
-		if (ret < 0) {
-			total = 0;
+		total = ret;
+		if (ret < 0)
 			goto err;
-		}
-		total = (length + PAYLOAD_HEADER_LENGTH);
 	}
 
 	if (total > 0) {
@@ -232,14 +258,57 @@
 			total = -EFAULT;
 		}
 	}
-	mutex_unlock(&qca199x_dev->read_mutex);
 err:
-	if (ret < 0)
 		mutex_unlock(&qca199x_dev->read_mutex);
 done:
 	return total;
 }
 
+/*
+	Local routine to read from nfcc buffer. This is called to clear any
+	pending receive messages in the nfcc's read buffer, which may be there
+	following a POR. In this way, the upper layers (Device Transport) will
+	associate the next rsp/ntf nci message with the next nci command to the
+	nfcc. Otherwise, the DT may interpret a ntf from the nfcc as being from
+	the nci core reset command when in fact it was already present in the
+	nfcc read buffer following a POR.
+*/
+
+int nfcc_read_buff_svc(struct qca199x_dev *qca199x_dev)
+{
+	unsigned char tmp[PACKET_MAX_LENGTH];
+	unsigned char len[PAYLOAD_HEADER_LENGTH];
+	int total, length, ret;
+	total = 0;
+	length = 0;
+	mutex_lock(&qca199x_dev->read_mutex);
+	memset(tmp, 0, sizeof(tmp));
+	memset(len, 0, sizeof(len));
+
+	/* Read the header */
+	ret = i2c_master_recv(qca199x_dev->client, len, PAYLOAD_HEADER_LENGTH);
+	if (ret < PAYLOAD_HEADER_LENGTH) {
+		total = ret;
+		goto leave;
+	}
+	length = len[PAYLOAD_HEADER_LENGTH - 1];
+	if (length == 0) {
+		ret = PAYLOAD_HEADER_LENGTH;
+		total = ret;
+		goto leave;
+	}
+	/** make sure full packet fits in the buffer **/
+	if ((length > 0) && ((length + PAYLOAD_HEADER_LENGTH) <= PACKET_MAX_LENGTH)) {
+		/* Read the packet */
+		ret = i2c_master_recv(qca199x_dev->client, tmp, (length +
+			PAYLOAD_HEADER_LENGTH));
+		total = ret;
+	}
+leave:
+	mutex_unlock(&qca199x_dev->read_mutex);
+	return total;
+}
+
 static ssize_t nfc_write(struct file *filp, const char __user *buf,
 				size_t count, loff_t *offset)
 {
@@ -247,6 +316,7 @@
 	char tmp[MAX_BUFFER_SIZE];
 	int ret = 0;
 	enum ehandler_mode dmode;
+	int nfcc_buffer = 0;
 
 	if (count > MAX_BUFFER_SIZE) {
 		dev_err(&qca199x_dev->client->dev, "out of memory\n");
@@ -257,10 +327,28 @@
 			"nfc-nci write: failed to copy from user space\n");
 		return -EFAULT;
 	}
+	/*
+		A catch for when the DT is sending the initial NCI write
+		following a hardware POR. In this case we should clear any
+		pending messages in nfcc buffer and open the interrupt gate
+		for new messages coming from the nfcc.
+	*/
+	if ((qca199x_dev->sent_first_nci_write == false) &&
+		 (qca199x_dev->irq_enabled == false)) {
+		/* check rsp/ntf from nfcc read-side buffer */
+		nfcc_buffer = nfcc_read_buff_svc(qca199x_dev);
+		/* There has been an error while reading from nfcc */
+		if (nfcc_buffer < 0) {
+			dev_err(&qca199x_dev->client->dev,
+				"nfc-nci write: error while servicing nfcc read buffer\n");
+		}
+		qca199x_dev->sent_first_nci_write = true;
+		qca199x_enable_irq(qca199x_dev);
+	}
 	mutex_lock(&qca199x_dev->read_mutex);
 	dmode = device_mode.handle_flavour;
 	/* FTM-DIRECT-I2C RD/WR MODE */
-	/* This is a special FTM-i2c mode case,where tester is not using NCI */
+	/* This is a special FTM-i2c mode case, where tester is not using NCI */
 	if ((dmode == UNSOLICITED_FTM_RAW_MODE) ||
 		(dmode == SOLICITED_FTM_RAW_MODE)) {
 		/* Read From Register */
@@ -378,6 +466,9 @@
 	struct qca199x_dev *qca199x_dev = filp->private_data;
 
 	if (arg == 0) {
+		r = qca199x_clock_select(qca199x_dev);
+		if (r < 0)
+			goto err_req;
 		gpio_set_value(qca199x_dev->dis_gpio, 0);
 		r = gpio_direction_output(qca199x_dev->dis_gpio, 1);
 		if (r) {
@@ -389,6 +480,23 @@
 		gpio_set_value(qca199x_dev->dis_gpio, 0);
 		msleep(20);
 	} else if (arg == 1) {
+		/*
+			We are attempting a hardware reset so let us disable
+			interrupts to avoid spurious notifications to upper
+			layers.
+		*/
+		qca199x_disable_irq(qca199x_dev);
+		/* Deselection of clock */
+		r = qca199x_clock_deselect(qca199x_dev);
+		if (r < 0)
+			goto err_req;
+		/*
+			Also, set flag for initial NCI write following resetas
+			may wish to do some house keeping. Ensure no pending
+			messages in NFCC buffers which may be wrongly
+			construed as response to initial message
+		*/
+		qca199x_dev->sent_first_nci_write = false;
 		gpio_set_value(qca199x_dev->dis_gpio, 0);
 		r = gpio_direction_output(qca199x_dev->dis_gpio, 1);
 		if (r) {
@@ -402,10 +510,12 @@
 	} else if (arg == 2) {
 		mutex_lock(&qca199x_dev->read_mutex);
 		r = nfcc_initialise(qca199x_dev->client, 0xE);
+		/* Also reset first NCI write */
+		qca199x_dev->sent_first_nci_write = false;
 		mutex_unlock(&qca199x_dev->read_mutex);
 		if (r) {
 			dev_err(&qca199x_dev->client->dev,
-					"nfc-nci probe: request nfcc initialise failed\n");
+				"nfc_ioctl_power_states: request nfcc initialise failed\n");
 			goto err_req;
 		}
 	} else if (arg == 3) {
@@ -536,8 +646,6 @@
 	return raw_chip_version;
 }
 
-
-
 /*
  * Inside nfc_ioctl_kernel_logging
  *
@@ -664,72 +772,211 @@
 	unsigned char raw_1P8_PAD_CFG_CLK_REQ[]	= {0xA5, 0x1};
 	unsigned char raw_1P8_PAD_CFG_PWR_REQ[]	= {0xA7, 0x1};
 	unsigned char buf = 0;
+	bool core_reset_completed = false;
+	unsigned char rsp[6];
+	int time_taken = 0;
+	int ret = 0;
 
 	client->addr = curr_addr;
 	r = i2c_master_send(client, &buf, 1);
+	if (r < 0)
+		goto err_init;
+
 	buf = 0;
 	r = i2c_master_recv(client, &buf, 1);
+	if (r < 0)
+		goto err_init;
+
 	if (0x10 != (0x10 & buf)) {
 		RAW(s73, 0x02);
 
 		r = nfc_i2c_write(client, &raw_s73[0], sizeof(raw_s73));
+		if (r < 0)
+			goto err_init;
+
 		usleep(1000);
 		RAW(1p8_CONTROL_011, XTAL_CLOCK | 0x01);
 
 		r = nfc_i2c_write(client, &raw_1p8_CONTROL_011[0],
 						sizeof(raw_1p8_CONTROL_011));
+		if (r < 0)
+			goto err_init;
+
 		usleep(1000);
 		RAW(1P8_CONTROL_010, (0x8));
 		r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
 						sizeof(raw_1P8_CONTROL_010));
+		if (r < 0)
+			goto err_init;
 
 		usleep(10000);  /* 10ms wait */
 		RAW(1P8_CONTROL_010, (0xC));
 		r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
 					sizeof(raw_1P8_CONTROL_010));
+		if (r < 0)
+			goto err_init;
+
 		usleep(100);  /* 100uS wait */
 		RAW(1P8_X0_0B0, (FREQ_SEL_19));
 		r = nfc_i2c_write(client, &raw_1P8_X0_0B0[0],
 						sizeof(raw_1P8_X0_0B0));
+		if (r < 0)
+			goto err_init;
+
 		usleep(1000);
 
 		/* PWR_EN = 1 */
 		RAW(1P8_CONTROL_010, (0xd));
 		r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
 						sizeof(raw_1P8_CONTROL_010));
+		if (r < 0)
+			goto err_init;
+
+
 		usleep(20000);  /* 20ms wait */
 		/* LS_EN = 1 */
 		RAW(1P8_CONTROL_010, 0xF);
 		r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
 						sizeof(raw_1P8_CONTROL_010));
+		if (r < 0)
+			goto err_init;
+
 		usleep(20000);  /* 20ms wait */
 
 		/* Enable the PMIC clock */
 		RAW(1P8_PAD_CFG_CLK_REQ, (0x1));
 		r = nfc_i2c_write(client, &raw_1P8_PAD_CFG_CLK_REQ[0],
 					  sizeof(raw_1P8_PAD_CFG_CLK_REQ));
+		if (r < 0)
+			goto err_init;
+
 		usleep(1000);
 
 		RAW(1P8_PAD_CFG_PWR_REQ, (0x1));
 		r = nfc_i2c_write(client, &raw_1P8_PAD_CFG_PWR_REQ[0],
 					  sizeof(raw_1P8_PAD_CFG_PWR_REQ));
+		if (r < 0)
+			goto err_init;
+
 		usleep(1000);
 
 		RAW(slave2, 0x10);
 		r = nfc_i2c_write(client, &raw_slave2[0], sizeof(raw_slave2));
+		if (r < 0)
+			goto err_init;
+
 		usleep(1000);
 
 		RAW(slave1, NCI_I2C_SLAVE);
 		r = nfc_i2c_write(client, &raw_slave1[0], sizeof(raw_slave1));
+		if (r < 0)
+			goto err_init;
+
 		usleep(1000);
 
 		/* QCA199x NFCC CPU should now boot... */
 		r = i2c_master_recv(client, &raw_slave1_rd, 1);
 		/* Talk on NCI slave address NCI_I2C_SLAVE 0x2C*/
 		client->addr = NCI_I2C_SLAVE;
+
+		/*
+			Start with small delay and then we will poll until we
+			get a core reset notification - This is time for chip
+			& NFCC controller to come-up.
+		*/
+		usleep(1000); /* 1 ms */
+
+		do {
+			ret = i2c_master_recv(client, rsp, 5);
+			/* Found core reset notification */
+			if (((rsp[0] == CORE_RESET_RSP_GID) &&
+				(rsp[1] == CORE_RESET_OID) &&
+				(rsp[2] == CORE_RST_NTF_LENGTH))
+					|| time_taken == NTF_TIMEOUT) {
+				core_reset_completed = true;
+			}
+			usleep(10);  /* 10us sleep before retry */
+			time_taken++;
+		} while (!core_reset_completed);
 		r = 0;
 	} else {
-		r = 1;
+		goto err_init;
+	}
+	return r;
+err_init:
+	r = 1;
+	dev_err(&client->dev,
+		"nfc-nci nfcc_initialise: failed. Check Hardware\n");
+	return r;
+}
+/*
+	Routine to Select clocks
+*/
+static int qca199x_clock_select(struct qca199x_dev *qca199x_dev)
+{
+	int r = 0;
+
+	if (!strcmp(qca199x_dev->clk_src_name, "BBCLK2")) {
+		qca199x_dev->s_clk  =
+			clk_get(&qca199x_dev->client->dev, "ref_clk");
+		if (qca199x_dev->s_clk == NULL)
+			goto err_invalid_dis_gpio;
+	} else if (!strcmp(qca199x_dev->clk_src_name, "RFCLK3")) {
+		qca199x_dev->s_clk  =
+			clk_get(&qca199x_dev->client->dev, "ref_clk_rf");
+		if (qca199x_dev->s_clk == NULL)
+			goto err_invalid_dis_gpio;
+	} else if (!strcmp(qca199x_dev->clk_src_name, "GPCLK")) {
+		if (gpio_is_valid(qca199x_dev->clk_src_gpio)) {
+			qca199x_dev->s_clk  =
+				clk_get(&qca199x_dev->client->dev, "core_clk");
+			if (qca199x_dev->s_clk == NULL)
+				goto err_invalid_dis_gpio;
+		} else {
+			goto err_invalid_dis_gpio;
+		}
+	} else if (!strcmp(qca199x_dev->clk_src_name, "GPCLK2")) {
+		if (gpio_is_valid(qca199x_dev->clk_src_gpio)) {
+			qca199x_dev->s_clk  =
+				clk_get(&qca199x_dev->client->dev, "core_clk_pvt");
+			if (qca199x_dev->s_clk == NULL)
+				goto err_invalid_dis_gpio;
+		} else {
+			goto err_invalid_dis_gpio;
+		}
+	} else {
+		qca199x_dev->s_clk = NULL;
+		goto err_invalid_dis_gpio;
+	}
+	if (qca199x_dev->clk_run == false) {
+		r = clk_prepare_enable(qca199x_dev->s_clk);
+		if (r)
+			goto err_invalid_clk;
+		qca199x_dev->clk_run = true;
+	}
+	r = 0;
+	return r;
+
+err_invalid_clk:
+	r = -1;
+	return r;
+err_invalid_dis_gpio:
+	r = -2;
+	return r;
+}
+/*
+	Routine to De-Select clocks
+*/
+
+static int qca199x_clock_deselect(struct qca199x_dev *qca199x_dev)
+{
+	int r = -1;
+	if (qca199x_dev->s_clk != NULL) {
+		if (qca199x_dev->clk_run == true) {
+			clk_disable_unprepare(qca199x_dev->s_clk);
+			qca199x_dev->clk_run = false;
+		}
+		return 0;
 	}
 	return r;
 }
@@ -755,10 +1002,10 @@
 	if ((!gpio_is_valid(pdata->irq_gpio)))
 		return -EINVAL;
 
-	r = of_property_read_string(np, "qcom,clk-src", &pdata->clk_src);
+	r = of_property_read_string(np, "qcom,clk-src", &pdata->clk_src_name);
 
-	if ((!strcmp(pdata->clk_src, "GPCLK")) ||
-	    (!strcmp(pdata->clk_src, "GPCLK2")))
+	if ((!strcmp(pdata->clk_src_name, "GPCLK")) ||
+	    (!strcmp(pdata->clk_src_name, "GPCLK2")))
 		pdata->clk_src_gpio = of_get_named_gpio(np,
 				"qcom,clk-en-gpio", 0);
 
@@ -772,7 +1019,6 @@
 {
 	int r = 0;
 	int irqn = 0;
-	struct clk *nfc_clk = NULL;
 	struct device_node *node = client->dev.of_node;
 	struct qca199x_platform_data *platform_data;
 	struct qca199x_dev *qca199x_dev;
@@ -810,12 +1056,13 @@
 		"nfc-nci probe: failed to allocate memory for module data\n");
 		return -ENOMEM;
 	}
+	qca199x_dev->client = client;
 	if (gpio_is_valid(platform_data->irq_gpio)) {
 		r = gpio_request(platform_data->irq_gpio, "nfc_irq_gpio");
 		if (r) {
 			dev_err(&client->dev, "unable to request gpio [%d]\n",
 				platform_data->irq_gpio);
-			goto err_irq;
+			goto err_free_dev;
 		}
 		r = gpio_direction_input(platform_data->irq_gpio);
 		if (r) {
@@ -843,7 +1090,7 @@
 			dev_err(&client->dev,
 			"NFC: unable to request gpio [%d]\n",
 				platform_data->dis_gpio);
-			goto err_free_dev;
+			goto err_irq;
 		}
 		r = gpio_direction_output(platform_data->dis_gpio, 1);
 		if (r) {
@@ -856,40 +1103,17 @@
 		dev_err(&client->dev, "dis gpio not provided\n");
 		goto err_irq;
 	}
-	gpio_set_value(platform_data->dis_gpio, 1);/* HPD */
-	msleep(20);
-	gpio_set_value(platform_data->dis_gpio, 0);/* ULPM */
-	if (!strcmp(platform_data->clk_src, "BBCLK2")) {
-		nfc_clk  = clk_get(&client->dev, "ref_clk");
-		if (nfc_clk == NULL)
+	/* Get the clock source name and gpio from from Device Tree */
+	qca199x_dev->clk_src_name = platform_data->clk_src_name;
+	qca199x_dev->clk_src_gpio = platform_data->clk_src_gpio;
+	qca199x_dev->clk_run = false;
+	r = qca199x_clock_select(qca199x_dev);
+	if (r != 0) {
+		if (r == -1)
+			goto err_clk;
+		else
 			goto err_dis_gpio;
-	} else if (!strcmp(platform_data->clk_src, "RFCLK3")) {
-		nfc_clk  = clk_get(&client->dev, "ref_clk_rf");
-		if (nfc_clk == NULL)
-			goto err_dis_gpio;
-	} else if (!strcmp(platform_data->clk_src, "GPCLK")) {
-		if (gpio_is_valid(platform_data->clk_src_gpio)) {
-			nfc_clk  = clk_get(&client->dev, "core_clk");
-			if (nfc_clk == NULL)
-				goto err_dis_gpio;
-		} else {
-			goto err_dis_gpio;
-		}
-	} else if (!strcmp(platform_data->clk_src, "GPCLK2")) {
-		if (gpio_is_valid(platform_data->clk_src_gpio)) {
-			nfc_clk  = clk_get(&client->dev, "core_clk_pvt");
-			if (nfc_clk == NULL)
-				goto err_dis_gpio;
-		} else {
-			goto err_dis_gpio;
-		}
-	} else {
-		nfc_clk = NULL;
 	}
-	r = clk_prepare_enable(nfc_clk);
-	if (r)
-		goto err_clk;
-
 	platform_data->ven_gpio = of_get_named_gpio(node,
 						"qcom,clk-gpio", 0);
 
@@ -902,7 +1126,6 @@
 		}
 		r = gpio_direction_input(platform_data->ven_gpio);
 		if (r) {
-
 			dev_err(&client->dev,
 			"unable to set direction for gpio [%d]\n",
 						platform_data->ven_gpio);
@@ -915,7 +1138,6 @@
 	qca199x_dev->dis_gpio = platform_data->dis_gpio;
 	qca199x_dev->irq_gpio = platform_data->irq_gpio;
 	qca199x_dev->ven_gpio = platform_data->ven_gpio;
-	qca199x_dev->client = client;
 
 	/* init mutex and queues */
 	init_waitqueue_head(&qca199x_dev->read_wq);
@@ -950,12 +1172,6 @@
 	* for reading.  It is cleared when all data has been read.
 	*/
 	device_mode.handle_flavour = UNSOLICITED_MODE;
-	r = nfcc_initialise(client, platform_data->reg);
-	if (r) {
-		dev_err(&client->dev, "nfc-nci probe: request nfcc initialise failed\n");
-		goto err_nfcc_init_failed;
-	}
-
 	qca199x_dev->irq_enabled = true;
 	r = request_irq(client->irq, qca199x_dev_irq_handler,
 			  IRQF_TRIGGER_RISING, client->name, qca199x_dev);
@@ -965,12 +1181,12 @@
 	}
 	qca199x_disable_irq(qca199x_dev);
 	i2c_set_clientdata(client, qca199x_dev);
+	gpio_set_value(platform_data->dis_gpio, 1);
 	dev_dbg(&client->dev,
 	"nfc-nci probe: %s, probing qca1990 exited successfully\n",
 		 __func__);
 	return 0;
 
-err_nfcc_init_failed:
 err_request_irq_failed:
 	misc_deregister(&qca199x_dev->qca199x_device);
 err_misc_register:
@@ -978,13 +1194,13 @@
 err_ven_gpio:
 	gpio_free(platform_data->ven_gpio);
 err_clk:
-	clk_disable_unprepare(nfc_clk);
+		qca199x_clock_deselect(qca199x_dev);
 err_dis_gpio:
 	r = gpio_direction_input(platform_data->dis_gpio);
 	if (r)
 		dev_err(&client->dev, "nfc-nci probe: Unable to set direction\n");
-	if ((!strcmp(platform_data->clk_src, "GPCLK")) ||
-            (!strcmp(platform_data->clk_src, "GPCLK2"))) {
+	if ((!strcmp(platform_data->clk_src_name, "GPCLK")) ||
+            (!strcmp(platform_data->clk_src_name, "GPCLK2"))) {
 		r = gpio_direction_input(platform_data->clk_src_gpio);
 		if (r)
 			dev_err(&client->dev, "nfc-nci probe: Unable to set direction\n");
diff --git a/drivers/usb/class/Kconfig b/drivers/usb/class/Kconfig
index 2519e32..f7321e5 100644
--- a/drivers/usb/class/Kconfig
+++ b/drivers/usb/class/Kconfig
@@ -50,3 +50,15 @@
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called usbtmc.
+
+config USB_CCID_BRIDGE
+	tristate "USB  Smart Card Class (CCID) support"
+	help
+	  Say Y here if you want to connect a USB Smart Card device that
+	  follows the USB.org specification for Integrated Circuit(s) Cards
+	  Interface Devices to your computer's USB port.  This module
+	  provides a character device interface to exchange the messages.
+	  Ioctls facilitate control transfers and interrupt transfers.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ccid_bridge.
diff --git a/drivers/usb/class/Makefile b/drivers/usb/class/Makefile
index 32e8527..c2ee6f3 100644
--- a/drivers/usb/class/Makefile
+++ b/drivers/usb/class/Makefile
@@ -7,3 +7,4 @@
 obj-$(CONFIG_USB_PRINTER)	+= usblp.o
 obj-$(CONFIG_USB_WDM)		+= cdc-wdm.o
 obj-$(CONFIG_USB_TMC)		+= usbtmc.o
+obj-$(CONFIG_USB_CCID_BRIDGE)	+= ccid_bridge.o
diff --git a/drivers/usb/class/ccid_bridge.c b/drivers/usb/class/ccid_bridge.c
new file mode 100644
index 0000000..a3e100a
--- /dev/null
+++ b/drivers/usb/class/ccid_bridge.c
@@ -0,0 +1,885 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt "\n", __func__
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/usb.h>
+#include <linux/wait.h>
+#include <linux/cdev.h>
+
+#include <linux/usb/ccid_bridge.h>
+
+#define CCID_CLASS_DECRIPTOR_TYPE 0x21
+#define CCID_NOTIFY_SLOT_CHANGE	0x50
+#define CCID_NOTIFY_HARDWARE_ERROR 0x51
+#define CCID_ABORT_REQ 0x1
+#define CCID_GET_CLK_FREQ_REQ 0x2
+#define CCID_GET_DATA_RATES 0x3
+
+#define CCID_BRIDGE_MSG_SZ 512
+#define CCID_BRIDGE_OPEN_TIMEOUT 500 /* msec */
+#define CCID_CONTROL_TIMEOUT 500 /* msec */
+#define CCID_BRIDGE_MSG_TIMEOUT 500 /* msec */
+
+struct ccid_bridge {
+	struct usb_device *udev;
+	struct usb_interface *intf;
+	unsigned int in_pipe;
+	unsigned int out_pipe;
+	unsigned int int_pipe;
+	struct urb *inturb;
+	struct urb *readurb;
+	struct urb *writeurb;
+
+	bool opened;
+	bool events_supported;
+	bool is_suspended;
+	struct mutex open_mutex;
+	struct mutex write_mutex;
+	struct mutex read_mutex;
+	struct mutex event_mutex;
+	int write_result;
+	int read_result;
+	int event_result;
+	wait_queue_head_t open_wq;
+	wait_queue_head_t write_wq;
+	wait_queue_head_t read_wq;
+	wait_queue_head_t event_wq;
+	struct usb_ccid_event cur_event;
+	void *intbuf;
+
+	dev_t chrdev;
+	struct cdev cdev;
+	struct class *class;
+	struct device *device;
+};
+
+static struct ccid_bridge *__ccid_bridge_dev;
+
+static void ccid_bridge_out_cb(struct urb *urb)
+{
+	struct ccid_bridge *ccid = urb->context;
+
+	if (urb->dev->state == USB_STATE_NOTATTACHED)
+		ccid->write_result = -ENODEV;
+	else
+		ccid->write_result = urb->status ? : urb->actual_length;
+
+	pr_debug("write result = %d", ccid->write_result);
+	wake_up(&ccid->write_wq);
+}
+
+static void ccid_bridge_in_cb(struct urb *urb)
+{
+	struct ccid_bridge *ccid = urb->context;
+
+	if (urb->dev->state == USB_STATE_NOTATTACHED)
+		ccid->read_result = -ENODEV;
+	else
+		ccid->read_result = urb->status ? : urb->actual_length;
+
+	pr_debug("read result = %d", ccid->read_result);
+	wake_up(&ccid->read_wq);
+}
+
+static void ccid_bridge_int_cb(struct urb *urb)
+{
+	struct ccid_bridge *ccid = urb->context;
+	u8 *msg_type;
+	bool wakeup = true;
+
+	if (urb->dev->state == USB_STATE_NOTATTACHED || (urb->status &&
+				urb->status != -ENOENT)) {
+		ccid->event_result = -ENODEV;
+		wakeup = true;
+		goto out;
+	}
+
+	/*
+	 * Don't wakeup the event ioctl process during suspend.
+	 * The suspend state is not visible to user space.
+	 * we wake up the process after resume to send RESUME
+	 * event if the device supports remote wakeup.
+	 */
+	if (urb->status == -ENOENT && !urb->actual_length) {
+		ccid->event_result = -ENOENT;
+		wakeup = false;
+		goto out;
+	}
+
+	ccid->event_result = 0;
+	msg_type = urb->transfer_buffer;
+	switch (*msg_type) {
+	case CCID_NOTIFY_SLOT_CHANGE:
+		pr_debug("NOTIFY_SLOT_CHANGE event arrived");
+		ccid->cur_event.event = USB_CCID_NOTIFY_SLOT_CHANGE_EVENT;
+		ccid->cur_event.u.notify.slot_icc_state = *(++msg_type);
+		break;
+	case CCID_NOTIFY_HARDWARE_ERROR:
+		pr_debug("NOTIFY_HARDWARE_ERROR event arrived");
+		ccid->cur_event.event = USB_CCID_HARDWARE_ERROR_EVENT;
+		ccid->cur_event.u.error.slot = *(++msg_type);
+		ccid->cur_event.u.error.seq = *(++msg_type);
+		ccid->cur_event.u.error.error_code = *(++msg_type);
+		break;
+	default:
+		pr_err("UNKNOWN event arrived\n");
+		ccid->event_result = -EINVAL;
+	}
+
+out:
+	pr_debug("returning %d", ccid->event_result);
+	if (wakeup)
+		wake_up(&ccid->event_wq);
+}
+
+static int ccid_bridge_submit_inturb(struct ccid_bridge *ccid)
+{
+	int ret = 0;
+
+	/*
+	 * Don't resume the bus to submit an interrupt URB.
+	 * We submit the URB in resume path.  This is important.
+	 * Because the device will be in suspend state during
+	 * multiple system suspend/resume cycles.  The user space
+	 * process comes here during system resume after it is
+	 * unfrozen.
+	 */
+	if (!ccid->int_pipe || ccid->is_suspended)
+		goto out;
+
+	ret = usb_autopm_get_interface(ccid->intf);
+	if (ret < 0) {
+		pr_debug("fail to get autopm with %d\n", ret);
+		goto out;
+	}
+	ret = usb_submit_urb(ccid->inturb, GFP_KERNEL);
+	if (ret < 0)
+		pr_err("fail to submit int urb with %d\n", ret);
+	usb_autopm_put_interface(ccid->intf);
+
+out:
+	pr_debug("returning %d", ret);
+	return ret;
+}
+
+static int ccid_bridge_get_event(struct ccid_bridge *ccid)
+{
+	int ret = 0;
+
+	/*
+	 * The first event returned after the device resume
+	 * will be RESUME event.  This event is set by
+	 * the resume.
+	 */
+	if (ccid->cur_event.event)
+		goto out;
+
+	ccid->event_result = -EINPROGRESS;
+
+	ret = ccid_bridge_submit_inturb(ccid);
+	if (ret < 0)
+		goto out;
+
+	/*
+	 * Wait for the notification on interrupt endpoint
+	 * or remote wakeup event from the resume.  The
+	 * int urb completion handler and resume callback
+	 * take care of setting the current event.
+	 */
+	mutex_unlock(&ccid->event_mutex);
+	ret = wait_event_interruptible(ccid->event_wq,
+			(ccid->event_result != -EINPROGRESS));
+	mutex_lock(&ccid->event_mutex);
+
+	if (ret == -ERESTARTSYS) /* interrupted */
+		usb_kill_urb(ccid->inturb);
+	else
+		ret = ccid->event_result;
+out:
+	pr_debug("returning %d", ret);
+	return ret;
+}
+
+static int ccid_bridge_open(struct inode *ip, struct file *fp)
+{
+	struct ccid_bridge *ccid = container_of(ip->i_cdev,
+				struct ccid_bridge, cdev);
+	int ret;
+
+	pr_debug("called");
+
+	mutex_lock(&ccid->open_mutex);
+	if (ccid->opened) {
+		ret = -EBUSY;
+		goto out;
+	}
+	mutex_unlock(&ccid->open_mutex);
+
+	ret = wait_event_interruptible_timeout(ccid->open_wq,
+			ccid->intf != NULL, msecs_to_jiffies(
+				CCID_BRIDGE_OPEN_TIMEOUT));
+
+	mutex_lock(&ccid->open_mutex);
+
+	if (ret != -ERESTARTSYS && ccid->intf) {
+		fp->private_data = ccid;
+		ccid->opened = true;
+		ret = 0;
+	} else if (!ret) { /* timed out */
+		ret = -ENODEV;
+	}
+out:
+	mutex_unlock(&ccid->open_mutex);
+	pr_debug("returning %d", ret);
+	return ret;
+}
+
+static ssize_t ccid_bridge_write(struct file *fp, const char __user *ubuf,
+				 size_t count, loff_t *pos)
+{
+	struct ccid_bridge *ccid = fp->private_data;
+	int ret;
+	char *kbuf;
+
+	pr_debug("called with %d", count);
+
+	if (!ccid->intf) {
+		pr_debug("intf is not active");
+		return -ENODEV;
+	}
+
+	mutex_lock(&ccid->write_mutex);
+
+	if (!count || count > CCID_BRIDGE_MSG_SZ) {
+		pr_err("invalid count");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	kbuf = kmalloc(count, GFP_KERNEL);
+	if (!kbuf) {
+		pr_err("fail to allocate memory");
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ret = copy_from_user(kbuf, ubuf, count);
+	if (ret) {
+		pr_err("fail to copy user buf");
+		ret = -EFAULT;
+		goto free_kbuf;
+	}
+
+	ret = usb_autopm_get_interface(ccid->intf);
+	if (ret) {
+		pr_err("fail to get autopm with %d", ret);
+		goto free_kbuf;
+	}
+
+	ccid->write_result = 0;
+
+	usb_fill_bulk_urb(ccid->writeurb, ccid->udev, ccid->out_pipe,
+			kbuf, count, ccid_bridge_out_cb, ccid);
+	ret = usb_submit_urb(ccid->writeurb, GFP_KERNEL);
+	if (ret < 0) {
+		pr_err("urb submit fail with %d", ret);
+		goto put_pm;
+	}
+
+	ret = wait_event_interruptible_timeout(ccid->write_wq,
+			ccid->write_result != 0,
+			msecs_to_jiffies(CCID_BRIDGE_MSG_TIMEOUT));
+	if (!ret || ret == -ERESTARTSYS) { /* timedout or interrupted */
+		usb_kill_urb(ccid->writeurb);
+		if (!ret)
+			ret = -ETIMEDOUT;
+	} else {
+		ret = ccid->write_result;
+	}
+
+	pr_debug("returning %d", ret);
+
+put_pm:
+	if (ret != -ENODEV)
+		usb_autopm_put_interface(ccid->intf);
+free_kbuf:
+	kfree(kbuf);
+out:
+	mutex_unlock(&ccid->write_mutex);
+	return ret;
+
+}
+
+static ssize_t ccid_bridge_read(struct file *fp, char __user *ubuf,
+				 size_t count, loff_t *pos)
+{
+	struct ccid_bridge *ccid = fp->private_data;
+	int ret;
+	char *kbuf;
+
+	pr_debug("called with %d", count);
+	if (!ccid->intf) {
+		pr_debug("intf is not active");
+		return -ENODEV;
+	}
+
+	mutex_lock(&ccid->read_mutex);
+
+	if (!count || count > CCID_BRIDGE_MSG_SZ) {
+		pr_err("invalid count");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	kbuf = kmalloc(count, GFP_KERNEL);
+	if (!kbuf) {
+		pr_err("fail to allocate memory");
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ret = usb_autopm_get_interface(ccid->intf);
+	if (ret) {
+		pr_err("fail to get autopm with %d", ret);
+		goto free_kbuf;
+	}
+
+	ccid->read_result = 0;
+
+	usb_fill_bulk_urb(ccid->readurb, ccid->udev, ccid->in_pipe,
+			kbuf, count, ccid_bridge_in_cb, ccid);
+	ret = usb_submit_urb(ccid->readurb, GFP_KERNEL);
+	if (ret < 0) {
+		pr_err("urb submit fail with %d", ret);
+		if (ret != -ENODEV)
+			usb_autopm_put_interface(ccid->intf);
+		goto free_kbuf;
+	}
+
+
+	ret = wait_event_interruptible_timeout(ccid->read_wq,
+			ccid->read_result != 0,
+			msecs_to_jiffies(CCID_BRIDGE_MSG_TIMEOUT));
+	if (!ret || ret == -ERESTARTSYS) { /* timedout or interrupted */
+		usb_kill_urb(ccid->readurb);
+		if (!ret)
+			ret = -ETIMEDOUT;
+	} else {
+		ret = ccid->read_result;
+	}
+
+
+	if (ret > 0) {
+		if (copy_to_user(ubuf, kbuf, ret))
+			ret = -EFAULT;
+	}
+
+	usb_autopm_put_interface(ccid->intf);
+	pr_debug("returning %d", ret);
+
+free_kbuf:
+	kfree(kbuf);
+out:
+	mutex_unlock(&ccid->read_mutex);
+	return ret;
+}
+
+static long
+ccid_bridge_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
+{
+	struct ccid_bridge *ccid = fp->private_data;
+	char *buf;
+	struct usb_ccid_data data;
+	struct usb_ccid_abort abort;
+	struct usb_descriptor_header *header;
+	int ret;
+	struct usb_device *udev = ccid->udev;
+	__u8 intf = ccid->intf->cur_altsetting->desc.bInterfaceNumber;
+	__u8 breq = 0;
+
+	if (!ccid->intf) {
+		pr_debug("intf is not active");
+		return -ENODEV;
+	}
+
+	mutex_lock(&ccid->event_mutex);
+	switch (cmd) {
+	case USB_CCID_GET_CLASS_DESC:
+		pr_debug("GET_CLASS_DESC ioctl called");
+		ret = copy_from_user(&data, (void __user *)arg, sizeof(data));
+		if (ret) {
+			ret = -EFAULT;
+			break;
+		}
+		ret = __usb_get_extra_descriptor(udev->rawdescriptors[0],
+				le16_to_cpu(udev->config[0].desc.wTotalLength),
+				CCID_CLASS_DECRIPTOR_TYPE, (void **) &buf);
+		if (ret) {
+			ret = -ENOENT;
+			break;
+		}
+		header = (struct usb_descriptor_header *) buf;
+		if (data.length != header->bLength) {
+			ret = -EINVAL;
+			break;
+		}
+		ret = copy_to_user((void __user *)data.data, buf, data.length);
+		if (ret)
+			ret = -EFAULT;
+		break;
+	case USB_CCID_GET_CLOCK_FREQUENCIES:
+		pr_debug("GET_CLOCK_FREQUENCIES ioctl called");
+		breq = CCID_GET_CLK_FREQ_REQ;
+		/* fall through */
+	case USB_CCID_GET_DATA_RATES:
+		if (!breq) {
+			pr_debug("GET_DATA_RATES ioctl called");
+			breq = CCID_GET_DATA_RATES;
+		}
+		ret = copy_from_user(&data, (void __user *)arg, sizeof(data));
+		if (ret) {
+			ret = -EFAULT;
+			break;
+		}
+		buf = kmalloc(data.length, GFP_KERNEL);
+		if (!buf) {
+			ret = -ENOMEM;
+			break;
+		}
+		ret = usb_autopm_get_interface(ccid->intf);
+		if (ret < 0) {
+			pr_debug("fail to get autopm with %d", ret);
+			break;
+		}
+		ret = usb_control_msg(ccid->udev,
+				usb_rcvctrlpipe(ccid->udev, 0),
+				breq, (USB_DIR_IN | USB_TYPE_CLASS |
+				 USB_RECIP_INTERFACE), 0, intf, buf,
+				data.length, CCID_CONTROL_TIMEOUT);
+		usb_autopm_put_interface(ccid->intf);
+		if (ret == data.length) {
+			ret = copy_to_user((void __user *)data.data, buf,
+					data.length);
+			if (ret)
+				ret = -EFAULT;
+		} else {
+			if (ret > 0)
+				ret = -EPIPE;
+		}
+		kfree(buf);
+		break;
+	case USB_CCID_ABORT:
+		pr_debug("ABORT ioctl called");
+		breq = CCID_ABORT_REQ;
+		ret = copy_from_user(&abort, (void __user *)arg, sizeof(abort));
+		if (ret) {
+			ret = -EFAULT;
+			break;
+		}
+		ret = usb_autopm_get_interface(ccid->intf);
+		if (ret < 0) {
+			pr_debug("fail to get autopm with %d", ret);
+			break;
+		}
+		ret = usb_control_msg(ccid->udev,
+				usb_sndctrlpipe(ccid->udev, 0),
+				breq, (USB_DIR_OUT | USB_TYPE_CLASS |
+				 USB_RECIP_INTERFACE),
+				(abort.seq << 8) | abort.slot, intf, NULL,
+				0, CCID_CONTROL_TIMEOUT);
+		if (ret < 0)
+			pr_err("abort request failed with err %d\n", ret);
+		usb_autopm_put_interface(ccid->intf);
+		break;
+	case USB_CCID_GET_EVENT:
+		pr_debug("GET_EVENT ioctl called");
+		if (!ccid->events_supported) {
+			ret = -ENOENT;
+			break;
+		}
+		ret = ccid_bridge_get_event(ccid);
+		if (ret == 0) {
+			ret = copy_to_user((void __user *)arg, &ccid->cur_event,
+					sizeof(ccid->cur_event));
+			if (ret)
+				ret = -EFAULT;
+		}
+		ccid->cur_event.event = 0;
+		break;
+	default:
+		pr_err("UNKNOWN ioctl called");
+		ret = -EINVAL;
+		break;
+	}
+
+	mutex_unlock(&ccid->event_mutex);
+	pr_debug("returning %d", ret);
+	return ret;
+}
+
+static int ccid_bridge_release(struct inode *ip, struct file *fp)
+{
+	struct ccid_bridge *ccid = fp->private_data;
+
+	pr_debug("called");
+
+	usb_kill_urb(ccid->writeurb);
+	usb_kill_urb(ccid->readurb);
+	if (ccid->int_pipe)
+		usb_kill_urb(ccid->inturb);
+
+	ccid->event_result = -EIO;
+	wake_up(&ccid->event_wq);
+
+	mutex_lock(&ccid->open_mutex);
+	ccid->opened = false;
+	mutex_unlock(&ccid->open_mutex);
+	return 0;
+}
+
+static const struct file_operations ccid_bridge_fops = {
+	.owner = THIS_MODULE,
+	.open = ccid_bridge_open,
+	.write = ccid_bridge_write,
+	.read = ccid_bridge_read,
+	.unlocked_ioctl = ccid_bridge_ioctl,
+	.release = ccid_bridge_release,
+};
+
+static int ccid_bridge_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	struct ccid_bridge *ccid = usb_get_intfdata(intf);
+	int ret = 0;
+
+	pr_debug("called");
+
+	if (!ccid->opened)
+		goto out;
+
+	mutex_lock(&ccid->event_mutex);
+	if (ccid->int_pipe) {
+		usb_kill_urb(ccid->inturb);
+		if (ccid->event_result != -ENOENT) {
+			ret = -EBUSY;
+			goto rel_mutex;
+		}
+	}
+
+	ccid->is_suspended = true;
+rel_mutex:
+	mutex_unlock(&ccid->event_mutex);
+out:
+	pr_debug("returning %d", ret);
+	return ret;
+}
+
+static int ccid_bridge_resume(struct usb_interface *intf)
+{
+	struct ccid_bridge *ccid = usb_get_intfdata(intf);
+	int ret;
+
+	pr_debug("called");
+
+	if (!ccid->opened)
+		goto out;
+
+	mutex_lock(&ccid->event_mutex);
+
+	ccid->is_suspended = false;
+
+	if (device_can_wakeup(&ccid->udev->dev)) {
+		ccid->event_result = 0;
+		ccid->cur_event.event = USB_CCID_RESUME_EVENT;
+		wake_up(&ccid->event_wq);
+	} else if (ccid->int_pipe) {
+		ccid->event_result = -EINPROGRESS;
+		ret = usb_submit_urb(ccid->inturb, GFP_KERNEL);
+		if (ret < 0)
+			pr_debug("fail to submit inturb with %d\n", ret);
+	}
+
+	mutex_unlock(&ccid->event_mutex);
+out:
+	return 0;
+}
+
+static int
+ccid_bridge_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+	struct ccid_bridge *ccid = __ccid_bridge_dev;
+	struct usb_host_interface *intf_desc;
+	struct usb_endpoint_descriptor *ep_desc;
+	struct usb_host_endpoint *ep;
+	__u8 epin_addr = 0, epout_addr = 0, epint_addr = 0;
+	int i, ret;
+
+	intf_desc = intf->cur_altsetting;
+
+	if (intf_desc->desc.bNumEndpoints > 3)
+		return -ENODEV;
+
+	for (i = 0; i < intf_desc->desc.bNumEndpoints; i++) {
+		ep_desc = &intf_desc->endpoint[i].desc;
+
+		if (usb_endpoint_is_bulk_in(ep_desc))
+			epin_addr = ep_desc->bEndpointAddress;
+		else if (usb_endpoint_is_bulk_out(ep_desc))
+			epout_addr = ep_desc->bEndpointAddress;
+		else if (usb_endpoint_is_int_in(ep_desc))
+			epint_addr = ep_desc->bEndpointAddress;
+		else
+			return -ENODEV;
+	}
+
+	if (!epin_addr || !epout_addr)
+		return -ENODEV;
+
+	ccid->udev = usb_get_dev(interface_to_usbdev(intf));
+	ccid->in_pipe = usb_rcvbulkpipe(ccid->udev, epin_addr);
+	ccid->out_pipe = usb_sndbulkpipe(ccid->udev, epout_addr);
+	if (epint_addr)
+		ccid->int_pipe = usb_rcvbulkpipe(ccid->udev, epint_addr);
+
+	ccid->writeurb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!ccid->writeurb) {
+		pr_err("fail to allocate write urb");
+		ret = -ENOMEM;
+		goto put_udev;
+	}
+	ccid->readurb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!ccid->readurb) {
+		pr_err("fail to allocate read urb");
+		ret = -ENOMEM;
+		goto free_writeurb;
+	}
+
+	if (ccid->int_pipe) {
+		pr_debug("interrupt endpoint is present");
+		ep = usb_pipe_endpoint(ccid->udev, ccid->int_pipe);
+		ccid->inturb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!ccid->inturb) {
+			pr_err("fail to allocate int urb");
+			ret = -ENOMEM;
+			goto free_readurb;
+		}
+		ccid->intbuf = kmalloc(usb_endpoint_maxp(&ep->desc),
+				GFP_KERNEL);
+		if (!ccid->intbuf) {
+			pr_err("fail to allocated int buf");
+			ret = -ENOMEM;
+			goto free_inturb;
+		}
+		usb_fill_int_urb(ccid->inturb, ccid->udev,
+				usb_rcvintpipe(ccid->udev, epint_addr),
+				ccid->intbuf, usb_endpoint_maxp(&ep->desc),
+				ccid_bridge_int_cb, ccid,
+				ep->desc.bInterval);
+	}
+
+	if (ccid->int_pipe || device_can_wakeup(&ccid->udev->dev)) {
+		pr_debug("event support is present");
+		ccid->events_supported = true;
+	}
+
+	usb_set_intfdata(intf, ccid);
+
+	mutex_lock(&ccid->open_mutex);
+	ccid->intf = intf;
+	wake_up(&ccid->open_wq);
+	mutex_unlock(&ccid->open_mutex);
+
+	pr_info("success");
+	return 0;
+
+free_inturb:
+	if (ccid->int_pipe)
+		usb_free_urb(ccid->inturb);
+free_readurb:
+	usb_free_urb(ccid->readurb);
+free_writeurb:
+	usb_free_urb(ccid->writeurb);
+put_udev:
+	usb_put_dev(ccid->udev);
+	return ret;
+}
+
+static void ccid_bridge_disconnect(struct usb_interface *intf)
+{
+	struct ccid_bridge *ccid = usb_get_intfdata(intf);
+
+	pr_debug("called");
+
+	usb_kill_urb(ccid->writeurb);
+	usb_kill_urb(ccid->readurb);
+	if (ccid->int_pipe)
+		usb_kill_urb(ccid->inturb);
+
+	ccid->event_result = -ENODEV;
+	wake_up(&ccid->event_wq);
+
+	/*
+	 * This would synchronize any ongoing read/write/ioctl.
+	 * After acquiring the mutex, we can safely set
+	 * intf to NULL.
+	 */
+	mutex_lock(&ccid->open_mutex);
+	mutex_lock(&ccid->write_mutex);
+	mutex_lock(&ccid->read_mutex);
+	mutex_lock(&ccid->event_mutex);
+
+	usb_free_urb(ccid->writeurb);
+	usb_free_urb(ccid->readurb);
+	if (ccid->int_pipe) {
+		usb_free_urb(ccid->inturb);
+		kfree(ccid->intbuf);
+		ccid->int_pipe = 0;
+	}
+
+	ccid->intf = NULL;
+
+	mutex_unlock(&ccid->event_mutex);
+	mutex_unlock(&ccid->read_mutex);
+	mutex_unlock(&ccid->write_mutex);
+	mutex_unlock(&ccid->open_mutex);
+
+}
+
+static const struct usb_device_id ccid_bridge_ids[] = {
+	{ USB_INTERFACE_INFO(USB_CLASS_CSCID, 0, 0) },
+
+	{} /* terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, ccid_bridge_ids);
+
+static struct usb_driver ccid_bridge_driver = {
+	.name = "ccid_bridge",
+	.probe = ccid_bridge_probe,
+	.disconnect = ccid_bridge_disconnect,
+	.suspend = ccid_bridge_suspend,
+	.resume = ccid_bridge_resume,
+	.id_table = ccid_bridge_ids,
+	.supports_autosuspend = 1,
+};
+
+static int __init ccid_bridge_init(void)
+{
+	int ret;
+	struct ccid_bridge *ccid;
+
+	ccid = kzalloc(sizeof(*ccid), GFP_KERNEL);
+	if (!ccid) {
+		pr_err("Fail to allocate ccid");
+		ret = -ENOMEM;
+		goto out;
+	}
+	__ccid_bridge_dev = ccid;
+
+	mutex_init(&ccid->open_mutex);
+	mutex_init(&ccid->write_mutex);
+	mutex_init(&ccid->read_mutex);
+	mutex_init(&ccid->event_mutex);
+
+	init_waitqueue_head(&ccid->open_wq);
+	init_waitqueue_head(&ccid->write_wq);
+	init_waitqueue_head(&ccid->read_wq);
+	init_waitqueue_head(&ccid->event_wq);
+
+	ret = usb_register(&ccid_bridge_driver);
+	if (ret < 0) {
+		pr_err("Fail to register ccid usb driver with %d", ret);
+		goto free_ccid;
+	}
+
+	ret = alloc_chrdev_region(&ccid->chrdev, 0, 1, "ccid_bridge");
+	if (ret < 0) {
+		pr_err("Fail to allocate ccid char dev region with %d", ret);
+		goto unreg_driver;
+	}
+	ccid->class = class_create(THIS_MODULE, "ccid_bridge");
+	if (IS_ERR(ccid->class)) {
+		ret = PTR_ERR(ccid->class);
+		pr_err("Fail to create ccid class with %d", ret);
+		goto unreg_chrdev;
+	}
+	cdev_init(&ccid->cdev, &ccid_bridge_fops);
+	ccid->cdev.owner = THIS_MODULE;
+
+	ret = cdev_add(&ccid->cdev, ccid->chrdev, 1);
+	if (ret < 0) {
+		pr_err("Fail to add ccid cdev with %d", ret);
+		goto destroy_class;
+	}
+	ccid->device = device_create(ccid->class,
+					NULL, ccid->chrdev, NULL,
+					"ccid_bridge");
+	if (IS_ERR(ccid->device)) {
+		ret = PTR_ERR(ccid->device);
+		pr_err("Fail to create ccid device with %d", ret);
+		goto del_cdev;
+	}
+
+	pr_info("success");
+
+	return 0;
+
+del_cdev:
+	cdev_del(&ccid->cdev);
+destroy_class:
+	class_destroy(ccid->class);
+unreg_chrdev:
+	unregister_chrdev_region(ccid->chrdev, 1);
+unreg_driver:
+	usb_deregister(&ccid_bridge_driver);
+free_ccid:
+	mutex_destroy(&ccid->open_mutex);
+	mutex_destroy(&ccid->write_mutex);
+	mutex_destroy(&ccid->read_mutex);
+	mutex_destroy(&ccid->event_mutex);
+	kfree(ccid);
+	__ccid_bridge_dev = NULL;
+out:
+	return ret;
+}
+
+static void __exit ccid_bridge_exit(void)
+{
+	struct ccid_bridge *ccid = __ccid_bridge_dev;
+
+	pr_debug("called");
+	device_destroy(ccid->class, ccid->chrdev);
+	cdev_del(&ccid->cdev);
+	class_destroy(ccid->class);
+	unregister_chrdev_region(ccid->chrdev, 1);
+
+	usb_deregister(&ccid_bridge_driver);
+
+	mutex_destroy(&ccid->open_mutex);
+	mutex_destroy(&ccid->write_mutex);
+	mutex_destroy(&ccid->read_mutex);
+	mutex_destroy(&ccid->event_mutex);
+
+	kfree(ccid);
+	__ccid_bridge_dev = NULL;
+}
+
+module_init(ccid_bridge_init);
+module_exit(ccid_bridge_exit);
+
+MODULE_DESCRIPTION("USB CCID bridge driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index d97d548..827ac9d 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -3159,7 +3159,8 @@
 	for (i = 0; i < GET_DESCRIPTOR_TRIES; (++i, msleep(100))) {
 		if (USE_NEW_SCHEME(retry_counter) &&
 			!(hcd->driver->flags & HCD_USB3) &&
-			!(hcd->driver->flags & HCD_OLD_ENUM)) {
+			!((hcd->driver->flags & HCD_RT_OLD_ENUM) &&
+				!hdev->parent)) {
 			struct usb_device_descriptor *buf;
 			int r = 0;
 
@@ -3261,7 +3262,8 @@
 			msleep(10);
 			if (USE_NEW_SCHEME(retry_counter) &&
 				!(hcd->driver->flags & HCD_USB3) &&
-				!(hcd->driver->flags & HCD_OLD_ENUM))
+				!((hcd->driver->flags & HCD_RT_OLD_ENUM) &&
+					!hdev->parent))
 				break;
   		}
 
diff --git a/drivers/usb/dwc3/debug.h b/drivers/usb/dwc3/debug.h
index 4901f4b..57d27cd 100644
--- a/drivers/usb/dwc3/debug.h
+++ b/drivers/usb/dwc3/debug.h
@@ -48,15 +48,17 @@
 extern void dwc3_debugfs_exit(struct dwc3 *);
 extern void dbg_print_reg(const char *name, int reg);
 #else
-static inline void dbg_event(u8, const char*, int)
+static inline void dbg_event(u8 ep_num, const char *name, int status)
 {  }
-static inline void dbg_print(u8, const char*, int, const char*)
+static inline void dbg_print(u8 ep_num, const char *name, int status,
+			     const char *extra)
 {  }
-static inline void dbg_done(u8, const u32, int)
+static inline void dbg_done(u8 ep_num, const u32 count, int status)
 {  }
-static inline void dbg_queue(u8, const struct usb_request*, int)
+static inline void dbg_queue(u8 ep_num, const struct usb_request *req,
+			     int status)
 {  }
-static inline void dbg_setup(u8, const struct usb_ctrlrequest*)
+static inline void dbg_setup(u8 ep_num, const struct usb_ctrlrequest *req)
 {  }
 static inline void dbg_print_reg(const char *name, int reg)
 {  }
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 1030664..a89ac06 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -1486,7 +1486,7 @@
 	 * generic hardware linkage
 	 */
 	.irq			= msm_hsic_irq,
-	.flags			= HCD_USB2 | HCD_MEMORY | HCD_OLD_ENUM,
+	.flags			= HCD_USB2 | HCD_MEMORY | HCD_RT_OLD_ENUM,
 
 	.reset			= ehci_hsic_reset,
 	.start			= ehci_run,
diff --git a/drivers/video/msm/mdss/dsi_host_v2.c b/drivers/video/msm/mdss/dsi_host_v2.c
index 25ee3e4..53b6fc6 100644
--- a/drivers/video/msm/mdss/dsi_host_v2.c
+++ b/drivers/video/msm/mdss/dsi_host_v2.c
@@ -959,11 +959,17 @@
 
 	msm_dsi_clk_ctrl(&ctrl->panel_data, 1);
 
+	if (0 == (req->flags & CMD_REQ_LP_MODE))
+		dsi_set_tx_power_mode(0);
+
 	if (req->flags & CMD_REQ_RX)
 		msm_dsi_cmdlist_rx(ctrl, req);
 	else
 		msm_dsi_cmdlist_tx(ctrl, req);
 
+	if (0 == (req->flags & CMD_REQ_LP_MODE))
+		dsi_set_tx_power_mode(1);
+
 	msm_dsi_clk_ctrl(&ctrl->panel_data, 0);
 
 	mutex_unlock(&ctrl->cmd_mutex);
diff --git a/drivers/video/msm/mdss/mdp3_ppp.c b/drivers/video/msm/mdss/mdp3_ppp.c
index d778af8..71cbbe4 100644
--- a/drivers/video/msm/mdss/mdp3_ppp.c
+++ b/drivers/video/msm/mdss/mdp3_ppp.c
@@ -283,7 +283,7 @@
 	spin_unlock_irqrestore(&ppp_stat->ppp_lock, flag);
 
 	if (wait) {
-		ret = wait_for_completion_interruptible_timeout(
+		ret = wait_for_completion_timeout(
 		   &ppp_stat->ppp_comp, 5 * HZ);
 		if (!ret)
 			pr_err("%s: Timed out waiting for the MDP.\n",
@@ -1099,7 +1099,7 @@
 	while (req_q->count >= MDP3_PPP_MAX_LIST_REQ) {
 		ppp_stat->wait_for_pop = true;
 		mutex_unlock(&ppp_stat->req_mutex);
-		rc = wait_for_completion_interruptible_timeout(
+		rc = wait_for_completion_timeout(
 		   &ppp_stat->pop_q_comp, 5 * HZ);
 		if (rc == 0) {
 			/* This will only occur if there is serious problem */
diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h
index ce4005e..ab54cbe 100644
--- a/drivers/video/msm/mdss/mdss.h
+++ b/drivers/video/msm/mdss/mdss.h
@@ -93,6 +93,8 @@
 	size_t mdp_reg_size;
 	char __iomem *vbif_base;
 
+	struct mutex reg_lock;
+
 	u32 irq;
 	u32 irq_mask;
 	u32 irq_ena;
diff --git a/drivers/video/msm/mdss/mdss_dsi_cmd.h b/drivers/video/msm/mdss/mdss_dsi_cmd.h
index c480756..f806e78 100644
--- a/drivers/video/msm/mdss/mdss_dsi_cmd.h
+++ b/drivers/video/msm/mdss/mdss_dsi_cmd.h
@@ -98,6 +98,7 @@
 #define CMD_REQ_COMMIT  0x0002
 #define CMD_CLK_CTRL    0x0004
 #define CMD_REQ_NO_MAX_PKT_SIZE 0x0008
+#define CMD_REQ_LP_MODE 0x0010
 
 struct dcs_cmd_req {
 	struct dsi_cmd_desc *cmds;
diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c
index 8c3e470..60e2cf9 100644
--- a/drivers/video/msm/mdss/mdss_dsi_panel.c
+++ b/drivers/video/msm/mdss/mdss_dsi_panel.c
@@ -118,6 +118,11 @@
 	cmdreq.cmds = pcmds->cmds;
 	cmdreq.cmds_cnt = pcmds->cmd_cnt;
 	cmdreq.flags = CMD_REQ_COMMIT;
+
+	/*Panel ON/Off commands should be sent in DSI Low Power Mode*/
+	if (pcmds->link_state == DSI_LP_MODE)
+		cmdreq.flags  |= CMD_REQ_LP_MODE;
+
 	cmdreq.rlen = 0;
 	cmdreq.cb = NULL;
 
diff --git a/drivers/video/msm/mdss/mdss_edp.c b/drivers/video/msm/mdss/mdss_edp.c
index 95c746e..c9050f7 100644
--- a/drivers/video/msm/mdss/mdss_edp.c
+++ b/drivers/video/msm/mdss/mdss_edp.c
@@ -198,6 +198,7 @@
 	int ret = 0;
 	struct mdss_edp_drv_pdata *edp_drv = NULL;
 	int bl_max;
+	int period_ns;
 
 	edp_drv = container_of(pdata, struct mdss_edp_drv_pdata, panel_data);
 	if (!edp_drv) {
@@ -210,13 +211,29 @@
 		if (bl_level > bl_max)
 			bl_level = bl_max;
 
-		ret = pwm_config_us(edp_drv->bl_pwm,
-				bl_level * edp_drv->pwm_period / bl_max,
-				edp_drv->pwm_period);
-		if (ret) {
-			pr_err("%s: pwm_config_us() failed err=%d.\n", __func__,
-					ret);
-			return;
+		/* In order to avoid overflow, use the microsecond version
+		 * of pwm_config if the pwm_period is greater than or equal
+		 * to 1 second.
+		 */
+		if (edp_drv->pwm_period >= USEC_PER_SEC) {
+			ret = pwm_config_us(edp_drv->bl_pwm,
+					bl_level * edp_drv->pwm_period / bl_max,
+					edp_drv->pwm_period);
+			if (ret) {
+				pr_err("%s: pwm_config_us() failed err=%d.\n",
+						__func__, ret);
+				return;
+			}
+		} else {
+			period_ns = edp_drv->pwm_period * NSEC_PER_USEC;
+			ret = pwm_config(edp_drv->bl_pwm,
+					bl_level * period_ns / bl_max,
+					period_ns);
+			if (ret) {
+				pr_err("%s: pwm_config() failed err=%d.\n",
+						__func__, ret);
+				return;
+			}
 		}
 
 		ret = pwm_enable(edp_drv->bl_pwm);
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 77080e8..08cdcef 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -123,7 +123,7 @@
 
 	if (notify == NOTIFY_UPDATE_START) {
 		INIT_COMPLETION(mfd->update.comp);
-		ret = wait_for_completion_interruptible_timeout(
+		ret = wait_for_completion_timeout(
 						&mfd->update.comp, 4 * HZ);
 		to_user = (unsigned int)mfd->update.value;
 		if (mfd->update.type == NOTIFY_TYPE_SUSPEND) {
@@ -132,13 +132,13 @@
 		}
 	} else if (notify == NOTIFY_UPDATE_STOP) {
 		INIT_COMPLETION(mfd->no_update.comp);
-		ret = wait_for_completion_interruptible_timeout(
+		ret = wait_for_completion_timeout(
 						&mfd->no_update.comp, 4 * HZ);
 		to_user = (unsigned int)mfd->no_update.value;
 	} else {
 		if (mfd->panel_power_on) {
 			INIT_COMPLETION(mfd->power_off_comp);
-			ret = wait_for_completion_interruptible_timeout(
+			ret = wait_for_completion_timeout(
 						&mfd->power_off_comp, 1 * HZ);
 		}
 	}
diff --git a/drivers/video/msm/mdss/mdss_hdmi_cec.c b/drivers/video/msm/mdss/mdss_hdmi_cec.c
index 410f2b3..9d85070 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_cec.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_cec.c
@@ -366,7 +366,7 @@
 	DSS_REG_W(io, HDMI_CEC_CTRL, BIT(0) | BIT(1) |
 		((msg->frame_size & 0x1F) << 4) | BIT(9));
 
-	if (!wait_for_completion_interruptible_timeout(
+	if (!wait_for_completion_timeout(
 		&cec_ctrl->cec_msg_wr_done, HZ)) {
 		DEV_ERR("%s: timedout", __func__);
 		hdmi_cec_dump_msg(cec_ctrl, msg);
diff --git a/drivers/video/msm/mdss/mdss_hdmi_hdcp.c b/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
index 8ff9059..e56e9fa 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
@@ -520,7 +520,7 @@
 	/* Write R0' to HDCP registers and check to see if it is a match */
 	INIT_COMPLETION(hdcp_ctrl->r0_checked);
 	DSS_REG_W(io, HDMI_HDCP_RCVPORT_DATA2_0, (((u32)buf[1]) << 8) | buf[0]);
-	timeout_count = wait_for_completion_interruptible_timeout(
+	timeout_count = wait_for_completion_timeout(
 		&hdcp_ctrl->r0_checked, HZ*2);
 	link0_status = DSS_REG_R(io, HDMI_HDCP_LINK0_STATUS);
 	is_match = link0_status & BIT(12);
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index 99f45ed..a29fb751 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -2536,7 +2536,7 @@
 	flush_work_sync(&hdmi_ctrl->power_off_work);
 
 	if (hdmi_ctrl->pdata.primary) {
-		timeout = wait_for_completion_interruptible_timeout(
+		timeout = wait_for_completion_timeout(
 			&hdmi_ctrl->hpd_done, HZ);
 		if (!timeout) {
 			DEV_ERR("%s: cable connection hasn't happened yet\n",
@@ -3003,7 +3003,7 @@
 			u32 timeout;
 			hdmi_ctrl->panel_suspend = false;
 
-			timeout = wait_for_completion_interruptible_timeout(
+			timeout = wait_for_completion_timeout(
 				&hdmi_ctrl->hpd_done, HZ/10);
 			if (!timeout & !hdmi_ctrl->hpd_state) {
 				DEV_INFO("%s: cable removed during suspend\n",
diff --git a/drivers/video/msm/mdss/mdss_hdmi_util.c b/drivers/video/msm/mdss/mdss_hdmi_util.c
index 711ec68..de422a4 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_util.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_util.c
@@ -296,7 +296,7 @@
 	INIT_COMPLETION(ddc_ctrl->ddc_sw_done);
 	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(0) | BIT(20));
 
-	time_out_count = wait_for_completion_interruptible_timeout(
+	time_out_count = wait_for_completion_timeout(
 		&ddc_ctrl->ddc_sw_done, HZ/2);
 	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL, BIT(1));
 	if (!time_out_count) {
@@ -547,7 +547,7 @@
 	INIT_COMPLETION(ddc_ctrl->ddc_sw_done);
 	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(0) | BIT(21));
 
-	time_out_count = wait_for_completion_interruptible_timeout(
+	time_out_count = wait_for_completion_timeout(
 		&ddc_ctrl->ddc_sw_done, HZ/2);
 
 	reg_val = DSS_REG_R(ddc_ctrl->io, HDMI_DDC_INT_CTRL);
@@ -721,7 +721,7 @@
 	INIT_COMPLETION(ddc_ctrl->ddc_sw_done);
 	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(0) | BIT(20));
 
-	time_out_count = wait_for_completion_interruptible_timeout(
+	time_out_count = wait_for_completion_timeout(
 		&ddc_ctrl->ddc_sw_done, HZ/2);
 
 	reg_val = DSS_REG_R(ddc_ctrl->io, HDMI_DDC_INT_CTRL);
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index 131744c..e843a78 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -1136,6 +1136,7 @@
 	mdata->pdev = pdev;
 	platform_set_drvdata(pdev, mdata);
 	mdss_res = mdata;
+	mutex_init(&mdata->reg_lock);
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mdp_phys");
 	if (!res) {
@@ -1234,6 +1235,7 @@
 	if (IS_ERR_VALUE(rc)) {
 		mdss_mdp_hw.ptr = NULL;
 		mdss_mdp_pp_term(&pdev->dev);
+		mutex_destroy(&mdata->reg_lock);
 		mdss_res = NULL;
 	}
 
@@ -1552,8 +1554,8 @@
 {
 	u32 npipes, dma_off;
 	int rc = 0;
-	u32 nids = 0, setup_cnt = 0, len;
-	u32 *offsets = NULL, *ftch_id = NULL;
+	u32 nfids = 0, setup_cnt = 0, len, nxids = 0;
+	u32 *offsets = NULL, *ftch_id = NULL, *xin_id = NULL;
 
 	struct mdss_data_type *mdata = platform_get_drvdata(pdev);
 
@@ -1564,33 +1566,47 @@
 	mdata->ndma_pipes = mdss_mdp_parse_dt_prop_len(pdev,
 				"qcom,mdss-pipe-dma-off");
 
-	nids  += mdss_mdp_parse_dt_prop_len(pdev,
-			"qcom,mdss-pipe-vig-fetch-id");
-	nids  += mdss_mdp_parse_dt_prop_len(pdev,
-			"qcom,mdss-pipe-rgb-fetch-id");
-	nids  += mdss_mdp_parse_dt_prop_len(pdev,
-			"qcom,mdss-pipe-dma-fetch-id");
-
 	npipes = mdata->nvig_pipes + mdata->nrgb_pipes + mdata->ndma_pipes;
 
-	if (npipes != nids) {
+	nfids  += mdss_mdp_parse_dt_prop_len(pdev,
+			"qcom,mdss-pipe-vig-fetch-id");
+	nfids  += mdss_mdp_parse_dt_prop_len(pdev,
+			"qcom,mdss-pipe-rgb-fetch-id");
+	nfids  += mdss_mdp_parse_dt_prop_len(pdev,
+			"qcom,mdss-pipe-dma-fetch-id");
+	if (npipes != nfids) {
 		pr_err("device tree err: unequal number of pipes and smp ids");
 		return -EINVAL;
 	}
 
+	nxids += mdss_mdp_parse_dt_prop_len(pdev, "qcom,mdss-pipe-vig-xin-id");
+	nxids += mdss_mdp_parse_dt_prop_len(pdev, "qcom,mdss-pipe-rgb-xin-id");
+	nxids += mdss_mdp_parse_dt_prop_len(pdev, "qcom,mdss-pipe-dma-xin-id");
+	if (npipes != nxids) {
+		pr_err("device tree err: unequal number of pipes and xin ids");
+		return -EINVAL;
+	}
+
 	offsets = kzalloc(sizeof(u32) * npipes, GFP_KERNEL);
 	if (!offsets) {
 		pr_err("no mem assigned for offsets: kzalloc fail\n");
 		return -ENOMEM;
 	}
 
-	ftch_id = kzalloc(sizeof(u32) * nids, GFP_KERNEL);
+	ftch_id = kzalloc(sizeof(u32) * nfids, GFP_KERNEL);
 	if (!ftch_id) {
 		pr_err("no mem assigned for ftch_id: kzalloc fail\n");
 		rc = -ENOMEM;
 		goto ftch_alloc_fail;
 	}
 
+	xin_id = kzalloc(sizeof(u32) * nxids, GFP_KERNEL);
+	if (!xin_id) {
+		pr_err("no mem assigned for xin_id: kzalloc fail\n");
+		rc = -ENOMEM;
+		goto xin_alloc_fail;
+	}
+
 	mdata->vig_pipes = devm_kzalloc(&mdata->pdev->dev,
 		sizeof(struct mdss_mdp_pipe) * mdata->nvig_pipes, GFP_KERNEL);
 	if (!mdata->vig_pipes) {
@@ -1618,7 +1634,12 @@
 	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-pipe-vig-fetch-id",
 		ftch_id, mdata->nvig_pipes);
 	if (rc)
-		goto parse_done;
+		goto parse_fail;
+
+	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-pipe-vig-xin-id",
+		xin_id, mdata->nvig_pipes);
+	if (rc)
+		goto parse_fail;
 
 	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-pipe-vig-off",
 		offsets, mdata->nvig_pipes);
@@ -1627,7 +1648,7 @@
 
 	len = min_t(int, DEFAULT_TOTAL_VIG_PIPES, (int)mdata->nvig_pipes);
 	rc = mdss_mdp_pipe_addr_setup(mdata, mdata->vig_pipes, offsets, ftch_id,
-		MDSS_MDP_PIPE_TYPE_VIG, MDSS_MDP_SSPP_VIG0, len);
+		xin_id, MDSS_MDP_PIPE_TYPE_VIG, MDSS_MDP_SSPP_VIG0, len);
 	if (rc)
 		goto parse_fail;
 
@@ -1638,6 +1659,11 @@
 	if (rc)
 		goto parse_fail;
 
+	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-pipe-rgb-xin-id",
+		xin_id + mdata->nvig_pipes, mdata->nrgb_pipes);
+	if (rc)
+		goto parse_fail;
+
 	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-pipe-rgb-off",
 		offsets + mdata->nvig_pipes, mdata->nrgb_pipes);
 	if (rc)
@@ -1646,7 +1672,8 @@
 	len = min_t(int, DEFAULT_TOTAL_RGB_PIPES, (int)mdata->nrgb_pipes);
 	rc = mdss_mdp_pipe_addr_setup(mdata, mdata->rgb_pipes,
 		offsets + mdata->nvig_pipes, ftch_id + mdata->nvig_pipes,
-		MDSS_MDP_PIPE_TYPE_RGB, MDSS_MDP_SSPP_RGB0, len);
+		xin_id + mdata->nvig_pipes, MDSS_MDP_PIPE_TYPE_RGB,
+		MDSS_MDP_SSPP_RGB0, len);
 	if (rc)
 		goto parse_fail;
 
@@ -1658,6 +1685,11 @@
 	if (rc)
 		goto parse_fail;
 
+	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-pipe-dma-xin-id",
+		xin_id + dma_off, mdata->ndma_pipes);
+	if (rc)
+		goto parse_fail;
+
 	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-pipe-dma-off",
 		offsets + dma_off, mdata->ndma_pipes);
 	if (rc)
@@ -1665,8 +1697,8 @@
 
 	len = mdata->ndma_pipes;
 	rc = mdss_mdp_pipe_addr_setup(mdata, mdata->dma_pipes,
-		 offsets + dma_off, ftch_id + dma_off, MDSS_MDP_PIPE_TYPE_DMA,
-		 MDSS_MDP_SSPP_DMA0, len);
+		offsets + dma_off, ftch_id + dma_off, xin_id + dma_off,
+		MDSS_MDP_PIPE_TYPE_DMA, MDSS_MDP_SSPP_DMA0, len);
 	if (rc)
 		goto parse_fail;
 
@@ -1677,6 +1709,7 @@
 			mdata->vig_pipes + DEFAULT_TOTAL_VIG_PIPES,
 			offsets + DEFAULT_TOTAL_VIG_PIPES,
 			ftch_id + DEFAULT_TOTAL_VIG_PIPES,
+			xin_id + DEFAULT_TOTAL_VIG_PIPES,
 			MDSS_MDP_PIPE_TYPE_VIG, setup_cnt,
 			mdata->nvig_pipes - DEFAULT_TOTAL_VIG_PIPES);
 		if (rc)
@@ -1690,6 +1723,7 @@
 			mdata->rgb_pipes + DEFAULT_TOTAL_RGB_PIPES,
 			offsets + mdata->nvig_pipes + DEFAULT_TOTAL_RGB_PIPES,
 			ftch_id + mdata->nvig_pipes + DEFAULT_TOTAL_RGB_PIPES,
+			xin_id + mdata->nvig_pipes + DEFAULT_TOTAL_RGB_PIPES,
 			MDSS_MDP_PIPE_TYPE_RGB, setup_cnt,
 			mdata->nrgb_pipes - DEFAULT_TOTAL_RGB_PIPES);
 		if (rc)
@@ -1708,6 +1742,8 @@
 	kfree(mdata->vig_pipes);
 parse_done:
 vig_alloc_fail:
+	kfree(xin_id);
+xin_alloc_fail:
 	kfree(ftch_id);
 ftch_alloc_fail:
 	kfree(offsets);
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 8918df8..ed9973e 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -344,6 +344,7 @@
 	u32 ndx;
 	char __iomem *base;
 	u32 ftch_id;
+	u32 xin_id;
 	atomic_t ref_cnt;
 	u32 play_cnt;
 	int pid;
@@ -368,7 +369,6 @@
 	u8 overfetch_disable;
 	u32 transp;
 	u32 bg_color;
-	u8 has_buf;
 
 	struct msm_fb_data_type *mfd;
 	struct mdss_mdp_mixer *mixer;
@@ -603,8 +603,8 @@
 void mdss_mdp_smp_release(struct mdss_mdp_pipe *pipe);
 
 int mdss_mdp_pipe_addr_setup(struct mdss_data_type *mdata,
-	struct mdss_mdp_pipe *head, u32 *offsets, u32 *ftch_y_id, u32 type,
-	u32 num_base, u32 len);
+	struct mdss_mdp_pipe *head, u32 *offsets, u32 *ftch_y_id, u32 *xin_id,
+	u32 type, u32 num_base, u32 len);
 int mdss_mdp_mixer_addr_setup(struct mdss_data_type *mdata, u32 *mixer_offsets,
 		u32 *dspp_offsets, u32 *pingpong_offsets, u32 type, u32 len);
 int mdss_mdp_ctl_addr_setup(struct mdss_data_type *mdata, u32 *ctl_offsets,
@@ -613,6 +613,7 @@
 int mdss_mdp_pipe_destroy(struct mdss_mdp_pipe *pipe);
 int mdss_mdp_pipe_queue_data(struct mdss_mdp_pipe *pipe,
 			     struct mdss_mdp_data *src_data);
+int mdss_mdp_pipe_fetch_halt(struct mdss_mdp_pipe *pipe);
 
 int mdss_mdp_data_check(struct mdss_mdp_data *data,
 			struct mdss_mdp_plane_sizes *ps);
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index d57e4fb..db67773 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1459,6 +1459,8 @@
 
 	if (mixer->num == MDSS_MDP_INTF_LAYERMIXER3)
 		ctl->flush_bits |= BIT(20);
+	else if (mixer->type == MDSS_MDP_MIXER_TYPE_WRITEBACK)
+		ctl->flush_bits |= BIT(9) << mixer->num;
 	else
 		ctl->flush_bits |= BIT(6) << mixer->num;
 
diff --git a/drivers/video/msm/mdss/mdss_mdp_hwio.h b/drivers/video/msm/mdss/mdss_mdp_hwio.h
index 5d3e841..9948738 100644
--- a/drivers/video/msm/mdss/mdss_mdp_hwio.h
+++ b/drivers/video/msm/mdss/mdss_mdp_hwio.h
@@ -580,4 +580,8 @@
 #define MDSS_MDP_LP_MISR_SEL_LMIX4_BLEND	0x10
 #define MDSS_MDP_LP_MISR_SEL_LMIX4_GC		0x11
 
+/* following offsets are with respect to MDP VBIF base */
+#define MMSS_VBIF_XIN_HALT_CTRL0	0x200
+#define MMSS_VBIF_XIN_HALT_CTRL1	0x204
+
 #endif
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
index c4a0645..ae45587 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -427,9 +427,6 @@
 
 	pdata->panel_info.cont_splash_enabled = 0;
 
-	ret = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_CONT_SPLASH_FINISH,
-			NULL);
-
 	mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_PANEL_CLK_CTRL, (void *)0);
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
 
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index 572af1c..8da775b 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -604,7 +604,6 @@
 	}
 
 	pipe->params_changed++;
-	pipe->has_buf = 0;
 
 	req->vert_deci = pipe->vert_deci;
 
@@ -762,6 +761,7 @@
 	list_for_each_entry_safe(pipe, tmp, &mdp5_data->pipes_cleanup,
 				cleanup_list) {
 		list_move(&pipe->cleanup_list, &destroy_pipes);
+		mdss_mdp_pipe_fetch_halt(pipe);
 		mdss_mdp_overlay_free_buf(&pipe->back_buf);
 		__mdss_mdp_overlay_free_list_add(mfd, &pipe->front_buf);
 		pipe->mfd = NULL;
@@ -835,8 +835,7 @@
 	if (ctl->power_on) {
 		if (!mdp5_data->mdata->batfet)
 			mdss_mdp_batfet_ctrl(mdp5_data->mdata, true);
-		if (!is_mdss_iommu_attached() &&
-					!mfd->panel_info->cont_splash_enabled)
+		if (!mfd->panel_info->cont_splash_enabled)
 			mdss_iommu_attach(mdp5_data->mdata);
 		return 0;
 	}
@@ -956,9 +955,6 @@
 	int ret = 0;
 	int sd_in_pipe = 0;
 
-	if (!is_mdss_iommu_attached() && !mfd->panel_info->cont_splash_enabled)
-		mdss_iommu_attach(mdp5_data->mdata);
-
 	if (ctl->shared_lock)
 		mutex_lock(ctl->shared_lock);
 
@@ -1258,9 +1254,15 @@
 
 	pr_debug("ov queue pnum=%d\n", pipe->num);
 
+	if (pipe->flags & MDP_SOLID_FILL)
+		pr_warn("Unexpected buffer queue to a solid fill pipe\n");
+
 	flags = (pipe->flags & MDP_SECURE_OVERLAY_SESSION);
 	flags |= (pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION);
 
+	if (!mfd->panel_info->cont_splash_enabled)
+		mdss_iommu_attach(mdata);
+
 	src_data = &pipe->back_buf;
 	if (src_data->num_planes) {
 		pr_warn("dropped buffer pnum=%d play=%d addr=0x%x\n",
@@ -1272,7 +1274,6 @@
 	if (IS_ERR_VALUE(ret)) {
 		pr_err("src_data pmem error\n");
 	}
-	pipe->has_buf = 1;
 	mdss_mdp_pipe_unmap(pipe);
 
 	return ret;
@@ -1544,7 +1545,6 @@
 	else
 		buf->p[0].len = fbi->fix.smem_len - offset;
 	buf->num_planes = 1;
-	pipe->has_buf = 1;
 	mdss_mdp_pipe_unmap(pipe);
 
 	if (fbi->var.xres > MAX_MIXER_WIDTH || mfd->split_display) {
@@ -1562,7 +1562,6 @@
 			pipe_ndx[1] = pipe->ndx;
 
 		pipe->back_buf = *buf;
-		pipe->has_buf = 1;
 		mdss_mdp_pipe_unmap(pipe);
 	}
 	mutex_unlock(&mdp5_data->ov_lock);
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index 0abd4d5..88a2a69 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -15,6 +15,7 @@
 
 #include <linux/bitmap.h>
 #include <linux/errno.h>
+#include <linux/iopoll.h>
 #include <linux/mutex.h>
 
 #include "mdss_mdp.h"
@@ -25,6 +26,8 @@
 #define SMP_MB_ENTRY_SIZE	16
 #define MAX_BPP 4
 
+#define PIPE_HALT_TIMEOUT_US	0x4000
+
 static DEFINE_MUTEX(mdss_mdp_sspp_lock);
 static DEFINE_MUTEX(mdss_mdp_smp_lock);
 
@@ -176,6 +179,31 @@
 			pipe->src_fmt, &ps);
 		if (rc)
 			return rc;
+		/*
+		 * Override fetch strides with SMP buffer size for both the
+		 * planes
+		 */
+		if (pipe->src_fmt->fetch_planes == MDSS_MDP_PLANE_INTERLEAVED) {
+			/*
+			 * BWC line buffer needs to be divided into 16
+			 * segments and every segment is aligned to format
+			 * specific RAU size
+			 */
+			ps.ystride[0] = ALIGN(pipe->src.w / 16 , 32) * 16 *
+				ps.rau_h[0] * pipe->src_fmt->bpp;
+			ps.ystride[1] = 0;
+		} else {
+			u32 bwc_width = ALIGN(pipe->src.w / 16, 64) * 16;
+			ps.ystride[0] = bwc_width * ps.rau_h[0];
+			ps.ystride[1] = bwc_width * ps.rau_h[1];
+			/*
+			 * Since chroma for H1V2 is not subsampled it needs
+			 * to be accounted for with bpp factor
+			 */
+			if (pipe->src_fmt->chroma_sample ==
+				MDSS_MDP_CHROMA_H1V2)
+				ps.ystride[1] *= 2;
+		}
 		pr_debug("BWC SMP strides ystride0=%x ystride1=%x\n",
 			ps.ystride[0], ps.ystride[1]);
 	} else {
@@ -460,6 +488,13 @@
 		pipe = NULL;
 	}
 
+	if (pipe && mdss_mdp_pipe_fetch_halt(pipe)) {
+		pr_err("%d failed because vbif client is in bad state\n",
+			pipe->num);
+		atomic_dec(&pipe->ref_cnt);
+		return NULL;
+	}
+
 	if (pipe) {
 		pr_debug("type=%x   pnum=%d\n", pipe->type, pipe->num);
 		mutex_init(&pipe->pp_res.hist.hist_mutex);
@@ -596,6 +631,64 @@
 	return 0;
 }
 
+/**
+ * mdss_mdp_pipe_fetch_halt() - Halt VBIF client corresponding to specified pipe
+ * @pipe: pointer to the pipe data structure which needs to be halted.
+ *
+ * Check if VBIF client corresponding to specified pipe is idle or not. If not
+ * send a halt request for the client in question and wait for it be idle.
+ *
+ * This function would typically be called after pipe is unstaged or before it
+ * is initialized. On success it should be assumed that pipe is in idle state
+ * and would not fetch any more data. This function cannot be called from
+ * interrupt context.
+ */
+int mdss_mdp_pipe_fetch_halt(struct mdss_mdp_pipe *pipe)
+{
+	bool is_idle;
+	int rc = 0;
+	u32 reg_val, idle_mask, status;
+	struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+
+	idle_mask = BIT(pipe->xin_id + 16);
+	reg_val = readl_relaxed(mdata->vbif_base + MMSS_VBIF_XIN_HALT_CTRL1);
+
+	is_idle = (reg_val & idle_mask) ? true : false;
+	if (!is_idle) {
+		pr_debug("%pS: pipe%d is not idle. xin_id=%d halt_ctrl1=0x%x\n",
+			__builtin_return_address(0), pipe->num, pipe->xin_id,
+			reg_val);
+
+		mutex_lock(&mdata->reg_lock);
+		reg_val = readl_relaxed(mdata->vbif_base +
+			MMSS_VBIF_XIN_HALT_CTRL0);
+		writel_relaxed(reg_val | BIT(pipe->xin_id),
+			mdata->vbif_base + MMSS_VBIF_XIN_HALT_CTRL0);
+		mutex_unlock(&mdata->reg_lock);
+
+		rc = readl_poll_timeout(mdata->vbif_base +
+			MMSS_VBIF_XIN_HALT_CTRL1, status, (status & idle_mask),
+			1000, PIPE_HALT_TIMEOUT_US);
+		if (rc == -ETIMEDOUT)
+			pr_err("VBIF client %d not halting. TIMEDOUT.\n",
+				pipe->xin_id);
+		else
+			pr_debug("VBIF client %d is halted\n", pipe->xin_id);
+
+		mutex_lock(&mdata->reg_lock);
+		reg_val = readl_relaxed(mdata->vbif_base +
+			MMSS_VBIF_XIN_HALT_CTRL0);
+		writel_relaxed(reg_val & ~BIT(pipe->xin_id),
+			mdata->vbif_base + MMSS_VBIF_XIN_HALT_CTRL0);
+		mutex_unlock(&mdata->reg_lock);
+	}
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+
+	return rc;
+}
+
 int mdss_mdp_pipe_destroy(struct mdss_mdp_pipe *pipe)
 {
 	int tmp;
@@ -853,8 +946,8 @@
 }
 
 int mdss_mdp_pipe_addr_setup(struct mdss_data_type *mdata,
-	struct mdss_mdp_pipe *head, u32 *offsets, u32 *ftch_id, u32 type,
-	u32 num_base, u32 len)
+	struct mdss_mdp_pipe *head, u32 *offsets, u32 *ftch_id, u32 *xin_id,
+	u32 type, u32 num_base, u32 len)
 {
 	u32 i;
 
@@ -866,6 +959,7 @@
 	for (i = 0; i < len; i++) {
 		head[i].type = type;
 		head[i].ftch_id  = ftch_id[i];
+		head[i].xin_id = xin_id[i];
 		head[i].num = i + num_base;
 		head[i].ndx = BIT(i + num_base);
 		head[i].base = mdata->mdp_base + offsets[i];
@@ -972,7 +1066,7 @@
 			 (pipe->mixer->type == MDSS_MDP_MIXER_TYPE_WRITEBACK)
 			 && (ctl->mdata->mixer_switched)) ||
 			 ctl->roi_changed;
-	if (src_data == NULL || !pipe->has_buf) {
+	if (src_data == NULL || (pipe->flags & MDP_SOLID_FILL)) {
 		pipe->params_changed = 0;
 		mdss_mdp_pipe_solidfill_setup(pipe);
 		goto update_nobuf;
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index e99fa49..87f0779 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -3962,7 +3962,7 @@
 			mutex_unlock(&ad->lock);
 		}
 		if (wait) {
-			ret = wait_for_completion_interruptible_timeout(
+			ret = wait_for_completion_timeout(
 					&ad->comp, HIST_WAIT_TIMEOUT(1));
 			if (ret == 0)
 				ret = -ETIMEDOUT;
diff --git a/drivers/video/msm/mdss/mdss_mdp_rotator.c b/drivers/video/msm/mdss/mdss_mdp_rotator.c
index 883a728..588e217 100644
--- a/drivers/video/msm/mdss/mdss_mdp_rotator.c
+++ b/drivers/video/msm/mdss/mdss_mdp_rotator.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -48,6 +48,8 @@
 			rot->ref_cnt++;
 			rot->session_id = i | MDSS_MDP_ROT_SESSION_MASK;
 			mutex_init(&rot->lock);
+			INIT_LIST_HEAD(&rot->head);
+			INIT_LIST_HEAD(&rot->list);
 			break;
 		}
 	}
@@ -104,8 +106,11 @@
 	if (!pipe) {
 		mdss_mdp_wb_mixer_destroy(mixer);
 		pr_debug("dma pipe allocation failed\n");
+		return NULL;
 	}
 
+	pipe->mixer_stage = MDSS_MDP_STAGE_UNUSED;
+
 	return pipe;
 }
 
@@ -125,7 +130,6 @@
 		if (ctl->shared_lock)
 			mutex_unlock(ctl->shared_lock);
 	}
-	mdss_mdp_smp_release(rot->pipe);
 	mutex_unlock(&rot->lock);
 
 	return 0;
@@ -167,7 +171,6 @@
 		if (rot->pipe) {
 			pr_debug("use new rotator pipe=%d\n", rot->pipe->num);
 
-			rot->pipe->mixer_stage = MDSS_MDP_STAGE_UNUSED;
 			list_add_tail(&rot->head, &rotator_queue);
 		} else if (!list_empty(&rotator_queue)) {
 			tmp = list_first_entry(&rotator_queue,
@@ -197,6 +200,45 @@
 	return 0;
 }
 
+/**
+ * __mdss_mdp_rotator_to_pipe() - setup pipe according to rotator session params
+ * @rot:	Pointer to rotator session
+ * @pipe:	Pointer to pipe driving structure
+ *
+ * After calling this the pipe structure will contain all parameters required
+ * to use rotator pipe. Note that this function assumes rotator pipe is idle.
+ */
+static int __mdss_mdp_rotator_to_pipe(struct mdss_mdp_rotator_session *rot,
+		struct mdss_mdp_pipe *pipe)
+{
+	int ret;
+
+	pipe->flags = rot->flags;
+	pipe->src_fmt = mdss_mdp_get_format_params(rot->format);
+	pipe->img_width = rot->img_width;
+	pipe->img_height = rot->img_height;
+	pipe->src = rot->src_rect;
+	pipe->dst = rot->src_rect;
+	pipe->dst.x = 0;
+	pipe->dst.y = 0;
+	pipe->params_changed++;
+	rot->params_changed = 0;
+
+	/*
+	 * Clear previous SMP reservations and reserve according
+	 * to the latest configuration
+	 */
+	mdss_mdp_smp_unreserve(pipe);
+
+	ret = mdss_mdp_smp_reserve(pipe);
+	if (ret) {
+		pr_err("unable to mdss_mdp_smp_reserve rot data\n");
+		return ret;
+	}
+
+	return 0;
+}
+
 static int mdss_mdp_rotator_queue_sub(struct mdss_mdp_rotator_session *rot,
 			   struct mdss_mdp_data *src_data,
 			   struct mdss_mdp_data *dst_data)
@@ -232,28 +274,17 @@
 	}
 
 	if (rot->params_changed || rot_ctl->mdata->mixer_switched) {
-		rot->params_changed = 0;
-		rot_pipe->flags = rot->flags;
-		rot_pipe->src_fmt = mdss_mdp_get_format_params(rot->format);
-		rot_pipe->img_width = rot->img_width;
-		rot_pipe->img_height = rot->img_height;
-		rot_pipe->src = rot->src_rect;
-		rot_pipe->dst = rot->src_rect;
-		rot_pipe->dst.x = 0;
-		rot_pipe->dst.y = 0;
-		rot_pipe->params_changed++;
+		ret = __mdss_mdp_rotator_to_pipe(rot, rot_pipe);
+		if (ret) {
+			pr_err("rotator session=%x to pipe=%d failed %d\n",
+					rot->session_id, rot_pipe->num, ret);
+			goto error;
+		}
 	}
 
-	ret = mdss_mdp_smp_reserve(rot->pipe);
-	if (ret) {
-		pr_err("unable to mdss_mdp_smp_reserve rot data\n");
-		goto error;
-	}
-
-	ret = mdss_mdp_pipe_queue_data(rot->pipe, src_data);
+	ret = mdss_mdp_pipe_queue_data(rot_pipe, src_data);
 	if (ret) {
 		pr_err("unable to queue rot data\n");
-		mdss_mdp_smp_unreserve(rot->pipe);
 		goto error;
 	}
 
@@ -367,6 +398,45 @@
 	return ret;
 }
 
+/*
+ * Try to reserve hardware resources for rotator session if possible, if this
+ * is not possible we may still have a chance to reuse existing pipes used by
+ * other sessions at a later point.
+ */
+static int __mdss_mdp_rotator_pipe_reserve(struct mdss_mdp_rotator_session *rot)
+{
+	int ret;
+
+	if (!rot->pipe) {
+		rot->pipe = mdss_mdp_rotator_pipe_alloc();
+		if (rot->pipe) {
+			pr_debug("reserved rotator pipe=%d\n", rot->pipe->num);
+			list_add_tail(&rot->head, &rotator_queue);
+		} else {
+			/*
+			 * if rotator queue is not empty means that we'll be
+			 * able to reuse existing rotator pipes for this rotator
+			 * session, otherwise it means that there are no DMA
+			 * pipes available so we should abort now
+			 */
+			if (list_empty(&rotator_queue)) {
+				pr_err("unable to reserve rot pipe\n");
+				return -ENODEV;
+			}
+
+			pr_debug("unable to get rot pipe but some in queue\n");
+			return 0;
+		}
+	}
+
+	ret = __mdss_mdp_rotator_to_pipe(rot, rot->pipe);
+	if (ret)
+		pr_err("rotator session=%x to pipe=%d failed %d\n",
+				rot->session_id, rot->pipe->num, ret);
+
+	return ret;
+}
+
 int mdss_mdp_rotator_setup(struct msm_fb_data_type *mfd,
 			   struct mdp_overlay *req)
 {
@@ -391,14 +461,14 @@
 
 	if (req->id == MSMFB_NEW_REQUEST) {
 		rot = mdss_mdp_rotator_session_alloc();
-		rot->pid = current->tgid;
-		list_add(&rot->list, &mdp5_data->rot_proc_list);
-
 		if (!rot) {
 			pr_err("unable to allocate rotator session\n");
 			ret = -ENOMEM;
 			goto rot_err;
 		}
+
+		rot->pid = current->tgid;
+		list_add(&rot->list, &mdp5_data->rot_proc_list);
 	} else if (req->id & MDSS_MDP_ROT_SESSION_MASK) {
 		rot = mdss_mdp_rotator_session_get(req->id);
 
@@ -526,15 +596,22 @@
 
 	rot->params_changed++;
 
+	ret = __mdss_mdp_rotator_pipe_reserve(rot);
+	if (!ret && rot->next)
+		ret = __mdss_mdp_rotator_pipe_reserve(rot->next);
+
+	if (ret)
+		goto rot_err;
+
 	req->id = rot->session_id;
 
  rot_err:
-	mutex_unlock(&rotator_lock);
 	if (ret) {
 		pr_err("Unable to setup rotator session\n");
-		if (rot)
-			mdss_mdp_rotator_release(rot);
+		if (rot && (req->id == MSMFB_NEW_REQUEST))
+			mdss_mdp_rotator_finish(rot);
 	}
+	mutex_unlock(&rotator_lock);
 	return ret;
 }
 
@@ -560,6 +637,9 @@
 		list_del(&rot->head);
 	}
 
+	if (!list_empty(&rot->list))
+		list_del(&rot->list);
+
 	rot_sync_pt_data = rot->rot_sync_pt_data;
 	commit_work = rot->commit_work;
 	memset(rot, 0, sizeof(*rot));
@@ -616,6 +696,7 @@
 			    struct msmfb_overlay_data *req)
 {
 	struct mdss_mdp_rotator_session *rot;
+	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
 	int ret;
 	u32 flgs;
 
@@ -635,6 +716,9 @@
 		goto dst_buf_fail;
 	}
 
+	if (!mfd->panel_info->cont_splash_enabled)
+		mdss_iommu_attach(mdp5_data->mdata);
+
 	mdss_mdp_overlay_free_buf(&rot->src_buf);
 	ret = mdss_mdp_overlay_get_buf(mfd, &rot->src_buf, &req->data, 1, flgs);
 	if (ret) {
@@ -671,8 +755,6 @@
 		mdss_mdp_overlay_free_buf(&rot->dst_buf);
 
 		rot->pid = 0;
-		if (!list_empty(&rot->list))
-			list_del_init(&rot->list);
 		ret = mdss_mdp_rotator_finish(rot);
 	}
 	mutex_unlock(&rotator_lock);
diff --git a/drivers/video/msm/mdss/mdss_mdp_wb.c b/drivers/video/msm/mdss/mdss_mdp_wb.c
index 5789341..dc791d9 100644
--- a/drivers/video/msm/mdss/mdss_mdp_wb.c
+++ b/drivers/video/msm/mdss/mdss_mdp_wb.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -438,6 +438,7 @@
 {
 	struct mdss_mdp_wb *wb = mfd_to_wb(mfd);
 	struct mdss_mdp_wb_data *node = NULL;
+	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
 	int ret = 0;
 
 	if (!wb) {
@@ -447,6 +448,9 @@
 
 	pr_debug("fb%d queue\n", wb->fb_ndx);
 
+	if (!mfd->panel_info->cont_splash_enabled)
+		mdss_iommu_attach(mdp5_data->mdata);
+
 	mutex_lock(&wb->lock);
 	if (local)
 		node = get_local_node(wb, data);
diff --git a/drivers/video/msm/mdss/mdss_qpic.c b/drivers/video/msm/mdss/mdss_qpic.c
index fa6bd3d..54b837a 100644
--- a/drivers/video/msm/mdss/mdss_qpic.c
+++ b/drivers/video/msm/mdss/mdss_qpic.c
@@ -368,7 +368,7 @@
 		phys_addr += block_len;
 		len -= block_len;
 	}
-	ret = wait_for_completion_interruptible_timeout(
+	ret = wait_for_completion_timeout(
 		&qpic_res->qpic_endpt.completion,
 		msecs_to_jiffies(100 * 4));
 	if (ret <= 0)
diff --git a/drivers/video/msm/mdss/mhl_sii8334.c b/drivers/video/msm/mdss/mhl_sii8334.c
index ab01566..1f728e0 100644
--- a/drivers/video/msm/mdss/mhl_sii8334.c
+++ b/drivers/video/msm/mdss/mhl_sii8334.c
@@ -364,7 +364,7 @@
 	 * after toggling reset line and enabling disc
 	 * tx can take a while to generate intr
 	 */
-	timeout = wait_for_completion_interruptible_timeout
+	timeout = wait_for_completion_timeout
 		(&mhl_ctrl->rgnd_done, HZ * 3);
 	if (!timeout) {
 		/*
@@ -1274,7 +1274,7 @@
 
 	INIT_COMPLETION(mhl_ctrl->msc_cmd_done);
 	MHL_SII_REG_NAME_WR(REG_CBUS_PRI_START, start_bit);
-	timeout = wait_for_completion_interruptible_timeout
+	timeout = wait_for_completion_timeout
 		(&mhl_ctrl->msc_cmd_done, msecs_to_jiffies(T_ABORT_NEXT));
 	if (!timeout) {
 		pr_err("%s: cbus_command_send timed out!\n", __func__);
diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h
index d00847a..c65599e 100644
--- a/include/linux/devfreq.h
+++ b/include/linux/devfreq.h
@@ -51,6 +51,7 @@
  * bound (greatest lower bound)
  */
 #define DEVFREQ_FLAG_LEAST_UPPER_BOUND		0x1
+#define DEVFREQ_FLAG_WAKEUP_MAXFREQ		0x2
 
 #define DEVFREQ_FLAG_FAST_HINT	0x2
 #define DEVFREQ_FLAG_SLOW_HINT	0x4
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 121a00c..b7f9b86 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -169,7 +169,7 @@
 #define MDP_BLUR 0x10
 #define MDP_BLEND_FG_PREMULT 0x20000
 #define MDP_IS_FG 0x40000
-#define MDP_SOLID_FILL 0x0000100
+#define MDP_SOLID_FILL 0x00000020
 #define MDP_DEINTERLACE 0x80000000
 #define MDP_SHARPENING  0x40000000
 #define MDP_NO_DMA_BARRIER_START	0x20000000
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index ddbb6a9..289754e 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -254,8 +254,9 @@
 
 				exclude_host   :  1, /* don't count in host   */
 				exclude_guest  :  1, /* don't count in guest  */
+				constraint_duplicate : 1,
 
-				__reserved_1   : 43;
+				__reserved_1   : 42;
 
 	union {
 		__u32		wakeup_events;	  /* wakeup every n events */
@@ -740,6 +741,8 @@
 	int * __percpu			pmu_disable_count;
 	struct perf_cpu_context * __percpu pmu_cpu_context;
 	int				task_ctx_nr;
+	u32                             events_across_hotplug:1,
+					reserved:31;
 
 	/*
 	 * Fully disable/enable this PMU, can be used to protect from the PMI
diff --git a/include/linux/qseecom.h b/include/linux/qseecom.h
index a45c34c..8a9947e 100644
--- a/include/linux/qseecom.h
+++ b/include/linux/qseecom.h
@@ -127,6 +127,7 @@
 
 enum qseecom_key_management_usage_type {
 	QSEOS_KM_USAGE_DISK_ENCRYPTION = 0x01,
+	QSEOS_KM_USAGE_MAX
 };
 
 struct qseecom_create_key_req {
@@ -138,6 +139,12 @@
 	enum qseecom_key_management_usage_type usage;
 };
 
+struct qseecom_update_key_userinfo_req {
+	unsigned char current_hash32[QSEECOM_HASH_SIZE];
+	unsigned char new_hash32[QSEECOM_HASH_SIZE];
+	enum qseecom_key_management_usage_type usage;
+};
+
 #define SHA256_DIGEST_LENGTH	(256/8)
 /*
  * struct qseecom_save_partition_hash_req
@@ -256,4 +263,7 @@
 #define QSEECOM_IOCTL_SET_BUS_SCALING_REQ \
 	_IOWR(QSEECOM_IOC_MAGIC, 23, int)
 
+#define QSEECOM_IOCTL_UPDATE_KEY_USER_INFO_REQ \
+	_IOWR(QSEECOM_IOC_MAGIC, 24, struct qseecom_update_key_userinfo_req)
+
 #endif /* __QSEECOM_H_ */
diff --git a/include/linux/usb/Kbuild b/include/linux/usb/Kbuild
index 087d163..fe4d6da 100644
--- a/include/linux/usb/Kbuild
+++ b/include/linux/usb/Kbuild
@@ -1,4 +1,5 @@
 header-y += audio.h
+header-y += ccid_bridge.h
 header-y += cdc.h
 header-y += ch9.h
 header-y += ch11.h
diff --git a/include/linux/usb/ccid_bridge.h b/include/linux/usb/ccid_bridge.h
new file mode 100644
index 0000000..1d1b895
--- /dev/null
+++ b/include/linux/usb/ccid_bridge.h
@@ -0,0 +1,64 @@
+#ifndef __UAPI_USB_CCID_BRIDGE_H
+#define __UAPI_USB_CCID_BRIDGE_H
+
+#include <linux/ioctl.h>
+
+/**
+ * struct usb_ccid_data - Used to receive the CCID class descriptor,
+ *        clock rates and data rates supported by the device.
+ * @length: The length of the buffer.
+ * @data: The buffer as it is returned by the device for GET_DESCRIPTOR,
+ *        GET_CLOCK_FREQUENCIES and GET_DATA_RATES requests.
+ */
+struct usb_ccid_data {
+	uint8_t length;
+	void *data;
+};
+
+/**
+ * struct usb_ccid_abort - Used to abort an already sent command.
+ * @seq: The sequence number of the command.
+ * @slot: The slot of the IC, on which the command is sent.
+ */
+struct usb_ccid_abort {
+	uint8_t seq;
+	uint8_t slot;
+};
+
+#define USB_CCID_NOTIFY_SLOT_CHANGE_EVENT 1
+#define USB_CCID_HARDWARE_ERROR_EVENT 2
+#define USB_CCID_RESUME_EVENT 3
+/**
+ * struct usb_ccid_event - Used to receive notify slot change or hardware
+ *        error event.
+ * @notify: If the event is USB_CCID_NOTIFY_SLOT_CHANGE_EVENT, slot_icc_state
+ *        has the information about the current slots state.
+ * @error: If the event is USB_CCID_HARDWARE_ERROR_EVENT, error has
+ *        information about the hardware error condition.
+ */
+struct usb_ccid_event {
+	uint8_t event;
+	union {
+		struct {
+			uint8_t slot_icc_state;
+		} notify;
+
+		struct {
+			uint8_t slot;
+			uint8_t seq;
+			uint8_t error_code;
+		} error;
+	} u;
+};
+
+#define USB_CCID_GET_CLASS_DESC _IOWR('C', 0, struct usb_ccid_data)
+
+#define USB_CCID_GET_CLOCK_FREQUENCIES _IOWR('C', 1, struct usb_ccid_data)
+
+#define USB_CCID_GET_DATA_RATES _IOWR('C', 2, struct usb_ccid_data)
+
+#define USB_CCID_ABORT _IOW('C', 3, struct usb_ccid_abort)
+
+#define USB_CCID_GET_EVENT _IOR('C', 4, struct usb_ccid_event)
+
+#endif /* __UAPI_USB_CCID_BRIDGE_H */
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index 4fb20f6..f9dec0b 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -212,7 +212,8 @@
 #define	HCD_MEMORY	0x0001		/* HC regs use memory (else I/O) */
 #define	HCD_LOCAL_MEM	0x0002		/* HC needs local memory */
 #define	HCD_SHARED	0x0004		/* Two (or more) usb_hcds share HW */
-#define	HCD_OLD_ENUM	0x0008		/* HC supports short enumeration */
+#define	HCD_RT_OLD_ENUM	0x0008		/* HC supports short enumeration
+					   on root port */
 #define	HCD_USB11	0x0010		/* USB 1.1 */
 #define	HCD_USB2	0x0020		/* USB 2.0 */
 #define	HCD_USB3	0x0040		/* USB 3.0 */
diff --git a/include/linux/wcnss_wlan.h b/include/linux/wcnss_wlan.h
index 39357e0..9241b93 100644
--- a/include/linux/wcnss_wlan.h
+++ b/include/linux/wcnss_wlan.h
@@ -86,7 +86,11 @@
 {
 }
 #endif
-
+int wcnss_set_wlan_unsafe_channel(
+				u16 *unsafe_ch_list, u16 ch_count);
+int wcnss_get_wlan_unsafe_channel(
+				u16 *unsafe_ch_list, u16 buffer_size,
+				u16 *ch_count);
 #define wcnss_wlan_get_drvdata(dev) dev_get_drvdata(dev)
 #define wcnss_wlan_set_drvdata(dev, data) dev_set_drvdata((dev), (data))
 /* WLAN driver uses these names */
diff --git a/include/media/msm_vidc.h b/include/media/msm_vidc.h
index bc85ebb..81db11a 100644
--- a/include/media/msm_vidc.h
+++ b/include/media/msm_vidc.h
@@ -7,8 +7,8 @@
 #include <linux/videodev2.h>
 
 enum core_id {
-	MSM_VIDC_CORE_0 = 0,
-	MSM_VIDC_CORE_1,      /* for Q6 core */
+	MSM_VIDC_CORE_VENUS = 0,
+	MSM_VIDC_CORE_Q6,
 	MSM_VIDC_CORES_MAX,
 };
 
diff --git a/kernel/events/core.c b/kernel/events/core.c
index aafa4c1..7dd822b 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -1194,6 +1194,28 @@
 	return 0;
 }
 
+#ifdef CONFIG_SMP
+static void perf_retry_remove(struct perf_event *event)
+{
+	int up_ret;
+	/*
+	 * CPU was offline. Bring it online so we can
+	 * gracefully exit a perf context.
+	 */
+	up_ret = cpu_up(event->cpu);
+	if (!up_ret)
+		/* Try the remove call once again. */
+		cpu_function_call(event->cpu, __perf_remove_from_context,
+				  event);
+	else
+		pr_err("Failed to bring up CPU: %d, ret: %d\n",
+		       event->cpu, up_ret);
+}
+#else
+static void perf_retry_remove(struct perf_event *event)
+{
+}
+#endif
 
 /*
  * Remove the event from a task's (or a CPU's) list of events.
@@ -1208,19 +1230,22 @@
  * When called from perf_event_exit_task, it's OK because the
  * context has been detached from its task.
  */
-static void perf_remove_from_context(struct perf_event *event)
+static void __ref perf_remove_from_context(struct perf_event *event)
 {
 	struct perf_event_context *ctx = event->ctx;
 	struct task_struct *task = ctx->task;
+	int ret;
 
 	lockdep_assert_held(&ctx->mutex);
 
 	if (!task) {
 		/*
-		 * Per cpu events are removed via an smp call and
-		 * the removal is always successful.
+		 * Per cpu events are removed via an smp call
 		 */
-		cpu_function_call(event->cpu, __perf_remove_from_context, event);
+		ret = cpu_function_call(event->cpu, __perf_remove_from_context,
+					event);
+		if (ret == -ENXIO)
+			perf_retry_remove(event);
 		return;
 	}
 
@@ -2934,6 +2959,14 @@
 	struct perf_event *event = file->private_data;
 	struct task_struct *owner;
 
+	/*
+	 * Event can be in state OFF because of a constraint check.
+	 * Change to ACTIVE so that it gets cleaned up correctly.
+	 */
+	if ((event->state == PERF_EVENT_STATE_OFF) &&
+	    event->attr.constraint_duplicate)
+		event->state = PERF_EVENT_STATE_ACTIVE;
+
 	file->private_data = NULL;
 
 	rcu_read_lock();
@@ -5171,6 +5204,7 @@
 	.read		= perf_swevent_read,
 
 	.event_idx	= perf_swevent_event_idx,
+	.events_across_hotplug = 1,
 };
 
 #ifdef CONFIG_EVENT_TRACING
@@ -5265,6 +5299,7 @@
 	.read		= perf_swevent_read,
 
 	.event_idx	= perf_swevent_event_idx,
+	.events_across_hotplug = 1,
 };
 
 static inline void perf_tp_register(void)
@@ -5492,6 +5527,7 @@
 	.read		= cpu_clock_event_read,
 
 	.event_idx	= perf_swevent_event_idx,
+	.events_across_hotplug = 1,
 };
 
 /*
@@ -5572,6 +5608,7 @@
 	.read		= task_clock_event_read,
 
 	.event_idx	= perf_swevent_event_idx,
+	.events_across_hotplug = 1,
 };
 
 static void perf_pmu_nop_void(struct pmu *pmu)
@@ -7029,11 +7066,20 @@
 
 	idx = srcu_read_lock(&pmus_srcu);
 	list_for_each_entry_rcu(pmu, &pmus, entry) {
-		ctx = &per_cpu_ptr(pmu->pmu_cpu_context, cpu)->ctx;
+		/*
+		 * If keeping events across hotplugging is supported, do not
+		 * remove the event list, but keep it alive across CPU hotplug.
+		 * The context is exited via an fd close path when userspace
+		 * is done and the target CPU is online.
+		 */
+		if (!pmu->events_across_hotplug) {
+			ctx = &per_cpu_ptr(pmu->pmu_cpu_context, cpu)->ctx;
 
-		mutex_lock(&ctx->mutex);
-		smp_call_function_single(cpu, __perf_event_exit_context, ctx, 1);
-		mutex_unlock(&ctx->mutex);
+			mutex_lock(&ctx->mutex);
+			smp_call_function_single(cpu, __perf_event_exit_context,
+						 ctx, 1);
+			mutex_unlock(&ctx->mutex);
+		}
 	}
 	srcu_read_unlock(&pmus_srcu, idx);
 }
diff --git a/kernel/events/hw_breakpoint.c b/kernel/events/hw_breakpoint.c
index bb38c4d..98e6903 100644
--- a/kernel/events/hw_breakpoint.c
+++ b/kernel/events/hw_breakpoint.c
@@ -635,6 +635,7 @@
 	.read		= hw_breakpoint_pmu_read,
 
 	.event_idx	= hw_breakpoint_event_idx,
+	.events_across_hotplug = 1,
 };
 
 int __init init_hw_breakpoint(void)
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
index aa27d39..2be4f33 100644
--- a/kernel/time/alarmtimer.c
+++ b/kernel/time/alarmtimer.c
@@ -98,6 +98,8 @@
 
 static inline void alarmtimer_rtc_timer_init(void)
 {
+	mutex_init(&power_on_alarm_lock);
+
 	rtc_timer_init(&rtctimer, NULL, NULL);
 }
 
diff --git a/net/wireless/db.txt b/net/wireless/db.txt
index b1efe57..24bb5d0 100644
--- a/net/wireless/db.txt
+++ b/net/wireless/db.txt
@@ -849,7 +849,7 @@
 
 country TW:
 	(2402 - 2472 @ 40), (3, 27)
-	(5270 - 5330 @ 80), (6, 17), DFS
+	(5270 - 5330 @ 40), (6, 17), DFS
 	(5490 - 5710 @ 80), (6, 30), DFS
 	(5735 - 5815 @ 80), (6, 30)
 
diff --git a/sound/soc/codecs/msm8x10-wcd.c b/sound/soc/codecs/msm8x10-wcd.c
index 1962ff0..87416dd 100644
--- a/sound/soc/codecs/msm8x10-wcd.c
+++ b/sound/soc/codecs/msm8x10-wcd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -50,6 +50,8 @@
 #define BITS_PER_REG		8
 #define MSM8X10_WCD_TX_PORT_NUMBER	4
 
+#define DAPM_MICBIAS_EXTERNAL_STANDALONE "MIC BIAS External Standalone"
+
 #define MSM8X10_WCD_I2S_MASTER_MODE_MASK	0x08
 #define MSM8X10_DINO_CODEC_BASE_ADDR		0xFE043000
 #define MSM8X10_DINO_CODEC_REG_SIZE		0x200
@@ -1271,6 +1273,10 @@
 	"ZERO", "RX3", "RX2"
 };
 
+static const char * const rx_rdac3_text[] = {
+	"RX1", "RX2"
+};
+
 static const struct soc_enum rx_mix1_inp1_chain_enum =
 	SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_CONN_RX1_B1_CTL, 0, 6, rx_mix1_text);
 
@@ -1312,6 +1318,10 @@
 	SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_CONN_LO_DAC_CTL, 0, 3,
 	rx_rdac4_text);
 
+static const struct soc_enum rx_rdac3_enum  =
+	SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_CONN_HPHR_DAC_CTL, 0, 2,
+	rx_rdac3_text);
+
 static const struct soc_enum adc2_enum =
 	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(adc2_mux_text), adc2_mux_text);
 
@@ -1345,6 +1355,9 @@
 static const struct snd_kcontrol_new rx_dac4_mux =
 	SOC_DAPM_ENUM("RDAC4 MUX Mux", rx_rdac4_enum);
 
+static const struct snd_kcontrol_new rx_dac3_mux =
+	SOC_DAPM_ENUM("RDAC3 MUX Mux", rx_rdac3_enum);
+
 static const struct snd_kcontrol_new tx_adc2_mux =
 	SOC_DAPM_ENUM("ADC2 MUX Mux", adc2_enum);
 
@@ -1635,6 +1648,8 @@
 
 		/* Always pull up TxFe for TX2 to Micbias */
 		snd_soc_update_bits(codec, micb_int_reg, 0x04, 0x04);
+		snd_soc_update_bits(codec, MSM8X10_WCD_A_MICB_1_CTL,
+					0x80, 0x80);
 		break;
 	case SND_SOC_DAPM_POST_PMU:
 		usleep_range(20000, 20100);
@@ -1642,6 +1657,8 @@
 		wcd9xxx_resmgr_notifier_call(&msm8x10_wcd->resmgr, e_post_on);
 		break;
 	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_update_bits(codec, MSM8X10_WCD_A_MICB_1_CTL,
+					0x80, 0x00);
 		/* Let MBHC module know so micbias switch to be off */
 		wcd9xxx_resmgr_notifier_call(&msm8x10_wcd->resmgr, e_post_off);
 
@@ -1972,7 +1989,10 @@
 
 	{"DAC1", "Switch", "RX1 CHAIN"},
 	{"HPHL DAC", "Switch", "RX1 CHAIN"},
-	{"HPHR DAC", NULL, "RX2 CHAIN"},
+	{"HPHR DAC", NULL, "RDAC3 MUX"},
+
+	{"RDAC3 MUX", "RX1", "RX1 CHAIN"},
+	{"RDAC3 MUX", "RX2", "RX2 CHAIN"},
 
 	{"LINEOUT", NULL, "LINEOUT PA"},
 	{"SPK_OUT", NULL, "SPK PA"},
@@ -2300,7 +2320,8 @@
 	SND_SOC_DAPM_OUTPUT("EAR"),
 
 	SND_SOC_DAPM_PGA_E("EAR PA", MSM8X10_WCD_A_RX_EAR_EN, 4, 0, NULL, 0,
-			msm8x10_wcd_codec_enable_ear_pa, SND_SOC_DAPM_POST_PMU),
+			msm8x10_wcd_codec_enable_ear_pa,
+			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 
 	SND_SOC_DAPM_MIXER("DAC1", MSM8X10_WCD_A_RX_EAR_EN, 6, 0, dac1_switch,
 		ARRAY_SIZE(dac1_switch)),
@@ -2414,6 +2435,8 @@
 		&rx2_mix2_inp1_mux),
 	SND_SOC_DAPM_MUX("RDAC4 MUX", SND_SOC_NOPM, 0, 0,
 		&rx_dac4_mux),
+	SND_SOC_DAPM_MUX("RDAC3 MUX", SND_SOC_NOPM, 0, 0,
+		&rx_dac3_mux),
 
 	SND_SOC_DAPM_SUPPLY("MICBIAS_REGULATOR", SND_SOC_NOPM,
 		ON_DEMAND_MICBIAS, 0,
@@ -2458,6 +2481,11 @@
 		MSM8X10_WCD_A_MICB_1_CTL, 7, 0,
 		msm8x10_wcd_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E(DAPM_MICBIAS_EXTERNAL_STANDALONE,
+		MSM8X10_WCD_A_MICB_1_CTL,
+		7, 0, msm8x10_wcd_codec_enable_micbias,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_POST_PMD),
 
 	SND_SOC_DAPM_ADC_E("ADC1", NULL, MSM8X10_WCD_A_TX_1_EN, 7, 0,
 		msm8x10_wcd_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
@@ -2709,6 +2737,30 @@
 	return ret;
 }
 
+static int msm8x10_wcd_enable_mbhc_micbias(struct snd_soc_codec *codec,
+	 bool enable)
+{
+	int rc;
+
+	if (enable)
+		rc = snd_soc_dapm_force_enable_pin(&codec->dapm,
+			DAPM_MICBIAS_EXTERNAL_STANDALONE);
+	else
+		rc = snd_soc_dapm_disable_pin(&codec->dapm,
+			DAPM_MICBIAS_EXTERNAL_STANDALONE);
+	snd_soc_dapm_sync(&codec->dapm);
+
+	snd_soc_update_bits(codec, WCD9XXX_A_MICB_1_CTL,
+		0x80, enable ? 0x80 : 0x00);
+	if (rc)
+		pr_debug("%s: Failed to force %s micbias", __func__,
+			enable ? "enable" : "disable");
+	else
+		pr_debug("%s: Trying force %s micbias", __func__,
+			enable ? "enable" : "disable");
+	return rc;
+}
+
 static void msm8x10_wcd_micb_internal(struct snd_soc_codec *codec, bool on)
 {
 	snd_soc_update_bits(codec, MSM8X10_WCD_A_MICB_1_INT_RBIAS,
@@ -3191,7 +3243,8 @@
 
 	ret = wcd9xxx_mbhc_init(&msm8x10_wcd_priv->mbhc,
 				&msm8x10_wcd_priv->resmgr,
-				codec, NULL, &mbhc_cb, &cdc_intr_ids,
+				codec, msm8x10_wcd_enable_mbhc_micbias,
+				&mbhc_cb, &cdc_intr_ids,
 				HELICON_MCLK_CLK_9P6MHZ, true);
 	if (ret) {
 		dev_err(msm8x10_wcd->dev, "%s: Failed to initialize mbhc\n",
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
index 27ea648..1dc78ff 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -1888,9 +1888,10 @@
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
-		if (w->reg == TAPAN_A_TX_3_EN)
+		if (w->reg == TAPAN_A_TX_3_EN ||
+		    w->reg == TAPAN_A_TX_1_EN)
 			wcd9xxx_resmgr_notifier_call(&tapan->resmgr,
-						WCD9XXX_EVENT_PRE_TX_3_ON);
+						WCD9XXX_EVENT_PRE_TX_1_3_ON);
 		snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift,
 				1 << init_bit_shift);
 		break;
@@ -1900,9 +1901,10 @@
 
 		break;
 	case SND_SOC_DAPM_POST_PMD:
-		if (w->reg == TAPAN_A_TX_3_EN)
+		if (w->reg == TAPAN_A_TX_3_EN ||
+		    w->reg == TAPAN_A_TX_1_EN)
 			wcd9xxx_resmgr_notifier_call(&tapan->resmgr,
-						WCD9XXX_EVENT_POST_TX_3_OFF);
+						WCD9XXX_EVENT_POST_TX_1_3_OFF);
 		break;
 	}
 	return 0;
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index a7d1563..32ca0c6 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -1468,6 +1468,12 @@
 			type = PLUG_TYPE_INVALID;
 		}
 	}
+
+	if (type == PLUG_TYPE_HEADSET &&
+	    (mbhc->mbhc_cfg->micbias_enable_flags &
+	    (1 << MBHC_MICBIAS_ENABLE_REGULAR_HEADSET)))
+		mbhc->micbias_enable = true;
+
 exit:
 	pr_debug("%s: Plug type %d detected\n", __func__, type);
 	return type;
@@ -2038,7 +2044,8 @@
 
 		/* if PA is already on, switch micbias source to VDDIO */
 		if (mbhc->event_state &
-		    (1 << MBHC_EVENT_PA_HPHL | 1 << MBHC_EVENT_PA_HPHR))
+		    (1 << MBHC_EVENT_PA_HPHL | 1 << MBHC_EVENT_PA_HPHR |
+		     1 << MBHC_EVENT_PRE_TX_1_3_ON))
 			__wcd9xxx_switch_micbias(mbhc, 1, false, false);
 		wcd9xxx_start_hs_polling(mbhc);
 	} else if (plug_type == PLUG_TYPE_HIGH_HPH) {
@@ -4269,6 +4276,14 @@
 			if (!mbhc->polling_active)
 				wcd9xxx_enable_mbhc_txfe(mbhc, false);
 		}
+		if (mbhc->micbias_enable && mbhc->polling_active &&
+		    !(snd_soc_read(mbhc->codec, mbhc->mbhc_bias_regs.ctl_reg)
+	            & 0x80)) {
+			pr_debug("%s:Micbias turned off by recording, set up again",
+				 __func__);
+			snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.ctl_reg,
+					    0x80, 0x80);
+		}
 		break;
 	/* PA usage change */
 	case WCD9XXX_EVENT_PRE_HPHL_PA_ON:
@@ -4289,7 +4304,7 @@
 			hphlocp_off_report(mbhc, SND_JACK_OC_HPHL);
 		if (!(mbhc->event_state &
 		      (1 << MBHC_EVENT_PA_HPHL | 1 << MBHC_EVENT_PA_HPHR |
-		       1 << MBHC_EVENT_PRE_TX_3_ON)))
+		       1 << MBHC_EVENT_PRE_TX_1_3_ON)))
 			wcd9xxx_switch_micbias(mbhc, 0);
 		break;
 	case WCD9XXX_EVENT_POST_HPHR_PA_OFF:
@@ -4301,7 +4316,7 @@
 			hphrocp_off_report(mbhc, SND_JACK_OC_HPHL);
 		if (!(mbhc->event_state &
 		      (1 << MBHC_EVENT_PA_HPHL | 1 << MBHC_EVENT_PA_HPHR |
-		       1 << MBHC_EVENT_PRE_TX_3_ON)))
+		       1 << MBHC_EVENT_PRE_TX_1_3_ON)))
 			wcd9xxx_switch_micbias(mbhc, 0);
 		break;
 	/* Clock usage change */
@@ -4383,23 +4398,23 @@
 	case WCD9XXX_EVENT_POST_BG_MBHC_ON:
 		/* Not used for now */
 		break;
-	case WCD9XXX_EVENT_PRE_TX_3_ON:
+	case WCD9XXX_EVENT_PRE_TX_1_3_ON:
 		/*
 		 * if polling is ON, mbhc micbias not enabled
 		 *  switch micbias source to VDDIO
 		 */
-		set_bit(MBHC_EVENT_PRE_TX_3_ON, &mbhc->event_state);
+		set_bit(MBHC_EVENT_PRE_TX_1_3_ON, &mbhc->event_state);
 		if (!(snd_soc_read(codec, mbhc->mbhc_bias_regs.ctl_reg)
 		      & 0x80) &&
 		    mbhc->polling_active && !mbhc->mbhc_micbias_switched)
 			wcd9xxx_switch_micbias(mbhc, 1);
 		break;
-	case WCD9XXX_EVENT_POST_TX_3_OFF:
+	case WCD9XXX_EVENT_POST_TX_1_3_OFF:
 		/*
 		 * Switch back to micbias if HPH PA or TX3 path
 		 * is disabled
 		 */
-		clear_bit(MBHC_EVENT_PRE_TX_3_ON, &mbhc->event_state);
+		clear_bit(MBHC_EVENT_PRE_TX_1_3_ON, &mbhc->event_state);
 		if (mbhc->polling_active && mbhc->mbhc_micbias_switched &&
 		    !(mbhc->event_state & (1 << MBHC_EVENT_PA_HPHL |
 		      1 << MBHC_EVENT_PA_HPHR)))
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.h b/sound/soc/codecs/wcd9xxx-mbhc.h
index 98f73fc..b5031a6 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.h
+++ b/sound/soc/codecs/wcd9xxx-mbhc.h
@@ -123,8 +123,8 @@
 enum wcd9xxx_mbhc_event_state {
 	MBHC_EVENT_PA_HPHL,
 	MBHC_EVENT_PA_HPHR,
-	MBHC_EVENT_PRE_TX_3_ON,
-	MBHC_EVENT_POST_TX_3_OFF,
+	MBHC_EVENT_PRE_TX_1_3_ON,
+	MBHC_EVENT_POST_TX_1_3_OFF,
 };
 
 struct wcd9xxx_mbhc_general_cfg {
diff --git a/sound/soc/codecs/wcd9xxx-resmgr.c b/sound/soc/codecs/wcd9xxx-resmgr.c
index e56b182..4843b51 100644
--- a/sound/soc/codecs/wcd9xxx-resmgr.c
+++ b/sound/soc/codecs/wcd9xxx-resmgr.c
@@ -92,8 +92,8 @@
 
 	"WCD9XXX_EVENT_POST_RESUME",
 
-	"WCD9XXX_EVENT_PRE_TX_3_ON",
-	"WCD9XXX_EVENT_POST_TX_3_OFF",
+	"WCD9XXX_EVENT_PRE_TX_1_3_ON",
+	"WCD9XXX_EVENT_POST_TX_1_3_OFF",
 
 	"WCD9XXX_EVENT_LAST",
 };
diff --git a/sound/soc/codecs/wcd9xxx-resmgr.h b/sound/soc/codecs/wcd9xxx-resmgr.h
index 9f383b6..29896fc 100644
--- a/sound/soc/codecs/wcd9xxx-resmgr.h
+++ b/sound/soc/codecs/wcd9xxx-resmgr.h
@@ -105,8 +105,8 @@
 
 	WCD9XXX_EVENT_POST_RESUME,
 
-	WCD9XXX_EVENT_PRE_TX_3_ON,
-	WCD9XXX_EVENT_POST_TX_3_OFF,
+	WCD9XXX_EVENT_PRE_TX_1_3_ON,
+	WCD9XXX_EVENT_POST_TX_1_3_OFF,
 
 	WCD9XXX_EVENT_LAST,
 };
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index 373090e..635f125 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -1179,7 +1179,13 @@
 			char modelId[128];
 			struct snd_dec_dts opt_dts =
 				compr->info.codec_param.codec.dts;
-			int modelIdLength = opt_dts.modelIdLength;
+			unsigned int modelIdLength = opt_dts.modelIdLength;
+			if (modelIdLength >= sizeof(modelId)) {
+				rc = -EINVAL;
+				pr_err("%s: ERROR: modelIdLength is"
+						"invalid\n", __func__);
+				return rc;
+			}
 			if (copy_from_user(modelId, (void *)opt_dts.modelId,
 				modelIdLength))
 				pr_err("%s: ERROR: copy modelId\n", __func__);
@@ -1222,8 +1228,14 @@
 			char modelId[128];
 			struct snd_dec_dts opt_dts =
 				compr->info.codec_param.codec.dts;
-			int modelIdLength = opt_dts.modelIdLength;
+			unsigned int modelIdLength = opt_dts.modelIdLength;
 			pr_debug("SND_AUDIOCODEC_DTS\n");
+			if (modelIdLength >= sizeof(modelId)) {
+				rc = -EINVAL;
+				pr_err("%s: ERROR: modelIdLength is"
+						"invalid\n", __func__);
+				return rc;
+			}
 			if (copy_from_user(modelId, (void *)opt_dts.modelId,
 				modelIdLength))
 				pr_err("%s: ERROR: copy modelId\n", __func__);
diff --git a/sound/soc/msm/msm8x10.c b/sound/soc/msm/msm8x10.c
index c1ba26a..caf81fc 100644
--- a/sound/soc/msm/msm8x10.c
+++ b/sound/soc/msm/msm8x10.c
@@ -99,6 +99,8 @@
 	.insert_detect = true,
 	.swap_gnd_mic = NULL,
 	.use_int_rbias = false,
+	.micbias_enable_flags = 1 << MBHC_MICBIAS_ENABLE_THRESHOLD_HEADSET |
+				1 << MBHC_MICBIAS_ENABLE_REGULAR_HEADSET,
 	.cs_enable_flags = (1 << MBHC_CS_ENABLE_POLLING |
 			    1 << MBHC_CS_ENABLE_INSERTION |
 			    1 << MBHC_CS_ENABLE_REMOVAL),
@@ -607,21 +609,21 @@
 	btn_high = wcd9xxx_mbhc_cal_btn_det_mp(btn_cfg,
 					       MBHC_BTN_DET_V_BTN_HIGH);
 	btn_low[0] = -50;
-	btn_high[0] = 10;
-	btn_low[1] = 11;
-	btn_high[1] = 52;
-	btn_low[2] = 53;
-	btn_high[2] = 94;
-	btn_low[3] = 95;
-	btn_high[3] = 133;
-	btn_low[4] = 134;
-	btn_high[4] = 171;
-	btn_low[5] = 172;
-	btn_high[5] = 208;
-	btn_low[6] = 209;
-	btn_high[6] = 244;
-	btn_low[7] = 245;
-	btn_high[7] = 330;
+	btn_high[0] = 20;
+	btn_low[1] = 21;
+	btn_high[1] = 61;
+	btn_low[2] = 62;
+	btn_high[2] = 104;
+	btn_low[3] = 105;
+	btn_high[3] = 148;
+	btn_low[4] = 149;
+	btn_high[4] = 189;
+	btn_low[5] = 190;
+	btn_high[5] = 228;
+	btn_low[6] = 229;
+	btn_high[6] = 269;
+	btn_low[7] = 270;
+	btn_high[7] = 500;
 	n_ready = wcd9xxx_mbhc_cal_btn_det_mp(btn_cfg, MBHC_BTN_DET_N_READY);
 	n_ready[0] = 80;
 	n_ready[1] = 68;
diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
index c83e623..5f512ae 100644
--- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
@@ -67,6 +67,7 @@
 	uint32_t initial_samples_drop;
 	uint32_t trailing_samples_drop;
 	uint32_t gapless_transition;
+	bool use_dsp_gapless_mode;
 };
 
 struct msm_compr_pdata {
@@ -74,6 +75,7 @@
 	struct snd_compr_stream *cstream[MSM_FRONTEND_DAI_MAX];
 	uint32_t volume[MSM_FRONTEND_DAI_MAX][2]; /* For both L & R */
 	struct msm_compr_audio_effects *audio_effects[MSM_FRONTEND_DAI_MAX];
+	bool use_dsp_gapless_mode;
 };
 
 struct msm_compr_audio {
@@ -175,7 +177,7 @@
 
 	pr_debug("%s: bytes_received = %d copied_total = %d\n",
 		__func__, prtd->bytes_received, prtd->copied_total);
-	if (prtd->first_buffer)
+	if (prtd->first_buffer &&  prtd->gapless_state.use_dsp_gapless_mode)
 		q6asm_send_meta_data(prtd->audio_client,
 				prtd->gapless_state.initial_samples_drop,
 				prtd->gapless_state.trailing_samples_drop);
@@ -449,7 +451,8 @@
 	pr_debug("%s\n", __func__);
 	ret = q6asm_stream_open_write_v2(ac,
 				prtd->codec, bits_per_sample,
-				ac->stream_id, true/*gapless*/);
+				ac->stream_id,
+				prtd->gapless_state.use_dsp_gapless_mode);
 	if (ret < 0) {
 		pr_err("%s: Session out open failed\n", __func__);
 		 return -ENOMEM;
@@ -557,6 +560,13 @@
 	prtd->first_buffer = 1;
 	prtd->partial_drain_delay = 0;
 	memset(&prtd->gapless_state, 0, sizeof(struct msm_compr_gapless_state));
+	/*
+	 * Update the use_dsp_gapless_mode from gapless struture with the value
+	 * part of platform data.
+	 */
+	prtd->gapless_state.use_dsp_gapless_mode = pdata->use_dsp_gapless_mode;
+
+	pr_debug("%s: gapless mode %d", __func__, pdata->use_dsp_gapless_mode);
 
 	spin_lock_init(&prtd->lock);
 
@@ -870,6 +880,10 @@
 		break;
 	case SND_COMPR_TRIGGER_PARTIAL_DRAIN:
 		pr_debug("%s: SND_COMPR_TRIGGER_PARTIAL_DRAIN\n", __func__);
+		if (!prtd->gapless_state.use_dsp_gapless_mode) {
+			pr_debug("%s: set partial drain as drain\n", __func__);
+			cmd = SND_COMPR_TRIGGER_DRAIN;
+		}
 	case SND_COMPR_TRIGGER_DRAIN:
 		pr_debug("%s: SNDRV_COMPRESS_DRAIN\n", __func__);
 		/* Make sure all the data is sent to DSP before sending EOS */
@@ -916,6 +930,7 @@
 		if ((cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN) &&
 		    (prtd->gapless_state.set_next_stream_id)) {
 			/* wait for the last buffer to be returned */
+
 			if (prtd->last_buffer) {
 				pr_debug("%s: last buffer drain\n", __func__);
 				rc = msm_compr_drain_buffer(prtd, &flags);
@@ -1014,7 +1029,7 @@
 			rc = -EINTR;
 
 		/*FIXME : what if a flush comes while PC is here */
-		if (rc == 0 && (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN)) {
+		if (rc == 0) {
 			/*
 			 * Failed to open second stream in DSP for gapless
 			 * so prepare the current stream in session for gapless playback
@@ -1043,12 +1058,18 @@
 			prtd->first_buffer = 1;
 			prtd->last_buffer = 0;
 			atomic_set(&prtd->drain, 0);
+			atomic_set(&prtd->xrun, 1);
 			q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
 			spin_unlock_irqrestore(&prtd->lock, flags);
 		}
 		prtd->cmd_interrupt = 0;
 		break;
 	case SND_COMPR_TRIGGER_NEXT_TRACK:
+		if (!prtd->gapless_state.use_dsp_gapless_mode) {
+			pr_debug("%s: ignore trigger next track\n", __func__);
+			rc = 0;
+			break;
+		}
 		pr_debug("%s: SND_COMPR_TRIGGER_NEXT_TRACK\n", __func__);
 		spin_lock_irqsave(&prtd->lock, flags);
 		rc = 0;
@@ -1060,9 +1081,9 @@
 		}
 		spin_unlock_irqrestore(&prtd->lock, flags);
 		rc = q6asm_stream_open_write_v2(prtd->audio_client,
-						prtd->codec, 16,
-						stream_id,
-						true /*gapless*/);
+				prtd->codec, 16,
+				stream_id,
+				prtd->gapless_state.use_dsp_gapless_mode);
 		if (rc < 0) {
 			pr_err("%s: Session out open failed for gapless\n",
 				 __func__);
@@ -1316,7 +1337,6 @@
 	prtd = cstream->runtime->private_data;
 	if (!prtd && !prtd->audio_client)
 		return -EINVAL;
-
 	ac = prtd->audio_client;
 	if (metadata->key == SNDRV_COMPRESS_ENCODER_PADDING) {
 		pr_debug("%s, got encoder padding %u", __func__, metadata->value[0]);
@@ -1472,6 +1492,13 @@
 		pdata->cstream[i] = NULL;
 	}
 
+	/*
+	 * use_dsp_gapless_mode part of platform data(pdata) is updated from HAL
+	 * through a mixer control before compress driver is opened. The mixer
+	 * control is used to decide if dsp gapless mode needs to be enabled.
+	 * Gapless is disabled by default.
+	 */
+	pdata->use_dsp_gapless_mode = false;
 	return 0;
 }
 
@@ -1581,7 +1608,7 @@
 
 	fe_audio_effects_config_control[0].name = mixer_str;
 	fe_audio_effects_config_control[0].private_value = rtd->dai_link->be_id;
-	pr_debug("Registering new mixer ctl %s", mixer_str);
+	pr_debug("Registering new mixer ctl %s\n", mixer_str);
 	snd_soc_add_platform_controls(rtd->platform,
 				fe_audio_effects_config_control,
 				ARRAY_SIZE(fe_audio_effects_config_control));
@@ -1589,6 +1616,38 @@
 	return 0;
 }
 
+static int msm_compr_gapless_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_platform *platform = snd_kcontrol_chip(kcontrol);
+	struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
+		snd_soc_platform_get_drvdata(platform);
+	pdata->use_dsp_gapless_mode =  ucontrol->value.integer.value[0];
+	pr_debug("%s: value: %ld\n", __func__,
+		ucontrol->value.integer.value[0]);
+
+	return 0;
+}
+
+static int msm_compr_gapless_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_platform *platform = snd_kcontrol_chip(kcontrol);
+	struct msm_compr_pdata *pdata =
+		snd_soc_platform_get_drvdata(platform);
+	pr_debug("%s:gapless mode %d\n", __func__, pdata->use_dsp_gapless_mode);
+	ucontrol->value.integer.value[0] = pdata->use_dsp_gapless_mode;
+
+	return 0;
+}
+
+static const struct snd_kcontrol_new msm_compr_gapless_controls[] = {
+	SOC_SINGLE_EXT("Compress Gapless Playback",
+			0, 0, 1, 0,
+			msm_compr_gapless_get,
+			msm_compr_gapless_put),
+};
+
 static int msm_compr_new(struct snd_soc_pcm_runtime *rtd)
 {
 	int rc;
@@ -1619,7 +1678,10 @@
 static struct snd_soc_platform_driver msm_soc_platform = {
 	.probe		= msm_compr_probe,
 	.compr_ops	= &msm_compr_ops,
-	.pcm_new = msm_compr_new,
+	.pcm_new	= msm_compr_new,
+	.controls       = msm_compr_gapless_controls,
+	.num_controls   = ARRAY_SIZE(msm_compr_gapless_controls),
+
 };
 
 static __devinit int msm_compr_dev_probe(struct platform_device *pdev)
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 24f5f3b..e60cd26 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -335,15 +335,12 @@
 static int q6asm_session_alloc(struct audio_client *ac)
 {
 	int n;
-	mutex_lock(&session_lock);
 	for (n = 1; n <= SESSION_MAX; n++) {
 		if (!session[n]) {
 			session[n] = ac;
-			mutex_unlock(&session_lock);
 			return n;
 		}
 	}
-	mutex_unlock(&session_lock);
 	return -ENOMEM;
 }
 
@@ -351,9 +348,7 @@
 {
 	pr_debug("%s: sessionid[%d]\n", __func__, ac->session);
 	rtac_remove_popp_from_adm_devices(ac->session);
-	mutex_lock(&session_lock);
 	session[ac->session] = 0;
-	mutex_unlock(&session_lock);
 	ac->session = 0;
 	ac->perf_mode = LEGACY_PCM_MODE;
 	ac->fptr_cache_ops = NULL;
@@ -724,6 +719,9 @@
 	struct audio_port_data *port;
 	if (!ac || !ac->session)
 		return;
+
+	mutex_lock(&session_lock);
+
 	pr_debug("%s: Session id %d\n", __func__, ac->session);
 	if (ac->io_mode & SYNC_IO_MODE) {
 		for (loopcnt = 0; loopcnt <= OUT; loopcnt++) {
@@ -748,6 +746,8 @@
 /*done:*/
 	kfree(ac);
 	ac = NULL;
+	mutex_unlock(&session_lock);
+
 	return;
 }
 
@@ -804,9 +804,13 @@
 	ac = kzalloc(sizeof(struct audio_client), GFP_KERNEL);
 	if (!ac)
 		return NULL;
+
+	mutex_lock(&session_lock);
 	n = q6asm_session_alloc(ac);
-	if (n <= 0)
+	if (n <= 0) {
+		mutex_unlock(&session_lock);
 		goto fail_session;
+	}
 	ac->session = n;
 	ac->cb = cb;
 	ac->priv = priv;
@@ -820,7 +824,8 @@
 
 	if (ac->apr == NULL) {
 		pr_err("%s Registration with APR failed\n", __func__);
-			goto fail;
+		mutex_unlock(&session_lock);
+		goto fail;
 	}
 	ac->apr2 = apr_register("ADSP", "ASM", \
 				(apr_fn)q6asm_callback,\
@@ -829,14 +834,17 @@
 
 	if (ac->apr2 == NULL) {
 		pr_err("%s Registration with APR-2 failed\n", __func__);
-			goto fail;
+		mutex_unlock(&session_lock);
+		goto fail;
 	}
 	rtac_set_asm_handle(n, ac->apr);
 
 	pr_debug("%s Registering the common port with APR\n", __func__);
 	ac->mmap_apr = q6asm_mmap_apr_reg();
-	if (ac->mmap_apr == NULL)
+	if (ac->mmap_apr == NULL) {
+		mutex_unlock(&session_lock);
 		goto fail;
+        }
 
 	init_waitqueue_head(&ac->cmd_wait);
 	init_waitqueue_head(&ac->time_wait);
@@ -856,6 +864,8 @@
 
 	pr_debug("%s: session[%d]\n", __func__, ac->session);
 
+	mutex_unlock(&session_lock);
+
 	return ac;
 fail:
 	q6asm_audio_client_free(ac);
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c
index b9af9b6..0970a83 100644
--- a/sound/soc/soc-compress.c
+++ b/sound/soc/soc-compress.c
@@ -95,7 +95,7 @@
 	else
 		stream = SNDRV_PCM_STREAM_CAPTURE;
 
-	mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
+	mutex_lock(&fe->card->dpcm_mutex);
 
 	if (platform->driver->compr_ops && platform->driver->compr_ops->open) {
 		ret = platform->driver->compr_ops->open(cstream);
@@ -154,7 +154,7 @@
 	codec_dai->active++;
 	fe->codec->active++;
 
-	mutex_unlock(&fe->card->mutex);
+	mutex_unlock(&fe->card->dpcm_mutex);
 
 	return 0;
 
@@ -166,7 +166,7 @@
 		platform->driver->compr_ops->free(cstream);
 out:
 	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
-	mutex_unlock(&fe->card->mutex);
+	mutex_unlock(&fe->card->dpcm_mutex);
 	return ret;
 }
 
@@ -273,8 +273,7 @@
 	else
 		stream = SNDRV_PCM_STREAM_CAPTURE;
 
-	mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
-
+	mutex_lock(&fe->card->dpcm_mutex);
 	if (cstream->direction == SND_COMPRESS_PLAYBACK) {
 		cpu_dai->playback_active--;
 		codec_dai->playback_active--;
@@ -323,7 +322,7 @@
 		platform->driver->compr_ops->free(cstream);
 	//cpu_dai->runtime = NULL;
 
-	mutex_unlock(&fe->card->mutex);
+	mutex_unlock(&fe->card->dpcm_mutex);
 	return 0;
 }
 
@@ -393,8 +392,7 @@
 		stream = SNDRV_PCM_STREAM_CAPTURE;
 
 
-	mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
-
+	mutex_lock(&fe->card->dpcm_mutex);
 	if (platform->driver->compr_ops && platform->driver->compr_ops->trigger) {
 		ret = platform->driver->compr_ops->trigger(cstream, cmd);
 		if (ret < 0)
@@ -422,7 +420,7 @@
 
 out:
 	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
-	mutex_unlock(&fe->card->mutex);
+	mutex_unlock(&fe->card->dpcm_mutex);
 	return ret;
 }
 
@@ -489,8 +487,7 @@
 	if (hw_params == NULL)
 		return -ENOMEM;
 
-	mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
-
+	mutex_lock(&fe->card->dpcm_mutex);
 	/* first we call set_params for the platform driver
 	 * this should configure the soc side
 	 * if the machine has compressed ops then we call that as well
@@ -535,7 +532,7 @@
 
 out:
 	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
-	mutex_unlock(&fe->card->mutex);
+	mutex_unlock(&fe->card->dpcm_mutex);
 	return ret;
 }
 
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 63bbbdd..2f9e319 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -1904,16 +1904,12 @@
 	}
 
 	if (found) {
-		if (widget->platform) {
-			soc_dpcm_runtime_update(widget);
-		} else {
-	  		dapm_mark_dirty(widget, "mux change");
-			dapm_power_widgets(widget->dapm,
-					   SND_SOC_DAPM_STREAM_NOP);
-		}
+		dapm_mark_dirty(widget, "mux change");
+		dapm_power_widgets(widget->dapm,
+			   SND_SOC_DAPM_STREAM_NOP);
 	}
 
-	return 0;
+	return found;
 }
 
 int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
@@ -1925,6 +1921,8 @@
 	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_PCM);
 	ret = soc_dapm_mux_update_power(widget, kcontrol, change, mux, e);
 	mutex_unlock(&card->dapm_mutex);
+	if (ret > 0)
+		soc_dpcm_runtime_update(widget);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power);
@@ -1953,16 +1951,11 @@
 	}
 
 	if (found) {
-	  if (widget->platform) {
-		soc_dpcm_runtime_update(widget);
-	  } else {
 		dapm_mark_dirty(widget, "mixer update");
 		dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP);
-	  }
-
 	}
 
-	return 0;
+	return found;
 }
 
 int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
@@ -1973,6 +1966,8 @@
 	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_PCM);
 	ret = soc_dapm_mixer_update_power(widget, kcontrol, connect);
 	mutex_unlock(&card->dapm_mutex);
+	if (ret > 0)
+		soc_dpcm_runtime_update(widget);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power);
@@ -3100,9 +3095,11 @@
 {
 	struct snd_soc_dapm_context *pdapm = &rtd->platform->dapm;
 	struct snd_soc_dapm_context *cdapm = &rtd->codec->dapm;
+	struct snd_soc_card *card = rtd->card;
 
 	dev_dbg(rtd->dev, "rtd stream %d event %d\n", stream, event);
 
+	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
 	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		widget_stream_event(pdapm, rtd->cpu_dai->playback_aif, event);
 		widget_stream_event(cdapm, rtd->codec_dai->playback_aif, event);
@@ -3110,6 +3107,7 @@
 		widget_stream_event(pdapm, rtd->cpu_dai->capture_aif, event);
 		widget_stream_event(cdapm, rtd->codec_dai->capture_aif, event);
 	}
+	mutex_unlock(&card->dapm_mutex);
 
 	/* do we need to notify any clients that DAPM stream is complete */
 	if (pdapm->stream_event)
@@ -3133,14 +3131,14 @@
 int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd,
 	const char *stream, int event)
 {
+	struct snd_soc_card *card = rtd->card;
 	struct snd_soc_codec *codec = rtd->codec;
 
 	if (stream == NULL)
 		return 0;
-
-	mutex_lock(&codec->mutex);
+	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_PCM);
 	soc_dapm_stream_event(&codec->dapm, stream, event);
-	mutex_unlock(&codec->mutex);
+	mutex_unlock(&card->dapm_mutex);
 	return 0;
 }