Merge "defconfig: msm8610: Use correct csi and ispif version"
diff --git a/Documentation/devicetree/bindings/arm/msm/rpm-rbcpr-stats.txt b/Documentation/devicetree/bindings/arm/msm/rpm-rbcpr-stats.txt
new file mode 100644
index 0000000..9b69037
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/rpm-rbcpr-stats.txt
@@ -0,0 +1,26 @@
+* RPM RBCPR
+
+The RBCPR(Rapid Bridge Core Power Reduction) is  module on RPM that controls
+the voltage level on the chip based on feedback received through various
+sensors on the chip that allow compensation of the chip process variation,
+temperature etc.
+RPM maintains RBCPR (Rapid Bridge Core Power Reduction) related stats in
+data memory. This module allows users to read those stats.
+
+The required properties for rpm-stats are:
+
+- compatible: "qcom,rpmrbcpr-stats"
+- reg: Pointer to the start of the RPM Data Memory. The size of the memory
+		is inclusive of the entire RPM data memory.
+- qcom,start_offset: The offset at which the RBCPR stats are maintained. The
+			driver module reads this parameter to get another offset
+			that contain the rbcpr stats.
+
+
+Example:
+
+qcom,rpm-rbcpr-stats@fc000000 {
+	compatible = "qcom,rpmrbcpr-stats";
+	reg = <0xfc000000 0x1a0000>;
+	qcom,start-offset = <0x190010>;
+};
diff --git a/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt b/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt
index adb93b8..3095b0a 100644
--- a/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt
+++ b/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt
@@ -12,11 +12,11 @@
 - reg:		Specifies the SPMI address and size for this PON (power-on) peripheral
 - interrupts:	Specifies the interrupt associated with PON.
 - interrupt-names:	Specify the interrupt names associated with interrupts. Must be
-			one of "kpdpwr", "kpdpwr-bark", "resin", "resin-bark", "cblpwr".
-			Bark interrupts are associated with system reset configuration
-			to allow default reset configuration to be activated. If system
-			reset configuration is not supported then bark interrupts are
-			nops.
+			one of "kpdpwr", "kpdpwr-bark", "resin", "resin-bark", "cblpwr",
+			"kpdpwr-resin-bark". Bark interrupts are associated with system
+			reset configuration to allow default reset configuration to be
+			activated. If system reset configuration is not supported then
+			bark interrupts are nops.
 
 Optional properties:
 - qcom,pon-dbc-delay		The debounce delay for the power-key interrupt
@@ -34,6 +34,8 @@
 				to reset the system. This property can only be
 				used by one device on the system. It is an error
 				to include it more than once.
+- qcom,s3-debounce		The debounce delay for stage3 reset trigger in
+				secs. The values range from 0 to 128.
 
 All the below properties are in the sub-node section (properties of the child
 node).
@@ -82,9 +84,13 @@
 		reg = <0x800 0x100>;
 		interrupts = <0x0 0x8 0x0>,
 			     <0x0 0x8 0x1>,
-			     <0x0 0x8 0x4>;
-		interrupt-names = "kpdpwr", "resin", "resin-bark";
+			     <0x0 0x8 0x4>,
+			     <0x0 0x8 0x5>;
+		interrupt-names = "kpdpwr", "resin",
+				"resin-bark", "kpdpwr-resin-bark";
 		qcom,pon-dbc-delay = <15625>;
+		qcom,system-reset;
+		qcom,s3-debounce = <32>;
 
 		qcom,pon_1 {
 			qcom,pon-type = <0>;
@@ -96,9 +102,18 @@
 			qcom,pon-type = <1>;
 			qcom,support-reset = <1>;
 			qcom,pull-up = <1>;
-			qcom,s1-timer = <3072>;
+			qcom,s1-timer = <0>;
 			qcom,s2-timer = <2000>;
 			qcom,s2-type = <1>;
 			linux,code = <114>;
 		};
-	}
+
+		qcom,pon_3 {
+			qcom,pon-type = <3>;
+			qcom,support-reset = <1>;
+			qcom,s1-timer = <6720>;
+			qcom,s2-timer = <2000>;
+			qcom,s2-type = <7>;
+			qcom,pull-up = <1>;
+		};
+	};
diff --git a/arch/arm/boot/dts/dsi-panel-nt35596-1080p-video.dtsi b/arch/arm/boot/dts/dsi-panel-nt35596-1080p-video.dtsi
new file mode 100644
index 0000000..1ecad71
--- /dev/null
+++ b/arch/arm/boot/dts/dsi-panel-nt35596-1080p-video.dtsi
@@ -0,0 +1,580 @@
+/* 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.
+ */
+
+&soc {
+	qcom,mdss_dsi_nt35596_1080p_video {
+		compatible = "qcom,mdss-dsi-panel";
+		label = "nt35596 1080p video mode dsi panel";
+		status = "disable";
+		qcom,dsi-ctrl-phandle = <&mdss_dsi0>;
+		qcom,rst-gpio = <&msmgpio 25 0>;
+		qcom,mdss-pan-res = <1080 1920>;
+		qcom,mdss-pan-bpp = <24>;
+		qcom,mdss-pan-dest = "display_1";
+		qcom,mdss-pan-porch-values = <32 8 32 18 2 2>;
+		qcom,mdss-pan-underflow-clr = <0xff>;
+		qcom,mdss-pan-bl-ctrl = "bl_ctrl_wled";
+		qcom,mdss-pan-bl-levels = <1 4095>;
+		qcom,mdss-pan-dsi-mode = <0>;
+		qcom,mdss-pan-dsi-h-pulse-mode = <1>;
+		qcom,mdss-pan-dsi-h-power-stop = <0 0 0>;
+		qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
+		qcom,mdss-pan-dsi-traffic-mode = <2>;
+		qcom,mdss-pan-dsi-dst-format = <3>;
+		qcom,mdss-pan-dsi-vc = <0>;
+		qcom,mdss-pan-dsi-rgb-swap = <0>;
+		qcom,mdss-pan-dsi-data-lanes = <1 1 1 1>; /* 4 lanes */
+		qcom,mdss-pan-dsi-dlane-swap = <0>;
+		qcom,mdss-pan-dsi-t-clk = <0x38 0x1e>;
+		qcom,mdss-pan-dsi-stream = <0>;
+		qcom,mdss-pan-dsi-mdp-tr = <0x0>;
+		qcom,mdss-pan-dsi-dma-tr = <0x04>;
+		qcom,mdss-pan-dsi-frame-rate = <60>;
+		qcom,panel-phy-regulatorSettings = [07 09 03 00  /* Regualotor settings */
+						    20 00 01];
+		qcom,panel-phy-timingSettings = [f9 3d 34 00 58 4d
+						    36 3f 53 03 04 00];
+		qcom,panel-phy-strengthCtrl = [ff 06];
+		qcom,panel-phy-bistCtrl = [00 00 b1 ff           /* BIST Ctrl settings */
+					   00 00];
+		qcom,panel-phy-laneConfig = [00 00 00 00 00 00 00 01 97 /* lane0 config */
+					     00 00 00 00 05 00 00 01 97 /* lane1 config */
+					     00 00 00 00 0a 00 00 01 97 /* lane2 config */
+					     00 00 00 00 0f 00 00 01 97 /* lane3 config */
+					     00 c0 00 00 00 00 00 01 bb]; /* Clk ln config */
+		qcom,panel-on-cmds = [29 01 00 00 00 00 02 FF EE
+			29 01 00 00 00 00 02 FB 01
+			29 01 00 00 00 00 02 1F 45
+			29 01 00 00 00 00 02 24 4F
+			29 01 00 00 00 00 02 38 C8
+			29 01 00 00 00 00 02 39 2C
+			29 01 00 00 00 00 02 1E BB
+			29 01 00 00 00 00 02 1D 0F
+			29 01 00 00 00 00 02 7E B1
+			29 01 00 00 00 00 02 FF 00
+			29 01 00 00 00 00 02 FB 01
+			29 01 00 00 00 00 02 35 01
+			29 01 00 00 00 00 02 BA 03
+			29 01 00 00 00 00 02 FF 01
+			29 01 00 00 00 00 02 FB 01
+			29 01 00 00 00 00 02 00 01
+			29 01 00 00 00 00 02 01 55
+			29 01 00 00 00 00 02 02 40
+			29 01 00 00 00 00 02 05 00
+			29 01 00 00 00 00 02 06 1B
+			29 01 00 00 00 00 02 07 24
+			29 01 00 00 00 00 02 08 0C
+			29 01 00 00 00 00 02 0B 87
+			29 01 00 00 00 00 02 0C 87
+			29 01 00 00 00 00 02 0E B0
+			29 01 00 00 00 00 02 0F B3
+			29 01 00 00 00 00 02 11 10
+			29 01 00 00 00 00 02 12 10
+			29 01 00 00 00 00 02 13 05
+			29 01 00 00 00 00 02 14 4A
+			29 01 00 00 00 00 02 15 18
+			29 01 00 00 00 00 02 16 18
+			29 01 00 00 00 00 02 18 00
+			29 01 00 00 00 00 02 19 77
+			29 01 00 00 00 00 02 1A 55
+			29 01 00 00 00 00 02 1B 13
+			29 01 00 00 00 00 02 1C 00
+			29 01 00 00 00 00 02 1D 00
+			29 01 00 00 00 00 02 1E 13
+			29 01 00 00 00 00 02 1F 00
+			29 01 00 00 00 00 02 23 00
+			29 01 00 00 00 00 02 24 00
+			29 01 00 00 00 00 02 25 00
+			29 01 00 00 00 00 02 26 00
+			29 01 00 00 00 00 02 27 00
+			29 01 00 00 00 00 02 28 00
+			29 01 00 00 00 00 02 35 00
+			29 01 00 00 00 00 02 66 00
+			29 01 00 00 00 00 02 58 82
+			29 01 00 00 00 00 02 59 02
+			29 01 00 00 00 00 02 5A 02
+			29 01 00 00 00 00 02 5B 02
+			29 01 00 00 00 00 02 5C 82
+			29 01 00 00 00 00 02 5D 82
+			29 01 00 00 00 00 02 5E 02
+			29 01 00 00 00 00 02 5F 02
+			29 01 00 00 00 00 02 72 31
+			29 01 00 00 00 00 02 FF 05
+			29 01 00 00 00 00 02 FB 01
+			29 01 00 00 00 00 02 00 01
+			29 01 00 00 00 00 02 01 0B
+			29 01 00 00 00 00 02 02 0C
+			29 01 00 00 00 00 02 03 09
+			29 01 00 00 00 00 02 04 0A
+			29 01 00 00 00 00 02 05 00
+			29 01 00 00 00 00 02 06 0F
+			29 01 00 00 00 00 02 07 10
+			29 01 00 00 00 00 02 08 00
+			29 01 00 00 00 00 02 09 00
+			29 01 00 00 00 00 02 0A 00
+			29 01 00 00 00 00 02 0B 00
+			29 01 00 00 00 00 02 0C 00
+			29 01 00 00 00 00 02 0D 13
+			29 01 00 00 00 00 02 0E 15
+			29 01 00 00 00 00 02 0F 17
+			29 01 00 00 00 00 02 10 01
+			29 01 00 00 00 00 02 11 0B
+			29 01 00 00 00 00 02 12 0C
+			29 01 00 00 00 00 02 13 09
+			29 01 00 00 00 00 02 14 0A
+			29 01 00 00 00 00 02 15 00
+			29 01 00 00 00 00 02 16 0F
+			29 01 00 00 00 00 02 17 10
+			29 01 00 00 00 00 02 18 00
+			29 01 00 00 00 00 02 19 00
+			29 01 00 00 00 00 02 1A 00
+			29 01 00 00 00 00 02 1B 00
+			29 01 00 00 00 00 02 1C 00
+			29 01 00 00 00 00 02 1D 13
+			29 01 00 00 00 00 02 1E 15
+			29 01 00 00 00 00 02 1F 17
+			29 01 00 00 00 00 02 20 00
+			29 01 00 00 00 00 02 21 03
+			29 01 00 00 00 00 02 22 01
+			29 01 00 00 00 00 02 23 40
+			29 01 00 00 00 00 02 24 40
+			29 01 00 00 00 00 02 25 ED
+			29 01 00 00 00 00 02 29 58
+			29 01 00 00 00 00 02 2A 12
+			29 01 00 00 00 00 02 2B 01
+			29 01 00 00 00 00 02 4B 06
+			29 01 00 00 00 00 02 4C 11
+			29 01 00 00 00 00 02 4D 20
+			29 01 00 00 00 00 02 4E 02
+			29 01 00 00 00 00 02 4F 02
+			29 01 00 00 00 00 02 50 20
+			29 01 00 00 00 00 02 51 61
+			29 01 00 00 00 00 02 52 01
+			29 01 00 00 00 00 02 53 63
+			29 01 00 00 00 00 02 54 77
+			29 01 00 00 00 00 02 55 ED
+			29 01 00 00 00 00 02 5B 00
+			29 01 00 00 00 00 02 5C 00
+			29 01 00 00 00 00 02 5D 00
+			29 01 00 00 00 00 02 5E 00
+			29 01 00 00 00 00 02 5F 15
+			29 01 00 00 00 00 02 60 75
+			29 01 00 00 00 00 02 61 00
+			29 01 00 00 00 00 02 62 00
+			29 01 00 00 00 00 02 63 00
+			29 01 00 00 00 00 02 64 00
+			29 01 00 00 00 00 02 65 00
+			29 01 00 00 00 00 02 66 00
+			29 01 00 00 00 00 02 67 00
+			29 01 00 00 00 00 02 68 04
+			29 01 00 00 00 00 02 69 00
+			29 01 00 00 00 00 02 6A 00
+			29 01 00 00 00 00 02 6C 40
+			29 01 00 00 00 00 02 75 01
+			29 01 00 00 00 00 02 76 01
+			29 01 00 00 00 00 02 7A 80
+			29 01 00 00 00 00 02 7B C5
+			29 01 00 00 00 00 02 7C D8
+			29 01 00 00 00 00 02 7D 60
+			29 01 00 00 00 00 02 7F 10
+			29 01 00 00 00 00 02 80 81
+			29 01 00 00 00 00 02 83 05
+			29 01 00 00 00 00 02 93 08
+			29 01 00 00 00 00 02 94 10
+			29 01 00 00 00 00 02 8A 00
+			29 01 00 00 00 00 02 9B 0F
+			29 01 00 00 00 00 02 EA FF
+			29 01 00 00 00 00 02 EC 00
+			29 01 00 00 00 00 02 FF 01
+			29 01 00 00 00 00 02 FB 01
+			29 01 00 00 00 00 02 75 00
+			29 01 00 00 00 00 02 76 8E
+			29 01 00 00 00 00 02 77 00
+			29 01 00 00 00 00 02 78 90
+			29 01 00 00 00 00 02 79 00
+			29 01 00 00 00 00 02 7A B2
+			29 01 00 00 00 00 02 7B 00
+			29 01 00 00 00 00 02 7C C7
+			29 01 00 00 00 00 02 7D 00
+			29 01 00 00 00 00 02 7E D7
+			29 01 00 00 00 00 02 7F 00
+			29 01 00 00 00 00 02 80 E9
+			29 01 00 00 00 00 02 81 00
+			29 01 00 00 00 00 02 82 F9
+			29 01 00 00 00 00 02 83 01
+			29 01 00 00 00 00 02 84 01
+			29 01 00 00 00 00 02 85 01
+			29 01 00 00 00 00 02 86 0B
+			29 01 00 00 00 00 02 87 01
+			29 01 00 00 00 00 02 88 3A
+			29 01 00 00 00 00 02 89 01
+			29 01 00 00 00 00 02 8A 5D
+			29 01 00 00 00 00 02 8B 01
+			29 01 00 00 00 00 02 8C 94
+			29 01 00 00 00 00 02 8D 01
+			29 01 00 00 00 00 02 8E BC
+			29 01 00 00 00 00 02 8F 02
+			29 01 00 00 00 00 02 90 00
+			29 01 00 00 00 00 02 91 02
+			29 01 00 00 00 00 02 92 39
+			29 01 00 00 00 00 02 93 02
+			29 01 00 00 00 00 02 94 3A
+			29 01 00 00 00 00 02 95 02
+			29 01 00 00 00 00 02 96 6B
+			29 01 00 00 00 00 02 97 02
+			29 01 00 00 00 00 02 98 A2
+			29 01 00 00 00 00 02 99 02
+			29 01 00 00 00 00 02 9A C7
+			29 01 00 00 00 00 02 9B 02
+			29 01 00 00 00 00 02 9C FB
+			29 01 00 00 00 00 02 9D 03
+			29 01 00 00 00 00 02 9E 20
+			29 01 00 00 00 00 02 9F 03
+			29 01 00 00 00 00 02 A0 54
+			29 01 00 00 00 00 02 A2 03
+			29 01 00 00 00 00 02 A3 6D
+			29 01 00 00 00 00 02 A4 03
+			29 01 00 00 00 00 02 A5 80
+			29 01 00 00 00 00 02 A6 03
+			29 01 00 00 00 00 02 A7 81
+			29 01 00 00 00 00 02 A9 03
+			29 01 00 00 00 00 02 AA C7
+			29 01 00 00 00 00 02 AB 03
+			29 01 00 00 00 00 02 AC F0
+			29 01 00 00 00 00 02 AD 03
+			29 01 00 00 00 00 02 AE F8
+			29 01 00 00 00 00 02 AF 03
+			29 01 00 00 00 00 02 B0 FD
+			29 01 00 00 00 00 02 B1 03
+			29 01 00 00 00 00 02 B2 FE
+			29 01 00 00 00 00 02 B3 00
+			29 01 00 00 00 00 02 B4 8E
+			29 01 00 00 00 00 02 B5 00
+			29 01 00 00 00 00 02 B6 90
+			29 01 00 00 00 00 02 B7 00
+			29 01 00 00 00 00 02 B8 B2
+			29 01 00 00 00 00 02 B9 00
+			29 01 00 00 00 00 02 BA C7
+			29 01 00 00 00 00 02 BB 00
+			29 01 00 00 00 00 02 BC D7
+			29 01 00 00 00 00 02 BD 00
+			29 01 00 00 00 00 02 BE E9
+			29 01 00 00 00 00 02 BF 00
+			29 01 00 00 00 00 02 C0 F9
+			29 01 00 00 00 00 02 C1 01
+			29 01 00 00 00 00 02 C2 01
+			29 01 00 00 00 00 02 C3 01
+			29 01 00 00 00 00 02 C4 0B
+			29 01 00 00 00 00 02 C5 01
+			29 01 00 00 00 00 02 C6 3A
+			29 01 00 00 00 00 02 C7 01
+			29 01 00 00 00 00 02 C8 5D
+			29 01 00 00 00 00 02 C9 01
+			29 01 00 00 00 00 02 CA 94
+			29 01 00 00 00 00 02 CB 01
+			29 01 00 00 00 00 02 CC BC
+			29 01 00 00 00 00 02 CD 02
+			29 01 00 00 00 00 02 CE 00
+			29 01 00 00 00 00 02 CF 02
+			29 01 00 00 00 00 02 D0 39
+			29 01 00 00 00 00 02 D1 02
+			29 01 00 00 00 00 02 D2 3A
+			29 01 00 00 00 00 02 D3 02
+			29 01 00 00 00 00 02 D4 6B
+			29 01 00 00 00 00 02 D5 02
+			29 01 00 00 00 00 02 D6 A2
+			29 01 00 00 00 00 02 D7 02
+			29 01 00 00 00 00 02 D8 C7
+			29 01 00 00 00 00 02 D9 02
+			29 01 00 00 00 00 02 DA FB
+			29 01 00 00 00 00 02 DB 03
+			29 01 00 00 00 00 02 DC 20
+			29 01 00 00 00 00 02 DD 03
+			29 01 00 00 00 00 02 DE 54
+			29 01 00 00 00 00 02 DF 03
+			29 01 00 00 00 00 02 E0 6D
+			29 01 00 00 00 00 02 E1 03
+			29 01 00 00 00 00 02 E2 80
+			29 01 00 00 00 00 02 E3 03
+			29 01 00 00 00 00 02 E4 81
+			29 01 00 00 00 00 02 E5 03
+			29 01 00 00 00 00 02 E6 C7
+			29 01 00 00 00 00 02 E7 03
+			29 01 00 00 00 00 02 E8 F0
+			29 01 00 00 00 00 02 E9 03
+			29 01 00 00 00 00 02 EA F8
+			29 01 00 00 00 00 02 EB 03
+			29 01 00 00 00 00 02 EC FD
+			29 01 00 00 00 00 02 ED 03
+			29 01 00 00 00 00 02 EE FE
+			29 01 00 00 00 00 02 EF 00
+			29 01 00 00 00 00 02 F0 03
+			29 01 00 00 00 00 02 F1 00
+			29 01 00 00 00 00 02 F2 0B
+			29 01 00 00 00 00 02 F3 00
+			29 01 00 00 00 00 02 F4 0D
+			29 01 00 00 00 00 02 F5 00
+			29 01 00 00 00 00 02 F6 4A
+			29 01 00 00 00 00 02 F7 00
+			29 01 00 00 00 00 02 F8 71
+			29 01 00 00 00 00 02 F9 00
+			29 01 00 00 00 00 02 FA 8C
+			29 01 00 00 00 00 02 FF 02
+			29 01 00 00 00 00 02 FB 01
+			29 01 00 00 00 00 02 00 00
+			29 01 00 00 00 00 02 01 A1
+			29 01 00 00 00 00 02 02 00
+			29 01 00 00 00 00 02 03 B6
+			29 01 00 00 00 00 02 04 00
+			29 01 00 00 00 00 02 05 C9
+			29 01 00 00 00 00 02 06 00
+			29 01 00 00 00 00 02 07 FD
+			29 01 00 00 00 00 02 08 01
+			29 01 00 00 00 00 02 09 29
+			29 01 00 00 00 00 02 0A 01
+			29 01 00 00 00 00 02 0B 6B
+			29 01 00 00 00 00 02 0C 01
+			29 01 00 00 00 00 02 0D 9E
+			29 01 00 00 00 00 02 0E 01
+			29 01 00 00 00 00 02 0F EB
+			29 01 00 00 00 00 02 10 02
+			29 01 00 00 00 00 02 11 25
+			29 01 00 00 00 00 02 12 02
+			29 01 00 00 00 00 02 13 27
+			29 01 00 00 00 00 02 14 02
+			29 01 00 00 00 00 02 15 5C
+			29 01 00 00 00 00 02 16 02
+			29 01 00 00 00 00 02 17 95
+			29 01 00 00 00 00 02 18 02
+			29 01 00 00 00 00 02 19 BA
+			29 01 00 00 00 00 02 1A 02
+			29 01 00 00 00 00 02 1B EC
+			29 01 00 00 00 00 02 1C 03
+			29 01 00 00 00 00 02 1D 0C
+			29 01 00 00 00 00 02 1E 03
+			29 01 00 00 00 00 02 1F 34
+			29 01 00 00 00 00 02 20 03
+			29 01 00 00 00 00 02 21 3F
+			29 01 00 00 00 00 02 22 03
+			29 01 00 00 00 00 02 23 48
+			29 01 00 00 00 00 02 24 03
+			29 01 00 00 00 00 02 25 49
+			29 01 00 00 00 00 02 26 03
+			29 01 00 00 00 00 02 27 6B
+			29 01 00 00 00 00 02 28 03
+			29 01 00 00 00 00 02 29 7E
+			29 01 00 00 00 00 02 2A 03
+			29 01 00 00 00 00 02 2B 8F
+			29 01 00 00 00 00 02 2D 03
+			29 01 00 00 00 00 02 2F 9E
+			29 01 00 00 00 00 02 30 03
+			29 01 00 00 00 00 02 31 A0
+			29 01 00 00 00 00 02 32 00
+			29 01 00 00 00 00 02 33 03
+			29 01 00 00 00 00 02 34 00
+			29 01 00 00 00 00 02 35 0B
+			29 01 00 00 00 00 02 36 00
+			29 01 00 00 00 00 02 37 0D
+			29 01 00 00 00 00 02 38 00
+			29 01 00 00 00 00 02 39 4A
+			29 01 00 00 00 00 02 3A 00
+			29 01 00 00 00 00 02 3B 71
+			29 01 00 00 00 00 02 3D 00
+			29 01 00 00 00 00 02 3F 8C
+			29 01 00 00 00 00 02 40 00
+			29 01 00 00 00 00 02 41 A1
+			29 01 00 00 00 00 02 42 00
+			29 01 00 00 00 00 02 43 B6
+			29 01 00 00 00 00 02 44 00
+			29 01 00 00 00 00 02 45 C9
+			29 01 00 00 00 00 02 46 00
+			29 01 00 00 00 00 02 47 FD
+			29 01 00 00 00 00 02 48 01
+			29 01 00 00 00 00 02 49 29
+			29 01 00 00 00 00 02 4A 01
+			29 01 00 00 00 00 02 4B 6B
+			29 01 00 00 00 00 02 4C 01
+			29 01 00 00 00 00 02 4D 9E
+			29 01 00 00 00 00 02 4E 01
+			29 01 00 00 00 00 02 4F EB
+			29 01 00 00 00 00 02 50 02
+			29 01 00 00 00 00 02 51 25
+			29 01 00 00 00 00 02 52 02
+			29 01 00 00 00 00 02 53 27
+			29 01 00 00 00 00 02 54 02
+			29 01 00 00 00 00 02 55 5C
+			29 01 00 00 00 00 02 56 02
+			29 01 00 00 00 00 02 58 95
+			29 01 00 00 00 00 02 59 02
+			29 01 00 00 00 00 02 5A BA
+			29 01 00 00 00 00 02 5B 02
+			29 01 00 00 00 00 02 5C EC
+			29 01 00 00 00 00 02 5D 03
+			29 01 00 00 00 00 02 5E 0C
+			29 01 00 00 00 00 02 5F 03
+			29 01 00 00 00 00 02 60 34
+			29 01 00 00 00 00 02 61 03
+			29 01 00 00 00 00 02 62 3F
+			29 01 00 00 00 00 02 63 03
+			29 01 00 00 00 00 02 64 48
+			29 01 00 00 00 00 02 65 03
+			29 01 00 00 00 00 02 66 49
+			29 01 00 00 00 00 02 67 03
+			29 01 00 00 00 00 02 68 6B
+			29 01 00 00 00 00 02 69 03
+			29 01 00 00 00 00 02 6A 7E
+			29 01 00 00 00 00 02 6B 03
+			29 01 00 00 00 00 02 6C 8F
+			29 01 00 00 00 00 02 6D 03
+			29 01 00 00 00 00 02 6E 9E
+			29 01 00 00 00 00 02 6F 03
+			29 01 00 00 00 00 02 70 A0
+			29 01 00 00 00 00 02 71 00
+			29 01 00 00 00 00 02 72 FB
+			29 01 00 00 00 00 02 73 00
+			29 01 00 00 00 00 02 74 FD
+			29 01 00 00 00 00 02 75 01
+			29 01 00 00 00 00 02 76 05
+			29 01 00 00 00 00 02 77 01
+			29 01 00 00 00 00 02 78 0D
+			29 01 00 00 00 00 02 79 01
+			29 01 00 00 00 00 02 7A 17
+			29 01 00 00 00 00 02 7B 01
+			29 01 00 00 00 00 02 7C 1F
+			29 01 00 00 00 00 02 7D 01
+			29 01 00 00 00 00 02 7E 28
+			29 01 00 00 00 00 02 7F 01
+			29 01 00 00 00 00 02 80 32
+			29 01 00 00 00 00 02 81 01
+			29 01 00 00 00 00 02 82 38
+			29 01 00 00 00 00 02 83 01
+			29 01 00 00 00 00 02 84 53
+			29 01 00 00 00 00 02 85 01
+			29 01 00 00 00 00 02 86 72
+			29 01 00 00 00 00 02 87 01
+			29 01 00 00 00 00 02 88 9B
+			29 01 00 00 00 00 02 89 01
+			29 01 00 00 00 00 02 8A C3
+			29 01 00 00 00 00 02 8B 02
+			29 01 00 00 00 00 02 8C 01
+			29 01 00 00 00 00 02 8D 02
+			29 01 00 00 00 00 02 8E 36
+			29 01 00 00 00 00 02 8F 02
+			29 01 00 00 00 00 02 90 37
+			29 01 00 00 00 00 02 91 02
+			29 01 00 00 00 00 02 92 69
+			29 01 00 00 00 00 02 93 02
+			29 01 00 00 00 00 02 94 A1
+			29 01 00 00 00 00 02 95 02
+			29 01 00 00 00 00 02 96 C8
+			29 01 00 00 00 00 02 97 02
+			29 01 00 00 00 00 02 98 FF
+			29 01 00 00 00 00 02 99 03
+			29 01 00 00 00 00 02 9A 26
+			29 01 00 00 00 00 02 9B 03
+			29 01 00 00 00 00 02 9C 69
+			29 01 00 00 00 00 02 9D 03
+			29 01 00 00 00 00 02 9E 88
+			29 01 00 00 00 00 02 9F 03
+			29 01 00 00 00 00 02 A0 F8
+			29 01 00 00 00 00 02 A2 03
+			29 01 00 00 00 00 02 A3 F9
+			29 01 00 00 00 00 02 A4 03
+			29 01 00 00 00 00 02 A5 FE
+			29 01 00 00 00 00 02 A6 03
+			29 01 00 00 00 00 02 A7 FE
+			29 01 00 00 00 00 02 A9 03
+			29 01 00 00 00 00 02 AA FE
+			29 01 00 00 00 00 02 AB 03
+			29 01 00 00 00 00 02 AC FE
+			29 01 00 00 00 00 02 AD 03
+			29 01 00 00 00 00 02 AE FE
+			29 01 00 00 00 00 02 AF 00
+			29 01 00 00 00 00 02 B0 FB
+			29 01 00 00 00 00 02 B1 00
+			29 01 00 00 00 00 02 B2 FD
+			29 01 00 00 00 00 02 B3 01
+			29 01 00 00 00 00 02 B4 05
+			29 01 00 00 00 00 02 B5 01
+			29 01 00 00 00 00 02 B6 0D
+			29 01 00 00 00 00 02 B7 01
+			29 01 00 00 00 00 02 B8 17
+			29 01 00 00 00 00 02 B9 01
+			29 01 00 00 00 00 02 BA 1F
+			29 01 00 00 00 00 02 BB 01
+			29 01 00 00 00 00 02 BC 28
+			29 01 00 00 00 00 02 BD 01
+			29 01 00 00 00 00 02 BE 32
+			29 01 00 00 00 00 02 BF 01
+			29 01 00 00 00 00 02 C0 38
+			29 01 00 00 00 00 02 C1 01
+			29 01 00 00 00 00 02 C2 53
+			29 01 00 00 00 00 02 C3 01
+			29 01 00 00 00 00 02 C4 72
+			29 01 00 00 00 00 02 C5 01
+			29 01 00 00 00 00 02 C6 9B
+			29 01 00 00 00 00 02 C7 01
+			29 01 00 00 00 00 02 C8 C3
+			29 01 00 00 00 00 02 C9 02
+			29 01 00 00 00 00 02 CA 01
+			29 01 00 00 00 00 02 CB 02
+			29 01 00 00 00 00 02 CC 36
+			29 01 00 00 00 00 02 CD 02
+			29 01 00 00 00 00 02 CE 37
+			29 01 00 00 00 00 02 CF 02
+			29 01 00 00 00 00 02 D0 69
+			29 01 00 00 00 00 02 D1 02
+			29 01 00 00 00 00 02 D2 A1
+			29 01 00 00 00 00 02 D3 02
+			29 01 00 00 00 00 02 D4 C8
+			29 01 00 00 00 00 02 D5 02
+			29 01 00 00 00 00 02 D6 FF
+			29 01 00 00 00 00 02 D7 03
+			29 01 00 00 00 00 02 D8 26
+			29 01 00 00 00 00 02 D9 03
+			29 01 00 00 00 00 02 DA 69
+			29 01 00 00 00 00 02 DB 03
+			29 01 00 00 00 00 02 DC 88
+			29 01 00 00 00 00 02 DD 03
+			29 01 00 00 00 00 02 DE F8
+			29 01 00 00 00 00 02 DF 03
+			29 01 00 00 00 00 02 E0 F9
+			29 01 00 00 00 00 02 E1 03
+			29 01 00 00 00 00 02 E2 FE
+			29 01 00 00 00 00 02 E3 03
+			29 01 00 00 00 00 02 E4 FE
+			29 01 00 00 00 00 02 E5 03
+			29 01 00 00 00 00 02 E6 FE
+			29 01 00 00 00 00 02 E7 03
+			29 01 00 00 00 00 02 E8 FE
+			29 01 00 00 00 00 02 E9 03
+			29 01 00 00 00 00 02 EA FE
+			29 01 00 00 00 00 02 FF 01
+			29 01 00 00 00 00 02 FB 01
+			29 01 00 00 00 00 02 FF 02
+			29 01 00 00 00 00 02 FB 01
+			29 01 00 00 00 00 02 FF 04
+			29 01 00 00 00 00 02 FB 01
+			29 01 00 00 00 00 02 FF 00
+			29 01 00 00 00 00 02 D3 14
+			29 01 00 00 00 00 02 D4 14
+			29 01 00 00 96 00 02 11 00
+			29 01 00 00 00 00 02 FF 00
+			29 01 00 00 00 00 02 35 00
+			29 01 00 00 78 00 02 29 00];
+
+		qcom,on-cmds-dsi-state = "DSI_LP_MODE";
+		qcom,panel-off-cmds = [05 01 00 00 32 00 02 28 00
+					05 01 00 00 78 00 02 10 00];
+		qcom,off-cmds-dsi-state = "DSI_HS_MODE";
+	};
+};
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index b4e557e..ce050a4 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -46,10 +46,13 @@
 			reg = <0x800 0x100>;
 			interrupts = <0x0 0x8 0x0>,
 				     <0x0 0x8 0x1>,
-				     <0x0 0x8 0x4>;
-			interrupt-names = "kpdpwr", "resin", "resin-bark";
+				     <0x0 0x8 0x4>,
+				     <0x0 0x8 0x5>;
+			interrupt-names = "kpdpwr", "resin",
+					"resin-bark", "kpdpwr-resin-bark";
 			qcom,pon-dbc-delay = <15625>;
 			qcom,system-reset;
+			qcom,s3-debounce = <32>;
 
 			qcom,pon_1 {
 				qcom,pon-type = <0>;
@@ -66,6 +69,15 @@
 				qcom,s2-type = <1>;
 				linux,code = <114>;
 			};
+
+			qcom,pon_3 {
+				qcom,pon-type = <3>;
+				qcom,support-reset = <1>;
+				qcom,s1-timer = <6720>;
+				qcom,s2-timer = <2000>;
+				qcom,s2-type = <7>;
+				qcom,pull-up = <1>;
+			};
 		};
 
 		bif_ctrl: qcom,bsi@1b00 {
diff --git a/arch/arm/boot/dts/msm8610-ion.dtsi b/arch/arm/boot/dts/msm8610-ion.dtsi
index 456b60c..d625b95 100644
--- a/arch/arm/boot/dts/msm8610-ion.dtsi
+++ b/arch/arm/boot/dts/msm8610-ion.dtsi
@@ -33,6 +33,21 @@
 			reg = <27>;
 			linux,contiguous-region = <&qsecom_mem>;
 		};
+
+		qcom,ion-heap@23 { /* OTHER PIL HEAP */
+			compatible = "qcom,msm-ion-reserve";
+			reg = <23>;
+			qcom,heap-align = <0x1000>;
+			qcom,memory-fixed = <0x0bf00000 0x1A00000>;
+		};
+
+		qcom,ion-heap@26 { /* MODEM HEAP */
+			compatible = "qcom,msm-ion-reserve";
+			reg = <26>;
+			qcom,heap-align = <0x1000>;
+			qcom,memory-fixed = <0x08000000 0x3F00000>;
+		};
+
 	};
 };
 
diff --git a/arch/arm/boot/dts/msm8610-qrd.dts b/arch/arm/boot/dts/msm8610-qrd.dts
index 22e7aa0..90225c0 100644
--- a/arch/arm/boot/dts/msm8610-qrd.dts
+++ b/arch/arm/boot/dts/msm8610-qrd.dts
@@ -57,6 +57,27 @@
 		status = "ok";
 	};
 
+	i2c@f9925000 { /* BLSP-1 QUP-3 */
+		kionix@f {
+			compatible = "kionix,kxtj9";
+			reg = <0x0f>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <81 0x2>;
+			vdd-supply = <&pm8110_l19>;
+			vio-supply = <&pm8110_l14>;
+			kionix,min_interval = <5>;
+			kionix,init_interval = <200>;
+			kionix,axis_map_x = <1>;
+			kionix,axis_map_y = <0>;
+			kionix,axis_map_z = <2>;
+			kionix,g-range = <2>;
+			kionix,negate-x;
+			kionix,negate-y;
+			kionix,negate-z;
+			kionix,res-12bit;
+		};
+	};
+
 	gpio_keys {
                 compatible = "gpio-keys";
                 input-name = "gpio-keys";
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index a62df58..7e1b201 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -237,6 +237,7 @@
 	android_usb@fe8050c8 {
 		compatible = "qcom,android-usb";
 		reg = <0xfe8050c8 0xc8>;
+		qcom,android-usb-swfi-latency = <1>;
 	};
 
 	sdcc1: qcom,sdcc@f9824000 {
@@ -418,7 +419,7 @@
 
 	qcom,msm-mem-hole {
 		compatible = "qcom,msm-mem-hole";
-		qcom,memblock-remove = <0x07B00000 0x6400000>; /* Address and Size of Hole */
+		qcom,memblock-remove = <0x07b00000 0x6400000>; /* Address and Size of Hole */
 	};
 
 	qcom,wdt@f9017000 {
diff --git a/arch/arm/boot/dts/msm8974-v2-pm.dtsi b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
index 178a1ee..eed1aae 100644
--- a/arch/arm/boot/dts/msm8974-v2-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
@@ -328,18 +328,23 @@
 			<50 172>, /* usb1_hs_async_wakeup_irq */
 			<53 104>, /* mdss_irq */
 			<62 222>, /* ee0_krait_hlos_spmi_periph_irq */
+			<0xff 56>,  /* modem_watchdog */
 			<0xff 57>,  /* mss_to_apps_irq(0) */
 			<0xff 58>,  /* mss_to_apps_irq(1) */
 			<0xff 59>,  /* mss_to_apps_irq(2) */
 			<0xff 60>,  /* mss_to_apps_irq(3) */
+			<0xff 70>,  /* iommu_pmon_nonsecure_irq */
+			<0xff 97>,  /* iommu_nonsecure_irq */
+			<0xff 105>, /* iommu_pmon_nonsecure_irq */
 			<0xff 173>, /* o_wcss_apss_smd_hi */
 			<0xff 174>, /* o_wcss_apss_smd_med */
 			<0xff 175>, /* o_wcss_apss_smd_low */
 			<0xff 176>, /* o_wcss_apss_smsm_irq */
 			<0xff 177>, /* o_wcss_apss_wlan_data_xfer_done */
 			<0xff 178>, /* o_wcss_apss_wlan_rx_data_avail */
-			<0xff 179>, /* o_wcss_apss_asic_intr
+			<0xff 179>, /* o_wcss_apss_asic_intr */
 
+			<0xff 181>, /* wcnss watchdog */
 			<0xff 188>, /* lpass_irq_out_apcs(0) */
 			<0xff 189>, /* lpass_irq_out_apcs(1) */
 			<0xff 190>, /* lpass_irq_out_apcs(2) */
@@ -358,6 +363,7 @@
 			<0xff 205>, /* rpm_ipc(25) */
 			<0xff 206>, /* rpm_ipc(26) */
 			<0xff 207>, /* rpm_ipc(27) */
+			<0xff 211>, /* usb_dwc3_otg */
 			<0xff 240>; /* summary_irq_kpss */
 
 		qcom,gpio-parent = <&msmgpio>;
diff --git a/arch/arm/boot/dts/msm8974-v2.dtsi b/arch/arm/boot/dts/msm8974-v2.dtsi
index 96e78ac..0240039 100644
--- a/arch/arm/boot/dts/msm8974-v2.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2.dtsi
@@ -115,12 +115,12 @@
 		<49880000 1496000>;
 	qcom,dec-ddr-ab-ib = <0 0>,
 		<208000 303000>,
-		<536000 303000>,
-		<1012000 303000>,
-		<2024000 606000>,
-		<3240000 970000>,
-		<4048000 1212000>,
-		<4264000 1279000>;
+		<536000 1600000>,
+		<1012000 1600000>,
+		<2024000 1600000>,
+		<3240000 1600000>,
+		<4048000 1600000>,
+		<4264000 1600000>;
 	qcom,iommu-groups = <&venus_domain_ns &venus_domain_sec_bitstream
 			&venus_domain_sec_pixel &venus_domain_sec_non_pixel>;
 	qcom,iommu-group-buffer-types = <0xfff 0x91 0x42 0x120>;
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index fc0636e..f4553e0 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -878,7 +878,6 @@
 			interrupt-parent = <&intc>;
 			interrupts = <0 131 0>, <0 179 0>;
 			interrupt-names = "irq", "otg_irq";
-			tx-fifo-resize;
 		};
 	};
 
@@ -1223,7 +1222,7 @@
 		qcom,iris-vddxo-supply = <&pm8941_l6>;
 		qcom,iris-vddrfa-supply = <&pm8941_l11>;
 		qcom,iris-vddpa-supply = <&pm8941_l19>;
-		qcom,iris-vdddig-supply = <&pm8941_l3>;
+		qcom,iris-vdddig-supply = <&pm8941_s3>;
 
 		gpios = <&msmgpio 36 0>, <&msmgpio 37 0>, <&msmgpio 38 0>, <&msmgpio 39 0>, <&msmgpio 40 0>;
 		qcom,has-48mhz-xo;
diff --git a/arch/arm/boot/dts/msmkrypton.dtsi b/arch/arm/boot/dts/msmkrypton.dtsi
index 7bbd528..ba6377c 100644
--- a/arch/arm/boot/dts/msmkrypton.dtsi
+++ b/arch/arm/boot/dts/msmkrypton.dtsi
@@ -45,6 +45,11 @@
 		qcom,direct-connect-irqs = <8>;
 	};
 
+	qcom,msm-imem@fe805000 {
+		compatible = "qcom,msm-imem";
+		reg = <0xfe807800 0x1000>; /* Address and size of IMEM */
+	};
+
 	timer@f9020000 {
 		#address-cells = <1>;
 		#size-cells = <1>;
diff --git a/arch/arm/boot/dts/msmsamarium.dtsi b/arch/arm/boot/dts/msmsamarium.dtsi
index 81699b6..968daff 100644
--- a/arch/arm/boot/dts/msmsamarium.dtsi
+++ b/arch/arm/boot/dts/msmsamarium.dtsi
@@ -87,4 +87,13 @@
 		qcom,bus-width = <4>;
 		status = "disabled";
 	};
+
+	qcom,wdt@f9017000 {
+		compatible = "qcom,msm-watchdog";
+		reg = <0xf9017000 0x1000>;
+		interrupts = <0 3 0>, <0 4 0>;
+		qcom,bark-time = <11000>;
+		qcom,pet-time = <10000>;
+		qcom,ipi-ping;
+	};
 };
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index e801467..9d104fd 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -283,6 +283,7 @@
 CONFIG_MSMB_CAMERA=y
 CONFIG_OV9724=y
 CONFIG_SP1628=y
+CONFIG_GC0339=y
 CONFIG_MSMB_JPEG=y
 CONFIG_MSM_VIDC_V4L2=y
 CONFIG_MSM_WFD=y
@@ -378,3 +379,4 @@
 CONFIG_CRYPTO_TWOFISH=y
 # CONFIG_CRYPTO_HW is not set
 CONFIG_CRC_CCITT=y
+CONFIG_INPUT_KXTJ9=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 1df43fa..0587e50 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -280,6 +280,7 @@
 CONFIG_MSM_CSI22_HEADER=y
 CONFIG_OV9724=y
 CONFIG_SP1628=y
+CONFIG_GC0339=y
 CONFIG_MSMB_JPEG=y
 CONFIG_MSM_VIDC_V4L2=y
 CONFIG_MSM_WFD=y
@@ -420,3 +421,4 @@
 CONFIG_CRYPTO_DEV_QCE=y
 CONFIG_CRYPTO_DEV_QCEDEV=m
 CONFIG_CRC_CCITT=y
+CONFIG_INPUT_KXTJ9=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 85fa764..8bf7ec9 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -2372,6 +2372,15 @@
           RBCPR (Rapid Bridge Core Power Reduction) information . The drivers
           outputs the message via a debugfs node.
 
+config MSM_RPM_RBCPR_STATS_V2_LOG
+        tristate "MSM Resource Power Manager RPBCPR Stat Driver"
+        depends on DEBUG_FS
+          help
+          This option enables v2 of the rpmrbcpr_stats driver which reads RPM
+          memory for statistics pertaining to RPM's RBCPR(Rapid Bridge Core
+          Power Reduction) driver. The drivers outputs the message via a
+          debugfs node.
+
 config MSM_DIRECT_SCLK_ACCESS
 	bool "Direct access to the SCLK timer"
 	default n
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 1c07dc1..e9a236e 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -333,6 +333,7 @@
 obj-$(CONFIG_MSM_MPM) += mpm.o
 obj-$(CONFIG_MSM_RPM_STATS_LOG) += rpm_stats.o rpm_master_stat.o
 obj-$(CONFIG_MSM_RPM_RBCPR_STATS_LOG) += rpm_rbcpr_stats.o
+obj-$(CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG) += rpm_rbcpr_stats_v2.o
 obj-$(CONFIG_MSM_RPM_LOG) += rpm_log.o
 obj-$(CONFIG_MSM_TZ_LOG) += tz_log.o
 obj-$(CONFIG_MSM_XO) += msm_xo.o
diff --git a/arch/arm/mach-msm/peripheral-loader.c b/arch/arm/mach-msm/peripheral-loader.c
index 475e8a1..c572291 100644
--- a/arch/arm/mach-msm/peripheral-loader.c
+++ b/arch/arm/mach-msm/peripheral-loader.c
@@ -113,6 +113,7 @@
  * @region_end: address where relocatable region ends or highest address for
  * non-relocatable images
  * @region: region allocated for relocatable images
+ * @unvoted_flag: flag to keep track if we have unvoted or not.
  *
  * This struct contains data for a pil_desc that should not be exposed outside
  * of this file. This structure points to the descriptor and the descriptor
@@ -132,6 +133,7 @@
 	struct ion_handle *region;
 	struct pil_image_info __iomem *info;
 	int id;
+	int unvoted_flag;
 };
 
 /**
@@ -184,15 +186,21 @@
 }
 EXPORT_SYMBOL(pil_get_entry_addr);
 
-static void pil_proxy_work(struct work_struct *work)
+static void __pil_proxy_unvote(struct pil_priv *priv)
 {
-	struct delayed_work *delayed = to_delayed_work(work);
-	struct pil_priv *priv = container_of(delayed, struct pil_priv, proxy);
 	struct pil_desc *desc = priv->desc;
 
 	desc->ops->proxy_unvote(desc);
 	wake_unlock(&priv->wlock);
 	module_put(desc->owner);
+
+}
+
+static void pil_proxy_unvote_work(struct work_struct *work)
+{
+	struct delayed_work *delayed = to_delayed_work(work);
+	struct pil_priv *priv = container_of(delayed, struct pil_priv, proxy);
+	__pil_proxy_unvote(priv);
 }
 
 static int pil_proxy_vote(struct pil_desc *desc)
@@ -206,6 +214,10 @@
 		if (ret)
 			wake_unlock(&priv->wlock);
 	}
+
+	if (desc->proxy_unvote_irq)
+		enable_irq(desc->proxy_unvote_irq);
+
 	return ret;
 }
 
@@ -237,8 +249,13 @@
 static irqreturn_t proxy_unvote_intr_handler(int irq, void *dev_id)
 {
 	struct pil_desc *desc = dev_id;
+	struct pil_priv *priv = desc->priv;
 
-	schedule_delayed_work(&desc->priv->proxy, 0);
+	if (!desc->priv->unvoted_flag) {
+		desc->priv->unvoted_flag = 1;
+		__pil_proxy_unvote(priv);
+	}
+
 	return IRQ_HANDLED;
 }
 
@@ -651,6 +668,7 @@
 			goto release_fw;
 	}
 
+	desc->priv->unvoted_flag = 0;
 	ret = pil_proxy_vote(desc);
 	if (ret) {
 		pil_err(desc, "Failed to proxy vote\n");
@@ -687,10 +705,19 @@
 void pil_shutdown(struct pil_desc *desc)
 {
 	struct pil_priv *priv = desc->priv;
+
 	if (desc->ops->shutdown)
 		desc->ops->shutdown(desc);
-	if (proxy_timeout_ms == 0 && desc->ops->proxy_unvote)
-		desc->ops->proxy_unvote(desc);
+
+	if (desc->proxy_unvote_irq) {
+		disable_irq(desc->proxy_unvote_irq);
+		if (!desc->priv->unvoted_flag)
+			pil_proxy_unvote(desc, 1);
+		return;
+	}
+
+	if (!proxy_timeout_ms)
+		pil_proxy_unvote(desc, 1);
 	else
 		flush_delayed_work(&priv->proxy);
 }
@@ -741,7 +768,8 @@
 	__iowrite32_copy(priv->info->name, buf, sizeof(buf) / 4);
 
 	if (desc->proxy_unvote_irq > 0) {
-		ret = request_irq(desc->proxy_unvote_irq,
+		ret = request_threaded_irq(desc->proxy_unvote_irq,
+				  NULL,
 				  proxy_unvote_intr_handler,
 				  IRQF_TRIGGER_RISING|IRQF_SHARED,
 				  desc->name, desc);
@@ -751,11 +779,12 @@
 				ret);
 			goto err;
 		}
+		disable_irq(desc->proxy_unvote_irq);
 	}
 
 	snprintf(priv->wname, sizeof(priv->wname), "pil-%s", desc->name);
 	wake_lock_init(&priv->wlock, WAKE_LOCK_SUSPEND, priv->wname);
-	INIT_DELAYED_WORK(&priv->proxy, pil_proxy_work);
+	INIT_DELAYED_WORK(&priv->proxy, pil_proxy_unvote_work);
 	INIT_LIST_HEAD(&priv->segs);
 
 	return 0;
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index 8cf6011..b83202b 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -628,15 +628,8 @@
 	if (ret)
 		return ret;
 	ret = pil_boot(&drv->desc);
-	if (ret) {
+	if (ret)
 		pil_shutdown(&drv->q6->desc);
-		/*
-		 * We know now that the unvote interrupt is not coming.
-		 * Remove the proxy votes immediately.
-		 */
-		if (drv->q6->desc.proxy_unvote_irq)
-			pil_q6v5_mss_remove_proxy_votes(&drv->q6->desc);
-	}
 	return ret;
 }
 
diff --git a/arch/arm/mach-msm/rpm_rbcpr_stats_v2.c b/arch/arm/mach-msm/rpm_rbcpr_stats_v2.c
new file mode 100644
index 0000000..8f0ccd4
--- /dev/null
+++ b/arch/arm/mach-msm/rpm_rbcpr_stats_v2.c
@@ -0,0 +1,430 @@
+/* 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 <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/sort.h>
+#include <asm/uaccess.h>
+#include <mach/msm_iomap.h>
+
+#define RBCPR_BUF_LEN 8000
+#define RBCPR_STATS_MAX_SIZE SZ_2K
+#define RBCPR_MAX_RAILS 4
+#define RBCPR_NUM_RECMNDS 3
+#define RBCPR_NUM_CORNERS 3
+
+#define FIELD(a)     ((strnstr(#a, "->", 80) + 2))
+#define PRINT(buf, pos, format, ...) \
+	((pos < RBCPR_BUF_LEN) ? snprintf((buf + pos), (RBCPR_BUF_LEN - pos),\
+	format, ## __VA_ARGS__) : 0)
+
+enum {
+	CORNER_OFF,
+	CORNER_SVS,
+	CORNER_NOMINAL,
+	CORNER_TURBO,
+	CORNER_MAX,
+};
+
+struct rbcpr_recmnd_data_type {
+	uint32_t microvolts;
+	uint64_t timestamp;
+};
+
+struct rbcpr_corners_data_type {
+	uint32_t efuse_adjustment;
+	uint32_t programmed_voltage;
+	uint32_t isr_count;
+	uint32_t min_count;
+	uint32_t max_count;
+	struct rbcpr_recmnd_data_type rbcpr_recmnd[RBCPR_NUM_RECMNDS];
+};
+
+struct rbcpr_rail_stats_type {
+	uint32_t num_corners;
+	uint32_t num_latest_recommends;
+	struct rbcpr_corners_data_type rbcpr_corners[RBCPR_NUM_CORNERS];
+	uint32_t current_corner;
+	uint32_t railway_voltage;
+	uint32_t off_corner;
+	uint32_t margin;
+};
+
+struct rbcpr_stats_type {
+	uint32_t num_rails;
+	uint32_t status;
+	struct rbcpr_rail_stats_type *rbcpr_rail;
+};
+
+struct rbcpr_data_type {
+	void __iomem *start;
+	uint32_t len;
+	char buf[RBCPR_BUF_LEN];
+};
+
+static char *rbcpr_rail_labels[] = {
+	[0] = "VDD-CX",
+	[1] = "VDD-GFX",
+};
+
+static char *rbcpr_corner_string[] = {
+	[CORNER_OFF] = "CORNERS_OFF",
+	[CORNER_SVS] = "SVS",
+	[CORNER_NOMINAL] = "NOMINAL",
+	[CORNER_TURBO] = "TURBO",
+};
+#define CORNER_STRING(a)	\
+	((a >= CORNER_MAX) ? "INVALID Corner" : rbcpr_corner_string[a])
+
+static struct rbcpr_data_type *rbcpr_data;
+static struct rbcpr_stats_type *rbcpr_stats;
+
+static void msm_rpmrbcpr_read_rpm_data(void)
+{
+	uint32_t start_offset;
+	uint32_t stats_size;
+
+	start_offset = offsetof(struct rbcpr_stats_type, rbcpr_rail);
+	stats_size =
+		rbcpr_stats->num_rails * sizeof(struct rbcpr_rail_stats_type);
+
+	if (stats_size > RBCPR_STATS_MAX_SIZE) {
+		pr_err("%s: Max copy size exceeded. stats size %d max %d",
+			__func__, stats_size, RBCPR_STATS_MAX_SIZE);
+		return;
+	}
+
+	memcpy_fromio(rbcpr_stats->rbcpr_rail,
+		(rbcpr_data->start + start_offset), stats_size);
+}
+
+static uint32_t msm_rpmrbcpr_print_data(void)
+{
+	uint32_t pos = 0;
+	uint32_t i, j, k;
+	struct rbcpr_rail_stats_type *rail;
+	struct rbcpr_corners_data_type *corner;
+	struct rbcpr_recmnd_data_type *rbcpr_recmnd;
+	char *buf = rbcpr_data->buf;
+
+	pos += PRINT(buf, pos, ":RBCPR STATS\n");
+	pos += PRINT(buf, pos, "(%s: %d)", FIELD(rbcpr_stats->num_rails),
+				rbcpr_stats->num_rails);
+	pos += PRINT(buf, pos, "(%s: %d)\n", FIELD(rbcpr_stats->status),
+				rbcpr_stats->status);
+
+
+	for (i = 0; i < rbcpr_stats->num_rails; i++) {
+		rail = &rbcpr_stats->rbcpr_rail[i];
+		pos += PRINT(buf, pos, ":%s Rail Data\n", rbcpr_rail_labels[i]);
+		pos += PRINT(buf, pos, "(%s: %s)",
+			FIELD(rail->current_corner),
+			CORNER_STRING(rail->current_corner));
+		pos += PRINT(buf, pos, "(%s: %d)",
+			FIELD(rail->railway_voltage), rail->railway_voltage);
+		pos += PRINT(buf, pos, "(%s: %d)",
+			FIELD(rail->off_corner), rail->off_corner);
+		pos += PRINT(buf, pos, "(%s: %d)\n",
+			FIELD(rail->margin), rail->margin);
+
+		for (j = 0; j < RBCPR_NUM_CORNERS; j++) {
+			pos += PRINT(buf, pos, "\t\tCorner Data:%s ",
+							CORNER_STRING(j + 1));
+			corner = &rail->rbcpr_corners[j];
+			pos += PRINT(buf, pos, "(%s: %d)",
+				FIELD(corner->efuse_adjustment),
+						corner->efuse_adjustment);
+			pos += PRINT(buf, pos, "(%s: %d)",
+				FIELD(corner->programmed_voltage),
+						corner->programmed_voltage);
+			pos += PRINT(buf, pos, "(%s: %d)",
+				FIELD(corner->isr_count), corner->isr_count);
+			pos += PRINT(buf, pos, "(%s: %d)",
+				FIELD(corner->min_count), corner->min_count);
+			pos += PRINT(buf, pos, "(%s: %d)\n",
+				FIELD(corner->max_count), corner->max_count);
+
+
+			for (k = 0; k < RBCPR_NUM_RECMNDS; k++) {
+				rbcpr_recmnd = &corner->rbcpr_recmnd[k];
+				pos += PRINT(buf, pos,
+					"\t\t\t\tVoltage History[%d] ", k);
+				pos += PRINT(buf, pos, " (%s: %d) ",
+					FIELD(rbcpr_recmd->microvolts),
+						rbcpr_recmnd->microvolts);
+				pos += PRINT(buf, pos, " (%s: %lld)\n",
+					FIELD(rbcpr_recmd->timestamp),
+						rbcpr_recmnd->timestamp);
+			}
+		}
+	}
+
+	return pos;
+}
+
+
+static int msm_rpmrbcpr_file_read(struct file *file, char __user *bufu,
+					size_t count, loff_t *ppos)
+{
+	struct rbcpr_data_type *pdata = file->private_data;
+	int ret = 0;
+	int status_counter;
+	static DEFINE_MUTEX(rbcpr_lock);
+
+	mutex_lock(&rbcpr_lock);
+	if (!pdata) {
+		pr_err("%s pdata is null", __func__);
+		ret = -EINVAL;
+		goto exit_rpmrbcpr_file_read;
+	}
+
+	if (!bufu || count < 0) {
+		pr_err("%s count %d ", __func__, count);
+		ret = -EINVAL;
+		goto exit_rpmrbcpr_file_read;
+	}
+
+	if (*ppos > pdata->len || !*ppos) {
+		/* Read RPM stats */
+		status_counter = readl_relaxed(pdata->start +
+			offsetof(struct rbcpr_stats_type, status));
+		if (status_counter != rbcpr_stats->status) {
+			msm_rpmrbcpr_read_rpm_data();
+			rbcpr_stats->status = status_counter;
+		}
+		pdata->len = msm_rpmrbcpr_print_data();
+		*ppos = 0;
+	}
+
+	/* copy to user data*/
+	ret = simple_read_from_buffer(bufu, count, ppos, pdata->buf,
+					pdata->len);
+exit_rpmrbcpr_file_read:
+	mutex_unlock(&rbcpr_lock);
+	return ret;
+}
+
+static int msm_rpmrbcpr_file_open(struct inode *inode, struct file *file)
+{
+	file->private_data = rbcpr_data;
+
+	if (!rbcpr_data->start)
+		return -ENODEV;
+
+	return 0;
+}
+
+static int msm_rpmrbcpr_file_close(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+static const struct file_operations msm_rpmrbcpr_fops = {
+	.owner    = THIS_MODULE,
+	.open     = msm_rpmrbcpr_file_open,
+	.read     = msm_rpmrbcpr_file_read,
+	.release  = msm_rpmrbcpr_file_close,
+	.llseek   = no_llseek,
+};
+
+static int msm_rpmrbcpr_memalloc(struct platform_device *pdev)
+{
+	void *addr = NULL;
+	int ret = 0;
+	uint32_t num_latest_recommends = 0;
+	uint32_t num_corners = 0;
+
+	rbcpr_stats->num_rails = readl_relaxed(rbcpr_data->start);
+
+	if (rbcpr_stats->num_rails > RBCPR_MAX_RAILS) {
+		pr_err("%s: Invalid number of RPM RBCPR rails %d",
+				__func__, rbcpr_stats->num_rails);
+		rbcpr_stats->num_rails = 0;
+		ret = -EFAULT;
+		goto rbcpr_memalloc_fail;
+	}
+
+	rbcpr_stats->rbcpr_rail =
+		devm_kzalloc(&pdev->dev,
+			sizeof(struct rbcpr_rail_stats_type) *
+			rbcpr_stats->num_rails, GFP_KERNEL);
+
+	if (!rbcpr_stats->rbcpr_rail) {
+		ret = -ENOMEM;
+		goto rbcpr_memalloc_fail;
+	}
+
+	addr = rbcpr_data->start + offsetof(struct rbcpr_stats_type,
+								rbcpr_rail);
+
+	/* Each rail has the same number of corners and number of latest
+	   recommended values. Read these from the first rail and check them
+	   to make sure the values are valid. (RPM doesn't 0 initialize this
+	   memory region, so its possible we end up with bogus values if the
+	   rbcpr driver is not initialized.).
+	*/
+	num_corners = readl_relaxed(addr);
+	num_latest_recommends = readl_relaxed(addr +
+				offsetof(struct rbcpr_rail_stats_type,
+						num_latest_recommends));
+
+	if ((num_latest_recommends != RBCPR_NUM_RECMNDS)
+		|| (num_corners != RBCPR_NUM_CORNERS)) {
+		pr_err("%s: Invalid num corners %d, num recmnds %d",
+			__func__, num_corners, num_latest_recommends);
+		ret = -EFAULT;
+		goto rbcpr_memalloc_fail;
+	}
+
+rbcpr_memalloc_fail:
+	return ret;
+}
+
+static  int __devinit msm_rpmrbcpr_probe(struct platform_device *pdev)
+{
+	struct dentry *dent;
+	int ret = 0;
+	struct resource *res = NULL;
+	void __iomem *start_ptr = NULL;
+	uint32_t rbcpr_start_addr = 0;
+	char *key = NULL;
+	uint32_t start_addr;
+
+	rbcpr_data = devm_kzalloc(&pdev->dev,
+				sizeof(struct rbcpr_data_type), GFP_KERNEL);
+
+	if (!rbcpr_data)
+		return -ENOMEM;
+
+	rbcpr_stats = devm_kzalloc(&pdev->dev,
+				sizeof(struct rbcpr_stats_type), GFP_KERNEL);
+
+	if (!rbcpr_stats) {
+		pr_err("%s: Failed to allocate memory for RBCPR stats",
+						__func__);
+		return -ENOMEM;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	if (!res) {
+		pr_err("%s: Failed to get IO resource from platform device",
+				__func__);
+		ret = -ENXIO;
+		goto rbcpr_probe_fail;
+	}
+
+	key = "qcom,start-offset";
+	ret = of_property_read_u32(pdev->dev.of_node, key, &start_addr);
+
+	if (ret) {
+		pr_err("%s: Failed to get start offset", __func__);
+		goto rbcpr_probe_fail;
+	}
+
+	start_addr += res->start;
+	start_ptr = ioremap_nocache(start_addr, 4);
+
+	if (!start_ptr) {
+		pr_err("%s: Failed to remap RBCPR start pointer",
+					__func__);
+		goto rbcpr_probe_fail;
+	}
+
+	rbcpr_start_addr = res->start + readl_relaxed(start_ptr);
+
+	if ((rbcpr_start_addr > (res->end - RBCPR_STATS_MAX_SIZE)) ||
+			(rbcpr_start_addr < start_addr)) {
+		pr_err("%s: Invalid start address for rbcpr stats 0x%x",
+			__func__, rbcpr_start_addr);
+		goto rbcpr_probe_fail;
+	}
+
+	rbcpr_data->start = devm_ioremap_nocache(&pdev->dev, rbcpr_start_addr,
+							RBCPR_STATS_MAX_SIZE);
+
+	if (!rbcpr_data->start) {
+		pr_err("%s: Failed to remap RBCPR start address",
+				__func__);
+		goto rbcpr_probe_fail;
+	}
+
+	ret = msm_rpmrbcpr_memalloc(pdev);
+
+	if (ret)
+		goto rbcpr_probe_fail;
+
+	dent = debugfs_create_file("rpm_rbcpr", S_IRUGO, NULL,
+			pdev->dev.platform_data, &msm_rpmrbcpr_fops);
+
+	if (!dent) {
+		pr_err("%s: error debugfs_create_file failed\n", __func__);
+		ret = -ENOMEM;
+		goto rbcpr_probe_fail;
+	}
+
+	platform_set_drvdata(pdev, dent);
+rbcpr_probe_fail:
+	iounmap(start_ptr);
+	return ret;
+}
+
+static int __devexit msm_rpmrbcpr_remove(struct platform_device *pdev)
+{
+	struct dentry *dent;
+
+	dent = platform_get_drvdata(pdev);
+	debugfs_remove(dent);
+	platform_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+static struct of_device_id rpmrbcpr_stats_table[] = {
+	{.compatible = "qcom,rpmrbcpr-stats"},
+	{},
+};
+
+static struct platform_driver msm_rpmrbcpr_driver = {
+	.probe  = msm_rpmrbcpr_probe,
+	.remove = __devexit_p(msm_rpmrbcpr_remove),
+	.driver = {
+		.name = "msm_rpmrbcpr_stats",
+		.owner = THIS_MODULE,
+		.of_match_table = rpmrbcpr_stats_table,
+	},
+};
+
+static int __init msm_rpmrbcpr_init(void)
+{
+	return platform_driver_register(&msm_rpmrbcpr_driver);
+}
+
+static void __exit msm_rpmrbcpr_exit(void)
+{
+	platform_driver_unregister(&msm_rpmrbcpr_driver);
+}
+
+module_init(msm_rpmrbcpr_init);
+module_exit(msm_rpmrbcpr_exit);
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index e98fff2..83d94f1 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -87,7 +87,7 @@
 static inline int buf_get_pages(void *addr, int sz, int nr_pages, int access,
 				  struct smq_phy_page *pages, int nr_elems)
 {
-	struct vm_area_struct *vma;
+	struct vm_area_struct *vma, *vmaend;
 	uint32_t start = buf_page_start(addr);
 	uint32_t end = buf_page_start((void *)((uint32_t)addr + sz - 1));
 	uint32_t len = nr_pages << PAGE_SHIFT;
@@ -101,14 +101,14 @@
 	VERIFY(err, 0 != (vma = find_vma(current->mm, start)));
 	if (err)
 		goto bail;
-	VERIFY(err, ((uint32_t)addr + sz) <= vma->vm_end);
+	VERIFY(err, 0 != (vmaend = find_vma(current->mm, end)));
 	if (err)
 		goto bail;
 	n = 0;
 	VERIFY(err, 0 == follow_pfn(vma, start, &pfn));
 	if (err)
 		goto bail;
-	VERIFY(err, 0 == follow_pfn(vma, end, &pfnend));
+	VERIFY(err, 0 == follow_pfn(vmaend, end, &pfnend));
 	if (err)
 		goto bail;
 	VERIFY(err, (pfn + nr_pages - 1) == pfnend);
diff --git a/drivers/crypto/msm/qcrypto.c b/drivers/crypto/msm/qcrypto.c
index 39b9a46..7fc9a9c 100644
--- a/drivers/crypto/msm/qcrypto.c
+++ b/drivers/crypto/msm/qcrypto.c
@@ -824,7 +824,14 @@
 	struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher);
 	struct qcrypto_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
 	u32 tmp[DES_EXPKEY_WORDS];
-	int ret = des_ekey(tmp, key);
+	int ret;
+
+	if (!key) {
+		pr_err("%s Inavlid key pointer\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = des_ekey(tmp, key);
 
 	if ((ctx->flags & QCRYPTO_CTX_USE_HW_KEY) == QCRYPTO_CTX_USE_HW_KEY) {
 		pr_err("%s HW KEY usage not supported for DES algorithm\n",
@@ -843,14 +850,9 @@
 	}
 
 	ctx->enc_key_len = len;
-	if (!(ctx->flags & QCRYPTO_CTX_USE_PIPE_KEY)) {
-		if (key != NULL) {
-			memcpy(ctx->enc_key, key, len);
-		} else {
-			pr_err("%s Inavlid key pointer\n", __func__);
-			return -EINVAL;
-		}
-	}
+	if (!(ctx->flags & QCRYPTO_CTX_USE_PIPE_KEY))
+		memcpy(ctx->enc_key, key, len);
+
 	return 0;
 };
 
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 29855f7..a757a22 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2735,6 +2735,9 @@
 {
 	unsigned int in, out;
 
+	if (countable > 1)
+		return;
+
 	adreno_regread(device, A3XX_RBBM_RBBM_CTL, &in);
 
 	if (countable == 0)
@@ -2790,6 +2793,9 @@
 {
 	unsigned int in, out, bit;
 
+	if (countable > 2)
+		return;
+
 	adreno_regread(device, A3XX_VBIF_PERF_CNT_EN, &in);
 	if (countable == 0)
 		bit = VBIF_PERF_PWR_CNT_0;
@@ -2823,12 +2829,6 @@
 	unsigned int val = 0;
 	struct a3xx_perfcounter_register *reg;
 
-	if (group >= ARRAY_SIZE(a3xx_perfcounter_reglist))
-		return;
-
-	if (counter >= a3xx_perfcounter_reglist[group].count)
-		return;
-
 	/* Special cases */
 	if (group == KGSL_PERFCOUNTER_GROUP_PWR)
 		return a3xx_perfcounter_enable_pwr(device, countable);
@@ -2837,6 +2837,12 @@
 	else if (group == KGSL_PERFCOUNTER_GROUP_VBIF_PWR)
 		return a3xx_perfcounter_enable_vbif_pwr(device, countable);
 
+	if (group >= ARRAY_SIZE(a3xx_perfcounter_reglist))
+		return;
+
+	if (counter >= a3xx_perfcounter_reglist[group].count)
+		return;
+
 	reg = &(a3xx_perfcounter_reglist[group].regs[counter]);
 
 	/* Select the desired perfcounter */
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index becb4ef..5fda9d7 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -59,6 +59,8 @@
 	struct sg_table *table;
 };
 
+static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry);
+
 /**
  * kgsl_hang_check() - Check for GPU hang
  * data: KGSL device structure
@@ -255,6 +257,9 @@
 						    struct kgsl_mem_entry,
 						    refcount);
 
+	/* Detach from process list */
+	kgsl_mem_entry_detach_process(entry);
+
 	if (entry->memtype != KGSL_MEM_ENTRY_KERNEL)
 		kgsl_driver.stats.mapped -= entry->memdesc.size;
 
@@ -286,23 +291,46 @@
 EXPORT_SYMBOL(kgsl_mem_entry_destroy);
 
 /**
- * kgsl_mem_entry_track_gpuaddr - Insert a mem_entry in the address tree
+ * kgsl_mem_entry_track_gpuaddr - Insert a mem_entry in the address tree and
+ * assign it with a gpu address space before insertion
  * @process: the process that owns the memory
  * @entry: the memory entry
  *
- * Insert a kgsl_mem_entry in to the rb_tree for searching by GPU address.
- * Not all mem_entries will have gpu addresses when first created, so this
- * function may be called after creation when the GPU address is finally
- * assigned.
+ * @returns - 0 on succcess else error code
+ *
+ * Insert the kgsl_mem_entry in to the rb_tree for searching by GPU address.
+ * The assignment of gpu address and insertion into list needs to
+ * happen with the memory lock held to avoid race conditions between
+ * gpu address being selected and some other thread looking through the
+ * rb list in search of memory based on gpuaddr
+ * This function should be called with processes memory spinlock held
  */
-static void
+static int
 kgsl_mem_entry_track_gpuaddr(struct kgsl_process_private *process,
 				struct kgsl_mem_entry *entry)
 {
+	int ret = 0;
 	struct rb_node **node;
 	struct rb_node *parent = NULL;
 
-	spin_lock(&process->mem_lock);
+	assert_spin_locked(&process->mem_lock);
+	/*
+	 * If cpu=gpu map is used then caller needs to set the
+	 * gpu address
+	 */
+	if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) {
+		if (!entry->memdesc.gpuaddr)
+			goto done;
+	} else if (entry->memdesc.gpuaddr) {
+		WARN_ONCE(1, "gpuaddr assigned w/o holding memory lock\n");
+		ret = -EINVAL;
+		goto done;
+	}
+	if (!kgsl_memdesc_use_cpu_map(&entry->memdesc)) {
+		ret = kgsl_mmu_get_gpuaddr(process->pagetable, &entry->memdesc);
+		if (ret)
+			goto done;
+	}
 
 	node = &process->mem_rb.rb_node;
 
@@ -321,7 +349,27 @@
 	rb_link_node(&entry->node, parent, node);
 	rb_insert_color(&entry->node, &process->mem_rb);
 
-	spin_unlock(&process->mem_lock);
+done:
+	return ret;
+}
+
+/**
+ * kgsl_mem_entry_untrack_gpuaddr() - Untrack memory that is previously tracked
+ * process - Pointer to process private to which memory belongs
+ * entry - Memory entry to untrack
+ *
+ * Function just does the opposite of kgsl_mem_entry_track_gpuaddr. Needs to be
+ * called with processes spin lock held
+ */
+static void
+kgsl_mem_entry_untrack_gpuaddr(struct kgsl_process_private *process,
+				struct kgsl_mem_entry *entry)
+{
+	assert_spin_locked(&process->mem_lock);
+	if (entry->memdesc.gpuaddr) {
+		kgsl_mmu_put_gpuaddr(process->pagetable, &entry->memdesc);
+		rb_erase(&entry->node, &entry->priv->mem_rb);
+	}
 }
 
 /**
@@ -360,8 +408,19 @@
 	}
 	entry->priv = process;
 
-	if (entry->memdesc.gpuaddr != 0)
-		kgsl_mem_entry_track_gpuaddr(process, entry);
+	spin_lock(&process->mem_lock);
+	ret = kgsl_mem_entry_track_gpuaddr(process, entry);
+	if (ret)
+		idr_remove(&process->mem_idr, entry->id);
+	spin_unlock(&process->mem_lock);
+	if (ret)
+		goto err;
+	/* map the memory after unlocking if gpuaddr has been assigned */
+	if (entry->memdesc.gpuaddr) {
+		ret = kgsl_mmu_map(process->pagetable, &entry->memdesc);
+		if (ret)
+			kgsl_mem_entry_detach_process(entry);
+	}
 err:
 	return ret;
 }
@@ -370,37 +429,23 @@
 
 static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry)
 {
-	bool had_gpuaddr = false;
-
 	if (entry == NULL)
 		return;
 
-	/*
-	 * Unmap the entry first so that there isn't a period of
-	 * time where kgsl doesn't know about the address range
-	 * but it is still present in the pagetable. Unmapping will
-	 * clear the gpuaddr field, so remember if we had a mapping,
-	 * and an rbtree entry for later.
-	 */
-	had_gpuaddr = entry->memdesc.gpuaddr != 0;
-	kgsl_mmu_unmap(entry->memdesc.pagetable, &entry->memdesc);
+	/* Unmap here so that below we can call kgsl_mmu_put_gpuaddr */
+	kgsl_mmu_unmap(entry->priv->pagetable, &entry->memdesc);
 
 	spin_lock(&entry->priv->mem_lock);
 
+	kgsl_mem_entry_untrack_gpuaddr(entry->priv, entry);
 	if (entry->id != 0)
 		idr_remove(&entry->priv->mem_idr, entry->id);
 	entry->id = 0;
 
-	if (had_gpuaddr)
-		rb_erase(&entry->node, &entry->priv->mem_rb);
-
+	entry->priv->stats[entry->memtype].cur -= entry->memdesc.size;
 	spin_unlock(&entry->priv->mem_lock);
 
-	entry->priv->stats[entry->memtype].cur -= entry->memdesc.size;
 	entry->priv = NULL;
-
-
-	kgsl_mem_entry_put(entry);
 }
 
 /* Allocate a new context id */
@@ -759,7 +804,7 @@
 		rcu_read_unlock();
 		if (entry == NULL)
 			break;
-		kgsl_mem_entry_detach_process(entry);
+		kgsl_mem_entry_put(entry);
 		/*
 		 * Always start back at the beginning, to
 		 * ensure all entries are removed,
@@ -1069,12 +1114,13 @@
 kgsl_sharedmem_find_region(struct kgsl_process_private *private,
 	unsigned int gpuaddr, size_t size)
 {
-	struct rb_node *node = private->mem_rb.rb_node;
+	struct rb_node *node;
 
 	if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, gpuaddr))
 		return NULL;
 
 	spin_lock(&private->mem_lock);
+	node = private->mem_rb.rb_node;
 	while (node != NULL) {
 		struct kgsl_mem_entry *entry;
 
@@ -1124,16 +1170,19 @@
  * @size: length of the region.
  *
  * Checks that there are no existing allocations within an address
- * region.
+ * region. This function should be called with processes spin lock
+ * held.
  */
-int
+static int
 kgsl_sharedmem_region_empty(struct kgsl_process_private *private,
 	unsigned int gpuaddr, size_t size)
 {
 	int result = 1;
 	unsigned int gpuaddr_end = gpuaddr + size;
 
-	struct rb_node *node = private->mem_rb.rb_node;
+	struct rb_node *node;
+
+	assert_spin_locked(&private->mem_lock);
 
 	if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, gpuaddr))
 		return 0;
@@ -1142,7 +1191,6 @@
 	if (gpuaddr_end < gpuaddr)
 		return 0;
 
-	spin_lock(&private->mem_lock);
 	node = private->mem_rb.rb_node;
 	while (node != NULL) {
 		struct kgsl_mem_entry *entry;
@@ -1163,7 +1211,6 @@
 			break;
 		}
 	}
-	spin_unlock(&private->mem_lock);
 	return result;
 }
 
@@ -1191,6 +1238,30 @@
 	return entry;
 }
 
+/**
+ * kgsl_mem_entry_set_pend() - Set the pending free flag of a memory entry
+ * @entry - The memory entry
+ *
+ * @returns - true if pending flag was 0 else false
+ *
+ * This function will set the pending free flag if it is previously unset. Used
+ * to prevent race condition between ioctls calling free/freememontimestamp
+ * on the same entry. Whichever thread set's the flag first will do the free.
+ */
+static inline bool kgsl_mem_entry_set_pend(struct kgsl_mem_entry *entry)
+{
+	bool ret = false;
+	spin_lock(&entry->priv->mem_lock);
+	if (entry && entry->pending_free) {
+		ret = false;
+	} else if (entry) {
+		entry->pending_free = 1;
+		ret = true;
+	}
+	spin_unlock(&entry->priv->mem_lock);
+	return ret;
+}
+
 /*call all ioctl sub functions with driver locked*/
 static long kgsl_ioctl_device_getproperty(struct kgsl_device_private *dev_priv,
 					  unsigned int cmd, void *data)
@@ -1469,7 +1540,7 @@
 {
 	struct kgsl_mem_entry *entry = priv;
 	trace_kgsl_mem_timestamp_free(device, entry, id, timestamp, 0);
-	kgsl_mem_entry_detach_process(entry);
+	kgsl_mem_entry_put(entry);
 }
 
 static long _cmdstream_freememontimestamp(struct kgsl_device_private *dev_priv,
@@ -1488,11 +1559,12 @@
 				"invalid gpuaddr %08x\n", gpuaddr);
 		return -EINVAL;
 	}
-	if (entry->memdesc.priv & KGSL_MEMDESC_FREE_PENDING) {
+	if (!kgsl_mem_entry_set_pend(entry)) {
+		KGSL_DRV_WARN(dev_priv->device,
+		"Cannot set pending bit for gpuaddr %08x\n", gpuaddr);
 		kgsl_mem_entry_put(entry);
 		return -EBUSY;
 	}
-	entry->memdesc.priv |= KGSL_MEMDESC_FREE_PENDING;
 
 	trace_kgsl_mem_timestamp_queue(device, entry, context_id,
 				       kgsl_readtimestamp(device, context,
@@ -1592,8 +1664,7 @@
 				param->gpuaddr);
 		return -EINVAL;
 	}
-
-	if (entry->memdesc.priv & KGSL_MEMDESC_FREE_PENDING) {
+	if (!kgsl_mem_entry_set_pend(entry)) {
 		kgsl_mem_entry_put(entry);
 		return -EBUSY;
 	}
@@ -1605,7 +1676,12 @@
 				    entry->memdesc.size,
 				    entry->memdesc.flags);
 
-	kgsl_mem_entry_detach_process(entry);
+	/*
+	 * First kgsl_mem_entry_put is for the reference that we took in
+	 * this function when calling kgsl_sharedmem_find, second one is
+	 * to free the memory since this is a free ioctl
+	 */
+	kgsl_mem_entry_put(entry);
 	kgsl_mem_entry_put(entry);
 	return 0;
 }
@@ -1624,7 +1700,7 @@
 		return -EINVAL;
 	}
 
-	if (entry->memdesc.priv & KGSL_MEMDESC_FREE_PENDING) {
+	if (!kgsl_mem_entry_set_pend(entry)) {
 		kgsl_mem_entry_put(entry);
 		return -EBUSY;
 	}
@@ -1636,7 +1712,12 @@
 				    entry->memdesc.size,
 				    entry->memdesc.flags);
 
-	kgsl_mem_entry_detach_process(entry);
+	/*
+	 * First kgsl_mem_entry_put is for the reference that we took in
+	 * this function when calling kgsl_sharedmem_find_id, second one is
+	 * to free the memory since this is a free ioctl
+	 */
+	kgsl_mem_entry_put(entry);
 	kgsl_mem_entry_put(entry);
 	return 0;
 }
@@ -2111,18 +2192,15 @@
 	else if (entry->memdesc.size >= SZ_64K)
 		kgsl_memdesc_set_align(&entry->memdesc, ilog2(SZ_64));
 
-	result = kgsl_mmu_map(private->pagetable, &entry->memdesc);
-	if (result)
-		goto error_put_file_ptr;
-
-	/* Adjust the returned value for a non 4k aligned offset */
-	param->gpuaddr = entry->memdesc.gpuaddr + (param->offset & ~PAGE_MASK);
 	/* echo back flags */
 	param->flags = entry->memdesc.flags;
 
 	result = kgsl_mem_entry_attach_process(entry, private);
 	if (result)
-		goto error_unmap;
+		goto error_attach;
+
+	/* Adjust the returned value for a non 4k aligned offset */
+	param->gpuaddr = entry->memdesc.gpuaddr + (param->offset & ~PAGE_MASK);
 
 	KGSL_STATS_ADD(param->len, kgsl_driver.stats.mapped,
 		kgsl_driver.stats.mapped_max);
@@ -2133,9 +2211,7 @@
 
 	return result;
 
-error_unmap:
-	kgsl_mmu_unmap(private->pagetable, &entry->memdesc);
-error_put_file_ptr:
+error_attach:
 	switch (entry->memtype) {
 	case KGSL_MEM_ENTRY_PMEM:
 	case KGSL_MEM_ENTRY_ASHMEM:
@@ -2395,10 +2471,6 @@
 	if (result)
 		return result;
 
-	result = kgsl_mmu_map(private->pagetable, &entry->memdesc);
-	if (result)
-		goto err;
-
 	result = kgsl_mem_entry_attach_process(entry, private);
 	if (result != 0)
 		goto err;
@@ -2432,12 +2504,6 @@
 	if (result != 0)
 		goto err;
 
-	if (!kgsl_memdesc_use_cpu_map(&entry->memdesc)) {
-		result = kgsl_mmu_map(private->pagetable, &entry->memdesc);
-		if (result)
-			goto err;
-	}
-
 	result = kgsl_mem_entry_attach_process(entry, private);
 	if (result != 0)
 		goto err;
@@ -3021,8 +3087,30 @@
 			ret = ALIGN(ret, (1 << align));
 
 		/*make sure there isn't a GPU only mapping at this address */
-		if (kgsl_sharedmem_region_empty(private, ret, orig_len))
+		spin_lock(&private->mem_lock);
+		if (kgsl_sharedmem_region_empty(private, ret, orig_len)) {
+			int ret_val;
+			/*
+			 * We found a free memory map, claim it here with
+			 * memory lock held
+			 */
+			entry->memdesc.gpuaddr = ret;
+			/* This should never fail */
+			ret_val = kgsl_mem_entry_track_gpuaddr(private, entry);
+			spin_unlock(&private->mem_lock);
+			BUG_ON(ret_val);
+			/* map cannot be called with lock held */
+			ret_val = kgsl_mmu_map(private->pagetable,
+						&entry->memdesc);
+			if (ret_val) {
+				spin_lock(&private->mem_lock);
+				kgsl_mem_entry_untrack_gpuaddr(private, entry);
+				spin_unlock(&private->mem_lock);
+				ret = ret_val;
+			}
 			break;
+		}
+		spin_unlock(&private->mem_lock);
 
 		trace_kgsl_mem_unmapped_area_collision(entry, addr, orig_len,
 							ret);
@@ -3079,17 +3167,6 @@
 	if (ret)
 		return ret;
 
-	if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) {
-		entry->memdesc.gpuaddr = vma->vm_start;
-
-		ret = kgsl_mmu_map(private->pagetable, &entry->memdesc);
-		if (ret) {
-			kgsl_mem_entry_put(entry);
-			return ret;
-		}
-		kgsl_mem_entry_track_gpuaddr(private, entry);
-	}
-
 	vma->vm_flags |= entry->memdesc.ops->vmflags(&entry->memdesc);
 
 	vma->vm_private_data = entry;
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index 0983111..d05d391 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -156,8 +156,8 @@
 #define KGSL_MEMDESC_GLOBAL BIT(1)
 /* The memdesc is frozen during a snapshot */
 #define KGSL_MEMDESC_FROZEN BIT(2)
-/* The memdesc is scheduled to be freed on a timestamp */
-#define KGSL_MEMDESC_FREE_PENDING BIT(3)
+/* The memdesc is mapped into a pagetable */
+#define KGSL_MEMDESC_MAPPED BIT(3)
 
 /* shared memory allocation */
 struct kgsl_memdesc {
@@ -195,6 +195,8 @@
 	/* back pointer to private structure under whose context this
 	* allocation is made */
 	struct kgsl_process_private *priv;
+	/* Initialized to 0, set to 1 when entry is marked for freeing */
+	int pending_free;
 };
 
 #ifdef CONFIG_MSM_KGSL_MMU_PAGE_FAULT
diff --git a/drivers/gpu/msm/kgsl_drm.c b/drivers/gpu/msm/kgsl_drm.c
index 007f89a..daeefd0 100644
--- a/drivers/gpu/msm/kgsl_drm.c
+++ b/drivers/gpu/msm/kgsl_drm.c
@@ -224,10 +224,23 @@
 				return result;
 			}
 
+			result = kgsl_mmu_get_gpuaddr(priv->pagetable,
+							&priv->memdesc);
+			if (result) {
+				DRM_ERROR(
+				"kgsl_mmu_get_gpuaddr failed. result = %d\n",
+				result);
+				ion_free(kgsl_drm_ion_client,
+					priv->ion_handle);
+				priv->ion_handle = NULL;
+				return result;
+			}
 			result = kgsl_mmu_map(priv->pagetable, &priv->memdesc);
 			if (result) {
 				DRM_ERROR(
 				"kgsl_mmu_map failed.  result = %d\n", result);
+				kgsl_mmu_put_gpuaddr(priv->pagetable,
+							&priv->memdesc);
 				ion_free(kgsl_drm_ion_client,
 					priv->ion_handle);
 				priv->ion_handle = NULL;
@@ -273,10 +286,17 @@
 			priv->memdesc.sglen++;
 		}
 
+		result = kgsl_mmu_get_gpuaddr(priv->pagetable, &priv->memdesc);
+		if (result) {
+			DRM_ERROR(
+			"kgsl_mmu_get_gpuaddr failed.  result = %d\n", result);
+			goto memerr;
+		}
 		result = kgsl_mmu_map(priv->pagetable, &priv->memdesc);
 		if (result) {
 			DRM_ERROR(
 			"kgsl_mmu_map failed.  result = %d\n", result);
+			kgsl_mmu_put_gpuaddr(priv->pagetable, &priv->memdesc);
 			goto memerr;
 		}
 
@@ -311,8 +331,10 @@
 	if (!kgsl_gem_memory_allocated(obj) || TYPE_IS_FD(priv->type))
 		return;
 
-	if (priv->memdesc.gpuaddr)
+	if (priv->memdesc.gpuaddr) {
 		kgsl_mmu_unmap(priv->memdesc.pagetable, &priv->memdesc);
+		kgsl_mmu_put_gpuaddr(priv->memdesc.pagetable, &priv->memdesc);
+	}
 
 	/* ION will take care of freeing the sg table. */
 	priv->memdesc.sg = NULL;
@@ -645,9 +667,21 @@
 		priv->memdesc.sglen++;
 	}
 
+	ret = kgsl_mmu_get_gpuaddr(priv->pagetable, &priv->memdesc);
+	if (ret) {
+		DRM_ERROR("kgsl_mmu_get_gpuaddr failed.  ret = %d\n", ret);
+		ion_free(kgsl_drm_ion_client,
+			priv->ion_handle);
+		priv->ion_handle = NULL;
+		kgsl_mmu_putpagetable(priv->pagetable);
+		drm_gem_object_release(obj);
+		kfree(priv);
+		return -ENOMEM;
+	}
 	ret = kgsl_mmu_map(priv->pagetable, &priv->memdesc);
 	if (ret) {
 		DRM_ERROR("kgsl_mmu_map failed.  ret = %d\n", ret);
+		kgsl_mmu_put_gpuaddr(priv->pagetable, &priv->memdesc);
 		ion_free(kgsl_drm_ion_client,
 			priv->ion_handle);
 		priv->ion_handle = NULL;
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 12a4b25..952019f 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -613,15 +613,20 @@
 }
 EXPORT_SYMBOL(kgsl_mh_start);
 
+/**
+ * kgsl_mmu_get_gpuaddr - Assign a memdesc with a gpuadddr from the gen pool
+ * @pagetable - pagetable whose pool is to be used
+ * @memdesc - memdesc to which gpuaddr is assigned
+ *
+ * returns - 0 on success else error code
+ */
 int
-kgsl_mmu_map(struct kgsl_pagetable *pagetable,
-				struct kgsl_memdesc *memdesc)
+kgsl_mmu_get_gpuaddr(struct kgsl_pagetable *pagetable,
+			struct kgsl_memdesc *memdesc)
 {
-	int ret;
 	struct gen_pool *pool = NULL;
 	int size;
 	int page_align = ilog2(PAGE_SIZE);
-	unsigned int protflags = kgsl_memdesc_protflags(memdesc);
 
 	if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE) {
 		if (memdesc->sglen == 1) {
@@ -693,6 +698,28 @@
 			return -ENOMEM;
 		}
 	}
+	return 0;
+}
+EXPORT_SYMBOL(kgsl_mmu_get_gpuaddr);
+
+int
+kgsl_mmu_map(struct kgsl_pagetable *pagetable,
+				struct kgsl_memdesc *memdesc)
+{
+	int ret = 0;
+	int size;
+	unsigned int protflags = kgsl_memdesc_protflags(memdesc);
+
+	if (!memdesc->gpuaddr)
+		return -EINVAL;
+	/* Only global mappings should be mapped multiple times */
+	if (!kgsl_memdesc_is_global(memdesc) &&
+		(KGSL_MEMDESC_MAPPED & memdesc->priv))
+		return -EINVAL;
+	/* Add space for the guard page when allocating the mmu VA. */
+	size = memdesc->size;
+	if (kgsl_memdesc_has_guard_page(memdesc))
+		size += PAGE_SIZE;
 
 	if (KGSL_MMU_TYPE_IOMMU != kgsl_mmu_get_mmutype())
 		spin_lock(&pagetable->lock);
@@ -702,7 +729,7 @@
 		spin_lock(&pagetable->lock);
 
 	if (ret)
-		goto err_free_gpuaddr;
+		goto done;
 
 	/* Keep track of the statistics for the sysfs files */
 
@@ -713,34 +740,76 @@
 		       pagetable->stats.max_mapped);
 
 	spin_unlock(&pagetable->lock);
+	memdesc->priv |= KGSL_MEMDESC_MAPPED;
 
 	return 0;
 
-err_free_gpuaddr:
+done:
 	spin_unlock(&pagetable->lock);
-	if (pool)
-		gen_pool_free(pool, memdesc->gpuaddr, size);
-	memdesc->gpuaddr = 0;
 	return ret;
 }
 EXPORT_SYMBOL(kgsl_mmu_map);
 
+/**
+ * kgsl_mmu_put_gpuaddr - Free a gpuaddress from memory pool
+ * @pagetable - pagetable whose pool memory is freed from
+ * @memdesc - memdesc whose gpuaddress is freed
+ *
+ * returns - 0 on success else error code
+ */
+int
+kgsl_mmu_put_gpuaddr(struct kgsl_pagetable *pagetable,
+			struct kgsl_memdesc *memdesc)
+{
+	struct gen_pool *pool;
+	int size;
+
+	if (memdesc->size == 0 || memdesc->gpuaddr == 0)
+		return 0;
+
+	if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE)
+		goto done;
+
+	/* Add space for the guard page when freeing the mmu VA. */
+	size = memdesc->size;
+	if (kgsl_memdesc_has_guard_page(memdesc))
+		size += PAGE_SIZE;
+
+	pool = pagetable->pool;
+
+	if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype()) {
+		if (kgsl_memdesc_is_global(memdesc))
+			pool = pagetable->kgsl_pool;
+		else if (kgsl_memdesc_use_cpu_map(memdesc))
+			pool = NULL;
+	}
+	if (pool)
+		gen_pool_free(pool, memdesc->gpuaddr, size);
+	/*
+	 * Don't clear the gpuaddr on global mappings because they
+	 * may be in use by other pagetables
+	 */
+done:
+	if (!kgsl_memdesc_is_global(memdesc))
+		memdesc->gpuaddr = 0;
+	return 0;
+}
+EXPORT_SYMBOL(kgsl_mmu_put_gpuaddr);
+
 int
 kgsl_mmu_unmap(struct kgsl_pagetable *pagetable,
 		struct kgsl_memdesc *memdesc)
 {
-	struct gen_pool *pool;
 	int size;
 	unsigned int start_addr = 0;
 	unsigned int end_addr = 0;
 
-	if (memdesc->size == 0 || memdesc->gpuaddr == 0)
-		return 0;
+	if (memdesc->size == 0 || memdesc->gpuaddr == 0 ||
+		!(KGSL_MEMDESC_MAPPED & memdesc->priv))
+		return -EINVAL;
 
-	if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE) {
-		memdesc->gpuaddr = 0;
+	if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE)
 		return 0;
-	}
 
 	/* Add space for the guard page when freeing the mmu VA. */
 	size = memdesc->size;
@@ -767,24 +836,8 @@
 	pagetable->stats.mapped -= size;
 
 	spin_unlock(&pagetable->lock);
-
-	pool = pagetable->pool;
-
-	if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype()) {
-		if (kgsl_memdesc_is_global(memdesc))
-			pool = pagetable->kgsl_pool;
-		else if (kgsl_memdesc_use_cpu_map(memdesc))
-			pool = NULL;
-	}
-	if (pool)
-		gen_pool_free(pool, memdesc->gpuaddr, size);
-
-	/*
-	 * Don't clear the gpuaddr on global mappings because they
-	 * may be in use by other pagetables
-	 */
 	if (!kgsl_memdesc_is_global(memdesc))
-		memdesc->gpuaddr = 0;
+		memdesc->priv &= ~KGSL_MEMDESC_MAPPED;
 	return 0;
 }
 EXPORT_SYMBOL(kgsl_mmu_unmap);
@@ -805,9 +858,12 @@
 	gpuaddr = memdesc->gpuaddr;
 	memdesc->priv |= KGSL_MEMDESC_GLOBAL;
 
-	result = kgsl_mmu_map(pagetable, memdesc);
+	result = kgsl_mmu_get_gpuaddr(pagetable, memdesc);
 	if (result)
 		goto error;
+	result = kgsl_mmu_map(pagetable, memdesc);
+	if (result)
+		goto error_put_gpuaddr;
 
 	/*global mappings must have the same gpu address in all pagetables*/
 	if (gpuaddr && gpuaddr != memdesc->gpuaddr) {
@@ -818,6 +874,8 @@
 	return result;
 error_unmap:
 	kgsl_mmu_unmap(pagetable, memdesc);
+error_put_gpuaddr:
+	kgsl_mmu_put_gpuaddr(pagetable, memdesc);
 error:
 	return result;
 }
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index 27cfc40..faba81e 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -222,10 +222,14 @@
 int kgsl_mmu_close(struct kgsl_device *device);
 int kgsl_mmu_map(struct kgsl_pagetable *pagetable,
 		 struct kgsl_memdesc *memdesc);
+int kgsl_mmu_get_gpuaddr(struct kgsl_pagetable *pagetable,
+		 struct kgsl_memdesc *memdesc);
 int kgsl_mmu_map_global(struct kgsl_pagetable *pagetable,
 			struct kgsl_memdesc *memdesc);
 int kgsl_mmu_unmap(struct kgsl_pagetable *pagetable,
 		    struct kgsl_memdesc *memdesc);
+int kgsl_mmu_put_gpuaddr(struct kgsl_pagetable *pagetable,
+		 struct kgsl_memdesc *memdesc);
 unsigned int kgsl_virtaddr_to_physaddr(void *virtaddr);
 void kgsl_setstate(struct kgsl_mmu *mmu, unsigned int context_id,
 			uint32_t flags);
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index 01f0768..2939df6 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -781,8 +781,10 @@
 	if (memdesc == NULL || memdesc->size == 0)
 		return;
 
-	if (memdesc->gpuaddr)
+	if (memdesc->gpuaddr) {
 		kgsl_mmu_unmap(memdesc->pagetable, memdesc);
+		kgsl_mmu_put_gpuaddr(memdesc->pagetable, memdesc);
+	}
 
 	if (memdesc->ops && memdesc->ops->free)
 		memdesc->ops->free(memdesc);
diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h
index 985b9b8..9f84690 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.h
+++ b/drivers/gpu/msm/kgsl_sharedmem.h
@@ -260,6 +260,11 @@
 	ret = kgsl_sharedmem_page_alloc(memdesc, pagetable, size);
 	if (ret)
 		return ret;
+	ret = kgsl_mmu_get_gpuaddr(pagetable, memdesc);
+	if (ret) {
+		kgsl_sharedmem_free(memdesc);
+		return ret;
+	}
 	ret = kgsl_mmu_map(pagetable, memdesc);
 	if (ret)
 		kgsl_sharedmem_free(memdesc);
diff --git a/drivers/media/platform/msm/camera_v2/Kconfig b/drivers/media/platform/msm/camera_v2/Kconfig
index 116fb72..3a30970 100644
--- a/drivers/media/platform/msm/camera_v2/Kconfig
+++ b/drivers/media/platform/msm/camera_v2/Kconfig
@@ -155,6 +155,15 @@
 		1280 * 270. It does not support auto focus. It supports
 		few special effects like saturation.
 
+config SP1628
+	bool "Sensor SP1628 (YUV 720P)"
+	depends on MSMB_CAMERA
+	---help---
+		SP1628 is SuperPix YUV sensor. It supports 720P preview
+		and snapshot. The preview and snapshot resolution shall be
+		1280 * 270. It does not support auto focus. It supports
+		few special effects like mono.
+
 config OV8825
 	bool "OmniVision OV8825 (BAYER 8MP)"
 	depends on MSMB_CAMERA
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 c79e8e3..df72328 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
@@ -817,6 +817,7 @@
 	cpp_dev->cpp_open_cnt++;
 	if (cpp_dev->cpp_open_cnt == 1) {
 		cpp_init_hardware(cpp_dev);
+		iommu_attach_device(cpp_dev->domain, cpp_dev->iommu_ctx);
 		cpp_init_mem(cpp_dev);
 		cpp_dev->state = CPP_STATE_IDLE;
 	}
@@ -853,6 +854,7 @@
 	if (cpp_dev->cpp_open_cnt == 0) {
 		msm_camera_io_w(0x0, cpp_dev->base + MSM_CPP_MICRO_CLKEN_CTL);
 		cpp_deinit_mem(cpp_dev);
+		iommu_detach_device(cpp_dev->domain, cpp_dev->iommu_ctx);
 		cpp_release_hardware(cpp_dev);
 		cpp_dev->state = CPP_STATE_OFF;
 	}
@@ -1465,6 +1467,7 @@
 	return msm_register_domain(&cpp_fw_layout);
 }
 
+
 static int __devinit cpp_probe(struct platform_device *pdev)
 {
 	struct cpp_device *cpp_dev;
@@ -1579,7 +1582,6 @@
 	cpp_dev->msm_sd.sd.entity.revision = cpp_dev->msm_sd.sd.devnode->num;
 	cpp_dev->state = CPP_STATE_BOOT;
 	cpp_init_hardware(cpp_dev);
-	iommu_attach_device(cpp_dev->domain, cpp_dev->iommu_ctx);
 
 	msm_camera_io_w(0x0, cpp_dev->base +
 					   MSM_CPP_MICRO_IRQGEN_MASK);
@@ -1597,7 +1599,6 @@
 	cpp_dev->cpp_open_cnt = 0;
 	cpp_dev->is_firmware_loaded = 0;
 	return rc;
-
 ERROR3:
 	release_mem_region(cpp_dev->mem->start, resource_size(cpp_dev->mem));
 ERROR2:
@@ -1627,7 +1628,6 @@
 		return 0;
 	}
 
-	iommu_detach_device(cpp_dev->domain, cpp_dev->iommu_ctx);
 	msm_sd_unregister(&cpp_dev->msm_sd);
 	release_mem_region(cpp_dev->mem->start, resource_size(cpp_dev->mem));
 	release_mem_region(cpp_dev->vbif_mem->start,
diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
index 300daca..c188105 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
@@ -30,6 +30,7 @@
 static struct msm_actuator msm_vcm_actuator_table;
 static struct msm_actuator msm_piezo_actuator_table;
 
+static struct i2c_driver msm_actuator_i2c_driver;
 static struct msm_actuator *actuators[] = {
 	&msm_vcm_actuator_table,
 	&msm_piezo_actuator_table,
@@ -549,7 +550,11 @@
 		pr_err("failed\n");
 		return -EINVAL;
 	}
-	*subdev_id = a_ctrl->pdev->id;
+	if (a_ctrl->act_device_type == MSM_CAMERA_PLATFORM_DEVICE)
+		*subdev_id = a_ctrl->pdev->id;
+	else
+		*subdev_id = a_ctrl->subdev_id;
+
 	CDBG("subdev_id %d\n", *subdev_id);
 	CDBG("Exit\n");
 	return 0;
@@ -684,6 +689,11 @@
 	.core = &msm_actuator_subdev_core_ops,
 };
 
+static const struct i2c_device_id msm_actuator_i2c_id[] = {
+	{"qcom,actuator", (kernel_ulong_t)NULL},
+	{ }
+};
+
 static int32_t msm_actuator_i2c_probe(struct i2c_client *client,
 	const struct i2c_device_id *id)
 {
@@ -691,19 +701,46 @@
 	struct msm_actuator_ctrl_t *act_ctrl_t = NULL;
 	CDBG("Enter\n");
 
+	if (client == NULL) {
+		pr_err("msm_actuator_i2c_probe: client is null\n");
+		rc = -EINVAL;
+		goto probe_failure;
+	}
+
+	act_ctrl_t = kzalloc(sizeof(struct msm_actuator_ctrl_t),
+		GFP_KERNEL);
+	if (!act_ctrl_t) {
+		pr_err("%s:%d failed no memory\n", __func__, __LINE__);
+		return -ENOMEM;
+	}
+
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
 		pr_err("i2c_check_functionality failed\n");
 		goto probe_failure;
 	}
 
-	act_ctrl_t = (struct msm_actuator_ctrl_t *)(id->driver_data);
 	CDBG("client = %x\n", (unsigned int) client);
+
+	rc = of_property_read_u32(client->dev.of_node, "cell-index",
+		&act_ctrl_t->subdev_id);
+	CDBG("cell-index %d, rc %d\n", act_ctrl_t->subdev_id, rc);
+	if (rc < 0) {
+		pr_err("failed rc %d\n", rc);
+		return rc;
+	}
+
+	act_ctrl_t->i2c_driver = &msm_actuator_i2c_driver;
 	act_ctrl_t->i2c_client.client = client;
+	act_ctrl_t->curr_step_pos = 0,
+	act_ctrl_t->curr_region_index = 0,
 	/* Set device type as I2C */
 	act_ctrl_t->act_device_type = MSM_CAMERA_I2C_DEVICE;
 	act_ctrl_t->i2c_client.i2c_func_tbl = &msm_sensor_qup_func_tbl;
 	act_ctrl_t->act_v4l2_subdev_ops = &msm_actuator_subdev_ops;
 	act_ctrl_t->actuator_mutex = &msm_actuator_mutex;
+
+	act_ctrl_t->cam_name = act_ctrl_t->subdev_id;
+	CDBG("act_ctrl_t->cam_name: %d", act_ctrl_t->cam_name);
 	/* Assign name for sub device */
 	snprintf(act_ctrl_t->msm_sd.sd.name, sizeof(act_ctrl_t->msm_sd.sd.name),
 		"%s", act_ctrl_t->i2c_driver->driver.name);
@@ -720,7 +757,7 @@
 	act_ctrl_t->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_ACTUATOR;
 	act_ctrl_t->msm_sd.close_seq = MSM_SD_CLOSE_2ND_CATEGORY | 0x2;
 	msm_sd_register(&act_ctrl_t->msm_sd);
-	CDBG("succeeded\n");
+	pr_info("msm_actuator_i2c_probe: succeeded\n");
 	CDBG("Exit\n");
 
 probe_failure:
@@ -795,17 +832,21 @@
 	return rc;
 }
 
-static const struct i2c_device_id msm_actuator_i2c_id[] = {
-	{"msm_actuator", (kernel_ulong_t)NULL},
-	{ }
+static const struct of_device_id msm_actuator_i2c_dt_match[] = {
+	{.compatible = "qcom,actuator"},
+	{}
 };
 
+MODULE_DEVICE_TABLE(of, msm_actuator_i2c_dt_match);
+
 static struct i2c_driver msm_actuator_i2c_driver = {
 	.id_table = msm_actuator_i2c_id,
 	.probe  = msm_actuator_i2c_probe,
 	.remove = __exit_p(msm_actuator_i2c_remove),
 	.driver = {
-		.name = "msm_actuator",
+		.name = "qcom,actuator",
+		.owner = THIS_MODULE,
+		.of_match_table = msm_actuator_i2c_dt_match,
 	},
 };
 
diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.h b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.h
index c616307..c4a4137 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.h
@@ -80,6 +80,7 @@
 	struct msm_camera_i2c_reg_tbl *i2c_reg_tbl;
 	uint16_t i2c_tbl_index;
 	enum cci_i2c_master_t cci_master;
+	uint32_t subdev_id;
 };
 
 #endif
diff --git a/drivers/mfd/pm8xxx-pwm.c b/drivers/mfd/pm8xxx-pwm.c
index 0388484..eb8320f 100644
--- a/drivers/mfd/pm8xxx-pwm.c
+++ b/drivers/mfd/pm8xxx-pwm.c
@@ -262,6 +262,9 @@
 
 	chip = pwm->chip;
 
+	if (!pwm->banks)
+		pwm->banks = (PM_PWM_BANK_LO | PM_PWM_BANK_HI);
+
 	if (pwm->banks & PM_PWM_BANK_LO) {
 		if (enable)
 			reg = chip->lo_bank_mask | (1 << pwm->pwm_id);
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 3986cdd..e285bfa 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -3747,6 +3747,7 @@
 {
 	struct msmsdcc_host *host = mmc_priv(mmc);
 	unsigned long flags;
+	bool prev_pwrsave, curr_pwrsave;
 	int rc = 0;
 
 	switch (ios->signal_voltage) {
@@ -3779,7 +3780,9 @@
 	 * low voltage is required
 	 */
 	spin_lock_irqsave(&host->lock, flags);
-
+	prev_pwrsave = !!(readl_relaxed(host->base + MMCICLOCK) &
+			MCI_CLK_PWRSAVE);
+	curr_pwrsave = prev_pwrsave;
 	/*
 	 * Poll on MCIDATIN_3_0 and MCICMDIN bits of MCI_TEST_INPUT
 	 * register until they become all zeros.
@@ -3792,9 +3795,12 @@
 	}
 
 	/* Stop SD CLK output. */
-	writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
-			MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
-	msmsdcc_sync_reg_wr(host);
+	if (!prev_pwrsave) {
+		writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
+				MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
+		msmsdcc_sync_reg_wr(host);
+		curr_pwrsave = true;
+	}
 	spin_unlock_irqrestore(&host->lock, flags);
 
 	/*
@@ -3815,6 +3821,7 @@
 	writel_relaxed((readl_relaxed(host->base + MMCICLOCK)
 			& ~MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
 	msmsdcc_sync_reg_wr(host);
+	curr_pwrsave = false;
 	spin_unlock_irqrestore(&host->lock, flags);
 
 	/*
@@ -3835,10 +3842,9 @@
 	}
 
 out_unlock:
-	/* Enable PWRSAVE */
-	writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
-			MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
-	msmsdcc_sync_reg_wr(host);
+	/* Restore the correct PWRSAVE state */
+	if (prev_pwrsave ^ curr_pwrsave)
+		msmsdcc_set_pwrsave(mmc, prev_pwrsave);
 	spin_unlock_irqrestore(&host->lock, flags);
 out:
 	return rc;
@@ -3877,17 +3883,24 @@
 	int rc = 0;
 	unsigned long flags;
 	u32 wait_cnt;
+	bool prev_pwrsave, curr_pwrsave;
 
 	spin_lock_irqsave(&host->lock, flags);
+	prev_pwrsave = !!(readl_relaxed(host->base + MMCICLOCK) &
+			MCI_CLK_PWRSAVE);
+	curr_pwrsave = prev_pwrsave;
 	/*
 	 * Make sure that clock is always enabled when DLL
 	 * tuning is in progress. Keeping PWRSAVE ON may
 	 * turn off the clock. So let's disable the PWRSAVE
 	 * here and re-enable it once tuning is completed.
 	 */
-	writel_relaxed((readl_relaxed(host->base + MMCICLOCK)
-			& ~MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
-	msmsdcc_sync_reg_wr(host);
+	if (prev_pwrsave) {
+		writel_relaxed((readl_relaxed(host->base + MMCICLOCK)
+				& ~MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
+		msmsdcc_sync_reg_wr(host);
+		curr_pwrsave = false;
+	}
 
 	/* Write 1 to DLL_RST bit of MCI_DLL_CONFIG register */
 	writel_relaxed((readl_relaxed(host->base + MCI_DLL_CONFIG)
@@ -3930,10 +3943,9 @@
 	}
 
 out:
-	/* re-enable PWRSAVE */
-	writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
-			MCI_CLK_PWRSAVE), host->base + MMCICLOCK);
-	msmsdcc_sync_reg_wr(host);
+	/* Restore the correct PWRSAVE state */
+	if (prev_pwrsave ^ curr_pwrsave)
+		msmsdcc_set_pwrsave(host->mmc, prev_pwrsave);
 	spin_unlock_irqrestore(&host->lock, flags);
 
 	return rc;
diff --git a/drivers/net/wireless/wcnss/wcnss_vreg.c b/drivers/net/wireless/wcnss/wcnss_vreg.c
index c02daa4..2251f2f 100644
--- a/drivers/net/wireless/wcnss/wcnss_vreg.c
+++ b/drivers/net/wireless/wcnss/wcnss_vreg.c
@@ -100,7 +100,7 @@
 	{"qcom,iris-vddpa",  VREG_NULL_CONFIG, 2900000, 0,
 		3000000, 515000, NULL},
 	{"qcom,iris-vdddig", VREG_NULL_CONFIG, 1225000, 0,
-		1300000, 10000,  NULL},
+		1800000, 10000,  NULL},
 };
 
 /* WCNSS regulators for Pronto hardware */
diff --git a/drivers/platform/msm/qpnp-power-on.c b/drivers/platform/msm/qpnp-power-on.c
index d378838..087cfa8 100644
--- a/drivers/platform/msm/qpnp-power-on.c
+++ b/drivers/platform/msm/qpnp-power-on.c
@@ -43,9 +43,14 @@
 #define QPNP_PON_RESIN_S2_TIMER(base)		(base + 0x45)
 #define QPNP_PON_RESIN_S2_CNTL(base)		(base + 0x46)
 #define QPNP_PON_RESIN_S2_CNTL2(base)		(base + 0x47)
+#define QPNP_PON_KPDPWR_RESIN_S1_TIMER(base)	(base + 0x48)
+#define QPNP_PON_KPDPWR_RESIN_S2_TIMER(base)	(base + 0x49)
+#define QPNP_PON_KPDPWR_RESIN_S2_CNTL(base)	(base + 0x4A)
+#define QPNP_PON_KPDPWR_RESIN_S2_CNTL2(base)	(base + 0x4B)
 #define QPNP_PON_PS_HOLD_RST_CTL(base)		(base + 0x5A)
 #define QPNP_PON_PS_HOLD_RST_CTL2(base)		(base + 0x5B)
 #define QPNP_PON_TRIGGER_EN(base)		(base + 0x80)
+#define QPNP_PON_S3_DBC_CTL(base)		(base + 0x75)
 
 #define QPNP_PON_WARM_RESET_TFT			BIT(4)
 
@@ -65,6 +70,7 @@
 #define QPNP_PON_RESIN_N_SET			BIT(1)
 #define QPNP_PON_CBLPWR_N_SET			BIT(2)
 #define QPNP_PON_RESIN_BARK_N_SET		BIT(4)
+#define QPNP_PON_KPDPWR_RESIN_BARK_N_SET	BIT(5)
 
 #define QPNP_PON_RESET_EN			BIT(7)
 #define QPNP_PON_WARM_RESET			BIT(0)
@@ -73,6 +79,8 @@
 /* Ranges */
 #define QPNP_PON_S1_TIMER_MAX			10256
 #define QPNP_PON_S2_TIMER_MAX			2000
+#define QPNP_PON_S3_TIMER_SECS_MAX		128
+#define QPNP_PON_S3_DBC_DELAY_MASK		0x07
 #define QPNP_PON_RESET_TYPE_MAX			0xF
 #define PON_S1_COUNT_MAX			0xF
 
@@ -83,6 +91,7 @@
 	PON_KPDPWR,
 	PON_RESIN,
 	PON_CBLPWR,
+	PON_KPDPWR_RESIN,
 };
 
 struct qpnp_pon_config {
@@ -325,6 +334,9 @@
 	case PON_CBLPWR:
 		pon_rt_bit = QPNP_PON_CBLPWR_N_SET;
 		break;
+	case PON_KPDPWR_RESIN:
+		pon_rt_bit = QPNP_PON_KPDPWR_RESIN_BARK_N_SET;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -364,6 +376,11 @@
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t qpnp_kpdpwr_resin_bark_irq(int irq, void *_pon)
+{
+	return IRQ_HANDLED;
+}
+
 static irqreturn_t qpnp_cblpwr_irq(int irq, void *_pon)
 {
 	int rc;
@@ -477,6 +494,9 @@
 	case PON_CBLPWR:
 		pull_bit = QPNP_PON_CBLPWR_PULL_UP;
 		break;
+	case PON_KPDPWR_RESIN:
+		pull_bit = QPNP_PON_KPDPWR_PULL_UP | QPNP_PON_RESIN_PULL_UP;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -505,6 +525,10 @@
 		s1_timer_addr = QPNP_PON_RESIN_S1_TIMER(pon->base);
 		s2_timer_addr = QPNP_PON_RESIN_S2_TIMER(pon->base);
 		break;
+	case PON_KPDPWR_RESIN:
+		s1_timer_addr = QPNP_PON_KPDPWR_RESIN_S1_TIMER(pon->base);
+		s2_timer_addr = QPNP_PON_KPDPWR_RESIN_S2_TIMER(pon->base);
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -624,6 +648,20 @@
 			return rc;
 		}
 		break;
+	case PON_KPDPWR_RESIN:
+		if (cfg->support_reset) {
+			rc = devm_request_irq(&pon->spmi->dev, cfg->bark_irq,
+					qpnp_kpdpwr_resin_bark_irq,
+					IRQF_TRIGGER_RISING,
+					"qpnp_kpdpwr_resin_bark", pon);
+			if (rc < 0) {
+				dev_err(&pon->spmi->dev,
+					"Can't request %d IRQ\n",
+						cfg->bark_irq);
+				return rc;
+			}
+		}
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -663,11 +701,11 @@
 	int rc = 0, i = 0;
 	struct device_node *pp = NULL;
 	struct qpnp_pon_config *cfg;
-	u8 reg;
+	u8 pon_ver;
 
 	/* Check if it is rev B */
 	rc = spmi_ext_register_readl(pon->spmi->ctrl, pon->spmi->sid,
-			QPNP_PON_REVISION2(pon->base), &reg, 1);
+			QPNP_PON_REVISION2(pon->base), &pon_ver, 1);
 	if (rc) {
 		dev_err(&pon->spmi->dev,
 			"Unable to read addr=%x, rc(%d)\n",
@@ -714,7 +752,7 @@
 				}
 			}
 
-			if (reg == QPNP_PON_REV_B) {
+			if (pon_ver == QPNP_PON_REV_B) {
 				cfg->s2_cntl_addr =
 					QPNP_PON_KPDPWR_S2_CNTL(pon->base);
 				cfg->s2_cntl2_addr =
@@ -752,7 +790,7 @@
 				}
 			}
 
-			if (reg == QPNP_PON_REV_B) {
+			if (pon_ver == QPNP_PON_REV_B) {
 				cfg->s2_cntl_addr =
 					QPNP_PON_RESIN_S2_CNTL(pon->base);
 				cfg->s2_cntl2_addr =
@@ -772,6 +810,36 @@
 				return rc;
 			}
 			break;
+		case PON_KPDPWR_RESIN:
+			rc = of_property_read_u32(pp, "qcom,support-reset",
+							&cfg->support_reset);
+			if (rc && rc != -EINVAL) {
+				dev_err(&pon->spmi->dev,
+					"Unable to read 'support-reset'\n");
+				return rc;
+			}
+
+			if (cfg->support_reset) {
+				cfg->bark_irq = spmi_get_irq_byname(pon->spmi,
+						NULL, "kpdpwr-resin-bark");
+				if (cfg->bark_irq < 0) {
+					dev_err(&pon->spmi->dev,
+					"Unable to get kpdpwr-resin-bark irq\n");
+					return cfg->bark_irq;
+				}
+			}
+
+			if (pon_ver == QPNP_PON_REV_B) {
+				cfg->s2_cntl_addr =
+				QPNP_PON_KPDPWR_RESIN_S2_CNTL(pon->base);
+				cfg->s2_cntl2_addr =
+				QPNP_PON_KPDPWR_RESIN_S2_CNTL2(pon->base);
+			} else {
+				cfg->s2_cntl_addr = cfg->s2_cntl2_addr =
+				QPNP_PON_KPDPWR_RESIN_S2_CNTL(pon->base);
+			}
+
+			break;
 		default:
 			dev_err(&pon->spmi->dev, "PON RESET %d not supported",
 								cfg->pon_type);
@@ -819,13 +887,14 @@
 					"Incorrect reset type specified\n");
 				return -EINVAL;
 			}
+
 		}
 		/*
 		 * Get the standard-key parameters. This might not be
 		 * specified if there is no key mapping on the reset line.
 		 */
 		rc = of_property_read_u32(pp, "linux,code", &cfg->key_code);
-		if (rc && rc == -EINVAL) {
+		if (rc && rc != -EINVAL) {
 			dev_err(&pon->spmi->dev,
 				"Unable to read key-code\n");
 			return rc;
@@ -896,7 +965,7 @@
 	struct qpnp_pon *pon;
 	struct resource *pon_resource;
 	struct device_node *itr = NULL;
-	u32 delay = 0;
+	u32 delay = 0, s3_debounce = 0;
 	int rc, sys_reset;
 
 	pon = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_pon),
@@ -956,6 +1025,32 @@
 		}
 	}
 
+	/* program s3 debounce */
+	rc = of_property_read_u32(pon->spmi->dev.of_node,
+				"qcom,s3-debounce", &s3_debounce);
+	if (rc) {
+		if (rc != -EINVAL) {
+			dev_err(&pon->spmi->dev, "Unable to read s3 timer\n");
+			return rc;
+		}
+	} else {
+		if (s3_debounce > QPNP_PON_S3_TIMER_SECS_MAX) {
+			dev_info(&pon->spmi->dev,
+				"Exceeded S3 max value, set it to max\n");
+			s3_debounce = QPNP_PON_S3_TIMER_SECS_MAX;
+		}
+
+		/* 0 is a special value to indicate instant s3 reset */
+		if (s3_debounce != 0)
+			s3_debounce = ilog2(s3_debounce);
+		rc = qpnp_pon_masked_write(pon, QPNP_PON_S3_DBC_CTL(pon->base),
+				QPNP_PON_S3_DBC_DELAY_MASK, s3_debounce);
+		if (rc) {
+			dev_err(&spmi->dev, "Unable to set S3 debounce\n");
+			return rc;
+		}
+	}
+
 	dev_set_drvdata(&spmi->dev, pon);
 
 	INIT_DELAYED_WORK(&pon->bark_work, bark_work_func);
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index 4d464c1..7f669d8 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -245,6 +245,48 @@
 #define UARTDM_TO_MSM(uart_port) \
 	container_of((uart_port), struct msm_hs_port, uport)
 
+
+static int msm_hs_ioctl(struct uart_port *uport, unsigned int cmd,
+						unsigned long arg)
+{
+	int ret = 0, state = 1;
+	enum msm_hs_clk_states_e clk_state;
+	unsigned long flags;
+	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
+
+	switch (cmd) {
+	case MSM_ENABLE_UART_CLOCK: {
+		pr_debug("%s():ENABLE UART CLOCK: cmd=%d\n", __func__, cmd);
+		msm_hs_request_clock_on(&msm_uport->uport);
+		break;
+	}
+	case MSM_DISABLE_UART_CLOCK: {
+		pr_debug("%s():DISABLE UART CLOCK: cmd=%d\n", __func__, cmd);
+		msm_hs_request_clock_off(&msm_uport->uport);
+		break;
+	}
+	case MSM_GET_UART_CLOCK_STATUS: {
+		/* Return value 0 - UART CLOCK is OFF
+		 * Return value 1 - UART CLOCK is ON */
+		pr_debug("%s():GET UART CLOCK STATUS: cmd=%d\n", __func__, cmd);
+		spin_lock_irqsave(&msm_uport->uport.lock, flags);
+		clk_state = msm_uport->clk_state;
+		spin_unlock_irqrestore(&msm_uport->uport.lock, flags);
+		if (clk_state <= MSM_HS_CLK_OFF)
+			state = 0;
+		ret = state;
+		break;
+	}
+	default: {
+		pr_debug("%s():Unknown cmd specified: cmd=%d\n", __func__, cmd);
+		ret = -ENOIOCTLCMD;
+		break;
+	}
+	}
+
+	return ret;
+}
+
 static ssize_t show_clock(struct device *dev, struct device_attribute *attr,
 			  char *buf)
 {
@@ -3307,6 +3349,7 @@
 	.release_port = msm_hs_release_port,
 	.request_port = msm_hs_request_port,
 	.flush_buffer = msm_hs_flush_buffer,
+	.ioctl = msm_hs_ioctl,
 };
 
 module_init(msm_serial_hs_init);
diff --git a/drivers/tty/serial/msm_serial_hs_hwreg.h b/drivers/tty/serial/msm_serial_hs_hwreg.h
index cdd0450..cd24f23 100644
--- a/drivers/tty/serial/msm_serial_hs_hwreg.h
+++ b/drivers/tty/serial/msm_serial_hs_hwreg.h
@@ -32,6 +32,10 @@
 #define ADM1_CRCI_GSBI6_RX_SEL         0x800
 #define ADM1_CRCI_GSBI6_TX_SEL         0x400
 
+#define MSM_ENABLE_UART_CLOCK 13
+#define MSM_DISABLE_UART_CLOCK 14
+#define MSM_GET_UART_CLOCK_STATUS 15
+
 enum msm_hsl_regs {
 	UARTDM_MR1,
 	UARTDM_MR2,
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 6aeb26e..f31481f 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -381,15 +381,29 @@
  */
 static u32 dwc3_msm_ssusb_read_phycreg(void *base, u32 addr)
 {
+	bool first_read = true;
+
 	iowrite32(addr, base + SS_CR_PROTOCOL_DATA_IN_REG);
 	iowrite32(0x1, base + SS_CR_PROTOCOL_CAP_ADDR_REG);
 	while (ioread32(base + SS_CR_PROTOCOL_CAP_ADDR_REG))
 		cpu_relax();
 
+	/*
+	 * Due to hardware bug, first read of SSPHY register might be
+	 * incorrect. Hence as workaround, SW should perform SSPHY register
+	 * read twice, but use only second read and ignore first read.
+	 */
+retry:
 	iowrite32(0x1, base + SS_CR_PROTOCOL_READ_REG);
 	while (ioread32(base + SS_CR_PROTOCOL_READ_REG))
 		cpu_relax();
 
+	if (first_read) {
+		ioread32(base + SS_CR_PROTOCOL_DATA_OUT_REG);
+		first_read = false;
+		goto retry;
+	}
+
 	return ioread32(base + SS_CR_PROTOCOL_DATA_OUT_REG);
 }
 
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 1059a4d..63698de 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -36,6 +36,7 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
@@ -56,6 +57,11 @@
 #include "debug.h"
 #include "io.h"
 
+static bool tx_fifo_resize_enable;
+module_param(tx_fifo_resize_enable, bool, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(tx_fifo_resize_enable,
+			"Enable allocating Tx fifo for endpoints");
+
 /**
  * dwc3_gadget_set_test_mode - Enables USB2 Test Modes
  * @dwc: pointer to our context structure
@@ -178,7 +184,7 @@
 	int		mdwidth;
 	int		num;
 
-	if (!dwc->needs_fifo_resize)
+	if (!dwc->needs_fifo_resize && !tx_fifo_resize_enable)
 		return 0;
 
 	ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7);
diff --git a/drivers/usb/gadget/f_adb.c b/drivers/usb/gadget/f_adb.c
index ff2287e..55f5b80 100644
--- a/drivers/usb/gadget/f_adb.c
+++ b/drivers/usb/gadget/f_adb.c
@@ -662,7 +662,7 @@
 {
 	struct adb_dev *dev = _adb_dev;
 
-	printk(KERN_INFO "adb_bind_config\n");
+	pr_debug("adb_bind_config\n");
 
 	dev->cdev = c->cdev;
 	dev->function.name = "adb";
diff --git a/drivers/usb/gadget/f_rmnet.c b/drivers/usb/gadget/f_rmnet.c
index f095efb..6dcc3b4 100644
--- a/drivers/usb/gadget/f_rmnet.c
+++ b/drivers/usb/gadget/f_rmnet.c
@@ -1121,7 +1121,7 @@
 			goto fail;
 	}
 
-	pr_info("%s: RmNet(%d) %s Speed, IN:%s OUT:%s\n",
+	pr_debug("%s: RmNet(%d) %s Speed, IN:%s OUT:%s\n",
 			__func__, dev->port_num,
 			gadget_is_dualspeed(cdev->gadget) ? "dual" : "full",
 			dev->port.in->name, dev->port.out->name);
diff --git a/drivers/usb/gadget/u_bam.c b/drivers/usb/gadget/u_bam.c
index edcafcc..c71d79c 100644
--- a/drivers/usb/gadget/u_bam.c
+++ b/drivers/usb/gadget/u_bam.c
@@ -639,6 +639,7 @@
 			gbam_epout_complete, GFP_ATOMIC);
 	if (ret) {
 		pr_err("%s: rx req allocation failed\n", __func__);
+		spin_unlock_irqrestore(&port->port_lock_ul, flags);
 		return;
 	}
 
@@ -655,6 +656,7 @@
 	if (ret) {
 		pr_err("%s: tx req allocation failed\n", __func__);
 		gbam_free_requests(ep, &d->rx_idle);
+		spin_unlock_irqrestore(&port->port_lock_dl, flags);
 		return;
 	}
 
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index c2e8943..0b89dd0 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -28,6 +28,7 @@
 #include <linux/pm_runtime.h>
 
 #include <linux/usb/otg.h>
+#include <linux/usb/msm_hsusb.h>
 #include <linux/usb/msm_hsusb_hw.h>
 
 #define MSM_USB_BASE (hcd->regs)
@@ -51,7 +52,13 @@
 	/* Use the AHB transactor */
 	writel_relaxed(0x08, USB_AHBMODE);
 	/* Disable streaming mode and select host mode */
-	writel(0x13, USB_USBMODE);
+	writel_relaxed(0x13, USB_USBMODE);
+
+	if (ehci->transceiver->flags & ENABLE_SECONDARY_PHY) {
+		ehci_dbg(ehci, "using secondary hsphy\n");
+		writel_relaxed(readl_relaxed(USB_PHY_CTRL2) | (1<<16),
+							USB_PHY_CTRL2);
+	}
 
 	ehci_port_power(ehci, 1);
 	return 0;
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 111f26b..c168907 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1881,8 +1881,6 @@
 {
 	int delta = 0;
 
-	if (headroom < NET_SKB_PAD)
-		headroom = NET_SKB_PAD;
 	if (headroom > skb_headroom(skb))
 		delta = headroom - skb_headroom(skb);
 
diff --git a/scripts/build-all.py b/scripts/build-all.py
index 4789af7..c585e4a 100755
--- a/scripts/build-all.py
+++ b/scripts/build-all.py
@@ -88,6 +88,7 @@
         r'[fm]sm[0-9]*_defconfig',
         r'apq*_defconfig',
         r'qsd*_defconfig',
+	r'msmkrypton*_defconfig',
         )
     for p in arch_pats:
         for n in glob.glob('arch/arm/configs/' + p):
diff --git a/sound/soc/codecs/msm8x10-wcd.c b/sound/soc/codecs/msm8x10-wcd.c
index 807cdad..f3c6ef8 100644
--- a/sound/soc/codecs/msm8x10-wcd.c
+++ b/sound/soc/codecs/msm8x10-wcd.c
@@ -50,6 +50,11 @@
 
 #define MSM8X10_WCD_I2S_MASTER_MODE_MASK	0x08
 #define MSM8X10_DINO_CODEC_BASE_ADDR		0xFE043000
+#define MSM8x10_TLMM_CDC_PULL_CTL			0xFD512050
+#define HELICON_CORE_0_I2C_ADDR				0x0d
+#define HELICON_CORE_1_I2C_ADDR				0x77
+#define HELICON_CORE_2_I2C_ADDR				0x66
+#define HELICON_CORE_3_I2C_ADDR				0x55
 
 #define MAX_MSM8X10_WCD_DEVICE	4
 #define CODEC_DT_MAX_PROP_SIZE	40
@@ -2400,6 +2405,15 @@
 }
 EXPORT_SYMBOL_GPL(msm8x10_wcd_hs_detect);
 
+static int msm8x10_wcd_bringup(struct snd_soc_codec *codec)
+{
+	snd_soc_write(codec, MSM8X10_WCD_A_CDC_RST_CTL, 0x02);
+	snd_soc_write(codec, MSM8X10_WCD_A_CHIP_CTL, 0x00);
+	usleep_range(5000, 5000);
+	snd_soc_write(codec, MSM8X10_WCD_A_CDC_RST_CTL, 0x03);
+	return 0;
+}
+
 static int msm8x10_wcd_codec_probe(struct snd_soc_codec *codec)
 {
 	struct msm8x10_wcd_priv *msm8x10_wcd;
@@ -2422,6 +2436,7 @@
 	codec->control_data = dev_get_drvdata(codec->dev);
 	snd_soc_codec_set_drvdata(codec, msm8x10_wcd);
 	msm8x10_wcd->codec = codec;
+	msm8x10_wcd_bringup(codec);
 	msm8x10_wcd_codec_init_reg(codec);
 	msm8x10_wcd_update_reg_defaults(codec);
 
@@ -2557,13 +2572,27 @@
 	kfree(msm8x10->supplies);
 }
 
-static int msm8x10_wcd_bringup(struct msm8x10_wcd *msm8x10)
+static int msm8x10_wcd_pads_config(void)
 {
-	msm8x10->read_dev = msm8x10_wcd_reg_read;
-	msm8x10->write_dev(msm8x10, MSM8X10_WCD_A_CDC_RST_CTL, 0x02);
-	msm8x10->write_dev(msm8x10, MSM8X10_WCD_A_CHIP_CTL, 0x00);
-	usleep_range(5000, 5000);
-	msm8x10->write_dev(msm8x10, MSM8X10_WCD_A_CDC_RST_CTL, 0x03);
+	/* Set I2C pads as pull up and rest of pads as no pull */
+	iowrite32(0x03C00000, ioremap(MSM8x10_TLMM_CDC_PULL_CTL, 4));
+	usleep_range(100, 200);
+	return 0;
+}
+
+
+static int msm8x10_wcd_clk_init(void)
+{
+	/* Div-2 */
+	iowrite32(0x3, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CFG_RCGR, 4));
+	iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_M, 4));
+	iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_N, 4));
+	iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_D, 4));
+	/* Digital codec clock enable */
+	iowrite32(0x1, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CBCR, 4));
+	/* Set the update bit to make the settings go through */
+	iowrite32(0x1, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CMD_RCGR, 4));
+	usleep_range(100, 200);
 	return 0;
 }
 
@@ -2573,11 +2602,8 @@
 	mutex_init(&msm8x10->xfer_lock);
 	mutex_init(&msm8x10->pm_lock);
 	msm8x10->wlock_holders = 0;
-
-	iowrite32(0x03C00000, ioremap(0xFD512050, 4));
-	usleep_range(5000, 5000);
-
-	msm8x10_wcd_bringup(msm8x10);
+	msm8x10_wcd_pads_config();
+	msm8x10_wcd_clk_init();
 	return 0;
 }
 
@@ -2589,15 +2615,44 @@
 	struct msm8x10_wcd_pdata *pdata;
 	static int device_id;
 	struct device *dev;
+	enum apr_subsys_state q6_state;
 
-	dev_dbg(&client->dev, "%s:slave addr = 0x%x device_id = %d\n",
-		__func__, client->addr, device_id);
+	dev_dbg(&client->dev, "%s(%d):slave addr = 0x%x device_id = %d\n",
+		__func__, __LINE__,  client->addr, device_id);
 
-	if (device_id > 0) {
-		msm8x10_wcd_modules[device_id++].client = client;
+	switch (client->addr) {
+	case HELICON_CORE_0_I2C_ADDR:
+		msm8x10_wcd_modules[0].client = client;
+		break;
+	case HELICON_CORE_1_I2C_ADDR:
+		msm8x10_wcd_modules[1].client = client;
+		goto rtn;
+	case HELICON_CORE_2_I2C_ADDR:
+		msm8x10_wcd_modules[2].client = client;
+		goto rtn;
+	case HELICON_CORE_3_I2C_ADDR:
+		msm8x10_wcd_modules[3].client = client;
+		goto rtn;
+	default:
+		ret = -EINVAL;
 		goto rtn;
 	}
 
+	q6_state = apr_get_q6_state();
+	if ((q6_state == APR_SUBSYS_DOWN) &&
+	    (client->addr == HELICON_CORE_0_I2C_ADDR)) {
+		dev_info(&client->dev, "defering %s, adsp_state %d\n", __func__,
+			q6_state);
+		return -EPROBE_DEFER;
+	} else
+		dev_info(&client->dev, "adsp is ready\n");
+
+	dev_dbg(&client->dev, "%s(%d):slave addr = 0x%x device_id = %d\n",
+		__func__, __LINE__,  client->addr, device_id);
+
+	if (client->addr != HELICON_CORE_0_I2C_ADDR)
+		goto rtn;
+
 	dev = &client->dev;
 	if (client->dev.of_node) {
 		dev_dbg(&client->dev, "%s:Platform data from device tree\n",
@@ -2619,7 +2674,6 @@
 	}
 
 	msm8x10->dev = &client->dev;
-	msm8x10_wcd_modules[device_id++].client = client;
 	msm8x10->read_dev = msm8x10_wcd_reg_read;
 	msm8x10->write_dev = msm8x10_wcd_reg_write;
 	ret = msm8x10_wcd_enable_supplies(msm8x10, pdata);
diff --git a/sound/soc/codecs/msm8x10-wcd.h b/sound/soc/codecs/msm8x10-wcd.h
index d250e0a..08a2725 100644
--- a/sound/soc/codecs/msm8x10-wcd.h
+++ b/sound/soc/codecs/msm8x10-wcd.h
@@ -23,6 +23,15 @@
 #define MSM8X10_WCD_NUM_IRQ_REGS	3
 #define MAX_REGULATOR				7
 #define MSM8X10_WCD_REG_VAL(reg, val)		{reg, 0, val}
+#define MSM8X10_DINO_LPASS_AUDIO_CORE_DIG_CODEC_CLK_SEL	0xFE03B004
+#define MSM8X10_DINO_LPASS_DIGCODEC_CMD_RCGR			0xFE02C000
+#define MSM8X10_DINO_LPASS_DIGCODEC_CFG_RCGR			0xFE02C004
+#define MSM8X10_DINO_LPASS_DIGCODEC_M				0xFE02C008
+#define MSM8X10_DINO_LPASS_DIGCODEC_N				0xFE02C00C
+#define MSM8X10_DINO_LPASS_DIGCODEC_D				0xFE02C010
+#define MSM8X10_DINO_LPASS_DIGCODEC_CBCR			0xFE02C014
+#define MSM8X10_DINO_LPASS_DIGCODEC_AHB_CBCR			0xFE02C018
+
 
 #define MSM8X10_WCD_IS_DINO_REG(reg) \
 	(((reg >= 0x400) && (reg <= 0x5FF)) ? 1 : 0)
diff --git a/sound/soc/msm/msm-pcm-host-voice.c b/sound/soc/msm/msm-pcm-host-voice.c
index 36826cc..2eafc1d 100644
--- a/sound/soc/msm/msm-pcm-host-voice.c
+++ b/sound/soc/msm/msm-pcm-host-voice.c
@@ -941,7 +941,8 @@
 						struct hpcm_buf_node, list);
 			list_del(&buf_node->list);
 			spin_unlock_irqrestore(&dai_data->dsp_lock, dsp_flags);
-			ret = copy_from_user(&buf_node->frame, buf, count);
+			ret = copy_from_user(&buf_node->frame.voc_pkt,
+					     buf, count);
 			buf_node->frame.len = count;
 			spin_lock_irqsave(&dai_data->dsp_lock, dsp_flags);
 			list_add_tail(&buf_node->list, &dai_data->filled_queue);
@@ -986,7 +987,9 @@
 					struct hpcm_buf_node, list);
 			list_del(&buf_node->list);
 			spin_unlock_irqrestore(&dai_data->dsp_lock, dsp_flags);
-			ret = copy_to_user(buf, &buf_node->frame, count);
+			ret = copy_to_user(buf,
+					   &buf_node->frame.voc_pkt,
+					   count);
 			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 22cd61a..9782b2d 100644
--- a/sound/soc/msm/msm8226.c
+++ b/sound/soc/msm/msm8226.c
@@ -126,6 +126,7 @@
 static struct clk *codec_clk;
 static int clk_users;
 static int vdd_spkr_gpio = -1;
+static int msm_proxy_rx_ch = 2;
 
 static int msm_snd_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable,
 					bool dapm)
@@ -235,6 +236,8 @@
 
 static const char *const slim0_rx_ch_text[] = {"One", "Two"};
 static const char *const slim0_tx_ch_text[] = {"One", "Two", "Three", "Four"};
+static const char *const proxy_rx_ch_text[] = {"One", "Two", "Three", "Four",
+	"Five", "Six", "Seven", "Eight"};
 
 static const struct soc_enum msm_enum[] = {
 	SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
@@ -349,6 +352,23 @@
 	return 0;
 }
 
+static int msm_proxy_rx_ch_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	pr_debug("%s: msm_proxy_rx_ch = %d\n", __func__,
+						msm_proxy_rx_ch);
+	ucontrol->value.integer.value[0] = msm_proxy_rx_ch - 1;
+	return 0;
+}
+
+static int msm_proxy_rx_ch_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	msm_proxy_rx_ch = ucontrol->value.integer.value[0] + 1;
+	pr_debug("%s: msm_proxy_rx_ch = %d\n", __func__,
+						msm_proxy_rx_ch);
+	return 1;
+}
 static int msm_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
 					struct snd_pcm_hw_params *params)
 {
@@ -364,15 +384,31 @@
 	return 0;
 }
 
-static int msm_proxy_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
-			struct snd_pcm_hw_params *params)
+static int msm_proxy_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+					struct snd_pcm_hw_params *params)
 {
 	struct snd_interval *rate = hw_param_interval(params,
-	SNDRV_PCM_HW_PARAM_RATE);
+					SNDRV_PCM_HW_PARAM_RATE);
 
-	pr_debug("%s()\n", __func__);
+	struct snd_interval *channels = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_CHANNELS);
+
+	pr_debug("%s: msm_proxy_rx_ch =%d\n", __func__, msm_proxy_rx_ch);
+
+	if (channels->max < 2)
+		channels->min = channels->max = 2;
+	channels->min = channels->max = msm_proxy_rx_ch;
 	rate->min = rate->max = 48000;
+	return 0;
+}
 
+static int msm_proxy_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+					struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *rate = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_RATE);
+
+	rate->min = rate->max = 48000;
 	return 0;
 }
 
@@ -535,6 +571,7 @@
 static const struct soc_enum msm_snd_enum[] = {
 	SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
 	SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
+	SOC_ENUM_SINGLE_EXT(8, proxy_rx_ch_text),
 };
 
 static const struct snd_kcontrol_new msm_snd_controls[] = {
@@ -546,6 +583,8 @@
 			msm8226_auxpcm_rate_get, msm8226_auxpcm_rate_put),
 	SOC_ENUM_EXT("Internal BTSCO SampleRate", msm_btsco_enum[0],
 		     msm_btsco_rate_get, msm_btsco_rate_put),
+	SOC_ENUM_EXT("PROXY_RX Channels", msm_snd_enum[2],
+			msm_proxy_rx_ch_get, msm_proxy_rx_ch_put),
 };
 
 static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
@@ -1049,7 +1088,7 @@
 		.codec_dai_name = "msm-stub-rx",
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
-		.be_hw_params_fixup = msm_proxy_be_hw_params_fixup,
+		.be_hw_params_fixup = msm_proxy_rx_be_hw_params_fixup,
 		/* this dainlink has playback support */
 		.ignore_pmdown_time = 1,
 		.ignore_suspend = 1,
@@ -1063,7 +1102,7 @@
 		.codec_dai_name = "msm-stub-tx",
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
-		.be_hw_params_fixup = msm_proxy_be_hw_params_fixup,
+		.be_hw_params_fixup = msm_proxy_tx_be_hw_params_fixup,
 		.ignore_suspend = 1,
 	},
 	/* HDMI Hostless */
diff --git a/sound/soc/msm/msm8x10.c b/sound/soc/msm/msm8x10.c
index ce6cfea..a076246 100644
--- a/sound/soc/msm/msm8x10.c
+++ b/sound/soc/msm/msm8x10.c
@@ -40,14 +40,6 @@
 static int msm_proxy_rx_ch = 2;
 static struct snd_soc_jack hs_jack;
 
-#define MSM8X10_DINO_LPASS_AUDIO_CORE_DIG_CODEC_CLK_SEL	0xFE03B004
-#define MSM8X10_DINO_LPASS_DIGCODEC_CMD_RCGR			0xFE02C000
-#define MSM8X10_DINO_LPASS_DIGCODEC_CFG_RCGR			0xFE02C004
-#define MSM8X10_DINO_LPASS_DIGCODEC_M				0xFE02C008
-#define MSM8X10_DINO_LPASS_DIGCODEC_N				0xFE02C00C
-#define MSM8X10_DINO_LPASS_DIGCODEC_D				0xFE02C010
-#define MSM8X10_DINO_LPASS_DIGCODEC_CBCR			0xFE02C014
-#define MSM8X10_DINO_LPASS_DIGCODEC_AHB_CBCR			0xFE02C018
 
 /*
  * There is limitation for the clock root selection from
@@ -89,7 +81,8 @@
 	0,
 };
 
-static atomic_t aud_init_rsc_ref;
+static atomic_t mclk_rsc_ref;
+static struct mutex cdc_mclk_mutex;
 
 static int msm8x10_mclk_event(struct snd_soc_dapm_widget *w,
 			      struct snd_kcontrol *kcontrol, int event);
@@ -103,69 +96,9 @@
 
 };
 
-/*
- * This function will be replaced by
- * afe_set_lpass_internal_digital_codec_clock(port_id, cfg)
- * in the future after LPASS API fix
- */
-static int msm_enable_lpass_mclk(void)
-{
-	/* Select the codec root */
-	iowrite32(DIG_CDC_CLK_SEL_DIG_CODEC,
-		  ioremap(MSM8X10_DINO_LPASS_AUDIO_CORE_DIG_CODEC_CLK_SEL,
-		  4));
-	/* Div-2 */
-	iowrite32(0x3, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CFG_RCGR, 4));
-	iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_M, 4));
-	iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_N, 4));
-	iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_D, 4));
-	/* Digital codec clock enable */
-	iowrite32(0x1, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CBCR, 4));
-	/* AHB clock enable */
-	iowrite32(0x1, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_AHB_CBCR, 4));
-	/* Set the update bit to make the settings go through */
-	iowrite32(0x1, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CMD_RCGR, 4));
-
-	return 0;
-}
-
-static int msm_enable_mclk_root(u16 port_id, struct afe_digital_clk_cfg *cfg)
-{
-	int ret = 0;
-	/*
-	  * msm_enable_lpass_mclk() function call will be replaced by
-	  * ret =  afe_set_lpass_internal_digital_codec_clock(port_id, cfg)
-	  * in the future. Currentlt there is a bug in LPASS plan which
-	  * doesn't consider the digital codec clock. It will be fixed soon
-	  * in new Q6 image
-	  */
-	msm_enable_lpass_mclk();
-	pr_debug("%s(): return = %d\n", __func__, ret);
-	return ret;
-}
-
 static int msm_config_mclk(u16 port_id, struct afe_digital_clk_cfg *cfg)
 {
-	/* Select the codec root */
-	iowrite32(DIG_CDC_CLK_SEL_DIG_CODEC,
-		  ioremap(MSM8X10_DINO_LPASS_AUDIO_CORE_DIG_CODEC_CLK_SEL,
-		  4));
-	/* Div-2 */
-	iowrite32(0x3, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CFG_RCGR, 4));
-	iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_M, 4));
-	iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_N, 4));
-	iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_D, 4));
-	/* Digital codec clock enable */
-	if (cfg->clk_val == 0) {
-		iowrite32(0x0, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CBCR, 4));
-		pr_debug("%s(line %d)\n", __func__, __LINE__);
-	} else {
-		iowrite32(0x1, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CBCR, 4));
-		pr_debug("%s(line %d)\n", __func__, __LINE__);
-	}
 	iowrite32(0x1, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CBCR, 4));
-	/* AHB clock enable */
-	iowrite32(0x1, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_AHB_CBCR, 4));
 	/* Set the update bit to make the settings go through */
 	iowrite32(0x1, ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CMD_RCGR, 4));
 
@@ -173,42 +106,6 @@
 
 }
 
-static int msm_config_mi2s_clk(int enable)
-{
-	int ret = 0;
-	pr_debug("%s(line %d):enable = %x\n", __func__, __LINE__, enable);
-	if (enable) {
-		digital_cdc_clk.clk_val = 9600000;
-		mi2s_rx_clk.clk_val2 = Q6AFE_LPASS_OSR_CLK_12_P288_MHZ;
-		mi2s_rx_clk.clk_val1 = Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ;
-		ret = afe_set_lpass_clock(AFE_PORT_ID_SECONDARY_MI2S_RX,
-					  &mi2s_rx_clk);
-		mi2s_tx_clk.clk_val2 = Q6AFE_LPASS_OSR_CLK_12_P288_MHZ;
-		mi2s_tx_clk.clk_val1 = Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ;
-		ret = afe_set_lpass_clock(AFE_PORT_ID_PRIMARY_MI2S_RX,
-					  &mi2s_tx_clk);
-		if (ret < 0)
-			pr_err("%s:afe_set_lpass_clock failed\n", __func__);
-
-	} else {
-		digital_cdc_clk.clk_val = 0;
-		mi2s_rx_clk.clk_val2 = Q6AFE_LPASS_OSR_CLK_DISABLE;
-		mi2s_rx_clk.clk_val1 = Q6AFE_LPASS_IBIT_CLK_DISABLE;
-		ret = afe_set_lpass_clock(AFE_PORT_ID_SECONDARY_MI2S_RX,
-					  &mi2s_rx_clk);
-		mi2s_tx_clk.clk_val2 = Q6AFE_LPASS_OSR_CLK_DISABLE;
-		mi2s_tx_clk.clk_val1 = Q6AFE_LPASS_IBIT_CLK_DISABLE;
-		ret = afe_set_lpass_clock(AFE_PORT_ID_PRIMARY_MI2S_RX,
-					  &mi2s_tx_clk);
-		if (ret < 0)
-			pr_err("%s:afe_set_lpass_clock failed\n", __func__);
-
-	}
-	ret = msm_config_mclk(AFE_PORT_ID_SECONDARY_MI2S_RX, &digital_cdc_clk);
-	return ret;
-}
-
-
 static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
 				struct snd_pcm_hw_params *params)
 {
@@ -284,7 +181,6 @@
 			pr_err("%s:afe_set_lpass_clock failed\n", __func__);
 
 	}
-	ret = msm_config_mclk(AFE_PORT_ID_SECONDARY_MI2S_RX, &digital_cdc_clk);
 	return ret;
 }
 
@@ -293,20 +189,27 @@
 {
 	int ret = 0;
 
-	pr_debug("%s: enable = %d  codec name %s enable %x\n",
-		   __func__, enable, codec->name, enable);
+	mutex_lock(&cdc_mclk_mutex);
+
+	pr_debug("%s: enable = %d  codec name %s enable %d mclk ref counter %d\n",
+		   __func__, enable, codec->name, enable,
+		   atomic_read(&mclk_rsc_ref));
 	if (enable) {
-		digital_cdc_clk.clk_val = 9600000;
-		msm_config_mi2s_clk(1);
-		ret = msm_config_mclk(AFE_PORT_ID_SECONDARY_MI2S_RX,
-					   &digital_cdc_clk);
-		msm8x10_wcd_mclk_enable(codec, 1, dapm);
+		if (atomic_inc_return(&mclk_rsc_ref) == 1) {
+			digital_cdc_clk.clk_val = 9600000;
+			msm_config_mclk(AFE_PORT_ID_SECONDARY_MI2S_RX,
+					&digital_cdc_clk);
+			msm8x10_wcd_mclk_enable(codec, 1, dapm);
+		}
 	} else {
-		msm8x10_wcd_mclk_enable(codec, 0, dapm);
-		ret = msm_config_mclk(AFE_PORT_ID_SECONDARY_MI2S_RX,
-					   &digital_cdc_clk);
-		msm_config_mi2s_clk(0);
+		if (atomic_dec_return(&mclk_rsc_ref) == 0) {
+			digital_cdc_clk.clk_val = 0;
+			msm8x10_wcd_mclk_enable(codec, 0, dapm);
+			msm_config_mclk(AFE_PORT_ID_SECONDARY_MI2S_RX,
+					&digital_cdc_clk);
+		}
 	}
+	mutex_unlock(&cdc_mclk_mutex);
 	return ret;
 }
 
@@ -363,27 +266,17 @@
 
 	pr_debug("%s(),dev_name%s\n", __func__, dev_name(cpu_dai->dev));
 
-	pr_debug("%s(): aud_init_rsc_ref counter = %d\n",
-		__func__, atomic_read(&aud_init_rsc_ref));
-	if (atomic_inc_return(&aud_init_rsc_ref) != 1)
-		goto exit;
-
 	snd_soc_dapm_new_controls(dapm, msm8x10_dapm_widgets,
 				ARRAY_SIZE(msm8x10_dapm_widgets));
 
 	snd_soc_dapm_sync(dapm);
-	ret =  msm_enable_mclk_root(AFE_PORT_ID_SECONDARY_MI2S_RX,
-				    &digital_cdc_clk);
 
 	ret = snd_soc_jack_new(codec, "Headset Jack",
 			SND_JACK_HEADSET, &hs_jack);
-
 	if (ret) {
 		pr_err("%s: Failed to create headset jack\n", __func__);
-		return ret;
 	}
 
-exit:
 	return ret;
 }
 
@@ -804,9 +697,8 @@
 			ret);
 		goto err;
 	}
-
-	atomic_set(&aud_init_rsc_ref, 0);
-
+	mutex_init(&cdc_mclk_mutex);
+	atomic_set(&mclk_rsc_ref, 0);
 	return 0;
 err:
 	return ret;
@@ -817,7 +709,7 @@
 	struct snd_soc_card *card = platform_get_drvdata(pdev);
 
 	snd_soc_unregister_card(card);
-
+	mutex_destroy(&cdc_mclk_mutex);
 	return 0;
 }
 
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index 2fabca1..87bee75 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -2761,6 +2761,12 @@
 	/* reset LCH mode */
 	v->lch_mode = 0;
 
+	/* clear mute setting */
+	v->dev_rx.dev_mute =  common.default_mute_val;
+	v->dev_tx.dev_mute =  common.default_mute_val;
+	v->stream_rx.stream_mute = common.default_mute_val;
+	v->stream_tx.stream_mute = common.default_mute_val;
+
 	/* detach VOCPROC and wait for response from mvm */
 	mvm_d_vocproc_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
 						APR_HDR_LEN(APR_HDR_SIZE),
@@ -4182,6 +4188,15 @@
 			pr_err("setup voice failed\n");
 			goto fail;
 		}
+
+		ret = voice_send_vol_index_cmd(v);
+		if (ret < 0)
+			pr_err("voice volume failed\n");
+
+		ret = voice_send_stream_mute_cmd(v);
+		if (ret < 0)
+			pr_err("voice mute failed\n");
+
 		ret = voice_send_start_voice_cmd(v);
 		if (ret < 0) {
 			pr_err("start voice failed\n");
@@ -4891,7 +4906,7 @@
 	memset(&common, 0, sizeof(struct common_data));
 
 	/* set default value */
-	common.default_mute_val = 1;  /* default is mute */
+	common.default_mute_val = 0;  /* default is un-mute */
 	common.default_vol_val = 0;
 	common.default_sample_val = 8000;
 
@@ -4907,8 +4922,8 @@
 
 		/* initialize dev_rx and dev_tx */
 		common.voice[i].dev_rx.volume = common.default_vol_val;
-		common.voice[i].dev_rx.dev_mute =  0;
-		common.voice[i].dev_tx.dev_mute =  0;
+		common.voice[i].dev_rx.dev_mute =  common.default_mute_val;
+		common.voice[i].dev_tx.dev_mute =  common.default_mute_val;
 		common.voice[i].stream_rx.stream_mute = common.default_mute_val;
 		common.voice[i].stream_tx.stream_mute = common.default_mute_val;