Merge "msm: vidc: add set ctrl for Dynamic Buffer mode"
diff --git a/Documentation/bif-framework.txt b/Documentation/bif-framework.txt
index 3ba500d..9831c80 100644
--- a/Documentation/bif-framework.txt
+++ b/Documentation/bif-framework.txt
@@ -235,10 +235,10 @@
 Get/put handle for a BIF slave:
 -------------------------------
 
-int bif_slave_match_count(const struct bif_ctrl *ctrl,
+int bif_slave_match_count(struct bif_ctrl *ctrl,
 			const struct bif_match_criteria *match_criteria);
 
-struct bif_slave *bif_slave_match_get(const struct bif_ctrl *ctrl,
+struct bif_slave *bif_slave_match_get(struct bif_ctrl *ctrl,
 	unsigned int id, const struct bif_match_criteria *match_criteria);
 
 void bif_slave_put(struct bif_slave *slave);
@@ -293,7 +293,6 @@
 int bif_ctrl_notifier_unregister(struct bif_ctrl *ctrl,
 				struct notifier_block *nb);
 
-
 Read or write BIF slave registers:
 ----------------------------------
 
@@ -302,6 +301,53 @@
 int bif_slave_write(struct bif_slave *slave, u16 addr, u8 *buf, int len);
 
 
+BIF slave non-volatile memory manipulation:
+-------------------------------------------
+
+int bif_slave_nvm_raw_read(struct bif_slave *slave, u16 offset, u8 *buf,
+				int len);
+
+int bif_slave_nvm_raw_write(struct bif_slave *slave, u16 offset, u8 *buf,
+				int len);
+
+Raw NVM writing may be needed in order to intialize the NVM BIF object list.
+However, its use can be dangerous as it can overwrite existing objects in the
+list and make the list unparsable.
+
+BIF object search in slave non-volatile memory:
+-----------------------------------------------
+int bif_object_match_count(struct bif_slave *slave,
+			const struct bif_obj_match_criteria *match_criteria);
+
+struct bif_object *bif_object_match_get(struct bif_slave *slave,
+	unsigned int id, const struct bif_obj_match_criteria *match_criteria);
+
+void bif_object_put(struct bif_object *object);
+
+bif_object_match_count() and bif_object_match_get() can be used together in
+order to retrieve the set of BIF objects within a slave which match certain
+criteria.  bif_object_put() is used to free the memory allocated by
+bif_object_match_get().
+
+BIF object manipulation in slave non-volatile memory:
+-----------------------------------------------------
+int bif_object_write(struct bif_slave *slave, u8 type, u8 version, u16
+			manufacturer_id, const u8 *data, int data_len);
+
+int bif_object_overwrite(struct bif_slave *slave,
+	struct bif_object *object, u8 type, u8 version,
+	u16 manufacturer_id, const u8 *data, int data_len);
+
+int bif_object_delete(struct bif_slave *slave, const struct bif_object *object);
+
+bif_object_write() can be used to write a new BIF data object into the NVM of
+a given slave.  The new object is added to the end of the NVM object list.
+bif_object_overwrite() can be used to overwrite an existing BIF data object
+in the NVM of a slave.  The new object data must be the same size as the
+existing object data.  bif_object_delete() can be used to delete a object from
+the NVM object list and shift all of the objects after it in order to fill the
+deleted object's space.
+
 Get or set the BIF bus state or period:
 ---------------------------------------
 
@@ -341,11 +387,17 @@
 
 int bif_task_is_busy(struct bif_slave *slave, unsigned int task);
 
+int bif_enable_auto_task(struct bif_slave *slave, unsigned int task);
+
+int bif_disable_auto_task(struct bif_slave *slave, unsigned int task);
+
 A consumer can request a slave interrupt and specify a notifier to call when the
 interrupt is triggered.  Once the interrupt is requested the consumer will need
 to call bif_trigger_task() in order to start the task associated with the
 interrupt (both are identified by the same index).  Polling for task completion
-is also supported via the bif_task_is_busy() function.
+is also supported via the bif_task_is_busy() function.  Auto task triggered can
+be enabled and disabled for a given task using bif_enable_auto_task() and
+bif_disable_auto_task() respectively.
 
 Raw BIF bus transactions:
 -------------------------
diff --git a/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt b/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt
index f57d928..917ea75 100644
--- a/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt
+++ b/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt
@@ -20,6 +20,7 @@
 		"pc_no_xo_shutdown" - Power Collapse with no XO shutdown
 - qcom,l2: The state of L2 cache. Values are:
 		"l2_cache_pc" - L2 cache in power collapse
+		"l2_cache_pc_no_rpm" - L2 cache in power collapse. This mode wouldn't inform the RPM
 		"l2_cache_retenetion" - L2 cache in retention
 		"l2_cache_gdhs" - L2 cache in GDHS
 		"l2_cache_active" - L2 cache in active mode
diff --git a/Documentation/devicetree/bindings/fb/mdss-mdp.txt b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
index 5a70b6b..bf30879 100644
--- a/Documentation/devicetree/bindings/fb/mdss-mdp.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
@@ -106,6 +106,7 @@
 				- "hdmi"
 
 Optional properties:
+- vdd-cx-supply :	Phandle for vdd CX regulator device node.
 - qcom,vbif-settings :	Array with key-value pairs of constant VBIF register
 			settings used to setup MDSS QoS for optimum performance.
 			The key used should be offset from "vbif_phys" register
@@ -177,6 +178,7 @@
 		reg-names = "mdp_phys", "vbif_phys";
 		interrupts = <0 72 0>;
 		vdd-supply = <&gdsc_mdss>;
+		vdd-cx-supply = <&pm8841_s2_corner>;
 		qcom,max-clk-rate = <320000000>;
 		qcom,vbif-settings = <0x0004 0x00000001>,
 				     <0x00D8 0x00000707>;
diff --git a/Documentation/devicetree/bindings/input/touchscreen/gt9xx/gt9xx.txt b/Documentation/devicetree/bindings/input/touchscreen/gt9xx/gt9xx.txt
index 3e223e6..fdba7c2 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/gt9xx/gt9xx.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/gt9xx/gt9xx.txt
@@ -7,7 +7,7 @@
  - interrupt-parent	: Parent of interrupt.
  - interrupts		: Configuration of touch panel controller interrupt
 				GPIO.
- - goodix,family-id	: Family identification of the controller.
+ - goodix,product-id	: Product identification of the controller.
  - interrupt-gpios	: Interrupt gpio which is to provide interrupts to
 				host, same as "interrupts" node.
  - reset-gpios		: Reset gpio to control the reset of chip.
@@ -32,10 +32,24 @@
  - goodix,no-force-update	: To specify force update is allowed.
  - goodix,button-map	: Button map of key codes. The number of key codes
 				depend on panel.
- - goodix,cfg-data	: Touchpanel controller configuration data, ask vendor
-				to provide that. Default configuration will be
-				used if this property is not present.
-
+ - goodix,cfg-data0	: Touch screen controller config data group 0. Ask vendor
+				to provide that.
+				Driver supports maximum six config groups. If more than one
+				groups are defined, driver will select config group depending
+				on hardware configuration. If only config group 0 is defined,
+				it will be used for all hardware configurations.
+				Touch screen controller will use its onchip default config data
+				if this property is not present.
+ - goodix,cfg-data1	: Touch screen controller config data group 1. Ask vendor
+				to provide that.
+ - goodix,cfg-data2	: Touch screen controller config data group 2. Ask vendor
+				to provide that.
+ - goodix,cfg-data3	: Touch screen controller config data group 3. Ask vendor
+				to provide that.
+ - goodix,cfg-data4	: Touch screen controller config data group 4. Ask vendor
+				to provide that.
+ - goodix,cfg-data5	: Touch screen controller config data group 5. Ask vendor
+				to provide that.
 Example:
 i2c@f9927000 {
 		goodix@5d {
@@ -49,26 +63,26 @@
 			goodix,panel-coords = <0 0 720 1200>;
 			goodix,display-coords = <0 0 720 1080>;
 			goodix,button-map= <158 102 139>;
-			goodix,family-id = <0x0>;
-			goodix,cfg-data = [
-		41 D0 02 00 05 0A 05 01 01 08
-		12 58 50 41 03 05 00 00 00 00
-		00 00 00 00 00 00 00 8C 2E 0E
-		28 24 73 13 00 00 00 83 03 1D
-		40 02 00 00 00 03 64 32 00 00
-		00 1A 38 94 C0 02 00 00 00 04
-		9E 1C 00 8D 20 00 7A 26 00 6D
-		2C 00 60 34 00 60 10 38 68 00
-		F0 50 35 FF FF 27 00 00 00 00
-		00 01 1B 14 0C 14 00 00 01 00
-		00 00 00 00 00 00 00 00 00 00
-		00 00 02 04 06 08 0A 0C 0E 10
-		12 14 16 18 1A 1C FF FF FF FF
-		FF FF FF FF FF FF FF FF FF FF
-		FF FF 00 02 04 06 08 0A 0C 0F
-		10 12 13 14 16 18 1C 1D 1E 1F
-		20 21 22 24 26 28 29 2A FF FF
-		FF FF FF FF FF FF FF 22 22 22
-		22 22 22 FF 07 01];
+			goodix,product-id = "915";
+			goodix,cfg-data0 = [
+				41 D0 02 00 05 0A 05 01 01 08
+				12 58 50 41 03 05 00 00 00 00
+				00 00 00 00 00 00 00 8C 2E 0E
+				28 24 73 13 00 00 00 83 03 1D
+				40 02 00 00 00 03 64 32 00 00
+				00 1A 38 94 C0 02 00 00 00 04
+				9E 1C 00 8D 20 00 7A 26 00 6D
+				2C 00 60 34 00 60 10 38 68 00
+				F0 50 35 FF FF 27 00 00 00 00
+				00 01 1B 14 0C 14 00 00 01 00
+				00 00 00 00 00 00 00 00 00 00
+				00 00 02 04 06 08 0A 0C 0E 10
+				12 14 16 18 1A 1C FF FF FF FF
+				FF FF FF FF FF FF FF FF FF FF
+				FF FF 00 02 04 06 08 0A 0C 0F
+				10 12 13 14 16 18 1C 1D 1E 1F
+				20 21 22 24 26 28 29 2A FF FF
+				FF FF FF FF FF FF FF 22 22 22
+				22 22 22 FF 07 01];
 		};
 };
diff --git a/Documentation/devicetree/bindings/iommu/msm_iommu_v0.txt b/Documentation/devicetree/bindings/iommu/msm_iommu_v0.txt
index c7c6415..cf21158 100644
--- a/Documentation/devicetree/bindings/iommu/msm_iommu_v0.txt
+++ b/Documentation/devicetree/bindings/iommu/msm_iommu_v0.txt
@@ -14,6 +14,7 @@
 - qcom,needs-alt-core-clk : boolean to enable the secondary core clock for
   access to the IOMMU configuration registers
 - Bus scaling properties: See msm_bus.txt
+- qcom,msm-enable-remote-spinlock : boolean to enable use of remote spinlock
 
 - List of sub nodes, one for each of the translation context banks supported.
     Required properties for each sub-node:
diff --git a/Documentation/devicetree/bindings/power/qpnp-charger.txt b/Documentation/devicetree/bindings/power/qpnp-charger.txt
index b1c4ebb..5425c92 100644
--- a/Documentation/devicetree/bindings/power/qpnp-charger.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-charger.txt
@@ -37,6 +37,9 @@
 - qcom,maxinput-usb-ma:			Maximum input current USB.
 - qcom,maxinput-dc-ma:			Maximum input current DC.
 - qcom,vbatdet-delta-mv:		Battery charging resume delta.
+- qcom,vbatweak-mv:			Weak battery voltage threshold in mV, above which
+					fast charging can start. The supported voltage range is
+					from 2100mV to 3600mV with a step size of 100mV.
 - qcom,charging-disabled:		Set this property to disable charging
 					by default. This can then be overriden
 					writing the the module parameter
@@ -86,6 +89,10 @@
 					that exhibit inaccuracies in battery current readings. This
 					phandle is used to check the version of the PMIC and apply
 					necessary software workarounds.
+- qcom,ovp-monitor-en			The ovp is enabled on hw by default. If this flag is
+					set, the charger ovp status is monitored in software.
+- qcom,ext-ovp-present			Indicates if an external OVP exists which reduces the
+					overall input resistance of the charge path.
 
 Sub node required structure:
 - A qcom,chg node must be a child of an SPMI node that has specified
@@ -200,6 +207,7 @@
 		qcom,ibatmax-ma = <1500>;
 		qcom,ibatterm-ma = <200>;
 		qcom,ibatsafe-ma = <1500>;
+		qcom,vbatweak-mv = <3200>;
 		qcom,thermal-mitigation = <1500 700 600 325>;
 		qcom,cool-bat-degc = <10>;
 		qcom,cool-bat-mv = <4100>;
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index aa37edc..adcf168 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -222,7 +222,8 @@
 	default DRAM_BASE if REMAP_VECTORS_TO_RAM
 	default 0x00000000
 	help
-	  The base address of exception vectors.
+	  The base address of exception vectors.  This must be two pages
+	  in size.
 
 config ARM_PATCH_PHYS_VIRT
 	bool "Patch physical to virtual translations at runtime" if EMBEDDED
diff --git a/arch/arm/boot/dts/msm-iommu-v0.dtsi b/arch/arm/boot/dts/msm-iommu-v0.dtsi
index 8ab9985..8891935 100644
--- a/arch/arm/boot/dts/msm-iommu-v0.dtsi
+++ b/arch/arm/boot/dts/msm-iommu-v0.dtsi
@@ -33,6 +33,7 @@
 		qcom,msm-bus,vectors-KBps =
 				<11 512 0 0>,
 				<11 512 0 1000>;
+		qcom,msm-enable-remote-spinlock;
 		status = "disabled";
 
 		lpass_q6_fw: qcom,iommu-ctx@fd000000 {
diff --git a/arch/arm/boot/dts/msm-pm8110.dtsi b/arch/arm/boot/dts/msm-pm8110.dtsi
index 6969940..8523524 100644
--- a/arch/arm/boot/dts/msm-pm8110.dtsi
+++ b/arch/arm/boot/dts/msm-pm8110.dtsi
@@ -113,7 +113,7 @@
 							"vdd-loop";
 			};
 
-			qcom,bat-if@1200 {
+			pm8110_chg_batif: qcom,bat-if@1200 {
 				status = "disabled";
 				reg = <0x1200 0x100>;
 				interrupts =	<0x0 0x12 0x0>,
diff --git a/arch/arm/boot/dts/msm-pm8226.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
index ba1bf08..5e0abea 100644
--- a/arch/arm/boot/dts/msm-pm8226.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226.dtsi
@@ -131,7 +131,7 @@
 							"vdd-loop";
 			};
 
-			qcom,bat-if@1200 {
+			pm8226_chg_batif: qcom,bat-if@1200 {
 				status = "disabled";
 				reg = <0x1200 0x100>;
 				interrupts =	<0x0 0x12 0x0>,
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 98d2f5e..8a239cc 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -250,7 +250,7 @@
 						"vdd-loop";
 		};
 
-		qcom,bat-if@1200 {
+		pm8941_chg_batif: qcom,bat-if@1200 {
 			status = "disabled";
 			reg = <0x1200 0x100>;
 			interrupts =	<0x0 0x12 0x0>,
diff --git a/arch/arm/boot/dts/msm8226-mdss.dtsi b/arch/arm/boot/dts/msm8226-mdss.dtsi
index d5c3811..3e2507ff 100644
--- a/arch/arm/boot/dts/msm8226-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8226-mdss.dtsi
@@ -37,6 +37,7 @@
 		qcom,mdss-intf-off = <0x00000000 0x00021300>;
 		qcom,mdss-rot-block-size = <64>;
 		qcom,mdss-smp-mb-per-pipe = <2>;
+		vdd-cx-supply = <&pm8226_s1_corner>;
 
 		qcom,vbif-settings = <0x004 0x00000001>,
 				     <0x0D8 0x00000707>,
diff --git a/arch/arm/boot/dts/msm8226-qrd-skuf.dtsi b/arch/arm/boot/dts/msm8226-qrd-skuf.dtsi
new file mode 100755
index 0000000..66f5095
--- /dev/null
+++ b/arch/arm/boot/dts/msm8226-qrd-skuf.dtsi
@@ -0,0 +1,215 @@
+/* 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.
+ */
+
+/include/ "msm8226-qrd.dtsi"
+
+&soc {
+	sound {
+		qcom,model = "msm8226-tapan-skuf-snd-card";
+
+		qcom,audio-routing =
+			"RX_BIAS", "MCLK",
+			"LDO_H", "MCLK",
+			"SPK_OUT", "MCLK",
+			"SPK_OUT", "EXT_VDD_SPKR",
+			"Lineout_1 amp", "LINEOUT1",
+			"Lineout_2 amp", "LINEOUT2",
+			"AMIC1", "MIC BIAS1 External",
+			"MIC BIAS1 External", "Handset Mic",
+			"AMIC2", "MIC BIAS2 External",
+			"MIC BIAS2 External", "Headset Mic",
+			"AMIC3", "MIC BIAS1 External",
+			"MIC BIAS1 External", "ANCRight Headset Mic",
+			"AMIC4", "MIC BIAS2 External",
+			"MIC BIAS2 External", "ANCLeft Headset Mic";
+
+		qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
+		qcom,cdc-lineout-spkr-gpios = <&pm8226_gpios 2 0>;
+		qcom,cdc-vdd-spkr-gpios;
+		qcom,cdc-us-euro-gpios;
+	};
+
+    sound-9302 {
+          qcom,model = "msm8226-tapan9302-skuf-snd-card";
+
+          qcom,audio-routing =
+              "RX_BIAS", "MCLK",
+              "LDO_H", "MCLK",
+              "SPK_OUT", "MCLK",
+              "SPK_OUT", "EXT_VDD_SPKR",
+              "Lineout_1 amp", "LINEOUT1",
+              "Lineout_2 amp", "LINEOUT2",
+              "AMIC1", "MIC BIAS1 External",
+              "MIC BIAS1 External", "Handset Mic",
+              "AMIC2", "MIC BIAS2 External",
+              "MIC BIAS2 External", "Headset Mic",
+              "AMIC3", "MIC BIAS1 External",
+              "MIC BIAS1 External", "Handset Mic";
+
+		qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
+		qcom,cdc-lineout-spkr-gpios = <&pm8226_gpios 2 0>;
+		qcom,cdc-vdd-spkr-gpios;
+		qcom,cdc-us-euro-gpios;
+	};
+
+	tp_power: regulator-tp {
+		compatible = "regulator-fixed";
+		regulator-name = "tp_power";
+		regulator-min-microvolt = <2800000>;
+		regulator-max-microvolt = <2800000>;
+		gpio = <&msmgpio 15 0>;
+		startup-delay-us = <20000>;
+		enable-active-high;
+	};
+
+	i2c@f9927000 {
+		goodix@5d {
+			compatible = "goodix,gt9xx";
+			reg = <0x5d>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <17 0x2008>;
+			reset-gpios = <&msmgpio 16 0x00>;
+			interrupt-gpios = <&msmgpio 17 0x00>;
+			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,product-id = "915";
+			goodix,cfg-data0 = [
+				41 D0 02 00 05 05 35 01 01 0F
+				2D 06 50 32 03 05 00 00 00 00
+				00 00 05 18 1A 1E 14 8C 0E 0E
+				3F 3D 2A 09 00 00 00 99 04 1D
+				00 00 00 00 00 00 00 00 00 00
+				00 32 6E 94 D5 01 05 00 00 04
+				CE 36 00 B5 3F 00 9E 4A 00 8B
+				57 00 7C 65 00 7C 10 38 68 00
+				56 50 35 66 66 27 00 00 00 00
+				00 00 00 00 00 00 00 00 00 00
+				00 00 00 00 00 00 00 00 00 00
+				00 00 02 04 06 08 0A 0C 0E 10
+				12 14 16 18 1A 1C 00 00 00 00
+				00 00 00 00 00 00 00 00 00 00
+				00 00 00 02 04 06 08 0A 0C 0F
+				10 12 13 14 16 18 1C 1D 1E 1F
+				20 21 22 24 26 28 29 2A 00 00
+				00 FF FF FF FF FF FF FF FF FF
+				FF FF FF FF A3 01];
+			goodix,cfg-data1 = [
+				41 D0 02 00 05 05 35 01 01 C3
+				2D 06 55 32 03 03 00 00 00 00
+				00 00 05 0A 0C 0F 0A 8C 0E 0E
+				30 2E B8 08 00 00 00 8F 03 1D
+				00 00 00 00 00 00 00 00 00 00
+				00 2D 62 94 D5 02 05 00 00 04
+				96 30 00 80 39 00 71 42 00 63
+				4D 00 56 5A 00 56 10 38 68 00
+				56 50 35 AA AA 27 00 00 00 00
+				00 01 1B 14 0C 14 00 00 01 00
+				00 00 00 00 00 00 00 00 00 00
+				00 00 02 04 06 08 0A 0C 0E 10
+				12 14 16 18 1A 1C FF FF FF FF
+				FF FF FF FF FF FF FF FF FF FF
+				FF FF 00 02 04 06 08 0A 0C 0F
+				10 12 13 14 16 18 1C 1D 1E 1F
+				20 21 22 24 26 28 29 2A FF FF
+				FF FF FF FF FF FF FF FF FF FF
+				FF FF FF FF 3E 01];
+		};
+	};
+};
+
+&spmi_bus {
+	qcom,pm8226@0 {
+		qcom,leds@a300 {
+			status = "disabled";
+		};
+
+		qcom,leds@a500 {
+			status = "disabled";
+		};
+	};
+
+	qcom,pm8226@1 {
+		qcom,leds@d800 {
+			status = "disabled";
+		};
+	};
+};
+
+&pm8226_mpps {
+	mpp@a300 { /* MPP 4 */
+		/* camera2_id */
+		qcom,mode = <4>; /* AIN input */
+		qcom,invert = <1>; /* Enable MPP */
+		qcom,ain-route = <3>; /* AMUX 8 */
+		qcom,master-en = <1>;
+		qcom,src-sel = <0>; /* Function constant */
+	};
+
+	mpp@a500 { /* MPP 6 */
+		/* camera_id */
+		qcom,mode = <4>; /* AIN input */
+		qcom,invert = <1>; /* Enable MPP */
+		qcom,ain-route = <1>; /* AMUX 6 */
+		qcom,master-en = <1>;
+		qcom,src-sel = <0>; /* Function constant */
+	};
+
+};
+
+&pm8226_vadc {
+	chan@13 {
+		label = "camera2_id";
+		reg = <0x13>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "absolute";
+		qcom,scale-function = <0>;
+		qcom,hw-settle-time = <0>;
+		qcom,fast-avg-setup = <0>;
+	};
+
+	chan@15 {
+		label = "camera_id";
+		reg = <0x15>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "absolute";
+		qcom,scale-function = <0>;
+		qcom,hw-settle-time = <0>;
+		qcom,fast-avg-setup = <0>;
+	};
+};
+
+&qrd_batterydata {
+	qcom,rpull-up-kohm = <100>;
+	qcom,vref-batt-therm = <1800000>;
+
+	/include/ "batterydata-qrd-4v35-2500mah.dtsi"
+};
+
+&pm8226_bms {
+	qcom,battery-data = <&qrd_batterydata>;
+};
+
+&pm8226_chg {
+	qcom,battery-data = <&qrd_batterydata>;
+};
+
+&mdss_dsi0 {
+	qcom,dsi-pref-prim-pan = <&dsi_nt35521_720_vid>;
+};
+
+&dsi_nt35521_720_vid {
+	qcom,cont-splash-enabled;
+};
diff --git a/arch/arm/boot/dts/msm8226-qrd.dtsi b/arch/arm/boot/dts/msm8226-qrd.dtsi
index 18a1aea..701a3ef 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-qrd.dtsi
@@ -385,6 +385,7 @@
 	status = "okay";
 	qcom,battery-data = <&qrd_batterydata>;
 	qcom,tchg-mins = <240>;
+	qcom,ovp-monitor-en;
 };
 
 &pm8226_gpios {
diff --git a/arch/arm/boot/dts/msm8226-regulator.dtsi b/arch/arm/boot/dts/msm8226-regulator.dtsi
index 838592c..23a2158 100644
--- a/arch/arm/boot/dts/msm8226-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8226-regulator.dtsi
@@ -491,6 +491,10 @@
 	otg-parent-supply = <&pm8226_chg_boost>;
 };
 
+&pm8226_chg_batif {
+	regulator-name = "batfet";
+};
+
 &pm8226_chg_otg {
 	regulator-name = "8226_smbbp_otg";
 };
diff --git a/arch/arm/boot/dts/msm8226-v1-pm.dtsi b/arch/arm/boot/dts/msm8226-v1-pm.dtsi
index 1530074..02feec8 100644
--- a/arch/arm/boot/dts/msm8226-v1-pm.dtsi
+++ b/arch/arm/boot/dts/msm8226-v1-pm.dtsi
@@ -99,6 +99,9 @@
 		qcom,saw2-spm-cmd-pc = [00 32 b0 10 e0 d0 6b c0 42 f0
 				11 07 01 b0 50 4e 02 02 c0 d0 12 e0 6b 02 32
 				50 f0 0f]; /*APCS_PMIC_OFF_L2RAM_OFF*/
+		qcom,saw2-spm-cmd-pc-no-rpm = [00 32 b0 10 e0 d0 6b c0 42 f0
+				11 03 01 b0 50 4e 02 02 c0 d0 12 e0 6b 02 32
+				50 f0 0f]; /*APCS_PMIC_OFF_L2RAM_OFF*/
 		qcom,L2-spm-is-apcs-master;
 	};
 
@@ -113,8 +116,8 @@
 			qcom,mode = "wfi";
 			qcom,l2 = "l2_cache_active";
 			qcom,latency-us = <1>;
-			qcom,ss-power = <784>;
-			qcom,energy-overhead = <190000>;
+			qcom,ss-power = <530>;
+			qcom,energy-overhead = <52800>;
 			qcom,time-overhead = <100>;
 		};
 
@@ -122,30 +125,30 @@
 			reg = <0x1>;
 			qcom,mode = "standalone_pc";
 			qcom,l2 = "l2_cache_active";
-			qcom,latency-us = <3000>;
-			qcom,ss-power = <725>;
-			qcom,energy-overhead = <99500>;
-			qcom,time-overhead = <3130>;
+			qcom,latency-us = <500>;
+			qcom,ss-power = <410>;
+			qcom,energy-overhead = <603400>;
+			qcom,time-overhead = <1200>;
 		};
 
 		qcom,lpm-level@2 {
 			reg = <0x2>;
 			qcom,mode = "pc";
-			qcom,l2 = "l2_cache_retention";
-			qcom,latency-us = <20000>;
-			qcom,ss-power = <138>;
-			qcom,energy-overhead = <1208400>;
-			qcom,time-overhead = <9200>;
+			qcom,l2 = "l2_cache_pc_no_rpm";
+			qcom,latency-us = <1000>;
+			qcom,ss-power = <315>;
+			qcom,energy-overhead = <1027150>;
+			qcom,time-overhead = <2400>;
 		};
 
 		qcom,lpm-level@3 {
 			reg = <0x3>;
 			qcom,mode = "pc";
 			qcom,l2 = "l2_cache_pc";
-			qcom,latency-us = <30000>;
-			qcom,ss-power = <110>;
-			qcom,energy-overhead = <1250300>;
-			qcom,time-overhead = <9500>;
+			qcom,latency-us = <11000>;
+			qcom,ss-power = <315>;
+			qcom,energy-overhead = <1027150>;
+			qcom,time-overhead = <2400>;
 		};
 	};
 
diff --git a/arch/arm/boot/dts/msm8226-v1-qrd-skuf-pvt.dts b/arch/arm/boot/dts/msm8226-v1-qrd-skuf-pvt.dts
new file mode 100644
index 0000000..43e1e21
--- /dev/null
+++ b/arch/arm/boot/dts/msm8226-v1-qrd-skuf-pvt.dts
@@ -0,0 +1,22 @@
+/* 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.
+ */
+
+/dts-v1/;
+/include/ "msm8226-v1.dtsi"
+/include/ "msm8226-qrd-skuf.dtsi"
+
+/ {
+	model = "Qualcomm MSM 8226v1 QRD PVT";
+	compatible = "qcom,msm8226-qrd", "qcom,msm8226", "qcom,skuf", "qcom,qrd";
+	qcom,board-id = <0x2000b 2>;
+};
+
diff --git a/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts b/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts
index d12f8c9..b836928 100644
--- a/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts
+++ b/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts
@@ -12,7 +12,7 @@
 
 /dts-v1/;
 /include/ "msm8226-v1.dtsi"
-/include/ "msm8226-qrd.dtsi"
+/include/ "msm8226-qrd-skuf.dtsi"
 
 / {
 	model = "Qualcomm MSM 8226v1 QRD";
@@ -20,184 +20,10 @@
 	qcom,board-id = <11 2>;
 };
 
-&soc {
-	sound {
-		qcom,model = "msm8226-tapan-skuf-snd-card";
-
-		qcom,audio-routing =
-			"RX_BIAS", "MCLK",
-			"LDO_H", "MCLK",
-			"SPK_OUT", "MCLK",
-			"SPK_OUT", "EXT_VDD_SPKR",
-			"Lineout_1 amp", "LINEOUT1",
-			"Lineout_2 amp", "LINEOUT2",
-			"AMIC1", "MIC BIAS1 External",
-			"MIC BIAS1 External", "Handset Mic",
-			"AMIC2", "MIC BIAS2 External",
-			"MIC BIAS2 External", "Headset Mic",
-			"AMIC3", "MIC BIAS1 External",
-			"MIC BIAS1 External", "ANCRight Headset Mic",
-			"AMIC4", "MIC BIAS2 External",
-			"MIC BIAS2 External", "ANCLeft Headset Mic";
-
-		qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
-		qcom,cdc-lineout-spkr-gpios = <&pm8226_gpios 2 0>;
-		qcom,cdc-vdd-spkr-gpios;
-		qcom,cdc-us-euro-gpios;
-	};
-
-    sound-9302 {
-          qcom,model = "msm8226-tapan9302-skuf-snd-card";
-
-          qcom,audio-routing =
-              "RX_BIAS", "MCLK",
-              "LDO_H", "MCLK",
-              "SPK_OUT", "MCLK",
-              "SPK_OUT", "EXT_VDD_SPKR",
-              "Lineout_1 amp", "LINEOUT1",
-              "Lineout_2 amp", "LINEOUT2",
-              "AMIC1", "MIC BIAS1 External",
-              "MIC BIAS1 External", "Handset Mic",
-              "AMIC2", "MIC BIAS2 External",
-              "MIC BIAS2 External", "Headset Mic",
-              "AMIC3", "MIC BIAS1 External",
-              "MIC BIAS1 External", "Handset Mic";
-
-          qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
-          qcom,cdc-lineout-spkr-gpios = <&pm8226_gpios 2 0>;
-          qcom,cdc-vdd-spkr-gpios;
-          qcom,cdc-us-euro-gpios;
-      };
-
-	tp_power: regulator-tp {
-		compatible = "regulator-fixed";
-		regulator-name = "tp_power";
-		regulator-min-microvolt = <2800000>;
-		regulator-max-microvolt = <2800000>;
-		gpio = <&msmgpio 15 0>;
-		startup-delay-us = <20000>;
-		enable-active-high;
-	};
-
-	i2c@f9927000 {
-		goodix@5d {
-			compatible = "goodix,gt9xx";
-			reg = <0x5d>;
-			interrupt-parent = <&msmgpio>;
-			interrupts = <17 0x2008>;
-			reset-gpios = <&msmgpio 16 0x00>;
-			interrupt-gpios = <&msmgpio 17 0x00>;
-			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,family-id = <0x0>;
-			goodix,cfg-data = [
-			41 D0 02 00 05 0A 35 01 01 0F
-			2D 08 55 32 03 04 00 00 00 00
-			00 00 05 0A 0C 0F 0A 8C 0E 0E
-			30 2E B8 08 00 00 00 83 03 1D
-			00 00 00 00 00 00 00 00 00 00
-			00 2D 62 94 C5 02 05 00 00 04
-			96 30 00 80 39 00 71 42 00 63
-			4D 00 56 5A 00 56 10 38 68 00
-			56 50 35 AA AA 27 00 00 00 00
-			00 01 1B 14 0C 14 00 00 01 00
-			00 00 00 00 00 00 00 00 00 00
-			00 00 02 04 06 08 0A 0C 0E 10
-			12 14 16 18 1A 1C FF FF FF FF
-			FF FF FF FF FF FF FF FF FF FF
-			FF FF 00 02 04 06 08 0A 0C 0F
-			10 12 13 14 16 18 1C 1D 1E 1F
-			20 21 22 24 26 28 29 2A FF FF
-			FF FF FF FF FF FF FF FF FF FF
-			FF FF FF FF 06 01];
-		};
-	};
-};
-
-&spmi_bus {
-	qcom,pm8226@0 {
-		qcom,leds@a300 {
-			status = "disabled";
-		};
-
-		qcom,leds@a500 {
-			status = "disabled";
-		};
-	};
-
-	qcom,pm8226@1 {
-		qcom,leds@d800 {
-			status = "disabled";
-		};
-	};
-};
-
-&pm8226_mpps {
-	mpp@a300 { /* MPP 4 */
-		/* camera2_id */
-		qcom,mode = <4>; /* AIN input */
-		qcom,invert = <1>; /* Enable MPP */
-		qcom,ain-route = <3>; /* AMUX 8 */
-		qcom,master-en = <1>;
-		qcom,src-sel = <0>; /* Function constant */
-	};
-
-	mpp@a500 { /* MPP 6 */
-		/* camera_id */
-		qcom,mode = <4>; /* AIN input */
-		qcom,invert = <1>; /* Enable MPP */
-		qcom,ain-route = <1>; /* AMUX 6 */
-		qcom,master-en = <1>;
-		qcom,src-sel = <0>; /* Function constant */
-	};
-
-};
-
-&pm8226_vadc {
-	chan@13 {
-		label = "camera2_id";
-		reg = <0x13>;
-		qcom,decimation = <0>;
-		qcom,pre-div-channel-scaling = <0>;
-		qcom,calibration-type = "absolute";
-		qcom,scale-function = <0>;
-		qcom,hw-settle-time = <0>;
-		qcom,fast-avg-setup = <0>;
-	};
-
-	chan@15 {
-		label = "camera_id";
-		reg = <0x15>;
-		qcom,decimation = <0>;
-		qcom,pre-div-channel-scaling = <0>;
-		qcom,calibration-type = "absolute";
-		qcom,scale-function = <0>;
-		qcom,hw-settle-time = <0>;
-		qcom,fast-avg-setup = <0>;
-	};
-};
-
-&qrd_batterydata {
-	qcom,rpull-up-kohm = <100>;
-	qcom,vref-batt-therm = <1800000>;
-
-	/include/ "batterydata-qrd-4v35-2500mah.dtsi"
-};
-
 &pm8226_bms {
-	qcom,battery-data = <&qrd_batterydata>;
+        qcom,use-external-rsense;
 };
 
-&pm8226_chg {
-	qcom,battery-data = <&qrd_batterydata>;
-};
-
-&mdss_dsi0 {
-	qcom,dsi-pref-prim-pan = <&dsi_nt35521_720_vid>;
-};
-
-&dsi_nt35521_720_vid {
-	qcom,cont-splash-enabled;
+&pm8226_iadc {
+        qcom,rsense = <10000000>;
 };
diff --git a/arch/arm/boot/dts/msm8226-v2-pm.dtsi b/arch/arm/boot/dts/msm8226-v2-pm.dtsi
index 9104cba..31d5a8f 100644
--- a/arch/arm/boot/dts/msm8226-v2-pm.dtsi
+++ b/arch/arm/boot/dts/msm8226-v2-pm.dtsi
@@ -98,6 +98,9 @@
 		qcom,saw2-spm-cmd-ret = [00 03 00 0f];
 		qcom,saw2-spm-cmd-gdhs = [00 20 32 6b c0 e0 d0 42 07 50
 				4e 02 02 d0 e0 c0 22 6b 02 32 50 0f];
+		qcom,saw2-spm-cmd-pc-no-rpm = [00 32 b0 10 e0 d0 6b c0 42 f0
+				11 03 01 b0 50 4e 02 02 c0 d0 12 e0 6b 02 32
+				50 f0 0f]; /*APCS_PMIC_OFF_L2RAM_OFF*/
 		qcom,saw2-spm-cmd-pc = [00 32 b0 10 e0 d0 6b c0 42 f0
 				11 07 01 b0 50 4e 02 02 c0 d0 12 e0 6b 02 32
 				50 f0 0f]; /*APCS_PMIC_OFF_L2RAM_OFF*/
@@ -115,8 +118,8 @@
 			qcom,mode = "wfi";
 			qcom,l2 = "l2_cache_active";
 			qcom,latency-us = <1>;
-			qcom,ss-power = <784>;
-			qcom,energy-overhead = <190000>;
+			qcom,ss-power = <530>;
+			qcom,energy-overhead = <52800>;
 			qcom,time-overhead = <100>;
 		};
 
@@ -124,30 +127,40 @@
 			reg = <0x1>;
 			qcom,mode = "standalone_pc";
 			qcom,l2 = "l2_cache_active";
-			qcom,latency-us = <3000>;
-			qcom,ss-power = <725>;
-			qcom,energy-overhead = <99500>;
-			qcom,time-overhead = <3130>;
+			qcom,latency-us = <500>;
+			qcom,ss-power = <410>;
+			qcom,energy-overhead = <603400>;
+			qcom,time-overhead = <1200>;
 		};
 
 		qcom,lpm-level@2 {
 			reg = <0x2>;
 			qcom,mode = "pc";
 			qcom,l2 = "l2_cache_gdhs";
-			qcom,latency-us = <20000>;
-			qcom,ss-power = <138>;
-			qcom,energy-overhead = <1208400>;
-			qcom,time-overhead = <9200>;
+			qcom,latency-us = <10700>;
+			qcom,ss-power = <372>;
+			qcom,energy-overhead = <738750>;
+			qcom,time-overhead = <1410>;
 		};
 
 		qcom,lpm-level@3 {
 			reg = <0x3>;
 			qcom,mode = "pc";
+			qcom,l2 = "l2_cache_pc_no_rpm";
+			qcom,latency-us = <1000>;
+			qcom,ss-power = <315>;
+			qcom,energy-overhead = <1027150>;
+			qcom,time-overhead = <2400>;
+		};
+
+		qcom,lpm-level@4 {
+			reg = <0x4>;
+			qcom,mode = "pc";
 			qcom,l2 = "l2_cache_pc";
-			qcom,latency-us = <30000>;
-			qcom,ss-power = <110>;
-			qcom,energy-overhead = <1250300>;
-			qcom,time-overhead = <9500>;
+			qcom,latency-us = <11000>;
+			qcom,ss-power = <315>;
+			qcom,energy-overhead = <1027150>;
+			qcom,time-overhead = <2400>;
 		};
 	};
 
diff --git a/arch/arm/boot/dts/msm8226-v2-qrd-skuf-pvt.dts b/arch/arm/boot/dts/msm8226-v2-qrd-skuf-pvt.dts
new file mode 100644
index 0000000..f5ac301
--- /dev/null
+++ b/arch/arm/boot/dts/msm8226-v2-qrd-skuf-pvt.dts
@@ -0,0 +1,22 @@
+/* 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.
+ */
+
+/dts-v1/;
+/include/ "msm8226-v2.dtsi"
+/include/ "msm8226-qrd-skuf.dtsi"
+
+/ {
+	model = "Qualcomm MSM 8226v2 QRD PVT";
+	compatible = "qcom,msm8226-qrd", "qcom,msm8226", "qcom,skuf", "qcom,qrd";
+	qcom,board-id = <0x2000b 0x2>;
+};
+
diff --git a/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts b/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts
index 9a750ae..9aa12f6 100644
--- a/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts
+++ b/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts
@@ -12,7 +12,7 @@
 
 /dts-v1/;
 /include/ "msm8226-v2.dtsi"
-/include/ "msm8226-qrd.dtsi"
+/include/ "msm8226-qrd-skuf.dtsi"
 
 / {
 	model = "Qualcomm MSM 8226v2 QRD";
@@ -20,189 +20,10 @@
 	qcom,board-id = <0xb 0x2>;
 };
 
-&soc {
-	sound {
-		qcom,model = "msm8226-tapan-skuf-snd-card";
-
-		qcom,audio-routing =
-			"RX_BIAS", "MCLK",
-			"LDO_H", "MCLK",
-			"SPK_OUT", "MCLK",
-			"SPK_OUT", "EXT_VDD_SPKR",
-			"Lineout_1 amp", "LINEOUT1",
-			"Lineout_2 amp", "LINEOUT2",
-			"AMIC1", "MIC BIAS1 External",
-			"MIC BIAS1 External", "Handset Mic",
-			"AMIC2", "MIC BIAS2 External",
-			"MIC BIAS2 External", "Headset Mic",
-			"AMIC3", "MIC BIAS1 External",
-			"MIC BIAS1 External", "ANCRight Headset Mic",
-			"AMIC4", "MIC BIAS2 External",
-			"MIC BIAS2 External", "ANCLeft Headset Mic";
-
-		qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
-		qcom,cdc-lineout-spkr-gpios = <&pm8226_gpios 2 0>;
-		qcom,cdc-vdd-spkr-gpios;
-		qcom,cdc-us-euro-gpios;
-	};
-
-    sound-9302 {
-          qcom,model = "msm8226-tapan9302-skuf-snd-card";
-
-          qcom,audio-routing =
-              "RX_BIAS", "MCLK",
-              "LDO_H", "MCLK",
-              "SPK_OUT", "MCLK",
-              "SPK_OUT", "EXT_VDD_SPKR",
-              "Lineout_1 amp", "LINEOUT1",
-              "Lineout_2 amp", "LINEOUT2",
-              "AMIC1", "MIC BIAS1 External",
-              "MIC BIAS1 External", "Handset Mic",
-              "AMIC2", "MIC BIAS2 External",
-              "MIC BIAS2 External", "Headset Mic",
-              "AMIC3", "MIC BIAS1 External",
-              "MIC BIAS1 External", "Handset Mic";
-
-          qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
-          qcom,cdc-lineout-spkr-gpios = <&pm8226_gpios 2 0>;
-          qcom,cdc-vdd-spkr-gpios;
-          qcom,cdc-us-euro-gpios;
-        };
-
-	tp_power: regulator-tp {
-		compatible = "regulator-fixed";
-		regulator-name = "tp_power";
-		regulator-min-microvolt = <2800000>;
-		regulator-max-microvolt = <2800000>;
-		gpio = <&msmgpio 15 0>;
-		startup-delay-us = <20000>;
-		enable-active-high;
-	};
-
-	i2c@f9927000 {
-		goodix@5d {
-			compatible = "goodix,gt9xx";
-			reg = <0x5d>;
-			interrupt-parent = <&msmgpio>;
-			interrupts = <17 0x2008>;
-			reset-gpios = <&msmgpio 16 0x00>;
-			interrupt-gpios = <&msmgpio 17 0x00>;
-			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,family-id = <0x0>;
-			goodix,cfg-data = [
-			41 D0 02 00 05 0A 35 01 01 0F
-			2D 08 55 32 03 04 00 00 00 00
-			00 00 05 0A 0C 0F 0A 8C 0E 0E
-			30 2E B8 08 00 00 00 83 03 1D
-			00 00 00 00 00 00 00 00 00 00
-			00 2D 62 94 C5 02 05 00 00 04
-			96 30 00 80 39 00 71 42 00 63
-			4D 00 56 5A 00 56 10 38 68 00
-			56 50 35 AA AA 27 00 00 00 00
-			00 01 1B 14 0C 14 00 00 01 00
-			00 00 00 00 00 00 00 00 00 00
-			00 00 02 04 06 08 0A 0C 0E 10
-			12 14 16 18 1A 1C FF FF FF FF
-			FF FF FF FF FF FF FF FF FF FF
-			FF FF 00 02 04 06 08 0A 0C 0F
-			10 12 13 14 16 18 1C 1D 1E 1F
-			20 21 22 24 26 28 29 2A FF FF
-			FF FF FF FF FF FF FF FF FF FF
-			FF FF FF FF 06 01];
-		};
-	};
-};
-
-&spmi_bus {
-	qcom,pm8226@0 {
-		qcom,leds@a300 {
-			status = "disabled";
-		};
-
-		qcom,leds@a500 {
-			status = "disabled";
-		};
-	};
-
-	qcom,pm8226@1 {
-		qcom,leds@d800 {
-			status = "disabled";
-		};
-	};
-};
-
-&pm8226_mpps {
-	mpp@a300 { /* MPP 4 */
-		/* camera2_id */
-		qcom,mode = <4>; /* AIN input */
-		qcom,invert = <1>; /* Enable MPP */
-		qcom,ain-route = <3>; /* AMUX 8 */
-		qcom,master-en = <1>;
-		qcom,src-sel = <0>; /* Function constant */
-	};
-
-	mpp@a500 { /* MPP 6 */
-		/* camera_id */
-		qcom,mode = <4>; /* AIN input */
-		qcom,invert = <1>; /* Enable MPP */
-		qcom,ain-route = <1>; /* AMUX 6 */
-		qcom,master-en = <1>;
-		qcom,src-sel = <0>; /* Function constant */
-	};
-
-};
-
-&pm8226_vadc {
-	chan@13 {
-		label = "camera2_id";
-		reg = <0x13>;
-		qcom,decimation = <0>;
-		qcom,pre-div-channel-scaling = <0>;
-		qcom,calibration-type = "absolute";
-		qcom,scale-function = <0>;
-		qcom,hw-settle-time = <0>;
-		qcom,fast-avg-setup = <0>;
-	};
-
-	chan@15 {
-		label = "camera_id";
-		reg = <0x15>;
-		qcom,decimation = <0>;
-		qcom,pre-div-channel-scaling = <0>;
-		qcom,calibration-type = "absolute";
-		qcom,scale-function = <0>;
-		qcom,hw-settle-time = <0>;
-		qcom,fast-avg-setup = <0>;
-	};
-};
-
-&qrd_batterydata {
-	qcom,rpull-up-kohm = <100>;
-	qcom,vref-batt-therm = <1800000>;
-
-	/include/ "batterydata-qrd-4v35-2500mah.dtsi"
-};
-
 &pm8226_bms {
 	qcom,use-external-rsense;
-	qcom,battery-data = <&qrd_batterydata>;
-};
-
-&pm8226_chg {
-	qcom,battery-data = <&qrd_batterydata>;
 };
 
 &pm8226_iadc {
 	qcom,rsense = <10000000>;
 };
-
-&mdss_dsi0 {
-	qcom,dsi-pref-prim-pan = <&dsi_nt35521_720_vid>;
-};
-
-&dsi_nt35521_720_vid {
-	qcom,cont-splash-enabled;
-};
diff --git a/arch/arm/boot/dts/msm8610-bus.dtsi b/arch/arm/boot/dts/msm8610-bus.dtsi
index 6b72e66..c6e81d8 100644
--- a/arch/arm/boot/dts/msm8610-bus.dtsi
+++ b/arch/arm/boot/dts/msm8610-bus.dtsi
@@ -56,8 +56,8 @@
 			qcom,ws = <10000>;
 			qcom,qport = <2>;
 			qcom,mas-hw-id = <11>;
-			qcom,prio1 = <2>;
-			qcom,prio0 = <2>;
+			qcom,prio1 = <3>;
+			qcom,prio0 = <3>;
 		};
 
 		mas-mdpe {
@@ -71,8 +71,8 @@
 			qcom,ws = <10000>;
 			qcom,qport = <7>;
 			qcom,mas-hw-id = <11>;
-			qcom,prio1 = <2>;
-			qcom,prio0 = <2>;
+			qcom,prio1 = <1>;
+			qcom,prio0 = <1>;
 		};
 
 		fab-bimc {
@@ -913,7 +913,7 @@
 		qcom,fabclk-dual = "mem_clk";
 		qcom,fabclk-active = "mem_a_clk";
 		qcom,ntieredslaves = <0>;
-		qcom,qos-freq = <4800>;
+		qcom,qos-freq = <19200>;
 		qcom,hw-sel = "BIMC";
 		qcom,rpm-en;
 
@@ -930,13 +930,19 @@
 			qcom,masterp = <0>;
 			qcom,tier = <2>;
 			qcom,hw-sel = "BIMC";
-			qcom,mode = "Fixed";
+			qcom,mode = "Limiter";
 			qcom,qport = <0>;
 			qcom,ws = <10000>;
 			qcom,mas-hw-id = <0>;
 			qcom,prio-rd = <0>;
 			qcom,prio-wr = <0>;
 			qcom,prio-lvl = <0>;
+			qcom,mode-thresh = "Fixed";
+			qcom,thresh = <800000>;
+			qcom,dual-conf;
+			qcom,bimc,bw = <300000>;
+			qcom,bimc,gp = <5>;
+			qcom,bimc,thmp = <50>;
 		};
 
 		mas-mss-proc {
diff --git a/arch/arm/boot/dts/msm8610-mtp.dtsi b/arch/arm/boot/dts/msm8610-mtp.dtsi
index e597353..8d0e201 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8610-mtp.dtsi
@@ -131,6 +131,17 @@
 			capella,ps_conf1_val = <0x0006>;
 			capella,ps_conf3_val = <0x3010>;
 		};
+		nfc-nci@0e {
+			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 = "GPCLK";
+			interrupt-parent = <&msmgpio>;
+			interrupts = <77 0>;
+			qcom,clk-gpio = <&pm8110_gpios 1 0>;
+		};
 	};
 
 	gen-vkeys {
@@ -374,6 +385,11 @@
 
 &pm8110_gpios {
 	gpio@c000 { /* GPIO 1 */
+		qcom,mode = <0>;		/* QPNP_PIN_MODE_DIG_IN */
+		qcom,pull = <5>;		/* QPNP_PIN_PULL_NO */
+		qcom,vin-sel = <2>;		/* QPNP_PIN_VIN2 */
+		qcom,src-sel = <2>;		/* QPNP_PIN_SEL_FUNC_1 */
+		qcom,master-en = <1>;
 	};
 
 	gpio@c100 { /* GPIO 2 */
diff --git a/arch/arm/boot/dts/msm8610-regulator.dtsi b/arch/arm/boot/dts/msm8610-regulator.dtsi
index eb69678..f97d991 100644
--- a/arch/arm/boot/dts/msm8610-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8610-regulator.dtsi
@@ -391,3 +391,7 @@
 		};
 	};
 };
+
+&pm8110_chg_batif {
+	regulator-name = "batfet";
+};
diff --git a/arch/arm/boot/dts/msm8610-v1-pm.dtsi b/arch/arm/boot/dts/msm8610-v1-pm.dtsi
index 4a2de1c..e560447 100644
--- a/arch/arm/boot/dts/msm8610-v1-pm.dtsi
+++ b/arch/arm/boot/dts/msm8610-v1-pm.dtsi
@@ -113,8 +113,8 @@
 			qcom,mode = "wfi";
 			qcom,l2 = "l2_cache_active";
 			qcom,latency-us = <1>;
-			qcom,ss-power = <784>;
-			qcom,energy-overhead = <190000>;
+			qcom,ss-power = <530>;
+			qcom,energy-overhead = <52800>;
 			qcom,time-overhead = <100>;
 		};
 
@@ -122,30 +122,30 @@
 			reg = <0x1>;
 			qcom,mode = "standalone_pc";
 			qcom,l2 = "l2_cache_active";
-			qcom,latency-us = <3000>;
-			qcom,ss-power = <725>;
-			qcom,energy-overhead = <99500>;
-			qcom,time-overhead = <3130>;
+			qcom,latency-us = <500>;
+			qcom,ss-power = <410>;
+			qcom,energy-overhead = <603400>;
+			qcom,time-overhead = <1200>;
 		};
 
 		qcom,lpm-level@2 {
 			reg = <0x2>;
 			qcom,mode = "pc";
 			qcom,l2 = "l2_cache_retention";
-			qcom,latency-us = <20000>;
-			qcom,ss-power = <138>;
-			qcom,energy-overhead = <1208400>;
-			qcom,time-overhead = <9200>;
+			qcom,latency-us = <520>;
+			qcom,ss-power = <460>;
+			qcom,energy-overhead = <704900>;
+			qcom,time-overhead = <1300>;
 		};
 
 		qcom,lpm-level@3 {
 			reg = <0x3>;
 			qcom,mode = "pc";
 			qcom,l2 = "l2_cache_pc";
-			qcom,latency-us = <30000>;
-			qcom,ss-power = <110>;
-			qcom,energy-overhead = <1250300>;
-			qcom,time-overhead = <9500>;
+			qcom,latency-us = <11700>;
+			qcom,ss-power = <315>;
+			qcom,energy-overhead = <1027150>;
+			qcom,time-overhead = <2400>;
 		};
 	};
 
diff --git a/arch/arm/boot/dts/msm8610-v2-pm.dtsi b/arch/arm/boot/dts/msm8610-v2-pm.dtsi
index 079f0b1..72509c1 100644
--- a/arch/arm/boot/dts/msm8610-v2-pm.dtsi
+++ b/arch/arm/boot/dts/msm8610-v2-pm.dtsi
@@ -115,8 +115,8 @@
 			qcom,mode = "wfi";
 			qcom,l2 = "l2_cache_active";
 			qcom,latency-us = <1>;
-			qcom,ss-power = <784>;
-			qcom,energy-overhead = <190000>;
+			qcom,ss-power = <530>;
+			qcom,energy-overhead = <52800>;
 			qcom,time-overhead = <100>;
 		};
 
@@ -124,30 +124,30 @@
 			reg = <0x1>;
 			qcom,mode = "standalone_pc";
 			qcom,l2 = "l2_cache_active";
-			qcom,latency-us = <3000>;
-			qcom,ss-power = <725>;
-			qcom,energy-overhead = <99500>;
-			qcom,time-overhead = <3130>;
+			qcom,latency-us = <500>;
+			qcom,ss-power = <410>;
+			qcom,energy-overhead = <603400>;
+			qcom,time-overhead = <1200>;
 		};
 
 		qcom,lpm-level@2 {
 			reg = <0x2>;
 			qcom,mode = "pc";
 			qcom,l2 = "l2_cache_gdhs";
-			qcom,latency-us = <20000>;
-			qcom,ss-power = <138>;
-			qcom,energy-overhead = <1208400>;
-			qcom,time-overhead = <9200>;
+			qcom,latency-us = <10700>;
+			qcom,ss-power = <325>;
+			qcom,energy-overhead = <441250>;
+			qcom,time-overhead = <1020>;
 		};
 
 		qcom,lpm-level@3 {
 			reg = <0x3>;
 			qcom,mode = "pc";
 			qcom,l2 = "l2_cache_pc";
-			qcom,latency-us = <30000>;
-			qcom,ss-power = <110>;
-			qcom,energy-overhead = <1250300>;
-			qcom,time-overhead = <9500>;
+			qcom,latency-us = <11700>;
+			qcom,ss-power = <315>;
+			qcom,energy-overhead = <1027150>;
+			qcom,time-overhead = <2400>;
 		};
 	};
 
diff --git a/arch/arm/boot/dts/msm8926.dtsi b/arch/arm/boot/dts/msm8926.dtsi
index e9b7b0b..bbddec3 100644
--- a/arch/arm/boot/dts/msm8926.dtsi
+++ b/arch/arm/boot/dts/msm8926.dtsi
@@ -49,6 +49,50 @@
 		qcom,cpu-sensors = "tsens_tz_sensor5", "tsens_tz_sensor5",
 				"tsens_tz_sensor1", "tsens_tz_sensor1";
 	};
+
+	qcom,mpm@fc4281d0 {
+		qcom,gpio-map = <3  1>,
+			<4  4 >,
+			<5  5 >,
+			<6  9 >,
+			<7  13>,
+			<8  17>,
+			<9  21>,
+			<10  27>,
+			<11  29>,
+			<12  31>,
+			<13  33>,
+			<14  35>,
+			<15  37>,
+			<16  38>,
+			<17  39>,
+			<18  41>,
+			<19  46>,
+			<20  48>,
+			<21  49>,
+			<22  50>,
+			<23  51>,
+			<24  52>,
+			<25  54>,
+			<26  62>,
+			<27  63>,
+			<28  64>,
+			<29  65>,
+			<30  66>,
+			<31  67>,
+			<32  68>,
+			<33  69>,
+			<34  71>,
+			<35  72>,
+			<36  106>,
+			<37  107>,
+			<38  108>,
+			<39  109>,
+			<40  110>,
+			<41  119>,
+			<54  111>,
+			<55  113>;
+	};
 };
 
 &pm8226_l3 {
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
index 9cbd45c..c84dfe5 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
@@ -78,6 +78,7 @@
 		qcom,mount-angle = <270>;
 		qcom,sensor-name = "imx135";
 		qcom,actuator-src = <&actuator1>;
+		qcom,led-flash-src = <&led_flash0>;
 		cam_vdig-supply = <&pm8941_l3>;
 		cam_vana-supply = <&pm8941_l17>;
 		cam_vio-supply = <&pm8941_lvs3>;
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi
index 68af4a6..02d2288 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi
@@ -78,6 +78,7 @@
 		qcom,mount-angle = <90>;
 		qcom,sensor-name = "imx135";
 		qcom,actuator-src = <&actuator1>;
+		qcom,led-flash-src = <&led_flash0>;
 		cam_vdig-supply = <&pm8941_l3>;
 		cam_vana-supply = <&pm8941_l17>;
 		cam_vio-supply = <&pm8941_lvs3>;
diff --git a/arch/arm/boot/dts/msm8974-regulator.dtsi b/arch/arm/boot/dts/msm8974-regulator.dtsi
index a88a709..344c26f 100644
--- a/arch/arm/boot/dts/msm8974-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974-regulator.dtsi
@@ -560,6 +560,10 @@
 	regulator-name = "8941_smbb_boost";
 };
 
+&pm8941_chg_batif  {
+	regulator-name = "batfet";
+};
+
 &pm8941_chg_otg {
 	regulator-name = "8941_smbb_otg";
 };
diff --git a/arch/arm/boot/dts/msm8974pro-ab-cdp.dts b/arch/arm/boot/dts/msm8974pro-ab-cdp.dts
index fae72fa..646eb56 100644
--- a/arch/arm/boot/dts/msm8974pro-ab-cdp.dts
+++ b/arch/arm/boot/dts/msm8974pro-ab-cdp.dts
@@ -18,7 +18,8 @@
 / {
 	model = "Qualcomm MSM 8974Pro CDP";
 	compatible = "qcom,msm8974-cdp", "qcom,msm8974", "qcom,cdp";
-	qcom,msm-id = <209 1 0x10000>,
+	qcom,msm-id = <208 1 0x10000>,
+		      <209 1 0x10000>,
 		      <211 1 0x10000>,
 		      <212 1 0x10000>,
 		      <214 1 0x10000>,
diff --git a/arch/arm/boot/dts/msm8974pro-ac-pm8941.dtsi b/arch/arm/boot/dts/msm8974pro-ac-pm8941.dtsi
index cc4b6ed..811b2ef 100644
--- a/arch/arm/boot/dts/msm8974pro-ac-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-ac-pm8941.dtsi
@@ -90,6 +90,10 @@
 	regulator-name = "8941_smbb_boost";
 };
 
+&pm8941_chg_batif {
+	regulator-name = "batfet";
+};
+
 &pm8941_chg_otg {
 	regulator-name = "8941_smbb_otg";
 };
diff --git a/arch/arm/boot/dts/msm8974pro-ion.dtsi b/arch/arm/boot/dts/msm8974pro-ion.dtsi
index 7faee21..4c427bf 100644
--- a/arch/arm/boot/dts/msm8974pro-ion.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-ion.dtsi
@@ -17,7 +17,7 @@
 			compatible = "qcom,msm-ion-reserve";
 			reg = <23>;
 			qcom,heap-align = <0x1000>;
-			qcom,memory-fixed = <0x05400000 0x2700000>;
+			qcom,memory-fixed = <0x05a00000 0x2100000>;
 		};
 
 		qcom,ion-heap@26 { /* MODEM HEAP */
diff --git a/arch/arm/boot/dts/msm8974pro.dtsi b/arch/arm/boot/dts/msm8974pro.dtsi
index 86f0058..f45d75e 100644
--- a/arch/arm/boot/dts/msm8974pro.dtsi
+++ b/arch/arm/boot/dts/msm8974pro.dtsi
@@ -46,6 +46,8 @@
 	/* Updated chip ID */
 	qcom,chipid = <0x03030002>;
 
+	qcom,initial-pwrlevel = <6>;
+
 	/* Updated bus bandwidth requirements */
 	qcom,msm-bus,vectors-KBps =
 		/* Off */
@@ -69,41 +71,69 @@
 
                qcom,gpu-pwrlevel@0 {
                        reg = <0>;
-                       qcom,gpu-freq = <550000000>;
+                       qcom,gpu-freq = <578000000>;
                        qcom,bus-freq = <5>;
                        qcom,io-fraction = <33>;
                };
 
-               qcom,gpu-pwrlevel@1 {
-                       reg = <1>;
-                       qcom,gpu-freq = <320000000>;
+		qcom,gpu-pwrlevel@1 {
+			reg = <1>;
+			qcom,gpu-freq = <462400000>;
+			qcom,bus-freq = <4>;
+			qcom,io-fraction = <33>;
+		};
+
+		qcom,gpu-pwrlevel@2 {
+			reg = <2>;
+			qcom,gpu-freq = <462400000>;
+			qcom,bus-freq = <3>;
+			qcom,io-fraction = <66>;
+		};
+
+		qcom,gpu-pwrlevel@3 {
+			reg = <3>;
+			qcom,gpu-freq = <389000000>;
+			qcom,bus-freq = <4>;
+			qcom,io-fraction = <66>;
+		};
+
+		qcom,gpu-pwrlevel@4 {
+			reg = <4>;
+			qcom,gpu-freq = <389000000>;
+			qcom,bus-freq = <3>;
+			qcom,io-fraction = <66>;
+		};
+
+               qcom,gpu-pwrlevel@5 {
+                       reg = <5>;
+                       qcom,gpu-freq = <330000000>;
                        qcom,bus-freq = <4>;
                        qcom,io-fraction = <66>;
                };
 
-               qcom,gpu-pwrlevel@2 {
-                       reg = <2>;
-                       qcom,gpu-freq = <320000000>;
+               qcom,gpu-pwrlevel@6 {
+                       reg = <6>;
+                       qcom,gpu-freq = <330000000>;
                        qcom,bus-freq = <3>;
                        qcom,io-fraction = <66>;
                };
 
-               qcom,gpu-pwrlevel@3 {
-                       reg = <3>;
+               qcom,gpu-pwrlevel@7 {
+                       reg = <7>;
                        qcom,gpu-freq = <200000000>;
                        qcom,bus-freq = <2>;
                        qcom,io-fraction = <100>;
                };
 
-               qcom,gpu-pwrlevel@4 {
-                       reg = <4>;
+               qcom,gpu-pwrlevel@8 {
+                       reg = <8>;
                        qcom,gpu-freq = <200000000>;
                        qcom,bus-freq = <1>;
                        qcom,io-fraction = <100>;
                };
 
-               qcom,gpu-pwrlevel@5 {
-                       reg = <5>;
+               qcom,gpu-pwrlevel@9 {
+                       reg = <9>;
                        qcom,gpu-freq = <27000000>;
                        qcom,bus-freq = <0>;
                        qcom,io-fraction = <0>;
@@ -203,5 +233,6 @@
 };
 
 &memory_hole {
-	qcom,memblock-remove = <0x05400000 0xab00000>; /* Address and size of the hole */
+	qcom,memblock-remove = <0x05a00000 0x7800000
+				0x0fa00000 0x500000>; /* Address and size of the hole */
 };
diff --git a/arch/arm/configs/msm8226-perf_defconfig b/arch/arm/configs/msm8226-perf_defconfig
index b822288..108907a 100644
--- a/arch/arm/configs/msm8226-perf_defconfig
+++ b/arch/arm/configs/msm8226-perf_defconfig
@@ -234,7 +234,6 @@
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
 CONFIG_TUN=y
-CONFIG_KS8851=y
 # CONFIG_MSM_RMNET is not set
 CONFIG_MSM_RMNET_BAM=y
 CONFIG_PPP=y
@@ -350,6 +349,7 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_EHSET=y
 CONFIG_USB_EHCI_MSM=y
+CONFIG_USB_EHCI_MSM_HSIC=y
 CONFIG_USB_ACM=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_STORAGE_DATAFAB=y
diff --git a/arch/arm/configs/msm8226_defconfig b/arch/arm/configs/msm8226_defconfig
index 546b6b9..6d50e8d 100644
--- a/arch/arm/configs/msm8226_defconfig
+++ b/arch/arm/configs/msm8226_defconfig
@@ -236,7 +236,6 @@
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
 CONFIG_TUN=y
-CONFIG_KS8851=y
 # CONFIG_MSM_RMNET is not set
 CONFIG_MSM_RMNET_BAM=y
 CONFIG_PPP=y
@@ -376,6 +375,7 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_EHSET=y
 CONFIG_USB_EHCI_MSM=y
+CONFIG_USB_EHCI_MSM_HSIC=y
 CONFIG_USB_ACM=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_STORAGE_DATAFAB=y
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index b91ce3c..c572ad8 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -412,3 +412,4 @@
 CONFIG_SENSORS_MMA8X5X=y
 CONFIG_LOGCAT_SIZE=64
 CONFIG_SENSORS_CAPELLA_CM36283=y
+CONFIG_NFC_QNCI=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 93e8f0f..6a7097d 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -443,6 +443,7 @@
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_ARC4=y
 CONFIG_CRYPTO_TWOFISH=y
+CONFIG_NFC_QNCI=y
 CONFIG_CRYPTO_DEV_QCRYPTO=m
 CONFIG_CRYPTO_DEV_QCE=y
 CONFIG_CRYPTO_DEV_QCEDEV=m
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index 329fcec..fb05a08 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -340,6 +340,7 @@
 CONFIG_MT9M114=y
 CONFIG_OV2720=y
 CONFIG_IMX135=y
+CONFIG_IMX132=y
 CONFIG_MSM_CAMERA_SENSOR=y
 CONFIG_MSM_EEPROM=y
 CONFIG_MSM_CPP=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 812faf6..b26a028 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -348,6 +348,7 @@
 CONFIG_MT9M114=y
 CONFIG_OV2720=y
 CONFIG_IMX135=y
+CONFIG_IMX132=y
 CONFIG_MSM_CAMERA_SENSOR=y
 CONFIG_MSM_EEPROM=y
 CONFIG_MSM_CPP=y
diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h
index 38050b1..56211f2 100644
--- a/arch/arm/include/asm/elf.h
+++ b/arch/arm/include/asm/elf.h
@@ -130,4 +130,10 @@
 extern unsigned long arch_randomize_brk(struct mm_struct *mm);
 #define arch_randomize_brk arch_randomize_brk
 
+#ifdef CONFIG_MMU
+#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
+struct linux_binprm;
+int arch_setup_additional_pages(struct linux_binprm *, int);
+#endif
+
 #endif
diff --git a/arch/arm/include/asm/mach/irq.h b/arch/arm/include/asm/mach/irq.h
index febe495..15cb035 100644
--- a/arch/arm/include/asm/mach/irq.h
+++ b/arch/arm/include/asm/mach/irq.h
@@ -17,7 +17,7 @@
 /*
  * This is internal.  Do not use it.
  */
-extern void init_FIQ(void);
+extern void init_FIQ(int);
 extern int show_fiq_list(struct seq_file *, int);
 
 #ifdef CONFIG_MULTI_IRQ_HANDLER
diff --git a/arch/arm/include/asm/mmu.h b/arch/arm/include/asm/mmu.h
index b8e580a..cf0c81f 100644
--- a/arch/arm/include/asm/mmu.h
+++ b/arch/arm/include/asm/mmu.h
@@ -9,6 +9,7 @@
 	raw_spinlock_t id_lock;
 #endif
 	unsigned int kvm_seq;
+	unsigned long	sigpage;
 } mm_context_t;
 
 #ifdef CONFIG_CPU_HAS_ASID
diff --git a/arch/arm/include/asm/page.h b/arch/arm/include/asm/page.h
index afc1ca7..673205e 100644
--- a/arch/arm/include/asm/page.h
+++ b/arch/arm/include/asm/page.h
@@ -151,7 +151,9 @@
 #define clear_page(page)	memset((void *)(page), 0, PAGE_SIZE)
 extern void copy_page(void *to, const void *from);
 
+#ifdef CONFIG_KUSER_HELPERS
 #define __HAVE_ARCH_GATE_AREA 1
+#endif
 
 #ifdef CONFIG_ARM_LPAE
 #include <asm/pgtable-3level-types.h>
diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
index 67d6443..2eb0c2c 100644
--- a/arch/arm/include/asm/thread_info.h
+++ b/arch/arm/include/asm/thread_info.h
@@ -58,7 +58,7 @@
 	struct cpu_context_save	cpu_context;	/* cpu context */
 	__u32			syscall;	/* syscall number */
 	__u8			used_cp[16];	/* thread used copro */
-	unsigned long		tp_value;
+	unsigned long		tp_value[2];	/* TLS registers */
 	struct crunch_state	crunchstate;
 	union fp_state		fpstate __attribute__((aligned(8)));
 	union vfp_state		vfpstate;
diff --git a/arch/arm/include/asm/tls.h b/arch/arm/include/asm/tls.h
index 73409e6..83259b8 100644
--- a/arch/arm/include/asm/tls.h
+++ b/arch/arm/include/asm/tls.h
@@ -2,27 +2,30 @@
 #define __ASMARM_TLS_H
 
 #ifdef __ASSEMBLY__
-	.macro set_tls_none, tp, tmp1, tmp2
+#include <asm/asm-offsets.h>
+	.macro switch_tls_none, base, tp, tpuser, tmp1, tmp2
 	.endm
 
-	.macro set_tls_v6k, tp, tmp1, tmp2
+	.macro switch_tls_v6k, base, tp, tpuser, tmp1, tmp2
+	mrc	p15, 0, \tmp2, c13, c0, 2	@ get the user r/w register
 	mcr	p15, 0, \tp, c13, c0, 3		@ set TLS register
-	mov	\tmp1, #0
-	mcr	p15, 0, \tmp1, c13, c0, 2	@ clear user r/w TLS register
+	mcr	p15, 0, \tpuser, c13, c0, 2	@ and the user r/w register
+	str	\tmp2, [\base, #TI_TP_VALUE + 4] @ save it
 	.endm
 
-	.macro set_tls_v6, tp, tmp1, tmp2
+	.macro switch_tls_v6, base, tp, tpuser, tmp1, tmp2
 	ldr	\tmp1, =elf_hwcap
 	ldr	\tmp1, [\tmp1, #0]
 	mov	\tmp2, #0xffff0fff
 	tst	\tmp1, #HWCAP_TLS		@ hardware TLS available?
-	mcrne	p15, 0, \tp, c13, c0, 3		@ yes, set TLS register
-	movne	\tmp1, #0
-	mcrne	p15, 0, \tmp1, c13, c0, 2	@ clear user r/w TLS register
 	streq	\tp, [\tmp2, #-15]		@ set TLS value at 0xffff0ff0
+	mrcne	p15, 0, \tmp2, c13, c0, 2	@ get the user r/w register
+	mcrne	p15, 0, \tp, c13, c0, 3		@ yes, set TLS register
+	mcrne	p15, 0, \tpuser, c13, c0, 2	@ set user r/w register
+	strne	\tmp2, [\base, #TI_TP_VALUE + 4] @ save it
 	.endm
 
-	.macro set_tls_software, tp, tmp1, tmp2
+	.macro switch_tls_software, base, tp, tpuser, tmp1, tmp2
 	mov	\tmp1, #0xffff0fff
 	str	\tp, [\tmp1, #-15]		@ set TLS value at 0xffff0ff0
 	.endm
@@ -31,19 +34,30 @@
 #ifdef CONFIG_TLS_REG_EMUL
 #define tls_emu		1
 #define has_tls_reg		1
-#define set_tls		set_tls_none
+#define switch_tls	switch_tls_none
 #elif defined(CONFIG_CPU_V6)
 #define tls_emu		0
 #define has_tls_reg		(elf_hwcap & HWCAP_TLS)
-#define set_tls		set_tls_v6
+#define switch_tls	switch_tls_v6
 #elif defined(CONFIG_CPU_32v6K)
 #define tls_emu		0
 #define has_tls_reg		1
-#define set_tls		set_tls_v6k
+#define switch_tls	switch_tls_v6k
 #else
 #define tls_emu		0
 #define has_tls_reg		0
-#define set_tls		set_tls_software
+#define switch_tls	switch_tls_software
 #endif
 
+#ifndef __ASSEMBLY__
+static inline unsigned long get_tpuser(void)
+{
+	unsigned long reg = 0;
+
+	if (has_tls_reg && !tls_emu)
+		__asm__("mrc p15, 0, %0, c13, c0, 2" : "=r" (reg));
+
+	return reg;
+}
+#endif
 #endif	/* __ASMARM_TLS_H */
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 9f52940..317400a 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -698,15 +698,16 @@
  UNWIND(.fnstart	)
  UNWIND(.cantunwind	)
 	add	ip, r1, #TI_CPU_SAVE
-	ldr	r3, [r2, #TI_TP_VALUE]
  ARM(	stmia	ip!, {r4 - sl, fp, sp, lr} )	@ Store most regs on stack
  THUMB(	stmia	ip!, {r4 - sl, fp}	   )	@ Store most regs on stack
  THUMB(	str	sp, [ip], #4		   )
  THUMB(	str	lr, [ip], #4		   )
+	ldr	r4, [r2, #TI_TP_VALUE]
+	ldr	r5, [r2, #TI_TP_VALUE + 4]
 #ifdef CONFIG_CPU_USE_DOMAINS
 	ldr	r6, [r2, #TI_CPU_DOMAIN]
 #endif
-	set_tls	r3, r4, r5
+	switch_tls r1, r4, r5, r3, r7
 #if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
 	ldr	r7, [r2, #TI_TASK]
 	ldr	r8, =__stack_chk_guard
@@ -754,6 +755,18 @@
 #endif
 	.endm
 
+	.macro	kuser_pad, sym, size
+	.if	(. - \sym) & 3
+	.rept	4 - (. - \sym) & 3
+	.byte	0
+	.endr
+	.endif
+	.rept	(\size - (. - \sym)) / 4
+	.word	0xe7fddef1
+	.endr
+	.endm
+
+#ifdef CONFIG_KUSER_HELPERS
 	.align	5
 	.globl	__kuser_helper_start
 __kuser_helper_start:
@@ -935,18 +948,13 @@
 #error "incoherent kernel configuration"
 #endif
 
-	/* pad to next slot */
-	.rept	(16 - (. - __kuser_cmpxchg64)/4)
-	.word	0
-	.endr
-
-	.align	5
+	kuser_pad __kuser_cmpxchg64, 64
 
 __kuser_memory_barrier:				@ 0xffff0fa0
 	smp_dmb	arm
 	usr_ret	lr
 
-	.align	5
+	kuser_pad __kuser_memory_barrier, 32
 
 __kuser_cmpxchg:				@ 0xffff0fc0
 
@@ -1019,13 +1027,14 @@
 
 #endif
 
-	.align	5
+	kuser_pad __kuser_cmpxchg, 32
 
 __kuser_get_tls:				@ 0xffff0fe0
 	ldr	r0, [pc, #(16 - 8)]	@ read TLS, set in kuser_get_tls_init
 	usr_ret	lr
 	mrc	p15, 0, r0, c13, c0, 3	@ 0xffff0fe8 hardware TLS code
-	.rep	4
+	kuser_pad __kuser_get_tls, 16
+	.rep	3
 	.word	0			@ 0xffff0ff0 software TLS value, then
 	.endr				@ pad up to __kuser_helper_version
 
@@ -1035,14 +1044,16 @@
 	.globl	__kuser_helper_end
 __kuser_helper_end:
 
+#endif
+
  THUMB(	.thumb	)
 
 /*
  * Vector stubs.
  *
- * This code is copied to 0xffff0200 so we can use branches in the
- * vectors, rather than ldr's.  Note that this code must not
- * exceed 0x300 bytes.
+ * This code is copied to 0xffff1000 so we can use branches in the
+ * vectors, rather than ldr's.  Note that this code must not exceed
+ * a page size.
  *
  * Common stub entry macro:
  *   Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
@@ -1101,8 +1112,17 @@
 1:
 	.endm
 
-	.globl	__stubs_start
+	.section .stubs, "ax", %progbits
 __stubs_start:
+	@ This must be the first word
+	.word	vector_swi
+
+vector_rst:
+ ARM(	swi	SYS_ERROR0	)
+ THUMB(	svc	#0		)
+ THUMB(	nop			)
+	b	vector_und
+
 /*
  * Interrupt dispatcher
  */
@@ -1197,6 +1217,16 @@
 	.align	5
 
 /*=============================================================================
+ * Address exception handler
+ *-----------------------------------------------------------------------------
+ * These aren't too critical.
+ * (they're not supposed to happen, and won't happen in 32-bit data mode).
+ */
+
+vector_addrexcptn:
+	b	vector_addrexcptn
+
+/*=============================================================================
  * Undefined FIQs
  *-----------------------------------------------------------------------------
  * Enter in FIQ mode, spsr = ANY CPSR, lr = ANY PC
@@ -1209,47 +1239,22 @@
 vector_fiq:
 	subs	pc, lr, #4
 
-/*=============================================================================
- * Address exception handler
- *-----------------------------------------------------------------------------
- * These aren't too critical.
- * (they're not supposed to happen, and won't happen in 32-bit data mode).
- */
-
-vector_addrexcptn:
-	b	vector_addrexcptn
-
-/*
- * We group all the following data together to optimise
- * for CPUs with separate I & D caches.
- */
-	.align	5
-
-.LCvswi:
-	.word	vector_swi
 .krait_fixup:
 	.word	msm_krait_need_wfe_fixup
 
-	.globl	__stubs_end
-__stubs_end:
+	.globl	vector_fiq_offset
+	.equ	vector_fiq_offset, vector_fiq
 
-	.equ	stubs_offset, __vectors_start + 0x200 - __stubs_start
-
-	.globl	__vectors_start
+	.section .vectors, "ax", %progbits
 __vectors_start:
- ARM(	swi	SYS_ERROR0	)
- THUMB(	svc	#0		)
- THUMB(	nop			)
-	W(b)	vector_und + stubs_offset
-	W(ldr)	pc, .LCvswi + stubs_offset
-	W(b)	vector_pabt + stubs_offset
-	W(b)	vector_dabt + stubs_offset
-	W(b)	vector_addrexcptn + stubs_offset
-	W(b)	vector_irq + stubs_offset
-	W(b)	vector_fiq + stubs_offset
-
-	.globl	__vectors_end
-__vectors_end:
+	W(b)	vector_rst
+	W(b)	vector_und
+	W(ldr)	pc, __vectors_start + 0x1000
+	W(b)	vector_pabt
+	W(b)	vector_dabt
+	W(b)	vector_addrexcptn
+	W(b)	vector_irq
+	W(b)	vector_fiq
 
 	.data
 
diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c
index ca852c5..f9f16ef 100644
--- a/arch/arm/kernel/fiq.c
+++ b/arch/arm/kernel/fiq.c
@@ -48,6 +48,11 @@
 #include <asm/irq.h>
 #include <asm/traps.h>
 
+#define FIQ_OFFSET ({					\
+		extern void *vector_fiq_offset;		\
+		(unsigned)&vector_fiq_offset;		\
+	})
+
 static unsigned long no_fiq_insn;
 
 /* Default reacquire function
@@ -80,14 +85,14 @@
 
 void set_fiq_handler(void *start, unsigned int length)
 {
-#if defined(CONFIG_CPU_USE_DOMAINS)
-	memcpy((void *)0xffff001c, start, length);
-#else
-	memcpy(vectors_page + 0x1c, start, length);
-#endif
-	flush_icache_range(0xffff001c, 0xffff001c + length);
-	if (!vectors_high())
-		flush_icache_range(0x1c, 0x1c + length);
+	void *base = vectors_page;
+	unsigned offset = FIQ_OFFSET;
+
+	memcpy(base + offset, start, length);
+	if (!cache_is_vipt_nonaliasing())
+		flush_icache_range((unsigned long)base + offset, offset +
+				   length);
+	flush_icache_range(0xffff0000 + offset, 0xffff0000 + offset + length);
 }
 
 int claim_fiq(struct fiq_handler *f)
@@ -123,14 +128,16 @@
 	while (current_fiq->fiq_op(current_fiq->dev_id, 0));
 }
 
+static int fiq_start;
+
 void enable_fiq(int fiq)
 {
-	enable_irq(fiq + FIQ_START);
+	enable_irq(fiq + fiq_start);
 }
 
 void disable_fiq(int fiq)
 {
-	disable_irq(fiq + FIQ_START);
+	disable_irq(fiq + fiq_start);
 }
 
 void fiq_set_type(int fiq, unsigned int type)
@@ -147,7 +154,9 @@
 EXPORT_SYMBOL(disable_fiq);
 EXPORT_SYMBOL(fiq_set_type);
 
-void __init init_FIQ(void)
+void __init init_FIQ(int start)
 {
-	no_fiq_insn = *(unsigned long *)0xffff001c;
+	unsigned offset = FIQ_OFFSET;
+	no_fiq_insn = *(unsigned long *)(0xffff0000 + offset);
+	fiq_start = start;
 }
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index 0241da1..2a3ab6e 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -116,7 +116,12 @@
 static int
 armpmu_map_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config)
 {
-	int mapping = (*event_map)[config];
+	int mapping;
+
+	if (config >= PERF_COUNT_HW_MAX)
+		return -EINVAL;
+
+	mapping = (*event_map)[config];
 	return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping;
 }
 
@@ -341,6 +346,9 @@
 	struct hw_perf_event fake_event = event->hw;
 	struct pmu *leader_pmu = event->group_leader->pmu;
 
+	if (is_software_event(event))
+		return 1;
+
 	if (event->pmu != leader_pmu || event->state <= PERF_EVENT_STATE_OFF)
 		return 1;
 
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index fe97ff2..c5fa883 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -38,6 +38,7 @@
 #include <asm/thread_notify.h>
 #include <asm/stacktrace.h>
 #include <asm/mach/time.h>
+#include <asm/tls.h>
 
 #ifdef CONFIG_CC_STACKPROTECTOR
 #include <linux/stackprotector.h>
@@ -534,7 +535,8 @@
 	clear_ptrace_hw_breakpoint(p);
 
 	if (clone_flags & CLONE_SETTLS)
-		thread->tp_value = regs->ARM_r3;
+		thread->tp_value[0] = childregs->ARM_r3;
+	thread->tp_value[1] = get_tpuser();
 
 	thread_notify(THREAD_NOTIFY_COPY, thread);
 
@@ -650,10 +652,11 @@
 }
 
 #ifdef CONFIG_MMU
+#ifdef CONFIG_KUSER_HELPERS
 /*
  * The vectors page is always readable from user space for the
- * atomic helpers and the signal restart code. Insert it into the
- * gate_vma so that it is visible through ptrace and /proc/<pid>/mem.
+ * atomic helpers. Insert it into the gate_vma so that it is visible
+ * through ptrace and /proc/<pid>/mem.
  */
 static struct vm_area_struct gate_vma;
 
@@ -682,14 +685,53 @@
 {
 	return in_gate_area(NULL, addr);
 }
+#define is_gate_vma(vma)	((vma) == &gate_vma)
+#else
+#define is_gate_vma(vma)	0
+#endif
 
 const char *arch_vma_name(struct vm_area_struct *vma)
 {
-	if (vma == &gate_vma)
+	if (is_gate_vma(vma))
 		return "[vectors]";
+	else if (vma->vm_mm && vma->vm_start == vma->vm_mm->context.sigpage)
+		return "[sigpage]";
 	else if (vma == get_user_timers_vma(NULL))
 		return "[timers]";
 	else
 		return NULL;
 }
+
+static struct page *signal_page;
+extern struct page *get_signal_page(void);
+
+int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
+{
+	struct mm_struct *mm = current->mm;
+	unsigned long addr;
+	int ret;
+
+	if (!signal_page)
+		signal_page = get_signal_page();
+	if (!signal_page)
+		return -ENOMEM;
+
+	down_write(&mm->mmap_sem);
+	addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, 0);
+	if (IS_ERR_VALUE(addr)) {
+		ret = addr;
+		goto up_fail;
+	}
+
+	ret = install_special_mapping(mm, addr, PAGE_SIZE,
+		VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC,
+		&signal_page);
+
+	if (ret == 0)
+		mm->context.sigpage = addr;
+
+ up_fail:
+	up_write(&mm->mmap_sem);
+	return ret;
+}
 #endif
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 9650c14..c6c6be7 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -844,7 +844,7 @@
 #endif
 
 		case PTRACE_GET_THREAD_AREA:
-			ret = put_user(task_thread_info(child)->tp_value,
+			ret = put_user(task_thread_info(child)->tp_value[0],
 				       datap);
 			break;
 
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index d68d1b6..e000e5e 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -8,6 +8,7 @@
  * published by the Free Software Foundation.
  */
 #include <linux/errno.h>
+#include <linux/random.h>
 #include <linux/signal.h>
 #include <linux/personality.h>
 #include <linux/freezer.h>
@@ -16,10 +17,10 @@
 
 #include <asm/elf.h>
 #include <asm/cacheflush.h>
+#include <asm/traps.h>
 #include <asm/ucontext.h>
 #include <asm/unistd.h>
 #include <asm/vfp.h>
-
 #include "signal.h"
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
@@ -44,7 +45,7 @@
 #define SWI_THUMB_SIGRETURN	(0xdf00 << 16 | 0x2700 | (__NR_sigreturn - __NR_SYSCALL_BASE))
 #define SWI_THUMB_RT_SIGRETURN	(0xdf00 << 16 | 0x2700 | (__NR_rt_sigreturn - __NR_SYSCALL_BASE))
 
-const unsigned long sigreturn_codes[7] = {
+static const unsigned long sigreturn_codes[7] = {
 	MOV_R7_NR_SIGRETURN,    SWI_SYS_SIGRETURN,    SWI_THUMB_SIGRETURN,
 	MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN,
 };
@@ -112,6 +113,8 @@
 	return ret;
 }
 
+static unsigned long signal_return_offset;
+
 #ifdef CONFIG_CRUNCH
 static int preserve_crunch_context(struct crunch_sigframe __user *frame)
 {
@@ -460,13 +463,20 @@
 		    __put_user(sigreturn_codes[idx+1], rc+1))
 			return 1;
 
+#ifdef CONFIG_MMU
 		if (cpsr & MODE32_BIT) {
+			struct mm_struct *mm = current->mm;
+
 			/*
-			 * 32-bit code can use the new high-page
-			 * signal return code support.
+			 * 32-bit code can use the signal return page
+			 * except when the MPU has protected the vectors
+			 * page from PL0
 			 */
-			retcode = KERN_SIGRETURN_CODE + (idx << 2) + thumb;
-		} else {
+			retcode = mm->context.sigpage + signal_return_offset +
+				  (idx << 2) + thumb;
+		} else
+#endif
+		{
 			/*
 			 * Ensure that the instruction cache sees
 			 * the return code written onto the stack.
@@ -739,3 +749,33 @@
 			key_replace_session_keyring();
 	}
 }
+
+struct page *get_signal_page(void)
+{
+	unsigned long ptr;
+	unsigned offset;
+	struct page *page;
+	void *addr;
+
+	page = alloc_pages(GFP_KERNEL, 0);
+
+	if (!page)
+		return NULL;
+
+	addr = page_address(page);
+
+	/* Give the signal return code some randomness */
+	offset = 0x200 + (get_random_int() & 0x7fc);
+	signal_return_offset = offset;
+
+	/*
+	 * Copy signal return handlers into the vector page, and
+	 * set sigreturn to be a pointer to these.
+	 */
+	memcpy(addr + offset, sigreturn_codes, sizeof(sigreturn_codes));
+
+	ptr = (unsigned long)addr + offset;
+	flush_icache_range(ptr, ptr + sizeof(sigreturn_codes));
+
+	return page;
+}
diff --git a/arch/arm/kernel/signal.h b/arch/arm/kernel/signal.h
index 6fcfe83..a0dcf5f 100644
--- a/arch/arm/kernel/signal.h
+++ b/arch/arm/kernel/signal.h
@@ -10,5 +10,4 @@
 #define KERN_SIGRETURN_CODE	(CONFIG_VECTORS_BASE + 0x00000500)
 #define KERN_RESTART_CODE	(KERN_SIGRETURN_CODE + sizeof(sigreturn_codes))
 
-extern const unsigned long sigreturn_codes[7];
 extern const unsigned long syscall_restart_code[2];
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 1e9504b..bd49b1f 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -35,8 +35,6 @@
 #include <asm/tls.h>
 #include <asm/system_misc.h>
 
-#include "signal.h"
-
 #include <trace/events/exception.h>
 
 static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
@@ -566,7 +564,7 @@
 		return regs->ARM_r0;
 
 	case NR(set_tls):
-		thread->tp_value = regs->ARM_r0;
+		thread->tp_value[0] = regs->ARM_r0;
 		if (tls_emu)
 			return 0;
 		if (has_tls_reg) {
@@ -684,7 +682,7 @@
 	int reg = (instr >> 12) & 15;
 	if (reg == 15)
 		return 1;
-	regs->uregs[reg] = current_thread_info()->tp_value;
+	regs->uregs[reg] = current_thread_info()->tp_value[0];
 	regs->ARM_pc += 4;
 	return 0;
 }
@@ -785,49 +783,55 @@
 	return;
 }
 
-static void __init kuser_get_tls_init(unsigned long vectors)
+#ifdef CONFIG_KUSER_HELPERS
+static void __init kuser_init(void *vectors)
 {
+	extern char __kuser_helper_start[], __kuser_helper_end[];
+	int kuser_sz = __kuser_helper_end - __kuser_helper_start;
+
+	memcpy(vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz);
+
 	/*
 	 * vectors + 0xfe0 = __kuser_get_tls
 	 * vectors + 0xfe8 = hardware TLS instruction at 0xffff0fe8
 	 */
 	if (tls_emu || has_tls_reg)
-		memcpy((void *)vectors + 0xfe0, (void *)vectors + 0xfe8, 4);
+		memcpy(vectors + 0xfe0, vectors + 0xfe8, 4);
 }
+#else
+static void __init kuser_init(void *vectors)
+{
+}
+#endif
 
 void __init early_trap_init(void *vectors_base)
 {
 	unsigned long vectors = (unsigned long)vectors_base;
 	extern char __stubs_start[], __stubs_end[];
 	extern char __vectors_start[], __vectors_end[];
-	extern char __kuser_helper_start[], __kuser_helper_end[];
-	int kuser_sz = __kuser_helper_end - __kuser_helper_start;
+	unsigned i;
 
 	vectors_page = vectors_base;
 
 	/*
+	 * Poison the vectors page with an undefined instruction.  This
+	 * instruction is chosen to be undefined for both ARM and Thumb
+	 * ISAs.  The Thumb version is an undefined instruction with a
+	 * branch back to the undefined instruction.
+	 */
+	for (i = 0; i < PAGE_SIZE / sizeof(u32); i++)
+		((u32 *)vectors_base)[i] = 0xe7fddef1;
+
+	/*
 	 * Copy the vectors, stubs and kuser helpers (in entry-armv.S)
 	 * into the vector page, mapped at 0xffff0000, and ensure these
 	 * are visible to the instruction stream.
 	 */
 	memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);
-	memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start);
-	memcpy((void *)vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz);
+	memcpy((void *)vectors + 0x1000, __stubs_start, __stubs_end - __stubs_start);
 
-	/*
-	 * Do processor specific fixups for the kuser helpers
-	 */
-	kuser_get_tls_init(vectors);
+	kuser_init(vectors_base);
 
-	/*
-	 * Copy signal return handlers into the vector page, and
-	 * set sigreturn to be a pointer to these.
-	 */
-	memcpy((void *)(vectors + KERN_SIGRETURN_CODE - CONFIG_VECTORS_BASE),
-	       sigreturn_codes, sizeof(sigreturn_codes));
-	memcpy((void *)(vectors + KERN_RESTART_CODE - CONFIG_VECTORS_BASE),
-	       syscall_restart_code, sizeof(syscall_restart_code));
-
-	flush_icache_range(vectors, vectors + PAGE_SIZE);
+	flush_icache_range(vectors, vectors + PAGE_SIZE * 2);
 	modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
 }
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index 0bf55ae..68c312b 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -151,6 +151,23 @@
 #endif
 	__init_begin = .;
 #endif
+	/*
+	 * The vectors and stubs are relocatable code, and the
+	 * only thing that matters is their relative offsets
+	 */
+	__vectors_start = .;
+	.vectors 0 : AT(__vectors_start) {
+		*(.vectors)
+	}
+	. = __vectors_start + SIZEOF(.vectors);
+	__vectors_end = .;
+
+	__stubs_start = .;
+	.stubs 0x1000 : AT(__stubs_start) {
+		*(.stubs)
+	}
+	. = __stubs_start + SIZEOF(.stubs);
+	__stubs_end = .;
 
 	INIT_TEXT_SECTION(8)
 	.exit.text : {
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 696ddf9..87c2f8c 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -473,6 +473,7 @@
 	select MSM_JTAG_MM if CORESIGHT_ETM
 	select MSM_CPR_REGULATOR
 	select MSM_RPM_LOG
+	select MSM_IOMMU_SYNC
 	select MSM_RPM_STATS_LOG
 
 config ARCH_MSM8226
diff --git a/arch/arm/mach-msm/board-8610-gpiomux.c b/arch/arm/mach-msm/board-8610-gpiomux.c
index 87794c4..b5ea3a5 100644
--- a/arch/arm/mach-msm/board-8610-gpiomux.c
+++ b/arch/arm/mach-msm/board-8610-gpiomux.c
@@ -41,6 +41,17 @@
 	.pull = GPIOMUX_PULL_NONE,
 };
 
+static struct gpiomux_setting gpio_nfc_config = {
+	.func = GPIOMUX_FUNC_2,
+	.drv  = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+static struct gpiomux_setting gpio_nfc_sus_config = {
+	.func = GPIOMUX_FUNC_2,
+	.drv  = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
 static struct gpiomux_setting atmel_int_act_cfg = {
 	.func = GPIOMUX_FUNC_GPIO,
 	.drv = GPIOMUX_DRV_8MA,
@@ -232,6 +243,13 @@
 			[GPIOMUX_SUSPENDED] = &gpio_cam_i2c_config,
 		},
 	},
+	{
+		.gpio      = 78,	/* NFC CLK */
+		.settings = {
+			[GPIOMUX_ACTIVE] = &gpio_nfc_config,
+			[GPIOMUX_SUSPENDED] = &gpio_nfc_sus_config,
+		},
+	},
 };
 
 static struct msm_gpiomux_config msm_atmel_configs[] __initdata = {
@@ -557,13 +575,6 @@
 		},
 	},
 	{
-		.gpio = 78,	/*ETH_INT */
-		.settings = {
-			[GPIOMUX_ACTIVE]    = &interrupt_gpio_active,
-			[GPIOMUX_SUSPENDED] = &interrupt_gpio_suspend_pullup,
-		},
-	},
-	{
 		.gpio = 80,	/*ALSP_INT */
 		.settings = {
 			[GPIOMUX_ACTIVE]    = &interrupt_gpio_active,
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index 1999379..993ce58 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -238,12 +238,6 @@
 DEFINE_CLK_RPM_SMD_XO_BUFFER_PINCTRL(cxo_a1_pin, cxo_a1_a_pin, A1_ID);
 DEFINE_CLK_RPM_SMD_XO_BUFFER_PINCTRL(cxo_a2_pin, cxo_a2_a_pin, A2_ID);
 
-struct measure_mux_entry {
-	struct clk *c;
-	int base;
-	u32 debug_mux;
-};
-
 static struct branch_clk oxilicx_axi_clk;
 
 #define MSS_DEBUG_CLOCK_CTL  0x0078
@@ -328,6 +322,7 @@
 #define CAMSS_VFE_VFE_AXI_CBCR                             (0x36BC)
 #define CAMSS_CSI_VFE0_BCR                                 (0x3700)
 #define CAMSS_CSI_VFE0_CBCR                                (0x3704)
+#define CAMSS_MICRO_BCR                                    (0x3490)
 #define OXILI_GFX3D_CBCR                                   (0x4028)
 #define OXILICX_BCR                                        (0x4030)
 #define OXILICX_AXI_CBCR                                   (0x4038)
@@ -1558,6 +1553,13 @@
 	},
 };
 
+#ifdef CONFIG_DEBUG_FS
+struct measure_mux_entry {
+	struct clk *c;
+	int base;
+	u32 debug_mux;
+};
+
 static struct measure_mux_entry measure_mux_GCC[] = {
 	{ &gcc_mss_cfg_ahb_clk.c,  GCC_BASE, 0x0030 },
 	{ &gcc_mss_q6_bimc_axi_clk.c,  GCC_BASE, 0x0031 },
@@ -1613,6 +1615,7 @@
 	{ &bimc_clk.c, GCC_BASE, 0x155},
 	{ &dummy_clk, N_BASES, 0x0000},
 };
+#endif /* CONFIG_DEBUG_FS */
 
 static struct pll_vote_clk mmpll0_pll = {
 	.en_reg = (void __iomem *)MMSS_PLL_VOTE_APCS,
@@ -2365,6 +2368,7 @@
 static struct branch_clk camss_micro_ahb_clk = {
 	.cbcr_reg = CAMSS_MICRO_AHB_CBCR,
 	.has_sibling = 1,
+	.bcr_reg = CAMSS_MICRO_BCR,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
 		.dbg_name = "camss_micro_ahb_clk",
@@ -2684,6 +2688,7 @@
 	},
 };
 
+#ifdef CONFIG_DEBUG_FS
 static struct measure_mux_entry measure_mux_MMSS[] = {
 	{ &mmss_mmssnoc_bto_ahb_clk.c,  MMSS_BASE, 0x0002 },
 	{ &mmss_misc_ahb_clk.c,  MMSS_BASE, 0x0003 },
@@ -2736,6 +2741,7 @@
 	{ &mmssnoc_ahb_clk.c,  MMSS_BASE, 0x0001 },
 	{&dummy_clk, N_BASES, 0x0000},
 };
+#endif /* CONFIG_DEBUG_FS */
 
 static struct branch_clk q6ss_ahb_lfabif_clk = {
 	.cbcr_reg = Q6SS_AHB_LFABIF_CBCR,
@@ -2771,12 +2777,14 @@
 	},
 };
 
+#ifdef CONFIG_DEBUG_FS
 static struct measure_mux_entry measure_mux_LPASS[] = {
 	{ &q6ss_ahbm_clk.c,  LPASS_BASE, 0x001d },
 	{ &q6ss_ahb_lfabif_clk.c,  LPASS_BASE, 0x001e },
 	{ &q6ss_xo_clk.c,  LPASS_BASE, 0x002b },
 	{&dummy_clk, N_BASES, 0x0000},
 };
+#endif /* CONFIG_DEBUG_FS */
 
 
 static DEFINE_CLK_MEASURE(apc0_m_clk);
@@ -2785,6 +2793,7 @@
 static DEFINE_CLK_MEASURE(apc3_m_clk);
 static DEFINE_CLK_MEASURE(l2_m_clk);
 
+#ifdef CONFIG_DEBUG_FS
 static struct  measure_mux_entry measure_mux_APSS[] = {
 	{&apc0_m_clk,                    APCS_BASE, 0x00010},
 	{&apc1_m_clk,                    APCS_BASE, 0x00114},
@@ -2793,6 +2802,7 @@
 	{&l2_m_clk,                      APCS_BASE, 0x01000},
 	{&dummy_clk, N_BASES, 0x0000}
 };
+#endif /* CONFIG_DEBUG_FS */
 
 #define APCS_SH_PLL_MODE        (0x000)
 #define APCS_SH_PLL_L_VAL       (0x004)
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index 95d2f70..85a9f45 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -2923,7 +2923,7 @@
 	CLK_LOOKUP("core_clk",                  gcc_ce1_clk.c, ""),
 	CLK_LOOKUP("iface_clk",       gcc_copss_smmu_ahb_clk.c, ""),
 	CLK_LOOKUP("iface_clk",        gcc_lpss_smmu_ahb_clk.c, ""),
-	CLK_LOOKUP("core_clk",                  gcc_gp1_clk.c, ""),
+	CLK_LOOKUP("core_clk",                  gcc_gp1_clk.c, "0-000e"),
 	CLK_LOOKUP("core_clk",                  gcc_gp2_clk.c, ""),
 	CLK_LOOKUP("core_clk",                  gcc_gp3_clk.c, ""),
 	CLK_LOOKUP("core_clk",         gcc_lpass_q6_axi_clk.c, ""),
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 9ae3340..32a2617 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -3909,6 +3909,7 @@
 static struct branch_clk camss_micro_ahb_clk = {
 	.cbcr_reg = CAMSS_MICRO_AHB_CBCR,
 	.has_sibling = 1,
+	.bcr_reg = CAMSS_MICRO_BCR,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
 		.dbg_name = "camss_micro_ahb_clk",
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index 7cfbd93..c4db727 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -101,6 +101,7 @@
  * @asid:         List of ASID and their usage count (index is ASID value).
  * @ctx_attach_count: Count of how many context are attached.
  * @bus_client  : Bus client needed to vote for bus bandwidth.
+ * @needs_rem_spinlock  : 1 if remote spinlock is needed, 0 otherwise
  *
  * A msm_iommu_drvdata holds the global driver data about a single piece
  * of an IOMMU hardware instance.
@@ -125,6 +126,7 @@
 	int *asid;
 	unsigned int ctx_attach_count;
 	unsigned int bus_client;
+	int needs_rem_spinlock;
 };
 
 /**
@@ -146,8 +148,8 @@
 	int (*iommu_clk_on)(struct msm_iommu_drvdata *);
 	void (*iommu_clk_off)(struct msm_iommu_drvdata *);
 	void * (*iommu_lock_initialize)(void);
-	void (*iommu_lock_acquire)(void);
-	void (*iommu_lock_release)(void);
+	void (*iommu_lock_acquire)(unsigned int need_extra_lock);
+	void (*iommu_lock_release)(unsigned int need_extra_lock);
 };
 
 void msm_iommu_add_drv(struct msm_iommu_drvdata *drv);
@@ -277,32 +279,21 @@
 }
 #endif
 
-#ifdef CONFIG_MSM_IOMMU_GPU_SYNC
-void msm_iommu_remote_p0_spin_lock(void);
-void msm_iommu_remote_p0_spin_unlock(void);
+#ifdef CONFIG_MSM_IOMMU_SYNC
+void msm_iommu_remote_p0_spin_lock(unsigned int need_lock);
+void msm_iommu_remote_p0_spin_unlock(unsigned int need_lock);
 
 #define msm_iommu_remote_lock_init() _msm_iommu_remote_spin_lock_init()
-#define msm_iommu_remote_spin_lock() msm_iommu_remote_p0_spin_lock()
-#define msm_iommu_remote_spin_unlock() msm_iommu_remote_p0_spin_unlock()
+#define msm_iommu_remote_spin_lock(need_lock) \
+				msm_iommu_remote_p0_spin_lock(need_lock)
+#define msm_iommu_remote_spin_unlock(need_lock) \
+				msm_iommu_remote_p0_spin_unlock(need_lock)
 #else
 #define msm_iommu_remote_lock_init()
-#define msm_iommu_remote_spin_lock()
-#define msm_iommu_remote_spin_unlock()
+#define msm_iommu_remote_spin_lock(need_lock)
+#define msm_iommu_remote_spin_unlock(need_lock)
 #endif
 
-/* Allows kgsl iommu driver to acquire lock */
-#define msm_iommu_lock() \
-	do { \
-		msm_iommu_mutex_lock(); \
-		msm_iommu_remote_spin_lock(); \
-	} while (0)
-
-#define msm_iommu_unlock() \
-	do { \
-		msm_iommu_remote_spin_unlock(); \
-		msm_iommu_mutex_unlock(); \
-	} while (0)
-
 #ifdef CONFIG_MSM_IOMMU
 /*
  * Look up an IOMMU context device by its context name. NULL if none found.
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8084.h b/arch/arm/mach-msm/include/mach/msm_iomap-8084.h
index 43f1de0..fe68524 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8084.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8084.h
@@ -31,6 +31,9 @@
 #define APQ8084_TLMM_PHYS	0xFD510000
 #define APQ8084_TLMM_SIZE	SZ_16K
 
+#define APQ8084_QGIC_CPU_PHYS	0xF9002000
+#define APQ8084_QGIC_CPU_SIZE	SZ_4K
+
 #ifdef CONFIG_DEBUG_APQ8084_UART
 #define MSM_DEBUG_UART_BASE	IOMEM(0xFA71E000)
 #define MSM_DEBUG_UART_PHYS	0xF991E000
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8092.h b/arch/arm/mach-msm/include/mach/msm_iomap-8092.h
index f460a4e..2ae36a5 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8092.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8092.h
@@ -28,6 +28,9 @@
 #define MPQ8092_QGIC_DIST_PHYS	0xF9000000
 #define MPQ8092_QGIC_DIST_SIZE	SZ_4K
 
+#define MPQ8092_QGIC_CPU_PHYS	0xF9002000
+#define MPQ8092_QGIC_CPU_SIZE	SZ_4K
+
 #define MPQ8092_TLMM_PHYS	0xFD510000
 #define MPQ8092_TLMM_SIZE	SZ_16K
 
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8226.h b/arch/arm/mach-msm/include/mach/msm_iomap-8226.h
index 327c1ea..adf66ff 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8226.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8226.h
@@ -28,6 +28,9 @@
 #define MSM8226_QGIC_DIST_PHYS	0xF9000000
 #define MSM8226_QGIC_DIST_SIZE	SZ_4K
 
+#define MSM8226_QGIC_CPU_PHYS	0xF9002000
+#define MSM8226_QGIC_CPU_SIZE	SZ_4K
+
 #define MSM8226_APCS_GCC_PHYS	0xF9011000
 #define MSM8226_APCS_GCC_SIZE	SZ_4K
 
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8610.h b/arch/arm/mach-msm/include/mach/msm_iomap-8610.h
index 18e448d..4431d71 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8610.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8610.h
@@ -27,6 +27,9 @@
 #define MSM8610_QGIC_DIST_PHYS	0xF9000000
 #define MSM8610_QGIC_DIST_SIZE	SZ_4K
 
+#define MSM8610_QGIC_CPU_PHYS	0xF9002000
+#define MSM8610_QGIC_CPU_SIZE	SZ_4K
+
 #define MSM8610_APCS_GCC_PHYS	0xF9011000
 #define MSM8610_APCS_GCC_SIZE	SZ_4K
 
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8974.h b/arch/arm/mach-msm/include/mach/msm_iomap-8974.h
index ec3c210..4072f2d 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8974.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8974.h
@@ -28,6 +28,9 @@
 #define MSM8974_QGIC_DIST_PHYS	0xF9000000
 #define MSM8974_QGIC_DIST_SIZE	SZ_4K
 
+#define MSM8974_QGIC_CPU_PHYS	0xF9002000
+#define MSM8974_QGIC_CPU_SIZE	SZ_4K
+
 #define MSM8974_TLMM_PHYS	0xFD510000
 #define MSM8974_TLMM_SIZE	SZ_16K
 
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-9625.h b/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
index 31b19b3..ee5a413 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
@@ -28,6 +28,9 @@
 #define MSM9625_QGIC_DIST_PHYS	0xF9000000
 #define MSM9625_QGIC_DIST_SIZE	SZ_4K
 
+#define MSM9625_QGIC_CPU_PHYS	0xF9002000
+#define MSM9625_QGIC_CPU_SIZE	SZ_4K
+
 #define MSM9625_TMR_PHYS	0xF9021000
 #define MSM9625_TMR_SIZE	SZ_4K
 
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index f736b30..d1c8500 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -299,6 +299,7 @@
 #ifdef CONFIG_ARCH_MSM8974
 static struct map_desc msm_8974_io_desc[] __initdata = {
 	MSM_CHIP_DEVICE(QGIC_DIST, MSM8974),
+	MSM_CHIP_DEVICE(QGIC_CPU, MSM8974),
 	MSM_CHIP_DEVICE(TLMM, MSM8974),
 	MSM_CHIP_DEVICE(MPM2_PSHOLD, MSM8974),
 	{
@@ -322,6 +323,7 @@
 #ifdef CONFIG_ARCH_APQ8084
 static struct map_desc msm_8084_io_desc[] __initdata = {
 	MSM_CHIP_DEVICE(QGIC_DIST, APQ8084),
+	MSM_CHIP_DEVICE(QGIC_CPU, APQ8084),
 	MSM_CHIP_DEVICE(TLMM, APQ8084),
 	{
 		.virtual =  (unsigned long) MSM_SHARED_RAM_BASE,
@@ -504,6 +506,7 @@
 #ifdef CONFIG_ARCH_MSM9625
 static struct map_desc msm9625_io_desc[] __initdata = {
 	MSM_CHIP_DEVICE(QGIC_DIST, MSM9625),
+	MSM_CHIP_DEVICE(QGIC_CPU, MSM9625),
 	MSM_CHIP_DEVICE(TLMM, MSM9625),
 	MSM_CHIP_DEVICE(MPM2_PSHOLD, MSM9625),
 	MSM_CHIP_DEVICE(TMR, MSM9625),
@@ -547,6 +550,7 @@
 #ifdef CONFIG_ARCH_MPQ8092
 static struct map_desc mpq8092_io_desc[] __initdata = {
 	MSM_CHIP_DEVICE(QGIC_DIST, MPQ8092),
+	MSM_CHIP_DEVICE(QGIC_CPU, MPQ8092),
 	MSM_CHIP_DEVICE(TLMM, MPQ8092),
 	{
 		.virtual =  (unsigned long) MSM_SHARED_RAM_BASE,
@@ -569,6 +573,7 @@
 #ifdef CONFIG_ARCH_MSM8226
 static struct map_desc msm_8226_io_desc[] __initdata = {
 	MSM_CHIP_DEVICE(QGIC_DIST, MSM8226),
+	MSM_CHIP_DEVICE(QGIC_CPU, MSM8226),
 	MSM_CHIP_DEVICE(APCS_GCC, MSM8226),
 	MSM_CHIP_DEVICE(TLMM, MSM8226),
 	MSM_CHIP_DEVICE(MPM2_PSHOLD, MSM8226),
@@ -594,6 +599,7 @@
 #ifdef CONFIG_ARCH_MSM8610
 static struct map_desc msm8610_io_desc[] __initdata = {
 	MSM_CHIP_DEVICE(QGIC_DIST, MSM8610),
+	MSM_CHIP_DEVICE(QGIC_CPU, MSM8610),
 	MSM_CHIP_DEVICE(APCS_GCC, MSM8610),
 	MSM_CHIP_DEVICE(TLMM, MSM8610),
 	MSM_CHIP_DEVICE(MPM2_PSHOLD, MSM8610),
diff --git a/arch/arm/mach-msm/lpm_levels.c b/arch/arm/mach-msm/lpm_levels.c
index 180d277..249a334 100644
--- a/arch/arm/mach-msm/lpm_levels.c
+++ b/arch/arm/mach-msm/lpm_levels.c
@@ -191,6 +191,9 @@
 	case MSM_SPM_L2_MODE_GDHS:
 		msm_pm_set_l2_flush_flag(MSM_SCM_L2_GDHS);
 		break;
+	case MSM_SPM_L2_MODE_PC_NO_RPM:
+		msm_pm_set_l2_flush_flag(MSM_SCM_L2_OFF);
+		break;
 	case MSM_SPM_L2_MODE_RETENTION:
 	case MSM_SPM_L2_MODE_DISABLED:
 		break;
@@ -448,6 +451,7 @@
 	int i;
 	struct lpm_lookup_table l2_mode_lookup[] = {
 		{MSM_SPM_L2_MODE_POWER_COLLAPSE, "l2_cache_pc"},
+		{MSM_SPM_L2_MODE_PC_NO_RPM, "l2_cache_pc_no_rpm"},
 		{MSM_SPM_L2_MODE_GDHS, "l2_cache_gdhs"},
 		{MSM_SPM_L2_MODE_RETENTION, "l2_cache_retention"},
 		{MSM_SPM_L2_MODE_DISABLED, "l2_cache_active"}
diff --git a/arch/arm/mach-msm/ocmem_core.c b/arch/arm/mach-msm/ocmem_core.c
index 153864d..c186a5e 100644
--- a/arch/arm/mach-msm/ocmem_core.c
+++ b/arch/arm/mach-msm/ocmem_core.c
@@ -43,6 +43,8 @@
 	unsigned int num_macros;
 	struct ocmem_hw_macro *macro;
 	struct msm_rpm_request *rpm_req;
+	unsigned long macro_size;
+	unsigned long region_size;
 	unsigned r_state;
 };
 
@@ -69,6 +71,9 @@
 #define NUM_MACROS_MASK (0x3F << 8)
 #define NUM_MACROS_SHIFT (8)
 
+#define LAST_REGN_HALFSIZE_MASK (0x1 << 16)
+#define LAST_REGN_HALFSIZE_SHIFT (16)
+
 #define INTERLEAVING_MASK (0x1 << 17)
 #define INTERLEAVING_SHIFT (17)
 
@@ -198,7 +203,13 @@
 
 	return state;
 }
+
 #ifndef CONFIG_MSM_OCMEM_POWER_DISABLE
+static struct ocmem_hw_region *get_ocmem_region(unsigned region_num)
+{
+	return &region_ctrl[region_num];
+}
+
 static int commit_region_staging(unsigned region_num, unsigned start_m,
 				unsigned new_state)
 {
@@ -933,6 +944,7 @@
 	unsigned start_m = num_banks;
 	unsigned end_m = num_banks;
 	unsigned long region_offset = 0;
+	struct ocmem_hw_region *region;
 	int rc = 0;
 
 	if (offset < 0)
@@ -966,6 +978,7 @@
 
 	for (i = region_start; i <= region_end; i++) {
 
+		region = get_ocmem_region(i);
 		curr_state = read_region_state(i);
 
 		switch (curr_state) {
@@ -981,14 +994,14 @@
 			break;
 		}
 
-		if (len >= region_size) {
+		if (len >= region->region_size) {
 			pr_debug("switch: entire region (%d)\n", i);
 			start_m = 0;
 			end_m = num_banks;
 		} else {
-			region_offset = offset - (i * region_size);
-			start_m = region_offset / macro_size;
-			end_m = (region_offset + len - 1) / macro_size;
+			region_offset = offset - (i * region->region_size);
+			start_m = region_offset / region->macro_size;
+			end_m = (region_offset + len - 1) / region->macro_size;
 			pr_debug("switch: macro (%u to %u)\n", start_m, end_m);
 		}
 
@@ -1002,7 +1015,7 @@
 		aggregate_region_state(i);
 		if (rpm_power_control)
 			commit_region_state(i);
-		len -= region_size;
+		len -= region->region_size;
 
 		/* If we voted ON/retain the banks must never be OFF */
 		if (new_state != REGION_DEFAULT_OFF) {
@@ -1123,6 +1136,7 @@
 	struct device   *dev = &pdev->dev;
 	struct ocmem_plat_data *pdata = NULL;
 	unsigned hw_ver;
+	bool last_region_halfsize;
 	bool interleaved;
 	unsigned i, j, k;
 	unsigned rsc_type = 0;
@@ -1146,6 +1160,9 @@
 		goto hw_not_supported;
 	}
 
+	last_region_halfsize = (hw_ver & LAST_REGN_HALFSIZE_MASK) >>
+					LAST_REGN_HALFSIZE_SHIFT;
+
 	interleaved = (hw_ver & INTERLEAVING_MASK) >> INTERLEAVING_SHIFT;
 
 	num_regions = pdata->nr_regions;
@@ -1179,6 +1196,14 @@
 		region->r_state = REGION_DEFAULT_OFF;
 		region->num_macros = num_banks;
 
+		if (last_region_halfsize && i == (num_regions - 1)) {
+			region->macro_size = macro_size / 2;
+			region->region_size = region_size / 2;
+		} else {
+			region->macro_size = macro_size;
+			region->region_size = region_size;
+		}
+
 		region->macro = devm_kzalloc(dev,
 					sizeof(struct ocmem_hw_macro) *
 						num_banks, GFP_KERNEL);
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index da5e67a..00b0b3b 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -481,6 +481,10 @@
 	bool collapsed = 0;
 	int ret;
 	bool save_cpu_regs = !cpu || from_idle;
+	unsigned int saved_gic_cpu_ctrl;
+
+	saved_gic_cpu_ctrl = readl_relaxed(MSM_QGIC_CPU_BASE + GIC_CPU_CTRL);
+	mb();
 
 	if (MSM_PM_DEBUG_POWER_COLLAPSE & msm_pm_debug_mask)
 		pr_info("CPU%u: %s: notify_rpm %d\n",
@@ -503,6 +507,9 @@
 	if (from_idle && msm_pm_pc_reset_timer)
 		clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
 
+#ifdef CONFIG_VFP
+	vfp_pm_suspend();
+#endif
 	collapsed = save_cpu_regs ? msm_pm_collapse() : msm_pm_pc_hotplug();
 
 	if (from_idle && msm_pm_pc_reset_timer)
@@ -511,7 +518,14 @@
 	msm_pm_boot_config_after_pc(cpu);
 
 	if (collapsed) {
+#ifdef CONFIG_VFP
+		vfp_pm_resume();
+#endif
 		cpu_init();
+		writel(0xF0, MSM_QGIC_CPU_BASE + GIC_CPU_PRIMASK);
+		writel_relaxed(saved_gic_cpu_ctrl,
+				MSM_QGIC_CPU_BASE + GIC_CPU_CTRL);
+		mb();
 		local_fiq_enable();
 	}
 
diff --git a/arch/arm/mach-msm/qdsp5/audio_amrnb.c b/arch/arm/mach-msm/qdsp5/audio_amrnb.c
index 1f04e76..d32dc4f 100644
--- a/arch/arm/mach-msm/qdsp5/audio_amrnb.c
+++ b/arch/arm/mach-msm/qdsp5/audio_amrnb.c
@@ -2,7 +2,7 @@
  *
  * amrnb audio decoder device
  *
- * Copyright (c) 2008-2009, 2011-2012 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2008-2009, 2011-2013 The Linux Foundation. All rights reserved.
  *
  * Based on the mp3 native driver in arch/arm/mach-msm/qdsp5/audio_mp3.c
  *
diff --git a/arch/arm/mach-msm/qdsp5/audio_amrnb_in.c b/arch/arm/mach-msm/qdsp5/audio_amrnb_in.c
index 743eee2..0eca74d 100644
--- a/arch/arm/mach-msm/qdsp5/audio_amrnb_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_amrnb_in.c
@@ -2,7 +2,7 @@
  *
  * amrnb encoder device
  *
- * Copyright (c) 2009, 2011-2012 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2009, 2011-2013 The Linux Foundation. All rights reserved.
  *
  * This code is based in part on arch/arm/mach-msm/qdsp5/audio_in.c, which is
  * Copyright (C) 2008 Google, Inc.
@@ -742,6 +742,7 @@
 	MM_DBG("\n");
 	if (cmd == AUDIO_GET_STATS) {
 		struct msm_audio_stats stats;
+		memset(&stats, 0, sizeof(stats));
 		stats.byte_count = atomic_read(&audio->in_bytes);
 		stats.sample_count = atomic_read(&audio->in_samples);
 		if (copy_to_user((void *) arg, &stats, sizeof(stats)))
diff --git a/arch/arm/mach-msm/qdsp5/audio_qcelp_in.c b/arch/arm/mach-msm/qdsp5/audio_qcelp_in.c
index 83a2633..cfda4b9 100644
--- a/arch/arm/mach-msm/qdsp5/audio_qcelp_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_qcelp_in.c
@@ -2,7 +2,7 @@
  *
  * qcelp audio input device
  *
- * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This code is based in part on arch/arm/mach-msm/qdsp5v2/audio_qcelp_in.c,
  * Copyright (C) 2008 Google, Inc.
@@ -732,6 +732,7 @@
 	MM_DBG("\n");
 	if (cmd == AUDIO_GET_STATS) {
 		struct msm_audio_stats stats;
+		memset(&stats, 0, sizeof(stats));
 		stats.byte_count = atomic_read(&audio->in_bytes);
 		stats.sample_count = atomic_read(&audio->in_samples);
 		if (copy_to_user((void *) arg, &stats, sizeof(stats)))
diff --git a/arch/arm/mach-msm/qdsp5/audio_voicememo.c b/arch/arm/mach-msm/qdsp5/audio_voicememo.c
index ae63f0d..f7295b7 100644
--- a/arch/arm/mach-msm/qdsp5/audio_voicememo.c
+++ b/arch/arm/mach-msm/qdsp5/audio_voicememo.c
@@ -4,7 +4,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
  *
  * This code is based in part on arch/arm/mach-msm/qdsp5/audio_mp3.c
  *
@@ -644,6 +644,7 @@
 
 	if (cmd == AUDIO_GET_STATS) {
 		struct msm_audio_stats stats;
+		memset(&stats, 0, sizeof(stats));
 		mutex_lock(&audio->dsp_lock);
 		stats.byte_count = audio->byte_count;
 		stats.sample_count = audio->frame_count;
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_amrnb_in.c b/arch/arm/mach-msm/qdsp5v2/audio_amrnb_in.c
index 8e66939..cb3c3ea 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_amrnb_in.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_amrnb_in.c
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2009-2013, 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
@@ -503,6 +503,7 @@
 
 	if (cmd == AUDIO_GET_STATS) {
 		struct msm_audio_stats stats;
+		memset(&stats, 0, sizeof(stats));
 		stats.byte_count = atomic_read(&audio->in_bytes);
 		stats.sample_count = atomic_read(&audio->in_samples);
 		if (copy_to_user((void *) arg, &stats, sizeof(stats)))
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_qcelp_in.c b/arch/arm/mach-msm/qdsp5v2/audio_qcelp_in.c
index 0f8956f..37a6726 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_qcelp_in.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_qcelp_in.c
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2009-2013, 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
@@ -778,6 +778,7 @@
 	MM_DBG("\n");
 	if (cmd == AUDIO_GET_STATS) {
 		struct msm_audio_stats stats;
+		memset(&stats, 0, sizeof(stats));
 		stats.byte_count = atomic_read(&audio->in_bytes);
 		stats.sample_count = atomic_read(&audio->in_samples);
 		if (copy_to_user((void *) arg, &stats, sizeof(stats)))
diff --git a/arch/arm/mach-msm/qdsp6/pcm_in.c b/arch/arm/mach-msm/qdsp6/pcm_in.c
index c6bddb8..288e1dc 100644
--- a/arch/arm/mach-msm/qdsp6/pcm_in.c
+++ b/arch/arm/mach-msm/qdsp6/pcm_in.c
@@ -141,6 +141,7 @@
 	}
 	case AUDIO_GET_CONFIG: {
 		struct msm_audio_config config;
+		memset(&config, 0, sizeof(config));
 		config.buffer_size = pcm->buffer_size;
 		config.buffer_count = 2;
 		config.sample_rate = pcm->sample_rate;
diff --git a/arch/arm/mach-msm/qdsp6v2/adsp-loader.c b/arch/arm/mach-msm/qdsp6v2/adsp-loader.c
index 0506e7e..0bd2010 100644
--- a/arch/arm/mach-msm/qdsp6v2/adsp-loader.c
+++ b/arch/arm/mach-msm/qdsp6v2/adsp-loader.c
@@ -54,25 +54,36 @@
 	int rc = 0;
 	u32 adsp_state;
 
+	if (!pdev) {
+		dev_err(&pdev->dev, "%s: Platform device null \n", __func__);
+		goto fail;
+	}
+
+	if (!pdev->dev.of_node) {
+		dev_err(&pdev->dev,
+			"%s: Device tree information missing \n", __func__);
+		goto fail;
+	}
+
 	rc = of_property_read_u32(pdev->dev.of_node, adsp_dt, &adsp_state);
 	if (rc) {
 		dev_err(&pdev->dev,
 			"%s: ADSP state = %x\n", __func__, adsp_state);
-		return;
+		goto fail;
 	}
 
 	if (adsp_state == APR_SUBSYS_DOWN) {
-		if (pdev) {
-			priv = platform_get_drvdata(pdev);
-		} else {
-			pr_err("%s: Private data get failed\n", __func__);
+		priv = platform_get_drvdata(pdev);
+		if (!priv) {
+			dev_err(&pdev->dev,
+				" %s: Private data get failed\n", __func__);
 			goto fail;
 		}
 
 
 		priv->pil_h = subsystem_get("adsp");
 		if (IS_ERR(priv->pil_h)) {
-			pr_err("%s: pil get failed,\n",
+			dev_err(&pdev->dev, "%s: pil get failed,\n",
 				__func__);
 			goto fail;
 		}
@@ -86,11 +97,11 @@
 	}
 
 
-	pr_info("%s: Q6/ADSP image is loaded\n", __func__);
+	dev_info(&pdev->dev, "%s: Q6/ADSP image is loaded\n", __func__);
 	return;
 fail:
 
-	pr_err("%s: Q6/ADSP image loading failed\n", __func__);
+	dev_err(&pdev->dev, "%s: Q6/ADSP image loading failed\n", __func__);
 	return;
 }
 
@@ -118,9 +129,9 @@
 
 	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
 	if (!priv) {
-		pr_err("%s: memory alloc failed\n", __func__);
+		dev_err(&pdev->dev, "%s: memory alloc failed\n", __func__);
 		ret = -ENOMEM;
-		goto error_return;
+		return ret;
 	}
 
 	platform_set_drvdata(pdev, priv);
@@ -131,7 +142,7 @@
 				sizeof(*(priv->attr_group)),
 				GFP_KERNEL);
 	if (!priv->attr_group) {
-		pr_err("%s: malloc attr_group failed\n",
+		dev_err(&pdev->dev, "%s: malloc attr_group failed\n",
 						__func__);
 		ret = -ENOMEM;
 		goto error_return;
@@ -141,7 +152,7 @@
 
 	priv->boot_adsp_obj = kobject_create_and_add("boot_adsp", kernel_kobj);
 	if (!priv->boot_adsp_obj) {
-		pr_err("%s: sysfs create and add failed\n",
+		dev_err(&pdev->dev, "%s: sysfs create and add failed\n",
 						__func__);
 		ret = -ENOMEM;
 		goto error_return;
@@ -149,7 +160,7 @@
 
 	ret = sysfs_create_group(priv->boot_adsp_obj, priv->attr_group);
 	if (ret) {
-		pr_err("%s: sysfs create group failed %d\n", \
+		dev_err(&pdev->dev, "%s: sysfs create group failed %d\n", \
 							__func__, ret);
 		goto error_return;
 	}
@@ -195,7 +206,7 @@
 {
 	int ret = adsp_loader_init_sysfs(pdev);
 	if (ret != 0) {
-		pr_err("%s: Error in initing sysfs\n", __func__);
+		dev_err(&pdev->dev, "%s: Error in initing sysfs\n", __func__);
 		return ret;
 	}
 
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_utils.c b/arch/arm/mach-msm/qdsp6v2/audio_utils.c
index 33bbac0..5355de1 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_utils.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_utils.c
@@ -197,6 +197,7 @@
 
 	if (cmd == AUDIO_GET_STATS) {
 		struct msm_audio_stats stats;
+		memset(&stats, 0, sizeof(stats));
 		stats.byte_count = atomic_read(&audio->in_bytes);
 		stats.sample_count = atomic_read(&audio->in_samples);
 		if (copy_to_user((void *) arg, &stats, sizeof(stats)))
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 888cd5e..53bbe20 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -1035,56 +1035,64 @@
 
 	msm_soc_device = soc_device_to_device(soc_dev);
 	populate_soc_sysfs_files(msm_soc_device);
+
 	err = sysdev_class_register(&soc_sysdev_class);
 	if (err) {
 		pr_err("%s: sysdev_class_register fail (%d)\n",
 		       __func__, err);
-		return err;
+		goto socinfo_init_err;
 	}
+
 	err = sysdev_register(&soc_sys_device);
 	if (err) {
 		pr_err("%s: sysdev_register fail (%d)\n",
 		       __func__, err);
-		return err;
+		goto socinfo_init_err;
 	}
+
 	socinfo_create_files(&soc_sys_device, socinfo_v1_files,
 				ARRAY_SIZE(socinfo_v1_files));
 	if (socinfo->v1.format < 2)
-		return err;
+		goto socinfo_init_err;
+
 	socinfo_create_files(&soc_sys_device, socinfo_v2_files,
 				ARRAY_SIZE(socinfo_v2_files));
 
 	if (socinfo->v1.format < 3)
-		return err;
+		goto socinfo_init_err;
 
 	socinfo_create_files(&soc_sys_device, socinfo_v3_files,
 				ARRAY_SIZE(socinfo_v3_files));
 
 	if (socinfo->v1.format < 4)
-		return err;
+		goto socinfo_init_err;
 
 	socinfo_create_files(&soc_sys_device, socinfo_v4_files,
 				ARRAY_SIZE(socinfo_v4_files));
 
 	if (socinfo->v1.format < 5)
-		return err;
+		goto socinfo_init_err;
 
 	socinfo_create_files(&soc_sys_device, socinfo_v5_files,
 				ARRAY_SIZE(socinfo_v5_files));
 
 	if (socinfo->v1.format < 6)
-		return err;
+		goto socinfo_init_err;
 
 	socinfo_create_files(&soc_sys_device, socinfo_v6_files,
 				ARRAY_SIZE(socinfo_v6_files));
 
 	if (socinfo->v1.format < 7)
-		return err;
+		goto socinfo_init_err;
 
 	socinfo_create_files(&soc_sys_device, socinfo_v7_files,
 				ARRAY_SIZE(socinfo_v7_files));
 
 	return 0;
+
+socinfo_init_err:
+	 kfree(soc_dev_attr);
+         return err;
 }
 
 arch_initcall(socinfo_init_sysdev);
diff --git a/arch/arm/mach-msm/spm.h b/arch/arm/mach-msm/spm.h
index 3207011..1769402 100644
--- a/arch/arm/mach-msm/spm.h
+++ b/arch/arm/mach-msm/spm.h
@@ -24,6 +24,7 @@
 	MSM_SPM_L2_MODE_DISABLED = MSM_SPM_MODE_DISABLED,
 	MSM_SPM_L2_MODE_RETENTION,
 	MSM_SPM_L2_MODE_GDHS,
+	MSM_SPM_L2_MODE_PC_NO_RPM,
 	MSM_SPM_L2_MODE_POWER_COLLAPSE,
 };
 
diff --git a/arch/arm/mach-msm/spm_devices.c b/arch/arm/mach-msm/spm_devices.c
index 3ac1348..19b0b80 100644
--- a/arch/arm/mach-msm/spm_devices.c
+++ b/arch/arm/mach-msm/spm_devices.c
@@ -397,6 +397,7 @@
 	struct mode_of of_l2_modes[] = {
 		{"qcom,saw2-spm-cmd-ret", MSM_SPM_L2_MODE_RETENTION, 1},
 		{"qcom,saw2-spm-cmd-gdhs", MSM_SPM_L2_MODE_GDHS, 1},
+		{"qcom,saw2-spm-cmd-pc-no-rpm", MSM_SPM_L2_MODE_PC_NO_RPM, 1},
 		{"qcom,saw2-spm-cmd-pc", MSM_SPM_L2_MODE_POWER_COLLAPSE, 1},
 	};
 
diff --git a/arch/arm/mach-rpc/irq.c b/arch/arm/mach-rpc/irq.c
index cf0e669..3e4fa84 100644
--- a/arch/arm/mach-rpc/irq.c
+++ b/arch/arm/mach-rpc/irq.c
@@ -163,6 +163,6 @@
 		}
 	}
 
-	init_FIQ();
+	init_FIQ(FIQ_START);
 }
 
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 194c5f6..7b9f754 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -436,24 +436,28 @@
 	select TLS_REG_EMUL if SMP || !MMU
 	select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
 	select CPU_USE_DOMAINS if MMU
+	select NEED_KUSER_HELPERS
 
 config CPU_32v4
 	bool
 	select TLS_REG_EMUL if SMP || !MMU
 	select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
 	select CPU_USE_DOMAINS if MMU
+	select NEED_KUSER_HELPERS
 
 config CPU_32v4T
 	bool
 	select TLS_REG_EMUL if SMP || !MMU
 	select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
 	select CPU_USE_DOMAINS if MMU
+	select NEED_KUSER_HELPERS
 
 config CPU_32v5
 	bool
 	select TLS_REG_EMUL if SMP || !MMU
 	select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
 	select CPU_USE_DOMAINS if MMU
+	select NEED_KUSER_HELPERS
 
 config CPU_32v6
 	bool
@@ -792,6 +796,7 @@
 
 config TLS_REG_EMUL
 	bool
+	select NEED_KUSER_HELPERS
 	help
 	  An SMP system using a pre-ARMv6 processor (there are apparently
 	  a few prototypes like that in existence) and therefore access to
@@ -799,11 +804,43 @@
 
 config NEEDS_SYSCALL_FOR_CMPXCHG
 	bool
+	select NEED_KUSER_HELPERS
 	help
 	  SMP on a pre-ARMv6 processor?  Well OK then.
 	  Forget about fast user space cmpxchg support.
 	  It is just not possible.
 
+config NEED_KUSER_HELPERS
+	bool
+
+config KUSER_HELPERS
+	bool "Enable kuser helpers in vector page" if !NEED_KUSER_HELPERS
+	default y
+	help
+	  Warning: disabling this option may break user programs.
+
+	  Provide kuser helpers in the vector page.  The kernel provides
+	  helper code to userspace in read only form at a fixed location
+	  in the high vector page to allow userspace to be independent of
+	  the CPU type fitted to the system.  This permits binaries to be
+	  run on ARMv4 through to ARMv7 without modification.
+
+	  See Documentation/arm/kernel_user_helpers.txt for details.
+
+	  However, the fixed address nature of these helpers can be used
+	  by ROP (return orientated programming) authors when creating
+	  exploits.
+
+	  If all of the binaries and libraries which run on your platform
+	  are built specifically for your platform, and make no use of
+	  these helpers, then you can turn this option off to hinder
+	  such exploits. However, in that case, if a binary or library
+	  relying on those helpers is run, it will receive a SIGILL signal,
+	  which will terminate the program.
+
+	  Say N here only if you are absolutely certain that you do not
+	  need these helpers; otherwise, the safe option is to say Y.
+
 config DMA_CACHE_RWFO
 	bool "Enable read/write for ownership DMA cache maintenance"
 	depends on CPU_V6K && SMP
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 509f59d..a1a2e51 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -1203,7 +1203,7 @@
 	/*
 	 * Allocate the vector page early.
 	 */
-	vectors = early_alloc(PAGE_SIZE);
+	vectors = early_alloc(PAGE_SIZE * 2);
 
 	early_trap_init(vectors);
 
@@ -1248,15 +1248,27 @@
 	map.pfn = __phys_to_pfn(virt_to_phys(vectors));
 	map.virtual = 0xffff0000;
 	map.length = PAGE_SIZE;
+#ifdef CONFIG_KUSER_HELPERS
 	map.type = MT_HIGH_VECTORS;
+#else
+	map.type = MT_LOW_VECTORS;
+#endif
 	create_mapping(&map);
 
 	if (!vectors_high()) {
 		map.virtual = 0;
+		map.length = PAGE_SIZE * 2;
 		map.type = MT_LOW_VECTORS;
 		create_mapping(&map);
 	}
 
+	/* Now create a kernel read-only mapping */
+	map.pfn += 1;
+	map.virtual = 0xffff0000 + PAGE_SIZE;
+	map.length = PAGE_SIZE;
+	map.type = MT_LOW_VECTORS;
+	create_mapping(&map);
+
 	/*
 	 * Ask the machine support to map in the statically mapped devices.
 	 */
@@ -1485,7 +1497,7 @@
 		vm->addr = (void *)(vaddr & PAGE_MASK);
 		vm->size = PAGE_ALIGN(length + (vaddr & ~PAGE_MASK));
 		vm->phys_addr = __pfn_to_phys(pfn);
-		vm->flags = VM_IOREMAP | VM_ARM_STATIC_MAPPING;
+		vm->flags = VM_LOWMEM | VM_ARM_STATIC_MAPPING;
 		vm->flags |= VM_ARM_MTYPE(type);
 		vm->caller = map_lowmem;
 		vm_area_add_early(vm++);
diff --git a/arch/arm/plat-mxc/avic.c b/arch/arm/plat-mxc/avic.c
index 689f81f..9091f03 100644
--- a/arch/arm/plat-mxc/avic.c
+++ b/arch/arm/plat-mxc/avic.c
@@ -199,7 +199,7 @@
 
 #ifdef CONFIG_FIQ
 	/* Initialize FIQ */
-	init_FIQ();
+	init_FIQ(FIQ_START);
 #endif
 
 	printk(KERN_INFO "MXC IRQ initialized\n");
diff --git a/arch/arm/plat-mxc/tzic.c b/arch/arm/plat-mxc/tzic.c
index 98308ec..5cebccf 100644
--- a/arch/arm/plat-mxc/tzic.c
+++ b/arch/arm/plat-mxc/tzic.c
@@ -180,7 +180,7 @@
 
 #ifdef CONFIG_FIQ
 	/* Initialize FIQ */
-	init_FIQ();
+	init_FIQ(FIQ_START);
 #endif
 
 	pr_info("TrustZone Interrupt Controller (TZIC) initialized\n");
diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c
index bc42c04..fe57bbb 100644
--- a/arch/arm/plat-s3c24xx/irq.c
+++ b/arch/arm/plat-s3c24xx/irq.c
@@ -533,7 +533,7 @@
 	int i;
 
 #ifdef CONFIG_FIQ
-	init_FIQ();
+	init_FIQ(FIQ_START);
 #endif
 
 	irqdbf("s3c2410_init_irq: clearing interrupt status flags\n");
diff --git a/drivers/base/sync.c b/drivers/base/sync.c
index abde6d9..645a698 100644
--- a/drivers/base/sync.c
+++ b/drivers/base/sync.c
@@ -92,14 +92,14 @@
 void sync_timeline_destroy(struct sync_timeline *obj)
 {
 	obj->destroyed = true;
+	smp_wmb();
 
 	/*
-	 * If this is not the last reference, signal any children
-	 * that their parent is going away.
+	 * signal any children that their parent is going away.
 	 */
+	sync_timeline_signal(obj);
 
-	if (!kref_put(&obj->kref, sync_timeline_free))
-		sync_timeline_signal(obj);
+	kref_put(&obj->kref, sync_timeline_free);
 }
 EXPORT_SYMBOL(sync_timeline_destroy);
 
diff --git a/drivers/bif/bif-core.c b/drivers/bif/bif-core.c
index 7bc9af2..4ff7355 100644
--- a/drivers/bif/bif-core.c
+++ b/drivers/bif/bif-core.c
@@ -205,13 +205,14 @@
 	}
 
 	if (sdev->nvm_function) {
-		pr_debug("  NVM function: pointer=0x%04X, task=%d, wr_buf_size=%d, nvm_base=0x%04X, nvm_size=%d\n",
+		pr_debug("  NVM function: pointer=0x%04X, task=%d, wr_buf_size=%d, nvm_base=0x%04X, nvm_size=%d, nvm_lock_offset=%d\n",
 			sdev->nvm_function->nvm_pointer,
 			sdev->nvm_function->slave_control_channel,
 			(sdev->nvm_function->write_buffer_size
 				? sdev->nvm_function->write_buffer_size : 0),
 			sdev->nvm_function->nvm_base_address,
-			sdev->nvm_function->nvm_size);
+			sdev->nvm_function->nvm_size,
+			sdev->nvm_function->nvm_lock_offset);
 		if (sdev->nvm_function->object_count)
 			pr_debug("  NVM objects:\n");
 		i = 0;
@@ -448,8 +449,13 @@
 		rc = bdev->desc->ops->read_slave_registers(bdev, addr, buf,
 							   len);
 		if (rc)
-			pr_err("read_slave_registers failed, rc=%d\n", rc);
-		return rc;
+			pr_debug("read_slave_registers failed, rc=%d\n", rc);
+		else
+			return rc;
+		/*
+		 * Fall back on individual transactions if high level register
+		 * read failed.
+		 */
 	}
 
 	for (i = 0; i < len; i++) {
@@ -521,8 +527,13 @@
 		rc = bdev->desc->ops->write_slave_registers(bdev, addr, buf,
 							    len);
 		if (rc)
-			pr_err("write_slave_registers failed, rc=%d\n", rc);
-		return rc;
+			pr_debug("write_slave_registers failed, rc=%d\n", rc);
+		else
+			return rc;
+		/*
+		 * Fall back on individual transactions if high level register
+		 * write failed.
+		 */
 	}
 
 	rc = bdev->desc->ops->bus_transaction(bdev, BIF_TRANS_ERA, addr >> 8);
@@ -567,6 +578,233 @@
 	return rc;
 }
 
+/* Perform a read-modify-write sequence on a single BIF slave register. */
+static int _bif_slave_masked_write(struct bif_slave_dev *sdev, u16 addr, u8 val,
+			u8 mask)
+{
+	int rc;
+	u8 reg;
+
+	rc = _bif_slave_read(sdev, addr, &reg, 1);
+	if (rc)
+		return rc;
+
+	reg = (reg & ~mask) | (val & mask);
+
+	return _bif_slave_write(sdev, addr, &reg, 1);
+}
+
+static int _bif_check_task(struct bif_slave_dev *sdev, unsigned int task)
+{
+	if (IS_ERR_OR_NULL(sdev)) {
+		pr_err("Invalid slave device handle=%ld\n", PTR_ERR(sdev));
+		return -EINVAL;
+	} else if (!sdev->bdev) {
+		pr_err("BIF controller has been removed\n");
+		return -ENXIO;
+	} else if (!sdev->slave_ctrl_function
+			|| sdev->slave_ctrl_function->task_count == 0) {
+		pr_err("BIF slave does not support slave control\n");
+		return -ENODEV;
+	} else if (task >= sdev->slave_ctrl_function->task_count) {
+		pr_err("Requested task: %u greater than max: %u for this slave\n",
+			task, sdev->slave_ctrl_function->task_count);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int _bif_task_is_busy(struct bif_slave_dev *sdev, unsigned int task)
+{
+	int rc;
+	u16 addr;
+	u8 reg = 0;
+
+	rc = _bif_check_task(sdev, task);
+	if (rc) {
+		pr_err("Invalid slave device or task, rc=%d\n", rc);
+		return rc;
+	}
+
+	/* Check the task busy state. */
+	addr = SLAVE_CTRL_FUNC_TASK_BUSY_ADDR(
+		sdev->slave_ctrl_function->slave_ctrl_pointer, task);
+	rc = _bif_slave_read(sdev, addr, &reg, 1);
+	if (rc) {
+		pr_err("BIF slave register read failed, rc=%d\n", rc);
+		return rc;
+	}
+
+	return (reg & BIT(task % SLAVE_CTRL_TASKS_PER_SET)) ? 1 : 0;
+}
+
+static int _bif_enable_auto_task(struct bif_slave_dev *sdev, unsigned int task)
+{
+	int rc;
+	u16 addr;
+	u8 mask;
+
+	rc = _bif_check_task(sdev, task);
+	if (rc) {
+		pr_err("Invalid slave device or task, rc=%d\n", rc);
+		return rc;
+	}
+
+	/* Enable the auto task within the slave */
+	mask = BIT(task % SLAVE_CTRL_TASKS_PER_SET);
+	addr = SLAVE_CTRL_FUNC_TASK_AUTO_TRIGGER_ADDR(
+		sdev->slave_ctrl_function->slave_ctrl_pointer, task);
+	if (task / SLAVE_CTRL_TASKS_PER_SET == 0) {
+		/* Set global auto task enable. */
+		mask |= BIT(0);
+	}
+	rc = _bif_slave_masked_write(sdev, addr, 0xFF, mask);
+	if (rc) {
+		pr_err("BIF slave register masked write failed, rc=%d\n", rc);
+		return rc;
+	}
+
+	/* Set global auto task enable if task not in set 0. */
+	if (task / SLAVE_CTRL_TASKS_PER_SET != 0) {
+		addr = SLAVE_CTRL_FUNC_TASK_AUTO_TRIGGER_ADDR(
+		       sdev->slave_ctrl_function->slave_ctrl_pointer, 0);
+		rc = _bif_slave_masked_write(sdev, addr, 0xFF, BIT(0));
+		if (rc) {
+			pr_err("BIF slave register masked write failed, rc=%d\n",
+				rc);
+			return rc;
+		}
+	}
+
+	return rc;
+}
+
+static int _bif_disable_auto_task(struct bif_slave_dev *sdev, unsigned int task)
+{
+	int rc;
+	u16 addr;
+	u8 mask;
+
+	rc = _bif_check_task(sdev, task);
+	if (rc) {
+		pr_err("Invalid slave or task, rc=%d\n", rc);
+		return rc;
+	}
+
+	/* Disable the auto task within the slave */
+	mask = BIT(task % SLAVE_CTRL_TASKS_PER_SET);
+	addr = SLAVE_CTRL_FUNC_TASK_AUTO_TRIGGER_ADDR(
+		sdev->slave_ctrl_function->slave_ctrl_pointer, task);
+	rc = _bif_slave_masked_write(sdev, addr, 0x00, mask);
+	if (rc) {
+		pr_err("BIF slave register masked write failed, rc=%d\n", rc);
+		return rc;
+	}
+
+	return rc;
+}
+
+/*
+ * The MIPI-BIF spec does not define a maximum time in which an NVM write must
+ * complete.  The following delay and recheck count therefore represent
+ * arbitrary but reasonable values.
+ */
+#define NVM_WRITE_POLL_DELAY_MS		20
+#define NVM_WRITE_MAX_POLL_COUNT	50
+
+static int _bif_slave_nvm_raw_write(struct bif_slave_dev *sdev, u16 offset,
+				u8 *buf, int len)
+{
+	int rc = 0;
+	int write_len, poll_count, rc2;
+	u8 write_buf[3];
+
+	if (!sdev->nvm_function) {
+		pr_err("BIF slave has no NVM function\n");
+		return -ENODEV;
+	} else if (offset + len > sdev->nvm_function->nvm_size) {
+		pr_err("write offset + len = %d > NVM size = %d\n",
+			offset + len, sdev->nvm_function->nvm_size);
+		return -EINVAL;
+	} else if (offset < sdev->nvm_function->nvm_lock_offset) {
+		pr_err("write offset = %d < first writable offset = %d\n",
+			offset, sdev->nvm_function->nvm_lock_offset);
+		return -EINVAL;
+	}
+
+	rc = _bif_enable_auto_task(sdev,
+			sdev->nvm_function->slave_control_channel);
+	if (rc) {
+		pr_err("Failed to enable NVM auto task, rc=%d\n", rc);
+		return rc;
+	}
+
+	while (len > 0) {
+		write_len = sdev->nvm_function->write_buffer_size;
+		if (write_len == 0)
+			write_len = 256;
+		write_len = min(write_len, len);
+
+		write_buf[0] = offset >> 8;
+		write_buf[1] = offset;
+		write_buf[2] = (write_len == 256) ? 0 : write_len;
+
+		/* Write offset and size registers. */
+		rc = _bif_slave_write(sdev, sdev->nvm_function->nvm_pointer + 6,
+					write_buf, 3);
+		if (rc) {
+			pr_err("BIF slave write failed, rc=%d\n", rc);
+			goto done;
+		}
+
+		/* Write to NVM write buffer registers. */
+		rc = _bif_slave_write(sdev, sdev->nvm_function->nvm_pointer + 9,
+					buf, write_len);
+		if (rc) {
+			pr_err("BIF slave write failed, rc=%d\n", rc);
+			goto done;
+		}
+
+		/*
+		 * Wait for completion of the NVM write which was auto-triggered
+		 * by the register write of the last byte in the NVM write
+		 * buffer.
+		 */
+		poll_count = NVM_WRITE_MAX_POLL_COUNT;
+		do {
+			msleep(NVM_WRITE_POLL_DELAY_MS);
+			rc = _bif_task_is_busy(sdev,
+				sdev->nvm_function->slave_control_channel);
+			poll_count--;
+		} while (rc > 0 && poll_count > 0);
+
+		if (rc < 0) {
+			pr_err("Failed to check task state, rc=%d", rc);
+			goto done;
+		} else if (rc > 0) {
+			pr_err("BIF slave NVM write not completed after %d ms\n",
+			    NVM_WRITE_POLL_DELAY_MS * NVM_WRITE_MAX_POLL_COUNT);
+			rc = -ETIMEDOUT;
+			goto done;
+		}
+
+		len -= write_len;
+		offset += write_len;
+		buf += write_len;
+	}
+
+done:
+	rc2 = _bif_disable_auto_task(sdev,
+			sdev->nvm_function->slave_control_channel);
+	if (rc2) {
+		pr_err("Failed to disable NVM auto task, rc=%d\n", rc2);
+		return rc2;
+	}
+
+	return rc;
+}
+
 /* Takes a mutex if this consumer is not an exclusive bus user. */
 static void bif_ctrl_lock(struct bif_ctrl *ctrl)
 {
@@ -595,25 +833,53 @@
 	bif_ctrl_unlock(&slave->ctrl);
 }
 
+/**
+ * bif_crc_ccitt() - calculate the CRC-CCITT CRC value of the data specified
+ * @buffer:	Data to calculate the CRC of
+ * @len:	Length of the data buffer in bytes
+ *
+ * MIPI-BIF specifies the usage of CRC-CCITT for BIF data objects.  This
+ * function performs the CRC calculation while taking into account the bit
+ * ordering used by BIF.
+ */
+u16 bif_crc_ccitt(const u8 *buffer, unsigned int len)
+{
+	u16 crc = 0xFFFF;
+
+	while (len--) {
+		crc = crc_ccitt_byte(crc, bitrev8(*buffer));
+		buffer++;
+	}
+	return bitrev16(crc);
+}
+EXPORT_SYMBOL(bif_crc_ccitt);
+
+static u16 bif_object_crc_ccitt(const struct bif_object *object)
+{
+	u16 crc = 0xFFFF;
+	int i;
+
+	crc = crc_ccitt_byte(crc, bitrev8(object->type));
+	crc = crc_ccitt_byte(crc, bitrev8(object->version));
+	crc = crc_ccitt_byte(crc, bitrev8(object->manufacturer_id >> 8));
+	crc = crc_ccitt_byte(crc, bitrev8(object->manufacturer_id));
+	crc = crc_ccitt_byte(crc, bitrev8(object->length >> 8));
+	crc = crc_ccitt_byte(crc, bitrev8(object->length));
+
+	for (i = 0; i < object->length - 8; i++)
+		crc = crc_ccitt_byte(crc, bitrev8(object->data[i]));
+
+	return bitrev16(crc);
+}
+
 static int bif_check_task(struct bif_slave *slave, unsigned int task)
 {
 	if (IS_ERR_OR_NULL(slave)) {
-		pr_err("Invalid slave handle.\n");
-		return -EINVAL;
-	} else if (!slave->sdev->bdev) {
-		pr_err("BIF controller has been removed.\n");
-		return -ENXIO;
-	} else if (!slave->sdev->slave_ctrl_function
-			|| slave->sdev->slave_ctrl_function->task_count == 0) {
-		pr_err("BIF slave does not support slave control.\n");
-		return -ENODEV;
-	} else if (task >= slave->sdev->slave_ctrl_function->task_count) {
-		pr_err("Requested task: %u greater than max: %u for this slave\n",
-			task, slave->sdev->slave_ctrl_function->task_count);
+		pr_err("Invalid slave pointer=%ld\n", PTR_ERR(slave));
 		return -EINVAL;
 	}
 
-	return 0;
+	return _bif_check_task(slave->sdev, task);
 }
 
 /**
@@ -817,6 +1083,61 @@
 EXPORT_SYMBOL(bif_trigger_task);
 
 /**
+ * bif_enable_auto_task() - enable task auto triggering for the specified task
+ * @slave:	BIF slave handle
+ * @task:	BIF task inside of the slave to configure for automatic
+ *		triggering.  This corresponds to the slave control channel
+ *		specified for a given BIF function inside of the slave.
+ *
+ * Returns 0 for success or errno if an error occurred.
+ */
+int bif_enable_auto_task(struct bif_slave *slave, unsigned int task)
+{
+	int rc;
+
+	if (IS_ERR_OR_NULL(slave)) {
+		pr_err("Invalid slave pointer=%ld\n", PTR_ERR(slave));
+		return -EINVAL;
+	}
+
+	bif_slave_ctrl_lock(slave);
+	rc = _bif_enable_auto_task(slave->sdev, task);
+	bif_slave_ctrl_unlock(slave);
+
+	return rc;
+}
+EXPORT_SYMBOL(bif_enable_auto_task);
+
+/**
+ * bif_disable_auto_task() - disable task auto triggering for the specified task
+ * @slave:	BIF slave handle
+ * @task:	BIF task inside of the slave to stop automatic triggering on.
+ *		This corresponds to the slave control channel specified for a
+ *		given BIF function inside of the slave.
+ *
+ * This function should be called after bif_enable_auto_task() in a paired
+ * fashion.
+ *
+ * Returns 0 for success or errno if an error occurred.
+ */
+int bif_disable_auto_task(struct bif_slave *slave, unsigned int task)
+{
+	int rc;
+
+	if (IS_ERR_OR_NULL(slave)) {
+		pr_err("Invalid slave pointer=%ld\n", PTR_ERR(slave));
+		return -EINVAL;
+	}
+
+	bif_slave_ctrl_lock(slave);
+	rc = _bif_disable_auto_task(slave->sdev, task);
+	bif_slave_ctrl_unlock(slave);
+
+	return rc;
+}
+EXPORT_SYMBOL(bif_disable_auto_task);
+
+/**
  * bif_task_is_busy() - checks the state of a BIF slave task
  * @slave:	BIF slave handle
  * @task:	BIF task inside of the slave to trigger.  This corresponds to
@@ -828,28 +1149,14 @@
 int bif_task_is_busy(struct bif_slave *slave, unsigned int task)
 {
 	int rc;
-	u16 addr;
-	u8 reg;
 
-	rc = bif_check_task(slave, task);
-	if (rc) {
-		pr_err("Invalid slave or task, rc=%d\n", rc);
-		return rc;
+	if (IS_ERR_OR_NULL(slave)) {
+		pr_err("Invalid slave pointer=%ld\n", PTR_ERR(slave));
+		return -EINVAL;
 	}
 
 	bif_slave_ctrl_lock(slave);
-
-	/* Check the task busy state. */
-	addr = SLAVE_CTRL_FUNC_TASK_BUSY_ADDR(
-		slave->sdev->slave_ctrl_function->slave_ctrl_pointer, task);
-	rc = _bif_slave_read(slave->sdev, addr, &reg, 1);
-	if (rc) {
-		pr_err("BIF slave register read failed, rc=%d\n", rc);
-		goto done;
-	}
-
-	rc = (reg & BIT(task % SLAVE_CTRL_TASKS_PER_SET)) ? 1 : 0;
-done:
+	rc = _bif_task_is_busy(slave->sdev, task);
 	bif_slave_ctrl_unlock(slave);
 
 	return rc;
@@ -1258,16 +1565,29 @@
 }
 EXPORT_SYMBOL(bif_ctrl_put);
 
+static bool bif_slave_object_match(const struct bif_object *object,
+		const struct bif_match_criteria *criteria)
+{
+	return (object->type == criteria->obj_type)
+		&& (object->version == criteria->obj_version
+			|| !(criteria->match_mask & BIF_MATCH_OBJ_VERSION))
+		&& (object->manufacturer_id == criteria->obj_manufacturer_id
+		    || !(criteria->match_mask & BIF_MATCH_OBJ_MANUFACTURER_ID));
+}
+
 /*
  * Returns true if all parameters are matched, otherwise false.
  * function_type and function_version mean that their exists some function in
  * the slave which has the specified type and subtype.  ctrl == NULL is treated
  * as a wildcard.
  */
-static bool bif_slave_match(const struct bif_ctrl *ctrl,
+static bool bif_slave_match(struct bif_ctrl *ctrl,
 	struct bif_slave_dev *sdev, const struct bif_match_criteria *criteria)
 {
 	int i, type, version;
+	struct bif_object *object;
+	bool function_found = false;
+	bool object_found = false;
 
 	if (ctrl && (ctrl->bdev != sdev->bdev))
 		return false;
@@ -1295,10 +1615,29 @@
 			if (type == criteria->function_type &&
 				(version == criteria->function_version
 					|| !(criteria->match_mask
-						& BIF_MATCH_FUNCTION_VERSION)))
-				return true;
+					       & BIF_MATCH_FUNCTION_VERSION))) {
+				function_found = true;
+				break;
+			}
 		}
-		return false;
+		if (!function_found)
+			return false;
+	}
+
+	if (criteria->match_mask & BIF_MATCH_OBJ_TYPE) {
+		if (!sdev->nvm_function)
+			return false;
+		bif_ctrl_lock(ctrl);
+		list_for_each_entry(object, &sdev->nvm_function->object_list,
+					list) {
+			if (bif_slave_object_match(object, criteria)) {
+				object_found = true;
+				break;
+			}
+		}
+		bif_ctrl_unlock(ctrl);
+		if (!object_found)
+			return false;
 	}
 
 	return true;
@@ -1311,7 +1650,7 @@
  * @ctrl:		BIF controller consumer handle
  * @match_criteria:	Matching criteria used to filter slaves
  */
-int bif_slave_match_count(const struct bif_ctrl *ctrl,
+int bif_slave_match_count(struct bif_ctrl *ctrl,
 			const struct bif_match_criteria *match_criteria)
 {
 	struct bif_slave_dev *sdev;
@@ -1342,7 +1681,7 @@
  *
  * Returns a BIF slave handle if successful or an ERR_PTR if not.
  */
-struct bif_slave *bif_slave_match_get(const struct bif_ctrl *ctrl,
+struct bif_slave *bif_slave_match_get(struct bif_ctrl *ctrl,
 	unsigned int id, const struct bif_match_criteria *match_criteria)
 {
 	struct bif_slave_dev *sdev;
@@ -1431,6 +1770,511 @@
 }
 EXPORT_SYMBOL(bif_slave_find_function);
 
+static bool bif_object_match(const struct bif_object *object,
+		const struct bif_obj_match_criteria *criteria)
+{
+	return (object->type == criteria->type
+			|| !(criteria->match_mask & BIF_OBJ_MATCH_TYPE))
+		&& (object->version == criteria->version
+			|| !(criteria->match_mask & BIF_OBJ_MATCH_VERSION))
+		&& (object->manufacturer_id == criteria->manufacturer_id
+		    || !(criteria->match_mask & BIF_OBJ_MATCH_MANUFACTURER_ID));
+}
+
+/**
+ * bif_object_match_count() - returns the number of objects associated with the
+ *			specified BIF slave which fit the matching criteria
+ * @slave:		BIF slave handle
+ * @match_criteria:	Matching criteria used to filter objects
+ */
+int bif_object_match_count(struct bif_slave *slave,
+			const struct bif_obj_match_criteria *match_criteria)
+{
+	struct bif_object *object;
+	int count = 0;
+
+	if (IS_ERR_OR_NULL(slave) || IS_ERR_OR_NULL(match_criteria)) {
+		pr_err("Invalid pointer input.\n");
+		return -EINVAL;
+	}
+
+	if (!slave->sdev->nvm_function)
+		return 0;
+
+	bif_slave_ctrl_lock(slave);
+	list_for_each_entry(object, &slave->sdev->nvm_function->object_list,
+			    list) {
+		if (bif_object_match(object, match_criteria))
+			count++;
+	}
+	bif_slave_ctrl_unlock(slave);
+
+	return count;
+}
+EXPORT_SYMBOL(bif_object_match_count);
+
+/**
+ * bif_object_match_get() - get a BIF object handle for the id'th object found
+ *			in the non-volatile memory of the specified BIF slave
+ *			which fits the matching criteria
+ * @slave:		BIF slave handle
+ * @id:			Index into the set of matching objects
+ * @match_criteria:	Matching criteria used to filter objects
+ *
+ * id must be in range [0, bif_object_match_count(slave, match_criteria) - 1].
+ *
+ * Returns a BIF object handle if successful or an ERR_PTR if not.  This handle
+ * must be freed using bif_object_put() when it is no longer needed.
+ */
+struct bif_object *bif_object_match_get(struct bif_slave *slave,
+	unsigned int id, const struct bif_obj_match_criteria *match_criteria)
+{
+	struct bif_object *object;
+	struct bif_object *object_found = NULL;
+	struct bif_object *object_consumer = ERR_PTR(-ENODEV);
+	int count = 0;
+
+	if (IS_ERR_OR_NULL(slave) || IS_ERR_OR_NULL(match_criteria)) {
+		pr_err("Invalid pointer input.\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (!slave->sdev->nvm_function)
+		return object_consumer;
+
+	bif_slave_ctrl_lock(slave);
+	list_for_each_entry(object, &slave->sdev->nvm_function->object_list,
+			    list) {
+		if (bif_object_match(object, match_criteria))
+			count++;
+		if (count == id + 1) {
+			object_found = object;
+			break;
+		}
+	}
+
+	if (object_found) {
+		object_consumer = kmemdup(object_found,
+					sizeof(*object_consumer), GFP_KERNEL);
+		if (!object_consumer) {
+			pr_err("out of memory\n");
+			object_consumer = ERR_PTR(-ENOMEM);
+			goto done;
+		}
+
+		object_consumer->data = kmemdup(object_found->data,
+					  object_found->length - 8, GFP_KERNEL);
+		if (!object_consumer->data) {
+			pr_err("out of memory\n");
+			kfree(object_consumer);
+			object_consumer = ERR_PTR(-ENOMEM);
+			goto done;
+		}
+
+		/*
+		 * Use prev pointer in consumer struct to point to original
+		 * struct in the internal linked list.
+		 */
+		object_consumer->list.prev = &object_found->list;
+	}
+
+done:
+	bif_slave_ctrl_unlock(slave);
+
+	return object_consumer;
+
+}
+EXPORT_SYMBOL(bif_object_match_get);
+
+/**
+ * bif_object_put() - frees the memory allocated for a BIF object pointer
+ *			returned by bif_object_match_get()
+ * @object:		BIF object to free
+ */
+void bif_object_put(struct bif_object *object)
+{
+	if (object)
+		kfree(object->data);
+	kfree(object);
+}
+EXPORT_SYMBOL(bif_object_put);
+
+/* Copies the contents of object into buf following MIPI-BIF formatting. */
+static void bif_object_flatten(u8 *buf, const struct bif_object *object)
+{
+	buf[0]			= object->type;
+	buf[1]			= object->version;
+	buf[2]			= object->manufacturer_id >> 8;
+	buf[3]			= object->manufacturer_id;
+	buf[4]			= object->length >> 8;
+	buf[5]			= object->length;
+	memcpy(&buf[6], object->data, object->length - 8);
+	buf[object->length - 2]	= object->crc >> 8;
+	buf[object->length - 1]	= object->crc;
+}
+
+/**
+ * bif_object_write() - writes a new BIF object at the end of the object list in
+ *			the non-volatile memory of a slave
+ * @slave:		BIF slave handle
+ * @type:		Type of the object
+ * @version:		Version of the object
+ * @manufacturer_id:	Manufacturer ID number allocated by MIPI
+ * @data:		Data contained in the object
+ * @data_len:		Length of the data
+ *
+ * Returns 0 on success or errno on failure.  This function will fail if the NVM
+ * lock points to an offset after the BIF object list terminator (0x00).
+ */
+int bif_object_write(struct bif_slave *slave, u8 type, u8 version,
+			u16 manufacturer_id, const u8 *data, int data_len)
+{
+	struct bif_object *object;
+	struct bif_object *tail_object;
+	struct bif_nvm_function	*nvm;
+	int rc;
+	int add_null = 0;
+	u16 offset = 0;
+	u8 *buf;
+
+	if (IS_ERR_OR_NULL(slave) || IS_ERR_OR_NULL(data)) {
+		pr_err("Invalid input pointer\n");
+		return -EINVAL;
+	}
+
+	nvm = slave->sdev->nvm_function;
+	if (!nvm) {
+		pr_err("BIF slave has no NVM function\n");
+		return -ENODEV;
+	}
+
+	bif_slave_ctrl_lock(slave);
+	if (nvm->object_count > 0) {
+		tail_object = list_entry(nvm->object_list.prev,
+					struct bif_object, list);
+		offset = tail_object->addr - nvm->nvm_base_address
+				+ tail_object->length;
+	}
+
+	if (offset < nvm->nvm_lock_offset) {
+		pr_err("Cannot write BIF object to NVM because the end of the object list is locked (end=%d < lock=%d)\n",
+			offset, nvm->nvm_lock_offset);
+		rc = -EPERM;
+		goto error_unlock;
+	} else if (offset + data_len + 8 > nvm->nvm_size) {
+		pr_err("Cannot write BIF object to NVM because there is not enough remaining space (size=%d > remaining=%d)\n",
+			data_len + 8, nvm->nvm_size - offset);
+		rc = -EINVAL;
+		goto error_unlock;
+	}
+
+	if (offset + data_len + 8 < nvm->nvm_size)
+		add_null = 1;
+	object = kzalloc(sizeof(*object), GFP_KERNEL);
+	if (!object) {
+		pr_err("kzalloc failed\n");
+		rc = -ENOMEM;
+		goto error_unlock;
+	}
+
+	object->data = kzalloc(data_len, GFP_KERNEL);
+	if (!object->data) {
+		pr_err("kzalloc failed\n");
+		rc = -ENOMEM;
+		goto free_object;
+	}
+
+	buf = kzalloc(data_len + 8 + add_null, GFP_KERNEL);
+	if (!buf) {
+		pr_err("kzalloc failed\n");
+		rc = -ENOMEM;
+		goto free_data;
+	}
+
+	object->type		= type;
+	object->version		= version;
+	object->manufacturer_id	= manufacturer_id;
+	object->length		= data_len + 8;
+	memcpy(object->data, data, data_len);
+	object->crc		= bif_object_crc_ccitt(object);
+	object->addr		= offset + nvm->nvm_base_address;
+
+	bif_object_flatten(buf, object);
+	if (add_null)
+		buf[object->length] = BIF_OBJ_END_OF_LIST;
+
+	rc = _bif_slave_nvm_raw_write(slave->sdev, offset, buf,
+					object->length + add_null);
+	if (rc < 0) {
+		pr_err("NVM write failed, rc=%d\n", rc);
+		kfree(buf);
+		goto free_data;
+	}
+	kfree(buf);
+
+	list_add_tail(&object->list, &nvm->object_list);
+	nvm->object_count++;
+
+	bif_slave_ctrl_unlock(slave);
+
+	return rc;
+
+free_data:
+	kfree(object->data);
+free_object:
+	kfree(object);
+error_unlock:
+	bif_slave_ctrl_unlock(slave);
+
+	return rc;
+
+}
+EXPORT_SYMBOL(bif_object_write);
+
+/*
+ * Returns a pointer to the internal object referenced by a consumer object
+ * if it exists.  Returns NULL if the internal object cannot be found.
+ */
+static struct bif_object *bif_object_consumer_search(
+	struct bif_nvm_function *nvm, const struct bif_object *consumer_object)
+{
+	struct bif_object *object = NULL;
+	struct bif_object *search_object;
+
+	/*
+	 * Internal struct in object linked list is pointed to by consumer
+	 * object list.prev.
+	 */
+	search_object = list_entry(consumer_object->list.prev,
+					struct bif_object, list);
+
+	list_for_each_entry(object, &nvm->object_list, list) {
+		if (object == search_object)
+			break;
+	}
+
+	if (object != search_object)
+		return NULL;
+
+	return object;
+}
+
+/**
+ * bif_object_overwrite() - overwrites an existing BIF object found in the
+ *			non-volatile memory of a slave
+ * @slave:		BIF slave handle
+ * @object:		Existing object in the slave to overwrite
+ * @type:		Type of the object
+ * @version:		Version of the object
+ * @manufacturer_id:	Manufacturer ID number allocated by MIPI
+ * @data:		Data contained in the object
+ * @data_len:		Length of the data
+ *
+ * Returns 0 on success or errno on failure.  The data stored within 'object'
+ * is updated to the new values upon success.  The new data written to the
+ * object must have exactly the same length as the old data (i.e.
+ * data_len == object->length - 8).
+ *
+ * This function will fail if the NVM lock points to an offset after the
+ * beginning of the existing BIF object.
+ */
+int bif_object_overwrite(struct bif_slave *slave,
+	struct bif_object *object, u8 type, u8 version,
+	u16 manufacturer_id, const u8 *data, int data_len)
+{
+	struct bif_object *edit_object = NULL;
+	struct bif_nvm_function *nvm;
+	int rc;
+	u16 crc;
+	u8 *buf;
+
+	if (IS_ERR_OR_NULL(slave) || IS_ERR_OR_NULL(object)
+	    || IS_ERR_OR_NULL(data)) {
+		pr_err("Invalid input pointer\n");
+		return -EINVAL;
+	}
+
+	nvm = slave->sdev->nvm_function;
+	if (!nvm) {
+		pr_err("BIF slave has no NVM function\n");
+		return -ENODEV;
+	}
+
+	if (data_len + 8 != object->length) {
+		pr_err("New data length=%d is different from existing length=%d\n",
+			data_len, object->length - 8);
+		return -EINVAL;
+	}
+
+	bif_slave_ctrl_lock(slave);
+
+	edit_object = bif_object_consumer_search(nvm, object);
+	if (!edit_object) {
+		pr_err("BIF object not found within slave\n");
+		rc = -EINVAL;
+		goto error_unlock;
+	}
+
+	if (edit_object->addr - nvm->nvm_base_address < nvm->nvm_lock_offset) {
+		pr_err("Cannot overwrite BIF object in NVM because some portion of it is locked\n");
+		rc = -EPERM;
+		goto error_unlock;
+	}
+
+	buf = kzalloc(data_len + 8, GFP_KERNEL);
+	if (!buf) {
+		pr_err("kzalloc failed\n");
+		rc = -ENOMEM;
+		goto error_unlock;
+	}
+
+	buf[0]			= type;
+	buf[1]			= version;
+	buf[2]			= manufacturer_id >> 8;
+	buf[3]			= manufacturer_id;
+	buf[4]			= (data_len + 8) >> 8;
+	buf[5]			= data_len + 8;
+	memcpy(&buf[6], data, data_len);
+	crc			= bif_crc_ccitt(buf, data_len + 6);
+	buf[data_len + 6]	= crc >> 8;
+	buf[data_len + 7]	= crc;
+
+	rc = _bif_slave_nvm_raw_write(slave->sdev,
+		object->addr - nvm->nvm_base_address, buf, data_len + 8);
+	if (rc < 0) {
+		pr_err("NVM write failed, rc=%d\n", rc);
+		kfree(buf);
+		goto error_unlock;
+	}
+	kfree(buf);
+
+	/* Update internal object struct. */
+	edit_object->type		= type;
+	edit_object->version		= version;
+	edit_object->manufacturer_id	= manufacturer_id;
+	edit_object->length		= data_len + 8;
+	memcpy(edit_object->data, data, data_len);
+	edit_object->crc		= crc;
+
+	/* Update consumer object struct. */
+	object->type			= type;
+	object->version			= version;
+	object->manufacturer_id		= manufacturer_id;
+	object->length			= data_len + 8;
+	memcpy(object->data, data, data_len);
+	object->crc			= crc;
+
+error_unlock:
+	bif_slave_ctrl_unlock(slave);
+
+	return rc;
+}
+EXPORT_SYMBOL(bif_object_overwrite);
+
+/**
+ * bif_object_delete() - deletes an existing BIF object found in the
+ *			non-volatile memory of a slave.  Objects found in the
+ *			object list in the NVM of the slave are shifted forward
+ *			in order to fill the hole left by the deleted object
+ * @slave:		BIF slave handle
+ * @object:		Existing object in the slave to delete
+ *
+ * Returns 0 on success or errno on failure.  bif_object_put() must still be
+ * called after this function in order to free the memory in the consumer
+ * 'object' struct pointer.
+ *
+ * This function will fail if the NVM lock points to an offset after the
+ * beginning of the existing BIF object.
+ */
+int bif_object_delete(struct bif_slave *slave, const struct bif_object *object)
+{
+	struct bif_object *del_object = NULL;
+	struct bif_object *tail_object;
+	struct bif_nvm_function *nvm;
+	bool found = false;
+	int pos = 0;
+	int rc;
+	u8 *buf;
+
+	if (IS_ERR_OR_NULL(slave) || IS_ERR_OR_NULL(object)) {
+		pr_err("Invalid input pointer\n");
+		return -EINVAL;
+	}
+
+	nvm = slave->sdev->nvm_function;
+	if (!nvm) {
+		pr_err("BIF slave has no NVM function\n");
+		return -ENODEV;
+	}
+
+	bif_slave_ctrl_lock(slave);
+
+	del_object = bif_object_consumer_search(nvm, object);
+	if (!del_object) {
+		pr_err("BIF object not found within slave\n");
+		rc = -EINVAL;
+		goto error_unlock;
+	}
+
+	if (del_object->addr - nvm->nvm_base_address < nvm->nvm_lock_offset) {
+		pr_err("Cannot delete BIF object in NVM because some portion of it is locked\n");
+		rc = -EPERM;
+		goto error_unlock;
+	}
+
+	buf = kmalloc(nvm->nvm_size, GFP_KERNEL);
+	if (!buf) {
+		pr_err("kzalloc failed\n");
+		rc = -ENOMEM;
+		goto error_unlock;
+	}
+
+	/*
+	 * Copy the contents of objects after the one to be deleted into a flat
+	 * array.
+	 */
+	list_for_each_entry(tail_object, &nvm->object_list, list) {
+		if (found) {
+			bif_object_flatten(&buf[pos], tail_object);
+			pos += tail_object->length;
+		} else if (tail_object == del_object) {
+			found = true;
+		}
+	}
+
+	/* Add the list terminator. */
+	buf[pos++] = BIF_OBJ_END_OF_LIST;
+
+	rc = _bif_slave_nvm_raw_write(slave->sdev,
+		del_object->addr - nvm->nvm_base_address, buf, pos);
+	if (rc < 0) {
+		pr_err("NVM write failed, rc=%d\n", rc);
+		kfree(buf);
+		goto error_unlock;
+	}
+	kfree(buf);
+
+	/* Update the addresses of the objects after the one to be deleted. */
+	found = false;
+	list_for_each_entry(tail_object, &nvm->object_list, list) {
+		if (found)
+			tail_object->addr -= del_object->length;
+		else if (tail_object == del_object)
+			found = true;
+	}
+
+	list_del(&del_object->list);
+	kfree(del_object->data);
+	kfree(del_object);
+	nvm->object_count--;
+
+error_unlock:
+	bif_slave_ctrl_unlock(slave);
+
+	return rc;
+}
+EXPORT_SYMBOL(bif_object_delete);
+
 /**
  * bif_slave_read() - read contiguous memory values from a BIF slave
  * @slave:	BIF slave handle
@@ -1492,6 +2336,74 @@
 EXPORT_SYMBOL(bif_slave_write);
 
 /**
+ * bif_slave_nvm_raw_read() - read contiguous memory values from a BIF slave's
+ *		non-volatile memory (NVM)
+ * @slave:	BIF slave handle
+ * @offset:	Offset from the beginning of BIF slave NVM to begin reading at
+ * @buf:	Buffer to fill with memory values
+ * @len:	Number of byte to read
+ *
+ * Returns 0 for success or errno if an error occurred.
+ */
+int bif_slave_nvm_raw_read(struct bif_slave *slave, u16 offset, u8 *buf,
+				int len)
+{
+	if (IS_ERR_OR_NULL(slave)) {
+		pr_err("Invalid slave pointer=%ld\n", PTR_ERR(slave));
+		return -EINVAL;
+	} else if (IS_ERR_OR_NULL(buf)) {
+		pr_err("Invalid buffer pointer=%ld\n", PTR_ERR(buf));
+		return -EINVAL;
+	} else if (!slave->sdev->nvm_function) {
+		pr_err("BIF slave has no NVM function\n");
+		return -ENODEV;
+	} else if (offset + len > slave->sdev->nvm_function->nvm_size) {
+		pr_err("read offset + len = %d > NVM size = %d\n",
+			offset + len, slave->sdev->nvm_function->nvm_size);
+		return -EINVAL;
+	}
+
+	return bif_slave_read(slave,
+		slave->sdev->nvm_function->nvm_base_address + offset, buf, len);
+}
+EXPORT_SYMBOL(bif_slave_nvm_raw_read);
+
+/**
+ * bif_slave_nvm_raw_write() - write contiguous memory values to a BIF slave's
+ *		non-volatile memory (NVM)
+ * @slave:	BIF slave handle
+ * @offset:	Offset from the beginning of BIF slave NVM to begin writing at
+ * @buf:	Buffer containing values to write
+ * @len:	Number of byte to write
+ *
+ * Note that this function does *not* respect the MIPI-BIF object data
+ * formatting specification.  It can cause corruption of the object data list
+ * stored in NVM if used improperly.
+ *
+ * Returns 0 for success or errno if an error occurred.
+ */
+int bif_slave_nvm_raw_write(struct bif_slave *slave, u16 offset, u8 *buf,
+				int len)
+{
+	int rc;
+
+	if (IS_ERR_OR_NULL(slave)) {
+		pr_err("Invalid slave pointer=%ld\n", PTR_ERR(slave));
+		return -EINVAL;
+	} else if (IS_ERR_OR_NULL(buf)) {
+		pr_err("Invalid buffer pointer=%ld\n", PTR_ERR(buf));
+		return -EINVAL;
+	}
+
+	bif_slave_ctrl_lock(slave);
+	rc = _bif_slave_nvm_raw_write(slave->sdev, offset, buf, len);
+	bif_slave_ctrl_unlock(slave);
+
+	return rc;
+}
+EXPORT_SYMBOL(bif_slave_nvm_raw_write);
+
+/**
  * bif_slave_is_present() - check if a slave is currently physically present
  *		in the system
  * @slave:	BIF slave handle
@@ -2032,45 +2944,6 @@
 	return rc;
 }
 
-/**
- * bif_crc_ccitt() - calculate the CRC-CCITT CRC value of the data specified
- * @buffer:	Data to calculate the CRC of
- * @len:	Length of the data buffer in bytes
- *
- * MIPI-BIF specifies the usage of CRC-CCITT for BIF data objects.  This
- * function performs the CRC calculation while taking into account the bit
- * ordering used by BIF.
- */
-u16 bif_crc_ccitt(const u8 *buffer, unsigned int len)
-{
-	u16 crc = 0xFFFF;
-
-	while (len--) {
-		crc = crc_ccitt_byte(crc, bitrev8(*buffer));
-		buffer++;
-	}
-	return bitrev16(crc);
-}
-EXPORT_SYMBOL(bif_crc_ccitt);
-
-static u16 bif_object_crc_ccitt(const struct bif_object *object)
-{
-	u16 crc = 0xFFFF;
-	int i;
-
-	crc = crc_ccitt_byte(crc, bitrev8(object->type));
-	crc = crc_ccitt_byte(crc, bitrev8(object->version));
-	crc = crc_ccitt_byte(crc, bitrev8(object->manufacturer_id >> 8));
-	crc = crc_ccitt_byte(crc, bitrev8(object->manufacturer_id));
-	crc = crc_ccitt_byte(crc, bitrev8(object->length >> 8));
-	crc = crc_ccitt_byte(crc, bitrev8(object->length));
-
-	for (i = 0; i < object->length - 8; i++)
-		crc = crc_ccitt_byte(crc, bitrev8(object->data[i]));
-
-	return bitrev16(crc);
-}
-
 /*
  * Check if the specified function is an NVM function and if it is, then
  * instantiate NVM function data for the slave and read all objects.
@@ -2079,7 +2952,7 @@
 		struct bif_ddb_l2_data *func)
 {
 	int rc = 0;
-	int data_len;
+	int data_len, read_size;
 	u8 buf[8], object_type;
 	struct bif_object *object;
 	struct bif_object *temp;
@@ -2109,12 +2982,21 @@
 		return rc;
 	}
 
-	sdev->nvm_function->nvm_pointer		= buf[0] << 8 | buf[1];
+	sdev->nvm_function->nvm_pointer			= buf[0] << 8 | buf[1];
 	sdev->nvm_function->slave_control_channel	= buf[2];
 	sdev->nvm_function->write_buffer_size		= buf[3];
 	sdev->nvm_function->nvm_base_address		= buf[4] << 8 | buf[5];
 	sdev->nvm_function->nvm_size			= buf[6] << 8 | buf[7];
 
+	/* Read NVM lock offset */
+	rc = _bif_slave_read(sdev, sdev->nvm_function->nvm_pointer, buf, 2);
+	if (rc) {
+		pr_err("Slave memory read failed, rc=%d\n", rc);
+		return rc;
+	}
+
+	sdev->nvm_function->nvm_lock_offset		= buf[0] << 8 | buf[1];
+
 	INIT_LIST_HEAD(&sdev->nvm_function->object_list);
 
 	/* Read object list */
@@ -2125,8 +3007,7 @@
 		return rc;
 	}
 
-	/* Object type == 0x00 corresponds to the end of the object list. */
-	while (object_type != 0x00) {
+	while (object_type != BIF_OBJ_END_OF_LIST) {
 		object = kzalloc(sizeof(*object), GFP_KERNEL);
 		if (!object) {
 			pr_err("out of memory\n");
@@ -2178,15 +3059,20 @@
 			goto free_data;
 		}
 
-		rc = _bif_slave_read(sdev, addr + 6 + data_len, buf, 3);
+		if ((object->length + addr) >= (sdev->nvm_function->nvm_size
+				+ sdev->nvm_function->nvm_base_address))
+			read_size = 2;
+		else
+			read_size = 3;
+		rc = _bif_slave_read(sdev, addr + 6 + data_len, buf, read_size);
 		if (rc) {
 			pr_err("Slave memory read of object CRC failed; addr=0x%04X, len=%d, rc=%d\n",
-				addr + 6 + data_len, 3, rc);
+				addr + 6 + data_len, read_size, rc);
 			goto free_data;
 		}
 
 		object->crc = buf[0] << 8 | buf[1];
-		object_type = buf[2];
+		object_type = (read_size == 3) ? buf[2] : BIF_OBJ_END_OF_LIST;
 		sdev->nvm_function->object_count++;
 
 		crc = bif_object_crc_ccitt(object);
@@ -2336,6 +3222,12 @@
 			} else if (rc == 1) {
 				sdev->present = true;
 				sdev->bdev->selected_sdev = sdev;
+				rc = bif_parse_slave_data(sdev);
+				if (rc) {
+					pr_err("Failed to parse secondary slave data, rc=%d\n",
+						rc);
+					goto free_slave;
+				}
 			} else {
 				sdev->present = false;
 				sdev->bdev->selected_sdev = NULL;
@@ -2459,6 +3351,11 @@
 			sdev->present = true;
 			sdev->bdev->selected_sdev = sdev;
 			rc = bif_parse_slave_data(sdev);
+			if (rc) {
+				pr_err("Failed to parse secondary slave data, rc=%d\n",
+					rc);
+				return rc;
+			}
 		} else {
 			pr_err("Slave failed to respond to DILC bus command; its UID is thus unverified.\n");
 			sdev->unique_id_bits_known = 0;
diff --git a/drivers/bif/qpnp-bsi.c b/drivers/bif/qpnp-bsi.c
index 19a560a..e3f7d2f 100644
--- a/drivers/bif/qpnp-bsi.c
+++ b/drivers/bif/qpnp-bsi.c
@@ -170,7 +170,7 @@
 #define QPNP_BSI_DEFAULT_VID_REF_UV	1800000
 
 /* These have units of tau_bif. */
-#define QPNP_BSI_MAX_TRANSMIT_CYCLES	36
+#define QPNP_BSI_MAX_TRANSMIT_CYCLES	46
 #define QPNP_BSI_MIN_RECEIVE_CYCLES	24
 #define QPNP_BSI_MAX_BUS_QUERY_CYCLES	17
 
@@ -544,12 +544,6 @@
 	struct qpnp_bsi_chip *chip = bdev_get_drvdata(bdev);
 	int rc;
 
-	rc = qpnp_bsi_clear_bsi_error(chip);
-	if (rc)
-		return rc;
-
-	qpnp_bsi_clear_irq_flags(chip);
-
 	qpnp_bsi_set_com_mode(chip, QPNP_BSI_COM_MODE_IRQ);
 
 	rc = qpnp_bsi_set_bus_state(bdev, BIF_BUS_STATE_ACTIVE);
@@ -563,6 +557,12 @@
 	if (rc)
 		return rc;
 
+	rc = qpnp_bsi_clear_bsi_error(chip);
+	if (rc)
+		return rc;
+
+	qpnp_bsi_clear_irq_flags(chip);
+
 	rc = qpnp_bsi_issue_transaction_wait_for_tx(chip, transaction, data);
 	if (rc)
 		return rc;
@@ -578,12 +578,6 @@
 	struct qpnp_bsi_chip *chip = bdev_get_drvdata(bdev);
 	int rc, timeout;
 
-	rc = qpnp_bsi_clear_bsi_error(chip);
-	if (rc)
-		return rc;
-
-	qpnp_bsi_clear_irq_flags(chip);
-
 	qpnp_bsi_set_com_mode(chip, QPNP_BSI_COM_MODE_IRQ);
 
 	rc = qpnp_bsi_set_bus_state(bdev, BIF_BUS_STATE_ACTIVE);
@@ -597,6 +591,12 @@
 	if (rc)
 		return rc;
 
+	rc = qpnp_bsi_clear_bsi_error(chip);
+	if (rc)
+		return rc;
+
+	qpnp_bsi_clear_irq_flags(chip);
+
 	rc = qpnp_bsi_issue_transaction_wait_for_tx(chip, transaction, data);
 	if (rc)
 		return rc;
@@ -624,12 +624,6 @@
 	int rc, timeout;
 	u8 buf[3];
 
-	rc = qpnp_bsi_clear_bsi_error(chip);
-	if (rc)
-		return rc;
-
-	qpnp_bsi_clear_irq_flags(chip);
-
 	qpnp_bsi_set_com_mode(chip, QPNP_BSI_COM_MODE_IRQ);
 
 	rc = qpnp_bsi_set_bus_state(bdev, BIF_BUS_STATE_ACTIVE);
@@ -643,6 +637,12 @@
 	if (rc)
 		return rc;
 
+	rc = qpnp_bsi_clear_bsi_error(chip);
+	if (rc)
+		return rc;
+
+	qpnp_bsi_clear_irq_flags(chip);
+
 	rc = qpnp_bsi_issue_transaction_wait_for_tx(chip, transaction, data);
 	if (rc)
 		return rc;
@@ -826,10 +826,10 @@
 	/*
 	 * Send burst read length bus commands according to the following:
 	 *
-	 * 256                --> RBL0
-	 * 0-255 = 16 * y + x --> RBEy and RBLx
-	 *		RBE0 does not need to be sent
-	 *		RBL0 does not need to be sent
+	 * 1                     --> No RBE or RBL
+	 * 2  - 15  = x          --> RBLx
+	 * 16 - 255 = 16 * y + x --> RBEy and RBLx (RBL0 not sent)
+	 * 256                   --> RBL0
 	 */
 	if (burst_len == 256) {
 		rc = qpnp_bsi_issue_transaction(chip, BIF_TRANS_BC,
@@ -851,7 +851,7 @@
 			return rc;
 	}
 
-	if (burst_len % 16) {
+	if (burst_len % 16 && burst_len > 1) {
 		rc = qpnp_bsi_issue_transaction(chip, BIF_TRANS_BC,
 					BIF_CMD_RBL + (burst_len % 16));
 		if (rc)
@@ -906,12 +906,6 @@
 	int rc, rc2, i, burst_len;
 	u8 buf[3];
 
-	rc = qpnp_bsi_clear_bsi_error(chip);
-	if (rc)
-		return rc;
-
-	qpnp_bsi_clear_irq_flags(chip);
-
 	qpnp_bsi_set_com_mode(chip, QPNP_BSI_COM_MODE_POLL);
 
 	rc = qpnp_bsi_set_bus_state(bdev, BIF_BUS_STATE_ACTIVE);
@@ -925,6 +919,12 @@
 	if (rc)
 		return rc;
 
+	rc = qpnp_bsi_clear_bsi_error(chip);
+	if (rc)
+		return rc;
+
+	qpnp_bsi_clear_irq_flags(chip);
+
 	while (len > 0) {
 		burst_len = min(len, 256);
 
@@ -1001,12 +1001,6 @@
 	unsigned long flags;
 	int rc, rc2, i;
 
-	rc = qpnp_bsi_clear_bsi_error(chip);
-	if (rc)
-		return rc;
-
-	qpnp_bsi_clear_irq_flags(chip);
-
 	qpnp_bsi_set_com_mode(chip, QPNP_BSI_COM_MODE_POLL);
 
 	rc = qpnp_bsi_set_bus_state(bdev, BIF_BUS_STATE_ACTIVE);
@@ -1020,6 +1014,12 @@
 	if (rc)
 		return rc;
 
+	rc = qpnp_bsi_clear_bsi_error(chip);
+	if (rc)
+		return rc;
+
+	qpnp_bsi_clear_irq_flags(chip);
+
 	rc = qpnp_bsi_issue_transaction(chip, BIF_TRANS_ERA, addr >> 8);
 	if (rc)
 		return rc;
@@ -1075,12 +1075,6 @@
 	struct qpnp_bsi_chip *chip = bdev_get_drvdata(bdev);
 	int rc;
 
-	rc = qpnp_bsi_clear_bsi_error(chip);
-	if (rc)
-		return rc;
-
-	qpnp_bsi_clear_irq_flags(chip);
-
 	qpnp_bsi_set_com_mode(chip, QPNP_BSI_COM_MODE_IRQ);
 
 	/*
@@ -1105,6 +1099,12 @@
 	 */
 	chip->state = BIF_BUS_STATE_INTERRUPT;
 
+	rc = qpnp_bsi_clear_bsi_error(chip);
+	if (rc)
+		return rc;
+
+	qpnp_bsi_clear_irq_flags(chip);
+
 	/* Send EINT bus command. */
 	rc = qpnp_bsi_issue_transaction_wait_for_tx(chip, BIF_TRANS_BC,
 							BIF_CMD_EINT);
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index 7409ccb..81a90fe 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -1661,6 +1661,9 @@
 static int qcedev_check_cipher_params(struct qcedev_cipher_op_req *req,
 						struct qcedev_control *podev)
 {
+	uint32_t total = 0;
+	uint32_t i;
+
 	if (req->use_pmem) {
 		pr_err("%s: Use of PMEM is not supported\n", __func__);
 		goto error;
@@ -1712,7 +1715,22 @@
 			goto error;
 		}
 	}
-
+	/* Check for sum of all dst length is equal to data_len  */
+	for (i = 0; (i < QCEDEV_MAX_BUFFERS) && (total < req->data_len); i++)
+		total += req->vbuf.dst[i].len;
+	if (total != req->data_len) {
+		pr_err("%s: Total (i=%d) dst(%d) buf size != data_len (%d)\n",
+			__func__, i, total, req->data_len);
+		goto error;
+	}
+	/* Check for sum of all src length is equal to data_len  */
+	for (i = 0, total = 0; i < req->entries; i++)
+		total += req->vbuf.src[i].len;
+	if (total != req->data_len) {
+		pr_err("%s: Total src(%d) buf size != data_len (%d)\n",
+			__func__, total, req->data_len);
+		goto error;
+	}
 	return 0;
 error:
 	return -EINVAL;
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index ecda5a7..a06ebbf 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -72,16 +72,18 @@
 
 static struct iommu_access_ops *iommu_access_ops;
 
-static void _iommu_lock(void)
+static void _iommu_lock(struct kgsl_iommu const *iommu)
 {
 	if (iommu_access_ops && iommu_access_ops->iommu_lock_acquire)
-		iommu_access_ops->iommu_lock_acquire();
+		iommu_access_ops->iommu_lock_acquire(
+						iommu->sync_lock_initialized);
 }
 
-static void _iommu_unlock(void)
+static void _iommu_unlock(struct kgsl_iommu const *iommu)
 {
 	if (iommu_access_ops && iommu_access_ops->iommu_lock_release)
-		iommu_access_ops->iommu_lock_release();
+		iommu_access_ops->iommu_lock_release(
+						iommu->sync_lock_initialized);
 }
 
 struct remote_iommu_petersons_spinlock kgsl_iommu_sync_lock_vars;
@@ -906,6 +908,8 @@
 	return 0;
 }
 
+#ifdef CONFIG_MSM_IOMMU_GPU_SYNC
+
 /*
  * kgsl_get_sync_lock - Init Sync Lock between GPU and CPU
  * @mmu - Pointer to mmu device
@@ -973,6 +977,12 @@
 
 	return status;
 }
+#else
+static int kgsl_iommu_init_sync_lock(struct kgsl_mmu *mmu)
+{
+	return 0;
+}
+#endif
 
 /*
  * kgsl_iommu_sync_lock - Acquire Sync Lock between GPU and CPU
@@ -1643,7 +1653,7 @@
 	 * changing pagetables we can use this lsb value of the pagetable w/o
 	 * having to read it again
 	 */
-	_iommu_lock();
+	_iommu_lock(iommu);
 	for (i = 0; i < iommu->unit_count; i++) {
 		struct kgsl_iommu_unit *iommu_unit = &iommu->iommu_units[i];
 		for (j = 0; j < iommu_unit->dev_count; j++) {
@@ -1682,7 +1692,7 @@
 		}
 	}
 	kgsl_iommu_lock_rb_in_tlb(mmu);
-	_iommu_unlock();
+	_iommu_unlock(iommu);
 
 	/* For complete CFF */
 	kgsl_cffdump_setmem(mmu->device, mmu->setstate_memory.gpuaddr +
@@ -1788,12 +1798,12 @@
 			for (j = 0; j < iommu_unit->dev_count; j++) {
 				if (iommu_unit->dev[j].fault) {
 					kgsl_iommu_enable_clk(mmu, j);
-					_iommu_lock();
+					_iommu_lock(iommu);
 					KGSL_IOMMU_SET_CTX_REG(iommu,
 						iommu_unit,
 						iommu_unit->dev[j].ctx_id,
 						RESUME, 1);
-					_iommu_unlock();
+					_iommu_unlock(iommu);
 					iommu_unit->dev[j].fault = 0;
 				}
 			}
@@ -1912,7 +1922,7 @@
 		kgsl_idle(mmu->device);
 
 	/* Acquire GPU-CPU sync Lock here */
-	_iommu_lock();
+	_iommu_lock(iommu);
 
 	if (flags & KGSL_MMUFLAGS_PTUPDATE) {
 		if (!msm_soc_version_supports_iommu_v0())
@@ -1979,7 +1989,7 @@
 	}
 
 	/* Release GPU-CPU sync Lock here */
-	_iommu_unlock();
+	_iommu_unlock(iommu);
 
 	/* Disable smmu clock */
 	kgsl_iommu_disable_clk_on_ts(mmu, 0, false);
diff --git a/drivers/input/misc/cm36283.c b/drivers/input/misc/cm36283.c
index d850a0e..17127a8 100644
--- a/drivers/input/misc/cm36283.c
+++ b/drivers/input/misc/cm36283.c
@@ -40,8 +40,6 @@
 #include <asm/mach-types.h>
 #include <asm/setup.h>
 
-#define D(x...) pr_info(x)
-
 #define I2C_RETRY_COUNT 10
 
 #define NEAR_DELAY_TIME ((100 * HZ) / 1000)
@@ -65,8 +63,6 @@
 #define CM36283_PS_MAX_POLL_DELAY	1000
 #define CM36283_PS_DEFAULT_POLL_DELAY	100
 
-static int record_init_fail = 0;
-
 static const int als_range[] = {
 	[CM36283_ALS_IT0] = 6554,
 	[CM36283_ALS_IT1] = 3277,
@@ -156,9 +152,8 @@
 static int I2C_RxData(uint16_t slaveAddr, uint8_t cmd, uint8_t *rxData, int length)
 {
 	uint8_t loop_i;
-	int val;
 	struct cm36283_info *lpi = lp_info;
-  uint8_t subaddr[1];
+	uint8_t subaddr[1];
 
 	struct i2c_msg msgs[] = {
 		{
@@ -174,24 +169,21 @@
 		 .buf = rxData,
 		 },		 
 	};
-  subaddr[0] = cmd;
+
+	subaddr[0] = cmd;
 
 	for (loop_i = 0; loop_i < I2C_RETRY_COUNT; loop_i++) {
 
 		if (i2c_transfer(lp_info->i2c_client->adapter, msgs, 2) > 0)
 			break;
 
-		val = gpio_get_value(lpi->intr_pin);
-		/*check intr GPIO when i2c error*/
-		if (loop_i == 0 || loop_i == I2C_RETRY_COUNT -1)
-			D("[PS][CM36283 error] %s, i2c err, slaveAddr 0x%x ISR gpio %d  = %d, record_init_fail %d \n",
-				__func__, slaveAddr, lpi->intr_pin, val, record_init_fail);
-
+		dev_err(&lpi->i2c_client->dev, "%s: I2C error(%d). Retrying.\n",
+				__func__, cmd);
 		msleep(10);
 	}
 	if (loop_i >= I2C_RETRY_COUNT) {
-		printk(KERN_ERR "[PS_ERR][CM36283 error] %s retry over %d\n",
-			__func__, I2C_RETRY_COUNT);
+		dev_err(&lpi->i2c_client->dev, "%s: Retry count exceeds %d.",
+				__func__, I2C_RETRY_COUNT);
 		return -EIO;
 	}
 
@@ -201,8 +193,8 @@
 static int I2C_TxData(uint16_t slaveAddr, uint8_t *txData, int length)
 {
 	uint8_t loop_i;
-	int val;
 	struct cm36283_info *lpi = lp_info;
+
 	struct i2c_msg msg[] = {
 		{
 		 .addr = slaveAddr,
@@ -216,18 +208,13 @@
 		if (i2c_transfer(lp_info->i2c_client->adapter, msg, 1) > 0)
 			break;
 
-		val = gpio_get_value(lpi->intr_pin);
-		/*check intr GPIO when i2c error*/
-		if (loop_i == 0 || loop_i == I2C_RETRY_COUNT -1)
-			D("[PS][CM36283 error] %s, i2c err, slaveAddr 0x%x, value 0x%x, ISR gpio%d  = %d, record_init_fail %d\n",
-				__func__, slaveAddr, txData[0], lpi->intr_pin, val, record_init_fail);
-
+		pr_err("%s: I2C error. Retrying...\n", __func__);
 		msleep(10);
 	}
 
 	if (loop_i >= I2C_RETRY_COUNT) {
-		printk(KERN_ERR "[PS_ERR][CM36283 error] %s retry over %d\n",
-			__func__, I2C_RETRY_COUNT);
+		dev_err(&lpi->i2c_client->dev, "%s: Retry count exceeds %d.",
+				__func__, I2C_RETRY_COUNT);
 		return -EIO;
 	}
 
@@ -244,18 +231,12 @@
 
 	ret = I2C_RxData(slaveAddr, cmd, buffer, 2);
 	if (ret < 0) {
-		pr_err(
-			"[PS_ERR][CM3218 error]%s: I2C_RxData fail [0x%x, 0x%x]\n",
-			__func__, slaveAddr, cmd);
+		pr_err("%s: I2C RxData fail(%d).\n", __func__, cmd);
 		return ret;
 	}
 
 	*pdata = (buffer[1]<<8)|buffer[0];
-#if 0
-	/* Debug use */
-	printk(KERN_DEBUG "[CM3218] %s: I2C_RxData[0x%x, 0x%x] = 0x%x\n",
-		__func__, slaveAddr, cmd, *pdata);
-#endif
+
 	return ret;
 }
 
@@ -263,19 +244,14 @@
 {
 	char buffer[3];
 	int ret = 0;
-#if 0
-	/* Debug use */
-	printk(KERN_DEBUG
-	"[CM3218] %s: _cm36283_I2C_Write_Word[0x%x, 0x%x, 0x%x]\n",
-		__func__, SlaveAddress, cmd, data);
-#endif
+
 	buffer[0] = cmd;
 	buffer[1] = (uint8_t)(data&0xff);
 	buffer[2] = (uint8_t)((data&0xff00)>>8);	
 	
 	ret = I2C_TxData(SlaveAddress, buffer, 3);
 	if (ret < 0) {
-		pr_err("[PS_ERR][CM3218 error]%s: I2C_TxData fail\n", __func__);
+		pr_err("%s: I2C_TxData failed.\n", __func__);
 		return -EIO;
 	}
 
@@ -285,7 +261,7 @@
 static int get_ls_adc_value(uint16_t *als_step, bool resume)
 {
 	struct cm36283_info *lpi = lp_info;
-	uint32_t tmpResult;
+	uint32_t tmp;
 	int ret = 0;
 
 	if (als_step == NULL)
@@ -294,22 +270,20 @@
 	/* Read ALS data: */
 	ret = _cm36283_I2C_Read_Word(lpi->slave_addr, ALS_DATA, als_step);
 	if (ret < 0) {
-		pr_err(
-			"[LS][CM3218 error]%s: _cm36283_I2C_Read_Word fail\n",
-			__func__);
+		dev_err(&lpi->i2c_client->dev, "%s: I2C read word failed.\n",
+				__func__);
 		return -EIO;
 	}
 
-  if (!lpi->ls_calibrate) {
-		tmpResult = (uint32_t)(*als_step) * lpi->als_gadc / lpi->als_kadc;
-		if (tmpResult > 0xFFFF)
+	if (!lpi->ls_calibrate) {
+		tmp = (uint32_t)(*als_step) * lpi->als_gadc / lpi->als_kadc;
+		if (tmp > 0xFFFF)
 			*als_step = 0xFFFF;
 		else
-		  *als_step = tmpResult;  			
+			*als_step = tmp;
 	}
 
-	D("[LS][CM3218] %s: raw adc = 0x%X, ls_calibrate = %d\n",
-		__func__, *als_step, lpi->ls_calibrate);
+	dev_dbg(&lpi->i2c_client->dev, "raw adc = 0x%x\n", *als_step);
 
 	return ret;
 }
@@ -335,18 +309,10 @@
 
 	ret = _cm36283_I2C_Read_Word(lpi->slave_addr, PS_DATA, data);
 	
+	if (ret < 0)
+		return ret;
+
 	(*data) &= 0xFF;
-	
-	if (ret < 0) {
-		pr_err(
-			"[PS][CM36283 error]%s: _cm36283_I2C_Read_Word fail\n",
-			__func__);
-		return -EIO;
-	} else {
-		pr_err(
-			"[PS][CM36283 OK]%s: _cm36283_I2C_Read_Word OK 0x%x\n",
-			__func__, *data);
-	}
 
 	return ret;
 }
@@ -383,16 +349,16 @@
 			msleep(10);
 			wait_count++;
 			if (wait_count > 12) {
-				pr_err("[PS_ERR][CM36283 error]%s: interrupt GPIO low,"
-					" get_ps_adc_value\n", __func__);
+				dev_err(&lpi->i2c_client->dev, "%s: interrupt GPIO low\n",
+					       __func__);
 				return -EIO;
 			}
 		}
 
 		ret = get_ps_adc_value(&value[i]);
 		if (ret < 0) {
-			pr_err("[PS_ERR][CM36283 error]%s: get_ps_adc_value\n",
-				__func__);
+			dev_err(&lpi->i2c_client->dev,
+					"%s: error get ps value\n", __func__);
 			return -EIO;
 		}
 
@@ -402,10 +368,8 @@
 		wait_count = 0;
 	}
 
-	/*D("Sta_ps: Before sort, value[0, 1, 2] = [0x%x, 0x%x, 0x%x]",
-		value[0], value[1], value[2]);*/
 	mid_val = mid_value(value, 3);
-	D("Sta_ps: After sort, value[0, 1, 2] = [0x%x, 0x%x, 0x%x]",
+	dev_dbg(&lpi->i2c_client->dev, "Sta_ps: After sort, value[0, 1, 2] = [0x%x, 0x%x, 0x%x]",
 		value[0], value[1], value[2]);
 	*ps_adc = (mid_val & 0xFF);
 
@@ -531,14 +495,16 @@
 
 static void psensor_initial_cmd(struct cm36283_info *lpi)
 {
-	/*must disable p-sensor interrupt befrore IST create*//*disable ALS func*/		
-  lpi->ps_conf1_val |= CM36283_PS_SD;
-  lpi->ps_conf1_val &= CM36283_PS_INT_MASK;  
-  _cm36283_I2C_Write_Word(lpi->slave_addr, PS_CONF1, lpi->ps_conf1_val);   
-  _cm36283_I2C_Write_Word(lpi->slave_addr, PS_CONF3, lpi->ps_conf3_val);
-  _cm36283_I2C_Write_Word(lpi->slave_addr, PS_THD, (lpi->ps_close_thd_set <<8)| lpi->ps_away_thd_set);
+	/*must disable p-sensor interrupt befrore IST create*/
+	lpi->ps_conf1_val |= CM36283_PS_SD;
+	lpi->ps_conf1_val &= CM36283_PS_INT_MASK;
+	_cm36283_I2C_Write_Word(lpi->slave_addr, PS_CONF1, lpi->ps_conf1_val);
+	_cm36283_I2C_Write_Word(lpi->slave_addr, PS_CONF3, lpi->ps_conf3_val);
+	_cm36283_I2C_Write_Word(lpi->slave_addr, PS_THD,
+			(lpi->ps_close_thd_set << 8) | lpi->ps_away_thd_set);
 
-	D("[PS][CM36283] %s, finish\n", __func__);	
+	dev_dbg(&lpi->i2c_client->dev,
+			"%s:send psensor initial command finished\n", __func__);
 }
 
 static int psensor_enable(struct cm36283_info *lpi)
@@ -547,10 +513,10 @@
 	unsigned int delay;
 	
 	mutex_lock(&ps_enable_mutex);
-	D("[PS][CM36283] %s\n", __func__);
+	dev_dbg(&lpi->i2c_client->dev, "psensor enable!\n");
 
 	if (lpi->ps_enable) {
-		D("[PS][CM36283] %s: already enabled\n", __func__);
+		dev_err(&lpi->i2c_client->dev, "already enabled\n");
 		ret = 0;
 	} else {
 		ret = control_and_report(lpi, CONTROL_PS, 1, 0);
@@ -573,10 +539,10 @@
 		cancel_delayed_work_sync(&lpi->pdwork);
 
 	mutex_lock(&ps_disable_mutex);
-	D("[PS][CM36283] %s\n", __func__);
+	dev_dbg(&lpi->i2c_client->dev, "psensor disable!\n");
 
 	if (lpi->ps_enable == 0) {
-		D("[PS][CM36283] %s: already disabled\n", __func__);
+		dev_err(&lpi->i2c_client->dev, "already disabled\n");
 		ret = 0;
 	} else {
 		ret = control_and_report(lpi, CONTROL_PS, 0, 0);
@@ -590,7 +556,7 @@
 {
 	struct cm36283_info *lpi = lp_info;
 
-	D("[PS][CM36283] %s\n", __func__);
+	dev_dbg(&lpi->i2c_client->dev, "psensor open!");
 
 	if (lpi->psensor_opened)
 		return -EBUSY;
@@ -604,7 +570,7 @@
 {
 	struct cm36283_info *lpi = lp_info;
 
-	D("[PS][CM36283] %s\n", __func__);
+	dev_dbg(&lpi->i2c_client->dev, "psensor release!");
 
 	lpi->psensor_opened = 0;
 
@@ -618,7 +584,7 @@
 	int val;
 	struct cm36283_info *lpi = lp_info;
 
-	D("[PS][CM36283] %s cmd %d\n", __func__, _IOC_NR(cmd));
+	dev_dbg(&lpi->i2c_client->dev, "%s cmd %d\n", __func__, _IOC_NR(cmd));
 
 	switch (cmd) {
 	case CAPELLA_CM3602_IOCTL_ENABLE:
@@ -633,7 +599,7 @@
 		return put_user(lpi->ps_enable, (unsigned long __user *)arg);
 		break;
 	default:
-		pr_err("[PS][CM36283 error]%s: invalid cmd %d\n",
+		dev_err(&lpi->i2c_client->dev, "%s: invalid cmd %d\n",
 			__func__, _IOC_NR(cmd));
 		return -EINVAL;
 	}
@@ -655,18 +621,19 @@
 void lightsensor_set_kvalue(struct cm36283_info *lpi)
 {
 	if (!lpi) {
-		pr_err("[LS][CM36283 error]%s: ls_info is empty\n", __func__);
+		pr_err("%s: ls_info is empty\n", __func__);
 		return;
 	}
 
-	D("[LS][CM36283] %s: ALS calibrated als_kadc=0x%x\n",
+	dev_dbg(&lpi->i2c_client->dev, "%s: ALS calibrated als_kadc=0x%x\n",
 			__func__, als_kadc);
 
 	if (als_kadc >> 16 == ALS_CALIBRATED)
 		lpi->als_kadc = als_kadc & 0xFFFF;
 	else {
 		lpi->als_kadc = 0;
-		D("[LS][CM36283] %s: no ALS calibrated\n", __func__);
+		dev_dbg(&lpi->i2c_client->dev, "%s: no ALS calibrated\n",
+				__func__);
 	}
 
 	if (lpi->als_kadc && lpi->golden_adc > 0) {
@@ -677,25 +644,26 @@
 		lpi->als_kadc = 1;
 		lpi->als_gadc = 1;
 	}
-	D("[LS][CM36283] %s: als_kadc=0x%x, als_gadc=0x%x\n",
+	dev_dbg(&lpi->i2c_client->dev, "%s: als_kadc=0x%x, als_gadc=0x%x\n",
 		__func__, lpi->als_kadc, lpi->als_gadc);
 }
 
 
 static int lightsensor_update_table(struct cm36283_info *lpi)
 {
-	uint32_t tmpData[10];
+	uint32_t tmp_data[10];
 	int i;
 	for (i = 0; i < 10; i++) {
-		tmpData[i] = (uint32_t)(*(lpi->adc_table + i))
-				* lpi->als_kadc / lpi->als_gadc ;
-		if( tmpData[i] <= 0xFFFF ){
-      lpi->cali_table[i] = (uint16_t) tmpData[i];		
-    } else {
-      lpi->cali_table[i] = 0xFFFF;    
-    }         
-		D("[LS][CM36283] %s: Calibrated adc_table: data[%d], %x\n",
-			__func__, i, lpi->cali_table[i]);
+		tmp_data[i] = (uint32_t)(*(lpi->adc_table + i))
+			* lpi->als_kadc / lpi->als_gadc;
+
+		if (tmp_data[i] <= 0xFFFF)
+			lpi->cali_table[i] = (uint16_t) tmp_data[i];
+		else
+			lpi->cali_table[i] = 0xFFFF;
+
+		dev_dbg(&lpi->i2c_client->dev, "%s: Calibrated adc_table: data[%d], %x\n",
+				__func__, i, lpi->cali_table[i]);
 	}
 
 	return 0;
@@ -708,10 +676,10 @@
 	unsigned int delay;
 	
 	mutex_lock(&als_enable_mutex);
-	D("[LS][CM36283] %s\n", __func__);
 
 	if (lpi->als_enable) {
-		D("[LS][CM36283] %s: already enabled\n", __func__);
+		dev_err(&lpi->i2c_client->dev, "%s: already enabled\n",
+			       __func__);
 		ret = 0;
 	} else {
 		ret = control_and_report(lpi, CONTROL_ALS, 1, 0);
@@ -731,13 +699,13 @@
 {
 	int ret = -EIO;
 	mutex_lock(&als_disable_mutex);
-	D("[LS][CM36283] %s\n", __func__);
+	dev_dbg(&lpi->i2c_client->dev, "disable lightsensor\n");
 
 	if (lpi->polling)
 		cancel_delayed_work_sync(&lpi->ldwork);
 
 	if ( lpi->als_enable == 0 ) {
-		D("[LS][CM36283] %s: already disabled\n", __func__);
+		dev_err(&lpi->i2c_client->dev, "already disabled\n");
 		ret = 0;
 	} else {
 		ret = control_and_report(lpi, CONTROL_ALS, 0, 0);
@@ -752,9 +720,10 @@
 	struct cm36283_info *lpi = lp_info;
 	int rc = 0;
 
-	D("[LS][CM36283] %s\n", __func__);
+	dev_dbg(&lpi->i2c_client->dev, "%s\n", __func__);
 	if (lpi->lightsensor_opened) {
-		pr_err("[LS][CM36283 error]%s: already opened\n", __func__);
+		dev_err(&lpi->i2c_client->dev, "%s: already opened\n",
+				__func__);
 		rc = -EBUSY;
 	}
 	lpi->lightsensor_opened = 1;
@@ -765,7 +734,7 @@
 {
 	struct cm36283_info *lpi = lp_info;
 
-	D("[LS][CM36283] %s\n", __func__);
+	dev_dbg(&lpi->i2c_client->dev, "%s\n", __func__);
 	lpi->lightsensor_opened = 0;
 	return 0;
 }
@@ -776,22 +745,16 @@
 	int rc, val;
 	struct cm36283_info *lpi = lp_info;
 
-	/*D("[CM36283] %s cmd %d\n", __func__, _IOC_NR(cmd));*/
-
 	switch (cmd) {
 	case LIGHTSENSOR_IOCTL_ENABLE:
 		if (get_user(val, (unsigned long __user *)arg)) {
 			rc = -EFAULT;
 			break;
 		}
-		D("[LS][CM36283] %s LIGHTSENSOR_IOCTL_ENABLE, value = %d\n",
-			__func__, val);
 		rc = val ? lightsensor_enable(lpi) : lightsensor_disable(lpi);
 		break;
 	case LIGHTSENSOR_IOCTL_GET_ENABLED:
 		val = lpi->als_enable;
-		D("[LS][CM36283] %s LIGHTSENSOR_IOCTL_GET_ENABLED, enabled %d\n",
-			__func__, val);
 		rc = put_user(val, (unsigned long __user *)arg);
 		break;
 	default:
@@ -850,29 +813,28 @@
 		&& ps_en != 10 && ps_en != 13 && ps_en != 16)
 		return -EINVAL;
 
-	if (ps_en) {
-		D("[PS][CM36283] %s: ps_en=%d\n",
+	dev_dbg(&lpi->i2c_client->dev, "%s: ps_en=%d\n",
 			__func__, ps_en);
-		psensor_enable(lpi);
-	} else
-		psensor_disable(lpi);
 
-	D("[PS][CM36283] %s\n", __func__);
+	if (ps_en)
+		psensor_enable(lpi);
+	else
+		psensor_disable(lpi);
 
 	return count;
 }
 
 static DEVICE_ATTR(ps_adc, 0664, ps_adc_show, ps_enable_store);
 
-unsigned PS_cmd_test_value;
 static ssize_t ps_parameters_show(struct device *dev,
 			struct device_attribute *attr, char *buf)
 {
 	int ret;
 	struct cm36283_info *lpi = lp_info;
 
-	ret = sprintf(buf, "PS_close_thd_set = 0x%x, PS_away_thd_set = 0x%x, PS_cmd_cmd:value = 0x%x\n",
-		lpi->ps_close_thd_set, lpi->ps_away_thd_set, PS_cmd_test_value);
+	ret = snprintf(buf, PAGE_SIZE,
+			"PS_close_thd_set = 0x%x, PS_away_thd_set = 0x%x\n",
+			lpi->ps_close_thd_set, lpi->ps_away_thd_set);
 
 	return ret;
 }
@@ -885,19 +847,23 @@
 	struct cm36283_info *lpi = lp_info;
 	char *token[10];
 	int i;
+	unsigned long tmp;
 
-	printk(KERN_INFO "[PS][CM36283] %s\n", buf);
 	for (i = 0; i < 3; i++)
 		token[i] = strsep((char **)&buf, " ");
 
-	lpi->ps_close_thd_set = simple_strtoul(token[0], NULL, 16);
-	lpi->ps_away_thd_set = simple_strtoul(token[1], NULL, 16);	
-	PS_cmd_test_value = simple_strtoul(token[2], NULL, 16);
-	printk(KERN_INFO
-		"[PS][CM36283]Set PS_close_thd_set = 0x%x, PS_away_thd_set = 0x%x, PS_cmd_cmd:value = 0x%x\n",
-		lpi->ps_close_thd_set, lpi->ps_away_thd_set, PS_cmd_test_value);
+	if (kstrtoul(token[0], 16, &tmp))
+		return -EINVAL;
+	lpi->ps_close_thd_set = tmp;
 
-	D("[PS][CM36283] %s\n", __func__);
+	if (kstrtoul(token[1], 16, &tmp))
+		return -EINVAL;
+	lpi->ps_away_thd_set = tmp;
+
+	dev_dbg(&lpi->i2c_client->dev, "ps_close_thd_set:0x%x\n",
+			lpi->ps_close_thd_set);
+	dev_dbg(&lpi->i2c_client->dev, "ps_away_thd_set:0x%x\n",
+			lpi->ps_away_thd_set);
 
 	return count;
 }
@@ -920,14 +886,14 @@
 	struct cm36283_info *lpi = lp_info;
 
 	sscanf(buf, "0x%x 0x%x", &code1, &code2);
+	dev_dbg(&lpi->i2c_client->dev, "PS_CONF1:0x%x PS_CONF3:0x%x\n",
+			code1, code2);
 
-	D("[PS]%s: store value PS conf1 reg = 0x%x PS conf3 reg = 0x%x\n", __func__, code1, code2);
+	lpi->ps_conf1_val = code1;
+	lpi->ps_conf3_val = code2;
 
-  lpi->ps_conf1_val = code1;
-  lpi->ps_conf3_val = code2;
-
-	_cm36283_I2C_Write_Word(lpi->slave_addr, PS_CONF3, lpi->ps_conf3_val );  
-	_cm36283_I2C_Write_Word(lpi->slave_addr, PS_CONF1, lpi->ps_conf1_val );
+	_cm36283_I2C_Write_Word(lpi->slave_addr, PS_CONF3, lpi->ps_conf3_val);
+	_cm36283_I2C_Write_Word(lpi->slave_addr, PS_CONF1, lpi->ps_conf1_val);
 
 	return count;
 }
@@ -950,12 +916,13 @@
 
 	sscanf(buf, "0x%x", &code);
 
-	D("[PS]%s: store value = 0x%x\n", __func__, code);
-
 	lpi->ps_away_thd_set = code &0xFF;
-	lpi->ps_close_thd_set = (code &0xFF00)>>8;	
+	lpi->ps_close_thd_set = (code & 0xFF00)>>8;
 
-	D("[PS]%s: ps_close_thd_set = 0x%x, ps_away_thd_set = 0x%x\n", __func__, lpi->ps_close_thd_set, lpi->ps_away_thd_set);
+	dev_dbg(&lpi->i2c_client->dev, "ps_away_thd_set:0x%x\n",
+			lpi->ps_away_thd_set);
+	dev_dbg(&lpi->i2c_client->dev, "ps_close_thd_set:0x%x\n",
+			lpi->ps_close_thd_set);
 
 	return count;
 }
@@ -977,12 +944,9 @@
 				const char *buf, size_t count)
 {
 	int code;
-//	struct cm36283_info *lpi = lp_info;
 
 	sscanf(buf, "0x%x", &code);
 
-	D("[PS]%s: store value = 0x%x\n", __func__, code);
-
 	return count;
 }
 static DEVICE_ATTR(ps_hw, 0664, ps_hw_show, ps_hw_store);
@@ -993,8 +957,6 @@
 	int ret;
 	struct cm36283_info *lpi = lp_info;
 
-	D("[LS][CM36283] %s: ADC = 0x%04X, Level = %d \n",
-		__func__, lpi->current_adc, lpi->current_level);
 	ret = sprintf(buf, "ADC[0x%04X] => level %d\n",
 		lpi->current_adc, lpi->current_level);
 
@@ -1038,12 +1000,14 @@
 		ret = lightsensor_disable(lpi);
 	}
 
-	D("[LS][CM36283] %s: lpi->als_enable = %d, lpi->ls_calibrate = %d, ls_auto=%d\n",
-		__func__, lpi->als_enable, lpi->ls_calibrate, ls_auto);
+	dev_dbg(&lpi->i2c_client->dev, "als_enable:0x%x\n",
+			lpi->als_enable);
+	dev_dbg(&lpi->i2c_client->dev, "ls_calibrate:0x%x\n",
+			lpi->ls_calibrate);
+	dev_dbg(&lpi->i2c_client->dev, "ls_auto:0x%x\n", ls_auto);
 
 	if (ret < 0)
-		pr_err(
-		"[LS][CM36283 error]%s: set auto light sensor fail\n",
+		dev_err(&lpi->i2c_client->dev, "%s: set auto light sensor fail\n",
 		__func__);
 
 	return count;
@@ -1074,17 +1038,18 @@
 	sscanf(buf, "%d", &kadc_temp);
 
 	mutex_lock(&als_get_adc_mutex);
-  if(kadc_temp != 0) {
+	if (kadc_temp != 0) {
 		lpi->als_kadc = kadc_temp;
-		if(  lpi->als_gadc != 0){
-  		if (lightsensor_update_table(lpi) < 0)
-				printk(KERN_ERR "[LS][CM36283 error] %s: update ls table fail\n", __func__);
-  	} else {
-			printk(KERN_INFO "[LS]%s: als_gadc =0x%x wait to be set\n",
-					__func__, lpi->als_gadc);
-  	}		
+		if (lpi->als_gadc != 0) {
+			if (lightsensor_update_table(lpi) < 0)
+				dev_err(&lpi->i2c_client->dev, "%s: update ls table fail\n",
+						__func__);
+			else
+				dev_dbg(&lpi->i2c_client->dev, "%s: als_gadc =0x%x wait to be set\n",
+						__func__, lpi->als_gadc);
+		}
 	} else {
-		printk(KERN_INFO "[LS]%s: als_kadc can't be set to zero\n",
+		dev_err(&lpi->i2c_client->dev, "%s: als_kadc can't be set to zero\n",
 				__func__);
 	}
 				
@@ -1115,18 +1080,18 @@
 	sscanf(buf, "%d", &gadc_temp);
 	
 	mutex_lock(&als_get_adc_mutex);
-  if(gadc_temp != 0) {
+	if (gadc_temp != 0) {
 		lpi->als_gadc = gadc_temp;
-		if(  lpi->als_kadc != 0){
-  		if (lightsensor_update_table(lpi) < 0)
-				printk(KERN_ERR "[LS][CM36283 error] %s: update ls table fail\n", __func__);
-  	} else {
-			printk(KERN_INFO "[LS]%s: als_kadc =0x%x wait to be set\n",
-					__func__, lpi->als_kadc);
-  	}		
+		if (lpi->als_kadc != 0) {
+			if (lightsensor_update_table(lpi) < 0)
+				dev_err(&lpi->i2c_client->dev, "%s: update ls table fail\n",
+						__func__);
+		} else {
+			dev_dbg(&lpi->i2c_client->dev, "als_kadc =0x%x wait to be set\n",
+					lpi->als_kadc);
+		}
 	} else {
-		printk(KERN_INFO "[LS]%s: als_gadc can't be set to zero\n",
-				__func__);
+		dev_err(&lpi->i2c_client->dev, "als_gadc can't be set to zero\n");
 	}
 	mutex_unlock(&als_get_adc_mutex);
 	return count;
@@ -1161,29 +1126,24 @@
 	uint16_t tempdata[10];
 	int i;
 
-	printk(KERN_INFO "[LS][CM36283]%s\n", buf);
 	for (i = 0; i < 10; i++) {
 		token[i] = strsep((char **)&buf, " ");
 		tempdata[i] = simple_strtoul(token[i], NULL, 16);
 		if (tempdata[i] < 1 || tempdata[i] > 0xffff) {
-			printk(KERN_ERR
-			"[LS][CM36283 error] adc_table[%d] =  0x%x Err\n",
+			dev_err(&lpi->i2c_client->dev,
+			"adc_table[%d] =  0x%x error\n",
 			i, tempdata[i]);
 			return count;
 		}
 	}
 	mutex_lock(&als_get_adc_mutex);
-	for (i = 0; i < 10; i++) {
+	for (i = 0; i < 10; i++)
 		lpi->adc_table[i] = tempdata[i];
-		printk(KERN_INFO
-		"[LS][CM36283]Set lpi->adc_table[%d] =  0x%x\n",
-		i, *(lp_info->adc_table + i));
-	}
+
 	if (lightsensor_update_table(lpi) < 0)
-		printk(KERN_ERR "[LS][CM36283 error] %s: update ls table fail\n",
+		dev_err(&lpi->i2c_client->dev, "%s: update ls table fail\n",
 		__func__);
 	mutex_unlock(&als_get_adc_mutex);
-	D("[LS][CM36283] %s\n", __func__);
 
 	return count;
 }
@@ -1206,8 +1166,9 @@
 	sscanf(buf, "0x%x", &value);
 
 	lpi->ls_cmd = value;
-	printk(KERN_INFO "[LS]set ALS_CONF = %x\n", lpi->ls_cmd);
-	
+
+	dev_dbg(&lpi->i2c_client->dev, "ALS_CONF:0x%x\n", lpi->ls_cmd);
+
 	_cm36283_I2C_Write_Word(lpi->slave_addr, ALS_CONF, lpi->ls_cmd);
 	return count;
 }
@@ -1285,7 +1246,6 @@
 	fLevel=value;
 	input_report_abs(lpi->ls_input_dev, ABS_MISC, fLevel);
 	input_sync(lpi->ls_input_dev);
-	printk(KERN_INFO "[LS]set fLevel = %d\n", fLevel);
 
 	msleep(1000);
 	fLevel=-1;
@@ -1381,7 +1341,8 @@
 	uint16_t idReg;
 
 	val = gpio_get_value(lpi->intr_pin);
-	D("[PS][CM36283] %s, INTERRUPT GPIO val = %d\n", __func__, val);
+	dev_dbg(&lpi->i2c_client->dev, "%s, INTERRUPT GPIO val = %d\n",
+		       __func__, val);
 
 	ret = _cm36283_I2C_Read_Word(lpi->slave_addr, ID_REG, &idReg);
 
@@ -1545,15 +1506,10 @@
 	struct cm36283_info *lpi;
 	struct cm36283_platform_data *pdata;
 
-	D("[PS][CM36283] %s\n", __func__);
-
-
 	lpi = kzalloc(sizeof(struct cm36283_info), GFP_KERNEL);
 	if (!lpi)
 		return -ENOMEM;
 
-	/*D("[CM36283] %s: client->irq = %d\n", __func__, client->irq);*/
-
 	lpi->i2c_client = client;
 
 	if (client->dev.of_node) {
@@ -1605,7 +1561,7 @@
 	
 	lpi->record_clear_int_fail=0;
 	
-	D("[PS][CM36283] %s: ls_cmd 0x%x\n",
+	dev_dbg(&lpi->i2c_client->dev, "[PS][CM36283] %s: ls_cmd 0x%x\n",
 		__func__, lpi->ls_cmd);
 	
 	if (pdata->ls_cmd == 0) {
@@ -1777,7 +1733,7 @@
 	mutex_init(&wq_lock);
 	INIT_DELAYED_WORK(&lpi->ldwork, lsensor_delay_work_handler);
 	INIT_DELAYED_WORK(&lpi->pdwork, psensor_delay_work_handler);
-	D("[PS][CM36283] %s: Probe success!\n", __func__);
+	dev_dbg(&lpi->i2c_client->dev, "%s: Probe success!\n", __func__);
 
 	return ret;
 
diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.c b/drivers/input/touchscreen/gt9xx/gt9xx.c
index 33ef141..8b08ac9 100644
--- a/drivers/input/touchscreen/gt9xx/gt9xx.c
+++ b/drivers/input/touchscreen/gt9xx/gt9xx.c
@@ -72,7 +72,8 @@
 #define RESET_DELAY_T3_US	200	/* T3: > 100us */
 #define RESET_DELAY_T4		20	/* T4: > 5ms */
 
-#define	PHY_BUF_SIZE		32
+#define PHY_BUF_SIZE		32
+#define PROP_NAME_SIZE		24
 
 #define GTP_MAX_TOUCH		5
 #define GTP_ESD_CHECK_CIRCLE_MS	2000
@@ -143,8 +144,6 @@
 	int ret = -EIO;
 	int retries = 0;
 
-	GTP_DEBUG_FUNC();
-
 	msgs[0].flags = !I2C_M_RD;
 	msgs[0].addr = client->addr;
 	msgs[0].len = GTP_ADDR_LENGTH;
@@ -167,7 +166,6 @@
 		if (DOZE_ENABLED == doze_status)
 			return ret;
 #endif
-		GTP_DEBUG("I2C communication timeout, resetting chip...");
 		if (init_done)
 			gtp_reset_guitar(ts, 10);
 		else
@@ -197,8 +195,6 @@
 	int ret = -EIO;
 	int retries = 0;
 
-	GTP_DEBUG_FUNC();
-
 	msg.flags = !I2C_M_RD;
 	msg.addr = client->addr;
 	msg.len = len;
@@ -215,7 +211,6 @@
 		if (DOZE_ENABLED == doze_status)
 			return ret;
 #endif
-		GTP_DEBUG("I2C communication timeout, resetting chip...");
 		if (init_done)
 			gtp_reset_guitar(ts, 10);
 		else
@@ -314,8 +309,6 @@
 {
 	unsigned long irqflags;
 
-	GTP_DEBUG_FUNC();
-
 	spin_lock_irqsave(&ts->irq_lock, irqflags);
 	if (!ts->irq_is_disabled) {
 		ts->irq_is_disabled = true;
@@ -336,8 +329,6 @@
 {
 	unsigned long irqflags = 0;
 
-	GTP_DEBUG_FUNC();
-
 	spin_lock_irqsave(&ts->irq_lock, irqflags);
 	if (ts->irq_is_disabled) {
 		enable_irq(ts->client->irq);
@@ -362,7 +353,7 @@
 		int w)
 {
 #if GTP_CHANGE_X2Y
-	GTP_SWAP(x, y);
+	swap(x, y);
 #endif
 
 	input_mt_slot(ts->input_dev, id);
@@ -371,8 +362,6 @@
 	input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y);
 	input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, w);
 	input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w);
-
-	GTP_DEBUG("ID:%d, X:%d, Y:%d, W:%d", id, x, y, w);
 }
 
 /*******************************************************
@@ -387,7 +376,6 @@
 {
 	input_mt_slot(ts->input_dev, id);
 	input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false);
-	GTP_DEBUG("Touch id[%2d] release!", id);
 }
 
 
@@ -428,8 +416,6 @@
 	u8 doze_buf[3] = {0x81, 0x4B};
 #endif
 
-	GTP_DEBUG_FUNC();
-
 	ts = container_of(work, struct goodix_ts_data, work);
 #ifdef CONFIG_GT9XX_TOUCHPANEL_UPDATE
 	if (ts->enter_update)
@@ -439,7 +425,6 @@
 #if GTP_SLIDE_WAKEUP
 	if (DOZE_ENABLED == doze_status) {
 		ret = gtp_i2c_read(ts->client, doze_buf, 3);
-		GTP_DEBUG("0x814B = 0x%02X", doze_buf[2]);
 		if (ret > 0) {
 			if (doze_buf[2] == 0xAA) {
 				dev_dbg(&ts->client->dev,
@@ -516,6 +501,7 @@
 
 	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]) {
@@ -537,11 +523,9 @@
 #endif
 	pre_key = key_value;
 
-	GTP_DEBUG("pre_touch:%02x, finger:%02x.", pre_touch, finger);
-
 #if GTP_WITH_PEN
 	if (pre_pen && (touch_num == 0)) {
-		GTP_DEBUG("Pen touch UP(Slot)!");
+		dev_dbg(&ts->client->dev, "Pen touch UP(Slot)!");
 		input_report_key(ts->input_dev, BTN_TOOL_PEN, 0);
 		input_mt_slot(ts->input_dev, 5);
 		input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1);
@@ -558,7 +542,8 @@
 #if GTP_WITH_PEN
 			id = coor_data[pos];
 			if (id == 128) {
-				GTP_DEBUG("Pen touch DOWN(Slot)!");
+				dev_dbg(&ts->client->dev,
+						"Pen touch DOWN(Slot)!");
 				input_x  = coor_data[pos + 1]
 					| (coor_data[pos + 2] << 8);
 				input_y  = coor_data[pos + 3]
@@ -577,7 +562,8 @@
 					ABS_MT_POSITION_Y, input_y);
 				input_report_abs(ts->input_dev,
 					ABS_MT_TOUCH_MAJOR, input_w);
-				GTP_DEBUG("Pen/Stylus: (%d, %d)[%d]",
+				dev_dbg(&ts->client->dev,
+					"Pen/Stylus: (%d, %d)[%d]",
 					input_x, input_y, input_w);
 				pre_pen = 1;
 				pre_touch = 0;
@@ -587,8 +573,6 @@
 			touch_index |= (0x01<<id);
 		}
 
-		GTP_DEBUG("id = %d,touch_index = 0x%x, pre_touch = 0x%x\n",
-			id, touch_index, pre_touch);
 		for (i = 0; i < GTP_MAX_TOUCH; i++) {
 #if GTP_WITH_PEN
 			if (pre_pen == 1)
@@ -644,8 +628,6 @@
 	struct goodix_ts_data
 		*ts = container_of(timer, struct goodix_ts_data, timer);
 
-	GTP_DEBUG_FUNC();
-
 	queue_work(ts->goodix_wq, &ts->work);
 	hrtimer_start(&ts->timer, ktime_set(0, (GTP_POLL_TIME + 6) * 1000000),
 			HRTIMER_MODE_REL);
@@ -666,8 +648,6 @@
 {
 	struct goodix_ts_data *ts = dev_id;
 
-	GTP_DEBUG_FUNC();
-
 	gtp_irq_disable(ts);
 
 	queue_work(ts->goodix_wq, &ts->work);
@@ -699,8 +679,6 @@
 *******************************************************/
 static void gtp_reset_guitar(struct goodix_ts_data *ts, int ms)
 {
-	GTP_DEBUG_FUNC();
-
 	/* This reset sequence will selcet I2C slave address */
 	gpio_direction_output(ts->pdata->reset_gpio, 0);
 	msleep(ms);
@@ -741,20 +719,17 @@
 		(u8)(GTP_REG_SLEEP >> 8),
 		(u8)GTP_REG_SLEEP, 8};
 
-	GTP_DEBUG_FUNC();
-
 #if GTP_DBL_CLK_WAKEUP
 	i2c_control_buf[2] = 0x09;
 #endif
 	gtp_irq_disable(ts);
 
-	GTP_DEBUG("entering doze mode...");
 	while (retry++ < 5) {
 		i2c_control_buf[0] = 0x80;
 		i2c_control_buf[1] = 0x46;
 		ret = gtp_i2c_write(ts->client, i2c_control_buf, 3);
 		if (ret < 0) {
-			GTP_DEBUG(
+			dev_err(&ts->client->dev,
 				"failed to set doze flag into 0x8046, %d",
 				retry);
 			continue;
@@ -793,8 +768,6 @@
 		(u8)(GTP_REG_SLEEP >> 8),
 		(u8)GTP_REG_SLEEP, 5};
 
-	GTP_DEBUG_FUNC();
-
 	ret = gpio_direction_output(ts->pdata->irq_gpio, 0);
 	usleep(5000);
 	while (retry++ < 5) {
@@ -825,8 +798,6 @@
 	u8 retry = 0;
 	s8 ret = -1;
 
-	GTP_DEBUG_FUNC();
-
 #if GTP_POWER_CTRL_SLEEP
 	gtp_reset_guitar(ts, 20);
 
@@ -897,26 +868,9 @@
 	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)};
-
-	GTP_DEBUG("Config Groups\' Lengths: %d, %d, %d, %d, %d, %d",
-			cfg_info_len[0], cfg_info_len[1], cfg_info_len[2],
-			cfg_info_len[3], cfg_info_len[4], cfg_info_len[5]);
+	for (i = 0; i < GOODIX_MAX_CFG_GROUP; i++)
+		dev_dbg(&client->dev, "Config Groups(%d) Lengths: %d",
+			i, ts->pdata->config_data_len[i]);
 
 	ret = gtp_i2c_read_dbl_check(ts->client, 0x41E4, opr_buf, 1);
 	if (SUCCESS == ret) {
@@ -927,14 +881,18 @@
 			return -EINVAL;
 		}
 	}
-	if ((!cfg_info_len[1]) && (!cfg_info_len[2]) && (!cfg_info_len[3])
-		&& (!cfg_info_len[4]) && (!cfg_info_len[5])) {
+
+	for (i = 1; i < GOODIX_MAX_CFG_GROUP; i++) {
+		if (ts->pdata->config_data_len[i])
+			break;
+	}
+	if (i == GOODIX_MAX_CFG_GROUP) {
 		sensor_id = 0;
 	} else {
 		ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_SENSOR_ID,
 			&sensor_id, 1);
 		if (SUCCESS == ret) {
-			if (sensor_id >= 0x06) {
+			if (sensor_id >= GOODIX_MAX_CFG_GROUP) {
 				dev_err(&client->dev,
 					"Invalid sensor_id(0x%02X), No Config Sent!",
 					sensor_id);
@@ -946,24 +904,26 @@
 			return -EINVAL;
 		}
 	}
-	GTP_DEBUG("Sensor_ID: %d", sensor_id);
 
-	ts->gtp_cfg_len = cfg_info_len[sensor_id];
+	dev_info(&client->dev, "Sensor ID selected: %d", sensor_id);
 
-	if (ts->gtp_cfg_len < GTP_CONFIG_MIN_LENGTH) {
+	if (ts->pdata->config_data_len[sensor_id] < GTP_CONFIG_MIN_LENGTH ||
+		!ts->pdata->config_data[sensor_id]) {
 		dev_err(&client->dev,
-				"Sensor_ID(%d) matches with NULL or INVALID CONFIG GROUP! NO Config Sent! You need to check you header file CFG_GROUP section!\n",
+				"Sensor_ID(%d) matches with NULL or invalid config group!\n",
 				sensor_id);
 		return -EINVAL;
 	}
+
 	ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_CONFIG_DATA,
 		&opr_buf[0], 1);
-
 	if (ret == SUCCESS) {
 		if (opr_buf[0] < 90) {
 			/* backup group config version */
-			grp_cfg_version = send_cfg_buf[sensor_id][0];
-			send_cfg_buf[sensor_id][0] = 0x00;
+			grp_cfg_version =
+			ts->pdata->config_data[sensor_id][GTP_ADDR_LENGTH];
+			ts->pdata->config_data[sensor_id][GTP_ADDR_LENGTH] =
+				0x00;
 			ts->fixed_cfg = 0;
 		} else {
 			/* treated as fixed config, not send config */
@@ -978,27 +938,9 @@
 		return -EINVAL;
 	}
 
-	if (ts->pdata->gtp_cfg_len) {
-		config_data = ts->pdata->config_data;
-		ts->config_data = ts->pdata->config_data;
-		ts->gtp_cfg_len = ts->pdata->gtp_cfg_len;
-	} else {
-		config_data = devm_kzalloc(&client->dev,
-			GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH,
-				GFP_KERNEL);
-		if (!config_data) {
-			dev_err(&client->dev,
-					"Not enough memory for panel config data\n");
-			return -ENOMEM;
-		}
-
-		ts->config_data = config_data;
-		config_data[0] = GTP_REG_CONFIG_DATA >> 8;
-		config_data[1] = GTP_REG_CONFIG_DATA & 0xff;
-		memset(&config_data[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH);
-		memcpy(&config_data[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];
 
 #if GTP_CUSTOM_CFG
 	config_data[RESOLUTION_LOC] =
@@ -1035,7 +977,6 @@
 	}
 #endif /* !DRIVER NOT SEND CONFIG */
 
-	GTP_DEBUG_FUNC();
 	if ((ts->abs_x_max == 0) && (ts->abs_y_max == 0)) {
 		ts->abs_x_max = (config_data[RESOLUTION_LOC + 1] << 8)
 				+ config_data[RESOLUTION_LOC];
@@ -1047,49 +988,79 @@
 	if (ret < 0)
 		dev_err(&client->dev, "%s: Send config error.\n", __func__);
 
-	GTP_DEBUG("X_MAX = %d, Y_MAX = %d, TRIGGER = 0x%02x",
-			ts->abs_x_max, ts->abs_y_max,
-			ts->int_trigger_type);
-
 	msleep(20);
 	return ret;
 }
 
 /*******************************************************
 Function:
-	Read chip version.
+	Read firmware version
 Input:
 	client:  i2c device
 	version: buffer to keep ic firmware version
 Output:
 	read operation return.
-	2: succeed, otherwise: failed
+	0: succeed, otherwise: failed
 *******************************************************/
-int gtp_read_version(struct i2c_client *client, u16 *version)
+static int gtp_read_fw_version(struct i2c_client *client, u16 *version)
 {
-	int ret = -EIO;
-	u8 buf[8] = { GTP_REG_VERSION >> 8, GTP_REG_VERSION & 0xff };
-
-	GTP_DEBUG_FUNC();
+	int ret = 0;
+	u8 buf[GTP_FW_VERSION_BUFFER_MAXSIZE] = {
+		GTP_REG_FW_VERSION >> 8, GTP_REG_FW_VERSION & 0xff };
 
 	ret = gtp_i2c_read(client, buf, sizeof(buf));
 	if (ret < 0) {
 		dev_err(&client->dev, "GTP read version failed.\n");
-		return ret;
+		return -EIO;
 	}
 
 	if (version)
-		*version = (buf[7] << 8) | buf[6];
+		*version = (buf[3] << 8) | buf[2];
+
+	return ret;
+}
+/*******************************************************
+Function:
+	Read and check chip id.
+Input:
+	client:  i2c device
+Output:
+	read operation return.
+	0: succeed, otherwise: failed
+*******************************************************/
+static int gtp_check_product_id(struct i2c_client *client)
+{
+	int ret = 0;
+	char product_id[GTP_PRODUCT_ID_MAXSIZE];
+	struct goodix_ts_data *ts = i2c_get_clientdata(client);
+	/* 04 bytes are used for the Product-id in the register space.*/
+	u8 buf[GTP_PRODUCT_ID_BUFFER_MAXSIZE] =	{
+		GTP_REG_PRODUCT_ID >> 8, GTP_REG_PRODUCT_ID & 0xff };
+
+	ret = gtp_i2c_read(client, buf, sizeof(buf));
+	if (ret < 0) {
+		dev_err(&client->dev, "GTP read version failed.\n");
+		return -EIO;
+	}
 
 	if (buf[5] == 0x00) {
-		dev_dbg(&client->dev, "IC Version: %c%c%c_%02x%02x\n", buf[2],
-				buf[3], buf[4], buf[7], buf[6]);
+		/* copy (GTP_PRODUCT_ID_MAXSIZE - 1) from buffer. Ex: 915 */
+		strlcpy(product_id, &buf[2], GTP_PRODUCT_ID_MAXSIZE - 1);
 	} else {
 		if (buf[5] == 'S' || buf[5] == 's')
 			chip_gt9xxs = 1;
-		dev_dbg(&client->dev, "IC Version: %c%c%c%c_%02x%02x\n", buf[2],
-				buf[3], buf[4], buf[5], buf[7], buf[6]);
+		/* copy GTP_PRODUCT_ID_MAXSIZE from buffer. Ex: 915s */
+		strlcpy(product_id, &buf[2], GTP_PRODUCT_ID_MAXSIZE);
 	}
+
+	dev_info(&client->dev, "Goodix Product ID = %s\n", product_id);
+
+	if (!IS_ERR(ts->pdata->product_id))
+		ret = strcmp(product_id, ts->pdata->product_id);
+
+	if (ret != 0)
+		return -EINVAL;
+
 	return ret;
 }
 
@@ -1108,8 +1079,6 @@
 	int retry = 5;
 	int ret = -EIO;
 
-	GTP_DEBUG_FUNC();
-
 	while (retry--) {
 		ret = gtp_i2c_read(client, buf, 3);
 		if (ret > 0)
@@ -1198,9 +1167,6 @@
 	int ret;
 	const u8 irq_table[] = GTP_IRQ_TAB;
 
-	GTP_DEBUG("INT trigger type:%x, irq=%d", ts->int_trigger_type,
-			ts->client->irq);
-
 	ret = request_irq(ts->client->irq, goodix_ts_irq_handler,
 			irq_table[ts->int_trigger_type],
 			ts->client->name, ts);
@@ -1240,8 +1206,6 @@
 	int index = 0;
 #endif
 
-	GTP_DEBUG_FUNC();
-
 	ts->input_dev = input_allocate_device();
 	if (ts->input_dev == NULL) {
 		dev_err(&ts->client->dev,
@@ -1274,7 +1238,7 @@
 #endif
 
 #if GTP_CHANGE_X2Y
-	GTP_SWAP(ts->abs_x_max, ts->abs_y_max);
+	swap(ts->abs_x_max, ts->abs_y_max);
 #endif
 
 	input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X,
@@ -1556,6 +1520,8 @@
 	struct property *prop;
 	u32 temp_val, num_buttons;
 	u32 button_map[MAX_BUTTONS];
+	char prop_name[PROP_NAME_SIZE];
+	int i, read_cfg_num;
 
 	rc = goodix_ts_get_dt_coords(dev, "goodix,panel-coords", pdata);
 	if (rc && (rc != -EINVAL))
@@ -1581,10 +1547,9 @@
 	if (pdata->irq_gpio < 0)
 		return pdata->irq_gpio;
 
-	rc = of_property_read_u32(np, "goodix,family-id", &temp_val);
-	if (!rc)
-		pdata->family_id = temp_val;
-	else
+	rc = of_property_read_string(np, "goodix,product-id",
+						&pdata->product_id);
+	if (rc < 0 || strlen(pdata->product_id) > GTP_PRODUCT_ID_MAXSIZE)
 		return rc;
 
 	prop = of_find_property(np, "goodix,button-map", NULL);
@@ -1602,26 +1567,32 @@
 		}
 	}
 
-	prop = of_find_property(np, "goodix,cfg-data", &pdata->gtp_cfg_len);
-	if (prop && prop->value) {
-		pdata->config_data = devm_kzalloc(dev,
-			GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH, GFP_KERNEL);
-		if (!pdata->config_data) {
-			dev_err(dev, "Not enough memory for panel config data\n");
+	read_cfg_num = 0;
+	for (i = 0; i < GOODIX_MAX_CFG_GROUP; i++) {
+		snprintf(prop_name, sizeof(prop_name), "goodix,cfg-data%d", i);
+		prop = of_find_property(np, prop_name,
+			&pdata->config_data_len[i]);
+		if (!prop || !prop->value) {
+			pdata->config_data_len[i] = 0;
+			pdata->config_data[i] = NULL;
+			continue;
+		}
+		pdata->config_data[i] = devm_kzalloc(dev,
+				GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH,
+				GFP_KERNEL);
+		if (!pdata->config_data[i]) {
+			dev_err(dev,
+				"Not enough memory for panel config data %d\n",
+				i);
 			return -ENOMEM;
 		}
-
-		pdata->config_data[0] = GTP_REG_CONFIG_DATA >> 8;
-		pdata->config_data[1] = GTP_REG_CONFIG_DATA & 0xff;
-		memset(&pdata->config_data[GTP_ADDR_LENGTH], 0,
-					GTP_CONFIG_MAX_LENGTH);
-		memcpy(&pdata->config_data[GTP_ADDR_LENGTH],
-				prop->value, pdata->gtp_cfg_len);
-	} else {
-		dev_err(dev,
-			"Unable to get configure data, default will be used.\n");
-		pdata->gtp_cfg_len = 0;
+		pdata->config_data[i][0] = GTP_REG_CONFIG_DATA >> 8;
+		pdata->config_data[i][1] = GTP_REG_CONFIG_DATA & 0xff;
+		memcpy(&pdata->config_data[i][GTP_ADDR_LENGTH],
+				prop->value, pdata->config_data_len[i]);
+		read_cfg_num++;
 	}
+	dev_dbg(dev, "%d config data read from device tree.\n", read_cfg_num);
 
 	return 0;
 }
@@ -1764,9 +1735,13 @@
 	else
 		dev_info(&client->dev, "GTP works in interrupt mode.\n");
 
-	ret = gtp_read_version(client, &version_info);
-	if (ret != 2) {
-		dev_err(&client->dev, "Read version failed.\n");
+	ret = gtp_read_fw_version(client, &version_info);
+	if (ret != 0)
+		dev_err(&client->dev, "GTP firmware version read failed.\n");
+
+	ret = gtp_check_product_id(client);
+	if (ret != 0) {
+		dev_err(&client->dev, "GTP Product id doesn't match.\n");
 		goto exit_free_irq;
 	}
 	if (ts->use_irq)
@@ -1831,7 +1806,6 @@
 {
 	struct goodix_ts_data *ts = i2c_get_clientdata(client);
 
-	GTP_DEBUG_FUNC();
 #if defined(CONFIG_FB)
 	if (fb_unregister_client(&ts->fb_notif))
 		dev_err(&client->dev,
@@ -1894,8 +1868,6 @@
 {
 	int ret = -1, i;
 
-	GTP_DEBUG_FUNC();
-
 #if GTP_ESD_PROTECT
 	ts->gtp_is_suspend = 1;
 	gtp_esd_switch(ts->client, SWITCH_OFF);
@@ -1936,8 +1908,6 @@
 {
 	int ret = -1;
 
-	GTP_DEBUG_FUNC();
-
 	ret = gtp_wakeup_sleep(ts);
 
 #if GTP_SLIDE_WAKEUP
@@ -2066,9 +2036,6 @@
 	int ret;
 	int retries = 0;
 
-	GTP_DEBUG("Init external watchdog...");
-	GTP_DEBUG_FUNC();
-
 	msg.flags = !I2C_M_RD;
 	msg.addr  = client->addr;
 	msg.len   = 4;
@@ -2101,8 +2068,6 @@
 	struct goodix_ts_data *ts = NULL;
 	u8 test[4] = {0x80, 0x40};
 
-	GTP_DEBUG_FUNC();
-
 	ts = i2c_get_clientdata(i2c_connect_client);
 
 	if (ts->gtp_is_suspend) {
@@ -2118,7 +2083,6 @@
 	for (i = 0; i < 3; i++) {
 		ret = gtp_i2c_read(ts->client, test, 4);
 
-		GTP_DEBUG("0x8040 = 0x%02X, 0x8041 = 0x%02X", test[2], test[3]);
 		if ((ret < 0)) {
 			/* IC works abnormally..*/
 			continue;
@@ -2190,7 +2154,6 @@
 {
 	int ret;
 
-	GTP_DEBUG_FUNC();
 #if GTP_ESD_PROTECT
 	INIT_DELAYED_WORK(&gtp_esd_check_work, gtp_esd_check_func);
 	gtp_esd_check_workqueue = create_workqueue("gtp_esd_check");
@@ -2209,7 +2172,6 @@
 ********************************************************/
 static void __exit goodix_ts_exit(void)
 {
-	GTP_DEBUG_FUNC();
 	i2c_del_driver(&goodix_ts_driver);
 }
 
diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.h b/drivers/input/touchscreen/gt9xx/gt9xx.h
index c9b81e7..1fdbfa3 100644
--- a/drivers/input/touchscreen/gt9xx/gt9xx.h
+++ b/drivers/input/touchscreen/gt9xx/gt9xx.h
@@ -45,12 +45,13 @@
 #define GOODIX_SUSPEND_LEVEL 1
 #endif
 
+#define GOODIX_MAX_CFG_GROUP	6
 struct goodix_ts_platform_data {
 	int irq_gpio;
 	u32 irq_gpio_flags;
 	int reset_gpio;
 	u32 reset_gpio_flags;
-	u32 family_id;
+	const char *product_id;
 	u32 x_max;
 	u32 y_max;
 	u32 x_min;
@@ -61,8 +62,8 @@
 	u32 panel_maxy;
 	bool no_force_update;
 	bool i2c_pull_up;
-	int gtp_cfg_len;
-	u8 *config_data;
+	size_t config_data_len[GOODIX_MAX_CFG_GROUP];
+	u8 *config_data[GOODIX_MAX_CFG_GROUP];
 };
 struct goodix_ts_data {
 	spinlock_t irq_lock;
@@ -122,7 +123,7 @@
 /* double-click wakeup, function together with GTP_SLIDE_WAKEUP */
 #define GTP_DBL_CLK_WAKEUP		0
 
-#define GTP_DEBUG_ON			1
+#define GTP_DEBUG_ON			0
 #define GTP_DEBUG_ARRAY_ON		0
 #define GTP_DEBUG_FUNC_ON		0
 
@@ -137,54 +138,6 @@
  *	VDDIO		NC/300K		4
  *	NC			NC/300K		5
 */
-/* Define your own default or for Sensor_ID == 0 config here */
-/* The predefined one is just a sample config,
- * which is not suitable for your tp in most cases. */
-#define CTP_CFG_GROUP1 {\
-	0x41, 0x1C, 0x02, 0xC0, 0x03, 0x0A, 0x05, 0x01, 0x01, 0x0F,\
-	0x23, 0x0F, 0x5F, 0x41, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00,\
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0x00, 0x0A,\
-	0x28, 0x00, 0xB8, 0x0B, 0x00, 0x00, 0x00, 0x9A, 0x03, 0x25,\
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x64, 0x32, 0x00, 0x00,\
-	0x00, 0x32, 0x8C, 0x94, 0x05, 0x01, 0x05, 0x00, 0x00, 0x96,\
-	0x0C, 0x22, 0xD8, 0x0E, 0x23, 0x56, 0x11, 0x25, 0xFF, 0x13,\
-	0x28, 0xA7, 0x15, 0x2E, 0x00, 0x00, 0x10, 0x30, 0x48, 0x00,\
-	0x56, 0x4A, 0x3A, 0xFF, 0xFF, 0x16, 0x00, 0x00, 0x00, 0x00,\
-	0x00, 0x01, 0x1B, 0x14, 0x0D, 0x19, 0x00, 0x00, 0x01, 0x00,\
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-	0x00, 0x00, 0x1A, 0x18, 0x16, 0x14, 0x12, 0x10, 0x0E, 0x0C,\
-	0x0A, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\
-	0xFF, 0xFF, 0x1D, 0x1E, 0x1F, 0x20, 0x22, 0x24, 0x28, 0x29,\
-	0x0C, 0x0A, 0x08, 0x00, 0x02, 0x04, 0x05, 0x06, 0x0E, 0xFF,\
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\
-	0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0x01\
-	}
-
-/* Define your config for Sensor_ID == 1 here, if needed */
-#define CTP_CFG_GROUP2 {\
-	}
-
-/* Define your config for Sensor_ID == 2 here, if needed */
-#define CTP_CFG_GROUP3 {\
-	}
-
-/* Define your config for Sensor_ID == 3 here, if needed */
-#define CTP_CFG_GROUP4 {\
-	}
-
-/* Define your config for Sensor_ID == 4 here, if needed */
-#define CTP_CFG_GROUP5 {\
-	}
-
-/* Define your config for Sensor_ID == 5 here, if needed */
-#define CTP_CFG_GROUP6 {\
-	}
 
 #define GTP_IRQ_TAB		{\
 				IRQ_TYPE_EDGE_RISING,\
@@ -206,30 +159,34 @@
 #define GTP_INT_TRIGGER		GTP_IRQ_TAB_FALLING
 #endif
 
-#define GTP_MAX_TOUCH         5
-#define GTP_ESD_CHECK_CIRCLE  2000      /* jiffy: ms */
+#define GTP_PRODUCT_ID_MAXSIZE	5
+#define GTP_PRODUCT_ID_BUFFER_MAXSIZE	6
+#define GTP_FW_VERSION_BUFFER_MAXSIZE	4
+#define GTP_MAX_TOUCH		5
+#define GTP_ESD_CHECK_CIRCLE	2000      /* jiffy: ms */
 
 /***************************PART3:OTHER define*********************************/
-#define GTP_DRIVER_VERSION		"V1.8<2013/06/08>"
-#define GTP_I2C_NAME			"Goodix-TS"
-#define GTP_POLL_TIME			10     /* jiffy: ms*/
-#define GTP_ADDR_LENGTH			2
+#define GTP_DRIVER_VERSION	"V1.8.1<2013/09/01>"
+#define GTP_I2C_NAME		"Goodix-TS"
+#define GTP_POLL_TIME		10     /* jiffy: ms*/
+#define GTP_ADDR_LENGTH		2
 #define GTP_CONFIG_MIN_LENGTH	186
 #define GTP_CONFIG_MAX_LENGTH	240
-#define FAIL					0
-#define SUCCESS					1
-#define SWITCH_OFF				0
-#define SWITCH_ON				1
+#define FAIL			0
+#define SUCCESS			1
+#define SWITCH_OFF		0
+#define SWITCH_ON		1
 
 /* Registers define */
-#define GTP_READ_COOR_ADDR		0x814E
-#define GTP_REG_SLEEP			0x8040
-#define GTP_REG_SENSOR_ID		0x814A
-#define GTP_REG_CONFIG_DATA		0x8047
-#define GTP_REG_VERSION			0x8140
+#define GTP_READ_COOR_ADDR	0x814E
+#define GTP_REG_SLEEP		0x8040
+#define GTP_REG_SENSOR_ID	0x814A
+#define GTP_REG_CONFIG_DATA	0x8047
+#define GTP_REG_FW_VERSION	0x8144
+#define GTP_REG_PRODUCT_ID	0x8140
 
-#define RESOLUTION_LOC			3
-#define TRIGGER_LOC				8
+#define RESOLUTION_LOC		3
+#define TRIGGER_LOC		8
 
 #define CFG_GROUP_LEN(p_cfg_grp) (sizeof(p_cfg_grp) / sizeof(p_cfg_grp[0]))
 /* Log define */
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 6324dff..8e70129 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -45,10 +45,22 @@
 
 	  If unsure, say N here.
 
+# MSM IOMMU sync lock support
+config MSM_IOMMU_SYNC
+	bool "MSM IOMMU Sync Lock Support"
+	depends on (ARCH_MSM8X60 || ARCH_MSM8960 || ARCH_APQ8064 || ARCH_MSM8930 || ARCH_MSM8610) && MSM_IOMMU_V0
+	help
+	  Say Y here if you want the IOMMU to grab a remote spinlock to ensure
+	  synchronization between IOMMU accesses by CPU and other exectution
+	  environments in the SoC.
+
+	  If unsure, say N here.
+
 # MSM IOMMU CPU-GPU sync programming support
 config MSM_IOMMU_GPU_SYNC
 	bool "MSM IOMMU CPU-GPU Sync Support"
-	depends on (ARCH_MSM8X60 || ARCH_MSM8960 || ARCH_APQ8064 || ARCH_MSM8930) && MSM_IOMMU_V0 && MSM_REMOTE_SPINLOCK_SFPB
+	depends on (ARCH_MSM8X60 || ARCH_MSM8960 || ARCH_APQ8064 || ARCH_MSM8930) && MSM_IOMMU_V0
+	select  MSM_IOMMU_SYNC
 	help
 	  Say Y here if you want to synchronize access to IOMMU configuration
 	  port between CPU and GPU. CPU will grab a remote spinlock before
diff --git a/drivers/iommu/msm_iommu-v0.c b/drivers/iommu/msm_iommu-v0.c
index 49bfdb8..99d071b 100644
--- a/drivers/iommu/msm_iommu-v0.c
+++ b/drivers/iommu/msm_iommu-v0.c
@@ -83,7 +83,7 @@
 
 static struct msm_iommu_remote_lock msm_iommu_remote_lock;
 
-#ifdef CONFIG_MSM_IOMMU_GPU_SYNC
+#ifdef CONFIG_MSM_IOMMU_SYNC
 static void _msm_iommu_remote_spin_lock_init(void)
 {
 	msm_iommu_remote_lock.lock = smem_alloc(SMEM_SPINLOCK_ARRAY, 32);
@@ -91,8 +91,11 @@
 			sizeof(*msm_iommu_remote_lock.lock));
 }
 
-void msm_iommu_remote_p0_spin_lock(void)
+void msm_iommu_remote_p0_spin_lock(unsigned int need_lock)
 {
+	if (!need_lock)
+		return;
+
 	msm_iommu_remote_lock.lock->flag[PROC_APPS] = 1;
 	msm_iommu_remote_lock.lock->turn = 1;
 
@@ -103,8 +106,11 @@
 		cpu_relax();
 }
 
-void msm_iommu_remote_p0_spin_unlock(void)
+void msm_iommu_remote_p0_spin_unlock(unsigned int need_lock)
 {
+	if (!need_lock)
+		return;
+
 	smp_mb();
 
 	msm_iommu_remote_lock.lock->flag[PROC_APPS] = 0;
@@ -200,14 +206,16 @@
 	return msm_iommu_lock_initialize();
 }
 
-static void _iommu_lock_acquire(void)
+static void _iommu_lock_acquire(unsigned int need_extra_lock)
 {
-	msm_iommu_lock();
+	msm_iommu_mutex_lock();
+	msm_iommu_remote_spin_lock(need_extra_lock);
 }
 
-static void _iommu_lock_release(void)
+static void _iommu_lock_release(unsigned int need_extra_lock)
 {
-	msm_iommu_unlock();
+	msm_iommu_remote_spin_unlock(need_extra_lock);
+	msm_iommu_mutex_unlock();
 }
 
 struct iommu_access_ops iommu_access_ops_v0 = {
@@ -241,7 +249,7 @@
 		if (ret)
 			goto fail;
 
-		msm_iommu_remote_spin_lock();
+		msm_iommu_remote_spin_lock(iommu_drvdata->needs_rem_spinlock);
 
 		asid = GET_CONTEXTIDR_ASID(iommu_drvdata->base,
 					   ctx_drvdata->num);
@@ -250,7 +258,7 @@
 			   asid | (va & TLBIVA_VA));
 		mb();
 
-		msm_iommu_remote_spin_unlock();
+		msm_iommu_remote_spin_unlock(iommu_drvdata->needs_rem_spinlock);
 
 		__disable_clocks(iommu_drvdata);
 	}
@@ -278,7 +286,7 @@
 		if (ret)
 			goto fail;
 
-		msm_iommu_remote_spin_lock();
+		msm_iommu_remote_spin_lock(iommu_drvdata->needs_rem_spinlock);
 
 		asid = GET_CONTEXTIDR_ASID(iommu_drvdata->base,
 					   ctx_drvdata->num);
@@ -286,7 +294,7 @@
 		SET_TLBIASID(iommu_drvdata->base, ctx_drvdata->num, asid);
 		mb();
 
-		msm_iommu_remote_spin_unlock();
+		msm_iommu_remote_spin_unlock(iommu_drvdata->needs_rem_spinlock);
 
 		__disable_clocks(iommu_drvdata);
 	}
@@ -318,13 +326,16 @@
 	mb();
 }
 
-static void __program_context(void __iomem *base, void __iomem *glb_base,
+static void __program_context(struct msm_iommu_drvdata *iommu_drvdata,
 			      int ctx, int ncb, phys_addr_t pgtable,
 			      int redirect, int ttbr_split)
 {
+	void __iomem *base = iommu_drvdata->base;
+	void __iomem *glb_base = iommu_drvdata->glb_base;
 	unsigned int prrr, nmrr;
 	int i, j, found;
-	msm_iommu_remote_spin_lock();
+
+	msm_iommu_remote_spin_lock(iommu_drvdata->needs_rem_spinlock);
 
 	__reset_context(base, glb_base, ctx);
 
@@ -416,7 +427,7 @@
 	SET_M(base, ctx, 1);
 	mb();
 
-	msm_iommu_remote_spin_unlock();
+	msm_iommu_remote_spin_unlock(iommu_drvdata->needs_rem_spinlock);
 }
 
 static int msm_iommu_domain_init(struct iommu_domain *domain, int flags)
@@ -526,7 +537,7 @@
 	if (ret)
 		goto unlock;
 
-	__program_context(iommu_drvdata->base, iommu_drvdata->glb_base,
+	__program_context(iommu_drvdata,
 			  ctx_drvdata->num, iommu_drvdata->ncb,
 			  __pa(priv->pt.fl_table), priv->pt.redirect,
 			  iommu_drvdata->ttbr_split);
@@ -577,7 +588,7 @@
 	if (ret)
 		goto unlock;
 
-	msm_iommu_remote_spin_lock();
+	msm_iommu_remote_spin_lock(iommu_drvdata->needs_rem_spinlock);
 
 	SET_TLBIASID(iommu_drvdata->base, ctx_drvdata->num,
 		    GET_CONTEXTIDR_ASID(iommu_drvdata->base, ctx_drvdata->num));
@@ -585,7 +596,7 @@
 	__reset_context(iommu_drvdata->base, iommu_drvdata->glb_base,
 			ctx_drvdata->num);
 
-	msm_iommu_remote_spin_unlock();
+	msm_iommu_remote_spin_unlock(iommu_drvdata->needs_rem_spinlock);
 
 	__disable_clocks(iommu_drvdata);
 
@@ -1246,7 +1257,7 @@
 	if (ret)
 		goto fail;
 
-	msm_iommu_remote_spin_lock();
+	msm_iommu_remote_spin_lock(iommu_drvdata->needs_rem_spinlock);
 
 	SET_V2PPR(base, ctx, va & V2Pxx_VA);
 
@@ -1262,7 +1273,7 @@
 	if (GET_FAULT(base, ctx))
 		ret = 0;
 
-	msm_iommu_remote_spin_unlock();
+	msm_iommu_remote_spin_unlock(iommu_drvdata->needs_rem_spinlock);
 
 	__disable_clocks(iommu_drvdata);
 fail:
@@ -1324,7 +1335,7 @@
 	if (ret)
 		goto fail;
 
-	msm_iommu_remote_spin_lock();
+	msm_iommu_remote_spin_lock(drvdata->needs_rem_spinlock);
 
 	fsr = GET_FSR(base, num);
 
@@ -1357,7 +1368,7 @@
 	} else
 		ret = IRQ_NONE;
 
-	msm_iommu_remote_spin_unlock();
+	msm_iommu_remote_spin_unlock(drvdata->needs_rem_spinlock);
 
 	__disable_clocks(drvdata);
 fail:
diff --git a/drivers/iommu/msm_iommu-v1.c b/drivers/iommu/msm_iommu-v1.c
index b9c4cae..c81aa0ac 100644
--- a/drivers/iommu/msm_iommu-v1.c
+++ b/drivers/iommu/msm_iommu-v1.c
@@ -123,12 +123,12 @@
 	clk_disable_unprepare(drvdata->pclk);
 }
 
-static void _iommu_lock_acquire(void)
+static void _iommu_lock_acquire(unsigned int need_extra_lock)
 {
 	mutex_lock(&msm_iommu_lock);
 }
 
-static void _iommu_lock_release(void)
+static void _iommu_lock_release(unsigned int need_extra_lock)
 {
 	mutex_unlock(&msm_iommu_lock);
 }
diff --git a/drivers/iommu/msm_iommu_dev-v0.c b/drivers/iommu/msm_iommu_dev-v0.c
index 2d0fba2..9382e52 100644
--- a/drivers/iommu/msm_iommu_dev-v0.c
+++ b/drivers/iommu/msm_iommu_dev-v0.c
@@ -216,6 +216,12 @@
 	drvdata->sec_id = -1;
 	drvdata->ttbr_split = 0;
 
+	drvdata->needs_rem_spinlock = of_property_read_bool(pdev->dev.of_node,
+					"qcom,msm-enable-remote-spinlock");
+
+	if (drvdata->needs_rem_spinlock)
+		pr_info("%s enabled remote spinlock\n", drvdata->name);
+
 	ret = of_platform_populate(pdev->dev.of_node,
 				   msm_iommu_v0_ctx_match_table,
 				   NULL, &pdev->dev);
diff --git a/drivers/iommu/msm_iommu_perfmon-v0.c b/drivers/iommu/msm_iommu_perfmon-v0.c
index 1073623..b08a9ec 100644
--- a/drivers/iommu/msm_iommu_perfmon-v0.c
+++ b/drivers/iommu/msm_iommu_perfmon-v0.c
@@ -176,9 +176,9 @@
 		goto out;
 	}
 
-	iommu->ops->iommu_lock_acquire();
+	iommu->ops->iommu_lock_acquire(1);
 	iommu_pm_check_for_overflow(pmon);
-	iommu->ops->iommu_lock_release();
+	iommu->ops->iommu_lock_release(1);
 
 	mutex_unlock(&pmon->lock);
 
diff --git a/drivers/iommu/msm_iommu_perfmon-v1.c b/drivers/iommu/msm_iommu_perfmon-v1.c
index 7d6dd34..2b55184 100644
--- a/drivers/iommu/msm_iommu_perfmon-v1.c
+++ b/drivers/iommu/msm_iommu_perfmon-v1.c
@@ -151,9 +151,9 @@
 		goto out;
 	}
 
-	iommu->ops->iommu_lock_acquire();
+	iommu->ops->iommu_lock_acquire(0);
 	iommu_pm_check_for_overflow(pmon);
-	iommu->ops->iommu_lock_release();
+	iommu->ops->iommu_lock_release(0);
 
 	mutex_unlock(&pmon->lock);
 
diff --git a/drivers/iommu/msm_iommu_perfmon.c b/drivers/iommu/msm_iommu_perfmon.c
index 958c6ca..503d4ab 100644
--- a/drivers/iommu/msm_iommu_perfmon.c
+++ b/drivers/iommu/msm_iommu_perfmon.c
@@ -188,11 +188,11 @@
 
 	if (event_class == MSM_IOMMU_PMU_NO_EVENT_CLASS) {
 		if (iommu->hw_ops->is_hw_access_OK(pmon)) {
-			iommu->ops->iommu_lock_acquire();
+			iommu->ops->iommu_lock_acquire(1);
 			iommu->hw_ops->counter_disable(iommu, counter);
 			iommu->hw_ops->ovfl_int_disable(iommu, counter);
 			iommu->hw_ops->set_event_class(pmon, count_no, 0);
-			iommu->ops->iommu_lock_release();
+			iommu->ops->iommu_lock_release(1);
 		}
 		counter->overflow_count = 0;
 		counter->value = 0;
@@ -200,12 +200,12 @@
 		counter->overflow_count = 0;
 		counter->value = 0;
 		if (iommu->hw_ops->is_hw_access_OK(pmon)) {
-			iommu->ops->iommu_lock_acquire();
+			iommu->ops->iommu_lock_acquire(1);
 			iommu->hw_ops->set_event_class(pmon, count_no,
 					event_class);
 			iommu->hw_ops->ovfl_int_enable(iommu, counter);
 			iommu->hw_ops->counter_enable(iommu, counter);
-			iommu->ops->iommu_lock_release();
+			iommu->ops->iommu_lock_release(1);
 		}
 	}
 }
@@ -261,9 +261,9 @@
 	iommu->ops->iommu_clk_on(iommu_drvdata);
 
 	/* Reset counters in HW */
-	iommu->ops->iommu_lock_acquire();
+	iommu->ops->iommu_lock_acquire(1);
 	iommu->hw_ops->reset_counters(&pmon->iommu);
-	iommu->ops->iommu_lock_release();
+	iommu->ops->iommu_lock_release(1);
 
 	/* Reset SW counters */
 	iommu_pm_reset_counts(pmon);
@@ -272,7 +272,7 @@
 
 	iommu_pm_set_all_counters(pmon);
 
-	iommu->ops->iommu_lock_acquire();
+	iommu->ops->iommu_lock_acquire(1);
 
 	/* enable all counter group */
 	for (i = 0; i < pmon->num_groups; ++i)
@@ -280,7 +280,7 @@
 
 	/* enable global counters */
 	iommu->hw_ops->enable_pm(iommu);
-	iommu->ops->iommu_lock_release();
+	iommu->ops->iommu_lock_release(1);
 
 	pr_info("%s: TLB performance monitoring turned ON\n",
 		pmon->iommu.iommu_name);
@@ -295,7 +295,7 @@
 
 	pmon->enabled = 0;
 
-	iommu->ops->iommu_lock_acquire();
+	iommu->ops->iommu_lock_acquire(1);
 
 	/* disable global counters */
 	iommu->hw_ops->disable_pm(iommu);
@@ -310,7 +310,7 @@
 	/* Update cached copy of counters before turning off power */
 	iommu_pm_read_all_counters(pmon);
 
-	iommu->ops->iommu_lock_release();
+	iommu->ops->iommu_lock_release(1);
 	iommu->ops->iommu_clk_off(iommu_drvdata);
 	iommu->ops->iommu_bus_vote(iommu_drvdata, 0);
 	iommu->ops->iommu_power_off(iommu_drvdata);
@@ -341,9 +341,9 @@
 	mutex_lock(&pmon->lock);
 
 	if (iommu->hw_ops->is_hw_access_OK(pmon)) {
-		iommu->ops->iommu_lock_acquire();
+		iommu->ops->iommu_lock_acquire(1);
 		counter->value = iommu->hw_ops->read_counter(counter);
-		iommu->ops->iommu_lock_release();
+		iommu->ops->iommu_lock_release(1);
 	}
 	full_count = (unsigned long long) counter->value +
 		     ((unsigned long long)counter->overflow_count *
@@ -448,9 +448,9 @@
 		rv = kstrtoul(buf, 10, &cmd);
 		if (!rv && (cmd == 1)) {
 			if (iommu->hw_ops->is_hw_access_OK(pmon)) {
-				iommu->ops->iommu_lock_acquire();
+				iommu->ops->iommu_lock_acquire(1);
 				iommu->hw_ops->reset_counters(&pmon->iommu);
-				iommu->ops->iommu_lock_release();
+				iommu->ops->iommu_lock_release(1);
 			}
 			iommu_pm_reset_counts(pmon);
 			pr_info("TLB performance counters reset\n");
diff --git a/drivers/iommu/msm_iommu_sec.c b/drivers/iommu/msm_iommu_sec.c
index 474efdf..5a1806e 100644
--- a/drivers/iommu/msm_iommu_sec.c
+++ b/drivers/iommu/msm_iommu_sec.c
@@ -194,7 +194,7 @@
 	struct msm_scm_fault_regs_dump *regs;
 	int tmp, ret = IRQ_HANDLED;
 
-	iommu_access_ops->iommu_lock_acquire();
+	iommu_access_ops->iommu_lock_acquire(0);
 
 	BUG_ON(!pdev);
 
@@ -266,7 +266,7 @@
 free_regs:
 	kfree(regs);
 lock_release:
-	iommu_access_ops->iommu_lock_release();
+	iommu_access_ops->iommu_lock_release(0);
 	return ret;
 }
 
@@ -510,12 +510,12 @@
 {
 	struct msm_iommu_priv *priv;
 
-	iommu_access_ops->iommu_lock_acquire();
+	iommu_access_ops->iommu_lock_acquire(0);
 	priv = domain->priv;
 	domain->priv = NULL;
 
 	kfree(priv);
-	iommu_access_ops->iommu_lock_release();
+	iommu_access_ops->iommu_lock_release(0);
 }
 
 static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
@@ -526,7 +526,7 @@
 	struct msm_iommu_ctx_drvdata *tmp_drvdata;
 	int ret = 0;
 
-	iommu_access_ops->iommu_lock_acquire();
+	iommu_access_ops->iommu_lock_acquire(0);
 
 	priv = domain->priv;
 	if (!priv || !dev) {
@@ -581,12 +581,12 @@
 	ctx_drvdata->attached_domain = domain;
 	++iommu_drvdata->ctx_attach_count;
 
-	iommu_access_ops->iommu_lock_release();
+	iommu_access_ops->iommu_lock_release(0);
 
 	msm_iommu_attached(dev->parent);
 	return ret;
 fail:
-	iommu_access_ops->iommu_lock_release();
+	iommu_access_ops->iommu_lock_release(0);
 	return ret;
 }
 
@@ -598,7 +598,7 @@
 
 	msm_iommu_detached(dev->parent);
 
-	iommu_access_ops->iommu_lock_acquire();
+	iommu_access_ops->iommu_lock_acquire(0);
 	if (!dev)
 		goto fail;
 
@@ -614,7 +614,7 @@
 	BUG_ON(iommu_drvdata->ctx_attach_count == 0);
 	--iommu_drvdata->ctx_attach_count;
 fail:
-	iommu_access_ops->iommu_lock_release();
+	iommu_access_ops->iommu_lock_release(0);
 }
 
 static int get_drvdata(struct iommu_domain *domain,
@@ -644,7 +644,7 @@
 	struct msm_iommu_ctx_drvdata *ctx_drvdata;
 	int ret = 0;
 
-	iommu_access_ops->iommu_lock_acquire();
+	iommu_access_ops->iommu_lock_acquire(0);
 
 	ret = get_drvdata(domain, &iommu_drvdata, &ctx_drvdata);
 	if (ret)
@@ -655,7 +655,7 @@
 					va, pa, len);
 	iommu_access_ops->iommu_clk_off(iommu_drvdata);
 fail:
-	iommu_access_ops->iommu_lock_release();
+	iommu_access_ops->iommu_lock_release(0);
 	return ret;
 }
 
@@ -666,7 +666,7 @@
 	struct msm_iommu_ctx_drvdata *ctx_drvdata;
 	int ret = -ENODEV;
 
-	iommu_access_ops->iommu_lock_acquire();
+	iommu_access_ops->iommu_lock_acquire(0);
 
 	ret = get_drvdata(domain, &iommu_drvdata, &ctx_drvdata);
 	if (ret)
@@ -677,7 +677,7 @@
 					va, len);
 	iommu_access_ops->iommu_clk_off(iommu_drvdata);
 fail:
-	iommu_access_ops->iommu_lock_release();
+	iommu_access_ops->iommu_lock_release(0);
 
 	/* the IOMMU API requires us to return how many bytes were unmapped */
 	len = ret ? 0 : len;
@@ -692,7 +692,7 @@
 	struct msm_iommu_drvdata *iommu_drvdata;
 	struct msm_iommu_ctx_drvdata *ctx_drvdata;
 
-	iommu_access_ops->iommu_lock_acquire();
+	iommu_access_ops->iommu_lock_acquire(0);
 
 	ret = get_drvdata(domain, &iommu_drvdata, &ctx_drvdata);
 	if (ret)
@@ -702,7 +702,7 @@
 						va, sg, len);
 	iommu_access_ops->iommu_clk_off(iommu_drvdata);
 fail:
-	iommu_access_ops->iommu_lock_release();
+	iommu_access_ops->iommu_lock_release(0);
 	return ret;
 }
 
@@ -714,7 +714,7 @@
 	struct msm_iommu_ctx_drvdata *ctx_drvdata;
 	int ret;
 
-	iommu_access_ops->iommu_lock_acquire();
+	iommu_access_ops->iommu_lock_acquire(0);
 
 	ret = get_drvdata(domain, &iommu_drvdata, &ctx_drvdata);
 	if (ret)
@@ -725,7 +725,7 @@
 	iommu_access_ops->iommu_clk_off(iommu_drvdata);
 
 fail:
-	iommu_access_ops->iommu_lock_release();
+	iommu_access_ops->iommu_lock_release(0);
 	return 0;
 }
 
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 4aa423f..87bffde 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
@@ -19,6 +19,7 @@
 #include <linux/io.h>
 #include <linux/list.h>
 #include <linux/delay.h>
+#include <linux/avtimer.h>
 #include <media/v4l2-subdev.h>
 #include <media/msmb_isp.h>
 #include <mach/msm_bus.h>
@@ -35,6 +36,10 @@
 #define MAX_INIT_FRAME_DROP 31
 #define ISP_Q2 (1 << 2)
 
+#define AVTIMER_MSW_PHY_ADDR 0xFE05300C
+#define AVTIMER_LSW_PHY_ADDR 0xFE053008
+#define AVTIMER_ITERATION_CTR 16
+
 #define VFE_PING_FLAG 0xFFFFFFFF
 #define VFE_PONG_FLAG 0x0
 
@@ -69,6 +74,8 @@
 struct msm_isp_timestamp {
 	/*Monotonic clock for v4l2 buffer*/
 	struct timeval buf_time;
+	/*Monotonic clock for VT */
+	struct timeval vt_time;
 	/*Wall clock for userspace event*/
 	struct timeval event_time;
 };
@@ -263,7 +270,7 @@
 	uint32_t stream_handle;
 	uint8_t buf_divert;
 	enum msm_vfe_axi_stream_type stream_type;
-
+	uint32_t vt_enable;
 	uint32_t frame_based;
 	uint32_t framedrop_period;
 	uint32_t framedrop_pattern;
@@ -436,6 +443,9 @@
 	int dump_reg;
 	int vfe_clk_idx;
 	uint32_t vfe_open_cnt;
+	uint8_t vt_enable;
+	void __iomem *p_avtimer_msw;
+	void __iomem *p_avtimer_lsw;
 };
 
 #endif
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 f547b0e..4f3094a 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
@@ -524,7 +524,16 @@
 	}
 
 	msm_isp_calculate_framedrop(&vfe_dev->axi_data, stream_cfg_cmd);
-
+	stream_info->vt_enable = stream_cfg_cmd->vt_enable;
+	if (stream_info->vt_enable) {
+		vfe_dev->vt_enable = stream_info->vt_enable;
+	#ifdef CONFIG_MSM_AVTIMER
+		avcs_core_open();
+		avcs_core_disable_power_collapse(1);
+	#endif
+		vfe_dev->p_avtimer_lsw = ioremap(AVTIMER_LSW_PHY_ADDR, 4);
+		vfe_dev->p_avtimer_msw = ioremap(AVTIMER_MSW_PHY_ADDR, 4);
+	}
 	if (stream_info->num_planes > 1) {
 		msm_isp_axi_reserve_comp_mask(
 			&vfe_dev->axi_data, stream_info);
@@ -783,15 +792,21 @@
 {
 	int rc;
 	struct msm_isp_event_data buf_event;
+	struct timeval *time_stamp;
 	uint32_t stream_idx = HANDLE_TO_IDX(stream_info->stream_handle);
 	uint32_t frame_id = vfe_dev->axi_data.
 		src_info[SRC_TO_INTF(stream_info->stream_src)].frame_id;
 
 	if (buf && ts) {
+		if (vfe_dev->vt_enable) {
+			time_stamp = &ts->vt_time;
+		} else {
+			time_stamp = &ts->buf_time;
+		}
 		if (stream_info->buf_divert) {
 			rc = vfe_dev->buf_mgr->ops->buf_divert(vfe_dev->buf_mgr,
 				buf->bufq_handle, buf->buf_idx,
-				&ts->buf_time, frame_id);
+				time_stamp, frame_id);
 			/* Buf divert return value represent whether the buf
 			 * can be diverted. A positive return value means
 			 * other ISP hardware is still processing the frame.
@@ -800,7 +815,7 @@
 				buf_event.input_intf =
 					SRC_TO_INTF(stream_info->stream_src);
 				buf_event.frame_id = frame_id;
-				buf_event.timestamp = ts->buf_time;
+				buf_event.timestamp = *time_stamp;
 				buf_event.u.buf_done.session_id =
 					stream_info->session_id;
 				buf_event.u.buf_done.stream_id =
@@ -817,7 +832,7 @@
 		} else {
 			vfe_dev->buf_mgr->ops->buf_done(vfe_dev->buf_mgr,
 				buf->bufq_handle, buf->buf_idx,
-				&ts->buf_time, frame_id,
+				time_stamp, frame_id,
 				stream_info->runtime_output_format);
 		}
 	}
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 b024569..5f36a4a 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
@@ -193,6 +193,32 @@
 	do_gettimeofday(&(time_stamp->event_time));
 }
 
+static inline void msm_isp_get_vt_tstamp(struct vfe_device *vfe_dev,
+	struct msm_isp_timestamp *time_stamp)
+{
+	uint32_t avtimer_msw_1st = 0, avtimer_lsw = 0;
+	uint32_t avtimer_msw_2nd = 0;
+	uint8_t iter = 0;
+	if (!vfe_dev->p_avtimer_msw || !vfe_dev->p_avtimer_lsw) {
+		pr_err("%s: ioremap failed\n", __func__);
+		return;
+	}
+	do {
+		avtimer_msw_1st = msm_camera_io_r(vfe_dev->p_avtimer_msw);
+		avtimer_lsw = msm_camera_io_r(vfe_dev->p_avtimer_lsw);
+		avtimer_msw_2nd = msm_camera_io_r(vfe_dev->p_avtimer_msw);
+	} while ((avtimer_msw_1st != avtimer_msw_2nd)
+		&& (iter++ < AVTIMER_ITERATION_CTR));
+	/*Just return if the MSW TimeStamps don't converge after
+	a few iterations Application needs to handle the zero TS values*/
+	if (iter >= AVTIMER_ITERATION_CTR) {
+		pr_err("%s: AVTimer MSW TS did not converge !!!\n", __func__);
+		return;
+	}
+	time_stamp->vt_time.tv_sec = avtimer_msw_1st;
+	time_stamp->vt_time.tv_usec = avtimer_lsw;
+}
+
 int msm_isp_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
 	struct v4l2_event_subscription *sub)
 {
@@ -885,6 +911,8 @@
 	queue_cmd->vfeInterruptStatus0 = irq_status0;
 	queue_cmd->vfeInterruptStatus1 = irq_status1;
 	msm_isp_get_timestamp(&queue_cmd->ts);
+	if (vfe_dev->vt_enable)
+		msm_isp_get_vt_tstamp(vfe_dev, &queue_cmd->ts);
 	queue_cmd->cmd_used = 1;
 	vfe_dev->taskletq_idx =
 		(vfe_dev->taskletq_idx + 1) % MSM_VFE_TASKLETQ_SIZE;
@@ -998,6 +1026,9 @@
 	vfe_dev->axi_data.hw_info = vfe_dev->hw_info->axi_hw_info;
 	vfe_dev->vfe_open_cnt++;
 	vfe_dev->taskletq_idx = 0;
+	vfe_dev->vt_enable = 0;
+	vfe_dev->p_avtimer_lsw = NULL;
+	vfe_dev->p_avtimer_msw = NULL;
 	mutex_unlock(&vfe_dev->core_mutex);
 	mutex_unlock(&vfe_dev->realtime_mutex);
 	return 0;
@@ -1024,6 +1055,14 @@
 	vfe_dev->buf_mgr->ops->buf_mgr_deinit(vfe_dev->buf_mgr);
 	vfe_dev->hw_info->vfe_ops.core_ops.release_hw(vfe_dev);
 	vfe_dev->vfe_open_cnt--;
+	if (vfe_dev->vt_enable) {
+		iounmap(vfe_dev->p_avtimer_lsw);
+		iounmap(vfe_dev->p_avtimer_msw);
+	#ifdef CONFIG_MSM_AVTIMER
+		avcs_core_disable_power_collapse(0);
+	#endif
+		vfe_dev->vt_enable = 0;
+	}
 	mutex_unlock(&vfe_dev->core_mutex);
 	mutex_unlock(&vfe_dev->realtime_mutex);
 	return 0;
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 c1f48f5..8b8d23b 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
@@ -27,6 +27,7 @@
 #include <linux/timer.h>
 #include <linux/kernel.h>
 #include <linux/workqueue.h>
+#include <mach/clk.h>
 #include <mach/iommu_domains.h>
 #include <mach/iommu.h>
 #include <mach/vreg.h>
@@ -48,6 +49,7 @@
 #define CONFIG_MSM_CPP_DBG 0
 
 #define CPP_CMD_TIMEOUT_MS 300
+#define MSM_MICRO_IFACE_CLK_IDX 7
 
 struct msm_cpp_timer_data_t {
 	struct cpp_device *cpp_dev;
@@ -646,6 +648,38 @@
 		}
 	}
 
+	cpp_dev->cpp_clk[MSM_MICRO_IFACE_CLK_IDX] =
+		clk_get(&cpp_dev->pdev->dev,
+		cpp_clk_info[MSM_MICRO_IFACE_CLK_IDX].clk_name);
+	if (IS_ERR(cpp_dev->cpp_clk[MSM_MICRO_IFACE_CLK_IDX])) {
+		pr_err("%s get failed\n",
+			cpp_clk_info[MSM_MICRO_IFACE_CLK_IDX].clk_name);
+		rc = PTR_ERR(cpp_dev->cpp_clk[MSM_MICRO_IFACE_CLK_IDX]);
+		goto remap_failed;
+	}
+
+	rc = clk_reset(cpp_dev->cpp_clk[MSM_MICRO_IFACE_CLK_IDX],
+		CLK_RESET_ASSERT);
+	if (rc) {
+		pr_err("%s:micro_iface_clk assert failed\n", __func__);
+		clk_put(cpp_dev->cpp_clk[MSM_MICRO_IFACE_CLK_IDX]);
+		goto remap_failed;
+	}
+
+	usleep_range(10000, 12000);
+
+	rc = clk_reset(cpp_dev->cpp_clk[MSM_MICRO_IFACE_CLK_IDX],
+		CLK_RESET_DEASSERT);
+	  if (rc) {
+		pr_err("%s:micro_iface_clk assert failed\n", __func__);
+		clk_put(cpp_dev->cpp_clk[MSM_MICRO_IFACE_CLK_IDX]);
+		goto remap_failed;
+	}
+
+	usleep_range(1000, 1200);
+
+	clk_put(cpp_dev->cpp_clk[MSM_MICRO_IFACE_CLK_IDX]);
+
 	rc = msm_cam_clk_enable(&cpp_dev->pdev->dev, cpp_clk_info,
 			cpp_dev->cpp_clk, ARRAY_SIZE(cpp_clk_info), 1);
 	if (rc < 0) {
diff --git a/drivers/media/platform/msm/camera_v2/sensor/Makefile b/drivers/media/platform/msm/camera_v2/sensor/Makefile
index e011793..280a9a0 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/Makefile
+++ b/drivers/media/platform/msm/camera_v2/sensor/Makefile
@@ -9,6 +9,7 @@
 obj-$(CONFIG_IMX135) += imx135.o
 obj-$(CONFIG_IMX134) += imx134.o
 obj-$(CONFIG_OV8825) += ov8825.o
+obj-$(CONFIG_OV8865) += ov8865.o
 obj-$(CONFIG_s5k4e1) += s5k4e1.o
 obj-$(CONFIG_OV12830) += ov12830.o
 obj-$(CONFIG_OV2720) += ov2720.o
@@ -18,4 +19,3 @@
 obj-$(CONFIG_MT9M114) += mt9m114.o
 obj-$(CONFIG_SP1628) += sp1628.o
 obj-$(CONFIG_GC0339) += gc0339.o
-obj-$(CONFIG_OV8865) += ov8865.o
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index 8cbce83..3f89d8b 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -180,7 +180,19 @@
 	cmd_done.device_id = device_id;
 	cmd_done.session_id = ((struct hal_session *) pkt->session_id)->
 		session_id;
-	callback(SESSION_ERROR, &cmd_done);
+	dprintk(VIDC_INFO, "Received : SESSION_ERROR with event id : %d\n",
+		pkt->event_data1);
+	switch (pkt->event_data1) {
+	case HFI_ERR_SESSION_INVALID_SCALE_FACTOR:
+	case HFI_ERR_SESSION_UNSUPPORT_BUFFERTYPE:
+	case HFI_ERR_SESSION_UNSUPPORTED_SETTING:
+		dprintk(VIDC_INFO, "Non Fatal : HFI_EVENT_SESSION_ERROR\n");
+		break;
+	default:
+		dprintk(VIDC_ERR, "HFI_EVENT_SESSION_ERROR\n");
+		callback(SESSION_ERROR, &cmd_done);
+		break;
+	}
 }
 static void hfi_process_event_notify(
 		msm_vidc_callback callback, u32 device_id,
@@ -204,7 +216,7 @@
 		hfi_process_sys_error(callback, device_id);
 		break;
 	case HFI_EVENT_SESSION_ERROR:
-		dprintk(VIDC_ERR, "HFI_EVENT_SESSION_ERROR");
+		dprintk(VIDC_INFO, "HFI_EVENT_SESSION_ERROR");
 		if (!validate_session_pkt(sessions, sess, session_lock))
 			hfi_process_session_error(callback, device_id, pkt);
 		break;
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index 5202835..7f2131d 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -836,7 +836,6 @@
 		return -EINVAL;
 	}
 	if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-		struct hal_frame_size frame_sz;
 
 		fmt = msm_comm_get_pixel_fmt_fourcc(vdec_formats,
 			ARRAY_SIZE(vdec_formats), f->fmt.pix_mp.pixelformat,
@@ -849,13 +848,6 @@
 			goto err_invalid_fmt;
 		}
 		inst->fmts[fmt->type] = fmt;
-		frame_sz.buffer_type = HAL_BUFFER_OUTPUT;
-		frame_sz.width = inst->prop.width;
-		frame_sz.height = inst->prop.height;
-		dprintk(VIDC_DBG, "width = %d, height = %d\n",
-				frame_sz.width, frame_sz.height);
-		ret = msm_comm_try_set_prop(inst,
-			HAL_PARAM_FRAME_SIZE, &frame_sz);
 		ret = ret || msm_comm_try_get_bufreqs(inst);
 		if (ret) {
 			for (i = 0; i < fmt->num_planes; ++i) {
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index 10a0eac..4258a10 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -495,7 +495,7 @@
 	inst->debugfs_root =
 		msm_vidc_debugfs_init_inst(inst, core->debugfs_root);
 
-	setup_event_queue(inst, &core->vdev[core_id].vdev);
+	setup_event_queue(inst, &core->vdev[session_type].vdev);
 
 	mutex_lock(&core->sync_lock);
 	list_add_tail(&inst->list, &core->instances);
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index b5c431e..050a98d 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -64,7 +64,12 @@
 
 #define HFI_ERR_SESSION_STREAM_CORRUPT		(HFI_COMMON_BASE + 0x100B)
 #define HFI_ERR_SESSION_ENC_OVERFLOW		(HFI_COMMON_BASE + 0x100C)
-#define  HFI_ERR_SESSION_UNSUPPORTED_STREAM	(HFI_COMMON_BASE + 0x100D)
+#define HFI_ERR_SESSION_UNSUPPORTED_STREAM	(HFI_COMMON_BASE + 0x100D)
+#define HFI_ERR_SESSION_CMDSIZE			(HFI_COMMON_BASE + 0x100E)
+#define HFI_ERR_SESSION_UNSUPPORT_CMD		(HFI_COMMON_BASE + 0x100F)
+#define HFI_ERR_SESSION_UNSUPPORT_BUFFERTYPE	(HFI_COMMON_BASE + 0x1010)
+#define HFI_ERR_SESSION_BUFFERCOUNT_TOOSMALL	(HFI_COMMON_BASE + 0x1011)
+#define HFI_ERR_SESSION_INVALID_SCALE_FACTOR	(HFI_COMMON_BASE + 0x1012)
 
 #define HFI_EVENT_SYS_ERROR				(HFI_COMMON_BASE + 0x1)
 #define HFI_EVENT_SESSION_ERROR			(HFI_COMMON_BASE + 0x2)
diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c
index 317c6a9..d8abc6d 100644
--- a/drivers/mfd/wcd9xxx-core.c
+++ b/drivers/mfd/wcd9xxx-core.c
@@ -1451,23 +1451,23 @@
 		dev_err(dev, "Looking up %s property in node %s failed",
 			"qcom,cdc-dmic-sample-rate",
 			dev->of_node->full_name);
-		dmic_sample_rate = TAIKO_DMIC_SAMPLE_RATE_UNDEFINED;
+		dmic_sample_rate = WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED;
 	}
-	if (pdata->mclk_rate == TAIKO_MCLK_CLK_9P6HZ) {
-		if ((dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_2P4MHZ) &&
-		    (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_3P2MHZ) &&
-		    (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_4P8MHZ) &&
-		    (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_UNDEFINED)) {
+	if (pdata->mclk_rate == WCD9XXX_MCLK_CLK_9P6HZ) {
+		if ((dmic_sample_rate != WCD9XXX_DMIC_SAMPLE_RATE_2P4MHZ) &&
+		    (dmic_sample_rate != WCD9XXX_DMIC_SAMPLE_RATE_3P2MHZ) &&
+		    (dmic_sample_rate != WCD9XXX_DMIC_SAMPLE_RATE_4P8MHZ) &&
+		    (dmic_sample_rate != WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED)) {
 			dev_err(dev, "Invalid dmic rate %d for mclk %d\n",
 				dmic_sample_rate, pdata->mclk_rate);
 			ret = -EINVAL;
 			goto err;
 		}
-	} else if (pdata->mclk_rate == TAIKO_MCLK_CLK_12P288MHZ) {
-		if ((dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_3P072MHZ) &&
-		    (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_4P096MHZ) &&
-		    (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_6P144MHZ) &&
-		    (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_UNDEFINED)) {
+	} else if (pdata->mclk_rate == WCD9XXX_MCLK_CLK_12P288MHZ) {
+		if ((dmic_sample_rate != WCD9XXX_DMIC_SAMPLE_RATE_3P072MHZ) &&
+		    (dmic_sample_rate != WCD9XXX_DMIC_SAMPLE_RATE_4P096MHZ) &&
+		    (dmic_sample_rate != WCD9XXX_DMIC_SAMPLE_RATE_6P144MHZ) &&
+		    (dmic_sample_rate != WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED)) {
 			dev_err(dev, "Invalid dmic rate %d for mclk %d\n",
 				dmic_sample_rate, pdata->mclk_rate);
 			ret = -EINVAL;
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 1452908..a30607c 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -314,7 +314,6 @@
 		return ret;
 	}
 	data->listener.id = 0;
-	data->type = QSEECOM_LISTENER_SERVICE;
 	if (!__qseecom_is_svc_unique(data, &rcvd_lstnr)) {
 		pr_err("Service is not unique and is already registered\n");
 		data->released = true;
@@ -432,9 +431,15 @@
 	uint32_t len;
 
 	/* Copy the relevant information needed for loading the image */
-	if (__copy_from_user(&req, (void __user *)argp, sizeof(req)))
+	if (copy_from_user(&req, (void __user *)argp, sizeof(req)))
 		return -EFAULT;
 
+	if ((req.ifd_data_fd <= 0) || (req.virt_sb_base == 0) ||
+					(req.sb_len == 0)) {
+		pr_err("Inavlid input(s)ion_fd(%d), sb_len(%d), vaddr(0x%x)\n",
+			req.ifd_data_fd, req.sb_len, req.virt_sb_base);
+		return -EFAULT;
+	}
 	/* Get the handle of the shared fd */
 	data->client.ihandle = ion_import_dma_buf(qseecom.ion_clnt,
 						req.ifd_data_fd);
@@ -605,7 +610,7 @@
 	struct qseecom_load_app_ireq load_req;
 
 	/* Copy the relevant information needed for loading the image */
-	if (__copy_from_user(&load_img_req,
+	if (copy_from_user(&load_img_req,
 				(void __user *)argp,
 				sizeof(struct qseecom_load_img_req))) {
 		pr_err("copy_from_user failed\n");
@@ -616,6 +621,7 @@
 	if (ret)
 		pr_warning("Unable to vote for SFPB clock");
 	req.qsee_cmd_id = QSEOS_APP_LOOKUP_COMMAND;
+	load_img_req.img_name[MAX_APP_NAME_SIZE-1] = '\0';
 	memcpy(req.app_name, load_img_req.img_name, MAX_APP_NAME_SIZE);
 
 	ret = __qseecom_check_app_exists(req);
@@ -876,7 +882,7 @@
 	struct qseecom_send_svc_cmd_req req;
 	/*struct qseecom_command_scm_resp resp;*/
 
-	if (__copy_from_user(&req,
+	if (copy_from_user(&req,
 				(void __user *)argp,
 				sizeof(req))) {
 		pr_err("copy_from_user failed\n");
@@ -888,8 +894,6 @@
 		return -EINVAL;
 	}
 
-	data->type = QSEECOM_SECURE_SERVICE;
-
 	switch (req.cmd_id) {
 	case QSEOS_RPMB_PROVISION_KEY_COMMAND:
 	case QSEOS_RPMB_ERASE_COMMAND:
@@ -901,6 +905,18 @@
 		pr_err("Unsupported cmd_id %d\n", req.cmd_id);
 		return -EINVAL;
 	}
+
+	ret = qsee_vote_for_clock(data, CLK_DFAB);
+	if (ret) {
+		pr_err("Failed to vote for DFAB clock%d\n", ret);
+		return ret;
+	}
+	ret = qsee_vote_for_clock(data, CLK_SFPB);
+	if (ret) {
+		pr_err("Failed to vote for SFPB clock%d\n", ret);
+		goto exit_reset_dfab_freq;
+	}
+
 	msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle,
 				data->client.sb_virt, data->client.sb_length,
 				ION_IOC_CLEAN_INV_CACHES);
@@ -912,7 +928,7 @@
 				ION_IOC_INV_CACHES);
 	if (ret) {
 		pr_err("qseecom_scm_call failed with err: %d\n", ret);
-		return ret;
+		goto exit_reset_sdfab_freq;
 	}
 
 	switch (resp.result) {
@@ -935,8 +951,11 @@
 		ret = -EINVAL;
 		break;
 	}
+exit_reset_sdfab_freq:
+	qsee_disable_clock_vote(data, CLK_SFPB);
+exit_reset_dfab_freq:
+	qsee_disable_clock_vote(data, CLK_DFAB);
 	return ret;
-
 }
 
 static int __qseecom_send_cmd(struct qseecom_dev_handle *data,
@@ -951,9 +970,22 @@
 		pr_err("cmd buffer or response buffer is null\n");
 		return -EINVAL;
 	}
+	if (((uint32_t)req->cmd_req_buf < data->client.user_virt_sb_base) ||
+		((uint32_t)req->cmd_req_buf >= (data->client.user_virt_sb_base +
+					data->client.sb_length))) {
+		pr_err("cmd buffer address not within shared bufffer\n");
+		return -EINVAL;
+	}
 
-	if (req->cmd_req_len <= 0 ||
-		req->resp_len <= 0 ||
+
+	if (((uint32_t)req->resp_buf < data->client.user_virt_sb_base)  ||
+		((uint32_t)req->resp_buf >= (data->client.user_virt_sb_base +
+					data->client.sb_length))){
+		pr_err("response buffer address not within shared bufffer\n");
+		return -EINVAL;
+	}
+
+	if ((req->cmd_req_len == 0) || (req->resp_len == 0) ||
 		req->cmd_req_len > data->client.sb_length ||
 		req->resp_len > data->client.sb_length) {
 		pr_err("cmd buffer length or "
@@ -1191,6 +1223,7 @@
 					void __user *argp)
 {
 	int ret = 0;
+	int i;
 	struct qseecom_send_modfd_cmd_req req;
 	struct qseecom_send_cmd_req send_cmd_req;
 
@@ -1204,6 +1237,14 @@
 	send_cmd_req.resp_buf = req.resp_buf;
 	send_cmd_req.resp_len = req.resp_len;
 
+	/* validate offsets */
+	for (i = 0; i < MAX_ION_FD; i++) {
+		if (req.ifd_data[i].cmd_buf_offset >= req.cmd_req_len) {
+			pr_err("Invalid offset %d = 0x%x\n",
+				i, req.ifd_data[i].cmd_buf_offset);
+			return -EINVAL;
+		}
+	}
 	ret = __qseecom_update_cmd_buf(&req, false, data, false);
 	if (ret)
 		return ret;
@@ -1794,11 +1835,20 @@
 						void __user *argp)
 {
 	struct qseecom_send_modfd_listener_resp resp;
+	int i;
 
 	if (copy_from_user(&resp, argp, sizeof(resp))) {
 		pr_err("copy_from_user failed");
 		return -EINVAL;
 	}
+	/* validate offsets */
+	for (i = 0; i < MAX_ION_FD; i++) {
+		if (resp.ifd_data[i].cmd_buf_offset >= resp.resp_len) {
+			pr_err("Invalid offset %d = 0x%x\n",
+				i, resp.ifd_data[i].cmd_buf_offset);
+			return -EINVAL;
+		}
+	}
 	__qseecom_update_cmd_buf(&resp, false, data, true);
 	qseecom.send_resp_flag = 1;
 	wake_up_interruptible(&qseecom.send_resp_wq);
@@ -2077,7 +2127,7 @@
 	struct qseecom_command_scm_resp resp;
 
 	/* Copy the relevant information needed for loading the image */
-	if (__copy_from_user(&load_img_req,
+	if (copy_from_user(&load_img_req,
 				(void __user *)argp,
 				sizeof(struct qseecom_load_img_req))) {
 		pr_err("copy_from_user failed\n");
@@ -2239,7 +2289,7 @@
 	unsigned long flags = 0;
 
 	/* Copy the relevant information needed for loading the image */
-	if (__copy_from_user(&query_req,
+	if (copy_from_user(&query_req,
 				(void __user *)argp,
 				sizeof(struct qseecom_qseos_app_load_query))) {
 		pr_err("copy_from_user failed\n");
@@ -2247,6 +2297,7 @@
 	}
 
 	req.qsee_cmd_id = QSEOS_APP_LOOKUP_COMMAND;
+	query_req.app_name[MAX_APP_NAME_SIZE-1] = '\0';
 	memcpy(req.app_name, query_req.app_name, MAX_APP_NAME_SIZE);
 
 	ret = __qseecom_check_app_exists(req);
@@ -2668,8 +2719,15 @@
 
 	switch (cmd) {
 	case QSEECOM_IOCTL_REGISTER_LISTENER_REQ: {
+		if (data->type != QSEECOM_GENERIC) {
+			pr_err("reg lstnr req: invalid handle (%d)\n",
+								data->type);
+			ret = -EINVAL;
+			break;
+		}
 		pr_debug("ioctl register_listener_req()\n");
 		atomic_inc(&data->ioctl_count);
+		data->type = QSEECOM_LISTENER_SERVICE;
 		ret = qseecom_register_listener(data, argp);
 		atomic_dec(&data->ioctl_count);
 		wake_up_all(&data->abort_wq);
@@ -2678,6 +2736,13 @@
 		break;
 	}
 	case QSEECOM_IOCTL_UNREGISTER_LISTENER_REQ: {
+		if ((data->listener.id == 0) ||
+			(data->type != QSEECOM_LISTENER_SERVICE)) {
+			pr_err("unreg lstnr req: invalid handle (%d) lid(%d)\n",
+						data->type, data->listener.id);
+			ret = -EINVAL;
+			break;
+		}
 		pr_debug("ioctl unregister_listener_req()\n");
 		atomic_inc(&data->ioctl_count);
 		ret = qseecom_unregister_listener(data);
@@ -2688,6 +2753,13 @@
 		break;
 	}
 	case QSEECOM_IOCTL_SEND_CMD_REQ: {
+		if ((data->client.app_id == 0) ||
+			(data->type != QSEECOM_CLIENT_APP)) {
+			pr_err("send cmd req: invalid handle (%d) app_id(%d)\n",
+					data->type, data->client.app_id);
+			ret = -EINVAL;
+			break;
+		}
 		/* Only one client allowed here at a time */
 		mutex_lock(&app_access_lock);
 		atomic_inc(&data->ioctl_count);
@@ -2700,6 +2772,13 @@
 		break;
 	}
 	case QSEECOM_IOCTL_SEND_MODFD_CMD_REQ: {
+		if ((data->client.app_id == 0) ||
+			(data->type != QSEECOM_CLIENT_APP)) {
+			pr_err("send mdfd cmd: invalid handle (%d) appid(%d)\n",
+					data->type, data->client.app_id);
+			ret = -EINVAL;
+			break;
+		}
 		/* Only one client allowed here at a time */
 		mutex_lock(&app_access_lock);
 		atomic_inc(&data->ioctl_count);
@@ -2712,6 +2791,13 @@
 		break;
 	}
 	case QSEECOM_IOCTL_RECEIVE_REQ: {
+		if ((data->listener.id == 0) ||
+			(data->type != QSEECOM_LISTENER_SERVICE)) {
+			pr_err("receive req: invalid handle (%d), lid(%d)\n",
+						data->type, data->listener.id);
+			ret = -EINVAL;
+			break;
+		}
 		atomic_inc(&data->ioctl_count);
 		ret = qseecom_receive_req(data);
 		atomic_dec(&data->ioctl_count);
@@ -2721,6 +2807,13 @@
 		break;
 	}
 	case QSEECOM_IOCTL_SEND_RESP_REQ: {
+		if ((data->listener.id == 0) ||
+			(data->type != QSEECOM_LISTENER_SERVICE)) {
+			pr_err("send resp req: invalid handle (%d), lid(%d)\n",
+						data->type, data->listener.id);
+			ret = -EINVAL;
+			break;
+		}
 		atomic_inc(&data->ioctl_count);
 		ret = qseecom_send_resp();
 		atomic_dec(&data->ioctl_count);
@@ -2730,6 +2823,15 @@
 		break;
 	}
 	case QSEECOM_IOCTL_SET_MEM_PARAM_REQ: {
+		if ((data->type != QSEECOM_CLIENT_APP) &&
+			(data->type != QSEECOM_GENERIC) &&
+			(data->type != QSEECOM_SECURE_SERVICE)) {
+			pr_err("set mem param req: invalid handle (%d)\n",
+								data->type);
+			ret = -EINVAL;
+			break;
+		}
+		pr_debug("SET_MEM_PARAM: qseecom addr = 0x%x\n", (u32)data);
 		ret = qseecom_set_client_mem_param(data, argp);
 		if (ret)
 			pr_err("failed Qqseecom_set_mem_param request: %d\n",
@@ -2737,6 +2839,15 @@
 		break;
 	}
 	case QSEECOM_IOCTL_LOAD_APP_REQ: {
+		if ((data->type != QSEECOM_GENERIC) &&
+			(data->type != QSEECOM_CLIENT_APP)) {
+			pr_err("load app req: invalid handle (%d)\n",
+								data->type);
+			ret = -EINVAL;
+			break;
+		}
+		data->type = QSEECOM_CLIENT_APP;
+		pr_debug("LOAD_APP_REQ: qseecom_addr = 0x%x\n", (u32)data);
 		mutex_lock(&app_access_lock);
 		atomic_inc(&data->ioctl_count);
 		if (qseecom.qsee_version > QSEEE_VERSION_00) {
@@ -2755,6 +2866,14 @@
 		break;
 	}
 	case QSEECOM_IOCTL_UNLOAD_APP_REQ: {
+		if ((data->client.app_id == 0) ||
+			(data->type != QSEECOM_CLIENT_APP)) {
+			pr_err("unload app req:invalid handle(%d) app_id(%d)\n",
+					data->type, data->client.app_id);
+			ret = -EINVAL;
+			break;
+		}
+		pr_debug("UNLOAD_APP: qseecom_addr = 0x%x\n", (u32)data);
 		mutex_lock(&app_access_lock);
 		atomic_inc(&data->ioctl_count);
 		ret = qseecom_unload_app(data);
@@ -2773,6 +2892,20 @@
 		break;
 	}
 	case QSEECOM_IOCTL_PERF_ENABLE_REQ:{
+		if ((data->type != QSEECOM_GENERIC) &&
+			(data->type != QSEECOM_CLIENT_APP)) {
+			pr_err("perf enable req: invalid handle (%d)\n",
+								data->type);
+			ret = -EINVAL;
+			break;
+		}
+		if ((data->type == QSEECOM_CLIENT_APP) &&
+			(data->client.app_id == 0)) {
+			pr_err("perf enable req:invalid handle(%d) appid(%d)\n",
+					data->type, data->client.app_id);
+			ret = -EINVAL;
+			break;
+		}
 		atomic_inc(&data->ioctl_count);
 		ret = qsee_vote_for_clock(data, CLK_DFAB);
 		if (ret)
@@ -2784,13 +2917,34 @@
 		break;
 	}
 	case QSEECOM_IOCTL_PERF_DISABLE_REQ:{
+		if ((data->type != QSEECOM_SECURE_SERVICE) &&
+			(data->type != QSEECOM_CLIENT_APP)) {
+			pr_err("perf disable req: invalid handle (%d)\n",
+								data->type);
+			ret = -EINVAL;
+			break;
+		}
+		if ((data->type == QSEECOM_CLIENT_APP) &&
+			(data->client.app_id == 0)) {
+			pr_err("perf disable: invalid handle (%d)app_id(%d)\n",
+					data->type, data->client.app_id);
+			ret = -EINVAL;
+			break;
+		}
 		atomic_inc(&data->ioctl_count);
-		qsee_disable_clock_vote(data, CLK_DFAB);
-		qsee_disable_clock_vote(data, CLK_SFPB);
+			qsee_disable_clock_vote(data, CLK_DFAB);
+			qsee_disable_clock_vote(data, CLK_SFPB);
 		atomic_dec(&data->ioctl_count);
 		break;
 	}
 	case QSEECOM_IOCTL_LOAD_EXTERNAL_ELF_REQ: {
+		if (data->type != QSEECOM_GENERIC) {
+			pr_err("load ext elf req: invalid client handle (%d)\n",
+								data->type);
+			ret = -EINVAL;
+			break;
+		}
+		data->type = QSEECOM_UNAVAILABLE_CLIENT_APP;
 		data->released = true;
 		mutex_lock(&app_access_lock);
 		atomic_inc(&data->ioctl_count);
@@ -2802,6 +2956,12 @@
 		break;
 	}
 	case QSEECOM_IOCTL_UNLOAD_EXTERNAL_ELF_REQ: {
+		if (data->type != QSEECOM_UNAVAILABLE_CLIENT_APP) {
+			pr_err("unload ext elf req: invalid handle (%d)\n",
+								data->type);
+			ret = -EINVAL;
+			break;
+		}
 		data->released = true;
 		mutex_lock(&app_access_lock);
 		atomic_inc(&data->ioctl_count);
@@ -2813,16 +2973,25 @@
 		break;
 	}
 	case QSEECOM_IOCTL_APP_LOADED_QUERY_REQ: {
+		data->type = QSEECOM_CLIENT_APP;
 		mutex_lock(&app_access_lock);
 		atomic_inc(&data->ioctl_count);
+		pr_debug("APP_LOAD_QUERY: qseecom_addr = 0x%x\n", (u32)data);
 		ret = qseecom_query_app_loaded(data, argp);
 		atomic_dec(&data->ioctl_count);
 		mutex_unlock(&app_access_lock);
 		break;
 	}
 	case QSEECOM_IOCTL_SEND_CMD_SERVICE_REQ: {
+		if (data->type != QSEECOM_GENERIC) {
+			pr_err("send cmd svc req: invalid handle (%d)\n",
+								data->type);
+			ret = -EINVAL;
+			break;
+		}
+		data->type = QSEECOM_SECURE_SERVICE;
 		if (qseecom.qsee_version < QSEE_VERSION_03) {
-			pr_err("SEND_CMD_SERVICE_REQ: Invalid qsee version %u\n",
+			pr_err("SEND_CMD_SERVICE_REQ: Invalid qsee ver %u\n",
 				qseecom.qsee_version);
 			return -EINVAL;
 		}
@@ -2834,8 +3003,14 @@
 		break;
 	}
 	case QSEECOM_IOCTL_CREATE_KEY_REQ: {
+		if (data->type != QSEECOM_GENERIC) {
+			pr_err("create key req: invalid handle (%d)\n",
+								data->type);
+			ret = -EINVAL;
+			break;
+		}
 		if (qseecom.qsee_version < QSEE_VERSION_05) {
-			pr_err("Create Key feature not supported in qsee version %u\n",
+			pr_err("Create Key feature unsupported: qsee ver %u\n",
 				qseecom.qsee_version);
 			return -EINVAL;
 		}
@@ -2851,8 +3026,14 @@
 		break;
 	}
 	case QSEECOM_IOCTL_WIPE_KEY_REQ: {
+		if (data->type != QSEECOM_GENERIC) {
+			pr_err("wipe key req: invalid handle (%d)\n",
+								data->type);
+			ret = -EINVAL;
+			break;
+		}
 		if (qseecom.qsee_version < QSEE_VERSION_05) {
-			pr_err("Wipe Key feature not supported in qsee version %u\n",
+			pr_err("Wipe Key feature unsupported in qsee ver %u\n",
 				qseecom.qsee_version);
 			return -EINVAL;
 		}
@@ -2867,6 +3048,12 @@
 		break;
 	}
 	case QSEECOM_IOCTL_SAVE_PARTITION_HASH_REQ: {
+		if (data->type != QSEECOM_GENERIC) {
+			pr_err("save part hash req: invalid handle (%d)\n",
+								data->type);
+			ret = -EINVAL;
+			break;
+		}
 		data->released = true;
 		mutex_lock(&app_access_lock);
 		atomic_inc(&data->ioctl_count);
@@ -2876,6 +3063,12 @@
 		break;
 	}
 	case QSEECOM_IOCTL_IS_ES_ACTIVATED_REQ: {
+		if (data->type != QSEECOM_GENERIC) {
+			pr_err("ES activated req: invalid handle (%d)\n",
+								data->type);
+			ret = -EINVAL;
+			break;
+		}
 		data->released = true;
 		mutex_lock(&app_access_lock);
 		atomic_inc(&data->ioctl_count);
@@ -2885,6 +3078,13 @@
 		break;
 	}
 	case QSEECOM_IOCTL_SEND_MODFD_RESP: {
+		if ((data->listener.id == 0) ||
+			(data->type != QSEECOM_LISTENER_SERVICE)) {
+			pr_err("receive req: invalid handle (%d), lid(%d)\n",
+						data->type, data->listener.id);
+			ret = -EINVAL;
+			break;
+		}
 		/* Only one client allowed here at a time */
 		atomic_inc(&data->ioctl_count);
 		ret = qseecom_send_modfd_resp(data, argp);
@@ -2895,6 +3095,13 @@
 		break;
 	}
 	case QSEECOM_IOCTL_UNPROTECT_BUF: {
+		if ((data->listener.id == 0) ||
+			(data->type != QSEECOM_LISTENER_SERVICE)) {
+			pr_err("receive req: invalid handle (%d), lid(%d)\n",
+						data->type, data->listener.id);
+			ret = -EINVAL;
+			break;
+		}
 		/* Only one client allowed here at a time */
 		atomic_inc(&data->ioctl_count);
 		ret = qseecom_unprotect_buffer(argp);
@@ -2905,6 +3112,7 @@
 		break;
 	}
 	default:
+		pr_err("Invalid IOCTL: %d\n", cmd);
 		return -EINVAL;
 	}
 	return ret;
@@ -2936,7 +3144,8 @@
 	int ret = 0;
 
 	if (data->released == false) {
-		pr_warn("data->released == false\n");
+		pr_warn("data: released = false, type = %d, data = 0x%x\n",
+			data->type, (u32)data);
 		switch (data->type) {
 		case QSEECOM_LISTENER_SERVICE:
 			ret = qseecom_unregister_listener(data);
@@ -2947,10 +3156,8 @@
 		case QSEECOM_SECURE_SERVICE:
 		case QSEECOM_GENERIC:
 			ret = qseecom_unmap_ion_allocated_memory(data);
-			if (ret) {
+			if (ret)
 				pr_err("Close failed\n");
-				return ret;
-			}
 			break;
 		case QSEECOM_UNAVAILABLE_CLIENT_APP:
 			break;
@@ -3269,9 +3476,10 @@
 			}
 			rc = scm_call(SCM_SVC_TZSCHEDULER, 1, &req, sizeof(req),
 							&resp, sizeof(resp));
-			if (rc) {
-				pr_err("Failed to send secapp region info %d\n",
-									rc);
+			if (rc || (resp.result != QSEOS_RESULT_SUCCESS)) {
+				pr_err("send secapp reg fail %d resp.res %d\n",
+							rc, resp.result);
+				rc = -EINVAL;
 				goto err;
 			}
 		}
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index 61f4946..97e952e 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -98,6 +98,23 @@
 }
 EXPORT_SYMBOL_GPL(power_supply_set_online);
 
+
+/** power_supply_set_health_state - set health state of the power supply
+ * @psy:       the power supply to control
+ * @health:    sets health property of power supply
+ */
+int power_supply_set_health_state(struct power_supply *psy, int health)
+{
+	const union power_supply_propval ret = {health,};
+
+	if (psy->set_property)
+		return psy->set_property(psy, POWER_SUPPLY_PROP_HEALTH,
+		&ret);
+	return -ENXIO;
+}
+EXPORT_SYMBOL(power_supply_set_health_state);
+
+
 /**
  * power_supply_set_scope - set scope of the power supply
  * @psy:	the power supply to control
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
index 02fd276..319a24d 100644
--- a/drivers/power/power_supply_sysfs.c
+++ b/drivers/power/power_supply_sysfs.c
@@ -150,6 +150,7 @@
 	POWER_SUPPLY_ATTR(input_voltage_regulation),
 	POWER_SUPPLY_ATTR(current_max),
 	POWER_SUPPLY_ATTR(input_current_max),
+	POWER_SUPPLY_ATTR(input_current_trim),
 	POWER_SUPPLY_ATTR(current_now),
 	POWER_SUPPLY_ATTR(current_avg),
 	POWER_SUPPLY_ATTR(power_now),
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index 49e57b9..ad39e88 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -80,8 +80,7 @@
 
 /* Configuration for saving of shutdown soc/iavg */
 #define IGNORE_SOC_TEMP_DECIDEG		50
-#define IAVG_STEP_SIZE_MA		50
-#define IAVG_START			600
+#define IAVG_STEP_SIZE_MA		10
 #define IAVG_INVALID			0xFF
 #define SOC_INVALID			0x7E
 
@@ -1234,7 +1233,6 @@
 }
 
 #define MIN_IAVG_MA 250
-#define MIN_SECONDS_FOR_VALID_SAMPLE	20
 static int calculate_unusable_charge_uah(struct qpnp_bms_chip *chip,
 					struct soc_params *params,
 					int batt_temp)
@@ -1258,17 +1256,19 @@
 		chip->iavg_num_samples = IAVG_SAMPLES;
 	}
 
-	/*
-	 * if charging use a nominal avg current to keep
-	 * a reasonable UUC while charging
-	 */
-	if (uuc_iavg_ma < MIN_IAVG_MA)
-		uuc_iavg_ma = MIN_IAVG_MA;
-	chip->iavg_samples_ma[chip->iavg_index] = uuc_iavg_ma;
-	chip->iavg_index = (chip->iavg_index + 1) % IAVG_SAMPLES;
-	chip->iavg_num_samples++;
-	if (chip->iavg_num_samples >= IAVG_SAMPLES)
-		chip->iavg_num_samples = IAVG_SAMPLES;
+	if (params->delta_time_s >= IAVG_MINIMAL_TIME) {
+		/*
+		* if charging use a nominal avg current to keep
+		* a reasonable UUC while charging
+		*/
+		if (uuc_iavg_ma < MIN_IAVG_MA)
+			uuc_iavg_ma = MIN_IAVG_MA;
+		chip->iavg_samples_ma[chip->iavg_index] = uuc_iavg_ma;
+		chip->iavg_index = (chip->iavg_index + 1) % IAVG_SAMPLES;
+		chip->iavg_num_samples++;
+		if (chip->iavg_num_samples >= IAVG_SAMPLES)
+			chip->iavg_num_samples = IAVG_SAMPLES;
+	}
 
 	/* now that this sample is added calcualte the average */
 	uuc_iavg_ma = 0;
@@ -1299,7 +1299,6 @@
 	uuc_uah_iavg = adjust_uuc(chip, params, pc_unusable,
 					uuc_uah_iavg, batt_temp);
 
-	chip->first_time_calc_uuc = 0;
 	return uuc_uah_iavg;
 }
 
@@ -1608,8 +1607,8 @@
 	int rc;
 	int iavg_ma = chip->prev_uuc_iavg_ma;
 
-	if (iavg_ma > IAVG_START)
-		temp = (iavg_ma - IAVG_START) / IAVG_STEP_SIZE_MA;
+	if (iavg_ma > MIN_IAVG_MA)
+		temp = (iavg_ma - MIN_IAVG_MA) / IAVG_STEP_SIZE_MA;
 	else
 		temp = 0;
 
@@ -2333,6 +2332,7 @@
 
 	get_current_time(&chip->last_recalc_time);
 	chip->first_time_calc_soc = 0;
+	chip->first_time_calc_uuc = 0;
 	return chip->calculated_soc;
 }
 
@@ -2687,7 +2687,8 @@
 		return;
 	}
 
-	temp = kzalloc(sizeof(struct single_row_lut), GFP_KERNEL);
+	temp = devm_kzalloc(chip->dev, sizeof(struct single_row_lut),
+			GFP_KERNEL);
 	if (!temp) {
 		pr_err("Cannot allocate memory for adjusted fcc table\n");
 		return;
@@ -2705,7 +2706,7 @@
 
 	old = chip->adjusted_fcc_temp_lut;
 	chip->adjusted_fcc_temp_lut = temp;
-	kfree(old);
+	devm_kfree(chip->dev, old);
 }
 
 static int read_fcc_data_from_backup(struct qpnp_bms_chip *chip)
@@ -3293,17 +3294,17 @@
 	if (rc) {
 		pr_err("failed to read addr = %d %d assuming %d\n",
 				chip->base + IAVG_STORAGE_REG, rc,
-				IAVG_START);
-		return IAVG_START;
+				MIN_IAVG_MA);
+		return MIN_IAVG_MA;
 	} else if (iavg == IAVG_INVALID) {
 		pr_err("invalid iavg read from BMS1_DATA_REG_1, using %d\n",
-				IAVG_START);
-		return IAVG_START;
+				MIN_IAVG_MA);
+		return MIN_IAVG_MA;
 	} else {
 		if (iavg == 0)
-			return IAVG_START;
+			return MIN_IAVG_MA;
 		else
-			return IAVG_START + IAVG_STEP_SIZE_MA * (iavg + 1);
+			return MIN_IAVG_MA + IAVG_STEP_SIZE_MA * iavg;
 	}
 }
 
@@ -3442,7 +3443,7 @@
 static int set_battery_data(struct qpnp_bms_chip *chip)
 {
 	int64_t battery_id;
-	int rc, dt_data = false;
+	int rc = 0, dt_data = false;
 	struct bms_battery_data *batt_data;
 	struct device_node *node;
 
@@ -3466,41 +3467,52 @@
 
 		node = of_find_node_by_name(chip->spmi->dev.of_node,
 				"qcom,battery-data");
-		if (node) {
-			batt_data = kzalloc(sizeof(struct bms_battery_data),
-					GFP_KERNEL);
-			batt_data->fcc_temp_lut = kzalloc(
-					sizeof(struct single_row_lut),
-					GFP_KERNEL);
-			batt_data->pc_temp_ocv_lut = kzalloc(
-					sizeof(struct pc_temp_ocv_lut),
-					GFP_KERNEL);
-			batt_data->rbatt_sf_lut = kzalloc(
-					sizeof(struct sf_lut), GFP_KERNEL);
+		if (!node) {
+			pr_warn("No available batterydata, using palladium 1500\n");
+			batt_data = &palladium_1500_data;
+			goto assign_data;
+		}
+		batt_data = devm_kzalloc(chip->dev,
+				sizeof(struct bms_battery_data), GFP_KERNEL);
+		if (!batt_data) {
+			pr_err("Could not alloc battery data\n");
+			batt_data = &palladium_1500_data;
+			goto assign_data;
+		}
+		batt_data->fcc_temp_lut = devm_kzalloc(chip->dev,
+				sizeof(struct single_row_lut),
+				GFP_KERNEL);
+		batt_data->pc_temp_ocv_lut = devm_kzalloc(chip->dev,
+				sizeof(struct pc_temp_ocv_lut),
+				GFP_KERNEL);
+		batt_data->rbatt_sf_lut = devm_kzalloc(chip->dev,
+				sizeof(struct sf_lut),
+				GFP_KERNEL);
 
-			batt_data->max_voltage_uv = -1;
-			batt_data->cutoff_uv = -1;
-			batt_data->iterm_ua = -1;
+		batt_data->max_voltage_uv = -1;
+		batt_data->cutoff_uv = -1;
+		batt_data->iterm_ua = -1;
 
-			rc = of_batterydata_read_data(node,
-					batt_data, battery_id);
-			if (rc) {
-				pr_err("battery data load failed, using palladium 1500\n");
-				kfree(batt_data->fcc_temp_lut);
-				kfree(batt_data->pc_temp_ocv_lut);
-				kfree(batt_data->rbatt_sf_lut);
-				kfree(batt_data);
-				batt_data = &palladium_1500_data;
-			} else {
-				dt_data = true;
-			}
+		/*
+		 * if the alloced luts are 0s, of_batterydata_read_data ignores
+		 * them.
+		 */
+		rc = of_batterydata_read_data(node, batt_data, battery_id);
+		if (rc == 0 && batt_data->fcc_temp_lut
+				&& batt_data->pc_temp_ocv_lut
+				&& batt_data->rbatt_sf_lut) {
+			dt_data = true;
 		} else {
-			pr_warn("invalid battid, palladium 1500 assumed batt_id %llx\n",
-					battery_id);
+			pr_err("battery data load failed, using palladium 1500\n");
+			devm_kfree(chip->dev, batt_data->fcc_temp_lut);
+			devm_kfree(chip->dev, batt_data->pc_temp_ocv_lut);
+			devm_kfree(chip->dev, batt_data->rbatt_sf_lut);
+			devm_kfree(chip->dev, batt_data);
 			batt_data = &palladium_1500_data;
 		}
 	}
 
+assign_data:
 	chip->fcc_mah = batt_data->fcc;
 	chip->fcc_temp_lut = batt_data->fcc_temp_lut;
 	chip->fcc_sf_lut = batt_data->fcc_sf_lut;
@@ -3519,13 +3531,20 @@
 	if (batt_data->iterm_ua >= 0 && dt_data)
 		chip->chg_term_ua = batt_data->iterm_ua;
 
-	if (dt_data)
-		kfree(batt_data);
-
 	if (chip->pc_temp_ocv_lut == NULL) {
-		pr_err("temp ocv lut table is NULL\n");
+		pr_err("temp ocv lut table has not been loaded\n");
+		if (dt_data) {
+			devm_kfree(chip->dev, batt_data->fcc_temp_lut);
+			devm_kfree(chip->dev, batt_data->pc_temp_ocv_lut);
+			devm_kfree(chip->dev, batt_data->rbatt_sf_lut);
+			devm_kfree(chip->dev, batt_data);
+		}
 		return -EINVAL;
 	}
+
+	if (dt_data)
+		devm_kfree(chip->dev, batt_data);
+
 	return 0;
 }
 
@@ -3642,6 +3661,8 @@
 		chip->fcc_learning_samples = devm_kzalloc(&chip->spmi->dev,
 				(sizeof(struct fcc_sample) *
 				chip->min_fcc_learning_samples), GFP_KERNEL);
+		if (chip->fcc_learning_samples == NULL)
+			return -ENOMEM;
 		pr_debug("min-fcc-soc=%d, min-fcc-pc=%d, min-fcc-cycles=%d\n",
 			chip->min_fcc_learning_soc, chip->min_fcc_ocv_pc,
 			chip->min_fcc_learning_samples);
@@ -3981,7 +4002,8 @@
 	bool warm_reset;
 	int rc, vbatt;
 
-	chip = kzalloc(sizeof *chip, GFP_KERNEL);
+	chip = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_bms_chip),
+			GFP_KERNEL);
 
 	if (chip == NULL) {
 		pr_err("kzalloc() failed.\n");
@@ -4172,17 +4194,12 @@
 	wake_lock_destroy(&chip->cv_wake_lock);
 error_resource:
 error_read:
-	kfree(chip);
 	return rc;
 }
 
-static int __devexit
-qpnp_bms_remove(struct spmi_device *spmi)
+static int qpnp_bms_remove(struct spmi_device *spmi)
 {
-	struct qpnp_bms_chip *chip = dev_get_drvdata(&spmi->dev);
-
 	dev_set_drvdata(&spmi->dev, NULL);
-	kfree(chip);
 	return 0;
 }
 
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 6e9dc57..64ad940 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -31,6 +31,7 @@
 #include <linux/of_batterydata.h>
 #include <linux/qpnp-revid.h>
 #include <linux/android_alarm.h>
+#include <linux/spinlock.h>
 
 /* Interrupt offsets */
 #define INT_RT_STS(base)			(base + 0x10)
@@ -81,11 +82,13 @@
 #define CHGR_USB_USB_SUSP			0x47
 #define CHGR_USB_USB_OTG_CTL			0x48
 #define CHGR_USB_ENUM_T_STOP			0x4E
+#define CHGR_USB_TRIM				0xF1
 #define CHGR_CHG_TEMP_THRESH			0x66
 #define CHGR_BAT_IF_PRES_STATUS			0x08
 #define CHGR_STATUS				0x09
 #define CHGR_BAT_IF_VCP				0x42
 #define CHGR_BAT_IF_BATFET_CTRL1		0x90
+#define CHGR_BAT_IF_BATFET_CTRL4		0x93
 #define CHGR_BAT_IF_SPARE			0xDF
 #define CHGR_MISC_BOOT_DONE			0x42
 #define CHGR_BUCK_PSTG_CTRL			0x73
@@ -241,6 +244,7 @@
  * @btc_disabled		Flag to disable btc (disables hot and cold irqs)
  * @max_voltage_mv:		the max volts the batt should be charged up to
  * @min_voltage_mv:		min battery voltage before turning the FET on
+ * @batt_weak_voltage_mv:	Weak battery voltage threshold
  * @max_bat_chg_current:	maximum battery charge current in mA
  * @warm_bat_chg_ma:	warm battery maximum charge current in mA
  * @cool_bat_chg_ma:	cool battery maximum charge current in mA
@@ -290,14 +294,19 @@
 	struct qpnp_chg_irq		chg_vbatdet_lo;
 	struct qpnp_chg_irq		batt_pres;
 	struct qpnp_chg_irq		batt_temp_ok;
+	struct qpnp_chg_irq		coarse_det_usb;
 	bool				bat_is_cool;
 	bool				bat_is_warm;
 	bool				chg_done;
 	bool				charger_monitor_checked;
 	bool				usb_present;
+	u8				usbin_health;
+	bool				usb_coarse_det;
 	bool				dc_present;
 	bool				batt_present;
 	bool				charging_disabled;
+	bool				ovp_monitor_enable;
+	bool				usb_valid_check_ovp;
 	bool				btc_disabled;
 	bool				use_default_batt_values;
 	bool				duty_cycle_100p;
@@ -308,6 +317,7 @@
 	unsigned int			safe_voltage_mv;
 	unsigned int			max_voltage_mv;
 	unsigned int			min_voltage_mv;
+	unsigned int			batt_weak_voltage_mv;
 	int				prev_usb_max_ma;
 	int				set_vddmax_mv;
 	int				delta_vddmax_mv;
@@ -341,14 +351,19 @@
 	struct work_struct		adc_disable_work;
 	struct delayed_work		arb_stop_work;
 	struct delayed_work		eoc_work;
+	struct delayed_work		usbin_health_check;
 	struct work_struct		soc_check_work;
 	struct delayed_work		aicl_check_work;
 	struct qpnp_chg_regulator	otg_vreg;
 	struct qpnp_chg_regulator	boost_vreg;
 	struct qpnp_chg_regulator	batfet_vreg;
+	bool				batfet_ext_en;
+	struct work_struct		batfet_lcl_work;
 	struct qpnp_vadc_chip		*vadc_dev;
 	struct qpnp_adc_tm_chip		*adc_tm_dev;
 	struct mutex			jeita_configure_lock;
+	spinlock_t			usbin_health_monitor_lock;
+	struct mutex			batfet_vreg_lock;
 	struct alarm			reduce_power_stage_alarm;
 	struct work_struct		reduce_power_stage_work;
 	bool				power_stage_workaround_running;
@@ -386,7 +401,13 @@
 	[COLD_THD_80_PCT] = BIT(1),
 };
 
-	static inline int
+enum usbin_health {
+	USBIN_UNKNOW,
+	USBIN_OK,
+	USBIN_OVP,
+};
+
+static inline int
 get_bpd(const char *name)
 {
 	int i = 0;
@@ -599,6 +620,58 @@
 	return (usbin_valid_rt_sts & USB_VALID_BIT) ? 1 : 0;
 }
 
+#define USB_VALID_MASK 0xC0
+#define USB_COARSE_DET 0x10
+#define USB_VALID_UVP_VALUE    0x00
+#define USB_VALID_OVP_VALUE    0x40
+static int
+qpnp_chg_check_usb_coarse_det(struct qpnp_chg_chip *chip)
+{
+	u8 usbin_chg_rt_sts;
+	int rc;
+	rc = qpnp_chg_read(chip, &usbin_chg_rt_sts,
+		chip->usb_chgpth_base + CHGR_STATUS , 1);
+	if (rc) {
+		pr_err("spmi read failed: addr=%03X, rc=%d\n",
+			chip->usb_chgpth_base + CHGR_STATUS, rc);
+		return rc;
+	}
+	return (usbin_chg_rt_sts & USB_COARSE_DET) ? 1 : 0;
+}
+
+static int
+qpnp_chg_check_usbin_health(struct qpnp_chg_chip *chip)
+{
+	u8 usbin_chg_rt_sts, usbin_health = 0;
+	int rc;
+
+	rc = qpnp_chg_read(chip, &usbin_chg_rt_sts,
+		chip->usb_chgpth_base + CHGR_STATUS , 1);
+
+	if (rc) {
+		pr_err("spmi read failed: addr=%03X, rc=%d\n",
+		chip->usb_chgpth_base + CHGR_STATUS, rc);
+		return rc;
+	}
+
+	pr_debug("chgr usb sts 0x%x\n", usbin_chg_rt_sts);
+	if ((usbin_chg_rt_sts & USB_COARSE_DET) == USB_COARSE_DET) {
+		if ((usbin_chg_rt_sts & USB_VALID_MASK)
+			 == USB_VALID_OVP_VALUE) {
+			usbin_health = USBIN_OVP;
+			pr_err("Over voltage charger inserted\n");
+		} else if ((usbin_chg_rt_sts & USB_VALID_BIT) != 0) {
+			usbin_health = USBIN_OK;
+			pr_debug("Valid charger inserted\n");
+		}
+	} else {
+		usbin_health = USBIN_UNKNOW;
+		pr_debug("Charger plug out\n");
+	}
+
+	return usbin_health;
+}
+
 static int
 qpnp_chg_is_dc_chg_plugged_in(struct qpnp_chg_chip *chip)
 {
@@ -676,6 +749,48 @@
 }
 
 static int
+qpnp_chg_iusb_trim_get(struct qpnp_chg_chip *chip)
+{
+	int rc = 0;
+	u8 trim_reg;
+
+	rc = qpnp_chg_read(chip, &trim_reg,
+			chip->usb_chgpth_base + CHGR_USB_TRIM, 1);
+	if (rc) {
+		pr_err("failed to read USB_TRIM rc=%d\n", rc);
+		return 0;
+	}
+
+	return trim_reg;
+}
+
+static int
+qpnp_chg_iusb_trim_set(struct qpnp_chg_chip *chip, int trim)
+{
+	int rc = 0;
+
+	rc = qpnp_chg_masked_write(chip,
+		chip->usb_chgpth_base + SEC_ACCESS,
+		0xFF,
+		0xA5, 1);
+	if (rc) {
+		pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
+		return rc;
+	}
+
+	rc = qpnp_chg_masked_write(chip,
+		chip->usb_chgpth_base + CHGR_USB_TRIM,
+		0xFF,
+		trim, 1);
+	if (rc) {
+		pr_err("failed to write USB TRIM rc=%d\n", rc);
+		return rc;
+	}
+
+	return rc;
+}
+
+static int
 qpnp_chg_iusbmax_set(struct qpnp_chg_chip *chip, int mA)
 {
 	int rc = 0;
@@ -737,7 +852,7 @@
 #define QPNP_CHG_VINMIN_MAX_MV		9600
 #define QPNP_CHG_VINMIN_STEP_MV		50
 #define QPNP_CHG_VINMIN_STEP_HIGH_MV	200
-#define QPNP_CHG_VINMIN_MASK		0x1F
+#define QPNP_CHG_VINMIN_MASK		0x3F
 #define QPNP_CHG_VINMIN_MIN_VAL	0x10
 static int
 qpnp_chg_vinmin_set(struct qpnp_chg_chip *chip, int voltage)
@@ -792,6 +907,26 @@
 	return vin_min_mv;
 }
 
+#define QPNP_CHG_VBATWEAK_MIN_MV	2100
+#define QPNP_CHG_VBATWEAK_MAX_MV	3600
+#define QPNP_CHG_VBATWEAK_STEP_MV	100
+static int
+qpnp_chg_vbatweak_set(struct qpnp_chg_chip *chip, int vbatweak_mv)
+{
+	u8 temp;
+
+	if (vbatweak_mv < QPNP_CHG_VBATWEAK_MIN_MV
+			|| vbatweak_mv > QPNP_CHG_VBATWEAK_MAX_MV)
+		return -EINVAL;
+
+	temp = (vbatweak_mv - QPNP_CHG_VBATWEAK_MIN_MV)
+			/ QPNP_CHG_VBATWEAK_STEP_MV;
+
+	pr_debug("voltage=%d setting %02x\n", vbatweak_mv, temp);
+	return qpnp_chg_write(chip, &temp,
+		chip->chgr_base + CHGR_VBAT_WEAK, 1);
+}
+
 static int
 qpnp_chg_usb_iusbmax_get(struct qpnp_chg_chip *chip)
 {
@@ -1117,12 +1252,128 @@
 				chip->delta_vddmax_mv);
 }
 
+static void
+qpnp_usbin_health_check_work(struct work_struct *work)
+{
+	int usbin_health = 0;
+	u8 psy_health_sts = 0;
+	struct delayed_work *dwork = to_delayed_work(work);
+	struct qpnp_chg_chip *chip = container_of(dwork,
+				struct qpnp_chg_chip, usbin_health_check);
+
+	usbin_health = qpnp_chg_check_usbin_health(chip);
+	spin_lock(&chip->usbin_health_monitor_lock);
+	if (chip->usbin_health != usbin_health) {
+		pr_debug("health_check_work: pr_usbin_health = %d, usbin_health = %d",
+			chip->usbin_health, usbin_health);
+		chip->usbin_health = usbin_health;
+		if (usbin_health == USBIN_OVP)
+			psy_health_sts = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
+		else if (usbin_health == USBIN_OK)
+			psy_health_sts = POWER_SUPPLY_HEALTH_GOOD;
+		power_supply_set_health_state(chip->usb_psy, psy_health_sts);
+		power_supply_changed(chip->usb_psy);
+	}
+	/* enable OVP monitor in usb valid after coarse-det complete */
+	chip->usb_valid_check_ovp = true;
+	spin_unlock(&chip->usbin_health_monitor_lock);
+	return;
+}
+
+#define USB_VALID_DEBOUNCE_TIME_MASK		0x3
+#define USB_DEB_BYPASS		0x0
+#define USB_DEB_5MS			0x1
+#define USB_DEB_10MS		0x2
+#define USB_DEB_20MS		0x3
+static irqreturn_t
+qpnp_chg_coarse_det_usb_irq_handler(int irq, void *_chip)
+{
+	struct qpnp_chg_chip *chip = _chip;
+	int host_mode, rc = 0;
+	int debounce[] = {
+		[USB_DEB_BYPASS] = 0,
+		[USB_DEB_5MS] = 5,
+		[USB_DEB_10MS] = 10,
+		[USB_DEB_20MS] = 20 };
+	u8 ovp_ctl;
+	bool usb_coarse_det;
+
+	host_mode = qpnp_chg_is_otg_en_set(chip);
+	usb_coarse_det = qpnp_chg_check_usb_coarse_det(chip);
+	pr_debug("usb coarse-det triggered: %d host_mode: %d\n",
+			usb_coarse_det, host_mode);
+
+	if (host_mode)
+		return IRQ_HANDLED;
+	/* ignore to monitor OVP in usbin valid irq handler
+	 if the coarse-det fired first, do the OVP state monitor
+	 in the usbin_health_check work, and after the work,
+	 enable monitor OVP in usbin valid irq handler */
+	chip->usb_valid_check_ovp = false;
+	if (chip->usb_coarse_det ^ usb_coarse_det) {
+		chip->usb_coarse_det = usb_coarse_det;
+		if (usb_coarse_det) {
+			/* usb coarse-det rising edge, check the usbin_valid
+			debounce time setting, and start a delay work to
+			check the OVP status*/
+			rc = qpnp_chg_read(chip, &ovp_ctl,
+					chip->usb_chgpth_base + USB_OVP_CTL, 1);
+
+			if (rc) {
+				pr_err("spmi read failed: addr=%03X, rc=%d\n",
+					chip->usb_chgpth_base + USB_OVP_CTL,
+					rc);
+				return rc;
+			}
+			ovp_ctl = ovp_ctl & USB_VALID_DEBOUNCE_TIME_MASK;
+			schedule_delayed_work(&chip->usbin_health_check,
+					msecs_to_jiffies(debounce[ovp_ctl]));
+		} else {
+			/* usb coarse-det rising edge, set the usb psy health
+			status to unknown */
+			pr_debug("usb coarse det clear, set usb health to unknown\n");
+			chip->usbin_health = USBIN_UNKNOW;
+			power_supply_set_health_state(chip->usb_psy,
+				POWER_SUPPLY_HEALTH_UNKNOWN);
+			power_supply_changed(chip->usb_psy);
+		}
+
+	}
+	return IRQ_HANDLED;
+}
+
+#define BATFET_LPM_MASK		0xC0
+#define BATFET_LPM		0x40
+#define BATFET_NO_LPM		0x00
+static int
+qpnp_chg_regulator_batfet_set(struct qpnp_chg_chip *chip, bool enable)
+{
+	int rc = 0;
+
+	if (chip->charging_disabled || !chip->bat_if_base)
+		return rc;
+
+	if (chip->type == SMBB)
+		rc = qpnp_chg_masked_write(chip,
+			chip->bat_if_base + CHGR_BAT_IF_SPARE,
+			BATFET_LPM_MASK,
+			enable ? BATFET_NO_LPM : BATFET_LPM, 1);
+	else
+		rc = qpnp_chg_masked_write(chip,
+			chip->bat_if_base + CHGR_BAT_IF_BATFET_CTRL4,
+			BATFET_LPM_MASK,
+			enable ? BATFET_NO_LPM : BATFET_LPM, 1);
+
+	return rc;
+}
+
 #define ENUM_T_STOP_BIT		BIT(0)
 static irqreturn_t
 qpnp_chg_usb_usbin_valid_irq_handler(int irq, void *_chip)
 {
 	struct qpnp_chg_chip *chip = _chip;
-	int usb_present, host_mode;
+	int usb_present, host_mode, usbin_health;
+	u8 psy_health_sts;
 
 	usb_present = qpnp_chg_is_usb_chg_plugged_in(chip);
 	host_mode = qpnp_chg_is_otg_en_set(chip);
@@ -1136,15 +1387,55 @@
 	if (chip->usb_present ^ usb_present) {
 		chip->usb_present = usb_present;
 		if (!usb_present) {
+			/* when a valid charger inserted, and increase the
+			 *  charger voltage to OVP threshold, then
+			 *  usb_in_valid falling edge interrupt triggers.
+			 *  So we handle the OVP monitor here, and ignore
+			 *  other health state changes */
+			if (chip->ovp_monitor_enable &&
+				       (chip->usb_valid_check_ovp)) {
+				usbin_health =
+					qpnp_chg_check_usbin_health(chip);
+				if (chip->usbin_health != usbin_health) {
+					chip->usbin_health = usbin_health;
+					if (usbin_health == USBIN_OVP)
+						psy_health_sts =
+					POWER_SUPPLY_HEALTH_OVERVOLTAGE;
+					power_supply_set_health_state(
+						chip->usb_psy,
+						psy_health_sts);
+					power_supply_changed(chip->usb_psy);
+				}
+			}
 			if (!qpnp_chg_is_dc_chg_plugged_in(chip)) {
 				chip->delta_vddmax_mv = 0;
 				qpnp_chg_set_appropriate_vddmax(chip);
+				chip->chg_done = false;
 			}
 			qpnp_chg_usb_suspend_enable(chip, 1);
-			if (!qpnp_chg_is_dc_chg_plugged_in(chip))
-				chip->chg_done = false;
 			chip->prev_usb_max_ma = -EINVAL;
 		} else {
+			/* when OVP clamped usbin, and then decrease
+			 * the charger voltage to lower than the OVP
+			 * threshold, a usbin_valid rising edge
+			 * interrupt triggered. So we change the usb
+			 * psy health state back to good */
+			if (chip->ovp_monitor_enable &&
+				       (chip->usb_valid_check_ovp)) {
+				usbin_health =
+					qpnp_chg_check_usbin_health(chip);
+				if (chip->usbin_health != usbin_health) {
+					chip->usbin_health = usbin_health;
+					 if (usbin_health == USBIN_OK)
+						psy_health_sts =
+						POWER_SUPPLY_HEALTH_GOOD;
+					power_supply_set_health_state(
+						chip->usb_psy,
+						psy_health_sts);
+					power_supply_changed(chip->usb_psy);
+				}
+			}
+
 			if (!qpnp_chg_is_dc_chg_plugged_in(chip)) {
 				chip->delta_vddmax_mv = 0;
 				qpnp_chg_set_appropriate_vddmax(chip);
@@ -1155,6 +1446,7 @@
 		}
 
 		power_supply_set_present(chip->usb_psy, chip->usb_present);
+		schedule_work(&chip->batfet_lcl_work);
 	}
 
 	return IRQ_HANDLED;
@@ -1232,6 +1524,7 @@
 		power_supply_changed(&chip->dc_psy);
 		pr_debug("psy changed batt_psy\n");
 		power_supply_changed(&chip->batt_psy);
+		schedule_work(&chip->batfet_lcl_work);
 	}
 
 	return IRQ_HANDLED;
@@ -1346,6 +1639,7 @@
 	case POWER_SUPPLY_PROP_CHARGING_ENABLED:
 	case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
 	case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
+	case POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM:
 	case POWER_SUPPLY_PROP_VOLTAGE_MIN:
 	case POWER_SUPPLY_PROP_COOL_TEMP:
 	case POWER_SUPPLY_PROP_WARM_TEMP:
@@ -1456,6 +1750,7 @@
 	POWER_SUPPLY_PROP_CAPACITY,
 	POWER_SUPPLY_PROP_CURRENT_NOW,
 	POWER_SUPPLY_PROP_INPUT_CURRENT_MAX,
+	POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM,
 	POWER_SUPPLY_PROP_VOLTAGE_MIN,
 	POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION,
 	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
@@ -1478,7 +1773,11 @@
 static int charger_monitor;
 module_param(charger_monitor, int, 0644);
 
+static int ext_ovp_present;
+module_param(ext_ovp_present, int, 0444);
+
 #define USB_WALL_THRESHOLD_MA	500
+#define OVP_USB_WALL_THRESHOLD_MA	200
 static int
 qpnp_power_get_property_mains(struct power_supply *psy,
 				  enum power_supply_property psp,
@@ -1820,8 +2119,12 @@
 			if (((ret.intval / 1000) > USB_WALL_THRESHOLD_MA)
 					&& (charger_monitor ||
 					!chip->charger_monitor_checked)) {
-				qpnp_chg_iusbmax_set(chip,
+				if (!ext_ovp_present)
+					qpnp_chg_iusbmax_set(chip,
 						USB_WALL_THRESHOLD_MA);
+				else
+					qpnp_chg_iusbmax_set(chip,
+						OVP_USB_WALL_THRESHOLD_MA);
 			} else {
 				qpnp_chg_iusbmax_set(chip, ret.intval / 1000);
 			}
@@ -1913,6 +2216,9 @@
 	case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
 		val->intval = qpnp_chg_usb_iusbmax_get(chip) * 1000;
 		break;
+	case POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM:
+		val->intval = qpnp_chg_iusb_trim_get(chip);
+		break;
 	case POWER_SUPPLY_PROP_VOLTAGE_MIN:
 		val->intval = qpnp_chg_vinmin_get(chip) * 1000;
 		break;
@@ -2353,20 +2659,50 @@
 	.list_voltage		= qpnp_chg_regulator_boost_list_voltage,
 };
 
-#define BATFET_LPM_MASK		0xC0
-#define BATFET_LPM		0x40
-#define BATFET_NO_LPM		0x00
+static int
+qpnp_chg_bat_if_batfet_reg_enabled(struct qpnp_chg_chip *chip)
+{
+	int rc = 0;
+	u8 reg = 0;
+
+	if (!chip->bat_if_base)
+		return rc;
+
+	if (chip->type == SMBB)
+		rc = qpnp_chg_read(chip, &reg,
+				chip->bat_if_base + CHGR_BAT_IF_SPARE, 1);
+	else
+		rc = qpnp_chg_read(chip, &reg,
+			chip->bat_if_base + CHGR_BAT_IF_BATFET_CTRL4, 1);
+
+	if (rc) {
+		pr_err("failed to read batt_if rc=%d\n", rc);
+		return rc;
+	}
+
+	if ((reg & BATFET_LPM_MASK) == BATFET_NO_LPM)
+		return 1;
+
+	return 0;
+}
+
 static int
 qpnp_chg_regulator_batfet_enable(struct regulator_dev *rdev)
 {
 	struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
-	int rc;
+	int rc = 0;
 
-	rc = qpnp_chg_masked_write(chip,
-			chip->bat_if_base + CHGR_BAT_IF_SPARE,
-			BATFET_LPM_MASK, BATFET_NO_LPM, 1);
-	if (rc)
-		pr_err("failed to write to batt_if rc=%d\n", rc);
+	mutex_lock(&chip->batfet_vreg_lock);
+	/* Only enable if not already enabled */
+	if (!qpnp_chg_bat_if_batfet_reg_enabled(chip)) {
+		rc = qpnp_chg_regulator_batfet_set(chip, 1);
+		if (rc)
+			pr_err("failed to write to batt_if rc=%d\n", rc);
+	}
+
+	chip->batfet_ext_en = true;
+	mutex_unlock(&chip->batfet_vreg_lock);
+
 	return rc;
 }
 
@@ -2374,13 +2710,20 @@
 qpnp_chg_regulator_batfet_disable(struct regulator_dev *rdev)
 {
 	struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
-	int rc;
+	int rc = 0;
 
-	rc = qpnp_chg_masked_write(chip,
-			chip->bat_if_base + CHGR_BAT_IF_SPARE,
-			BATFET_LPM_MASK, BATFET_LPM, 1);
-	if (rc)
-		pr_err("failed to write to batt_if rc=%d\n", rc);
+	mutex_lock(&chip->batfet_vreg_lock);
+	/* Don't allow disable if charger connected */
+	if (!qpnp_chg_is_usb_chg_plugged_in(chip) &&
+			!qpnp_chg_is_dc_chg_plugged_in(chip)) {
+		rc = qpnp_chg_regulator_batfet_set(chip, 0);
+		if (rc)
+			pr_err("failed to write to batt_if rc=%d\n", rc);
+	}
+
+	chip->batfet_ext_en = false;
+	mutex_unlock(&chip->batfet_vreg_lock);
+
 	return rc;
 }
 
@@ -2388,20 +2731,8 @@
 qpnp_chg_regulator_batfet_is_enabled(struct regulator_dev *rdev)
 {
 	struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
-	int rc;
-	u8 reg;
 
-	rc = qpnp_chg_read(chip, &reg,
-				chip->bat_if_base + CHGR_BAT_IF_SPARE, 1);
-	if (rc) {
-		pr_err("failed to read batt_if rc=%d\n", rc);
-		return rc;
-	}
-
-	if (reg && BATFET_LPM_MASK == BATFET_NO_LPM)
-		return 1;
-
-	return 0;
+	return chip->batfet_ext_en;
 }
 
 static struct regulator_ops qpnp_chg_batfet_vreg_ops = {
@@ -2890,6 +3221,25 @@
 }
 
 static void
+qpnp_chg_batfet_lcl_work(struct work_struct *work)
+{
+	struct qpnp_chg_chip *chip = container_of(work,
+				struct qpnp_chg_chip, batfet_lcl_work);
+
+	mutex_lock(&chip->batfet_vreg_lock);
+	if (qpnp_chg_is_usb_chg_plugged_in(chip) ||
+			qpnp_chg_is_dc_chg_plugged_in(chip)) {
+		qpnp_chg_regulator_batfet_set(chip, 1);
+		pr_debug("disabled ULPM\n");
+	} else if (!chip->batfet_ext_en && !qpnp_chg_is_usb_chg_plugged_in(chip)
+			&& !qpnp_chg_is_dc_chg_plugged_in(chip)) {
+		qpnp_chg_regulator_batfet_set(chip, 0);
+		pr_debug("enabled ULPM\n");
+	}
+	mutex_unlock(&chip->batfet_vreg_lock);
+}
+
+static void
 qpnp_chg_reduce_power_stage_work(struct work_struct *work)
 {
 	struct qpnp_chg_chip *chip = container_of(work,
@@ -2974,6 +3324,9 @@
 	case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
 		qpnp_chg_iusbmax_set(chip, val->intval / 1000);
 		break;
+	case POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM:
+		qpnp_chg_iusb_trim_set(chip, val->intval);
+		break;
 	case POWER_SUPPLY_PROP_VOLTAGE_MIN:
 		qpnp_chg_vinmin_set(chip, val->intval / 1000);
 		break;
@@ -3178,6 +3531,27 @@
 		case SMBB_USB_CHGPTH_SUBTYPE:
 		case SMBBP_USB_CHGPTH_SUBTYPE:
 		case SMBCL_USB_CHGPTH_SUBTYPE:
+			if (chip->ovp_monitor_enable) {
+				chip->coarse_det_usb.irq =
+					spmi_get_irq_byname(spmi,
+					spmi_resource, "coarse-det-usb");
+				if (chip->coarse_det_usb.irq < 0) {
+					pr_err("Can't get coarse-det irq\n");
+					return rc;
+				}
+				rc = devm_request_irq(chip->dev,
+					chip->coarse_det_usb.irq,
+					qpnp_chg_coarse_det_usb_irq_handler,
+					IRQF_TRIGGER_RISING |
+					IRQF_TRIGGER_FALLING,
+					"coarse-det-usb", chip);
+				if (rc < 0) {
+					pr_err("Can't req %d coarse-det: %d\n",
+						chip->coarse_det_usb.irq, rc);
+					return rc;
+				}
+			}
+
 			chip->usbin_valid.irq = spmi_get_irq_byname(spmi,
 						spmi_resource, "usbin-valid");
 			if (chip->usbin_valid.irq < 0) {
@@ -3313,6 +3687,8 @@
 	case SMBB_CHGR_SUBTYPE:
 	case SMBBP_CHGR_SUBTYPE:
 	case SMBCL_CHGR_SUBTYPE:
+		qpnp_chg_vbatweak_set(chip, chip->batt_weak_voltage_mv);
+
 		rc = qpnp_chg_vinmin_set(chip, chip->min_voltage_mv);
 		if (rc) {
 			pr_debug("failed setting  min_voltage rc=%d\n", rc);
@@ -3635,6 +4011,7 @@
 	OF_PROP_READ(chip, hot_batt_p, "batt-hot-percentage", rc, 1);
 	OF_PROP_READ(chip, cold_batt_p, "batt-cold-percentage", rc, 1);
 	OF_PROP_READ(chip, soc_resume_limit, "resume-soc", rc, 1);
+	OF_PROP_READ(chip, batt_weak_voltage_mv, "vbatweak-mv", rc, 1);
 
 	if (rc)
 		return rc;
@@ -3675,10 +4052,16 @@
 	chip->btc_disabled = of_property_read_bool(chip->spmi->dev.of_node,
 					"qcom,btc-disabled");
 
+	ext_ovp_present = of_property_read_bool(chip->spmi->dev.of_node,
+					"qcom,ext-ovp-present");
+
 	/* Get the charging-disabled property */
 	chip->charging_disabled = of_property_read_bool(chip->spmi->dev.of_node,
 					"qcom,charging-disabled");
 
+	chip->ovp_monitor_enable = of_property_read_bool(chip->spmi->dev.of_node,
+					"qcom,ovp-monitor-en");
+
 	/* Get the duty-cycle-100p property */
 	chip->duty_cycle_100p = of_property_read_bool(
 					chip->spmi->dev.of_node,
@@ -3746,10 +4129,14 @@
 	}
 
 	mutex_init(&chip->jeita_configure_lock);
+	spin_lock_init(&chip->usbin_health_monitor_lock);
 	alarm_init(&chip->reduce_power_stage_alarm, ANDROID_ALARM_RTC_WAKEUP,
 			qpnp_chg_reduce_power_stage_callback);
 	INIT_WORK(&chip->reduce_power_stage_work,
 			qpnp_chg_reduce_power_stage_work);
+	mutex_init(&chip->batfet_vreg_lock);
+	INIT_WORK(&chip->batfet_lcl_work,
+			qpnp_chg_batfet_lcl_work);
 
 	/* Get all device tree properties */
 	rc = qpnp_charger_read_dt_props(chip);
@@ -3959,6 +4346,8 @@
 
 	INIT_DELAYED_WORK(&chip->eoc_work, qpnp_eoc_work);
 	INIT_DELAYED_WORK(&chip->arb_stop_work, qpnp_arb_stop_work);
+	INIT_DELAYED_WORK(&chip->usbin_health_check,
+			qpnp_usbin_health_check_work);
 	INIT_WORK(&chip->soc_check_work, qpnp_chg_soc_check_work);
 	INIT_DELAYED_WORK(&chip->aicl_check_work, qpnp_aicl_check_work);
 
diff --git a/drivers/rtc/alarm-dev.c b/drivers/rtc/alarm-dev.c
index 1d60e97..4682e9c 100644
--- a/drivers/rtc/alarm-dev.c
+++ b/drivers/rtc/alarm-dev.c
@@ -98,7 +98,7 @@
 				wake_unlock(&alarm_wake_lock);
 		}
 		alarm_enabled &= ~alarm_type_mask;
-		if (alarm_type == ANDROID_ALARM_RTC_WAKEUP)
+		if (alarm_type == ANDROID_ALARM_RTC_POWEROFF_WAKEUP)
 			set_power_on_alarm(0);
 		spin_unlock_irqrestore(&alarm_slock, flags);
 		break;
@@ -127,7 +127,7 @@
 		alarm_start_range(&alarms[alarm_type],
 			timespec_to_ktime(new_alarm_time),
 			timespec_to_ktime(new_alarm_time));
-		if ((alarm_type == ANDROID_ALARM_RTC_WAKEUP) &&
+		if ((alarm_type == ANDROID_ALARM_RTC_POWEROFF_WAKEUP) &&
 				(ANDROID_ALARM_BASE_CMD(cmd) ==
 				 ANDROID_ALARM_SET(0)))
 			set_power_on_alarm(new_alarm_time.tv_sec);
@@ -171,6 +171,7 @@
 		switch (alarm_type) {
 		case ANDROID_ALARM_RTC_WAKEUP:
 		case ANDROID_ALARM_RTC:
+		case ANDROID_ALARM_RTC_POWEROFF_WAKEUP:
 			getnstimeofday(&tmp_time);
 			break;
 		case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP:
diff --git a/drivers/rtc/alarm.c b/drivers/rtc/alarm.c
index 1648cba..7d59e28 100644
--- a/drivers/rtc/alarm.c
+++ b/drivers/rtc/alarm.c
@@ -81,7 +81,8 @@
 {
 	struct alarm *alarm;
 	bool is_wakeup = base == &alarms[ANDROID_ALARM_RTC_WAKEUP] ||
-			base == &alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP];
+			base == &alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP] ||
+			base == &alarms[ANDROID_ALARM_RTC_POWEROFF_WAKEUP];
 
 	if (base->stopped) {
 		pr_alarm(FLOW, "changed alarm while setting the wall time\n");
@@ -423,15 +424,25 @@
 	hrtimer_cancel(&alarms[ANDROID_ALARM_RTC_WAKEUP].timer);
 	hrtimer_cancel(&alarms[
 			ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].timer);
+	hrtimer_cancel(&alarms[
+			ANDROID_ALARM_RTC_POWEROFF_WAKEUP].timer);
 
 	tmp_queue = &alarms[ANDROID_ALARM_RTC_WAKEUP];
 	if (tmp_queue->first)
 		wakeup_queue = tmp_queue;
+
 	tmp_queue = &alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP];
 	if (tmp_queue->first && (!wakeup_queue ||
 				hrtimer_get_expires(&tmp_queue->timer).tv64 <
 				hrtimer_get_expires(&wakeup_queue->timer).tv64))
 		wakeup_queue = tmp_queue;
+
+	tmp_queue = &alarms[ANDROID_ALARM_RTC_POWEROFF_WAKEUP];
+	if (tmp_queue->first && (!wakeup_queue ||
+				hrtimer_get_expires(&tmp_queue->timer).tv64 <
+				hrtimer_get_expires(&wakeup_queue->timer).tv64))
+		wakeup_queue = tmp_queue;
+
 	if (wakeup_queue) {
 		rtc_read_time(alarm_rtc_dev, &rtc_current_rtc_time);
 		getnstimeofday(&wall_time);
@@ -466,6 +477,8 @@
 									false);
 			update_timer_locked(&alarms[
 				ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP], false);
+			update_timer_locked(&alarms[
+					ANDROID_ALARM_RTC_POWEROFF_WAKEUP], false);
 			err = -EBUSY;
 			spin_unlock_irqrestore(&alarm_slock, flags);
 		}
@@ -489,6 +502,8 @@
 	update_timer_locked(&alarms[ANDROID_ALARM_RTC_WAKEUP], false);
 	update_timer_locked(&alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP],
 									false);
+	update_timer_locked(&alarms[ANDROID_ALARM_RTC_POWEROFF_WAKEUP],
+									false);
 	spin_unlock_irqrestore(&alarm_slock, flags);
 
 	return 0;
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index f71f54c..4cf4703 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -3607,6 +3607,9 @@
 	case POWER_SUPPLY_PROP_TYPE:
 		val->intval = psy->type;
 		break;
+	case POWER_SUPPLY_PROP_HEALTH:
+		val->intval = motg->usbin_health;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -3637,6 +3640,9 @@
 	case POWER_SUPPLY_PROP_TYPE:
 		psy->type = val->intval;
 		break;
+	case POWER_SUPPLY_PROP_HEALTH:
+		motg->usbin_health = val->intval;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -3649,6 +3655,7 @@
 						enum power_supply_property psp)
 {
 	switch (psp) {
+	case POWER_SUPPLY_PROP_HEALTH:
 	case POWER_SUPPLY_PROP_PRESENT:
 	case POWER_SUPPLY_PROP_ONLINE:
 	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
@@ -3666,6 +3673,7 @@
 };
 
 static enum power_supply_property otg_pm_power_props_usb[] = {
+	POWER_SUPPLY_PROP_HEALTH,
 	POWER_SUPPLY_PROP_PRESENT,
 	POWER_SUPPLY_PROP_ONLINE,
 	POWER_SUPPLY_PROP_VOLTAGE_MAX,
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index 08bff9a..9c909bf 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -481,12 +481,13 @@
 			pr_err("fail to start the MDP display interface\n");
 			goto on_error;
 		}
+	} else {
+		mdp3_session->first_commit = true;
 	}
 
 on_error:
 	if (!rc)
 		mdp3_session->status = 1;
-
 	mutex_unlock(&mdp3_session->lock);
 	return rc;
 }
@@ -557,6 +558,56 @@
 	return 0;
 }
 
+static int mdp3_ctrl_reset_cmd(struct msm_fb_data_type *mfd)
+{
+	int rc = 0;
+	struct mdp3_session_data *mdp3_session;
+	struct mdp3_dma *mdp3_dma;
+	struct mdss_panel_data *panel;
+	struct mdp3_vsync_notification vsync_client;
+
+	pr_debug("mdp3_ctrl_reset_cmd\n");
+	mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
+	if (!mdp3_session || !mdp3_session->panel || !mdp3_session->dma ||
+		!mdp3_session->intf) {
+		pr_err("mdp3_ctrl_reset no device");
+		return -ENODEV;
+	}
+
+	panel = mdp3_session->panel;
+	mdp3_dma = mdp3_session->dma;
+	mutex_lock(&mdp3_session->lock);
+
+	vsync_client = mdp3_dma->vsync_client;
+
+	rc = mdp3_dma->stop(mdp3_dma, mdp3_session->intf);
+	if (rc) {
+		pr_err("fail to stop the MDP3 dma\n");
+		goto reset_error;
+	}
+
+	rc = mdp3_iommu_enable(MDP3_CLIENT_DMA_P);
+	if (rc) {
+		pr_err("fail to attach dma iommu\n");
+		goto reset_error;
+	}
+
+	mdp3_ctrl_intf_init(mfd, mdp3_session->intf);
+	mdp3_ctrl_dma_init(mfd, mdp3_dma);
+
+	if (vsync_client.handler)
+		mdp3_dma->vsync_enable(mdp3_dma, &vsync_client);
+
+	if (mfd->fbi->screen_base)
+		rc = mdp3_dma->start(mdp3_dma, mdp3_session->intf);
+	else
+		mdp3_session->first_commit = true;
+
+reset_error:
+	mutex_unlock(&mdp3_session->lock);
+	return rc;
+}
+
 static int mdp3_ctrl_reset(struct msm_fb_data_type *mfd)
 {
 	int rc = 0;
@@ -573,11 +624,18 @@
 		return -ENODEV;
 	}
 
+	if (mfd->panel.type == MIPI_CMD_PANEL) {
+		rc = mdp3_ctrl_reset_cmd(mfd);
+		return rc;
+	}
+
 	panel = mdp3_session->panel;
 	mdp3_dma = mdp3_session->dma;
 	mutex_lock(&mdp3_session->lock);
 
 	vsync_client = mdp3_dma->vsync_client;
+	if (panel && panel->set_backlight)
+		panel->set_backlight(panel, 0);
 
 	rc = mdp3_dma->stop(mdp3_dma, mdp3_session->intf);
 	if (rc) {
@@ -633,6 +691,8 @@
 
 	if (mfd->fbi->screen_base)
 		rc = mdp3_dma->start(mdp3_dma, mdp3_session->intf);
+	else
+		mdp3_session->first_commit = true;
 
 reset_error:
 	mutex_unlock(&mdp3_session->lock);
@@ -747,7 +807,10 @@
 {
 	struct mdp3_session_data *mdp3_session;
 	struct mdp3_img_data *data;
+	struct mdss_panel_info *panel_info = mfd->panel_info;
 	int rc = 0;
+	bool reset_done = false;
+	struct mdss_panel_data *panel;
 
 	if (!mfd || !mfd->mdp.private1)
 		return -EINVAL;
@@ -756,9 +819,16 @@
 	if (!mdp3_session || !mdp3_session->dma)
 		return -EINVAL;
 
+	if (mdp3_bufq_count(&mdp3_session->bufq_in) == 0) {
+		pr_debug("no buffer in queue yet\n");
+		return -EPERM;
+	}
+
+	panel = mdp3_session->panel;
 	if (!mdp3_iommu_is_attached(MDP3_CLIENT_DMA_P)) {
 		pr_debug("continuous splash screen, IOMMU not attached\n");
 		mdp3_ctrl_reset(mfd);
+		reset_done = true;
 	}
 	mdp3_release_splash_memory();
 
@@ -782,6 +852,15 @@
 		data = mdp3_bufq_pop(&mdp3_session->bufq_out);
 		mdp3_put_img(data, MDP3_CLIENT_DMA_P);
 	}
+
+	if (mdp3_session->first_commit) {
+		/*wait for one frame time to ensure frame is sent to panel*/
+		msleep(1000 / panel_info->mipi.frame_rate);
+		mdp3_session->first_commit = false;
+	}
+	if (reset_done && (panel && panel->set_backlight))
+		panel->set_backlight(panel, panel->panel_info.bl_max);
+
 	mutex_unlock(&mdp3_session->lock);
 
 	mdss_fb_update_notify_update(mfd);
@@ -795,6 +874,7 @@
 	struct mdp3_session_data *mdp3_session;
 	u32 offset;
 	int bpp;
+	struct mdss_panel_info *panel_info = mfd->panel_info;
 
 	pr_debug("mdp3_ctrl_pan_display\n");
 	if (!mfd || !mfd->mdp.private1)
@@ -837,6 +917,13 @@
 		pr_debug("mdp3_ctrl_pan_display no memory, stop interface");
 		mdp3_session->dma->stop(mdp3_session->dma, mdp3_session->intf);
 	}
+
+	if (mdp3_session->first_commit) {
+		/*wait for one frame time to ensure frame is sent to panel*/
+		msleep(1000 / panel_info->mipi.frame_rate);
+		mdp3_session->first_commit = false;
+	}
+
 pan_error:
 	mutex_unlock(&mdp3_session->lock);
 }
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.h b/drivers/video/msm/mdss/mdp3_ctrl.h
index eb32797..7c4f6ac 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.h
+++ b/drivers/video/msm/mdss/mdp3_ctrl.h
@@ -51,6 +51,7 @@
 	struct mutex histo_lock;
 	int lut_sel;
 	int cc_vect_sel;
+	bool first_commit;
 };
 
 int mdp3_ctrl_init(struct msm_fb_data_type *mfd);
diff --git a/drivers/video/msm/mdss/mdp3_ppp.c b/drivers/video/msm/mdss/mdp3_ppp.c
index 1b1ddf1..8f6168a 100644
--- a/drivers/video/msm/mdss/mdp3_ppp.c
+++ b/drivers/video/msm/mdss/mdp3_ppp.c
@@ -54,6 +54,7 @@
 	[MDP_YCRYCB_H2V1] = true,
 	[MDP_Y_CBCR_H2V1] = true,
 	[MDP_Y_CRCB_H2V1] = true,
+	[MDP_BGRX_8888] = true,
 };
 
 #define MAX_LIST_WINDOW 16
@@ -554,8 +555,9 @@
 			tmp_v =
 				(MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) /
 				MDP_MAX_X_SCALE_FACTOR +
-				(MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) %
-				MDP_MAX_X_SCALE_FACTOR ? 1 : 0;
+				((MDP_SCALE_Q_FACTOR *
+				blit_op->dst.roi.height) %
+				MDP_MAX_X_SCALE_FACTOR ? 1 : 0);
 
 			/* move x location as roi width gets bigger */
 			blit_op->src.roi.x -= tmp_v - blit_op->src.roi.width;
@@ -565,8 +567,9 @@
 			tmp_v =
 				(MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) /
 				MDP_MIN_X_SCALE_FACTOR +
-				(MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) %
-				MDP_MIN_X_SCALE_FACTOR ? 1 : 0;
+				((MDP_SCALE_Q_FACTOR *
+				blit_op->dst.roi.height) %
+				MDP_MIN_X_SCALE_FACTOR ? 1 : 0);
 
 			/*
 			 * we don't move x location for continuity of
diff --git a/drivers/video/msm/mdss/mdp3_ppp_data.c b/drivers/video/msm/mdss/mdp3_ppp_data.c
index ba2a369..e562ad3 100644
--- a/drivers/video/msm/mdss/mdp3_ppp_data.c
+++ b/drivers/video/msm/mdss/mdp3_ppp_data.c
@@ -36,6 +36,7 @@
 	[MDP_YCRYCB_H2V1] = MDP_YCRYCB_H2V1_SRC_REG,
 	[MDP_Y_CBCR_H2V1] = MDP_Y_CRCB_H2V1_SRC_REG,
 	[MDP_Y_CRCB_H2V1] = MDP_Y_CRCB_H2V1_SRC_REG,
+	[MDP_BGRX_8888] = MDP_RGBX_8888_SRC_REG,
 };
 
 const uint32_t out_cfg_lut[MDP_IMGTYPE_LIMIT] = {
@@ -55,6 +56,7 @@
 	[MDP_YCRYCB_H2V1] = MDP_YCRYCB_H2V1_DST_REG,
 	[MDP_Y_CBCR_H2V1] = MDP_Y_CRCB_H2V1_DST_REG,
 	[MDP_Y_CRCB_H2V1] = MDP_Y_CRCB_H2V1_DST_REG,
+	[MDP_BGRX_8888] = MDP_RGBX_8888_DST_REG,
 };
 
 const uint32_t pack_patt_lut[MDP_IMGTYPE_LIMIT] = {
@@ -62,8 +64,8 @@
 	[MDP_BGR_565] = PPP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8),
 	[MDP_RGB_888] = PPP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8),
 	[MDP_BGR_888] = PPP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8),
-	[MDP_BGRA_8888] = PPP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R,
-		CLR_G, CLR_B, 8),
+	[MDP_BGRA_8888] = PPP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B,
+		CLR_G, CLR_R, 8),
 	[MDP_RGBA_8888] = PPP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R,
 		CLR_G, CLR_B, 8),
 	[MDP_ARGB_8888] = PPP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R,
@@ -82,6 +84,8 @@
 		CLR_CR, CLR_Y, CLR_CB, 8),
 	[MDP_Y_CBCR_H2V1] = PPP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8),
 	[MDP_Y_CRCB_H2V1] = PPP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8),
+	[MDP_BGRX_8888] = PPP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B,
+		CLR_G, CLR_R, 8),
 };
 
 const uint32_t dst_op_reg[MDP_IMGTYPE_LIMIT] = {
@@ -121,6 +125,7 @@
 	[MDP_Y_CRCB_H2V1] = 1,
 	[MDP_Y_CRCB_H2V2] = 1,
 	[MDP_YCRYCB_H2V1] = 2,
+	[MDP_BGRX_8888] = 4,
 };
 
 const bool per_pixel_alpha[MDP_IMGTYPE_LIMIT] = {
diff --git a/drivers/video/msm/mdss/mdp3_ppp_hwio.c b/drivers/video/msm/mdss/mdp3_ppp_hwio.c
index a051037..eb01d00 100644
--- a/drivers/video/msm/mdss/mdp3_ppp_hwio.c
+++ b/drivers/video/msm/mdss/mdp3_ppp_hwio.c
@@ -354,6 +354,7 @@
 	case MDP_ARGB_8888:
 	case MDP_XRGB_8888:
 	case MDP_RGBX_8888:
+	case MDP_BGRX_8888:
 		rgb = true;
 	default:
 		break;
diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h
index dd1a95b..3bf27e2 100644
--- a/drivers/video/msm/mdss/mdss.h
+++ b/drivers/video/msm/mdss/mdss.h
@@ -68,6 +68,7 @@
 	u32 mdp_rev;
 	struct clk *mdp_clk[MDSS_MAX_CLK];
 	struct regulator *fs;
+	struct regulator *vdd_cx;
 	u32 max_mdp_clk_rate;
 
 	struct platform_device *pdev;
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 2aaa641..4ca0a3f 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -591,9 +591,6 @@
 	},
 };
 
-static int unset_bl_level, bl_updated;
-static int bl_level_old;
-
 static void mdss_fb_scale_bl(struct msm_fb_data_type *mfd, u32 *bl_lvl)
 {
 	u32 temp = *bl_lvl;
@@ -615,11 +612,11 @@
 		 * scaling fraction (x/1024)
 		 */
 		temp = (temp * mfd->bl_scale) / 1024;
-
-		/*if less than minimum level, use min level*/
-		if (temp < mfd->bl_min_lvl)
-			temp = mfd->bl_min_lvl;
 	}
+	/*if less than minimum level, use min level*/
+	else if ((temp < mfd->bl_min_lvl) && (0 != temp))
+		temp = mfd->bl_min_lvl;
+
 	pr_debug("output = %d", temp);
 
 	(*bl_lvl) = temp;
@@ -632,11 +629,15 @@
 	int (*update_ad_input)(struct msm_fb_data_type *mfd);
 	u32 temp = bkl_lvl;
 
-	if ((!mfd->panel_power_on || !bl_updated) && !IS_CALIB_MODE_BL(mfd)) {
-		unset_bl_level = bkl_lvl;
-		return;
+	if (((!mfd->panel_power_on && mfd->dcm_state != DCM_ENTER)
+		|| !mfd->bl_updated) && !IS_CALIB_MODE_BL(mfd)) {
+			if (bkl_lvl < mfd->bl_min_lvl)
+				mfd->unset_bl_level = mfd->bl_min_lvl;
+			else
+				mfd->unset_bl_level = bkl_lvl;
+			return;
 	} else {
-		unset_bl_level = 0;
+		mfd->unset_bl_level = 0;
 	}
 
 	pdata = dev_get_platdata(&mfd->pdev->dev);
@@ -652,13 +653,13 @@
 		 * as well as setting bl_level to bkl_lvl even though the
 		 * backlight has been set to the scaled value.
 		 */
-		if (bl_level_old == temp) {
+		if (mfd->bl_level_old == temp) {
 			mfd->bl_level = bkl_lvl;
 			return;
 		}
 		pdata->set_backlight(pdata, temp);
 		mfd->bl_level = bkl_lvl;
-		bl_level_old = temp;
+		mfd->bl_level_old = temp;
 
 		if (mfd->mdp.update_ad_input) {
 			update_ad_input = mfd->mdp.update_ad_input;
@@ -674,15 +675,15 @@
 {
 	struct mdss_panel_data *pdata;
 
-	if (unset_bl_level && !bl_updated) {
+	if (mfd->unset_bl_level && !mfd->bl_updated) {
 		pdata = dev_get_platdata(&mfd->pdev->dev);
 		if ((pdata) && (pdata->set_backlight)) {
 			mutex_lock(&mfd->bl_lock);
-			mfd->bl_level = unset_bl_level;
+			mfd->bl_level = mfd->unset_bl_level;
 			pdata->set_backlight(pdata, mfd->bl_level);
-			bl_level_old = unset_bl_level;
+			mfd->bl_level_old = mfd->unset_bl_level;
 			mutex_unlock(&mfd->bl_lock);
-			bl_updated = 1;
+			mfd->bl_updated = 1;
 		}
 	}
 }
@@ -729,7 +730,7 @@
 			mfd->op_enable = false;
 			curr_pwr_state = mfd->panel_power_on;
 			mfd->panel_power_on = false;
-			bl_updated = 0;
+			mfd->bl_updated = 0;
 
 			ret = mfd->mdp.off_fnc(mfd);
 			if (ret)
@@ -1190,6 +1191,12 @@
 	if (!pinfo || (pinfo->pid != pid)) {
 		pr_warn("unable to find process info for fb%d pid=%d\n",
 				mfd->index, pid);
+		if (mfd->mdp.release_fnc) {
+			ret = mfd->mdp.release_fnc(mfd);
+			if (ret)
+				pr_err("error releasing fb%d resources\n",
+						mfd->index);
+		}
 	} else {
 		pr_debug("found process entry pid=%d ref=%d\n",
 				pinfo->pid, pinfo->ref_cnt);
@@ -1712,7 +1719,7 @@
 static int mdss_fb_handle_buf_sync_ioctl(struct msm_sync_pt_data *sync_pt_data,
 				 struct mdp_buf_sync *buf_sync)
 {
-	int i, fence_cnt = 0, ret = 0;
+	int i, ret = 0;
 	int acq_fen_fd[MDP_MAX_FENCE_FD];
 	struct sync_fence *fence;
 
@@ -1739,10 +1746,9 @@
 		}
 		sync_pt_data->acq_fen[i] = fence;
 	}
-	fence_cnt = i;
+	sync_pt_data->acq_fen_cnt = i;
 	if (ret)
 		goto buf_sync_err_1;
-	sync_pt_data->acq_fen_cnt = fence_cnt;
 
 	if (buf_sync->flags & MDP_BUF_SYNC_FLAG_WAIT)
 		mdss_fb_wait_for_fence(sync_pt_data);
@@ -1793,7 +1799,7 @@
 	sync_pt_data->cur_rel_fence = NULL;
 	sync_pt_data->cur_rel_fen_fd = 0;
 buf_sync_err_1:
-	for (i = 0; i < fence_cnt; i++)
+	for (i = 0; i < sync_pt_data->acq_fen_cnt; i++)
 		sync_fence_put(sync_pt_data->acq_fen[i]);
 	sync_pt_data->acq_fen_cnt = 0;
 	mutex_unlock(&sync_pt_data->sync_mutex);
diff --git a/drivers/video/msm/mdss/mdss_fb.h b/drivers/video/msm/mdss/mdss_fb.h
index 1400bdd..256789d 100644
--- a/drivers/video/msm/mdss/mdss_fb.h
+++ b/drivers/video/msm/mdss/mdss_fb.h
@@ -140,6 +140,9 @@
 	u32 bl_level;
 	u32 bl_scale;
 	u32 bl_min_lvl;
+	u32 unset_bl_level;
+	u32 bl_updated;
+	u32 bl_level_old;
 	struct mutex bl_lock;
 	struct mutex lock;
 
diff --git a/drivers/video/msm/mdss/mdss_hdmi_cec.c b/drivers/video/msm/mdss/mdss_hdmi_cec.c
index ecde0b9..410f2b3 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_cec.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_cec.c
@@ -350,7 +350,8 @@
 			(msg->operand[i] << 8) | frame_type);
 
 	while ((DSS_REG_R(io, HDMI_CEC_STATUS) & BIT(0)) &&
-		line_check_retry--) {
+		line_check_retry) {
+		line_check_retry--;
 		DEV_DBG("%s: CEC line is busy(%d)\n", __func__,
 			line_check_retry);
 		schedule();
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index 3107e38..4a4684b 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -48,6 +48,7 @@
 #include <mach/iommu_domains.h>
 #include <mach/memory.h>
 #include <mach/msm_memtypes.h>
+#include <mach/rpm-regulator-smd.h>
 
 #include "mdss.h"
 #include "mdss_fb.h"
@@ -700,6 +701,14 @@
 	}
 	mdata->fs_ena = false;
 
+	mdata->vdd_cx = devm_regulator_get(&mdata->pdev->dev,
+				"vdd-cx");
+	if (IS_ERR_OR_NULL(mdata->vdd_cx)) {
+		pr_debug("unable to get CX reg. rc=%d\n",
+					PTR_RET(mdata->vdd_cx));
+		mdata->vdd_cx = NULL;
+	}
+
 	if (mdss_mdp_irq_clk_register(mdata, "bus_clk", MDSS_CLK_AXI) ||
 	    mdss_mdp_irq_clk_register(mdata, "iface_clk", MDSS_CLK_AHB) ||
 	    mdss_mdp_irq_clk_register(mdata, "core_clk_src",
@@ -1931,6 +1940,49 @@
 	return rc;
 }
 
+static int mdss_mdp_cx_ctrl(struct mdss_data_type *mdata, int enable)
+{
+	int rc = 0;
+
+	if (!mdata->vdd_cx)
+		return rc;
+
+	if (enable) {
+		rc = regulator_set_voltage(
+				mdata->vdd_cx,
+				RPM_REGULATOR_CORNER_SVS_SOC,
+				RPM_REGULATOR_CORNER_SUPER_TURBO);
+		if (rc < 0)
+			goto vreg_set_voltage_fail;
+
+		pr_debug("Enabling CX power rail\n");
+		rc = regulator_enable(mdata->vdd_cx);
+		if (rc) {
+			pr_err("Failed to enable regulator.\n");
+			return rc;
+		}
+	} else {
+		pr_debug("Disabling CX power rail\n");
+		rc = regulator_disable(mdata->vdd_cx);
+		if (rc) {
+			pr_err("Failed to disable regulator.\n");
+			return rc;
+		}
+		rc = regulator_set_voltage(
+				mdata->vdd_cx,
+				RPM_REGULATOR_CORNER_NONE,
+				RPM_REGULATOR_CORNER_SUPER_TURBO);
+		if (rc < 0)
+			goto vreg_set_voltage_fail;
+	}
+
+	return rc;
+
+vreg_set_voltage_fail:
+	pr_err("Set vltg fail\n");
+	return rc;
+}
+
 static void mdss_mdp_footswitch_ctrl(struct mdss_data_type *mdata, int on)
 {
 	if (!mdata->fs)
@@ -1938,14 +1990,18 @@
 
 	if (on) {
 		pr_debug("Enable MDP FS\n");
-		if (!mdata->fs_ena)
+		if (!mdata->fs_ena) {
 			regulator_enable(mdata->fs);
+			mdss_mdp_cx_ctrl(mdata, true);
+		}
 		mdata->fs_ena = true;
 	} else {
 		pr_debug("Disable MDP FS\n");
 		mdss_iommu_dettach(mdata);
-		if (mdata->fs_ena)
+		if (mdata->fs_ena) {
 			regulator_disable(mdata->fs);
+			mdss_mdp_cx_ctrl(mdata, false);
+		}
 		mdata->fs_ena = false;
 	}
 }
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index e3e4509..f527c62 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -1036,7 +1036,7 @@
 	mutex_lock(&mdp5_data->ov_lock);
 	mutex_lock(&mfd->lock);
 	list_for_each_entry(pipe, &mdp5_data->pipes_used, used_list) {
-		if (pipe->pid == pid) {
+		if (!mfd->ref_cnt || (pipe->pid == pid)) {
 			unset_ndx |= pipe->ndx;
 			cnt++;
 		}
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index 79549a1..c18fd9b 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -307,7 +307,7 @@
 static struct mdss_mdp_pipe *mdss_mdp_pipe_init(struct mdss_mdp_mixer *mixer,
 						u32 type, u32 off)
 {
-	struct mdss_mdp_pipe *pipe;
+	struct mdss_mdp_pipe *pipe = NULL;
 	struct mdss_data_type *mdata;
 	struct mdss_mdp_pipe *pipe_pool = NULL;
 	u32 npipes;
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index 64d0bca..563a4a6 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -295,6 +295,9 @@
 				struct mdp_pgc_lut_data *config);
 static void pp_update_hist_lut(char __iomem *base,
 				struct mdp_hist_lut_data *cfg);
+static int pp_gm_has_invalid_lut_size(struct mdp_gamut_cfg_data *config);
+static void pp_gamut_config(struct mdp_gamut_cfg_data *gamut_cfg,
+				u32 base, struct pp_sts_type *pp_sts);
 static void pp_pa_config(unsigned long flags, u32 base,
 				struct pp_sts_type *pp_sts,
 				struct mdp_pa_cfg *pa_config);
@@ -2038,10 +2041,32 @@
 	return 0;
 }
 
+static int pp_gm_has_invalid_lut_size(struct mdp_gamut_cfg_data *config)
+{
+	if (config->tbl_size[0] != GAMUT_T0_SIZE)
+		return -EINVAL;
+	if (config->tbl_size[1] != GAMUT_T1_SIZE)
+		return -EINVAL;
+	if (config->tbl_size[2] != GAMUT_T2_SIZE)
+		return -EINVAL;
+	if (config->tbl_size[3] != GAMUT_T3_SIZE)
+		return -EINVAL;
+	if (config->tbl_size[4] != GAMUT_T4_SIZE)
+		return -EINVAL;
+	if (config->tbl_size[5] != GAMUT_T5_SIZE)
+		return -EINVAL;
+	if (config->tbl_size[6] != GAMUT_T6_SIZE)
+		return -EINVAL;
+	if (config->tbl_size[7] != GAMUT_T7_SIZE)
+		return -EINVAL;
+
+	return 0;
+}
+
 int mdss_mdp_gamut_config(struct mdp_gamut_cfg_data *config,
 					u32 *copyback)
 {
-	int i, j, size_total = 0, ret = 0;
+	int i, j, ret = 0;
 	u32 offset, disp_num, dspp_num = 0;
 	uint16_t *tbl_off;
 	struct mdp_gamut_cfg_data local_cfg;
@@ -2053,9 +2078,8 @@
 	if ((config->block < MDP_LOGICAL_BLOCK_DISP_0) ||
 		(config->block >= MDP_BLOCK_MAX))
 		return -EINVAL;
-	for (i = 0; i < MDP_GAMUT_TABLE_NUM; i++)
-		size_total += config->tbl_size[i];
-	if (size_total != GAMUT_TOTAL_TABLE_SIZE)
+
+	if (pp_gm_has_invalid_lut_size(config))
 		return -EINVAL;
 
 	mutex_lock(&mdss_pp_mutex);
@@ -3486,12 +3510,22 @@
 int mdss_mdp_calib_config_buffer(struct mdp_calib_config_buffer *cfg,
 						u32 *copyback)
 {
-	int ret = -1;
-	int counter = cfg->size / (sizeof(uint32_t) * 2);
+	int ret = -1, counter;
 	uint32_t *buff = NULL, *buff_org = NULL;
 	void *ptr;
 	int i = 0;
 
+	if (!cfg) {
+		pr_err("Invalid buffer pointer");
+		return ret;
+	}
+
+	if (cfg->size == 0) {
+		pr_err("Invalid buffer size");
+		return ret;
+	}
+
+	counter = cfg->size / (sizeof(uint32_t) * 2);
 	buff_org = buff = kzalloc(cfg->size, GFP_KERNEL);
 	if (buff == NULL) {
 		pr_err("Allocation failed");
diff --git a/include/linux/android_alarm.h b/include/linux/android_alarm.h
index 096f777..b017caa 100644
--- a/include/linux/android_alarm.h
+++ b/include/linux/android_alarm.h
@@ -25,6 +25,7 @@
 	ANDROID_ALARM_RTC,
 	ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP,
 	ANDROID_ALARM_ELAPSED_REALTIME,
+	ANDROID_ALARM_RTC_POWEROFF_WAKEUP,
 	ANDROID_ALARM_SYSTEMTIME,
 
 	ANDROID_ALARM_TYPE_COUNT,
@@ -86,6 +87,7 @@
 				1U << ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP,
 	ANDROID_ALARM_ELAPSED_REALTIME_MASK =
 				1U << ANDROID_ALARM_ELAPSED_REALTIME,
+	ANDROID_ALARM_RTC_POWEROFF_WAKEUP_MASK = 1U << ANDROID_ALARM_RTC_POWEROFF_WAKEUP,
 	ANDROID_ALARM_SYSTEMTIME_MASK = 1U << ANDROID_ALARM_SYSTEMTIME,
 	ANDROID_ALARM_TIME_CHANGE_MASK = 1U << 16
 };
diff --git a/include/linux/bif/consumer.h b/include/linux/bif/consumer.h
index e4c190e..a4579db 100644
--- a/include/linux/bif/consumer.h
+++ b/include/linux/bif/consumer.h
@@ -311,10 +311,11 @@
  * @type:		Object type
  * @version:		Object version
  * @manufacturer_id:	Manufacturer ID number allocated by MIPI
- * @length:		Length of the entire object including header and CRC
+ * @length:		Length of the entire object including header and CRC;
+ *			data length == total length - 8.
  * @data:		Raw byte data found in the object
  * @crc:		CRC of the object calculated using CRC-CCITT
- * @list:		Linked-list connection parameter
+ * @list:		Linked-list connection parameter; internal use only
  * @addr:		BIF slave address correspond to the start of the object
  *
  * manufacturer_id == 0x0000 if MIPI type and version.
@@ -342,6 +343,8 @@
  *				is used to denote a 256 byte buffer.
  * @nvm_base_address:		BIF slave address where NVM begins
  * @nvm_size:			NVM size in bytes
+ * @nvm_lock_offset:		Offset from the beginning of NVM of the first
+ *				writable address
  * @object_count:		Number of BIF objects read from NVM
  * @object_list:		List of BIF objects read from NVM
  */
@@ -351,6 +354,7 @@
 	u8			write_buffer_size;
 	u16			nvm_base_address;
 	u16			nvm_size;
+	u16			nvm_lock_offset;
 	int			object_count;
 	struct list_head	object_list;
 };
@@ -412,6 +416,9 @@
 #define BIF_MATCH_FUNCTION_TYPE		BIT(2)
 #define BIF_MATCH_FUNCTION_VERSION	BIT(3)
 #define BIF_MATCH_IGNORE_PRESENCE	BIT(4)
+#define BIF_MATCH_OBJ_TYPE		BIT(5)
+#define BIF_MATCH_OBJ_VERSION		BIT(6)
+#define BIF_MATCH_OBJ_MANUFACTURER_ID	BIT(7)
 
 /**
  * struct bif_match_criteria - specifies the matching criteria that a BIF
@@ -428,6 +435,17 @@
  * @ignore_presence:	If true, then slaves that are currently not present
  *			will be successfully matched against.  By default, only
  *			present slaves can be matched.
+ * @obj_type:		Defines the type of a BIF object found in the
+ *			non-volatile memory of a slave.
+ * @obj_version:	Defines the version of a BIF object found in the
+ *			non-volatile memory of a slave.
+ * @obj_manufacturer_id: Manufacturer ID of a BIF object found in the
+ *			non-volatile memory of a slave.
+ *
+ * If function_type and function_verion are both specified, then they must both
+ * match for a single BIF function.  If obj_type and obj_version or
+ * obj_manufacturer_id are specified, then all must match for a single BIF
+ * object.
  */
 struct bif_match_criteria {
 	u32	match_mask;
@@ -436,6 +454,34 @@
 	u8	function_type;
 	u8	function_version;
 	bool	ignore_presence;
+	u8	obj_type;
+	u8	obj_version;
+	u16	obj_manufacturer_id;
+};
+
+/* Mask values to be ORed for use in bif_obj_match_criteria.match_mask. */
+#define BIF_OBJ_MATCH_TYPE		BIT(0)
+#define BIF_OBJ_MATCH_VERSION		BIT(1)
+#define BIF_OBJ_MATCH_MANUFACTURER_ID	BIT(2)
+
+/**
+ * struct bif_obj_match_criteria - specifies the matching criteria that a BIF
+ *			consumer uses to find an appropriate BIF data object
+ *			within a slave
+ * @match_mask:		Mask value specifying which parameters to match upon.
+ *			This value should be some ORed combination of
+ *			BIF_OBJ_MATCH_* specified above.
+ * @type:		Defines the type of the object.  The type may be either
+ *			MIPI or manufacturer defined.
+ * @version:		Defines the version of the object.  The version may be
+ *			either MIPI or manufacturer defined.
+ * @manufacturer_id:	Manufacturer ID number allocated by MIPI.
+ */
+struct bif_obj_match_criteria {
+	u32	match_mask;
+	u8	type;
+	u8	version;
+	u16	manufacturer_id;
 };
 
 /**
@@ -472,6 +518,8 @@
 			struct notifier_block *nb);
 
 int bif_trigger_task(struct bif_slave *slave, unsigned int task);
+int bif_enable_auto_task(struct bif_slave *slave, unsigned int task);
+int bif_disable_auto_task(struct bif_slave *slave, unsigned int task);
 int bif_task_is_busy(struct bif_slave *slave, unsigned int task);
 
 int bif_ctrl_count(void);
@@ -481,10 +529,10 @@
 
 int bif_ctrl_signal_battery_changed(struct bif_ctrl *ctrl);
 
-int bif_slave_match_count(const struct bif_ctrl *ctrl,
+int bif_slave_match_count(struct bif_ctrl *ctrl,
 			const struct bif_match_criteria *match_criteria);
 
-struct bif_slave *bif_slave_match_get(const struct bif_ctrl *ctrl,
+struct bif_slave *bif_slave_match_get(struct bif_ctrl *ctrl,
 	unsigned int id, const struct bif_match_criteria *match_criteria);
 
 void bif_slave_put(struct bif_slave *slave);
@@ -500,9 +548,31 @@
 int bif_slave_find_function(struct bif_slave *slave, u8 function, u8 *version,
 				u16 *function_pointer);
 
+int bif_object_match_count(struct bif_slave *slave,
+			const struct bif_obj_match_criteria *match_criteria);
+
+struct bif_object *bif_object_match_get(struct bif_slave *slave,
+	unsigned int id, const struct bif_obj_match_criteria *match_criteria);
+
+void bif_object_put(struct bif_object *object);
+
 int bif_slave_read(struct bif_slave *slave, u16 addr, u8 *buf, int len);
 int bif_slave_write(struct bif_slave *slave, u16 addr, u8 *buf, int len);
 
+int bif_slave_nvm_raw_read(struct bif_slave *slave, u16 offset, u8 *buf,
+				int len);
+int bif_slave_nvm_raw_write(struct bif_slave *slave, u16 offset, u8 *buf,
+				int len);
+
+int bif_object_write(struct bif_slave *slave, u8 type, u8 version, u16
+			manufacturer_id, const u8 *data, int data_len);
+
+int bif_object_overwrite(struct bif_slave *slave,
+	struct bif_object *object, u8 type, u8 version,
+	u16 manufacturer_id, const u8 *data, int data_len);
+
+int bif_object_delete(struct bif_slave *slave, const struct bif_object *object);
+
 int bif_slave_is_present(struct bif_slave *slave);
 
 int bif_slave_is_selected(struct bif_slave *slave);
@@ -534,6 +604,12 @@
 
 static inline int bif_trigger_task(struct bif_slave *slave, unsigned int task)
 { return -EPERM; }
+static inline int bif_enable_auto_task(struct bif_slave *slave,
+			unsigned int task)
+{ return -EPERM; }
+static inline int bif_disable_auto_task(struct bif_slave *slave,
+			unsigned int task)
+{ return -EPERM; }
 static inline int bif_task_is_busy(struct bif_slave *slave, unsigned int task)
 { return -EPERM; }
 
@@ -544,13 +620,14 @@
 { return ERR_PTR(-EPERM); }
 static inline void bif_ctrl_put(struct bif_ctrl *ctrl) { return; }
 
-int bif_ctrl_signal_battery_changed(struct bif_ctrl *ctrl) { return -EPERM; }
+static inline int bif_ctrl_signal_battery_changed(struct bif_ctrl *ctrl)
+{ return -EPERM; }
 
-static inline int bif_slave_match_count(const struct bif_ctrl *ctrl,
+static inline int bif_slave_match_count(struct bif_ctrl *ctrl,
 			const struct bif_match_criteria *match_criteria)
 { return -EPERM; }
 
-static inline struct bif_slave *bif_slave_match_get(const struct bif_ctrl *ctrl,
+static inline struct bif_slave *bif_slave_match_get(struct bif_ctrl *ctrl,
 	unsigned int id, const struct bif_match_criteria *match_criteria)
 { return ERR_PTR(-EPERM); }
 
@@ -571,6 +648,17 @@
 				u8 *version, u16 *function_pointer)
 { return -EPERM; }
 
+static inline int bif_object_match_count(struct bif_slave *slave,
+			const struct bif_obj_match_criteria *match_criteria)
+{ return -EPERM; }
+
+static inline struct bif_object *bif_object_match_get(struct bif_slave *slave,
+	unsigned int id, const struct bif_obj_match_criteria *match_criteria)
+{ return ERR_PTR(-EPERM); }
+
+static inline void bif_object_put(struct bif_object *object)
+{}
+
 static inline int bif_slave_read(struct bif_slave *slave, u16 addr, u8 *buf,
 				int len)
 { return -EPERM; }
@@ -578,18 +666,42 @@
 				int len)
 { return -EPERM; }
 
-int bif_slave_is_present(struct bif_slave *slave) { return -EPERM; }
-
-int bif_slave_is_selected(struct bif_slave *slave) { return -EPERM; }
-int bif_slave_select(struct bif_slave *slave) { return -EPERM; }
-
-int bif_ctrl_raw_transaction(struct bif_ctrl *ctrl, int transaction, u8 data)
+static inline int bif_slave_nvm_raw_read(struct bif_slave *slave, u16 offset,
+				u8 *buf, int len)
 { return -EPERM; }
-int bif_ctrl_raw_transaction_read(struct bif_ctrl *ctrl, int transaction,
-					u8 data, int *response)
+static inline int bif_slave_nvm_raw_write(struct bif_slave *slave, u16 offset,
+				u8 *buf, int len)
 { return -EPERM; }
-int bif_ctrl_raw_transaction_query(struct bif_ctrl *ctrl, int transaction,
-		u8 data, bool *query_response)
+
+static inline int bif_object_write(struct bif_slave *slave, u8 type, u8 version,
+			u16 manufacturer_id, const u8 *data, int data_len)
+{ return -EPERM; }
+
+static inline int bif_object_overwrite(struct bif_slave *slave,
+	struct bif_object *object, u8 type, u8 version,
+	u16 manufacturer_id, const u8 *data, int data_len)
+{ return -EPERM; }
+
+static inline int bif_object_delete(struct bif_slave *slave,
+		const struct bif_object *object)
+{ return -EPERM; }
+
+static inline int bif_slave_is_present(struct bif_slave *slave)
+{ return -EPERM; }
+
+static inline int bif_slave_is_selected(struct bif_slave *slave)
+{ return -EPERM; }
+static inline int bif_slave_select(struct bif_slave *slave)
+{ return -EPERM; }
+
+static inline int bif_ctrl_raw_transaction(struct bif_ctrl *ctrl,
+				int transaction, u8 data)
+{ return -EPERM; }
+static inline int bif_ctrl_raw_transaction_read(struct bif_ctrl *ctrl,
+				int transaction, u8 data, int *response)
+{ return -EPERM; }
+static inline int bif_ctrl_raw_transaction_query(struct bif_ctrl *ctrl,
+				int transaction, u8 data, bool *query_response)
 { return -EPERM; }
 
 static inline void bif_ctrl_bus_lock(struct bif_ctrl *ctrl)
@@ -601,11 +713,14 @@
 { return 0; }
 
 static inline int bif_ctrl_measure_rid(struct bif_ctrl *ctrl) { return -EPERM; }
-int bif_ctrl_get_bus_period(struct bif_ctrl *ctrl) { return -EPERM; }
-int bif_ctrl_set_bus_period(struct bif_ctrl *ctrl, int period_ns)
+static inline int bif_ctrl_get_bus_period(struct bif_ctrl *ctrl)
 { return -EPERM; }
-int bif_ctrl_get_bus_state(struct bif_ctrl *ctrl) { return -EPERM; }
-int bif_ctrl_set_bus_state(struct bif_ctrl *ctrl, enum bif_bus_state state)
+static inline int bif_ctrl_set_bus_period(struct bif_ctrl *ctrl, int period_ns)
+{ return -EPERM; }
+static inline int bif_ctrl_get_bus_state(struct bif_ctrl *ctrl)
+{ return -EPERM; }
+static inline int bif_ctrl_set_bus_state(struct bif_ctrl *ctrl,
+				enum bif_bus_state state)
 { return -EPERM; }
 
 #endif
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index fbe89e1..eba0157 100644
--- a/include/linux/clocksource.h
+++ b/include/linux/clocksource.h
@@ -206,6 +206,7 @@
 #define CLOCK_SOURCE_WATCHDOG			0x10
 #define CLOCK_SOURCE_VALID_FOR_HRES		0x20
 #define CLOCK_SOURCE_UNSTABLE			0x40
+#define CLOCK_SOURCE_SUSPEND_NONSTOP		0x80
 
 /* simplify initialization of mask field */
 #define CLOCKSOURCE_MASK(bits) (cycle_t)((bits) < 64 ? ((1ULL<<(bits))-1) : -1)
diff --git a/include/linux/mfd/wcd9xxx/pdata.h b/include/linux/mfd/wcd9xxx/pdata.h
index b7ba6fb..ffbd732 100644
--- a/include/linux/mfd/wcd9xxx/pdata.h
+++ b/include/linux/mfd/wcd9xxx/pdata.h
@@ -69,20 +69,20 @@
 #define TABLA_DCYCLE_3839 0xE
 #define TABLA_DCYCLE_4095 0xF
 
-#define TAIKO_MCLK_CLK_12P288MHZ 12288000
-#define TAIKO_MCLK_CLK_9P6HZ 9600000
+#define WCD9XXX_MCLK_CLK_12P288MHZ 12288000
+#define WCD9XXX_MCLK_CLK_9P6HZ 9600000
 
 /* Only valid for 9.6 MHz mclk */
-#define TAIKO_DMIC_SAMPLE_RATE_2P4MHZ 2400000
-#define TAIKO_DMIC_SAMPLE_RATE_3P2MHZ 3200000
-#define TAIKO_DMIC_SAMPLE_RATE_4P8MHZ 4800000
+#define WCD9XXX_DMIC_SAMPLE_RATE_2P4MHZ 2400000
+#define WCD9XXX_DMIC_SAMPLE_RATE_3P2MHZ 3200000
+#define WCD9XXX_DMIC_SAMPLE_RATE_4P8MHZ 4800000
 
 /* Only valid for 12.288 MHz mclk */
-#define TAIKO_DMIC_SAMPLE_RATE_3P072MHZ 3072000
-#define TAIKO_DMIC_SAMPLE_RATE_4P096MHZ 4096000
-#define TAIKO_DMIC_SAMPLE_RATE_6P144MHZ 6144000
+#define WCD9XXX_DMIC_SAMPLE_RATE_3P072MHZ 3072000
+#define WCD9XXX_DMIC_SAMPLE_RATE_4P096MHZ 4096000
+#define WCD9XXX_DMIC_SAMPLE_RATE_6P144MHZ 6144000
 
-#define TAIKO_DMIC_SAMPLE_RATE_UNDEFINED 0
+#define WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED 0
 
 struct wcd9xxx_amic {
 	/*legacy mode, txfe_enable and txfe_buff take 7 input
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 48268f0..a5fa304 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -302,16 +302,16 @@
  * On nommu, vmalloc/vfree wrap through kmalloc/kfree directly, so there
  * is no special casing required.
  */
+
+#ifdef CONFIG_MMU
+extern int is_vmalloc_addr(const void *x);
+#else
 static inline int is_vmalloc_addr(const void *x)
 {
-#ifdef CONFIG_MMU
-	unsigned long addr = (unsigned long)x;
-
-	return addr >= VMALLOC_START && addr < VMALLOC_END;
-#else
 	return 0;
-#endif
 }
+#endif
+
 #ifdef CONFIG_MMU
 extern int is_vmalloc_or_module_addr(const void *x);
 #else
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 5106c71..93af04d 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -103,6 +103,7 @@
 	POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION,
 	POWER_SUPPLY_PROP_CURRENT_MAX,
 	POWER_SUPPLY_PROP_INPUT_CURRENT_MAX,
+	POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM,
 	POWER_SUPPLY_PROP_CURRENT_NOW,
 	POWER_SUPPLY_PROP_CURRENT_AVG,
 	POWER_SUPPLY_PROP_POWER_NOW,
@@ -228,6 +229,7 @@
 extern int power_supply_set_battery_charged(struct power_supply *psy);
 extern int power_supply_set_current_limit(struct power_supply *psy, int limit);
 extern int power_supply_set_online(struct power_supply *psy, bool enable);
+extern int power_supply_set_health_state(struct power_supply *psy, int health);
 extern int power_supply_set_present(struct power_supply *psy, bool enable);
 extern int power_supply_set_scope(struct power_supply *psy, int scope);
 extern int power_supply_set_charge_type(struct power_supply *psy, int type);
@@ -252,6 +254,9 @@
 static inline int power_supply_set_online(struct power_supply *psy,
 							bool enable)
 							{ return -ENOSYS; }
+static inline int power_supply_set_health_state(struct power_supply *psy,
+							int health)
+							{ return -ENOSYS; }
 static inline int power_supply_set_present(struct power_supply *psy,
 							bool enable)
 							{ return -ENOSYS; }
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index f462b64..be92ca7 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -440,6 +440,7 @@
 	unsigned int host_mode;
 	unsigned int voltage_max;
 	unsigned int current_max;
+	unsigned int usbin_health;
 
 	dev_t ext_chg_dev;
 	struct cdev ext_chg_cdev;
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
index 663bc05..7675a5c 100644
--- a/include/linux/vmalloc.h
+++ b/include/linux/vmalloc.h
@@ -14,6 +14,7 @@
 #define VM_USERMAP	0x00000008	/* suitable for remap_vmalloc_range */
 #define VM_VPAGES	0x00000010	/* buffer for pages was vmalloc'ed */
 #define VM_UNLIST	0x00000020	/* vm_struct is not listed in vmlist */
+#define VM_LOWMEM	0x00000040	/* Tracking of direct mapped lowmem */
 /* bits [20..32] reserved for arch specific ioremap internals */
 
 /*
diff --git a/include/media/msmb_isp.h b/include/media/msmb_isp.h
index 23b19b5..7b0ad14 100644
--- a/include/media/msmb_isp.h
+++ b/include/media/msmb_isp.h
@@ -129,6 +129,7 @@
 struct msm_vfe_axi_stream_request_cmd {
 	uint32_t session_id;
 	uint32_t stream_id;
+	uint32_t vt_enable;
 	uint32_t output_format;/*Planar/RAW/Misc*/
 	enum msm_vfe_axi_stream_src stream_src; /*CAMIF/IDEAL/RDIs*/
 	struct msm_vfe_axi_plane_cfg plane_cfg[MAX_PLANES_PER_STREAM];
diff --git a/mm/slub.c b/mm/slub.c
index 80848cd..931c8eb 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -2310,13 +2310,18 @@
 		return NULL;
 
 redo:
-
 	/*
 	 * Must read kmem_cache cpu data via this cpu ptr. Preemption is
 	 * enabled. We may switch back and forth between cpus while
 	 * reading from one cpu area. That does not matter as long
 	 * as we end up on the original cpu again when doing the cmpxchg.
+	 *
+	 * Preemption is disabled for the retrieval of the tid because that
+	 * must occur from the current processor. We cannot allow rescheduling
+	 * on a different processor between the determination of the pointer
+	 * and the retrieval of the tid.
 	 */
+	preempt_disable();
 	c = __this_cpu_ptr(s->cpu_slab);
 
 	/*
@@ -2326,7 +2331,7 @@
 	 * linked list in between.
 	 */
 	tid = c->tid;
-	barrier();
+	preempt_enable();
 
 	object = c->freelist;
 	if (unlikely(!object || !node_match(c, node)))
@@ -2572,10 +2577,11 @@
 	 * data is retrieved via this pointer. If we are on the same cpu
 	 * during the cmpxchg then the free will succedd.
 	 */
+	preempt_disable();
 	c = __this_cpu_ptr(s->cpu_slab);
 
 	tid = c->tid;
-	barrier();
+	preempt_enable();
 
 	if (likely(page == c->page)) {
 		set_freepointer(s, object, c->freelist);
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index a2ab2ab..e174693 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -184,6 +184,36 @@
 	return ret;
 }
 
+#ifdef ENABLE_VMALLOC_SAVING
+int is_vmalloc_addr(const void *x)
+{
+	struct rb_node *n;
+	struct vmap_area *va;
+	int ret = 0;
+
+	spin_lock(&vmap_area_lock);
+
+	for (n = rb_first(vmap_area_root); n; rb_next(n)) {
+		va = rb_entry(n, struct vmap_area, rb_node);
+		if (x >= va->va_start && x < va->va_end) {
+			ret = 1;
+			break;
+		}
+	}
+
+	spin_unlock(&vmap_area_lock);
+	return ret;
+}
+#else
+int is_vmalloc_addr(const void *x)
+{
+	unsigned long addr = (unsigned long)x;
+
+	return addr >= VMALLOC_START && addr < VMALLOC_END;
+}
+#endif
+EXPORT_SYMBOL(is_vmalloc_addr);
+
 int is_vmalloc_or_module_addr(const void *x)
 {
 	/*
@@ -2643,6 +2673,9 @@
 	if (v->flags & VM_VPAGES)
 		seq_printf(m, " vpages");
 
+	if (v->flags & VM_LOWMEM)
+		seq_printf(m, " lowmem");
+
 	show_numa_info(m, v);
 	seq_putc(m, '\n');
 	return 0;
diff --git a/sound/soc/codecs/msm8x10-wcd.c b/sound/soc/codecs/msm8x10-wcd.c
index 4e3df21..4c20bb9 100644
--- a/sound/soc/codecs/msm8x10-wcd.c
+++ b/sound/soc/codecs/msm8x10-wcd.c
@@ -2424,6 +2424,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("MIC BIAS External",
+		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 |
 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
@@ -2439,9 +2444,6 @@
 	SND_SOC_DAPM_MUX("ADC2 MUX", SND_SOC_NOPM, 0, 0,
 		&tx_adc2_mux),
 
-	SND_SOC_DAPM_MICBIAS("MIC BIAS External", MSM8X10_WCD_A_MICB_1_CTL,
-			     7, 0),
-
 	SND_SOC_DAPM_INPUT("AMIC3"),
 
 	SND_SOC_DAPM_MUX_E("DEC1 MUX",
@@ -2517,8 +2519,10 @@
 	/* Enable pulldown to reduce leakage */
 	MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_MICB_1_CTL, 0x82),
 	MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_TX_COM_BIAS, 0xE0),
+	/* Keep the same default gain settings for TX paths */
 	MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_TX_1_EN, 0x32),
 	MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_TX_2_EN, 0x32),
+	MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_TX_3_EN, 0x30),
 
 	/* ClassG fine tuning setting for 16 ohm HPH */
 	MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_CDC_CLSG_FREQ_THRESH_B1_CTL, 0x05),
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
index 577c1ed..17ed0d3 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -4600,6 +4600,9 @@
 	u8 flag = pdata->amic_settings.use_pdata;
 	u8 i = 0, j = 0;
 	u8 val_txfe = 0, value = 0;
+	u8 dmic_sample_rate_value = 0;
+	u8 dmic_b1_ctl_value = 0;
+	u8 anc_ctl_value = 0;
 
 	if (!pdata) {
 		dev_err(codec->dev, "%s: NULL pdata\n", __func__);
@@ -4693,6 +4696,78 @@
 		 0x00 : 0x10);
 	snd_soc_update_bits(codec, TAPAN_A_MICB_3_CTL, 0x10, value);
 
+	/* Set the DMIC sample rate */
+	if (pdata->mclk_rate == TAPAN_MCLK_CLK_9P6MHZ) {
+		switch (pdata->dmic_sample_rate) {
+		case WCD9XXX_DMIC_SAMPLE_RATE_2P4MHZ:
+			dmic_sample_rate_value = WCD9XXX_DMIC_SAMPLE_RATE_DIV_4;
+			dmic_b1_ctl_value = WCD9XXX_DMIC_B1_CTL_DIV_4;
+			anc_ctl_value = WCD9XXX_ANC_DMIC_X2_OFF;
+			break;
+		case WCD9XXX_DMIC_SAMPLE_RATE_4P8MHZ:
+			dmic_sample_rate_value = WCD9XXX_DMIC_SAMPLE_RATE_DIV_2;
+			dmic_b1_ctl_value = WCD9XXX_DMIC_B1_CTL_DIV_2;
+			anc_ctl_value = WCD9XXX_ANC_DMIC_X2_ON;
+			break;
+		case WCD9XXX_DMIC_SAMPLE_RATE_3P2MHZ:
+		case WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED:
+			dmic_sample_rate_value = WCD9XXX_DMIC_SAMPLE_RATE_DIV_3;
+			dmic_b1_ctl_value = WCD9XXX_DMIC_B1_CTL_DIV_3;
+			anc_ctl_value = WCD9XXX_ANC_DMIC_X2_OFF;
+			break;
+		default:
+			dev_err(codec->dev,
+				"%s Invalid sample rate %d for mclk %d\n",
+				__func__, pdata->dmic_sample_rate,
+				pdata->mclk_rate);
+			rc = -EINVAL;
+			goto done;
+		}
+	} else if (pdata->mclk_rate == TAPAN_MCLK_CLK_12P288MHZ) {
+		switch (pdata->dmic_sample_rate) {
+		case WCD9XXX_DMIC_SAMPLE_RATE_3P072MHZ:
+			dmic_sample_rate_value = WCD9XXX_DMIC_SAMPLE_RATE_DIV_4;
+			dmic_b1_ctl_value = WCD9XXX_DMIC_B1_CTL_DIV_4;
+			anc_ctl_value = WCD9XXX_ANC_DMIC_X2_OFF;
+			break;
+		case WCD9XXX_DMIC_SAMPLE_RATE_6P144MHZ:
+			dmic_sample_rate_value = WCD9XXX_DMIC_SAMPLE_RATE_DIV_2;
+			dmic_b1_ctl_value = WCD9XXX_DMIC_B1_CTL_DIV_2;
+			anc_ctl_value = WCD9XXX_ANC_DMIC_X2_ON;
+			break;
+		case WCD9XXX_DMIC_SAMPLE_RATE_4P096MHZ:
+		case WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED:
+			dmic_sample_rate_value = WCD9XXX_DMIC_SAMPLE_RATE_DIV_3;
+			dmic_b1_ctl_value = WCD9XXX_DMIC_B1_CTL_DIV_3;
+			anc_ctl_value = WCD9XXX_ANC_DMIC_X2_OFF;
+			break;
+		default:
+			dev_err(codec->dev,
+				"%s Invalid sample rate %d for mclk %d\n",
+				__func__, pdata->dmic_sample_rate,
+				pdata->mclk_rate);
+			rc = -EINVAL;
+			goto done;
+		}
+	} else {
+		dev_err(codec->dev, "%s MCLK is not set!\n", __func__);
+		rc = -EINVAL;
+		goto done;
+	}
+
+	snd_soc_update_bits(codec, TAPAN_A_CDC_TX1_DMIC_CTL,
+		0x7, dmic_sample_rate_value);
+	snd_soc_update_bits(codec, TAPAN_A_CDC_TX2_DMIC_CTL,
+		0x7, dmic_sample_rate_value);
+	snd_soc_update_bits(codec, TAPAN_A_CDC_TX3_DMIC_CTL,
+		0x7, dmic_sample_rate_value);
+	snd_soc_update_bits(codec, TAPAN_A_CDC_TX4_DMIC_CTL,
+		0x7, dmic_sample_rate_value);
+	snd_soc_update_bits(codec, TAPAN_A_CDC_CLK_DMIC_B1_CTL,
+		0xEE, dmic_b1_ctl_value);
+	snd_soc_update_bits(codec, TAPAN_A_CDC_ANC1_B2_CTL,
+		0x1, anc_ctl_value);
+
 done:
 	return rc;
 }
@@ -4886,15 +4961,6 @@
 	{TAPAN_A_CDC_TX3_MUX_CTL, 0x8, 0x0},
 	{TAPAN_A_CDC_TX4_MUX_CTL, 0x8, 0x0},
 
-	/* config Decimator for DMIC CLK_MODE_1(3.2Mhz@9.6Mhz mclk) */
-	{TAPAN_A_CDC_TX1_DMIC_CTL, 0x7, 0x1},
-	{TAPAN_A_CDC_TX2_DMIC_CTL, 0x7, 0x1},
-	{TAPAN_A_CDC_TX3_DMIC_CTL, 0x7, 0x1},
-	{TAPAN_A_CDC_TX4_DMIC_CTL, 0x7, 0x1},
-
-	/* config DMIC clk to CLK_MODE_1 (3.2Mhz@9.6Mhz mclk) */
-	{TAPAN_A_CDC_CLK_DMIC_B1_CTL, 0xEE, 0x22},
-
 	/* Compander zone selection */
 	{TAPAN_A_CDC_COMP0_B4_CTL, 0x3F, 0x37},
 	{TAPAN_A_CDC_COMP1_B4_CTL, 0x3F, 0x37},
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 4ce9b4a..2beda38 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -248,21 +248,6 @@
 
 #define TAIKO_I2S_MASTER_MODE_MASK 0x08
 
-#define TAIKO_DMIC_SAMPLE_RATE_DIV_2	0x0
-#define TAIKO_DMIC_SAMPLE_RATE_DIV_3	0x1
-#define TAIKO_DMIC_SAMPLE_RATE_DIV_4	0x2
-
-#define TAIKO_DMIC_B1_CTL_DIV_2 0x00
-#define TAIKO_DMIC_B1_CTL_DIV_3 0x22
-#define TAIKO_DMIC_B1_CTL_DIV_4 0x44
-
-#define TAIKO_DMIC_B2_CTL_DIV_2 0x00
-#define TAIKO_DMIC_B2_CTL_DIV_3 0x02
-#define TAIKO_DMIC_B2_CTL_DIV_4 0x04
-
-#define TAIKO_ANC_DMIC_X2_ON	0x1
-#define TAIKO_ANC_DMIC_X2_OFF	0x0
-
 #define TAIKO_SLIM_CLOSE_TIMEOUT 1000
 #define TAIKO_SLIM_IRQ_OVERFLOW (1 << 0)
 #define TAIKO_SLIM_IRQ_UNDERFLOW (1 << 1)
@@ -5741,24 +5726,24 @@
 	/* Set the DMIC sample rate */
 	if (pdata->mclk_rate == TAIKO_MCLK_CLK_9P6MHZ) {
 		switch (pdata->dmic_sample_rate) {
-		case TAIKO_DMIC_SAMPLE_RATE_2P4MHZ:
-			dmic_sample_rate_value = TAIKO_DMIC_SAMPLE_RATE_DIV_4;
-			dmic_b1_ctl_value = TAIKO_DMIC_B1_CTL_DIV_4;
-			dmic_b2_ctl_value = TAIKO_DMIC_B2_CTL_DIV_4;
-			anc_ctl_value = TAIKO_ANC_DMIC_X2_OFF;
+		case WCD9XXX_DMIC_SAMPLE_RATE_2P4MHZ:
+			dmic_sample_rate_value = WCD9XXX_DMIC_SAMPLE_RATE_DIV_4;
+			dmic_b1_ctl_value = WCD9XXX_DMIC_B1_CTL_DIV_4;
+			dmic_b2_ctl_value = WCD9XXX_DMIC_B2_CTL_DIV_4;
+			anc_ctl_value = WCD9XXX_ANC_DMIC_X2_OFF;
 			break;
-		case TAIKO_DMIC_SAMPLE_RATE_4P8MHZ:
-			dmic_sample_rate_value = TAIKO_DMIC_SAMPLE_RATE_DIV_2;
-			dmic_b1_ctl_value = TAIKO_DMIC_B1_CTL_DIV_2;
-			dmic_b2_ctl_value = TAIKO_DMIC_B2_CTL_DIV_2;
-			anc_ctl_value = TAIKO_ANC_DMIC_X2_ON;
+		case WCD9XXX_DMIC_SAMPLE_RATE_4P8MHZ:
+			dmic_sample_rate_value = WCD9XXX_DMIC_SAMPLE_RATE_DIV_2;
+			dmic_b1_ctl_value = WCD9XXX_DMIC_B1_CTL_DIV_2;
+			dmic_b2_ctl_value = WCD9XXX_DMIC_B2_CTL_DIV_2;
+			anc_ctl_value = WCD9XXX_ANC_DMIC_X2_ON;
 			break;
-		case TAIKO_DMIC_SAMPLE_RATE_3P2MHZ:
-		case TAIKO_DMIC_SAMPLE_RATE_UNDEFINED:
-			dmic_sample_rate_value = TAIKO_DMIC_SAMPLE_RATE_DIV_3;
-			dmic_b1_ctl_value = TAIKO_DMIC_B1_CTL_DIV_3;
-			dmic_b2_ctl_value = TAIKO_DMIC_B2_CTL_DIV_3;
-			anc_ctl_value = TAIKO_ANC_DMIC_X2_OFF;
+		case WCD9XXX_DMIC_SAMPLE_RATE_3P2MHZ:
+		case WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED:
+			dmic_sample_rate_value = WCD9XXX_DMIC_SAMPLE_RATE_DIV_3;
+			dmic_b1_ctl_value = WCD9XXX_DMIC_B1_CTL_DIV_3;
+			dmic_b2_ctl_value = WCD9XXX_DMIC_B2_CTL_DIV_3;
+			anc_ctl_value = WCD9XXX_ANC_DMIC_X2_OFF;
 			break;
 		default:
 			pr_err("%s Invalid sample rate %d for mclk %d\n",
@@ -5769,24 +5754,24 @@
 		}
 	} else if (pdata->mclk_rate == TAIKO_MCLK_CLK_12P288MHZ) {
 		switch (pdata->dmic_sample_rate) {
-		case TAIKO_DMIC_SAMPLE_RATE_3P072MHZ:
-			dmic_sample_rate_value = TAIKO_DMIC_SAMPLE_RATE_DIV_4;
-			dmic_b1_ctl_value = TAIKO_DMIC_B1_CTL_DIV_4;
-			dmic_b2_ctl_value = TAIKO_DMIC_B2_CTL_DIV_4;
-			anc_ctl_value = TAIKO_ANC_DMIC_X2_OFF;
+		case WCD9XXX_DMIC_SAMPLE_RATE_3P072MHZ:
+			dmic_sample_rate_value = WCD9XXX_DMIC_SAMPLE_RATE_DIV_4;
+			dmic_b1_ctl_value = WCD9XXX_DMIC_B1_CTL_DIV_4;
+			dmic_b2_ctl_value = WCD9XXX_DMIC_B2_CTL_DIV_4;
+			anc_ctl_value = WCD9XXX_ANC_DMIC_X2_OFF;
 			break;
-		case TAIKO_DMIC_SAMPLE_RATE_6P144MHZ:
-			dmic_sample_rate_value = TAIKO_DMIC_SAMPLE_RATE_DIV_2;
-			dmic_b1_ctl_value = TAIKO_DMIC_B1_CTL_DIV_2;
-			dmic_b2_ctl_value = TAIKO_DMIC_B2_CTL_DIV_2;
-			anc_ctl_value = TAIKO_ANC_DMIC_X2_ON;
+		case WCD9XXX_DMIC_SAMPLE_RATE_6P144MHZ:
+			dmic_sample_rate_value = WCD9XXX_DMIC_SAMPLE_RATE_DIV_2;
+			dmic_b1_ctl_value = WCD9XXX_DMIC_B1_CTL_DIV_2;
+			dmic_b2_ctl_value = WCD9XXX_DMIC_B2_CTL_DIV_2;
+			anc_ctl_value = WCD9XXX_ANC_DMIC_X2_ON;
 			break;
-		case TAIKO_DMIC_SAMPLE_RATE_4P096MHZ:
-		case TAIKO_DMIC_SAMPLE_RATE_UNDEFINED:
-			dmic_sample_rate_value = TAIKO_DMIC_SAMPLE_RATE_DIV_3;
-			dmic_b1_ctl_value = TAIKO_DMIC_B1_CTL_DIV_3;
-			dmic_b2_ctl_value = TAIKO_DMIC_B2_CTL_DIV_3;
-			anc_ctl_value = TAIKO_ANC_DMIC_X2_OFF;
+		case WCD9XXX_DMIC_SAMPLE_RATE_4P096MHZ:
+		case WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED:
+			dmic_sample_rate_value = WCD9XXX_DMIC_SAMPLE_RATE_DIV_3;
+			dmic_b1_ctl_value = WCD9XXX_DMIC_B1_CTL_DIV_3;
+			dmic_b2_ctl_value = WCD9XXX_DMIC_B2_CTL_DIV_3;
+			anc_ctl_value = WCD9XXX_ANC_DMIC_X2_OFF;
 			break;
 		default:
 			pr_err("%s Invalid sample rate %d for mclk %d\n",
diff --git a/sound/soc/codecs/wcd9xxx-common.h b/sound/soc/codecs/wcd9xxx-common.h
index e63d36a..0239c86 100644
--- a/sound/soc/codecs/wcd9xxx-common.h
+++ b/sound/soc/codecs/wcd9xxx-common.h
@@ -37,6 +37,21 @@
 #define	WCD9XXX_CLSH_STATE_LO (0x01 << 3)
 #define NUM_CLSH_STATES ((0x01 << 4) - 1)
 
+#define WCD9XXX_DMIC_SAMPLE_RATE_DIV_2    0x0
+#define WCD9XXX_DMIC_SAMPLE_RATE_DIV_3    0x1
+#define WCD9XXX_DMIC_SAMPLE_RATE_DIV_4    0x2
+
+#define WCD9XXX_DMIC_B1_CTL_DIV_2 0x00
+#define WCD9XXX_DMIC_B1_CTL_DIV_3 0x22
+#define WCD9XXX_DMIC_B1_CTL_DIV_4 0x44
+
+#define WCD9XXX_DMIC_B2_CTL_DIV_2 0x00
+#define WCD9XXX_DMIC_B2_CTL_DIV_3 0x02
+#define WCD9XXX_DMIC_B2_CTL_DIV_4 0x04
+
+#define WCD9XXX_ANC_DMIC_X2_ON    0x1
+#define WCD9XXX_ANC_DMIC_X2_OFF   0x0
+
 /* Derived State: Bits 1 and 2 should be set for Headphone stereo */
 #define WCD9XXX_CLSH_STATE_HPH_ST (WCD9XXX_CLSH_STATE_HPHL | \
 						WCD9XXX_CLSH_STATE_HPHR)
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index 88f46fa..eea4316 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -2850,6 +2850,10 @@
 		/* cancel detect plug */
 		wcd9xxx_cancel_hs_detect_plug(mbhc,
 					      &mbhc->correct_plug_swch);
+		if ((mbhc->current_plug != PLUG_TYPE_NONE) &&
+		    !(snd_soc_read(codec, WCD9XXX_A_MBHC_INSERT_DETECT) &
+				   (1 << 1)))
+			goto exit;
 
 		/* Disable Mic Bias pull down and HPH Switch to GND */
 		snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.ctl_reg, 0x01,
@@ -2902,7 +2906,7 @@
 			wcd9xxx_turn_onoff_override(mbhc, false);
 		}
 	}
-
+exit:
 	mbhc->in_swch_irq_handler = false;
 	WCD9XXX_BCL_UNLOCK(mbhc->resmgr);
 	pr_debug("%s: leave\n", __func__);
diff --git a/sound/soc/msm/msm-pcm-voip.c b/sound/soc/msm/msm-pcm-voip.c
index 22bc9e1..470f44e 100644
--- a/sound/soc/msm/msm-pcm-voip.c
+++ b/sound/soc/msm/msm-pcm-voip.c
@@ -721,6 +721,7 @@
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct voip_drv_info *prtd = runtime->private_data;
 	unsigned long dsp_flags;
+	int size;
 
 	count = frames_to_bytes(runtime, frames);
 
@@ -739,14 +740,19 @@
 					struct voip_buf_node, list);
 			list_del(&buf_node->list);
 			spin_unlock_irqrestore(&prtd->dsp_ul_lock, dsp_flags);
-			if (prtd->mode == MODE_PCM)
+			if (prtd->mode == MODE_PCM) {
 				ret = copy_to_user(buf,
 						   &buf_node->frame.voc_pkt,
-						   count);
-			else
+						   buf_node->frame.len);
+			} else {
+				size = sizeof(buf_node->frame.header) +
+				       sizeof(buf_node->frame.len) +
+				       buf_node->frame.len;
+
 				ret = copy_to_user(buf,
 						   &buf_node->frame,
-						   count);
+						   size;
+			}
 			if (ret) {
 				pr_err("%s: Copy to user retuned %d\n",
 					__func__, ret);
diff --git a/sound/soc/msm/msm8226.c b/sound/soc/msm/msm8226.c
index d1ddfae..40de65b 100644
--- a/sound/soc/msm/msm8226.c
+++ b/sound/soc/msm/msm8226.c
@@ -939,21 +939,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] = 12;
diff --git a/sound/soc/msm/qdsp6v2/audio_acdb.c b/sound/soc/msm/qdsp6v2/audio_acdb.c
index 9a2d4d3..93defcd 100644
--- a/sound/soc/msm/qdsp6v2/audio_acdb.c
+++ b/sound/soc/msm/qdsp6v2/audio_acdb.c
@@ -401,7 +401,7 @@
 		delay = &acdb_data.hw_delay_tx;
 
 	if ((delay == NULL) || ((delay != NULL) && delay->num_entries == 0)) {
-		pr_err("ACDB=> %s Invalid delay/ delay entries\n", __func__);
+		pr_debug("ACDB=> %s Invalid delay/ delay entries\n", __func__);
 		result = -EINVAL;
 		goto done;
 	}
@@ -455,7 +455,7 @@
 	}
 	if ((delay.num_entries <= 0) ||
 		(delay.num_entries > MAX_HW_DELAY_ENTRIES)) {
-		pr_err("ACDB=> %s incorrect no of hw delay entries: %d\n",
+		pr_debug("ACDB=> %s incorrect no of hw delay entries: %d\n",
 		       __func__, delay.num_entries);
 		result = -EINVAL;
 		goto done;
@@ -1120,8 +1120,12 @@
 	atomic_set(&acdb_data.valid_asm_custom_top, 1);
 	atomic_inc(&usage_count);
 
+	return result;
+}
+
+static void allocate_hw_delay_entries(void)
+{
 	/* Allocate memory for hw delay entries */
-	mutex_lock(&acdb_data.acdb_mutex);
 	acdb_data.hw_delay_rx.num_entries = 0;
 	acdb_data.hw_delay_tx.num_entries = 0;
 	acdb_data.hw_delay_rx.delay_info =
@@ -1140,9 +1144,6 @@
 		pr_err("%s : Failed to allocate av sync delay entries tx\n",
 			__func__);
 	}
-	mutex_unlock(&acdb_data.acdb_mutex);
-
-	return result;
 }
 
 static int unmap_cal_tables(void)
@@ -1194,15 +1195,17 @@
 	int	i;
 	pr_debug("%s\n", __func__);
 
+	mutex_lock(&acdb_data.acdb_mutex);
+	kfree(acdb_data.hw_delay_tx.delay_info);
+	kfree(acdb_data.hw_delay_rx.delay_info);
+
 	if (atomic64_read(&acdb_data.mem_len)) {
-		mutex_lock(&acdb_data.acdb_mutex);
 		/* unmap all cal data */
 		result = unmap_cal_tables();
 		if (result < 0)
 			pr_err("%s: unmap_cal_tables failed, err = %d\n",
 				__func__, result);
 
-
 		atomic64_set(&acdb_data.mem_len, 0);
 
 		for (i = 0; i < MAX_VOCPROC_TYPES; i++) {
@@ -1214,7 +1217,8 @@
 		acdb_data.ion_handle = NULL;
 		mutex_unlock(&acdb_data.acdb_mutex);
 	}
-	return result;
+	mutex_unlock(&acdb_data.acdb_mutex);
+	return 0;
 }
 
 static int register_memory(void)
@@ -1228,6 +1232,7 @@
 	pr_debug("%s\n", __func__);
 
 	mutex_lock(&acdb_data.acdb_mutex);
+	allocate_hw_delay_entries();
 	for (i = 0; i < MAX_VOCPROC_TYPES; i++) {
 		acdb_data.col_data[i] = kmalloc(MAX_COL_SIZE, GFP_KERNEL);
 		atomic_set(&acdb_data.vocproc_col_cal[i].cal_kvaddr,
@@ -1543,9 +1548,6 @@
 	else
 		result = deregister_memory();
 
-	kfree(acdb_data.hw_delay_rx.delay_info);
-	kfree(acdb_data.hw_delay_tx.delay_info);
-
 	return result;
 }
 
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index f6ea266..1b4fae9 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -1640,6 +1640,9 @@
 	SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
 	MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
+	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 	SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
 	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
@@ -1652,6 +1655,9 @@
 	SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_VOICE2_PLAYBACK_TX,
 	MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_VOICE2_PLAYBACK_TX,
+	MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 	SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_VOICE2_PLAYBACK_TX,
 	MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
@@ -1883,6 +1889,21 @@
 	SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_PRI_MI2S_TX,
 	MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_INT_FM_TX,
+	MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_INT_BT_SCO_TX,
+	MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("AFE_PCM_TX", MSM_BACKEND_DAI_AFE_PCM_TX,
+	MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("VOC_REC_DL", MSM_BACKEND_DAI_INCALL_RECORD_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
+	SOC_SINGLE_EXT("VOC_REC_UL", MSM_BACKEND_DAI_INCALL_RECORD_TX,
+	MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new mmul5_mixer_controls[] = {
@@ -3265,10 +3286,12 @@
 		/* incall */
 	{"Incall_Music Audio Mixer", "MultiMedia1", "MM_DL1"},
 	{"Incall_Music Audio Mixer", "MultiMedia2", "MM_DL2"},
+	{"Incall_Music Audio Mixer", "MultiMedia5", "MM_DL5"},
 	{"Incall_Music Audio Mixer", "MultiMedia9", "MM_DL9"},
 	{"VOICE_PLAYBACK_TX", NULL, "Incall_Music Audio Mixer"},
 	{"Incall_Music_2 Audio Mixer", "MultiMedia1", "MM_DL1"},
 	{"Incall_Music_2 Audio Mixer", "MultiMedia2", "MM_DL2"},
+	{"Incall_Music_2 Audio Mixer", "MultiMedia5", "MM_DL5"},
 	{"Incall_Music_2 Audio Mixer", "MultiMedia9", "MM_DL9"},
 	{"VOICE2_PLAYBACK_TX", NULL, "Incall_Music_2 Audio Mixer"},
 	{"SLIMBUS_4_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
@@ -3276,7 +3299,9 @@
 	{"SLIMBUS_4_RX", NULL, "SLIMBUS_4_RX Audio Mixer"},
 
 	{"MultiMedia1 Mixer", "VOC_REC_UL", "INCALL_RECORD_TX"},
+	{"MultiMedia4 Mixer", "VOC_REC_UL", "INCALL_RECORD_TX"},
 	{"MultiMedia1 Mixer", "VOC_REC_DL", "INCALL_RECORD_RX"},
+	{"MultiMedia4 Mixer", "VOC_REC_DL", "INCALL_RECORD_RX"},
 	{"MultiMedia1 Mixer", "SLIM_4_TX", "SLIMBUS_4_TX"},
 	{"MultiMedia4 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
 	{"MultiMedia4 Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"},
@@ -3371,11 +3396,14 @@
 	{"PCM_RX", NULL, "AFE_PCM_RX Audio Mixer"},
 
 	{"MultiMedia1 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
+	{"MultiMedia4 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
 	{"MultiMedia5 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
 	{"MultiMedia1 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
+	{"MultiMedia4 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
 	{"MultiMedia5 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
 
 	{"MultiMedia1 Mixer", "AFE_PCM_TX", "PCM_TX"},
+	{"MultiMedia4 Mixer", "AFE_PCM_TX", "PCM_TX"},
 	{"MultiMedia5 Mixer", "AFE_PCM_TX", "PCM_TX"},
 	{"MM_UL1", NULL, "MultiMedia1 Mixer"},
 	{"MultiMedia2 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
index 6cfc2ef..af25454 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
@@ -615,6 +615,7 @@
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct voip_drv_info *prtd = runtime->private_data;
 	unsigned long dsp_flags;
+	int size;
 
 	count = frames_to_bytes(runtime, frames);
 
@@ -633,14 +634,19 @@
 					struct voip_buf_node, list);
 			list_del(&buf_node->list);
 			spin_unlock_irqrestore(&prtd->dsp_ul_lock, dsp_flags);
-			if (prtd->mode == MODE_PCM)
+			if (prtd->mode == MODE_PCM) {
 				ret = copy_to_user(buf,
 						   &buf_node->frame.voc_pkt,
-						   count);
-			else
+						   buf_node->frame.pktlen);
+			} else {
+				size = sizeof(buf_node->frame.frm_hdr) +
+				       sizeof(buf_node->frame.pktlen) +
+				       buf_node->frame.pktlen;
+
 				ret = copy_to_user(buf,
 						   &buf_node->frame,
-						   count);
+						   size);
+			}
 			if (ret) {
 				pr_err("%s: Copy to user retuned %d\n",
 					__func__, ret);