Merge "thermal: tsens: Add local initialization flag"
diff --git a/Documentation/ABI/testing/sysfs-bus-msm_subsys b/Documentation/ABI/testing/sysfs-bus-msm_subsys
index fcfb1d4..f915a46 100644
--- a/Documentation/ABI/testing/sysfs-bus-msm_subsys
+++ b/Documentation/ABI/testing/sysfs-bus-msm_subsys
@@ -16,3 +16,16 @@
 
 		This file supports poll(3) to detect when a subsystem changes
 		state. Use POLLPRI to detect state changes.
+
+What:		/sys/bus/msm_subsys/devices/.../restart_level
+Date:		December 2012
+Contact:	Stephen Boyd <sboyd@codeaurora.org>
+Description:
+		Shows the restart level of a subsystem. The level is taken into
+		account when the subsystem is restarted via
+		subsystem_restart{_dev}(). Current supported states are:
+
+			SYSTEM	- reset the entire system
+			RELATED	- reset this subsystem and the other subsystems
+				  related to this one. Having no other
+				  subsystems related to this subsystem is valid.
diff --git a/Documentation/devicetree/bindings/arm/msm/qcom-wdog-debug.txt b/Documentation/devicetree/bindings/arm/msm/qcom-wdog-debug.txt
deleted file mode 100644
index e5fd1b2..0000000
--- a/Documentation/devicetree/bindings/arm/msm/qcom-wdog-debug.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-* Qualcomm's Watchdog Debug Image Controller
-
-The Qualcomm's Watchdog debug image controller is used for enabling/disabling of
-watchdog debug image feature.
-
-Required properties:
-- compatible : should be "qcom,msm-wdog-debug"
-- reg : base page aligned physical base address of the controller and length of
-	memory mapped region.
-
-Example:
-
-	qcom,msm-wdog-debug@fc401000 {
-		compatible = "qcom,msm-wdogi-debug";
-		reg = <0xfc401000 0x1000>;
-	};
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt
index 7d19c03..5c426f2 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt
@@ -8,22 +8,45 @@
 - cell-index:				Specifies the controller used among the two controllers.
 - reg:					offset and length of the register set for the device.
 - vdd-supply:				Phandle for vdd regulator device node.
-- vdd-io-supply:			Phandle for vdd-io regulator device node.
-- vreg-supply:				Phandle for vreg regulator device node.
+- vddio-supply:				Phandle for vdd-io regulator device node.
+- vdda-supply:				Phandle for vreg regulator device node.
 - qcom,mdss-fb-map:			pHandle that specifies the framebuffer to which the
 					interface is mapped.
 
 Optional properties:
 - label:		        	A string used to describe the controller used.
+- qcom,supply-names:			A list of strings that lists the names of the
+					regulator supplies.
+- qcom,supply-type:			A list of strings that list the type of supply(ies)
+					mentioned above. This list maps in the order of
+					the supply names listed above.
+					  regulator = supply with controlled output
+					  switch = supply without controlled output. i.e.
+					  voltage switch
+- qcom,supply-min-voltage-level:	A list that specifies minimum voltage level
+					of supply(ies) mentioned above. This list maps
+					in the order of the supply names listed above.
+- qcom,supply-max-voltage-level:	A list that specifies maximum voltage level of
+					supply(ies) mentioned above. This list maps in
+					the order of the supply names listed above.
+- qcom,supply-peak-current:		A list that specifies the peak current that will
+					be drawn from the supply(ies) mentioned above. This
+					list maps in the order of the supply names listed above.
+
 
 Example:
         mdss_dsi0: qcom,mdss_dsi@fd922800 {
-                compatible = "qcom,mdss-dsi-ctrl";
-                label = "MDSS DSI CTRL->0";
-                cell-index = <0>;
-                reg = <0xfd922800 0x600>;
-                vdd-supply = <&pm8941_l22>;
-                vdd_io-supply = <&pm8941_l12>;
-                vreg-supply = <&pm8941_l2>;
+		compatible = "qcom,mdss-dsi-ctrl";
+		label = "MDSS DSI CTRL->0";
+		cell-index = <0>;
+		reg = <0xfd922800 0x600>;
+		vdd-supply = <&pm8226_l15>;
+		vddio-supply = <&pm8226_l8>;
+		vdda-supply = <&pm8226_l4>;
+		qcom,supply-names = "vdd", "vddio", "vdda";
+		qcom,supply-type = "regulator", "regulator", "regulator";
+		qcom,supply-min-voltage-level = <2800000 1800000 1200000>;
+		qcom,supply-max-voltage-level = <2800000 1800000 1200000>;
+		qcom,supply-peak-current = <150000 100000 100000>;
 		qcom,mdss-fb-map = <&mdss_fb0>;
         };
diff --git a/Documentation/devicetree/bindings/power/qpnp-bms.txt b/Documentation/devicetree/bindings/power/qpnp-bms.txt
index 708ada1..5b22752 100644
--- a/Documentation/devicetree/bindings/power/qpnp-bms.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-bms.txt
@@ -40,13 +40,16 @@
 			The bms will not accept new ocvs between these
 			thresholds.
 - qcom,low-soc-calculate-soc-threshold : The SoC threshold for when
-			the period calculate_soc work speeds up. This ensures
+			the periodic calculate_soc work speeds up. This ensures
 			SoC is updated in userspace constantly when we are near
 			shutdown.
+- qcom,low-voltage-threshold : The battery voltage threshold in micro-volts for
+			when the BMS tries to wake up and hold a wakelock to
+			ensure a clean shutdown.
 - qcom,low-soc-calculate-soc-ms : The time period between subsequent
-
 			SoC recalculations when the current SoC is below
-			qcom,low-soc-calculate-soc-threshold.
+			qcom,low-soc-calculate-soc-threshold or when battery
+			voltage is below qcom,low-voltage-threshold.
 - qcom,soc-calculate-soc-ms : The time period between subsequent SoC
 			recalculations when the current SoC is above or equal
 			qcom,low-soc-calculate-soc-threshold.
@@ -107,6 +110,7 @@
 	qcom,adjust-soc-low-threshold = <25>;
 	qcom,adjust-soc-high-threshold = <45>;
 	qcom,low-soc-calculate-soc-threshold = <15>;
+	qcom,low-voltage-threshold = <3420000>;
 	qcom,low-soc-calculate-soc-ms = <5000>;
 	qcom,calculate-soc-ms = <20000>;
 	qcom,chg-term-ua = <100000>;
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index df88caa..02c2871 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -172,115 +172,90 @@
             If SSUSB_BAM is used, "ssusb" should be present.
             If HSUSB_BAM is used, "hsusb" should be present.
             If HSIC_BAM is used, "hsic" should be present.
-- qcom,usb-active-bam: active BAM type. Can be one of
-            0 - SSUSB_BAM
-            1 - HSUSB_BAM
-            2 - HSIC_BAM
-- qcom,usb-total-bam-num: total number of BAMs that are supported
 - qcom,usb-bam-num-pipes: max number of pipes that can be used
 - qcom,usb-base-address: physical base address of the BAM
 
 A number of USB BAM pipe parameters are represented as sub-nodes:
 
 Subnode Required:
-- label: a string describing the pipe's direction and BAM instance under use
-- qcom,usb-bam-type: BAM type. Can be one of
-            0 - SSUSB_BAM
-            1 - HSUSB_BAM
-            2 - HSIC_BAM
+- label: a string describing uniquely the usb bam pipe. The string can be
+  constracted as follows: <core>-<peer>-<direction>-<pipe num>.
+	core options: hsusb, ssusb/dwc3, hsic
+	peer options: qdss, ipa, a2
+	direction options: in (from peer to usb), out (from usb to peer)
+	pipe num options: 0..127
 - qcom,usb-bam-mem-type: Type of memory used by this PIPE. Can be one of
             0 - Uses SPS's dedicated pipe memory
             1 - USB's private memory residing @ 'qcom,usb-base-address'
             2 - System RAM allocated by driver
-- qcom,src-bam-physical-address: source BAM physical address
-- qcom,src-bam-pipe-index: source BAM pipe index
-- qcom,dst-bam-physical-address: destination BAM physical address
-- qcom,dst-bam-pipe-index: destination BAM pipe index
-- qcom,data-fifo-offset: data fifo offset address
+- qcom,bam-type: BAM type can be one of
+	0 - SSUSB_BAM
+	1 - HSUSB_BAM
+	2 - HSIC_BAM
+- qcom,dir: pipe direction
+	0 - from usb (out)
+	1 - to usb (in)
+- qcom,pipe-num: pipe number
+- qcom,peer-bam: peer BAM can be one of
+	0 - A2_P_BAM
+	1 - QDSS_P_BAM
+	2 - IPA_P_BAM
 - qcom,data-fifo-size: data fifo size
-- qcom,descriptor-fifo-offset: descriptor fifo offset address
 - qcom,descriptor-fifo-size: descriptor fifo size
 
 Optional Properties for Subnode:
 - qcom,reset-bam-on-connect: If present then BAM is RESET before connecting
   pipe. This may be required if BAM peripheral is also reset before connect.
+- qcom,dst-bam-physical-address: destination BAM physical address
+- qcom,dst-bam-pipe-index: destination BAM pipe index
+- qcom,src-bam-physical-address: source BAM physical address
+- qcom,src-bam-pipe-index: source BAM pipe index
+- qcom,data-fifo-offset: data fifo offset address
+- qcom,descriptor-fifo-offset: descriptor fifo offset address
 
 Optional properties :
 - qcom,ignore-core-reset-ack: If present then BAM ignores ACK from USB core
 	    while performing PIPE RESET
 - qcom,disable-clk-gating: If present then disable BAM clock gating.
 
-
 Example USB BAM controller device node:
 
-	qcom,usbbam@f9304000 {
+	qcom,usbbam@f9a44000 {
 		compatible = "qcom,usb-bam-msm";
-		reg = <0xf9304000 0x5000>,
-		      <0xf9a44000 0x11000>,
-		      <0xf92f880c 0x4>;
-		reg-names = "ssusb", "hsusb", "qscratch_ram1_reg";
-		interrupts = <0 132 0 0 135 0>;
-		interrupt-names = "ssusb", "hsusb";
-		qcom,usb-active-bam = <0>;
-		qcom,usb-total-bam-num = <2>;
+		reg = <0xf9a44000 0x11000>;
+		reg-names = "hsusb";
+		interrupts = <0 135 0>;
+		interrupt-names = "hsusb";
 		qcom,usb-bam-num-pipes = <16>;
-		qcom,usb-base-address = <0xf9200000>;
 		qcom,ignore-core-reset-ack;
+		qcom,disable-clk-gating;
 
+		qcom,pipe0 {
+			label = "hsusb-ipa-out-0";
+			qcom,usb-bam-mem-type = <0>;
+			qcom,bam-type = <1>;
+			qcom,dir = <0>;
+			qcom,pipe-num = <0>;
+			qcom,peer-bam = <2>;
+			qcom,src-bam-physical-address = <0xf9a44000>;
+			qcom,src-bam-pipe-index = <1>;
+			qcom,data-fifo-offset = <0x2200>;
+			qcom,data-fifo-size = <0x1e00>;
+			qcom,descriptor-fifo-offset = <0x2100>;
+			qcom,descriptor-fifo-size = <0x100>;
+		};
 		qcom,pipe1 {
-			label = "usb-to-peri-qdss-dwc3";
-			qcom,usb-bam-type = <0>;
-			qcom,usb-bam-mem-type = <1>;
-			qcom,src-bam-physical-address = <0>;
-			qcom,src-bam-pipe-index = <0>;
-			qcom,dst-bam-physical-address = <0>;
-			qcom,dst-bam-pipe-index = <0>;
-			qcom,data-fifo-offset = <0>;
-			qcom,data-fifo-size = <0>;
-			qcom,descriptor-fifo-offset = <0>;
-			qcom,descriptor-fifo-size = <0>;
-		};
-
-		qcom,pipe2 {
-			label = "peri-to-usb-qdss-dwc3";
-			qcom,usb-bam-type = <0>;
-			qcom,usb-bam-mem-type = <1>;
-			qcom,src-bam-physical-address = <0xfc37C000>;
-			qcom,src-bam-pipe-index = <0>;
-			qcom,dst-bam-physical-address = <0xf9304000>;
-			qcom,dst-bam-pipe-index = <2>;
-			qcom,data-fifo-offset = <0xf0000>;
-			qcom,data-fifo-size = <0x4000>;
-			qcom,descriptor-fifo-offset = <0xf4000>;
-			qcom,descriptor-fifo-size = <0x1400>;
-			qcom,reset-bam-on-connect;
-		};
-
-		qcom,pipe3 {
-			label = "usb-to-peri-qdss-hsusb";
-			qcom,usb-bam-type = <1>;
-			qcom,usb-bam-mem-type = <1>;
-			qcom,src-bam-physical-address = <0>;
-			qcom,src-bam-pipe-index = <0>;
-			qcom,dst-bam-physical-address = <0>;
-			qcom,dst-bam-pipe-index = <0>;
-			qcom,data-fifo-offset = <0>;
-			qcom,data-fifo-size = <0>;
-			qcom,descriptor-fifo-offset = <0>;
-			qcom,descriptor-fifo-size = <0>;
-		};
-
-		qcom,pipe4 {
-			label = "peri-to-usb-qdss-hsusb";
-			qcom,usb-bam-type = <1>;
-			qcom,usb-bam-mem-type = <1>;
-			qcom,src-bam-physical-address = <0xfc37c000>;
-			qcom,src-bam-pipe-index = <0>;
+			label = "hsusb-ipa-in-0";
+			qcom,usb-bam-mem-type = <0>;
+			qcom,bam-type = <1>;
+			qcom,dir = <1>;
+			qcom,pipe-num = <0>;
+			qcom,peer-bam = <2>;
 			qcom,dst-bam-physical-address = <0xf9a44000>;
-			qcom,dst-bam-pipe-index = <2>;
-			qcom,data-fifo-offset = <0xf4000>;
-			qcom,data-fifo-size = <0x1000>;
-			qcom,descriptor-fifo-offset = <0xf5000>;
-			qcom,descriptor-fifo-size = <0x400>;
+			qcom,dst-bam-pipe-index = <0>;
+			qcom,data-fifo-offset = <0x300>;
+			qcom,data-fifo-size = <0x1e00>;
+			qcom,descriptor-fifo-offset = <0>;
+			qcom,descriptor-fifo-size = <0x300>;
 		};
 	};
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index d456303..320c3e4a 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -111,6 +111,7 @@
 			qcom,calculate-soc-ms = <20000>;
 			qcom,chg-term-ua = <100000>;
 			qcom,batt-type = <0>;
+			qcom,low-voltage-threshold = <3420000>;
 
 			qcom,bms-iadc@3800 {
 				reg = <0x3800 0x100>;
diff --git a/arch/arm/boot/dts/msm8226-cdp.dts b/arch/arm/boot/dts/msm8226-cdp.dts
index ec4b464b..fa77c35 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dts
+++ b/arch/arm/boot/dts/msm8226-cdp.dts
@@ -87,6 +87,10 @@
 			vdd-phy-supply = <&pm8226_lvs1>;
 		};
 	};
+
+	sound {
+		qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
+	};
 };
 
 &sdcc1 {
@@ -178,6 +182,14 @@
 
 &pm8226_gpios {
 	gpio@c000 { /* GPIO 1 */
+		/* XO_PMIC_CDC_MCLK enable for tapan codec */
+		qcom,mode = <1>;		/* Digital output */
+		qcom,output-type = <0>;	/* CMOS logic */
+		qcom,pull = <5>;		/* QPNP_PIN_PULL_NO*/
+		qcom,vin-sel = <2>;		/* QPNP_PIN_VIN2 */
+		qcom,out-strength = <3>;/* QPNP_PIN_OUT_STRENGTH_HIGH */
+		qcom,src-sel = <2>;		/* QPNP_PIN_SEL_FUNC_1 */
+		qcom,master-en = <1>;	/* Enable GPIO */
 	};
 
 	gpio@c100 { /* GPIO 2 */
@@ -227,3 +239,8 @@
 	mpp@a700 { /* MPP 8 */
 	};
 };
+
+&pm8226_chg {
+	qcom,chg-charging-disabled;
+	qcom,chg-use-default-batt-values;
+};
diff --git a/arch/arm/boot/dts/msm8226-coresight.dtsi b/arch/arm/boot/dts/msm8226-coresight.dtsi
index 8d5d23c..30d79df 100644
--- a/arch/arm/boot/dts/msm8226-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8226-coresight.dtsi
@@ -142,12 +142,72 @@
 		coresight-child-ports = <7>;
 	};
 
+	etm0: etm@fc33c000 {
+		compatible = "arm,coresight-etm";
+		reg = <0xfc33c000 0x1000>;
+		reg-names = "etm0-base";
+
+		coresight-id = <10>;
+		coresight-name = "coresight-etm0";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_a7ss>;
+		coresight-child-ports = <0>;
+
+		qcom,round-robin;
+	};
+
+	etm1: etm@fc33d000 {
+		compatible = "arm,coresight-etm";
+		reg = <0xfc33d000 0x1000>;
+		reg-names = "etm1-base";
+
+		coresight-id = <11>;
+		coresight-name = "coresight-etm1";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_a7ss>;
+		coresight-child-ports = <1>;
+
+		qcom,round-robin;
+	};
+
+	etm2: etm@fc33e000 {
+		compatible = "arm,coresight-etm";
+		reg = <0xfc33e000 0x1000>;
+		reg-names = "etm2-base";
+
+		coresight-id = <12>;
+		coresight-name = "coresight-etm2";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_a7ss>;
+		coresight-child-ports = <2>;
+
+		qcom,round-robin;
+	};
+
+	etm3: etm@fc33f000 {
+		compatible = "arm,coresight-etm";
+		reg = <0xfc33f000 0x1000>;
+		reg-names = "etm3-base";
+
+		coresight-id = <13>;
+		coresight-name = "coresight-etm3";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_a7ss>;
+		coresight-child-ports = <3>;
+
+		qcom,round-robin;
+	};
+
 	csr: csr@fc302000 {
 		compatible = "qcom,coresight-csr";
 		reg = <0xfc302000 0x1000>;
 		reg-names = "csr-base";
 
-		coresight-id = <10>;
+		coresight-id = <14>;
 		coresight-name = "coresight-csr";
 		coresight-nr-inports = <0>;
 
diff --git a/arch/arm/boot/dts/msm8226-mdss.dtsi b/arch/arm/boot/dts/msm8226-mdss.dtsi
index 30a89ef..21ed66a 100644
--- a/arch/arm/boot/dts/msm8226-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8226-mdss.dtsi
@@ -59,8 +59,13 @@
 		cell-index = <0>;
 		reg = <0xfd922800 0x600>;
 		vdd-supply = <&pm8226_l15>;
-		vdd_io-supply = <&pm8226_l8>;
-		vreg-supply = <&pm8226_l4>;
+		vddio-supply = <&pm8226_l8>;
+		vdda-supply = <&pm8226_l4>;
+		qcom,supply-names = "vdd", "vddio", "vdda";
+		qcom,supply-type = "regulator", "regulator", "regulator";
+		qcom,supply-min-voltage-level = <2800000 1800000 1200000>;
+		qcom,supply-max-voltage-level = <2800000 1800000 1200000>;
+		qcom,supply-peak-current = <150000 100000 100000>;
 		qcom,mdss-fb-map = <&mdss_fb0>;
 	};
 
diff --git a/arch/arm/boot/dts/msm8226-mtp.dts b/arch/arm/boot/dts/msm8226-mtp.dts
index 57fb4b5..e747cb5 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dts
+++ b/arch/arm/boot/dts/msm8226-mtp.dts
@@ -87,6 +87,10 @@
 			vdd-phy-supply = <&pm8226_lvs1>;
 		};
 	};
+
+	sound {
+		qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
+	};
 };
 
 &sdcc1 {
@@ -175,6 +179,14 @@
 
 &pm8226_gpios {
 	gpio@c000 { /* GPIO 1 */
+		/* XO_PMIC_CDC_MCLK enable for tapan codec */
+		qcom,mode = <1>;		/* Digital output */
+		qcom,output-type = <0>;	/* CMOS logic */
+		qcom,pull = <5>;		/* QPNP_PIN_PULL_NO*/
+		qcom,vin-sel = <2>;		/* QPNP_PIN_VIN2 */
+		qcom,out-strength = <3>;/* QPNP_PIN_OUT_STRENGTH_HIGH */
+		qcom,src-sel = <2>;		/* QPNP_PIN_SEL_FUNC_1 */
+		qcom,master-en = <1>;	/* Enable GPIO */
 	};
 
 	gpio@c100 { /* GPIO 2 */
diff --git a/arch/arm/boot/dts/msm8226-qrd.dts b/arch/arm/boot/dts/msm8226-qrd.dts
index 09b2d0b..acc4597 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dts
+++ b/arch/arm/boot/dts/msm8226-qrd.dts
@@ -87,6 +87,10 @@
 			vdd-phy-supply = <&pm8226_lvs1>;
 		};
 	};
+
+	sound {
+		qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
+	};
 };
 
 &sdcc1 {
@@ -178,6 +182,14 @@
 
 &pm8226_gpios {
 	gpio@c000 { /* GPIO 1 */
+		/* XO_PMIC_CDC_MCLK enable for tapan codec */
+		qcom,mode = <1>;		/* Digital output */
+		qcom,output-type = <0>;	/* CMOS logic */
+		qcom,pull = <5>;		/* QPNP_PIN_PULL_NO*/
+		qcom,vin-sel = <2>;		/* QPNP_PIN_VIN2 */
+		qcom,out-strength = <3>;/* QPNP_PIN_OUT_STRENGTH_HIGH */
+		qcom,src-sel = <2>;		/* QPNP_PIN_SEL_FUNC_1 */
+		qcom,master-en = <1>;	/* Enable GPIO */
 	};
 
 	gpio@c100 { /* GPIO 2 */
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 17de157..1f51a37 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -215,6 +215,12 @@
 		compatible = "qcom,msm-pcm-routing";
 	};
 
+	qcom,msm-pcm-low-latency {
+		compatible = "qcom,msm-pcm-dsp";
+		qcom,msm-pcm-dsp-id = <1>;
+		qcom,msm-pcm-low-latency;
+	};
+
 	qcom,msm-pcm-lpa {
 		compatible = "qcom,msm-pcm-lpa";
 	};
@@ -770,9 +776,6 @@
 &pm8226_chg {
 	status = "ok";
 
-	qcom,chg-charging-disabled;
-	qcom,chg-use-default-batt-values;
-
 	qcom,chg-chgr@1000 {
 		status = "ok";
 	};
@@ -781,6 +784,10 @@
 		status = "ok";
 	};
 
+	qcom,chg-bat-if@1200 {
+		status = "ok";
+	};
+
 	qcom,chg-usb-chgpth@1300 {
 		status = "ok";
 	};
diff --git a/arch/arm/boot/dts/msm8610-coresight.dtsi b/arch/arm/boot/dts/msm8610-coresight.dtsi
new file mode 100644
index 0000000..298cb68
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-coresight.dtsi
@@ -0,0 +1,142 @@
+/* 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.
+ */
+
+/ {
+	tmc_etr: tmc@fc326000 {
+		compatible = "arm,coresight-tmc";
+		reg = <0xfc326000 0x1000>,
+		      <0xfc37c000 0x3000>;
+		reg-names = "tmc-etr-base", "tmc-etr-bam-base";
+
+		qcom,memory-reservation-type = "EBI1";
+		qcom,memory-reservation-size = <0x100000>; /* 1M EBI1 buffer */
+
+		coresight-id = <0>;
+		coresight-name = "coresight-tmc-etr";
+		coresight-nr-inports = <1>;
+	};
+
+	tpiu: tpiu@fc320000 {
+		compatible = "arm,coresight-tpiu";
+		reg = <0xfc320000 0x1000>;
+		reg-names = "tpiu-base";
+
+		coresight-id = <1>;
+		coresight-name = "coresight-tpiu";
+		coresight-nr-inports = <1>;
+	};
+
+	replicator: replicator@fc324000 {
+		compatible = "qcom,coresight-replicator";
+		reg = <0xfc324000 0x1000>;
+		reg-names = "replicator-base";
+
+		coresight-id = <2>;
+		coresight-name = "coresight-replicator";
+		coresight-nr-inports = <1>;
+		coresight-outports = <0 1>;
+		coresight-child-list = <&tmc_etr &tpiu>;
+		coresight-child-ports = <0 0>;
+	};
+
+	tmc_etf: tmc@fc325000 {
+		compatible = "arm,coresight-tmc";
+		reg = <0xfc325000 0x1000>;
+		reg-names = "tmc-etf-base";
+
+		coresight-id = <3>;
+		coresight-name = "coresight-tmc-etf";
+		coresight-nr-inports = <1>;
+		coresight-outports = <0>;
+		coresight-child-list = <&replicator>;
+		coresight-child-ports = <0>;
+		coresight-default-sink;
+	};
+
+	funnel_merg: funnel@fc323000 {
+		compatible = "arm,coresight-funnel";
+		reg = <0xfc323000 0x1000>;
+		reg-names = "funnel-merg-base";
+
+		coresight-id = <4>;
+		coresight-name = "coresight-funnel-merg";
+		coresight-nr-inports = <2>;
+		coresight-outports = <0>;
+		coresight-child-list = <&tmc_etf>;
+		coresight-child-ports = <0>;
+	};
+
+	funnel_in0: funnel@fc321000 {
+		compatible = "arm,coresight-funnel";
+		reg = <0xfc321000 0x1000>;
+		reg-names = "funnel-in0-base";
+
+		coresight-id = <5>;
+		coresight-name = "coresight-funnel-in0";
+		coresight-nr-inports = <8>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_merg>;
+		coresight-child-ports = <0>;
+	};
+
+	funnel_in1: funnel@fc322000 {
+		compatible = "arm,coresight-funnel";
+		reg = <0xfc322000 0x1000>;
+		reg-names = "funnel-in1-base";
+
+		coresight-id = <6>;
+		coresight-name = "coresight-funnel-in1";
+		coresight-nr-inports = <8>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_merg>;
+		coresight-child-ports = <1>;
+	};
+
+	funnel_a7ss: funnel@fc355000 {
+		compatible = "arm,coresight-funnel";
+		reg = <0xfc355000 0x1000>;
+		reg-names = "funnel-a7ss-base";
+
+		coresight-id = <7>;
+		coresight-name = "coresight-funnel-a7ss";
+		coresight-nr-inports = <4>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in1>;
+		coresight-child-ports = <5>;
+	};
+
+	stm: stm@fc302000 {
+		compatible = "arm,coresight-stm";
+		reg = <0xfc302000 0x1000>,
+		      <0xfa280000 0x180000>;
+		reg-names = "stm-base", "stm-data-base";
+
+		coresight-id = <8>;
+		coresight-name = "coresight-stm";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in1>;
+		coresight-child-ports = <7>;
+	};
+
+	csr: csr@fc301000 {
+		compatible = "qcom,coresight-csr";
+		reg = <0xfc301000 0x1000>;
+		reg-names = "csr-base";
+
+		coresight-id = <9>;
+		coresight-name = "coresight-csr";
+		coresight-nr-inports = <0>;
+
+		qcom,blk-size = <3>;
+	};
+};
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index 558095b..b258506 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -14,6 +14,7 @@
 /include/ "msm-iommu-v0.dtsi"
 /include/ "msm8610-ion.dtsi"
 /include/ "msm-gdsc.dtsi"
+/include/ "msm8610-coresight.dtsi"
 /include/ "msm8610-pm.dtsi"
 
 / {
diff --git a/arch/arm/boot/dts/msm8974-mdss.dtsi b/arch/arm/boot/dts/msm8974-mdss.dtsi
index f382c3e..2f9adbb 100644
--- a/arch/arm/boot/dts/msm8974-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8974-mdss.dtsi
@@ -75,8 +75,8 @@
 		cell-index = <0>;
 		reg = <0xfd922800 0x600>;
 		vdd-supply = <&pm8941_l22>;
-		vdd_io-supply = <&pm8941_l12>;
-		vreg-supply = <&pm8941_l2>;
+		vddio-supply = <&pm8941_l12>;
+		vdda-supply = <&pm8941_l2>;
 		qcom,mdss-fb-map = <&mdss_fb0>;
 	};
 
@@ -86,8 +86,8 @@
 		cell-index = <1>;
 		reg = <0xfd922e00 0x600>;
 		vdd-supply = <&pm8941_l22>;
-		vdd_io-supply = <&pm8941_l12>;
-		vreg-supply = <&pm8941_l2>;
+		vddio-supply = <&pm8941_l12>;
+		vdda-supply = <&pm8941_l2>;
 		qcom,mdss-fb-map = <&mdss_fb0>;
 	};
 
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 2a5347e..ee79827 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -36,13 +36,13 @@
 
 	memory {
 
-		secure_mem: region@0 {
+		secure_mem: secure_region {
 			linux,contiguous-region;
 			reg = <0 0x7800000>;
 			label = "secure_mem";
 		};
 
-		adsp_mem: region@0 {
+		adsp_mem: adsp_region {
 			linux,contiguous-region;
 			reg = <0 0x2000000>;
 			label = "adsp_mem";
@@ -1186,31 +1186,18 @@
 		reg-names = "ssusb", "hsusb", "qscratch_ram1_reg";
 		interrupts = <0 132 0 0 135 0>;
 		interrupt-names = "ssusb", "hsusb";
-		qcom,usb-active-bam = <0>;
-		qcom,usb-total-bam-num = <2>;
 		qcom,usb-bam-num-pipes = <16>;
 		qcom,usb-base-address = <0xf9200000>;
 		qcom,ignore-core-reset-ack;
 		qcom,disable-clk-gating;
 
-		qcom,pipe1 {
-			label = "usb-to-peri-qdss-dwc3";
-			qcom,usb-bam-type = <0>;
+		qcom,pipe0 {
+			label = "ssusb-qdss-in-0";
 			qcom,usb-bam-mem-type = <1>;
-			qcom,src-bam-physical-address = <0>;
-			qcom,src-bam-pipe-index = <0>;
-			qcom,dst-bam-physical-address = <0>;
-			qcom,dst-bam-pipe-index = <0>;
-			qcom,data-fifo-offset = <0>;
-			qcom,data-fifo-size = <0>;
-			qcom,descriptor-fifo-offset = <0>;
-			qcom,descriptor-fifo-size = <0>;
-		};
-
-		qcom,pipe2 {
-			label = "peri-to-usb-qdss-dwc3";
-			qcom,usb-bam-type = <0>;
-			qcom,usb-bam-mem-type = <1>;
+			qcom,bam-type = <0>;
+			qcom,dir = <1>;
+			qcom,pipe-num = <0>;
+			qcom,peer-bam = <1>;
 			qcom,src-bam-physical-address = <0xfc37C000>;
 			qcom,src-bam-pipe-index = <0>;
 			qcom,dst-bam-physical-address = <0xf9304000>;
@@ -1222,24 +1209,13 @@
 			qcom,reset-bam-on-connect;
 		};
 
-		qcom,pipe3 {
-			label = "usb-to-peri-qdss-hsusb";
-			qcom,usb-bam-type = <1>;
+		qcom,pipe1 {
+			label = "hsusb-qdss-in-0";
 			qcom,usb-bam-mem-type = <1>;
-			qcom,src-bam-physical-address = <0>;
-			qcom,src-bam-pipe-index = <0>;
-			qcom,dst-bam-physical-address = <0>;
-			qcom,dst-bam-pipe-index = <0>;
-			qcom,data-fifo-offset = <0>;
-			qcom,data-fifo-size = <0>;
-			qcom,descriptor-fifo-offset = <0>;
-			qcom,descriptor-fifo-size = <0>;
-		};
-
-		qcom,pipe4 {
-			label = "peri-to-usb-qdss-hsusb";
-			qcom,usb-bam-type = <1>;
-			qcom,usb-bam-mem-type = <1>;
+			qcom,bam-type = <1>;
+			qcom,dir = <1>;
+			qcom,pipe-num = <0>;
+			qcom,peer-bam = <1>;
 			qcom,src-bam-physical-address = <0xfc37c000>;
 			qcom,src-bam-pipe-index = <0>;
 			qcom,dst-bam-physical-address = <0xf9a44000>;
@@ -1266,10 +1242,6 @@
 		interrupts = <0 29 1>;
 	};
 
-        qcom,msm-wdog-debug@fc401000 {
-               compatible = "qcom,msm-wdog-debug";
-               reg = <0xfc401000 0x1000>;
-        };
         qcom,msm-mem-hole {
                 compatible = "qcom,msm-mem-hole";
                 qcom,memblock-remove = <0x7f00000 0x8000000>; /* Address and Size of Hole */
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 78786f6..a11398b 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -131,16 +131,17 @@
 		reg-names = "hsusb";
 		interrupts = <0 135 0>;
 		interrupt-names = "hsusb";
-		qcom,usb-active-bam = <1>;
-		qcom,usb-total-bam-num = <3>;
 		qcom,usb-bam-num-pipes = <16>;
 		qcom,ignore-core-reset-ack;
 		qcom,disable-clk-gating;
 
 		qcom,pipe0 {
-			label = "usb-to-ipa";
-			qcom,usb-bam-type = <1>;
+			label = "hsusb-ipa-out-0";
 			qcom,usb-bam-mem-type = <0>;
+			qcom,bam-type = <1>;
+			qcom,dir = <0>;
+			qcom,pipe-num = <0>;
+			qcom,peer-bam = <2>;
 			qcom,src-bam-physical-address = <0xf9a44000>;
 			qcom,src-bam-pipe-index = <1>;
 			qcom,data-fifo-offset = <0x2200>;
@@ -149,9 +150,12 @@
 			qcom,descriptor-fifo-size = <0x100>;
 		};
 		qcom,pipe1 {
-			label = "ipa-to-usb";
-			qcom,usb-bam-type = <1>;
+			label = "hsusb-ipa-in-0";
 			qcom,usb-bam-mem-type = <0>;
+			qcom,bam-type = <1>;
+			qcom,dir = <1>;
+			qcom,pipe-num = <0>;
+			qcom,peer-bam = <2>;
 			qcom,dst-bam-physical-address = <0xf9a44000>;
 			qcom,dst-bam-pipe-index = <0>;
 			qcom,data-fifo-offset = <0x300>;
@@ -160,22 +164,12 @@
 			qcom,descriptor-fifo-size = <0x300>;
 		};
 		qcom,pipe2 {
-			label = "usb-to-qdss-hsusb";
-			qcom,usb-bam-type = <1>;
+			label = "hsusb-qdss-in-0";
 			qcom,usb-bam-mem-type = <0>;
-			qcom,src-bam-physical-address = <0xf9a44000>;
-			qcom,src-bam-pipe-index = <0>;
-			qcom,dst-bam-physical-address = <0xfc37c000>;
-			qcom,dst-bam-pipe-index = <0>;
-			qcom,data-fifo-offset = <0>;
-			qcom,data-fifo-size = <0>;
-			qcom,descriptor-fifo-offset = <0>;
-			qcom,descriptor-fifo-size = <0>;
-		};
-		qcom,pipe3 {
-			label = "qdss-to-usb-hsusb";
-			qcom,usb-bam-type = <1>;
-			qcom,usb-bam-mem-type = <0>;
+			qcom,bam-type = <1>;
+			qcom,dir = <1>;
+			qcom,pipe-num = <0>;
+			qcom,peer-bam = <1>;
 			qcom,src-bam-physical-address = <0xfc37c000>;
 			qcom,src-bam-pipe-index = <0>;
 			qcom,dst-bam-physical-address = <0xf9a44000>;
@@ -727,8 +721,8 @@
 
 	sfpb_spinlock: qcom,ipc-spinlock@fd484000 {
 		compatible = "qcom,ipc-spinlock-sfpb";
-		reg = <0xfd484000 0x1000>;
-		qcom,num-locks = <32>;
+		reg = <0xfd484000 0x400>;
+		qcom,num-locks = <8>;
 	};
 
 	ldrex_spinlock: qcom,ipc-spinlock@fa00000 {
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 216fe99..d4abef2 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -324,6 +324,7 @@
 CONFIG_THERMAL=y
 CONFIG_THERMAL_TSENS8974=y
 CONFIG_THERMAL_MONITOR=y
+CONFIG_THERMAL_QPNP_ADC_TM=y
 CONFIG_MSM_RTB=y
 CONFIG_MSM_RTB_SEPARATE_CPUS=y
 CONFIG_CORESIGHT=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 68fee3b..b65016a 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -302,6 +302,7 @@
 	select SPARSE_IRQ
 	select REGULATOR
 	select ARM_HAS_SG_CHAIN
+	select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
 
 config ARCH_MPQ8092
 	bool "MPQ8092"
@@ -2843,12 +2844,12 @@
 	 does not have a direct access to the PMIC.
 
 config MSM_ENABLE_WDOG_DEBUG_CONTROL
-	bool "MSM Watchdog driver to disable debug Image"
+	bool "Enable control of watchdog debug and boot partition select"
 	help
-	 This driver supports the configuration of the GCC_WDOG_DEBUG register
-	 used to control debug image.
-	 This support is currently required for MSM8974 to disable debug image
-	 on PS HOLD reset
+	  Enables support for controlling watchdog debug and boot partition
+	  select. This is currently used to bypass debug image for PS_HOLD reset
+	  by disabling watchdog debug and boot partition select. This allows
+	  for a clean MSM reset for reboot scenarios.
 
 config MSM_FIQ
 	bool "Enable FIQ for debugging"
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index 833b213..20c461d 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -1577,8 +1577,6 @@
 {
 	DMUX_LOG_KERR("%s: modem timeout: BAM DMUX disabled\n", __func__);
 	in_global_reset = 1;
-	if (get_restart_level() <= RESET_SOC)
-		DMUX_LOG_KERR("%s: ssrestart not enabled\n", __func__);
 	return 1;
 }
 
diff --git a/arch/arm/mach-msm/board-8226-gpiomux.c b/arch/arm/mach-msm/board-8226-gpiomux.c
index 41263f8..e8e75df 100644
--- a/arch/arm/mach-msm/board-8226-gpiomux.c
+++ b/arch/arm/mach-msm/board-8226-gpiomux.c
@@ -17,7 +17,7 @@
 #include <mach/gpio.h>
 #include <mach/gpiomux.h>
 
-#define KS8851_IRQ_GPIO 75
+#define KS8851_IRQ_GPIO 115
 
 #if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
 static struct gpiomux_setting gpio_eth_config = {
@@ -84,6 +84,12 @@
 	.pull = GPIOMUX_PULL_DOWN,
 };
 
+static struct gpiomux_setting gpio_spi_cs_eth_config = {
+	.func = GPIOMUX_FUNC_4,
+	.drv = GPIOMUX_DRV_6MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
 static struct gpiomux_setting gpio_i2c_config = {
 	.func = GPIOMUX_FUNC_3,
 	.drv = GPIOMUX_DRV_2MA,
@@ -186,6 +192,12 @@
 			[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
 		},
 	},
+	{
+		.gpio      = 22,		/* BLSP1 QUP1 SPI_CS_ETH */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_spi_cs_eth_config,
+		},
+	},
 };
 
 static struct msm_gpiomux_config msm_synaptics_configs[] __initdata = {
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index f609bbc..50f4fd7 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -625,8 +625,13 @@
 #define USB_BAM_PHY_BASE	0x12502000
 #define HSIC_BAM_PHY_BASE	0x12542000
 #define A2_BAM_PHY_BASE		0x124C2000
-static struct usb_bam_pipe_connect msm_usb_bam_connections[MAX_BAMS][8][2] = {
-	[HSUSB_BAM][0][USB_TO_PEER_PERIPHERAL] = {
+static struct usb_bam_pipe_connect msm_usb_bam_connections[] = {
+	{
+		.name = "hsusb-a2-out-0",
+		.bam_type = HSUSB_BAM,
+		.peer_bam = A2_P_BAM,
+		.dir = USB_TO_PEER_PERIPHERAL,
+		.pipe_num = 0,
 		.src_phy_addr = USB_BAM_PHY_BASE,
 		.src_pipe_index = 11,
 		.dst_phy_addr = A2_BAM_PHY_BASE,
@@ -636,7 +641,12 @@
 		.desc_fifo_base_offset = 0x1700,
 		.desc_fifo_size = 0x300,
 	},
-	[HSUSB_BAM][0][PEER_PERIPHERAL_TO_USB] = {
+	{
+		.name = "hsusb-a2-in-0",
+		.bam_type = HSUSB_BAM,
+		.peer_bam = A2_P_BAM,
+		.dir = PEER_PERIPHERAL_TO_USB,
+		.pipe_num = 0,
 		.src_phy_addr = A2_BAM_PHY_BASE,
 		.src_pipe_index = 1,
 		.dst_phy_addr = USB_BAM_PHY_BASE,
@@ -646,7 +656,12 @@
 		.desc_fifo_base_offset = 0x1000,
 		.desc_fifo_size = 0x100,
 	},
-	[HSUSB_BAM][1][USB_TO_PEER_PERIPHERAL] = {
+	{
+		.name = "hsusb-a2-out-1",
+		.bam_type = HSUSB_BAM,
+		.peer_bam = A2_P_BAM,
+		.dir = USB_TO_PEER_PERIPHERAL,
+		.pipe_num = 1,
 		.src_phy_addr = USB_BAM_PHY_BASE,
 		.src_pipe_index = 13,
 		.dst_phy_addr = A2_BAM_PHY_BASE,
@@ -656,7 +671,12 @@
 		.desc_fifo_base_offset = 0x2700,
 		.desc_fifo_size = 0x300,
 	},
-	[HSUSB_BAM][1][PEER_PERIPHERAL_TO_USB] = {
+	{
+		.name = "hsusb-a2-in-1",
+		.bam_type = HSUSB_BAM,
+		.peer_bam = A2_P_BAM,
+		.dir = PEER_PERIPHERAL_TO_USB,
+		.pipe_num = 1,
 		.src_phy_addr = A2_BAM_PHY_BASE,
 		.src_pipe_index = 3,
 		.dst_phy_addr = USB_BAM_PHY_BASE,
@@ -666,7 +686,12 @@
 		.desc_fifo_base_offset = 0x2000,
 		.desc_fifo_size = 0x100,
 	},
-	[HSUSB_BAM][2][USB_TO_PEER_PERIPHERAL] = {
+	{
+		.name = "hsusb-a2-out-2",
+		.bam_type = HSUSB_BAM,
+		.peer_bam = A2_P_BAM,
+		.dir = USB_TO_PEER_PERIPHERAL,
+		.pipe_num = 2,
 		.src_phy_addr = USB_BAM_PHY_BASE,
 		.src_pipe_index = 15,
 		.dst_phy_addr = A2_BAM_PHY_BASE,
@@ -676,7 +701,12 @@
 		.desc_fifo_base_offset = 0x3700,
 		.desc_fifo_size = 0x300,
 	},
-	[HSUSB_BAM][2][PEER_PERIPHERAL_TO_USB] = {
+	{
+		.name = "hsusb-a2-in-2",
+		.bam_type = HSUSB_BAM,
+		.peer_bam = A2_P_BAM,
+		.dir = PEER_PERIPHERAL_TO_USB,
+		.pipe_num = 2,
 		.src_phy_addr = A2_BAM_PHY_BASE,
 		.src_pipe_index = 5,
 		.dst_phy_addr = USB_BAM_PHY_BASE,
@@ -686,7 +716,12 @@
 		.desc_fifo_base_offset = 0x3000,
 		.desc_fifo_size = 0x100,
 	},
-	[HSIC_BAM][0][USB_TO_PEER_PERIPHERAL] = {
+	{
+		.name = "hsic-a2-out-0",
+		.bam_type = HSIC_BAM,
+		.peer_bam = A2_P_BAM,
+		.dir = USB_TO_PEER_PERIPHERAL,
+		.pipe_num = 0,
 		.src_phy_addr = HSIC_BAM_PHY_BASE,
 		.src_pipe_index = 1,
 		.dst_phy_addr = A2_BAM_PHY_BASE,
@@ -696,7 +731,12 @@
 		.desc_fifo_base_offset = 0x1700,
 		.desc_fifo_size = 0x300,
 	},
-	[HSIC_BAM][0][PEER_PERIPHERAL_TO_USB] = {
+	{
+		.name = "hsic-a2-in-0",
+		.bam_type = HSIC_BAM,
+		.peer_bam = A2_P_BAM,
+		.dir = PEER_PERIPHERAL_TO_USB,
+		.pipe_num = 0,
 		.src_phy_addr = A2_BAM_PHY_BASE,
 		.src_pipe_index = 1,
 		.dst_phy_addr = HSIC_BAM_PHY_BASE,
@@ -706,7 +746,12 @@
 		.desc_fifo_base_offset = 0x1000,
 		.desc_fifo_size = 0x100,
 	},
-	[HSIC_BAM][1][USB_TO_PEER_PERIPHERAL] = {
+	{
+		.name = "hsic-a2-out-1",
+		.bam_type = HSIC_BAM,
+		.peer_bam = A2_P_BAM,
+		.dir = USB_TO_PEER_PERIPHERAL,
+		.pipe_num = 1,
 		.src_phy_addr = HSIC_BAM_PHY_BASE,
 		.src_pipe_index = 3,
 		.dst_phy_addr = A2_BAM_PHY_BASE,
@@ -716,7 +761,12 @@
 		.desc_fifo_base_offset = 0x2700,
 		.desc_fifo_size = 0x300,
 	},
-	[HSIC_BAM][1][PEER_PERIPHERAL_TO_USB] = {
+	{
+		.name = "hsic-a2-in-1",
+		.bam_type = HSIC_BAM,
+		.peer_bam = A2_P_BAM,
+		.dir = PEER_PERIPHERAL_TO_USB,
+		.pipe_num = 1,
 		.src_phy_addr = A2_BAM_PHY_BASE,
 		.src_pipe_index = 3,
 		.dst_phy_addr = HSIC_BAM_PHY_BASE,
@@ -726,7 +776,12 @@
 		.desc_fifo_base_offset = 0x2000,
 		.desc_fifo_size = 0x100,
 	},
-	[HSIC_BAM][2][USB_TO_PEER_PERIPHERAL] = {
+	{
+		.name = "hsic-a2-out-2",
+		.bam_type = HSIC_BAM,
+		.peer_bam = A2_P_BAM,
+		.dir = USB_TO_PEER_PERIPHERAL,
+		.pipe_num = 2,
 		.src_phy_addr = HSIC_BAM_PHY_BASE,
 		.src_pipe_index = 5,
 		.dst_phy_addr = A2_BAM_PHY_BASE,
@@ -736,7 +791,12 @@
 		.desc_fifo_base_offset = 0x3700,
 		.desc_fifo_size = 0x300,
 	},
-	[HSIC_BAM][2][PEER_PERIPHERAL_TO_USB] = {
+	{
+		.name = "hsic-a2-in-2",
+		.bam_type = HSIC_BAM,
+		.peer_bam = A2_P_BAM,
+		.dir = PEER_PERIPHERAL_TO_USB,
+		.pipe_num = 2,
 		.src_phy_addr = A2_BAM_PHY_BASE,
 		.src_pipe_index = 5,
 		.dst_phy_addr = HSIC_BAM_PHY_BASE,
@@ -749,12 +809,9 @@
 };
 
 static struct msm_usb_bam_platform_data msm_usb_bam_pdata = {
-	.connections = &msm_usb_bam_connections[0][0][0],
-#ifndef CONFIG_USB_CI13XXX_MSM_HSIC
-	.usb_active_bam = HSUSB_BAM,
-#else
-	.usb_active_bam = HSIC_BAM,
-#endif
+	.connections = &msm_usb_bam_connections[0],
+	.max_connections = sizeof(msm_usb_bam_connections) /
+		sizeof(struct usb_bam_pipe_connect),
 	.usb_bam_num_pipes = 16,
 };
 
diff --git a/arch/arm/mach-msm/board-zinc.c b/arch/arm/mach-msm/board-zinc.c
index 4cc907d..fa19e39 100644
--- a/arch/arm/mach-msm/board-zinc.c
+++ b/arch/arm/mach-msm/board-zinc.c
@@ -22,6 +22,7 @@
 #include <mach/board.h>
 #include <mach/gpiomux.h>
 #include <mach/msm_iomap.h>
+#include <mach/msm_memtypes.h>
 #include <mach/msm_smd.h>
 #include <mach/restart.h>
 #include <mach/socinfo.h>
@@ -31,12 +32,38 @@
 #include "devices.h"
 #include "platsmp.h"
 
+static struct memtype_reserve msmzinc_reserve_table[] __initdata = {
+	[MEMTYPE_SMI] = {
+	},
+	[MEMTYPE_EBI0] = {
+		.flags  =       MEMTYPE_FLAGS_1M_ALIGN,
+	},
+	[MEMTYPE_EBI1] = {
+		.flags  =       MEMTYPE_FLAGS_1M_ALIGN,
+	},
+};
+
+static int msmzinc_paddr_to_memtype(unsigned int paddr)
+{
+	return MEMTYPE_EBI1;
+}
+
+static struct reserve_info msmzinc_reserve_info __initdata = {
+	.memtype_reserve_table = msmzinc_reserve_table,
+	.paddr_to_memtype = msmzinc_paddr_to_memtype,
+};
+
 void __init msmzinc_reserve(void)
 {
+	reserve_info = &msmzinc_reserve_info;
+	of_scan_flat_dt(dt_scan_for_memory_reserve, msmzinc_reserve_table);
+	msm_reserve();
 }
 
 static void __init msmzinc_early_memory(void)
 {
+	reserve_info = &msmzinc_reserve_info;
+	of_scan_flat_dt(dt_scan_for_memory_hole, msmzinc_reserve_table);
 }
 
 static struct clk_lookup msm_clocks_dummy[] = {
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index 813b210..2899d93 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -3094,6 +3094,10 @@
 	CLK_LOOKUP("core_clk", qdss_clk.c, "fc33d000.etm"),
 	CLK_LOOKUP("core_clk", qdss_clk.c, "fc33e000.etm"),
 	CLK_LOOKUP("core_clk", qdss_clk.c, "fc33f000.etm"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc33c000.jtagmm"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc33d000.jtagmm"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc33e000.jtagmm"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc33f000.jtagmm"),
 
 	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc322000.tmc"),
 	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc318000.tpiu"),
@@ -3109,6 +3113,10 @@
 	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc33d000.etm"),
 	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc33e000.etm"),
 	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc33f000.etm"),
+	CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc33c000.jtagmm"),
+	CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc33d000.jtagmm"),
+	CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc33e000.jtagmm"),
+	CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc33f000.jtagmm"),
 
 	/* HSUSB-OTG Clocks */
 	CLK_LOOKUP("xo",                          xo.c, "f9a55000.usb"),
@@ -3350,6 +3358,15 @@
 	CLK_LOOKUP("", mmss_mmssnoc_bto_ahb_clk.c, ""),
 	CLK_LOOKUP("", mmss_mmssnoc_axi_clk.c, ""),
 	CLK_LOOKUP("", mmss_s0_axi_clk.c, ""),
+
+	/* Audio clocks */
+	CLK_LOOKUP("osr_clk", div_clk1.c, "msm-dai-q6-dev.224"),
+	CLK_LOOKUP("osr_clk", div_clk1.c, "msm-dai-q6-dev.4106"),
+	CLK_LOOKUP("osr_clk", div_clk1.c, "msm-dai-q6-dev.16384"),
+	CLK_LOOKUP("osr_clk", div_clk1.c, "msm-dai-q6-dev.16386"),
+	CLK_LOOKUP("osr_clk", div_clk1.c, "msm-dai-q6-dev.16390"),
+	CLK_LOOKUP("osr_clk", div_clk1.c, "msm-dai-q6-dev.16391"),
+
 };
 
 static struct clk_lookup msm_clocks_8226_rumi[] = {
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index 5690730..0aee878 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -3047,35 +3047,65 @@
 	CLK_LOOKUP("mem_a_clk",	bimc_msmbus_a_clk.c,	"msm_bimc"),
 	CLK_LOOKUP("mem_clk",	bimc_acpu_a_clk.c,	""),
 
-	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-tmc-etr"),
-	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-tpiu"),
-	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-replicator"),
-	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-tmc-etf"),
-	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel-merg"),
-	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel-in0"),
-	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel-in1"),
-	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel-kpss"),
-	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel-mmss"),
-	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-stm"),
-	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm0"),
-	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm1"),
-	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm2"),
-	CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm3"),
+	/* CoreSight clocks */
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc326000.tmc"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc320000.tpiu"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc324000.replicator"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc325000.tmc"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc323000.funnel"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc321000.funnel"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc322000.funnel"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc355000.funnel"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc302000.stm"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc34c000.etm"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc34d000.etm"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc34e000.etm"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc34f000.etm"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc301000.csr"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc310000.cti"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc311000.cti"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc312000.cti"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc313000.cti"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc314000.cti"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc315000.cti"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc316000.cti"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc317000.cti"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc318000.cti"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc351000.cti"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc352000.cti"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc353000.cti"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fc354000.cti"),
 
-	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-tmc-etr"),
-	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-tpiu"),
-	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-replicator"),
-	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-tmc-etf"),
-	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-funnel-merg"),
-	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-funnel-in0"),
-	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-funnel-in1"),
-	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-funnel-kpss"),
-	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-funnel-mmss"),
-	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-stm"),
-	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-etm0"),
-	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-etm1"),
-	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-etm2"),
-	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "coresight-etm3"),
+
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc326000.tmc"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc320000.tpiu"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc324000.replicator"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc325000.tmc"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc323000.funnel"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc321000.funnel"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc322000.funnel"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc355000.funnel"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc302000.stm"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc34c000.etm"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc34d000.etm"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc34e000.etm"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc34f000.etm"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc301000.csr"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc310000.cti"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc311000.cti"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc312000.cti"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc313000.cti"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc314000.cti"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc315000.cti"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc316000.cti"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc317000.cti"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc318000.cti"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc351000.cti"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc352000.cti"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc353000.cti"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc354000.cti"),
+
+
 
 	CLK_LOOKUP("core_clk_src", blsp1_qup1_spi_apps_clk_src.c, ""),
 	CLK_LOOKUP("core_clk_src", blsp1_qup2_spi_apps_clk_src.c, ""),
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 78e3259..0657c21 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -4851,6 +4851,7 @@
 	CLK_LOOKUP("phy_clk", gcc_usb_hsic_clk.c,	  "msm_hsic_host"),
 	CLK_LOOKUP("cal_clk", gcc_usb_hsic_io_cal_clk.c,  "msm_hsic_host"),
 	CLK_LOOKUP("core_clk", gcc_usb_hsic_system_clk.c, "msm_hsic_host"),
+	CLK_LOOKUP("osr_clk", div_clk1.c, "msm-dai-q6-dev.16384"),
 	CLK_LOOKUP("ref_clk", div_clk2.c, "msm_smsc_hub"),
 	CLK_LOOKUP("iface_clk", gcc_usb_hs_ahb_clk.c,     "msm_ehci_host"),
 	CLK_LOOKUP("core_clk", gcc_usb_hs_system_clk.c,   "msm_ehci_host"),
diff --git a/arch/arm/mach-msm/include/mach/memory.h b/arch/arm/mach-msm/include/mach/memory.h
index 8c53ea5..fff7fa4 100644
--- a/arch/arm/mach-msm/include/mach/memory.h
+++ b/arch/arm/mach-msm/include/mach/memory.h
@@ -1,7 +1,7 @@
 /* arch/arm/mach-msm/include/mach/memory.h
  *
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -96,11 +96,15 @@
 extern unsigned long memory_hole_offset;
 extern unsigned long memory_hole_start;
 extern unsigned long memory_hole_end;
+extern unsigned long memory_hole_align;
+extern unsigned long virtual_hole_start;
+extern unsigned long virtual_hole_end;
 #ifdef CONFIG_DONT_MAP_HOLE_AFTER_MEMBANK0
 void find_memory_hole(void);
 
 #define MEM_HOLE_END_PHYS_OFFSET (memory_hole_end)
-#define MEM_HOLE_PAGE_OFFSET (PAGE_OFFSET + memory_hole_offset)
+#define MEM_HOLE_PAGE_OFFSET (PAGE_OFFSET + memory_hole_offset + \
+				memory_hole_align)
 
 #define __phys_to_virt(phys)				\
 	((MEM_HOLE_END_PHYS_OFFSET && ((phys) >= MEM_HOLE_END_PHYS_OFFSET)) ? \
diff --git a/arch/arm/mach-msm/include/mach/subsystem_restart.h b/arch/arm/mach-msm/include/mach/subsystem_restart.h
index 1f6ca66..67f643e 100644
--- a/arch/arm/mach-msm/include/mach/subsystem_restart.h
+++ b/arch/arm/mach-msm/include/mach/subsystem_restart.h
@@ -21,9 +21,8 @@
 struct subsys_device;
 
 enum {
-	RESET_SOC = 1,
+	RESET_SOC = 0,
 	RESET_SUBSYS_COUPLED,
-	RESET_SUBSYS_INDEPENDENT,
 	RESET_LEVEL_MAX
 };
 
@@ -60,7 +59,7 @@
 
 #if defined(CONFIG_MSM_SUBSYSTEM_RESTART)
 
-extern int get_restart_level(void);
+extern int subsys_get_restart_level(struct subsys_device *dev);
 extern int subsystem_restart_dev(struct subsys_device *dev);
 extern int subsystem_restart(const char *name);
 extern int subsystem_crashed(const char *name);
@@ -75,7 +74,7 @@
 
 #else
 
-static inline int get_restart_level(void)
+static inline int subsys_get_restart_level(struct subsys_device *dev)
 {
 	return 0;
 }
diff --git a/arch/arm/mach-msm/include/mach/usb_bam.h b/arch/arm/mach-msm/include/mach/usb_bam.h
index b3fb8af..5a77d99 100644
--- a/arch/arm/mach-msm/include/mach/usb_bam.h
+++ b/arch/arm/mach-msm/include/mach/usb_bam.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -14,22 +14,36 @@
 #define _USB_BAM_H_
 #include "sps.h"
 #include <mach/ipa.h>
+#include <linux/usb/msm_hsusb.h>
 
-/**
- * SPS Pipes direction.
- *
- * USB_TO_PEER_PERIPHERAL	USB (as Producer) to other
- *                          peer peripheral.
- * PEER_PERIPHERAL_TO_USB	Other Peripheral to
- *                          USB (as consumer).
- */
+enum usb_bam {
+	SSUSB_BAM = 0,
+	HSUSB_BAM,
+	HSIC_BAM,
+	MAX_BAMS,
+};
+
+enum peer_bam {
+	A2_P_BAM = 0,
+	QDSS_P_BAM,
+	IPA_P_BAM,
+	MAX_PEER_BAMS,
+};
+
 enum usb_bam_pipe_dir {
 	USB_TO_PEER_PERIPHERAL,
 	PEER_PERIPHERAL_TO_USB,
 };
 
+enum usb_pipe_mem_type {
+	SPS_PIPE_MEM = 0,	/* Default, SPS dedicated pipe memory */
+	USB_PRIVATE_MEM,	/* USB's private memory */
+	SYSTEM_MEM,		/* System RAM, requires allocation */
+};
+
 struct usb_bam_connect_ipa_params {
-	u8 idx;
+	u8 src_idx;
+	u8 dst_idx;
 	u32 *src_pipe;
 	u32 *dst_pipe;
 	enum usb_bam_pipe_dir dir;
@@ -44,29 +58,100 @@
 			unsigned long data);
 };
 
+/**
+* struct usb_bam_event_info: suspend/resume event information.
+* @event: holds event data.
+* @callback: suspend/resume callback.
+* @param: port num (for suspend) or NULL (for resume).
+* @event_w: holds work queue parameters.
+*/
+struct usb_bam_event_info {
+	struct sps_register_event event;
+	int (*callback)(void *);
+	void *param;
+	struct work_struct event_w;
+};
+
+/**
+* struct usb_bam_pipe_connect: pipe connection information
+* between USB/HSIC BAM and another BAM. USB/HSIC BAM can be
+* either src BAM or dst BAM
+* @name: pipe description.
+* @mem_type: type of memory used for BAM FIFOs
+* @src_phy_addr: src bam physical address.
+* @src_pipe_index: src bam pipe index.
+* @dst_phy_addr: dst bam physical address.
+* @dst_pipe_index: dst bam pipe index.
+* @data_fifo_base_offset: data fifo offset.
+* @data_fifo_size: data fifo size.
+* @desc_fifo_base_offset: descriptor fifo offset.
+* @desc_fifo_size: descriptor fifo size.
+* @data_mem_buf: data fifo buffer.
+* @desc_mem_buf: descriptor fifo buffer.
+* @wake_event: event for wakeup.
+* @enabled: true if pipe is enabled.
+*/
+struct usb_bam_pipe_connect {
+	const char *name;
+	u32 pipe_num;
+	enum usb_pipe_mem_type mem_type;
+	enum usb_bam_pipe_dir dir;
+	enum usb_bam bam_type;
+	enum peer_bam peer_bam;
+	u32 src_phy_addr;
+	u32 src_pipe_index;
+	u32 dst_phy_addr;
+	u32 dst_pipe_index;
+	u32 data_fifo_base_offset;
+	u32 data_fifo_size;
+	u32 desc_fifo_base_offset;
+	u32 desc_fifo_size;
+	struct sps_mem_buffer data_mem_buf;
+	struct sps_mem_buffer desc_mem_buf;
+	struct usb_bam_event_info wake_event;
+	bool enabled;
+};
+
+/**
+ * struct msm_usb_bam_platform_data: pipe connection information
+ * between USB/HSIC BAM and another BAM. USB/HSIC BAM can be
+ * either src BAM or dst BAM
+ * @connections: holds all pipe connections data.
+ * @usb_bam_num_pipes: max number of pipes to use.
+ * @active_conn_num: number of active pipe connections.
+ * @usb_base_address: BAM physical address.
+ * @ignore_core_reset_ack: BAM can ignore ACK from USB core during PIPE RESET
+ * @disable_clk_gating: Disable clock gating
+ */
+struct msm_usb_bam_platform_data {
+	struct usb_bam_pipe_connect *connections;
+	u8 max_connections;
+	int usb_bam_num_pipes;
+	u32 usb_base_address;
+	bool ignore_core_reset_ack;
+	bool reset_on_connect[MAX_BAMS];
+	bool disable_clk_gating;
+};
+
 #ifdef CONFIG_USB_BAM
 /**
- * Connect USB-to-Periperal SPS connection.
+ * Connect USB-to-Peripheral SPS connection.
  *
- * This function returns the allocated pipes number.
+ * This function returns the allocated pipe number.
  *
  * @idx - Connection index.
  *
- * @src_pipe_idx - allocated pipe index - USB as a
- *  source (output)
- *
- * @dst_pipe_idx - allocated pipe index - USB as a
- * destination (output)
+ * @bam_pipe_idx - allocated pipe index.
  *
  * @return 0 on success, negative value on error
  *
  */
-int usb_bam_connect(u8 idx, u32 *src_pipe_idx, u32 *dst_pipe_idx);
+int usb_bam_connect(u8 idx, u32 *bam_pipe_idx);
 
 /**
  * Connect USB-to-IPA SPS connection.
  *
- * This function returns the allocated pipes number adn clnt handles.
+ * This function returns the allocated pipes number and clnt handles.
  *
  * @ipa_params - in/out parameters
  *
@@ -78,14 +163,12 @@
 /**
  * Disconnect USB-to-IPA SPS connection.
  *
- * @idx - Connection index.
- *
  * @ipa_params - in/out parameters
  *
  * @return 0 on success, negative value on error
  *
  */
-int usb_bam_disconnect_ipa(u8 idx,
+int usb_bam_disconnect_ipa(
 		struct usb_bam_connect_ipa_params *ipa_params);
 
 /**
@@ -99,13 +182,11 @@
  *
  */
 int usb_bam_register_wake_cb(u8 idx,
-	 int (*callback)(void *), void* param);
+	int (*callback)(void *), void *param);
 
 /**
  * Register a callback for peer BAM reset.
  *
- * @idx - Connection index.
- *
  * @callback - the callback function that will be called in USB
  *				driver upon a peer bam reset
  *
@@ -114,8 +195,7 @@
  * @return 0 on success, negative value on error
  *
  */
-int usb_bam_register_peer_reset_cb(u8 idx,
-	 int (*callback)(void *), void *param);
+int usb_bam_register_peer_reset_cb(int (*callback)(void *), void *param);
 
 /**
  * Disconnect USB-to-Periperal SPS connection.
@@ -129,9 +209,7 @@
 /**
  * Returns usb bam connection parameters.
  *
- * @conn_idx - Connection index.
- *
- * @usb_bam_pipe_dir - Usb pipe direction to/from peripheral.
+ * @idx - Connection index.
  *
  * @usb_bam_handle - Usb bam handle.
  *
@@ -143,16 +221,17 @@
  *
  * @data_fifo - Data fifo parameters.
  *
+ * @return pipe index on success, negative value on error.
  */
-void get_bam2bam_connection_info(u8 conn_idx, enum usb_bam_pipe_dir pipe_dir,
+int get_bam2bam_connection_info(u8 idx,
 	u32 *usb_bam_handle, u32 *usb_bam_pipe_idx, u32 *peer_pipe_idx,
 	struct sps_mem_buffer *desc_fifo, struct sps_mem_buffer *data_fifo);
 
 /**
- * Resets the entire USB BAM.
+ * Resets the USB BAM that has A2 pipes
  *
  */
-int usb_bam_reset(void);
+int usb_bam_a2_reset(void);
 
 /**
  * Indicates if the client of the USB BAM is ready to start
@@ -162,9 +241,41 @@
  *
  */
 int usb_bam_client_ready(bool ready);
+/**
+* Returns qdss index from the connections array.
+*
+* @num - The qdss pipe number.
+*
+* @return pipe index on success, negative value on error
+*/
+int usb_bam_get_qdss_idx(u8 num);
+
+/**
+* Saves qdss core number.
+*
+* @qdss_core - The qdss core name.
+*/
+void usb_bam_set_qdss_core(const char *qdss_core);
+
+/**
+* Indicates if the client of the USB BAM is ready to start
+* sending/receiving transfers.
+*
+* @name - Core name (ssusb/hsusb/hsic).
+*
+* @client - Usb pipe peer (a2, ipa, qdss...)
+*
+* @dir - In (from peer to usb) or out (from usb to peer)
+*
+* @num - Pipe number.
+*
+* @return 0 on success, negative value on error
+*/
+int usb_bam_get_connection_idx(const char *name, enum peer_bam client,
+	enum usb_bam_pipe_dir dir, u32 num);
 
 #else
-static inline int usb_bam_connect(u8 idx, u32 *src_pipe_idx, u32 *dst_pipe_idx)
+static inline int usb_bam_connect(u8 idx, u32 *bam_pipe_idx)
 {
 	return -ENODEV;
 }
@@ -175,7 +286,7 @@
 	return -ENODEV;
 }
 
-static inline int usb_bam_disconnect_ipa(u8 idx,
+static inline int usb_bam_disconnect_ipa(
 			struct usb_bam_connect_ipa_params *ipa_params)
 {
 	return -ENODEV;
@@ -187,8 +298,8 @@
 	return -ENODEV;
 }
 
-static inline int usb_bam_register_peer_reset_cb(u8 idx,
-	 int (*callback)(void *), void *param)
+static inline int usb_bam_register_peer_reset_cb(
+	int (*callback)(void *), void *param)
 {
 	return -ENODEV;
 }
@@ -198,15 +309,14 @@
 	return -ENODEV;
 }
 
-static inline void get_bam2bam_connection_info(u8 conn_idx,
-	enum usb_bam_pipe_dir pipe_dir, u32 *usb_bam_handle,
-	u32 *usb_bam_pipe_idx, u32 *peer_pipe_idx,
+static inline int get_bam2bam_connection_info(u8 idx,
+	u32 *usb_bam_handle, u32 *usb_bam_pipe_idx, u32 *peer_pipe_idx,
 	struct sps_mem_buffer *desc_fifo, struct sps_mem_buffer *data_fifo)
 {
-	return;
+	return -ENODEV;
 }
 
-static inline int usb_bam_reset(void)
+static inline int usb_bam_a2_reset(void)
 {
 	return -ENODEV;
 }
@@ -216,5 +326,20 @@
 	return -ENODEV;
 }
 
+static inline int usb_bam_get_qdss_idx(u8 num)
+{
+	return -ENODEV;
+}
+
+static inline void usb_bam_set_qdss_core(const char *qdss_core)
+{
+	return;
+}
+
+static inline int usb_bam_get_connection_idx(const char *name,
+		enum peer_bam client, enum usb_bam_pipe_dir dir, u32 num)
+{
+	return -ENODEV;
+}
 #endif
 #endif				/* _USB_BAM_H_ */
diff --git a/arch/arm/mach-msm/mdm.c b/arch/arm/mach-msm/mdm.c
index fd8c878..7474215 100644
--- a/arch/arm/mach-msm/mdm.c
+++ b/arch/arm/mach-msm/mdm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-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
@@ -119,7 +119,7 @@
 
 	CHARM_DBG("%s: setting AP2MDM_ERRFATAL high for a non graceful reset\n",
 			 __func__);
-	if (get_restart_level() == RESET_SOC)
+	if (subsys_get_restart_level(charm_subsys) == RESET_SOC)
 		pm8xxx_stay_on();
 
 	charm_disable_irqs();
@@ -237,7 +237,7 @@
 static void charm_fatal_fn(struct work_struct *work)
 {
 	pr_info("Reseting the charm due to an errfatal\n");
-	if (get_restart_level() == RESET_SOC)
+	if (subsys_get_restart_level(charm_subsys) == RESET_SOC)
 		pm8xxx_stay_on();
 	subsystem_restart_dev(charm_subsys);
 }
diff --git a/arch/arm/mach-msm/pil-dsps.c b/arch/arm/mach-msm/pil-dsps.c
index 0630e6a..65d60d6 100644
--- a/arch/arm/mach-msm/pil-dsps.c
+++ b/arch/arm/mach-msm/pil-dsps.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-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
@@ -142,9 +142,6 @@
 
 static void dsps_restart_handler(struct dsps_data *drv)
 {
-	pr_debug("%s: Restart lvl %d\n",
-		__func__, get_restart_level());
-
 	if (atomic_add_return(1, &drv->crash_in_progress) > 1) {
 		pr_err("%s: DSPS already resetting. Count %d\n", __func__,
 		       atomic_read(&drv->crash_in_progress));
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index 7fbbf2c..a22d664 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -999,10 +999,15 @@
 	 * up as they enter the deepest sleep mode, namely RPM assited power
 	 * collapse
 	 */
-	if (!enable)
+	if (!enable) {
+		preempt_disable();
 		smp_call_function_many(cpu_online_mask,
 				msm_pm_ack_retention_disable,
 				NULL, true);
+		preempt_enable();
+
+
+	}
 }
 EXPORT_SYMBOL(msm_pm_enable_retention);
 
diff --git a/arch/arm/mach-msm/restart.c b/arch/arm/mach-msm/restart.c
index a67af45..d95f979 100644
--- a/arch/arm/mach-msm/restart.c
+++ b/arch/arm/mach-msm/restart.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-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
@@ -253,7 +253,7 @@
 		__raw_writel(0x31F3, msm_tmr0_base + WDT0_BITE_TIME);
 		__raw_writel(1, msm_tmr0_base + WDT0_EN);
 	} else {
-		/* Needed for 8974: Reset GCC_WDOG_DEBUG register */
+		/* Needed to bypass debug image on some chips */
 		msm_disable_wdog_debug();
 		__raw_writel(0, MSM_MPM2_PSHOLD_BASE);
 	}
diff --git a/arch/arm/mach-msm/smd_pkt.c b/arch/arm/mach-msm/smd_pkt.c
index eb7aa8a..7eb9ead 100644
--- a/arch/arm/mach-msm/smd_pkt.c
+++ b/arch/arm/mach-msm/smd_pkt.c
@@ -645,8 +645,9 @@
 	struct smd_pkt_dev *smd_pkt_devp = priv;
 
 	if (smd_pkt_devp->ch == 0) {
-		pr_err("%s on a closed smd_pkt_dev id:%d\n",
-			__func__, smd_pkt_devp->i);
+		if (event != SMD_EVENT_CLOSE)
+			pr_err("%s on a closed smd_pkt_dev id:%d\n",
+					__func__, smd_pkt_devp->i);
 		return;
 	}
 
diff --git a/arch/arm/mach-msm/subsystem_restart.c b/arch/arm/mach-msm/subsystem_restart.c
index 29481d3..5fe7a29 100644
--- a/arch/arm/mach-msm/subsystem_restart.c
+++ b/arch/arm/mach-msm/subsystem_restart.c
@@ -72,6 +72,11 @@
 	[SUBSYS_ONLINE] = "ONLINE",
 };
 
+static const char * const restart_levels[] = {
+	[RESET_SOC] = "SYSTEM",
+	[RESET_SUBSYS_COUPLED] = "RELATED",
+};
+
 /**
  * struct subsys_tracking - track state of a subsystem or restart order
  * @p_state: private state of subsystem/order
@@ -123,6 +128,7 @@
  * @owner: module that provides @desc
  * @count: reference count of subsystem_get()/subsystem_put()
  * @id: ida
+ * @restart_level: restart level (0 - panic, 1 - related, 2 - independent, etc.)
  * @restart_order: order of other devices this devices restarts with
  * @dentry: debugfs directory for this device
  * @do_ramdump_on_put: ramdump on subsystem_put() if true
@@ -140,6 +146,7 @@
 	struct module *owner;
 	int count;
 	int id;
+	int restart_level;
 	struct subsys_soc_restart_order *restart_order;
 #ifdef CONFIG_DEBUG_FS
 	struct dentry *dentry;
@@ -167,6 +174,38 @@
 	return snprintf(buf, PAGE_SIZE, "%s\n", subsys_states[state]);
 }
 
+static ssize_t
+restart_level_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	int level = to_subsys(dev)->restart_level;
+	return snprintf(buf, PAGE_SIZE, "%s\n", restart_levels[level]);
+}
+
+static ssize_t restart_level_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct subsys_device *subsys = to_subsys(dev);
+	int i;
+	const char *p;
+
+	p = memchr(buf, '\n', count);
+	if (p)
+		count = p - buf;
+
+	for (i = 0; i < ARRAY_SIZE(restart_levels); i++)
+		if (!strncasecmp(buf, restart_levels[i], count)) {
+			subsys->restart_level = i;
+			return count;
+		}
+	return -EPERM;
+}
+
+int subsys_get_restart_level(struct subsys_device *dev)
+{
+	return dev->restart_level;
+}
+EXPORT_SYMBOL(subsys_get_restart_level);
+
 static void subsys_set_state(struct subsys_device *subsys,
 			     enum subsys_state state)
 {
@@ -199,6 +238,7 @@
 static struct device_attribute subsys_attrs[] = {
 	__ATTR_RO(name),
 	__ATTR_RO(state),
+	__ATTR(restart_level, 0644, restart_level_show, restart_level_store),
 	__ATTR_NULL,
 };
 
@@ -259,48 +299,6 @@
 static struct subsys_soc_restart_order **restart_orders;
 static int n_restart_orders;
 
-static int restart_level = RESET_SOC;
-
-int get_restart_level()
-{
-	return restart_level;
-}
-EXPORT_SYMBOL(get_restart_level);
-
-static int restart_level_set(const char *val, struct kernel_param *kp)
-{
-	int ret;
-	int old_val = restart_level;
-
-	if (cpu_is_msm9615()) {
-		pr_err("Only Phase 1 subsystem restart is supported\n");
-		return -EINVAL;
-	}
-
-	ret = param_set_int(val, kp);
-	if (ret)
-		return ret;
-
-	switch (restart_level) {
-	case RESET_SUBSYS_INDEPENDENT:
-		if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE) {
-			pr_info("Phase 3 is currently unsupported. Using phase 2 instead.\n");
-			restart_level = RESET_SUBSYS_COUPLED;
-		}
-	case RESET_SUBSYS_COUPLED:
-	case RESET_SOC:
-		pr_info("Phase %d behavior activated.\n", restart_level);
-		break;
-	default:
-		restart_level = old_val;
-		return -EINVAL;
-	}
-	return 0;
-}
-
-module_param_call(restart_level, restart_level_set, param_get_int,
-			&restart_level, 0644);
-
 static struct subsys_soc_restart_order *
 update_restart_order(struct subsys_device *dev)
 {
@@ -484,7 +482,7 @@
 {
 	struct subsys_soc_restart_order *order = subsys->restart_order;
 
-	if (restart_level != RESET_SUBSYS_INDEPENDENT && order)
+	if (order)
 		return &order->track;
 	else
 		return &subsys->track;
@@ -603,7 +601,7 @@
 	 * This is because the subsystem list inside the relevant
 	 * restart order is not being traversed.
 	 */
-	if (restart_level != RESET_SUBSYS_INDEPENDENT && order) {
+	if (order) {
 		list = order->subsys_ptrs;
 		count = order->count;
 		track = &order->track;
@@ -662,7 +660,8 @@
 	struct subsys_tracking *track;
 	unsigned long flags;
 
-	pr_debug("Restarting %s [level=%d]!\n", desc->name, restart_level);
+	pr_debug("Restarting %s [level=%s]!\n", desc->name,
+			restart_levels[dev->restart_level]);
 
 	track = subsys_get_track(dev);
 	/*
@@ -708,13 +707,12 @@
 		return -EBUSY;
 	}
 
-	pr_info("Restart sequence requested for %s, restart_level = %d.\n",
-		name, restart_level);
+	pr_info("Restart sequence requested for %s, restart_level = %s.\n",
+		name, restart_levels[dev->restart_level]);
 
-	switch (restart_level) {
+	switch (dev->restart_level) {
 
 	case RESET_SUBSYS_COUPLED:
-	case RESET_SUBSYS_INDEPENDENT:
 		__subsystem_restart_dev(dev);
 		break;
 	case RESET_SOC:
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index f410e7f..3144113 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -1082,9 +1082,11 @@
 		__raw_writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
 		gpt->status_mask = BIT(10);
 		dgt->status_mask = BIT(2);
-		gpt->freq = 32765;
-		gpt_hz = 32765;
-		sclk_hz = 32765;
+		if (!soc_class_is_apq8064()) {
+			gpt->freq = 32765;
+			gpt_hz = 32765;
+			sclk_hz = 32765;
+		}
 		if (!soc_class_is_msm8930() && !cpu_is_msm8960ab()) {
 			gpt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT;
 			dgt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT;
diff --git a/arch/arm/mach-msm/wdog_debug.c b/arch/arm/mach-msm/wdog_debug.c
index 8b39d26..cccca26 100644
--- a/arch/arm/mach-msm/wdog_debug.c
+++ b/arch/arm/mach-msm/wdog_debug.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-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
@@ -10,144 +10,31 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/mutex.h>
-#include <linux/sched.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
+#include <linux/module.h>
 #include <mach/scm.h>
-#include <linux/slab.h>
 
-#define MODULE_NAME "wdog_debug"
-#define WDOG_DEBUG_EN 17
-#define GCC_WDOG_DEBUG_OFFSET 0x780
-
-struct msm_wdog_debug_data {
-	unsigned int __iomem phys_base;
-	size_t size;
-	void __iomem *base;
-	struct device *dev;
-};
-
-static struct msm_wdog_debug_data *wdog_data;
-
-void msm_disable_wdog_debug(void)
-{
-	unsigned long int value;
-
-	if (wdog_data == NULL)
-		return;
-	value = readl_relaxed(wdog_data->base + GCC_WDOG_DEBUG_OFFSET);
-	value &= ~BIT(WDOG_DEBUG_EN);
-	writel_relaxed(value, wdog_data->base + GCC_WDOG_DEBUG_OFFSET);
-
-	/* Ensure the WDOG_DEBUG_EN status has changed */
-	while (readl_relaxed(wdog_data->base + GCC_WDOG_DEBUG_OFFSET) &
-		BIT(WDOG_DEBUG_EN))
-			;
-}
-EXPORT_SYMBOL(msm_disable_wdog_debug);
+#define SCM_WDOG_DEBUG_BOOT_PART	0x9
+#define BOOT_PART_EN_VAL		0x5D1
 
 void msm_enable_wdog_debug(void)
 {
-	unsigned long int value;
+	int ret;
 
-	if (wdog_data == NULL)
-		return;
-	value = readl_relaxed(wdog_data->base + GCC_WDOG_DEBUG_OFFSET);
-	value |= BIT(WDOG_DEBUG_EN);
-	writel_relaxed(value, wdog_data->base + GCC_WDOG_DEBUG_OFFSET);
+	ret = scm_call_atomic2(SCM_SVC_BOOT,
+			       SCM_WDOG_DEBUG_BOOT_PART, 0, BOOT_PART_EN_VAL);
+	if (ret)
+		pr_err("failed to enable wdog debug\n");
 }
 EXPORT_SYMBOL(msm_enable_wdog_debug);
 
-static int __devexit msm_wdog_debug_remove(struct platform_device *pdev)
-{
-	kfree(wdog_data);
-	wdog_data = NULL;
-	pr_info("MSM wdog_debug Exit - Deactivated\n");
-	return 0;
-}
-
-static int __devinit msm_wdog_debug_dt_to_pdata(struct platform_device *pdev,
-					struct msm_wdog_debug_data *pdata)
-{
-	struct resource *wdog_resource;
-
-	wdog_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!wdog_resource) {
-		dev_err(&pdev->dev, \
-		"%s cannot allocate resource for wdog_debug\n", \
-		 __func__);
-		return -ENXIO;
-	}
-	pdata->size = resource_size(wdog_resource);
-	pdata->phys_base = wdog_resource->start;
-	if (unlikely(!(devm_request_region(&pdev->dev, pdata->phys_base,
-					pdata->size, "msm-wdog-debug")))) {
-		dev_err(&pdev->dev, "%s cannot reserve wdog_debug region\n",
-								__func__);
-		return -ENXIO;
-	}
-	pdata->base  = devm_ioremap(&pdev->dev, pdata->phys_base,
-							pdata->size);
-	if (!pdata->base) {
-		dev_err(&pdev->dev, "%s cannot map wdog register space\n",
-				__func__);
-		return -ENXIO;
-	}
-
-	return 0;
-}
-
-static int __devinit msm_wdog_debug_probe(struct platform_device *pdev)
+void msm_disable_wdog_debug(void)
 {
 	int ret;
-	if (!pdev->dev.of_node)
-		return -ENODEV;
-	wdog_data = kzalloc(sizeof(struct msm_wdog_debug_data), GFP_KERNEL);
-	if (!wdog_data)
-		return -ENOMEM;
-	ret = msm_wdog_debug_dt_to_pdata(pdev, wdog_data);
+
+	ret = scm_call_atomic2(SCM_SVC_BOOT,
+			       SCM_WDOG_DEBUG_BOOT_PART, 1, 0);
 	if (ret)
-		goto err;
-	wdog_data->dev = &pdev->dev;
-	platform_set_drvdata(pdev, wdog_data);
-	return 0;
-err:
-	kzfree(wdog_data);
-	wdog_data = NULL;
-	return ret;
+		pr_err("failed to disable wdog debug\n");
 }
-
-static struct of_device_id msm_wdog_debug_match_table[] = {
-	{ .compatible = "qcom,msm-wdog-debug" },
-	{}
-};
-
-static struct platform_driver msm_wdog_debug_driver = {
-	.probe = msm_wdog_debug_probe,
-	.remove = msm_wdog_debug_remove,
-	.driver = {
-		.name = MODULE_NAME,
-		.owner = THIS_MODULE,
-		.of_match_table = msm_wdog_debug_match_table,
-	},
-};
-
-static int __devinit wdog_debug_init(void)
-{
-	return platform_driver_register(&msm_wdog_debug_driver);
-}
-module_init(wdog_debug_init);
-
-static void __exit wdog_debug_exit(void)
-{
-	platform_driver_unregister(&msm_wdog_debug_driver);
-}
-module_exit(wdog_debug_exit);
-
-MODULE_DESCRIPTION("MSM Driver to disable debug Image");
-MODULE_LICENSE("GPL v2");
+EXPORT_SYMBOL(msm_disable_wdog_debug);
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 38da432..f16f700 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -381,6 +381,10 @@
 EXPORT_SYMBOL(memory_hole_start);
 unsigned long memory_hole_end;
 EXPORT_SYMBOL(memory_hole_end);
+unsigned long memory_hole_align;
+EXPORT_SYMBOL(memory_hole_align);
+unsigned long virtual_hole_start;
+unsigned long virtual_hole_end;
 
 #ifdef CONFIG_DONT_MAP_HOLE_AFTER_MEMBANK0
 void find_memory_hole(void)
@@ -388,6 +392,7 @@
 	int i;
 	unsigned long hole_start;
 	unsigned long hole_size;
+	unsigned long hole_end_virt;
 
 	/*
 	 * Find the start and end of the hole, using meminfo
@@ -420,7 +425,32 @@
 			}
 		}
 	}
+
 	memory_hole_offset = memory_hole_start - PHYS_OFFSET;
+	if (!IS_ALIGNED(memory_hole_start, SECTION_SIZE)) {
+		pr_err("memory_hole_start %lx is not aligned to %lx\n",
+			memory_hole_start, SECTION_SIZE);
+		BUG();
+	}
+	if (!IS_ALIGNED(memory_hole_end, SECTION_SIZE)) {
+		pr_err("memory_hole_end %lx is not aligned to %lx\n",
+			memory_hole_end, SECTION_SIZE);
+		BUG();
+	}
+
+	hole_end_virt = __phys_to_virt(memory_hole_end);
+
+	if ((!IS_ALIGNED(hole_end_virt, PMD_SIZE) &&
+	     IS_ALIGNED(memory_hole_end, PMD_SIZE)) ||
+	     (IS_ALIGNED(hole_end_virt, PMD_SIZE) &&
+	      !IS_ALIGNED(memory_hole_end, PMD_SIZE))) {
+		memory_hole_align = max(hole_end_virt & ~PMD_MASK,
+					memory_hole_end & ~PMD_MASK);
+		virtual_hole_start = hole_end_virt;
+		virtual_hole_end = hole_end_virt + memory_hole_align;
+		pr_info("Physical memory hole is not aligned. There will be a virtual memory hole from %lx to %lx\n",
+			virtual_hole_start, virtual_hole_end);
+	}
 }
 
 #endif
diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c
index 3a8bbc5..ed91480 100644
--- a/drivers/base/dma-contiguous.c
+++ b/drivers/base/dma-contiguous.c
@@ -213,8 +213,7 @@
 	__be32 *prop;
 	char *name;
 
-	if (strncmp(uname, "region@", 7) != 0 || depth != 2 ||
-	    !of_get_flat_dt_prop(node, "linux,contiguous-region", NULL))
+	if (!of_get_flat_dt_prop(node, "linux,contiguous-region", NULL))
 		return 0;
 
 	prop = of_get_flat_dt_prop(node, "reg", &len);
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 532df09..a4eea54 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -291,6 +291,7 @@
 	struct diag_request *write_ptr_mdm;
 #endif
 #ifdef CONFIG_DIAGFWD_BRIDGE_CODE
+	spinlock_t hsic_ready_spinlock;
 	/* common for all bridges */
 	struct work_struct diag_disconnect_work;
 	/* SGLTE variables */
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index c523457..65fc89f 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -516,10 +516,59 @@
 	*pnum_data = num_data;
 	return exit_stat;
 }
+
+static void diag_update_data_ready(int index)
+{
+	int clear_bit = 1;
+	unsigned long hsic_lock_flags;
+	unsigned long ready_lock_flags;
+	int i;
+
+	/*
+	 * Determine whether the data_ready USER_SPACE_DATA_TYPE bit
+	 * should be updated/cleared or not. There is a race condition that
+	 * can occur when in MEMORY_DEVICE_MODE with the hsic data.
+	 * When new hsic data arrives we prepare the data so it can
+	 * later be copied to userspace.  We set the USER_SPACE_DATA_TYPE
+	 * bit in data ready at that time. We later copy the hsic data
+	 * to userspace and clear the USER_SPACE_DATA_TYPE bit in
+	 * data ready. The race condition occurs if new data arrives (bit set)
+	 * while we are processing the current data and sending
+	 * it to userspace (bit clear).  The clearing of the bit can
+	 * overwrite the setting of the bit.
+	 */
+
+	spin_lock_irqsave(&driver->hsic_ready_spinlock, ready_lock_flags);
+	for (i = 0; i < MAX_HSIC_CH; i++) {
+		if (diag_hsic[i].hsic_inited) {
+			spin_lock_irqsave(&diag_hsic[i].hsic_spinlock,
+							hsic_lock_flags);
+			if ((diag_hsic[i].num_hsic_buf_tbl_entries > 0) &&
+				diag_hsic[i].hsic_device_enabled &&
+				diag_hsic[i].hsic_ch) {
+				/* New data do not clear the bit */
+				clear_bit = 0;
+			}
+			spin_unlock_irqrestore(&diag_hsic[i].hsic_spinlock,
+							hsic_lock_flags);
+			if (!clear_bit)
+				break;
+		}
+	}
+
+	if (clear_bit)
+		driver->data_ready[index] ^= USER_SPACE_DATA_TYPE;
+
+	spin_unlock_irqrestore(&driver->hsic_ready_spinlock, ready_lock_flags);
+}
 #else
 inline uint16_t diag_get_remote_device_mask(void) { return 0; }
 inline int diag_copy_remote(char __user *buf, size_t count, int *pret,
 			    int *pnum_data) { return 0; }
+static void diag_update_data_ready(int index)
+{
+	driver->data_ready[index] ^= USER_SPACE_DATA_TYPE;
+}
 #endif
 
 int diag_command_reg(unsigned long ioarg)
@@ -1164,7 +1213,7 @@
 		/* copy number of data fields */
 		COPY_USER_SPACE_OR_EXIT(buf+4, num_data, 4);
 		ret -= 4;
-		driver->data_ready[index] ^= USER_SPACE_DATA_TYPE;
+		diag_update_data_ready(index);
 		for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) {
 			if (driver->smd_data[i].ch)
 				queue_work(driver->diag_wq,
@@ -1750,6 +1799,7 @@
 		diag_masks_init();
 		diagfwd_init();
 #ifdef CONFIG_DIAGFWD_BRIDGE_CODE
+		spin_lock_init(&driver->hsic_ready_spinlock);
 		diagfwd_bridge_init(HSIC);
 		diagfwd_bridge_init(HSIC_2);
 		/* register HSIC device */
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 2aca8cf..6a14143 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -351,12 +351,32 @@
 	diag_smd_send_req(smd_info);
 }
 
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
+static void diag_mem_dev_mode_ready_update(int index, int hsic_updated)
+{
+	if (hsic_updated) {
+		unsigned long flags;
+		spin_lock_irqsave(&driver->hsic_ready_spinlock, flags);
+		driver->data_ready[index] |= USER_SPACE_DATA_TYPE;
+		spin_unlock_irqrestore(&driver->hsic_ready_spinlock, flags);
+	} else {
+		driver->data_ready[index] |= USER_SPACE_DATA_TYPE;
+	}
+}
+#else
+static void diag_mem_dev_mode_ready_update(int index, int hsic_updated)
+{
+	(void) hsic_updated;
+	driver->data_ready[index] |= USER_SPACE_DATA_TYPE;
+}
+#endif
 int diag_device_write(void *buf, int data_type, struct diag_request *write_ptr)
 {
 	int i, err = 0, index;
 	index = 0;
 
 	if (driver->logging_mode == MEMORY_DEVICE_MODE) {
+		int hsic_updated = 0;
 		if (data_type == APPS_DATA) {
 			for (i = 0; i < driver->poolsize_write_struct; i++)
 				if (driver->buf_tbl[i].length == 0) {
@@ -377,6 +397,7 @@
 		else if (data_type == HSIC_DATA || data_type == HSIC_2_DATA) {
 			unsigned long flags;
 			int foundIndex = -1;
+			hsic_updated = 1;
 			index = data_type - HSIC_DATA;
 			spin_lock_irqsave(&diag_hsic[index].hsic_spinlock,
 									flags);
@@ -409,7 +430,7 @@
 						 driver->logging_process_id)
 				break;
 		if (i < driver->num_clients) {
-			driver->data_ready[i] |= USER_SPACE_DATA_TYPE;
+			diag_mem_dev_mode_ready_update(i, hsic_updated);
 			pr_debug("diag: wake up logging process\n");
 			wake_up_interruptible(&driver->wait_q);
 		} else
diff --git a/drivers/coresight/coresight-etm.c b/drivers/coresight/coresight-etm.c
index 2ae54ea..1033233 100644
--- a/drivers/coresight/coresight-etm.c
+++ b/drivers/coresight/coresight-etm.c
@@ -265,6 +265,16 @@
 
 static struct etm_drvdata *etmdrvdata[NR_CPUS];
 
+static bool etm_os_lock_present(struct etm_drvdata *drvdata)
+{
+	uint32_t etmoslsr;
+
+	etmoslsr = etm_readl(drvdata, ETMOSLSR);
+	if (!BVAL(etmoslsr, 0) && !BVAL(etmoslsr, 3))
+		return false;
+	return true;
+}
+
 /*
  * Memory mapped writes to clear os lock are not supported on Krait v1, v2
  * and OS lock must be unlocked before any memory mapped access, otherwise
@@ -272,10 +282,17 @@
  */
 static void etm_os_unlock(void *info)
 {
+	struct etm_drvdata *drvdata = (struct etm_drvdata *) info;
+
+	ETM_UNLOCK(drvdata);
 	if (cpu_is_krait()) {
 		etm_writel_cp14(0x0, ETMOSLAR);
 		isb();
+	} else if (etm_os_lock_present(drvdata)) {
+		etm_writel(drvdata, 0x0, ETMOSLAR);
+		mb();
 	}
+	ETM_LOCK(drvdata);
 }
 
 /*
@@ -2104,7 +2121,7 @@
 	get_online_cpus();
 	etmdrvdata[drvdata->cpu] = drvdata;
 
-	if (!smp_call_function_single(drvdata->cpu, etm_os_unlock, NULL, 1))
+	if (!smp_call_function_single(drvdata->cpu, etm_os_unlock, drvdata, 1))
 		drvdata->os_unlock = true;
 	/*
 	 * Use CPU0 to populate read-only configuration data for ETM0. For
diff --git a/drivers/coresight/coresight-tmc.c b/drivers/coresight/coresight-tmc.c
index 0afb5a2..86276b7 100644
--- a/drivers/coresight/coresight-tmc.c
+++ b/drivers/coresight/coresight-tmc.c
@@ -217,7 +217,7 @@
 {
 	struct tmc_etr_bam_data *bamdata = drvdata->bamdata;
 
-	get_bam2bam_connection_info(0, PEER_PERIPHERAL_TO_USB,
+	get_bam2bam_connection_info(usb_bam_get_qdss_idx(0),
 				    &bamdata->dest,
 				    &bamdata->dest_pipe_idx,
 				    &bamdata->src_pipe_idx,
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 6e1ecd1..e2869d4 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -2477,7 +2477,11 @@
 		mutex_unlock(&dev_priv->device->mutex);
 	}
 
-	if (ret == 0 && (cmd & IOC_OUT)) {
+	/*
+	 * Still copy back on failure, but assume function took
+	 * all necessary precautions sanitizing the return values.
+	 */
+	if (cmd & IOC_OUT) {
 		if (copy_to_user((void __user *) arg, uptr, _IOC_SIZE(cmd)))
 			ret = -EFAULT;
 	}
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index 70a704b..c568db5 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -158,7 +158,7 @@
 	void *hostptr; /* kernel virtual address */
 	unsigned long useraddr; /* userspace address */
 	unsigned int gpuaddr;
-	unsigned int physaddr;
+	phys_addr_t physaddr;
 	unsigned int size;
 	unsigned int priv; /* Internal flags and settings */
 	struct scatterlist *sg;
diff --git a/drivers/gpu/msm/kgsl_gpummu.c b/drivers/gpu/msm/kgsl_gpummu.c
index 8f28505..9a1a431 100644
--- a/drivers/gpu/msm/kgsl_gpummu.c
+++ b/drivers/gpu/msm/kgsl_gpummu.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -161,7 +161,7 @@
 }
 
 static void *
-_kgsl_ptpool_get_entry(struct kgsl_ptpool *pool, unsigned int *physaddr)
+_kgsl_ptpool_get_entry(struct kgsl_ptpool *pool, phys_addr_t *physaddr)
 {
 	struct kgsl_ptpool_chunk *chunk;
 
@@ -227,7 +227,7 @@
  */
 
 static void *kgsl_ptpool_alloc(struct kgsl_ptpool *pool,
-				unsigned int *physaddr)
+				phys_addr_t *physaddr)
 {
 	void *addr = NULL;
 	int ret;
diff --git a/drivers/gpu/msm/kgsl_gpummu.h b/drivers/gpu/msm/kgsl_gpummu.h
index 99e7d5f..1753aff 100644
--- a/drivers/gpu/msm/kgsl_gpummu.h
+++ b/drivers/gpu/msm/kgsl_gpummu.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -57,7 +57,7 @@
 	int dynamic;
 
 	void *data;
-	unsigned int phys;
+	phys_addr_t phys;
 
 	unsigned long *bitmap;
 	struct list_head list;
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 83cf83d..01b255c 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -759,9 +759,8 @@
 
 	/*global mappings must have the same gpu address in all pagetables*/
 	if (gpuaddr && gpuaddr != memdesc->gpuaddr) {
-		KGSL_CORE_ERR("pt %p addr mismatch phys 0x%08x"
-			"gpu 0x%0x 0x%08x", pagetable, memdesc->physaddr,
-			gpuaddr, memdesc->gpuaddr);
+		KGSL_CORE_ERR("pt %p addr mismatch phys %pa gpu 0x%0x 0x%08x",
+		     pagetable, &memdesc->physaddr, gpuaddr, memdesc->gpuaddr);
 		goto error_unmap;
 	}
 	return result;
diff --git a/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_platform.c b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_platform.c
index d5a8098..f0882f7 100644
--- a/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_platform.c
+++ b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_platform.c
@@ -15,7 +15,7 @@
 #include <linux/clk.h>
 #include <mach/clk.h>
 #include <linux/io.h>
-#include <linux/android_pmem.h>
+
 #include <mach/camera.h>
 #include <mach/iommu_domains.h>
 
@@ -35,8 +35,6 @@
 	ion_unmap_iommu(gemini_client, *ionhandle, CAMERA_DOMAIN, GEN_POOL);
 	ion_free(gemini_client, *ionhandle);
 	*ionhandle = NULL;
-#elif CONFIG_ANDROID_PMEM
-	put_pmem_file(file);
 #endif
 }
 
@@ -53,9 +51,6 @@
 
 	rc = ion_map_iommu(gemini_client, *ionhandle, CAMERA_DOMAIN, GEN_POOL,
 			SZ_4K, 0, &paddr, (unsigned long *)&size, 0, 0);
-#elif CONFIG_ANDROID_PMEM
-	unsigned long kvstart;
-	rc = get_pmem_file(fd, &paddr, &kvstart, &size, file_p);
 #else
 	rc = 0;
 	paddr = 0;
diff --git a/drivers/media/platform/msm/camera_v1/mercury/msm_mercury_platform.c b/drivers/media/platform/msm/camera_v1/mercury/msm_mercury_platform.c
index e6392fe..3607f2e 100644
--- a/drivers/media/platform/msm/camera_v1/mercury/msm_mercury_platform.c
+++ b/drivers/media/platform/msm/camera_v1/mercury/msm_mercury_platform.c
@@ -13,7 +13,7 @@
 #include <linux/module.h>
 #include <linux/clk.h>
 #include <linux/io.h>
-#include <linux/android_pmem.h>
+
 #include <mach/clk.h>
 #include <mach/camera.h>
 #include <mach/msm_subsystem_map.h>
@@ -39,8 +39,6 @@
 		GEN_POOL);
 	ion_free(mercury_client, *ionhandle);
 	*ionhandle = NULL;
-#elif CONFIG_ANDROID_PMEM
-	put_pmem_file(file);
 #endif
 }
 
@@ -59,10 +57,6 @@
 	rc = ion_map_iommu(mercury_client, *ionhandle, CAMERA_DOMAIN,
 		GEN_POOL, SZ_4K, 0, &paddr,
 		(unsigned long *)&size, 0, 0);
-#elif CONFIG_ANDROID_PMEM
-	unsigned long kvstart;
-	rc = get_pmem_file(fd, &paddr, &kvstart, &size, file_p);
-#else
 	rc = 0;
 	paddr = 0;
 	size = 0;
diff --git a/drivers/media/platform/msm/camera_v1/msm_camera.c b/drivers/media/platform/msm/camera_v1/msm_camera.c
index 622ecfd..213ccc7 100644
--- a/drivers/media/platform/msm/camera_v1/msm_camera.c
+++ b/drivers/media/platform/msm/camera_v1/msm_camera.c
@@ -28,7 +28,7 @@
 #include <linux/fs.h>
 #include <linux/list.h>
 #include <linux/uaccess.h>
-#include <linux/android_pmem.h>
+
 #include <linux/poll.h>
 #include <media/msm_camera.h>
 #include <mach/camera.h>
@@ -319,15 +319,6 @@
 			goto out1;
 		ion_phys(client_for_ion, region->handle,
 			&paddr, (size_t *)&len);
-#else
-	rc = get_pmem_file(info->fd, &paddr, &kvstart, &len, &file);
-	if (rc < 0) {
-		pr_err("%s: get_pmem_file fd %d error %d\n",
-			__func__,
-			info->fd, rc);
-		goto out1;
-	}
-	region->file = file;
 #endif
 	if (!info->len)
 		info->len = len;
@@ -364,8 +355,6 @@
 out2:
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 	ion_free(client_for_ion, region->handle);
-#else
-	put_pmem_file(region->file);
 #endif
 out1:
 	kfree(region);
@@ -649,8 +638,6 @@
 				hlist_del(node);
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 				ion_free(client_for_ion, region->handle);
-#else
-				put_pmem_file(region->file);
 #endif
 				kfree(region);
 				CDBG("%s: type %d, vaddr  0x%p\n",
@@ -673,8 +660,6 @@
 				hlist_del(node);
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 				ion_free(client_for_ion, region->handle);
-#else
-				put_pmem_file(region->file);
 #endif
 				kfree(region);
 				CDBG("%s: type %d, vaddr  0x%p\n",
@@ -696,8 +681,6 @@
 				hlist_del(node);
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 				ion_free(client_for_ion, region->handle);
-#else
-				put_pmem_file(region->file);
 #endif
 				kfree(region);
 				CDBG("%s: type %d, vaddr  0x%p\n",
@@ -3012,8 +2995,6 @@
 			hlist_del(hnode);
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 				ion_free(client_for_ion, region->handle);
-#else
-			put_pmem_file(region->file);
 #endif
 			kfree(region);
 		}
@@ -3023,8 +3004,6 @@
 			hlist_del(hnode);
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 				ion_free(client_for_ion, region->handle);
-#else
-			put_pmem_file(region->file);
 #endif
 			kfree(region);
 		}
diff --git a/drivers/media/platform/msm/camera_v1/msm_isp.c b/drivers/media/platform/msm/camera_v1/msm_isp.c
index f646f09..59290ec 100644
--- a/drivers/media/platform/msm/camera_v1/msm_isp.c
+++ b/drivers/media/platform/msm/camera_v1/msm_isp.c
@@ -21,7 +21,7 @@
 #include <linux/videodev2.h>
 #include <linux/proc_fs.h>
 #include <linux/vmalloc.h>
-#include <linux/android_pmem.h>
+
 
 #include <media/v4l2-dev.h>
 #include <media/v4l2-ioctl.h>
diff --git a/drivers/media/platform/msm/camera_v1/msm_mctl.c b/drivers/media/platform/msm/camera_v1/msm_mctl.c
index 0210d23..95e889d 100644
--- a/drivers/media/platform/msm/camera_v1/msm_mctl.c
+++ b/drivers/media/platform/msm/camera_v1/msm_mctl.c
@@ -26,7 +26,7 @@
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-device.h>
 
-#include <linux/android_pmem.h>
+
 
 #include "msm.h"
 #include "msm_cam_server.h"
diff --git a/drivers/media/platform/msm/camera_v1/msm_mctl_buf.c b/drivers/media/platform/msm/camera_v1/msm_mctl_buf.c
index 3ccd258..041f674 100644
--- a/drivers/media/platform/msm/camera_v1/msm_mctl_buf.c
+++ b/drivers/media/platform/msm/camera_v1/msm_mctl_buf.c
@@ -23,7 +23,7 @@
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-device.h>
 
-#include <linux/android_pmem.h>
+
 
 #include "msm.h"
 #include "msm_cam_server.h"
@@ -1015,78 +1015,6 @@
 	D("%s Frame mapped successfully ", __func__);
 	return 0;
 }
-#else
-/* Unmap using PMEM APIs */
-static int __msm_mctl_unmap_user_frame(struct msm_cam_meta_frame *meta_frame,
-	struct ion_client *client, int domain_num)
-{
-	int i = 0, rc = 0;
-
-	for (i = 0; i < meta_frame->frame.num_planes; i++) {
-		D("%s Plane %d handle %p", __func__, i,
-			meta_frame->map[i].handle);
-		put_pmem_file(meta_frame->map[i].file);
-	}
-}
-
-/* Map using PMEM APIs */
-static int __msm_mctl_map_user_frame(struct msm_cam_meta_frame *meta_frame,
-	struct ion_client *client, int domain_num)
-{
-	unsigned long kvstart = 0;
-	unsigned long paddr = 0;
-	struct file *file = NULL;
-	unsigned long len;
-	int i = 0, j = 0;
-
-	for (i = 0; i < meta_frame->frame.num_planes; i++) {
-		rc = get_pmem_file(meta_frame->frame.mp[i].fd,
-			&paddr, &kvstart, &len, &file);
-		if (rc < 0) {
-			pr_err("%s: get_pmem_file fd %d error %d\n",
-				__func__, meta_frame->frame.mp[i].fd, rc);
-			/* Roll back previous plane mappings, if any */
-			for (j = i-1; j >= 0; j--)
-				if (meta_frame->map[j].file)
-					put_pmem_file(meta_frame->map[j].file);
-
-			return -EACCES;
-		}
-		D("%s Got pmem file for fd %d plane %d as %p", __func__,
-			meta_frame->frame.mp[i].fd, i, file);
-		meta_frame->map[i].file = file;
-		/* Validate the offsets with the mapped length. */
-		if ((meta_frame->frame.mp[i].addr_offset > len) ||
-			(meta_frame->frame.mp[i].data_offset +
-			meta_frame->frame.mp[i].length > len)) {
-			pr_err("%s: Invalid offsets A %d D %d L %d len %ld",
-				__func__, meta_frame->frame.mp[i].addr_offset,
-				meta_frame->frame.mp[i].data_offset,
-				meta_frame->frame.mp[i].length, len);
-			/* Roll back previous plane mappings, if any */
-			for (j = i; j >= 0; j--)
-				if (meta_frame->map[j].file)
-					put_pmem_file(meta_frame->map[j].file);
-
-			return -EINVAL;
-		}
-		meta_frame->map[i].data_offset =
-			meta_frame->frame.mp[i].data_offset;
-		/* Add the addr_offset to the paddr here itself. The addr_offset
-		 * will be non-zero only if the user has allocated a buffer with
-		 * a single fd, but logically partitioned it into
-		 * multiple planes or buffers.*/
-		paddr += meta_frame->frame.mp[i].addr_offset;
-		meta_frame->map[i].paddr = paddr;
-		meta_frame->map[i].len = len;
-		D("%s Plane %d fd %d handle %p paddr %x", __func__,
-			i, meta_frame->frame.mp[i].fd,
-			meta_frame->map[i].handle,
-			(uint32_t)meta_frame->map[i].paddr);
-	}
-	D("%s Frame mapped successfully ", __func__);
-	return 0;
-}
 #endif
 
 int msm_mctl_map_user_frame(struct msm_cam_meta_frame *meta_frame,
diff --git a/drivers/media/platform/msm/camera_v1/msm_mctl_pp.c b/drivers/media/platform/msm/camera_v1/msm_mctl_pp.c
index 9267c9f..ae3ce63 100644
--- a/drivers/media/platform/msm/camera_v1/msm_mctl_pp.c
+++ b/drivers/media/platform/msm/camera_v1/msm_mctl_pp.c
@@ -25,7 +25,7 @@
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-device.h>
 
-#include <linux/android_pmem.h>
+
 
 #include "msm.h"
 #include "msm_vpe.h"
diff --git a/drivers/media/platform/msm/camera_v1/msm_mem.c b/drivers/media/platform/msm/camera_v1/msm_mem.c
index 8144415..c9a87d7 100644
--- a/drivers/media/platform/msm/camera_v1/msm_mem.c
+++ b/drivers/media/platform/msm/camera_v1/msm_mem.c
@@ -25,7 +25,7 @@
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-device.h>
 
-#include <linux/android_pmem.h>
+
 
 #include "msm.h"
 
@@ -71,26 +71,6 @@
 
 static DEFINE_MUTEX(hlist_mut);
 
-#ifdef CONFIG_ANDROID_PMEM
-static int check_pmem_info(struct msm_pmem_info *info, int len)
-{
-	if (info->offset < len &&
-		info->offset + info->len <= len &&
-		info->planar0_off < len &&
-		info->planar1_off < len)
-		return 0;
-
-	pr_err("%s: check failed: off %d len %d y %d cbcr %d (total len %d)\n",
-						__func__,
-						info->offset,
-						info->len,
-						info->planar0_off,
-						info->planar1_off,
-						len);
-	return -EINVAL;
-}
-#endif
-
 static int check_overlap(struct hlist_head *ptype,
 				unsigned long paddr,
 				unsigned long len)
@@ -138,14 +118,6 @@
 	if (ion_map_iommu(client, region->handle, domain_num, 0,
 				  SZ_4K, 0, &paddr, &len, 0, 0) < 0)
 		goto out2;
-#elif CONFIG_ANDROID_PMEM
-	rc = get_pmem_file(info->fd, &paddr, &kvstart, &len, &file);
-	if (rc < 0) {
-		pr_err("%s: get_pmem_file fd %d error %d\n",
-				__func__, info->fd, rc);
-		goto out1;
-	}
-	region->file = file;
 #else
 	paddr = 0;
 	file = NULL;
@@ -153,9 +125,6 @@
 #endif
 	if (!info->len)
 		info->len = len;
-	rc = check_pmem_info(info, len);
-	if (rc < 0)
-		goto out3;
 	paddr += info->offset;
 	len = info->len;
 
@@ -185,8 +154,6 @@
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 out2:
 	ion_free(client, region->handle);
-#elif CONFIG_ANDROID_PMEM
-	put_pmem_file(region->file);
 #endif
 out1:
 	kfree(region);
@@ -256,8 +223,6 @@
 				ion_unmap_iommu(client, region->handle,
 					domain_num, 0);
 				ion_free(client, region->handle);
-#else
-				put_pmem_file(region->file);
 #endif
 				kfree(region);
 			}
diff --git a/drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x.c b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x.c
index bbf9d1b..d7ec547 100644
--- a/drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x.c
+++ b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x.c
@@ -14,7 +14,7 @@
 #include <linux/msm_adsp.h>
 #include <linux/uaccess.h>
 #include <linux/fs.h>
-#include <linux/android_pmem.h>
+
 #include <linux/slab.h>
 #include <mach/msm_adsp.h>
 #include <mach/clk.h>
diff --git a/drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x27a.c b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x27a.c
index 0279c78..6b41b03 100644
--- a/drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x27a.c
+++ b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x27a.c
@@ -13,7 +13,7 @@
 #include <linux/msm_adsp.h>
 #include <linux/uaccess.h>
 #include <linux/fs.h>
-#include <linux/android_pmem.h>
+
 #include <linux/slab.h>
 #include <linux/pm_qos.h>
 #include <linux/delay.h>
diff --git a/drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x27a_v4l2.c b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x27a_v4l2.c
index f3388d9..3a8f1b2 100644
--- a/drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x27a_v4l2.c
+++ b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe7x27a_v4l2.c
@@ -13,7 +13,7 @@
 #include <linux/msm_adsp.h>
 #include <linux/uaccess.h>
 #include <linux/fs.h>
-#include <linux/android_pmem.h>
+
 #include <linux/slab.h>
 #include <linux/pm_qos.h>
 #include <linux/delay.h>
diff --git a/drivers/media/platform/msm/camera_v1/vfe/msm_vfe_stats_buf.c b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe_stats_buf.c
index a6807ed..a550d78 100644
--- a/drivers/media/platform/msm/camera_v1/vfe/msm_vfe_stats_buf.c
+++ b/drivers/media/platform/msm/camera_v1/vfe/msm_vfe_stats_buf.c
@@ -25,7 +25,7 @@
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-device.h>
 
-#include <linux/android_pmem.h>
+
 #include <media/msm_camera.h>
 #include <media/msm_isp.h>
 #include "msm.h"
@@ -162,25 +162,6 @@
 	return rc;
 }
 
-#ifdef CONFIG_ANDROID_PMEM
-static int msm_stats_check_pmem_info(struct msm_stats_buf_info *info, int len)
-{
-	if (info->offset < len &&
-		info->offset + info->len <= len &&
-		info->planar0_off < len && info->planar1_off < len)
-		return 0;
-
-	pr_err("%s: check failed: off %d len %d y %d cbcr %d (total len %d)\n",
-		   __func__,
-		   info->offset,
-		   info->len,
-		   info->planar0_off,
-		   info->planar1_off,
-		   len);
-	return -EINVAL;
-}
-#endif
-
 static int msm_stats_buf_prepare(struct msm_stats_bufq_ctrl *stats_ctrl,
 	struct msm_stats_buf_info *info, struct ion_client *client,
 	int domain_num)
@@ -226,14 +207,6 @@
 		pr_err("%s: cannot map address", __func__);
 		goto out2;
 	}
-#elif CONFIG_ANDROID_PMEM
-	rc = get_pmem_file(info->fd, &paddr, &kvstart, &len, &file);
-	if (rc < 0) {
-		pr_err("%s: get_pmem_file fd %d error %d\n",
-			   __func__, info->fd, rc);
-		goto out1;
-	}
-	stats_buf->file = file;
 #else
 	paddr = 0;
 	file = NULL;
@@ -241,11 +214,6 @@
 #endif
 	if (!info->len)
 		info->len = len;
-	rc = msm_stats_check_pmem_info(info, len);
-	if (rc < 0) {
-		pr_err("%s: msm_stats_check_pmem_info err = %d", __func__, rc);
-		goto out3;
-	}
 	paddr += info->offset;
 	len = info->len;
 	stats_buf->paddr = paddr;
@@ -256,15 +224,12 @@
 	D("%s pmem_stats address is 0x%ld\n", __func__, paddr);
 	stats_buf->state = MSM_STATS_BUFFER_STATE_PREPARED;
 	return 0;
-out3:
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 	ion_unmap_iommu(client, stats_buf->handle, domain_num, 0);
 #endif
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 out2:
 	ion_free(client, stats_buf->handle);
-#elif CONFIG_ANDROID_PMEM
-	put_pmem_file(stats_buf->file);
 #endif
 out1:
 	return rc;
@@ -295,8 +260,6 @@
 	ion_unmap_iommu(client, stats_buf->handle,
 					domain_num, 0);
 	ion_free(client, stats_buf->handle);
-#else
-	put_pmem_file(stats_buf->file);
 #endif
 	if (stats_buf->state == MSM_STATS_BUFFER_STATE_QUEUED) {
 		/* buf queued need delete from list */
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
index c8873b8..3a24428 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
@@ -20,7 +20,7 @@
 #include <linux/proc_fs.h>
 #include <linux/videodev2.h>
 #include <linux/vmalloc.h>
-#include <linux/android_pmem.h>
+
 
 #include <media/v4l2-dev.h>
 #include <media/v4l2-ioctl.h>
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
index 69d523c..38130db 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
@@ -378,8 +378,8 @@
 	struct msm_vfe_tasklet_queue_cmd
 		tasklet_queue_cmd[MSM_VFE_TASKLETQ_SIZE];
 
+	uint32_t vfe_hw_version;
 	struct msm_vfe_hardware_info *hw_info;
-
 	struct msm_vfe_axi_shared_data axi_data;
 	struct msm_vfe_stats_shared_data stats_data;
 	struct msm_vfe_error_info error_info;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
index fc0a8b5..b136125 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -29,6 +29,9 @@
 #define CDBG(fmt, args...) do { } while (0)
 #endif
 
+#define VFE40_V1_VERSION 0x10000018
+#define VFE40_V2_VERSION 0x1001001A
+
 #define VFE40_BURST_LEN 3
 #define VFE40_STATS_BURST_LEN 2
 #define VFE40_UB_SIZE 1536
@@ -123,53 +126,99 @@
 static void msm_vfe40_init_qos_parms(struct vfe_device *vfe_dev)
 {
 	void __iomem *vfebase = vfe_dev->vfe_base;
-	msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_0);
-	msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_1);
-	msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_2);
-	msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_3);
-	msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_4);
-	msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_5);
-	msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_6);
-	msm_camera_io_w(0x0002AAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_7);
+	if (vfe_dev->vfe_hw_version == VFE40_V1_VERSION) {
+		msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_0);
+		msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_1);
+		msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_2);
+		msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_3);
+		msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_4);
+		msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_5);
+		msm_camera_io_w(0xAAAAAAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_6);
+		msm_camera_io_w(0x0002AAAA, vfebase + VFE40_BUS_BDG_QOS_CFG_7);
+	} else if (vfe_dev->vfe_hw_version == VFE40_V2_VERSION) {
+		msm_camera_io_w(0xAAA9AAA9, vfebase + VFE40_BUS_BDG_QOS_CFG_0);
+		msm_camera_io_w(0xAAA9AAA9, vfebase + VFE40_BUS_BDG_QOS_CFG_1);
+		msm_camera_io_w(0xAAA9AAA9, vfebase + VFE40_BUS_BDG_QOS_CFG_2);
+		msm_camera_io_w(0xAAA9AAA9, vfebase + VFE40_BUS_BDG_QOS_CFG_3);
+		msm_camera_io_w(0xAAA9AAA9, vfebase + VFE40_BUS_BDG_QOS_CFG_4);
+		msm_camera_io_w(0xAAA9AAA9, vfebase + VFE40_BUS_BDG_QOS_CFG_5);
+		msm_camera_io_w(0xAAA9AAA9, vfebase + VFE40_BUS_BDG_QOS_CFG_6);
+		msm_camera_io_w(0x0001AAA9, vfebase + VFE40_BUS_BDG_QOS_CFG_7);
+	}
 }
 
-static void msm_vfe40_init_vbif_parms(
-	void __iomem *vfe_vbif_base)
+static void msm_vfe40_init_vbif_parms(struct vfe_device *vfe_dev)
 {
-	msm_camera_io_w(0x1,
-		vfe_vbif_base + VFE40_VBIF_CLKON);
-	msm_camera_io_w(0x01010101,
-		vfe_vbif_base + VFE40_VBIF_IN_RD_LIM_CONF0);
-	msm_camera_io_w(0x01010101,
-		vfe_vbif_base + VFE40_VBIF_IN_RD_LIM_CONF1);
-	msm_camera_io_w(0x10010110,
-		vfe_vbif_base + VFE40_VBIF_IN_RD_LIM_CONF2);
-	msm_camera_io_w(0x10101010,
-		vfe_vbif_base + VFE40_VBIF_IN_WR_LIM_CONF0);
-	msm_camera_io_w(0x10101010,
-		vfe_vbif_base + VFE40_VBIF_IN_WR_LIM_CONF1);
-	msm_camera_io_w(0x10101010,
-		vfe_vbif_base + VFE40_VBIF_IN_WR_LIM_CONF2);
-	msm_camera_io_w(0x00001010,
-		vfe_vbif_base + VFE40_VBIF_OUT_RD_LIM_CONF0);
-	msm_camera_io_w(0x00001010,
-		vfe_vbif_base + VFE40_VBIF_OUT_WR_LIM_CONF0);
-	msm_camera_io_w(0x00000707,
-		vfe_vbif_base + VFE40_VBIF_DDR_OUT_MAX_BURST);
-	msm_camera_io_w(0x00000707,
-		vfe_vbif_base + VFE40_VBIF_OCMEM_OUT_MAX_BURST);
-	msm_camera_io_w(0x00000030,
-		vfe_vbif_base + VFE40_VBIF_ARB_CTL);
-	msm_camera_io_w(0x00000FFF,
-		vfe_vbif_base + VFE40_VBIF_OUT_AXI_AOOO_EN);
-	msm_camera_io_w(0x0FFF0FFF,
-		vfe_vbif_base + VFE40_VBIF_OUT_AXI_AOOO);
-	msm_camera_io_w(0x00000001,
-		vfe_vbif_base + VFE40_VBIF_ROUND_ROBIN_QOS_ARB);
-	msm_camera_io_w(0x22222222,
-		vfe_vbif_base + VFE40_VBIF_OUT_AXI_AMEMTYPE_CONF0);
-	msm_camera_io_w(0x00002222,
-		vfe_vbif_base + VFE40_VBIF_OUT_AXI_AMEMTYPE_CONF1);
+	void __iomem *vfe_vbif_base = vfe_dev->vfe_vbif_base;
+	if (vfe_dev->vfe_hw_version == VFE40_V1_VERSION) {
+		msm_camera_io_w(0x1,
+			vfe_vbif_base + VFE40_VBIF_CLKON);
+		msm_camera_io_w(0x01010101,
+			vfe_vbif_base + VFE40_VBIF_IN_RD_LIM_CONF0);
+		msm_camera_io_w(0x01010101,
+			vfe_vbif_base + VFE40_VBIF_IN_RD_LIM_CONF1);
+		msm_camera_io_w(0x10010110,
+			vfe_vbif_base + VFE40_VBIF_IN_RD_LIM_CONF2);
+		msm_camera_io_w(0x10101010,
+			vfe_vbif_base + VFE40_VBIF_IN_WR_LIM_CONF0);
+		msm_camera_io_w(0x10101010,
+			vfe_vbif_base + VFE40_VBIF_IN_WR_LIM_CONF1);
+		msm_camera_io_w(0x10101010,
+			vfe_vbif_base + VFE40_VBIF_IN_WR_LIM_CONF2);
+		msm_camera_io_w(0x00001010,
+			vfe_vbif_base + VFE40_VBIF_OUT_RD_LIM_CONF0);
+		msm_camera_io_w(0x00001010,
+			vfe_vbif_base + VFE40_VBIF_OUT_WR_LIM_CONF0);
+		msm_camera_io_w(0x00000707,
+			vfe_vbif_base + VFE40_VBIF_DDR_OUT_MAX_BURST);
+		msm_camera_io_w(0x00000707,
+			vfe_vbif_base + VFE40_VBIF_OCMEM_OUT_MAX_BURST);
+		msm_camera_io_w(0x00000030,
+			vfe_vbif_base + VFE40_VBIF_ARB_CTL);
+		msm_camera_io_w(0x00000FFF,
+			vfe_vbif_base + VFE40_VBIF_OUT_AXI_AOOO_EN);
+		msm_camera_io_w(0x0FFF0FFF,
+			vfe_vbif_base + VFE40_VBIF_OUT_AXI_AOOO);
+		msm_camera_io_w(0x00000001,
+			vfe_vbif_base + VFE40_VBIF_ROUND_ROBIN_QOS_ARB);
+		msm_camera_io_w(0x22222222,
+			vfe_vbif_base + VFE40_VBIF_OUT_AXI_AMEMTYPE_CONF0);
+		msm_camera_io_w(0x00002222,
+			vfe_vbif_base + VFE40_VBIF_OUT_AXI_AMEMTYPE_CONF1);
+	} else if (vfe_dev->vfe_hw_version == VFE40_V2_VERSION) {
+		msm_camera_io_w(0x1,
+			vfe_vbif_base + VFE40_VBIF_CLKON);
+		msm_camera_io_w(0x10101010,
+			vfe_vbif_base + VFE40_VBIF_IN_RD_LIM_CONF0);
+		msm_camera_io_w(0x10101010,
+			vfe_vbif_base + VFE40_VBIF_IN_RD_LIM_CONF1);
+		msm_camera_io_w(0x10101010,
+			vfe_vbif_base + VFE40_VBIF_IN_RD_LIM_CONF2);
+		msm_camera_io_w(0x10101010,
+			vfe_vbif_base + VFE40_VBIF_IN_WR_LIM_CONF0);
+		msm_camera_io_w(0x10101010,
+			vfe_vbif_base + VFE40_VBIF_IN_WR_LIM_CONF1);
+		msm_camera_io_w(0x10101010,
+			vfe_vbif_base + VFE40_VBIF_IN_WR_LIM_CONF2);
+		msm_camera_io_w(0x00000010,
+			vfe_vbif_base + VFE40_VBIF_OUT_RD_LIM_CONF0);
+		msm_camera_io_w(0x00000010,
+			vfe_vbif_base + VFE40_VBIF_OUT_WR_LIM_CONF0);
+		msm_camera_io_w(0x00000707,
+			vfe_vbif_base + VFE40_VBIF_DDR_OUT_MAX_BURST);
+		msm_camera_io_w(0x00000010,
+			vfe_vbif_base + VFE40_VBIF_ARB_CTL);
+		msm_camera_io_w(0x00000FFF,
+			vfe_vbif_base + VFE40_VBIF_OUT_AXI_AOOO_EN);
+		msm_camera_io_w(0x0FFF0FFF,
+			vfe_vbif_base + VFE40_VBIF_OUT_AXI_AOOO);
+		msm_camera_io_w(0x00000003,
+			vfe_vbif_base + VFE40_VBIF_ROUND_ROBIN_QOS_ARB);
+		msm_camera_io_w(0x22222222,
+			vfe_vbif_base + VFE40_VBIF_OUT_AXI_AMEMTYPE_CONF0);
+		msm_camera_io_w(0x00002222,
+			vfe_vbif_base + VFE40_VBIF_OUT_AXI_AMEMTYPE_CONF1);
+	}
 }
 
 static int msm_vfe40_init_hardware(struct vfe_device *vfe_dev)
@@ -254,7 +303,7 @@
 static void msm_vfe40_init_hardware_reg(struct vfe_device *vfe_dev)
 {
 	msm_vfe40_init_qos_parms(vfe_dev);
-	msm_vfe40_init_vbif_parms(vfe_dev->vfe_vbif_base);
+	msm_vfe40_init_vbif_parms(vfe_dev);
 	/* CGC_OVERRIDE */
 	msm_camera_io_w(0x3FFFFFFF, vfe_dev->vfe_base + 0x14);
 	msm_camera_io_w(0xC001FF7F, vfe_dev->vfe_base + 0x974);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
index 5baeb28..f337e27 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
@@ -637,6 +637,9 @@
 		mutex_unlock(&vfe_dev->mutex);
 		return -EINVAL;
 	}
+	vfe_dev->vfe_hw_version = msm_camera_io_r(vfe_dev->vfe_base);
+	ISP_DBG("%s: HW Version: 0x%x\n", __func__, vfe_dev->vfe_hw_version);
+
 	vfe_dev->hw_info->vfe_ops.core_ops.init_hw_reg(vfe_dev);
 
 	for (i = 0; i < vfe_dev->hw_info->num_iommu_ctx; i++)
@@ -649,10 +652,6 @@
 		sizeof(struct msm_vfe_stats_shared_data));
 	memset(&vfe_dev->error_info, 0, sizeof(vfe_dev->error_info));
 	vfe_dev->axi_data.hw_info = vfe_dev->hw_info->axi_hw_info;
-
-	ISP_DBG("%s: HW Version: 0x%x\n",
-		__func__, msm_camera_io_r(vfe_dev->vfe_base));
-
 	vfe_dev->vfe_open_cnt++;
 	vfe_dev->taskletq_idx = 0;
 	mutex_unlock(&vfe_dev->mutex);
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c
index 8c484e7..b1253fa 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c
@@ -17,7 +17,7 @@
 #include <linux/clk.h>
 #include <mach/clk.h>
 #include <linux/io.h>
-#include <linux/android_pmem.h>
+
 #include <mach/camera.h>
 #include <mach/iommu_domains.h>
 #include <mach/msm_bus.h>
diff --git a/drivers/media/platform/msm/camera_v2/msm.c b/drivers/media/platform/msm/camera_v2/msm.c
index f8cddb2..6418f21 100644
--- a/drivers/media/platform/msm/camera_v2/msm.c
+++ b/drivers/media/platform/msm/camera_v2/msm.c
@@ -268,6 +268,8 @@
 	msm_enqueue(&session->stream_q, &stream->list);
 	session->stream_q.len++;
 
+	INIT_LIST_HEAD(&stream->queued_list);
+
 	return 0;
 }
 
@@ -852,6 +854,31 @@
 	return stream->vb2_q;
 }
 
+struct msm_stream *msm_get_stream_from_vb2q(struct vb2_queue *q)
+{
+	struct msm_session *session;
+	struct msm_stream *stream;
+	unsigned long flags1;
+	unsigned long flags2;
+	spin_lock_irqsave(&msm_session_q->lock, flags1);
+	list_for_each_entry(session, &(msm_session_q->list), list) {
+		spin_lock_irqsave(&(session->stream_q.lock), flags2);
+		list_for_each_entry(
+			stream, &(session->stream_q.list), list) {
+			if (stream->vb2_q == q) {
+				spin_unlock_irqrestore
+					(&(session->stream_q.lock), flags2);
+				spin_unlock_irqrestore
+					(&msm_session_q->lock, flags1);
+				return stream;
+			}
+		}
+		spin_unlock_irqrestore(&(session->stream_q.lock), flags2);
+	}
+	spin_unlock_irqrestore(&msm_session_q->lock, flags1);
+	return NULL;
+}
+
 static struct v4l2_subdev *msm_sd_find(const char *name)
 {
 	unsigned long flags;
diff --git a/drivers/media/platform/msm/camera_v2/msm.h b/drivers/media/platform/msm/camera_v2/msm.h
index eb15cab..39901ad 100644
--- a/drivers/media/platform/msm/camera_v2/msm.h
+++ b/drivers/media/platform/msm/camera_v2/msm.h
@@ -51,5 +51,6 @@
 	unsigned int stream_id);
 struct vb2_queue *msm_get_stream_vb2q(unsigned int session_id,
 	unsigned int stream_id);
+struct msm_stream *msm_get_stream_from_vb2q(struct vb2_queue *q);
 
 #endif /*_MSM_H */
diff --git a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c
index 079dbb5..29262af 100644
--- a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c
+++ b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c
@@ -38,22 +38,107 @@
 
 int msm_vb2_buf_init(struct vb2_buffer *vb)
 {
+	struct msm_stream *stream;
 	struct msm_vb2_buffer *msm_vb2_buf;
 
+	stream = msm_get_stream_from_vb2q(vb->vb2_queue);
+	if (!stream) {
+		pr_err("%s: Couldn't find stream\n", __func__);
+		return -EINVAL;
+	}
 	msm_vb2_buf = container_of(vb, struct msm_vb2_buffer, vb2_buf);
 	msm_vb2_buf->in_freeq = 0;
+	msm_vb2_buf->stream = stream;
 
 	return 0;
 }
 
 static void msm_vb2_buf_queue(struct vb2_buffer *vb)
 {
+	struct msm_vb2_buffer *msm_vb2;
+	struct msm_stream *stream;
+	unsigned long flags;
+
+	msm_vb2 = container_of(vb, struct msm_vb2_buffer, vb2_buf);
+
+	if (!msm_vb2) {
+		pr_err("%s:%d] vb2_buf NULL", __func__, __LINE__);
+		return;
+	}
+
+	stream = msm_vb2->stream;
+	if (!stream) {
+		pr_err("%s:%d] NULL stream", __func__, __LINE__);
+		return;
+	}
+
+	spin_lock_irqsave(&stream->stream_lock, flags);
+	list_add_tail(&msm_vb2->list, &stream->queued_list);
+	spin_unlock_irqrestore(&stream->stream_lock, flags);
+}
+
+static int msm_vb2_buf_finish(struct vb2_buffer *vb)
+{
+	struct msm_vb2_buffer *msm_vb2;
+	struct msm_stream *stream;
+	unsigned long flags;
+	struct msm_vb2_buffer *msm_vb2_entry, *temp;
+
+	msm_vb2 = container_of(vb, struct msm_vb2_buffer, vb2_buf);
+
+	if (!msm_vb2) {
+		pr_err("%s:%d] vb2_buf NULL", __func__, __LINE__);
+		return -EINVAL;
+	}
+
+	stream = msm_vb2->stream;
+	if (!stream) {
+		pr_err("%s:%d] NULL stream", __func__, __LINE__);
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&stream->stream_lock, flags);
+	list_for_each_entry_safe(msm_vb2_entry, temp, &(stream->queued_list),
+		list) {
+		if (msm_vb2_entry == msm_vb2) {
+			list_del_init(&msm_vb2_entry->list);
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&stream->stream_lock, flags);
+	return 0;
+}
+
+static void msm_vb2_buf_cleanup(struct vb2_buffer *vb)
+{
+	struct msm_vb2_buffer *msm_vb2;
+	struct msm_stream *stream;
+	unsigned long flags;
+
+	msm_vb2 = container_of(vb, struct msm_vb2_buffer, vb2_buf);
+
+	if (!msm_vb2) {
+		pr_err("%s:%d] vb2 NULL", __func__, __LINE__);
+		return;
+	}
+
+	stream = msm_vb2->stream;
+	if (!stream) {
+		pr_err("%s:%d] NULL stream", __func__, __LINE__);
+		return;
+	}
+
+	spin_lock_irqsave(&stream->stream_lock, flags);
+	INIT_LIST_HEAD(&stream->queued_list);
+	spin_unlock_irqrestore(&stream->stream_lock, flags);
 }
 
 static struct vb2_ops msm_vb2_get_q_op = {
-	.queue_setup		= msm_vb2_queue_setup,
-	.buf_init		= msm_vb2_buf_init,
-	.buf_queue              = msm_vb2_buf_queue,
+	.queue_setup	= msm_vb2_queue_setup,
+	.buf_init	= msm_vb2_buf_init,
+	.buf_queue	= msm_vb2_buf_queue,
+	.buf_cleanup	= msm_vb2_buf_cleanup,
+	.buf_finish	= msm_vb2_buf_finish,
 };
 
 
@@ -101,7 +186,7 @@
 {
 	struct msm_stream *stream;
 	struct vb2_buffer *vb2_buf = NULL;
-	struct msm_vb2_buffer *msm_vb2;
+	struct msm_vb2_buffer *msm_vb2 = NULL;
 	unsigned long flags;
 
 	stream = msm_get_stream(session_id, stream_id);
@@ -115,18 +200,18 @@
 		goto end;
 	}
 
-	list_for_each_entry(vb2_buf, &(stream->vb2_q->queued_list),
-		queued_entry) {
+	list_for_each_entry(msm_vb2, &(stream->queued_list), list) {
+		vb2_buf = &(msm_vb2->vb2_buf);
 		if (vb2_buf->state != VB2_BUF_STATE_ACTIVE)
 			continue;
 
-		msm_vb2 = container_of(vb2_buf, struct msm_vb2_buffer, vb2_buf);
 		if (msm_vb2->in_freeq)
 			continue;
 
 		msm_vb2->in_freeq = 1;
 		goto end;
 	}
+	msm_vb2 = NULL;
 	vb2_buf = NULL;
 end:
 	spin_unlock_irqrestore(&stream->stream_lock, flags);
@@ -136,9 +221,15 @@
 static int msm_vb2_put_buf(struct vb2_buffer *vb, int session_id,
 				unsigned int stream_id)
 {
+	struct msm_stream *stream;
 	struct msm_vb2_buffer *msm_vb2;
 	int rc = 0;
+	unsigned long flags;
+	stream = msm_get_stream(session_id, stream_id);
+	if (IS_ERR_OR_NULL(stream))
+		return -EINVAL;
 
+	spin_lock_irqsave(&stream->stream_lock, flags);
 	if (vb) {
 		msm_vb2 =
 			container_of(vb, struct msm_vb2_buffer, vb2_buf);
@@ -151,6 +242,7 @@
 		pr_err("%s: VB buffer is null\n", __func__);
 		rc = -EINVAL;
 	}
+	spin_unlock_irqrestore(&stream->stream_lock, flags);
 	return rc;
 }
 
diff --git a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.h b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.h
index cecc85e..027d344 100644
--- a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.h
+++ b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.h
@@ -42,6 +42,7 @@
 	struct vb2_buffer vb2_buf;
 	struct list_head list;
 	int in_freeq;
+	struct msm_stream *stream;
 };
 
 struct msm_vb2_private_data {
@@ -60,6 +61,7 @@
 	/* vb2 buffer handling */
 	struct vb2_queue *vb2_q;
 	spinlock_t stream_lock;
+	struct list_head queued_list;
 };
 
 struct vb2_ops *msm_vb2_get_q_ops(void);
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 41234c3..ca5e646 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
@@ -754,6 +754,9 @@
 	case VIDIOC_MSM_CPP_CFG:
 		rc = msm_cpp_cfg(cpp_dev, ioctl_ptr);
 		break;
+	case VIDIOC_MSM_CPP_FLUSH_QUEUE:
+		rc = msm_cpp_send_frame_to_hardware(cpp_dev);
+		break;
 	case VIDIOC_MSM_CPP_GET_EVENTPAYLOAD: {
 		struct msm_device_queue *queue = &cpp_dev->eventData_q;
 		struct msm_queue_cmd *event_qcmd;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index e55c0f1..b71a816 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -11,6 +11,7 @@
  *
  */
 
+#include <linux/jiffies.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <asm/div64.h>
@@ -21,7 +22,7 @@
 #include "msm_smem.h"
 #include "msm_vidc_debug.h"
 
-#define HW_RESPONSE_TIMEOUT (5 * 60 * 1000)
+#define HW_RESPONSE_TIMEOUT msecs_to_jiffies(200)
 
 #define IS_ALREADY_IN_STATE(__p, __d) ({\
 	int __rc = (__p >= __d);\
@@ -313,7 +314,7 @@
 	enum command_response cmd)
 {
 	int rc = 0;
-	rc = wait_for_completion_interruptible_timeout(
+	rc = wait_for_completion_timeout(
 		&inst->completions[SESSION_MSG_INDEX(cmd)],
 		msecs_to_jiffies(HW_RESPONSE_TIMEOUT));
 	if (!rc) {
diff --git a/drivers/media/platform/msm/vidc/q6_hfi.c b/drivers/media/platform/msm/vidc/q6_hfi.c
index 88dc4fe..d1948d1 100644
--- a/drivers/media/platform/msm/vidc/q6_hfi.c
+++ b/drivers/media/platform/msm/vidc/q6_hfi.c
@@ -1188,6 +1188,13 @@
 	return 0;
 }
 
+static int q6_hfi_get_stride_scanline(int color_fmt,
+	int width, int height, int *stride, int *scanlines) {
+	*stride = VENUS_Y_STRIDE(color_fmt, width);
+	*scanlines = VENUS_Y_SCANLINES(color_fmt, height);
+	return 0;
+}
+
 static void q6_init_hfi_callbacks(struct hfi_device *hdev)
 {
 	hdev->core_init = q6_hfi_core_init;
@@ -1223,6 +1230,7 @@
 	hdev->load_fw = q6_hfi_load_fw;
 	hdev->unload_fw = q6_hfi_unload_fw;
 	hdev->get_fw_info = q6_hfi_get_fw_info;
+	hdev->get_stride_scanline = q6_hfi_get_stride_scanline;
 }
 
 
diff --git a/drivers/media/video/videobuf-msm-mem.c b/drivers/media/video/videobuf-msm-mem.c
index 9e2cc22..eeda13a 100644
--- a/drivers/media/video/videobuf-msm-mem.c
+++ b/drivers/media/video/videobuf-msm-mem.c
@@ -24,7 +24,7 @@
 #include <linux/pagemap.h>
 #include <linux/sched.h>
 #include <linux/io.h>
-#include <linux/android_pmem.h>
+
 #include <linux/memory_alloc.h>
 #include <media/videobuf-msm-mem.h>
 #include <media/msm_camera.h>
@@ -140,55 +140,6 @@
 	.close    = videobuf_vm_close,
 };
 
-/**
- * videobuf_pmem_contig_user_put() - reset pointer to user space buffer
- * @mem: per-buffer private videobuf-contig-pmem data
- *
- * This function resets the user space pointer
- */
-static void videobuf_pmem_contig_user_put(struct videobuf_contig_pmem *mem)
-{
-	if (mem->phyaddr) {
-		put_pmem_file(mem->file);
-		mem->is_userptr = 0;
-		mem->phyaddr = 0;
-		mem->size = 0;
-	}
-}
-
-/**
- * videobuf_pmem_contig_user_get() - setup user space memory pointer
- * @mem: per-buffer private videobuf-contig-pmem data
- * @vb: video buffer to map
- *
- * This function validates and sets up a pointer to user space memory.
- * Only physically contiguous pfn-mapped memory is accepted.
- *
- * Returns 0 if successful.
- */
-static int videobuf_pmem_contig_user_get(struct videobuf_contig_pmem *mem,
-					struct videobuf_buffer *vb)
-{
-	unsigned long kvstart;
-	unsigned long len;
-	int rc;
-
-	mem->size = PAGE_ALIGN(vb->size);
-	rc = get_pmem_file(vb->baddr, (unsigned long *)&mem->phyaddr,
-					&kvstart, &len, &mem->file);
-	if (rc < 0) {
-		pr_err("%s: get_pmem_file fd %lu error %d\n",
-					__func__, vb->baddr,
-							rc);
-		return rc;
-	}
-	mem->phyaddr += vb->boff;
-	mem->y_off = 0;
-	mem->cbcr_off = (vb->size)*2/3;
-	mem->is_userptr = 1;
-	return rc;
-}
-
 static struct videobuf_buffer *__videobuf_alloc(size_t size)
 {
 	struct videobuf_contig_pmem *mem;
@@ -229,12 +180,6 @@
 
 		/* All handling should be done by __videobuf_mmap_mapper() */
 		break;
-	case V4L2_MEMORY_USERPTR:
-		D("%s memory method USERPTR\n", __func__);
-
-		/* handle pointer from user space */
-		rc = videobuf_pmem_contig_user_get(mem, vb);
-		break;
 	case V4L2_MEMORY_OVERLAY:
 	default:
 		pr_err("%s memory method OVERLAY/unknown\n", __func__);
@@ -383,7 +328,6 @@
 
 	/* handle user space pointer case */
 	if (buf->baddr) {
-		videobuf_pmem_contig_user_put(mem);
 		return 0;
 	} else {
 		/* don't support read() method */
diff --git a/drivers/media/video/videobuf2-msm-mem.c b/drivers/media/video/videobuf2-msm-mem.c
index cd07db8..8dbb522 100644
--- a/drivers/media/video/videobuf2-msm-mem.c
+++ b/drivers/media/video/videobuf2-msm-mem.c
@@ -24,7 +24,7 @@
 #include <linux/pagemap.h>
 #include <linux/sched.h>
 #include <linux/io.h>
-#include <linux/android_pmem.h>
+
 #include <linux/memory_alloc.h>
 #include <media/videobuf2-msm-mem.h>
 #include <media/msm_camera.h>
@@ -177,15 +177,14 @@
 					struct ion_client *client,
 					int domain_num)
 {
-	unsigned long len;
 	int rc = 0;
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
-	unsigned long kvstart;
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	unsigned long len;
 #endif
 	unsigned long paddr = 0;
 	if (mem->phyaddr != 0)
 		return 0;
-#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+#if defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
 	mem->ion_handle = ion_import_dma_buf(client, (int)mem->vaddr);
 	if (IS_ERR_OR_NULL(mem->ion_handle)) {
 		pr_err("%s ION import failed\n", __func__);
@@ -195,17 +194,8 @@
 		SZ_4K, 0, (unsigned long *)&mem->phyaddr, &len, 0, 0);
 	if (rc < 0)
 		ion_free(client, mem->ion_handle);
-#elif CONFIG_ANDROID_PMEM
-	rc = get_pmem_file((int)mem->vaddr, (unsigned long *)&mem->phyaddr,
-					&kvstart, &len, &mem->file);
-	if (rc < 0) {
-		pr_err("%s: get_pmem_file fd %d error %d\n",
-					__func__, (int)mem->vaddr, rc);
-		return rc;
-	}
 #else
 	paddr = 0;
-	kvstart = 0;
 #endif
 	if (offset)
 		mem->offset = *offset;
@@ -224,12 +214,10 @@
 				struct ion_client *client, int domain_num)
 {
 	if (mem->is_userptr) {
-#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+#if defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
 		ion_unmap_iommu(client, mem->ion_handle,
 				domain_num, 0);
 		ion_free(client, mem->ion_handle);
-#elif CONFIG_ANDROID_PMEM
-		put_pmem_file(mem->file);
 #endif
 	}
 	mem->is_userptr = 0;
diff --git a/drivers/net/ethernet/msm/ecm_ipa.c b/drivers/net/ethernet/msm/ecm_ipa.c
index 28ba41a..41dd6e7 100644
--- a/drivers/net/ethernet/msm/ecm_ipa.c
+++ b/drivers/net/ethernet/msm/ecm_ipa.c
@@ -118,8 +118,8 @@
 
 static int ecm_ipa_rules_cfg(struct ecm_ipa_dev *dev,
 		const void *dst_mac, const void *src_mac);
-static int ecm_ipa_register_tx(struct ecm_ipa_dev *dev);
-static void ecm_ipa_deregister_tx(struct ecm_ipa_dev *dev);
+static int ecm_ipa_register_properties(void);
+static void ecm_ipa_deregister_properties(void);
 static int ecm_ipa_debugfs_init(struct ecm_ipa_dev *dev);
 static void ecm_ipa_debugfs_destroy(struct ecm_ipa_dev *dev);
 static int ecm_ipa_debugfs_tx_open(struct inode *inode, struct file *file);
@@ -262,13 +262,13 @@
 	strlcpy(ipv4_hdr->name, ECM_IPA_IPV4_HDR_NAME, IPA_RESOURCE_NAME_MAX);
 	memcpy(eth_ipv4->h_dest, dst_mac, ETH_ALEN);
 	memcpy(eth_ipv4->h_source, src_mac, ETH_ALEN);
-	eth_ipv4->h_proto = ETH_P_IP;
+	eth_ipv4->h_proto = htons(ETH_P_IP);
 	ipv4_hdr->hdr_len = ETH_HLEN;
 	ipv4_hdr->is_partial = 0;
 	strlcpy(ipv6_hdr->name, ECM_IPA_IPV6_HDR_NAME, IPA_RESOURCE_NAME_MAX);
 	memcpy(eth_ipv6->h_dest, dst_mac, ETH_ALEN);
 	memcpy(eth_ipv6->h_source, src_mac, ETH_ALEN);
-	eth_ipv6->h_proto = ETH_P_IPV6;
+	eth_ipv6->h_proto = htons(ETH_P_IPV6);
 	ipv6_hdr->hdr_len = ETH_HLEN;
 	ipv6_hdr->is_partial = 0;
 	hdrs->commit = 1;
@@ -320,14 +320,29 @@
 		ECM_IPA_ERROR("ipa_del_hdr failed");
 }
 
-static int ecm_ipa_register_tx(struct ecm_ipa_dev *dev)
+/* ecm_ipa_register_properties() - set Tx/Rx properties for ipacm
+ *
+ * Register ecm0 interface with 2 Tx properties and 2 Rx properties:
+ * The 2 Tx properties are for data flowing from IPA to USB, they
+ * have Header-Insertion properties both for Ipv4 and Ipv6 Ethernet framing.
+ * The 2 Rx properties are for data flowing from USB to IPA, they have
+ * simple rule which always "hit".
+ *
+ */
+static int ecm_ipa_register_properties(void)
 {
 	struct ipa_tx_intf tx_properties = {0};
 	struct ipa_ioc_tx_intf_prop properties[2] = { {0}, {0} };
 	struct ipa_ioc_tx_intf_prop *ipv4_property;
 	struct ipa_ioc_tx_intf_prop *ipv6_property;
+	struct ipa_ioc_rx_intf_prop rx_ioc_properties[2] = { {0}, {0} };
+	struct ipa_rx_intf rx_properties = {0};
+	struct ipa_ioc_rx_intf_prop *rx_ipv4_property;
+	struct ipa_ioc_rx_intf_prop *rx_ipv6_property;
 	int result = 0;
+
 	ECM_IPA_LOG_ENTRY();
+
 	tx_properties.prop = properties;
 	ipv4_property = &tx_properties.prop[0];
 	ipv4_property->ip = IPA_IP_v4;
@@ -340,18 +355,32 @@
 	strlcpy(ipv6_property->hdr_name, ECM_IPA_IPV6_HDR_NAME,
 			IPA_RESOURCE_NAME_MAX);
 	tx_properties.num_props = 2;
-	result = ipa_register_intf("ecm0", &tx_properties, NULL);
+
+	rx_properties.prop = rx_ioc_properties;
+	rx_ipv4_property = &rx_properties.prop[0];
+	rx_ipv4_property->ip = IPA_IP_v4;
+	rx_ipv4_property->attrib.attrib_mask = 0;
+	rx_ipv4_property->src_pipe = IPA_CLIENT_USB_PROD;
+	rx_ipv6_property = &rx_properties.prop[1];
+	rx_ipv6_property->ip = IPA_IP_v6;
+	rx_ipv6_property->attrib.attrib_mask = 0;
+	rx_ipv6_property->src_pipe = IPA_CLIENT_USB_PROD;
+	rx_properties.num_props = 2;
+
+	result = ipa_register_intf("ecm0", &tx_properties, &rx_properties);
 	if (result)
-		ECM_IPA_ERROR("fail on Tx_prop registration\n");
+		ECM_IPA_ERROR("fail on Tx/Rx properties registration\n");
+
 	ECM_IPA_LOG_EXIT();
+
 	return result;
 }
 
-static void ecm_ipa_deregister_tx(struct ecm_ipa_dev *dev)
+static void ecm_ipa_deregister_properties(void)
 {
 	int result;
 	ECM_IPA_LOG_ENTRY();
-	result = ipa_deregister_intf(dev->net->name);
+	result = ipa_deregister_intf("ecm0");
 	if (result)
 		ECM_IPA_DEBUG("Fail on Tx prop deregister\n");
 	ECM_IPA_LOG_EXIT();
@@ -407,12 +436,12 @@
 		goto fail_set_device_ethernet;
 	}
 	ECM_IPA_DEBUG("Ethernet header insertion was set\n");
-	result = ecm_ipa_register_tx(dev);
+	result = ecm_ipa_register_properties();
 	if (result) {
 		ECM_IPA_ERROR("fail on properties set\n");
 		goto fail_register_tx;
 	}
-	ECM_IPA_DEBUG("ECM Tx properties were registered\n");
+	ECM_IPA_DEBUG("ECM 2 Tx and 2 Rx properties were registered\n");
 	result = register_netdev(net);
 	if (result) {
 		ECM_IPA_ERROR("register_netdev failed: %d\n", result);
@@ -422,7 +451,7 @@
 	ECM_IPA_LOG_EXIT();
 	return 0;
 fail_register_netdev:
-	ecm_ipa_deregister_tx(dev);
+	ecm_ipa_deregister_properties();
 fail_register_tx:
 fail_set_device_ethernet:
 	ecm_ipa_rules_destroy(dev);
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index e9130f6..fa0c568 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -35,7 +35,6 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/if_arp.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/ctype.h>
@@ -362,9 +361,6 @@
 		return -ENOMEM;
 	}
 
-	if (dev->net->type != ARPHRD_RAWIP)
-		skb_reserve(skb, NET_IP_ALIGN);
-
 	entry = (struct skb_data *) skb->cb;
 	entry->urb = urb;
 	entry->dev = dev;
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index a9a850c..ef21b7b 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -28,34 +28,8 @@
 #include <linux/dma-mapping.h>
 #include <mach/msm_smsm.h>
 
-#define USB_SUMMING_THRESHOLD 512
-#define CONNECTIONS_NUM	8
-
-static struct sps_bam_props usb_props;
-static struct sps_pipe *sps_pipes[CONNECTIONS_NUM][2];
-static struct sps_connect sps_connections[CONNECTIONS_NUM][2];
-static struct sps_mem_buffer data_mem_buf[CONNECTIONS_NUM][2];
-static struct sps_mem_buffer desc_mem_buf[CONNECTIONS_NUM][2];
-static struct platform_device *usb_bam_pdev;
-static struct workqueue_struct *usb_bam_wq;
-static u32 h_bam;
-static spinlock_t usb_bam_lock;
-
-struct usb_bam_event_info {
-	struct sps_register_event event;
-	int (*callback)(void *);
-	void *param;
-	struct work_struct event_w;
-};
-
-struct usb_bam_connect_info {
-	u8 idx;
-	u32 *src_pipe;
-	u32 *dst_pipe;
-	struct usb_bam_event_info wake_event;
-	bool src_enabled;
-	bool dst_enabled;
-};
+#define USB_THRESHOLD 512
+#define USB_BAM_MAX_STR_LEN 50
 
 enum usb_bam_sm {
 	USB_BAM_SM_INIT = 0,
@@ -64,7 +38,7 @@
 	USB_BAM_SM_UNPLUG_NOTIFIED,
 };
 
-struct usb_bam_peer_handhskae_info {
+struct usb_bam_peer_handshake_info {
 	enum usb_bam_sm state;
 	bool client_ready;
 	bool ack_received;
@@ -72,26 +46,79 @@
 	struct usb_bam_event_info reset_event;
 };
 
-static struct usb_bam_connect_info usb_bam_connections[CONNECTIONS_NUM];
-static struct usb_bam_pipe_connect ***msm_usb_bam_connections_info;
-static struct usb_bam_pipe_connect *bam_connection_arr;
-void __iomem *qscratch_ram1_reg;
-struct clk *mem_clk;
-struct clk *mem_iface_clk;
-struct usb_bam_peer_handhskae_info peer_handhskae_info;
+struct usb_bam_sps_type {
+	struct sps_bam_props usb_props;
+	struct sps_pipe **sps_pipes;
+	struct sps_connect *sps_connections;
+};
 
-static int connect_pipe(u8 conn_idx, enum usb_bam_pipe_dir pipe_dir,
-						u32 *usb_pipe_idx)
+struct usb_bam_ctx_type {
+	struct usb_bam_sps_type usb_bam_sps;
+	struct platform_device *usb_bam_pdev;
+	struct workqueue_struct *usb_bam_wq;
+	void __iomem *qscratch_ram1_reg;
+	u8 max_connections;
+	struct clk *mem_clk;
+	struct clk *mem_iface_clk;
+	char qdss_core_name[USB_BAM_MAX_STR_LEN];
+	char bam_enabled_list[USB_BAM_MAX_STR_LEN];
+	u32 h_bam[MAX_BAMS];
+};
+
+static char *bam_enable_strings[3] = {
+	[SSUSB_BAM] = "ssusb",
+	[HSUSB_BAM] = "hsusb",
+	[HSIC_BAM]  = "hsic",
+};
+
+static spinlock_t usb_bam_lock;
+static struct usb_bam_peer_handshake_info peer_handshake_info;
+static struct usb_bam_pipe_connect *usb_bam_connections;
+static struct usb_bam_ctx_type ctx;
+
+static int get_bam_type_from_core_name(const char *name)
+{
+	if (strnstr(name, bam_enable_strings[SSUSB_BAM],
+			USB_BAM_MAX_STR_LEN) ||
+		strnstr(name, "dwc3", USB_BAM_MAX_STR_LEN))
+		return SSUSB_BAM;
+	else if (strnstr(name, bam_enable_strings[HSIC_BAM],
+			USB_BAM_MAX_STR_LEN))
+		return HSIC_BAM;
+	else if (strnstr(name, bam_enable_strings[HSUSB_BAM],
+			USB_BAM_MAX_STR_LEN) ||
+		strnstr(name, "ci", USB_BAM_MAX_STR_LEN))
+		return HSUSB_BAM;
+
+	pr_err("%s: invalid BAM name(%s)\n", __func__, name);
+	return -EINVAL;
+}
+
+static bool bam_use_private_mem(enum usb_bam bam)
+{
+	int i;
+
+	for (i = 0; i < ctx.max_connections; i++)
+		if (usb_bam_connections[i].bam_type == bam &&
+			usb_bam_connections[i].mem_type == USB_PRIVATE_MEM)
+				return true;
+
+	return false;
+}
+
+static int connect_pipe(u8 idx, u32 *usb_pipe_idx)
 {
 	int ret, ram1_value;
-	struct sps_pipe **pipe = &sps_pipes[conn_idx][pipe_dir];
-	struct sps_connect *connection =
-		&sps_connections[conn_idx][pipe_dir];
+	enum usb_bam bam;
+	struct usb_bam_sps_type usb_bam_sps = ctx.usb_bam_sps;
+	struct sps_pipe **pipe = &(usb_bam_sps.sps_pipes[idx]);
+	struct sps_connect *sps_connection = &usb_bam_sps.sps_connections[idx];
 	struct msm_usb_bam_platform_data *pdata =
-		usb_bam_pdev->dev.platform_data;
-	struct usb_bam_pipe_connect *pipe_connection =
-				&msm_usb_bam_connections_info
-				[pdata->usb_active_bam][conn_idx][pipe_dir];
+		ctx.usb_bam_pdev->dev.platform_data;
+	struct usb_bam_pipe_connect *pipe_connect = &usb_bam_connections[idx];
+	enum usb_bam_pipe_dir dir = pipe_connect->dir;
+	struct sps_mem_buffer *data_buf = &(pipe_connect->data_mem_buf);
+	struct sps_mem_buffer *desc_buf = &(pipe_connect->desc_mem_buf);
 
 	*pipe = sps_alloc_endpoint();
 	if (*pipe == NULL) {
@@ -99,42 +126,42 @@
 		return -ENOMEM;
 	}
 
-	ret = sps_get_config(*pipe, connection);
+	ret = sps_get_config(*pipe, sps_connection);
 	if (ret) {
 		pr_err("%s: tx get config failed %d\n", __func__, ret);
 		goto free_sps_endpoint;
 	}
 
-	ret = sps_phy2h(pipe_connection->src_phy_addr, &(connection->source));
+	ret = sps_phy2h(pipe_connect->src_phy_addr, &(sps_connection->source));
 	if (ret) {
 		pr_err("%s: sps_phy2h failed (src BAM) %d\n", __func__, ret);
 		goto free_sps_endpoint;
 	}
 
-	connection->src_pipe_index = pipe_connection->src_pipe_index;
-	ret = sps_phy2h(pipe_connection->dst_phy_addr,
-					&(connection->destination));
+	sps_connection->src_pipe_index = pipe_connect->src_pipe_index;
+	ret = sps_phy2h(pipe_connect->dst_phy_addr,
+		&(sps_connection->destination));
 	if (ret) {
 		pr_err("%s: sps_phy2h failed (dst BAM) %d\n", __func__, ret);
 		goto free_sps_endpoint;
 	}
-	connection->dest_pipe_index = pipe_connection->dst_pipe_index;
+	sps_connection->dest_pipe_index = pipe_connect->dst_pipe_index;
 
-	if (pipe_dir == USB_TO_PEER_PERIPHERAL) {
-		connection->mode = SPS_MODE_SRC;
-		*usb_pipe_idx = connection->src_pipe_index;
+	if (dir == USB_TO_PEER_PERIPHERAL) {
+		sps_connection->mode = SPS_MODE_SRC;
+		*usb_pipe_idx = pipe_connect->src_pipe_index;
 	} else {
-		connection->mode = SPS_MODE_DEST;
-		*usb_pipe_idx = connection->dest_pipe_index;
+		sps_connection->mode = SPS_MODE_DEST;
+		*usb_pipe_idx = pipe_connect->dst_pipe_index;
 	}
 
 	/* If BAM is using dedicated SPS pipe memory, get it */
-	if (pipe_connection->mem_type == SPS_PIPE_MEM) {
+	if (pipe_connect->mem_type == SPS_PIPE_MEM) {
 		pr_debug("%s: USB BAM using SPS pipe memory\n", __func__);
 		ret = sps_setup_bam2bam_fifo(
-				&data_mem_buf[conn_idx][pipe_dir],
-				pipe_connection->data_fifo_base_offset,
-				pipe_connection->data_fifo_size, 1);
+			data_buf,
+			pipe_connect->data_fifo_base_offset,
+			pipe_connect->data_fifo_size, 1);
 		if (ret) {
 			pr_err("%s: data fifo setup failure %d\n", __func__,
 				ret);
@@ -142,90 +169,84 @@
 		}
 
 		ret = sps_setup_bam2bam_fifo(
-				&desc_mem_buf[conn_idx][pipe_dir],
-				pipe_connection->desc_fifo_base_offset,
-				pipe_connection->desc_fifo_size, 1);
+			desc_buf,
+			pipe_connect->desc_fifo_base_offset,
+			pipe_connect->desc_fifo_size, 1);
 		if (ret) {
 			pr_err("%s: desc. fifo setup failure %d\n", __func__,
 				ret);
 			goto free_sps_endpoint;
 		}
-	} else if (pipe_connection->mem_type == USB_PRIVATE_MEM) {
+	} else if (pipe_connect->mem_type == USB_PRIVATE_MEM) {
 		pr_debug("%s: USB BAM using private memory\n", __func__);
 
-		if (IS_ERR(mem_clk) || IS_ERR(mem_iface_clk)) {
+		if (IS_ERR(ctx.mem_clk) || IS_ERR(ctx.mem_iface_clk)) {
 			pr_err("%s: Failed to enable USB mem_clk\n", __func__);
-			ret = IS_ERR(mem_clk);
+			ret = IS_ERR(ctx.mem_clk);
 			goto free_sps_endpoint;
 		}
 
-		clk_prepare_enable(mem_clk);
-		clk_prepare_enable(mem_iface_clk);
+		clk_prepare_enable(ctx.mem_clk);
+		clk_prepare_enable(ctx.mem_iface_clk);
 
 		/*
 		 * Enable USB PRIVATE RAM to be used for BAM FIFOs
 		 * HSUSB: Only RAM13 is used for BAM FIFOs
 		 * SSUSB: RAM11, 12, 13 are used for BAM FIFOs
 		 */
-		if (pdata->usb_active_bam == HSUSB_BAM)
+		bam = pipe_connect->bam_type;
+		if (bam < 0)
+			goto free_sps_endpoint;
+
+		if (bam == HSUSB_BAM)
 			ram1_value = 0x4;
 		else
 			ram1_value = 0x7;
 
 		pr_debug("Writing 0x%x to QSCRATCH_RAM1\n", ram1_value);
-		writel_relaxed(ram1_value, qscratch_ram1_reg);
+		writel_relaxed(ram1_value, ctx.qscratch_ram1_reg);
 
-		data_mem_buf[conn_idx][pipe_dir].phys_base =
-			pipe_connection->data_fifo_base_offset +
+		data_buf->phys_base =
+			pipe_connect->data_fifo_base_offset +
 				pdata->usb_base_address;
-		data_mem_buf[conn_idx][pipe_dir].size =
-			pipe_connection->data_fifo_size;
-		data_mem_buf[conn_idx][pipe_dir].base =
-			ioremap(data_mem_buf[conn_idx][pipe_dir].phys_base,
-				data_mem_buf[conn_idx][pipe_dir].size);
-		memset(data_mem_buf[conn_idx][pipe_dir].base, 0,
-			data_mem_buf[conn_idx][pipe_dir].size);
+		data_buf->size = pipe_connect->data_fifo_size;
+		data_buf->base =
+			ioremap(data_buf->phys_base, data_buf->size);
+		memset(data_buf->base, 0, data_buf->size);
 
-		desc_mem_buf[conn_idx][pipe_dir].phys_base =
-			pipe_connection->desc_fifo_base_offset +
+		desc_buf->phys_base =
+			pipe_connect->desc_fifo_base_offset +
 				pdata->usb_base_address;
-		desc_mem_buf[conn_idx][pipe_dir].size =
-			pipe_connection->desc_fifo_size;
-		desc_mem_buf[conn_idx][pipe_dir].base =
-			ioremap(desc_mem_buf[conn_idx][pipe_dir].phys_base,
-				desc_mem_buf[conn_idx][pipe_dir].size);
-		memset(desc_mem_buf[conn_idx][pipe_dir].base, 0,
-			desc_mem_buf[conn_idx][pipe_dir].size);
+		desc_buf->size = pipe_connect->desc_fifo_size;
+		desc_buf->base =
+			ioremap(desc_buf->phys_base, desc_buf->size);
+		memset(desc_buf->base, 0, desc_buf->size);
 	} else {
 		pr_debug("%s: USB BAM using system memory\n", __func__);
 		/* BAM would use system memory, allocate FIFOs */
-		data_mem_buf[conn_idx][pipe_dir].size =
-					pipe_connection->data_fifo_size;
-		data_mem_buf[conn_idx][pipe_dir].base =
-			dma_alloc_coherent(&usb_bam_pdev->dev,
-				    pipe_connection->data_fifo_size,
-				    &data_mem_buf[conn_idx][pipe_dir].phys_base,
-				    0);
-		memset(data_mem_buf[conn_idx][pipe_dir].base, 0,
-					pipe_connection->data_fifo_size);
+		data_buf->size = pipe_connect->data_fifo_size;
+		data_buf->base =
+			dma_alloc_coherent(&ctx.usb_bam_pdev->dev,
+			pipe_connect->data_fifo_size,
+			&(data_buf->phys_base),
+			0);
+		memset(data_buf->base, 0, pipe_connect->data_fifo_size);
 
-		desc_mem_buf[conn_idx][pipe_dir].size =
-					pipe_connection->desc_fifo_size;
-		desc_mem_buf[conn_idx][pipe_dir].base =
-			dma_alloc_coherent(&usb_bam_pdev->dev,
-				    pipe_connection->desc_fifo_size,
-				    &desc_mem_buf[conn_idx][pipe_dir].phys_base,
-				    0);
-		memset(desc_mem_buf[conn_idx][pipe_dir].base, 0,
-					pipe_connection->desc_fifo_size);
+		desc_buf->size = pipe_connect->desc_fifo_size;
+		desc_buf->base =
+			dma_alloc_coherent(&ctx.usb_bam_pdev->dev,
+			pipe_connect->desc_fifo_size,
+			&(desc_buf->phys_base),
+			0);
+		memset(desc_buf->base, 0, pipe_connect->desc_fifo_size);
 	}
 
-	connection->data = data_mem_buf[conn_idx][pipe_dir];
-	connection->desc = desc_mem_buf[conn_idx][pipe_dir];
-	connection->event_thresh = 16;
-	connection->options = SPS_O_AUTO_ENABLE;
+	sps_connection->data = *data_buf;
+	sps_connection->desc = *desc_buf;
+	sps_connection->event_thresh = 16;
+	sps_connection->options = SPS_O_AUTO_ENABLE;
 
-	ret = sps_connect(*pipe, connection);
+	ret = sps_connect(*pipe, sps_connection);
 	if (ret < 0) {
 		pr_err("%s: sps_connect failed %d\n", __func__, ret);
 		goto error;
@@ -239,20 +260,15 @@
 	return ret;
 }
 
-static int connect_pipe_ipa(
-			struct usb_bam_connect_ipa_params *connection_params)
+static int connect_pipe_ipa(u8 idx,
+			struct usb_bam_connect_ipa_params *ipa_params)
 {
 	int ret;
-	u8 conn_idx = connection_params->idx;
-	enum usb_bam_pipe_dir pipe_dir = connection_params->dir;
-	struct sps_pipe **pipe = &sps_pipes[conn_idx][pipe_dir];
-	struct sps_connect *connection =
-		&sps_connections[conn_idx][pipe_dir];
-	struct msm_usb_bam_platform_data *pdata =
-		usb_bam_pdev->dev.platform_data;
-	struct usb_bam_pipe_connect *pipe_connection =
-				&msm_usb_bam_connections_info
-				[pdata->usb_active_bam][conn_idx][pipe_dir];
+	struct usb_bam_sps_type usb_bam_sps = ctx.usb_bam_sps;
+	enum usb_bam_pipe_dir dir = ipa_params->dir;
+	struct sps_pipe **pipe = &(usb_bam_sps.sps_pipes[idx]);
+	struct sps_connect *sps_connection = &usb_bam_sps.sps_connections[idx];
+	struct usb_bam_pipe_connect *pipe_connect = &usb_bam_connections[idx];
 
 	struct ipa_connect_params ipa_in_params;
 	struct ipa_sps_params sps_out_params;
@@ -262,12 +278,12 @@
 	memset(&ipa_in_params, 0, sizeof(ipa_in_params));
 	memset(&sps_out_params, 0, sizeof(sps_out_params));
 
-	if (pipe_dir == USB_TO_PEER_PERIPHERAL) {
-		usb_phy_addr = pipe_connection->src_phy_addr;
-		ipa_in_params.client_ep_idx = pipe_connection->src_pipe_index;
+	if (dir == USB_TO_PEER_PERIPHERAL) {
+		usb_phy_addr = pipe_connect->src_phy_addr;
+		ipa_in_params.client_ep_idx = pipe_connect->src_pipe_index;
 	} else {
-		usb_phy_addr = pipe_connection->dst_phy_addr;
-		ipa_in_params.client_ep_idx = pipe_connection->dst_pipe_index;
+		usb_phy_addr = pipe_connect->dst_phy_addr;
+		ipa_in_params.client_ep_idx = pipe_connect->dst_pipe_index;
 	}
 	/* Get HSUSB / HSIC bam handle */
 	ret = sps_phy2h(usb_phy_addr, &usb_handle);
@@ -279,46 +295,41 @@
 
 	/* IPA input parameters */
 	ipa_in_params.client_bam_hdl = usb_handle;
-	ipa_in_params.desc_fifo_sz = pipe_connection->desc_fifo_size;
-	ipa_in_params.data_fifo_sz = pipe_connection->data_fifo_size;
-	ipa_in_params.notify = connection_params->notify;
-	ipa_in_params.priv = connection_params->priv;
-	ipa_in_params.client = connection_params->client;
+	ipa_in_params.desc_fifo_sz = pipe_connect->desc_fifo_size;
+	ipa_in_params.data_fifo_sz = pipe_connect->data_fifo_size;
+	ipa_in_params.notify = ipa_params->notify;
+	ipa_in_params.priv = ipa_params->priv;
+	ipa_in_params.client = ipa_params->client;
 
 	/* If BAM is using dedicated SPS pipe memory, get it */
 
-	if (pipe_connection->mem_type == SPS_PIPE_MEM) {
+	if (pipe_connect->mem_type == SPS_PIPE_MEM) {
 		pr_debug("%s: USB BAM using SPS pipe memory\n", __func__);
 		ret = sps_setup_bam2bam_fifo(
-			&data_mem_buf[conn_idx][pipe_dir],
-			pipe_connection->data_fifo_base_offset,
-			pipe_connection->data_fifo_size, 1);
+			&pipe_connect->data_mem_buf,
+			pipe_connect->data_fifo_base_offset,
+			pipe_connect->data_fifo_size, 1);
 		if (ret) {
-			pr_err("%s: data fifo setup failure %d\n", __func__,
-				ret);
+			pr_err("%s: data fifo setup failure %d\n",
+				__func__, ret);
 			return ret;
 		}
 
 		ret = sps_setup_bam2bam_fifo(
-			&desc_mem_buf[conn_idx][pipe_dir],
-			pipe_connection->desc_fifo_base_offset,
-			pipe_connection->desc_fifo_size, 1);
+			&pipe_connect->desc_mem_buf,
+			pipe_connect->desc_fifo_base_offset,
+			pipe_connect->desc_fifo_size, 1);
 		if (ret) {
-			pr_err("%s: desc. fifo setup failure %d\n", __func__,
-				ret);
+			pr_err("%s: desc. fifo setup failure %d\n",
+				__func__, ret);
 			return ret;
 		}
 
-	} else {
-		pr_err("%s: unsupported memory type(%d)\n",
-			__func__, pipe_connection->mem_type);
-		return -EINVAL;
+		ipa_in_params.desc = pipe_connect->desc_mem_buf;
+		ipa_in_params.data = pipe_connect->data_mem_buf;
 	}
 
-	ipa_in_params.desc = desc_mem_buf[conn_idx][pipe_dir];
-	ipa_in_params.data = data_mem_buf[conn_idx][pipe_dir];
-
-	memcpy(&ipa_in_params.ipa_ep_cfg, &connection_params->ipa_ep_cfg,
+	memcpy(&ipa_in_params.ipa_ep_cfg, &ipa_params->ipa_ep_cfg,
 		   sizeof(struct ipa_ep_cfg));
 
 	ret = ipa_connect(&ipa_in_params, &sps_out_params, &clnt_hdl);
@@ -334,38 +345,48 @@
 		goto disconnect_ipa;
 	}
 
-	ret = sps_get_config(*pipe, connection);
+	ret = sps_get_config(*pipe, sps_connection);
 	if (ret) {
 		pr_err("%s: tx get config failed %d\n", __func__, ret);
 		goto free_sps_endpoints;
 	}
 
-	if (pipe_dir == USB_TO_PEER_PERIPHERAL) {
+	if (dir == USB_TO_PEER_PERIPHERAL) {
 		/* USB src IPA dest */
-		connection->mode = SPS_MODE_SRC;
-		connection_params->cons_clnt_hdl = clnt_hdl;
-		connection->source = usb_handle;
-		connection->destination = sps_out_params.ipa_bam_hdl;
-		connection->src_pipe_index = pipe_connection->src_pipe_index;
-		connection->dest_pipe_index = sps_out_params.ipa_ep_idx;
-		*(connection_params->src_pipe) = connection->src_pipe_index;
+		sps_connection->mode = SPS_MODE_SRC;
+		ipa_params->cons_clnt_hdl = clnt_hdl;
+		sps_connection->source = usb_handle;
+		sps_connection->destination = sps_out_params.ipa_bam_hdl;
+		sps_connection->src_pipe_index = pipe_connect->src_pipe_index;
+		sps_connection->dest_pipe_index = sps_out_params.ipa_ep_idx;
+		*(ipa_params->src_pipe) = sps_connection->src_pipe_index;
+		pipe_connect->dst_pipe_index = sps_out_params.ipa_ep_idx;
+		pr_debug("%s: BAM pipe usb[%x]->ipa[%x] connection\n",
+			__func__,
+			pipe_connect->src_pipe_index,
+			pipe_connect->dst_pipe_index);
 	} else {
 		/* IPA src, USB dest */
-		connection->mode = SPS_MODE_DEST;
-		connection_params->prod_clnt_hdl = clnt_hdl;
-		connection->source = sps_out_params.ipa_bam_hdl;
-		connection->destination = usb_handle;
-		connection->src_pipe_index = sps_out_params.ipa_ep_idx;
-		connection->dest_pipe_index = pipe_connection->dst_pipe_index;
-		*(connection_params->dst_pipe) = connection->dest_pipe_index;
+		sps_connection->mode = SPS_MODE_DEST;
+		ipa_params->prod_clnt_hdl = clnt_hdl;
+		sps_connection->source = sps_out_params.ipa_bam_hdl;
+		sps_connection->destination = usb_handle;
+		sps_connection->src_pipe_index = sps_out_params.ipa_ep_idx;
+		sps_connection->dest_pipe_index = pipe_connect->dst_pipe_index;
+		*(ipa_params->dst_pipe) = sps_connection->dest_pipe_index;
+		pipe_connect->src_pipe_index = sps_out_params.ipa_ep_idx;
+		pr_debug("%s: BAM pipe ipa[%x]->usb[%x] connection\n",
+			__func__,
+			pipe_connect->src_pipe_index,
+			pipe_connect->dst_pipe_index);
 	}
 
-	connection->data = sps_out_params.data;
-	connection->desc = sps_out_params.desc;
-	connection->event_thresh = 16;
-	connection->options = SPS_O_AUTO_ENABLE;
+	sps_connection->data = sps_out_params.data;
+	sps_connection->desc = sps_out_params.desc;
+	sps_connection->event_thresh = 16;
+	sps_connection->options = SPS_O_AUTO_ENABLE;
 
-	ret = sps_connect(*pipe, connection);
+	ret = sps_connect(*pipe, sps_connection);
 	if (ret < 0) {
 		pr_err("%s: sps_connect failed %d\n", __func__, ret);
 		goto error;
@@ -382,92 +403,83 @@
 	return ret;
 }
 
-static int disconnect_pipe(u8 connection_idx, enum usb_bam_pipe_dir pipe_dir)
+static int disconnect_pipe(u8 idx)
 {
-	struct msm_usb_bam_platform_data *pdata =
-				usb_bam_pdev->dev.platform_data;
-	struct usb_bam_pipe_connect *pipe_connection =
-			&msm_usb_bam_connections_info
-			[pdata->usb_active_bam][connection_idx][pipe_dir];
-	struct sps_pipe *pipe = sps_pipes[connection_idx][pipe_dir];
-	struct sps_connect *connection =
-		&sps_connections[connection_idx][pipe_dir];
+	struct usb_bam_pipe_connect *pipe_connect =
+		&usb_bam_connections[idx];
+	struct sps_pipe *pipe = ctx.usb_bam_sps.sps_pipes[idx];
+	struct sps_connect *sps_connection =
+		&ctx.usb_bam_sps.sps_connections[idx];
 
 	sps_disconnect(pipe);
 	sps_free_endpoint(pipe);
 
-	if (pipe_connection->mem_type == SYSTEM_MEM) {
+	if (pipe_connect->mem_type == SYSTEM_MEM) {
 		pr_debug("%s: Freeing system memory used by PIPE\n", __func__);
-		dma_free_coherent(&usb_bam_pdev->dev, connection->data.size,
-			  connection->data.base, connection->data.phys_base);
-		dma_free_coherent(&usb_bam_pdev->dev, connection->desc.size,
-			  connection->desc.base, connection->desc.phys_base);
-	} else if (pipe_connection->mem_type == USB_PRIVATE_MEM) {
+		dma_free_coherent(&ctx.usb_bam_pdev->dev,
+				sps_connection->data.size,
+				sps_connection->data.base,
+				sps_connection->data.phys_base);
+		dma_free_coherent(&ctx.usb_bam_pdev->dev,
+				sps_connection->desc.size,
+				sps_connection->desc.base,
+				sps_connection->desc.phys_base);
+	} else if (pipe_connect->mem_type == USB_PRIVATE_MEM) {
 		pr_debug("Freeing USB private memory used by BAM PIPE\n");
-		writel_relaxed(0x0, qscratch_ram1_reg);
-		iounmap(connection->data.base);
-		iounmap(connection->desc.base);
-		clk_disable_unprepare(mem_clk);
-		clk_disable_unprepare(mem_iface_clk);
+		writel_relaxed(0x0, ctx.qscratch_ram1_reg);
+		iounmap(sps_connection->data.base);
+		iounmap(sps_connection->desc.base);
+		clk_disable_unprepare(ctx.mem_clk);
+		clk_disable_unprepare(ctx.mem_iface_clk);
 	}
 
-	connection->options &= ~SPS_O_AUTO_ENABLE;
+	sps_connection->options &= ~SPS_O_AUTO_ENABLE;
 	return 0;
 }
 
-int usb_bam_connect(u8 idx, u32 *src_pipe_idx, u32 *dst_pipe_idx)
+int usb_bam_connect(u8 idx, u32 *bam_pipe_idx)
 {
-	struct usb_bam_connect_info *connection = &usb_bam_connections[idx];
-	struct msm_usb_bam_platform_data *pdata =
-				usb_bam_pdev->dev.platform_data;
-	int usb_active_bam = pdata->usb_active_bam;
 	int ret;
+	enum usb_bam bam;
+	struct usb_bam_pipe_connect *pipe_connect = &usb_bam_connections[idx];
+	struct msm_usb_bam_platform_data *pdata;
 
-	if (!usb_bam_pdev) {
+	if (!ctx.usb_bam_pdev) {
 		pr_err("%s: usb_bam device not found\n", __func__);
 		return -ENODEV;
 	}
 
-	if (idx >= CONNECTIONS_NUM) {
-		pr_err("%s: Invalid connection index\n",
-			__func__);
-		return -EINVAL;
-	}
+	pdata = ctx.usb_bam_pdev->dev.platform_data;
 
-	if (connection->src_enabled && connection->dst_enabled) {
+	if (pipe_connect->enabled) {
 		pr_debug("%s: connection %d was already established\n",
 			__func__, idx);
 		return 0;
 	}
-	connection->src_pipe = src_pipe_idx;
-	connection->dst_pipe = dst_pipe_idx;
-	connection->idx = idx;
+
+	if (!bam_pipe_idx) {
+		pr_err("%s: invalid bam_pipe_idx\n", __func__);
+		return -EINVAL;
+	}
+	if (idx < 0 || idx > ctx.max_connections) {
+		pr_err("idx is wrong %d", idx);
+		return -EINVAL;
+	}
+	bam = pipe_connect->bam_type;
+	if (bam < 0)
+		return -EINVAL;
 
 	/* Check if BAM requires RESET before connect */
-	if (pdata->reset_on_connect[usb_active_bam] == true)
-		sps_device_reset(h_bam);
+	if (pdata->reset_on_connect[bam] == true)
+		sps_device_reset(ctx.h_bam[bam]);
 
-	if (src_pipe_idx) {
-		/* open USB -> Peripheral pipe */
-		ret = connect_pipe(connection->idx, USB_TO_PEER_PERIPHERAL,
-						   connection->src_pipe);
-		if (ret) {
-			pr_err("%s: src pipe connection failure\n", __func__);
-			return ret;
-		}
-		connection->src_enabled = 1;
+	ret = connect_pipe(idx, bam_pipe_idx);
+	if (ret) {
+		pr_err("%s: pipe connection[%d] failure\n", __func__, idx);
+		return ret;
 	}
 
-	if (dst_pipe_idx) {
-		/* open Peripheral -> USB pipe */
-		ret = connect_pipe(connection->idx, PEER_PERIPHERAL_TO_USB,
-						   connection->dst_pipe);
-		if (ret) {
-			pr_err("%s: dst pipe connection failure\n", __func__);
-			return ret;
-		}
-		connection->dst_enabled = 1;
-	}
+	pipe_connect->enabled = 1;
 
 	return 0;
 }
@@ -531,64 +543,65 @@
 
 int usb_bam_connect_ipa(struct usb_bam_connect_ipa_params *ipa_params)
 {
-	u8 idx = ipa_params->idx;
-	struct usb_bam_connect_info *connection = &usb_bam_connections[idx];
+	u8 idx;
+	struct usb_bam_pipe_connect *pipe_connect;
 	int ret;
 
-	if (idx >= CONNECTIONS_NUM) {
-		pr_err("%s: Invalid connection index\n",
+	if (!ipa_params) {
+		pr_err("%s: Invalid ipa params\n",
 			__func__);
 		return -EINVAL;
 	}
 
-	if ((connection->src_enabled &&
-		 ipa_params->dir == USB_TO_PEER_PERIPHERAL) ||
-		 (connection->dst_enabled &&
-		  ipa_params->dir == PEER_PERIPHERAL_TO_USB)) {
+	if (ipa_params->dir == USB_TO_PEER_PERIPHERAL)
+		idx = ipa_params->src_idx;
+	else
+		idx = ipa_params->dst_idx;
+
+	if (idx >= ctx.max_connections) {
+		pr_err("%s: Invalid connection index\n",
+			__func__);
+		return -EINVAL;
+	}
+	pipe_connect = &usb_bam_connections[idx];
+
+	if (pipe_connect->enabled) {
 		pr_debug("%s: connection %d was already established\n",
 			__func__, idx);
 		return 0;
 	}
 
-	if (ipa_params->dir == USB_TO_PEER_PERIPHERAL)
-		connection->src_pipe = ipa_params->src_pipe;
-	else
-		connection->dst_pipe = ipa_params->dst_pipe;
-
-	connection->idx = idx;
-
+	ret = connect_pipe_ipa(idx, ipa_params);
 	ipa_rm_request_resource(IPA_CLIENT_USB_PROD);
 
-	ret = connect_pipe_ipa(ipa_params);
 	if (ret) {
 		pr_err("%s: dst pipe connection failure\n", __func__);
 		return ret;
 	}
 
-	if (ipa_params->dir == USB_TO_PEER_PERIPHERAL)
-		connection->src_enabled = 1;
-	else
-		connection->dst_enabled = 1;
+	pipe_connect->enabled = 1;
 
 	return 0;
 }
+EXPORT_SYMBOL(usb_bam_connect_ipa);
 
 int usb_bam_client_ready(bool ready)
 {
 	spin_lock(&usb_bam_lock);
-	if (peer_handhskae_info.client_ready == ready) {
+	if (peer_handshake_info.client_ready == ready) {
 		pr_debug("%s: client state is already %d\n",
 			__func__, ready);
 		spin_unlock(&usb_bam_lock);
 		return 0;
 	}
 
-	peer_handhskae_info.client_ready = ready;
+	peer_handshake_info.client_ready = ready;
 
 	spin_unlock(&usb_bam_lock);
-	if (!queue_work(usb_bam_wq, &peer_handhskae_info.reset_event.event_w)) {
+	if (!queue_work(ctx.usb_bam_wq,
+			&peer_handshake_info.reset_event.event_w)) {
 		spin_lock(&usb_bam_lock);
-		peer_handhskae_info.pending_work++;
+		peer_handshake_info.pending_work++;
 		spin_unlock(&usb_bam_lock);
 	}
 
@@ -608,65 +621,65 @@
 	struct usb_bam_event_info *wake_event_info =
 		(struct usb_bam_event_info *)notify->user;
 
-	queue_work(usb_bam_wq, &wake_event_info->event_w);
+	queue_work(ctx.usb_bam_wq, &wake_event_info->event_w);
 }
 
 static void usb_bam_sm_work(struct work_struct *w)
 {
 	pr_debug("%s: current state: %d\n", __func__,
-		peer_handhskae_info.state);
+		peer_handshake_info.state);
 
 	spin_lock(&usb_bam_lock);
 
-	switch (peer_handhskae_info.state) {
+	switch (peer_handshake_info.state) {
 	case USB_BAM_SM_INIT:
-		if (peer_handhskae_info.client_ready) {
+		if (peer_handshake_info.client_ready) {
 			spin_unlock(&usb_bam_lock);
 			smsm_change_state(SMSM_APPS_STATE, 0,
 				SMSM_USB_PLUG_UNPLUG);
 			spin_lock(&usb_bam_lock);
-			peer_handhskae_info.state = USB_BAM_SM_PLUG_NOTIFIED;
+			peer_handshake_info.state = USB_BAM_SM_PLUG_NOTIFIED;
 		}
 		break;
 	case USB_BAM_SM_PLUG_NOTIFIED:
-		if (peer_handhskae_info.ack_received) {
-			peer_handhskae_info.state = USB_BAM_SM_PLUG_ACKED;
-			peer_handhskae_info.ack_received = 0;
+		if (peer_handshake_info.ack_received) {
+			peer_handshake_info.state = USB_BAM_SM_PLUG_ACKED;
+			peer_handshake_info.ack_received = 0;
 		}
 		break;
 	case USB_BAM_SM_PLUG_ACKED:
-		if (!peer_handhskae_info.client_ready) {
+		if (!peer_handshake_info.client_ready) {
 			spin_unlock(&usb_bam_lock);
 			smsm_change_state(SMSM_APPS_STATE,
 				SMSM_USB_PLUG_UNPLUG, 0);
 			spin_lock(&usb_bam_lock);
-			peer_handhskae_info.state = USB_BAM_SM_UNPLUG_NOTIFIED;
+			peer_handshake_info.state = USB_BAM_SM_UNPLUG_NOTIFIED;
 		}
 		break;
 	case USB_BAM_SM_UNPLUG_NOTIFIED:
-		if (peer_handhskae_info.ack_received) {
+		if (peer_handshake_info.ack_received) {
 			spin_unlock(&usb_bam_lock);
-			peer_handhskae_info.reset_event.
-				callback(peer_handhskae_info.reset_event.param);
+			peer_handshake_info.reset_event.
+				callback(peer_handshake_info.reset_event.param);
 			spin_lock(&usb_bam_lock);
-			peer_handhskae_info.state = USB_BAM_SM_INIT;
-			peer_handhskae_info.ack_received = 0;
+			peer_handshake_info.state = USB_BAM_SM_INIT;
+			peer_handshake_info.ack_received = 0;
 		}
 		break;
 	}
 
-	if (peer_handhskae_info.pending_work) {
-		peer_handhskae_info.pending_work--;
+	if (peer_handshake_info.pending_work) {
+		peer_handshake_info.pending_work--;
 		spin_unlock(&usb_bam_lock);
-		queue_work(usb_bam_wq,
-			&peer_handhskae_info.reset_event.event_w);
+		queue_work(ctx.usb_bam_wq,
+			&peer_handshake_info.reset_event.event_w);
 		spin_lock(&usb_bam_lock);
 	}
 	spin_unlock(&usb_bam_lock);
 }
 
-static void usb_bam_ack_toggle_cb(void *priv, uint32_t old_state,
-	uint32_t new_state)
+static void usb_bam_ack_toggle_cb(void *priv,
+	uint32_t old_state, uint32_t new_state)
 {
 	static int last_processed_state;
 	int current_state;
@@ -681,27 +694,35 @@
 	}
 
 	last_processed_state = current_state;
-	peer_handhskae_info.ack_received = true;
+	peer_handshake_info.ack_received = true;
 
 	spin_unlock(&usb_bam_lock);
-	if (!queue_work(usb_bam_wq, &peer_handhskae_info.reset_event.event_w)) {
+	if (!queue_work(ctx.usb_bam_wq,
+			&peer_handshake_info.reset_event.event_w)) {
 		spin_lock(&usb_bam_lock);
-		peer_handhskae_info.pending_work++;
+		peer_handshake_info.pending_work++;
 		spin_unlock(&usb_bam_lock);
 	}
 }
 
-int usb_bam_register_wake_cb(u8 idx,
-	int (*callback)(void *user), void* param)
+int usb_bam_register_wake_cb(u8 idx, int (*callback)(void *user),
+	void *param)
 {
-	struct sps_pipe *pipe = sps_pipes[idx][PEER_PERIPHERAL_TO_USB];
-	struct sps_connect *sps_connection =
-		&sps_connections[idx][PEER_PERIPHERAL_TO_USB];
-	struct usb_bam_connect_info *connection = &usb_bam_connections[idx];
-	struct usb_bam_event_info *wake_event_info =
-		&connection->wake_event;
+	struct sps_pipe *pipe = ctx.usb_bam_sps.sps_pipes[idx];
+	struct sps_connect *sps_connection;
+	struct usb_bam_pipe_connect *pipe_connect;
+	struct usb_bam_event_info *wake_event_info;
 	int ret;
 
+	if (idx < 0 || idx > ctx.max_connections) {
+		pr_err("%s:idx is wrong %d", __func__, idx);
+		return -EINVAL;
+	}
+	pipe = ctx.usb_bam_sps.sps_pipes[idx];
+	sps_connection = &ctx.usb_bam_sps.sps_connections[idx];
+	pipe_connect = &usb_bam_connections[idx];
+	wake_event_info = &pipe_connect->wake_event;
+
 	wake_event_info->param = param;
 	wake_event_info->callback = callback;
 	wake_event_info->event.mode = SPS_TRIGGER_CALLBACK;
@@ -717,7 +738,7 @@
 
 	sps_connection->options = callback ?
 		(SPS_O_AUTO_ENABLE | SPS_O_WAKEUP | SPS_O_WAKEUP_IS_ONESHOT) :
-			SPS_O_AUTO_ENABLE;
+		SPS_O_AUTO_ENABLE;
 	ret = sps_set_config(pipe, sps_connection);
 	if (ret) {
 		pr_err("%s: sps_set_config() failed %d\n", __func__, ret);
@@ -727,14 +748,13 @@
 	return 0;
 }
 
-int usb_bam_register_peer_reset_cb(u8 idx,
-	 int (*callback)(void *), void *param)
+int usb_bam_register_peer_reset_cb(int (*callback)(void *), void *param)
 {
 	u32 ret = 0;
 
 	if (callback) {
-		peer_handhskae_info.reset_event.param = param;
-		peer_handhskae_info.reset_event.callback = callback;
+		peer_handshake_info.reset_event.param = param;
+		peer_handshake_info.reset_event.callback = callback;
 
 		ret = smsm_state_cb_register(SMSM_MODEM_STATE,
 			SMSM_USB_PLUG_UNPLUG, usb_bam_ack_toggle_cb, NULL);
@@ -748,8 +768,8 @@
 					SMSM_USB_PLUG_UNPLUG);
 		}
 	} else {
-		peer_handhskae_info.reset_event.param = NULL;
-		peer_handhskae_info.reset_event.callback = NULL;
+		peer_handshake_info.reset_event.param = NULL;
+		peer_handshake_info.reset_event.callback = NULL;
 		smsm_state_cb_deregister(SMSM_MODEM_STATE,
 			SMSM_USB_PLUG_UNPLUG, usb_bam_ack_toggle_cb, NULL);
 	}
@@ -759,126 +779,110 @@
 
 int usb_bam_disconnect_pipe(u8 idx)
 {
-	struct usb_bam_connect_info *connection = &usb_bam_connections[idx];
+	struct usb_bam_pipe_connect *pipe_connect;
 	int ret;
 
-	if (idx >= CONNECTIONS_NUM) {
-		pr_err("%s: Invalid connection index\n",
-			__func__);
-		return -EINVAL;
-	}
+	pipe_connect = &usb_bam_connections[idx];
 
-	if (!connection->src_enabled && !connection->dst_enabled) {
+	if (!pipe_connect->enabled) {
 		pr_debug("%s: connection %d isn't enabled\n",
 			__func__, idx);
 		return 0;
 	}
 
-	if (connection->src_enabled) {
-		/* close USB -> Peripheral pipe */
-		ret = disconnect_pipe(connection->idx, USB_TO_PEER_PERIPHERAL);
-		if (ret) {
-			pr_err("%s: src pipe connection failure\n", __func__);
-			return ret;
-		}
-		connection->src_enabled = 0;
-	}
-	if (connection->dst_enabled) {
-		/* close Peripheral -> USB pipe */
-		ret = disconnect_pipe(connection->idx, PEER_PERIPHERAL_TO_USB);
-		if (ret) {
-			pr_err("%s: dst pipe connection failure\n", __func__);
-			return ret;
-		}
-		connection->dst_enabled = 0;
+	ret = disconnect_pipe(idx);
+	if (ret) {
+		pr_err("%s: src pipe connection failure\n", __func__);
+		return ret;
 	}
 
-	connection->src_pipe = 0;
-	connection->dst_pipe = 0;
+	pipe_connect->enabled = 0;
 
 	return 0;
 }
 
-int usb_bam_disconnect_ipa(u8 idx,
-		struct usb_bam_connect_ipa_params *ipa_params)
+int usb_bam_disconnect_ipa(struct usb_bam_connect_ipa_params *ipa_params)
 {
-	struct usb_bam_connect_info *connection = &usb_bam_connections[idx];
 	int ret;
+	u8 idx;
+	struct usb_bam_pipe_connect *pipe_connect;
 
-	if (!usb_bam_pdev) {
-		pr_err("%s: usb_bam device not found\n", __func__);
-		return -ENODEV;
-	}
-
-	if (idx >= CONNECTIONS_NUM) {
-		pr_err("%s: Invalid connection index\n",
-			__func__);
-		return -EINVAL;
-	}
-
-	/* Currently just calls ipa_disconnect, no sps pipes
-	   disconenction support */
-
-	/* close IPA -> USB pipe */
-	if (connection->dst_pipe) {
+	if (ipa_params->prod_clnt_hdl) {
+		/* close USB -> IPA pipe */
+		idx = ipa_params->src_idx;
 		ret = ipa_disconnect(ipa_params->prod_clnt_hdl);
 		if (ret) {
 			pr_err("%s: dst pipe disconnection failure\n",
 				__func__);
 			return ret;
 		}
+		pipe_connect = &usb_bam_connections[idx];
+		pipe_connect->enabled = 0;
 	}
-	/* close USB -> IPA pipe */
-	if (connection->src_pipe) {
+	if (ipa_params->cons_clnt_hdl) {
+		/* close IPA -> USB pipe */
+		idx = ipa_params->dst_idx;
 		ret = ipa_disconnect(ipa_params->cons_clnt_hdl);
 		if (ret) {
 			pr_err("%s: src pipe disconnection failure\n",
 				__func__);
 			return ret;
 		}
+		pipe_connect = &usb_bam_connections[idx];
+		pipe_connect->enabled = 0;
 	}
 
 	ipa_rm_release_resource(IPA_CLIENT_USB_PROD);
 	return 0;
-
 }
+EXPORT_SYMBOL(usb_bam_disconnect_ipa);
 
-int usb_bam_reset(void)
+int usb_bam_a2_reset(void)
 {
-	struct usb_bam_connect_info *connection;
+	struct usb_bam_pipe_connect *pipe_connect;
 	int i;
 	int ret = 0, ret_int;
-	bool reconnect[CONNECTIONS_NUM];
-	u32 *reconnect_src_pipe[CONNECTIONS_NUM];
-	u32 *reconnect_dst_pipe[CONNECTIONS_NUM];
+	u8 bam = -1;
+	int reconnect_pipe_idx[ctx.max_connections];
 
-	/* Disconnect all pipes */
-	for (i = 0; i < CONNECTIONS_NUM; i++) {
-		connection = &usb_bam_connections[i];
-		reconnect[i] = connection->src_enabled ||
-			connection->dst_enabled;
-		reconnect_src_pipe[i] = connection->src_pipe;
-		reconnect_dst_pipe[i] = connection->dst_pipe;
+	for (i = 0; i < ctx.max_connections; i++)
+		reconnect_pipe_idx[i] = -1;
 
-		ret_int = usb_bam_disconnect_pipe(i);
-		if (ret_int) {
-			pr_err("%s: failure to connect pipe %d\n",
-				__func__, i);
-			ret = ret_int;
-			continue;
+	/* Disconnect a2 pipes */
+	for (i = 0; i < ctx.max_connections; i++) {
+		pipe_connect = &usb_bam_connections[i];
+		if (strnstr(pipe_connect->name, "a2", USB_BAM_MAX_STR_LEN) &&
+				pipe_connect->enabled) {
+			if (pipe_connect->dir == USB_TO_PEER_PERIPHERAL)
+				reconnect_pipe_idx[i] =
+					pipe_connect->src_pipe_index;
+			else
+				reconnect_pipe_idx[i] =
+					pipe_connect->dst_pipe_index;
+
+			bam = pipe_connect->bam_type;
+			if (bam < 0) {
+				ret = -EINVAL;
+				continue;
+			}
+			ret_int = usb_bam_disconnect_pipe(i);
+			if (ret_int) {
+				pr_err("%s: failure to connect pipe %d\n",
+					__func__, i);
+				ret = ret_int;
+				continue;
+			}
 		}
 	}
-
-	/* Reset USB/HSIC BAM */
-	if (sps_device_reset(h_bam))
+	/* Reset A2 (USB/HSIC) BAM */
+	if (bam != -1 && sps_device_reset(ctx.h_bam[bam]))
 		pr_err("%s: BAM reset failed\n", __func__);
 
-	/* Reconnect all pipes */
-	for (i = 0; i < CONNECTIONS_NUM; i++) {
-		connection = &usb_bam_connections[i];
-		if (reconnect[i]) {
-			ret_int = usb_bam_connect(i, reconnect_src_pipe[i],
-				reconnect_dst_pipe[i]);
+	/* Reconnect A2 pipes */
+	for (i = 0; i < ctx.max_connections; i++) {
+		pipe_connect = &usb_bam_connections[i];
+		if (reconnect_pipe_idx[i] != -1) {
+			ret_int = usb_bam_connect(i, &reconnect_pipe_idx[i]);
 			if (ret_int) {
 				pr_err("%s: failure to reconnect pipe %d\n",
 					__func__, i);
@@ -891,134 +895,23 @@
 	return ret;
 }
 
-static int update_connections_info(struct device_node *node, int bam,
-	int conn_num, int dir, enum usb_pipe_mem_type mem_type)
-{
-	u32 rc;
-	char *key = NULL;
-	uint32_t val = 0;
-
-	struct usb_bam_pipe_connect *pipe_connection;
-
-	pipe_connection = &msm_usb_bam_connections_info[bam][conn_num][dir];
-
-	pipe_connection->mem_type = mem_type;
-
-	key = "qcom,src-bam-physical-address";
-	rc = of_property_read_u32(node, key, &val);
-	if (!rc)
-		pipe_connection->src_phy_addr = val;
-
-	key = "qcom,src-bam-pipe-index";
-	rc = of_property_read_u32(node, key, &val);
-	if (!rc)
-		pipe_connection->src_pipe_index = val;
-
-	key = "qcom,dst-bam-physical-address";
-	rc = of_property_read_u32(node, key, &val);
-	if (!rc)
-		pipe_connection->dst_phy_addr = val;
-
-	key = "qcom,dst-bam-pipe-index";
-	rc = of_property_read_u32(node, key, &val);
-	if (!rc)
-		pipe_connection->dst_pipe_index = val;
-
-	key = "qcom,data-fifo-offset";
-	rc = of_property_read_u32(node, key, &val);
-	if (!rc)
-		pipe_connection->data_fifo_base_offset = val;
-
-	key = "qcom,data-fifo-size";
-	rc = of_property_read_u32(node, key, &val);
-	if (rc)
-		goto err;
-	pipe_connection->data_fifo_size = val;
-
-	key = "qcom,descriptor-fifo-offset";
-	rc = of_property_read_u32(node, key, &val);
-	if (!rc)
-		pipe_connection->desc_fifo_base_offset = val;
-
-	key = "qcom,descriptor-fifo-size";
-	rc = of_property_read_u32(node, key, &val);
-	if (rc)
-		goto err;
-	pipe_connection->desc_fifo_size = val;
-
-	return 0;
-
-err:
-	pr_err("%s: Error in name %s key %s\n", __func__,
-		node->full_name, key);
-	return -EFAULT;
-}
-
-static int usb_bam_update_conn_array_index(struct platform_device *pdev,
-		void *buff, int bam_max, int conn_max, int pipe_dirs)
-{
-	int bam_num, conn_num;
-	struct usb_bam_pipe_connect *bam_connection_arr = buff;
-
-	msm_usb_bam_connections_info = devm_kzalloc(&pdev->dev,
-		bam_max * sizeof(struct usb_bam_pipe_connect **),
-		GFP_KERNEL);
-
-	if (!msm_usb_bam_connections_info)
-		return -ENOMEM;
-
-	for (bam_num = 0; bam_num < bam_max; bam_num++) {
-		msm_usb_bam_connections_info[bam_num] =
-			devm_kzalloc(&pdev->dev, conn_max *
-			sizeof(struct usb_bam_pipe_connect *),
-			GFP_KERNEL);
-		if (!msm_usb_bam_connections_info[bam_num])
-			return -ENOMEM;
-
-		for (conn_num = 0; conn_num < conn_max; conn_num++)
-			msm_usb_bam_connections_info[bam_num][conn_num] =
-				bam_connection_arr +
-				(bam_num * conn_max * pipe_dirs) +
-				(conn_num * pipe_dirs);
-	}
-
-	return 0;
-}
-
 static struct msm_usb_bam_platform_data *usb_bam_dt_to_pdata(
 	struct platform_device *pdev)
 {
 	struct msm_usb_bam_platform_data *pdata;
 	struct device_node *node = pdev->dev.of_node;
-	int conn_num, bam;
-	u8 dir;
-	u8 ncolumns = 2;
-	int bam_amount, rc = 0;
-	u32 pipe_entry = 0;
-	char *key = NULL;
-	enum usb_pipe_mem_type mem_type;
+	int rc = 0;
+	u8 i = 0;
 	bool reset_bam;
+	enum usb_bam bam;
 
+	ctx.max_connections = 0;
 	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata) {
 		pr_err("unable to allocate platform data\n");
 		return NULL;
 	}
 
-	rc = of_property_read_u32(node, "qcom,usb-active-bam",
-		&pdata->usb_active_bam);
-	if (rc) {
-		pr_err("Invalid usb active bam property\n");
-		return NULL;
-	}
-
-	rc = of_property_read_u32(node, "qcom,usb-total-bam-num",
-		&pdata->total_bam_num);
-	if (rc) {
-		pr_err("Invalid usb total bam num property\n");
-		return NULL;
-	}
-
 	rc = of_property_read_u32(node, "qcom,usb-bam-num-pipes",
 		&pdata->usb_bam_num_pipes);
 	if (rc) {
@@ -1032,91 +925,113 @@
 		pr_debug("%s: Invalid usb base address property\n", __func__);
 
 	pdata->ignore_core_reset_ack = of_property_read_bool(node,
-					"qcom,ignore-core-reset-ack");
+		"qcom,ignore-core-reset-ack");
 
 	pdata->disable_clk_gating = of_property_read_bool(node,
-					"qcom,disable-clk-gating");
+		"qcom,disable-clk-gating");
 
 	for_each_child_of_node(pdev->dev.of_node, node)
-		pipe_entry++;
+		ctx.max_connections++;
 
-	/*
-	 * we need to know the number of connection, so we will know
-	 * how much memory to allocate
-	 */
-	conn_num = pipe_entry / 2;
-	bam_amount = pdata->total_bam_num;
-
-	if (conn_num <= 0 || conn_num >= pdata->usb_bam_num_pipes)
+	if (!ctx.max_connections) {
+		pr_err("%s: error: max_connections is zero\n", __func__);
 		goto err;
+	}
 
-
-	/* alloc msm_usb_bam_connections_info */
-	bam_connection_arr = devm_kzalloc(&pdev->dev, bam_amount *
-		conn_num * ncolumns *
+	usb_bam_connections = devm_kzalloc(&pdev->dev, ctx.max_connections *
 		sizeof(struct usb_bam_pipe_connect), GFP_KERNEL);
 
-	if (!bam_connection_arr)
-		goto err;
-
-	rc = usb_bam_update_conn_array_index(pdev, bam_connection_arr,
-					bam_amount, conn_num, ncolumns);
-	if (rc)
-		goto err;
+	if (!usb_bam_connections) {
+		pr_err("%s: devm_kzalloc failed(%d)\n", __func__,  __LINE__);
+		return NULL;
+	}
 
 	/* retrieve device tree parameters */
 	for_each_child_of_node(pdev->dev.of_node, node) {
-		const char *str;
-
-		key = "qcom,usb-bam-type";
-		rc = of_property_read_u32(node, key, &bam);
+		rc = of_property_read_string(node, "label",
+			&usb_bam_connections[i].name);
 		if (rc)
 			goto err;
 
-		key = "qcom,usb-bam-mem-type";
-		rc = of_property_read_u32(node, key, &mem_type);
+		rc = of_property_read_u32(node, "qcom,usb-bam-mem-type",
+			&usb_bam_connections[i].mem_type);
 		if (rc)
 			goto err;
 
-		if (mem_type == USB_PRIVATE_MEM &&
-			!pdata->usb_base_address)
-			goto err;
-
-		rc = of_property_read_string(node, "label", &str);
-		if (rc) {
-			pr_err("Cannot read string\n");
+		if (usb_bam_connections[i].mem_type == USB_PRIVATE_MEM &&
+			!pdata->usb_base_address) {
+			pr_err("%s: base address is missing for private mem\n",
+				__func__);
 			goto err;
 		}
+
+		rc = of_property_read_u32(node, "qcom,bam-type",
+			&usb_bam_connections[i].bam_type);
+		if (rc) {
+			pr_err("%s: bam type is missing in device tree\n",
+				__func__);
+			goto err;
+		}
+
+		rc = of_property_read_u32(node, "qcom,peer-bam",
+			&usb_bam_connections[i].peer_bam);
+		if (rc) {
+			pr_err("%s: peer bam is missing in device tree\n",
+				__func__);
+			goto err;
+		}
+		rc = of_property_read_u32(node, "qcom,dir",
+			&usb_bam_connections[i].dir);
+		if (rc) {
+			pr_err("%s: direction is missing in device tree\n",
+				__func__);
+			goto err;
+		}
+
+		rc = of_property_read_u32(node, "qcom,pipe-num",
+			&usb_bam_connections[i].pipe_num);
+		if (rc) {
+			pr_err("%s: pipe num is missing in device tree\n",
+				__func__);
+			goto err;
+		}
+
 		reset_bam = of_property_read_bool(node,
-					"qcom,reset-bam-on-connect");
+			"qcom,reset-bam-on-connect");
 		if (reset_bam)
 			pdata->reset_on_connect[bam] = true;
 
-		if (strnstr(str, "usb-to", 30))
-			dir = USB_TO_PEER_PERIPHERAL;
-		else if (strnstr(str, "to-usb", 30))
-			dir = PEER_PERIPHERAL_TO_USB;
-		else
-			goto err;
+		of_property_read_u32(node, "qcom,src-bam-physical-address",
+			&usb_bam_connections[i].src_phy_addr);
 
-		/* Check if connection type is supported */
-		if (!strcmp(str, "usb-to-peri-qdss-dwc3") ||
-			!strcmp(str, "peri-to-usb-qdss-dwc3") ||
-			!strcmp(str, "usb-to-ipa") ||
-			!strcmp(str, "ipa-to-usb") ||
-			!strcmp(str, "usb-to-peri-qdss-hsusb") ||
-			!strcmp(str, "peri-to-usb-qdss-hsusb"))
-				conn_num = 0;
-		else
-			goto err;
+		of_property_read_u32(node, "qcom,src-bam-pipe-index",
+			&usb_bam_connections[i].src_pipe_index);
 
-		rc = update_connections_info(node, bam, conn_num,
-						dir, mem_type);
+		of_property_read_u32(node, "qcom,dst-bam-physical-address",
+			&usb_bam_connections[i].dst_phy_addr);
+
+		of_property_read_u32(node, "qcom,dst-bam-pipe-index",
+			&usb_bam_connections[i].dst_pipe_index);
+
+		of_property_read_u32(node, "qcom,data-fifo-offset",
+			&usb_bam_connections[i].data_fifo_base_offset);
+
+		rc = of_property_read_u32(node, "qcom,data-fifo-size",
+			&usb_bam_connections[i].data_fifo_size);
 		if (rc)
 			goto err;
+
+		of_property_read_u32(node, "qcom,descriptor-fifo-offset",
+			&usb_bam_connections[i].desc_fifo_base_offset);
+
+		rc = of_property_read_u32(node, "qcom,descriptor-fifo-size",
+			&usb_bam_connections[i].desc_fifo_size);
+		if (rc)
+			goto err;
+		i++;
 	}
 
-	pdata->connections = &msm_usb_bam_connections_info[0][0][0];
+	pdata->connections = usb_bam_connections;
 
 	return pdata;
 err:
@@ -1124,83 +1039,78 @@
 	return NULL;
 }
 
-static char *bam_enable_strings[3] = {
-	[SSUSB_BAM] = "ssusb",
-	[HSUSB_BAM] = "hsusb",
-	[HSIC_BAM]  = "hsic",
-};
-
-static int usb_bam_init(void)
+static int usb_bam_init(int bam_idx)
 {
-	int ret;
+	int ret, irq;
 	void *usb_virt_addr;
 	struct msm_usb_bam_platform_data *pdata =
-		usb_bam_pdev->dev.platform_data;
-	struct usb_bam_pipe_connect *pipe_connection =
-		&msm_usb_bam_connections_info[pdata->usb_active_bam][0][0];
+		ctx.usb_bam_pdev->dev.platform_data;
 	struct resource *res, *ram_resource;
-	int irq;
+	struct sps_bam_props props = ctx.usb_bam_sps.usb_props;
 
-	res = platform_get_resource_byname(usb_bam_pdev, IORESOURCE_MEM,
-				bam_enable_strings[pdata->usb_active_bam]);
+	pr_debug("%s: usb_bam_init - %s\n", __func__,
+		bam_enable_strings[bam_idx]);
+	res = platform_get_resource_byname(ctx.usb_bam_pdev, IORESOURCE_MEM,
+		bam_enable_strings[bam_idx]);
 	if (!res) {
-		dev_err(&usb_bam_pdev->dev, "Unable to get memory resource\n");
-		return -ENODEV;
+		dev_dbg(&ctx.usb_bam_pdev->dev, "bam not initialized\n");
+		return 0;
 	}
 
-	irq = platform_get_irq_byname(usb_bam_pdev,
-				bam_enable_strings[pdata->usb_active_bam]);
+	irq = platform_get_irq_byname(ctx.usb_bam_pdev,
+		bam_enable_strings[bam_idx]);
 	if (irq < 0) {
-		dev_err(&usb_bam_pdev->dev, "Unable to get IRQ resource\n");
+		dev_err(&ctx.usb_bam_pdev->dev, "Unable to get IRQ resource\n");
 		return irq;
 	}
 
-	usb_virt_addr = devm_ioremap(&usb_bam_pdev->dev, res->start,
-							 resource_size(res));
+	usb_virt_addr = devm_ioremap(&ctx.usb_bam_pdev->dev, res->start,
+		resource_size(res));
 	if (!usb_virt_addr) {
 		pr_err("%s: ioremap failed\n", __func__);
 		return -ENOMEM;
 	}
 
 	/* Check if USB3 pipe memory needs to be enabled */
-	if (pipe_connection->mem_type == USB_PRIVATE_MEM) {
+	if (bam_idx == SSUSB_BAM && bam_use_private_mem(bam_idx)) {
 		pr_debug("%s: Enabling USB private memory for: %s\n", __func__,
-				bam_enable_strings[pdata->usb_active_bam]);
+			bam_enable_strings[bam_idx]);
 
-		ram_resource = platform_get_resource_byname(usb_bam_pdev,
-					 IORESOURCE_MEM, "qscratch_ram1_reg");
+		ram_resource = platform_get_resource_byname(ctx.usb_bam_pdev,
+			IORESOURCE_MEM, "qscratch_ram1_reg");
 		if (!res) {
-			dev_err(&usb_bam_pdev->dev, "Unable to get qscratch\n");
+			dev_err(&ctx.usb_bam_pdev->dev, "Unable to get qscratch\n");
 			ret = -ENODEV;
 			goto free_bam_regs;
 		}
 
-		qscratch_ram1_reg = devm_ioremap(&usb_bam_pdev->dev,
-						ram_resource->start,
-						resource_size(ram_resource));
-		if (!qscratch_ram1_reg) {
+		ctx.qscratch_ram1_reg = devm_ioremap(&ctx.usb_bam_pdev->dev,
+			ram_resource->start,
+			resource_size(ram_resource));
+		if (!ctx.qscratch_ram1_reg) {
 			pr_err("%s: ioremap failed for qscratch\n", __func__);
 			ret = -ENOMEM;
 			goto free_bam_regs;
 		}
 	}
-	usb_props.phys_addr = res->start;
-	usb_props.virt_addr = usb_virt_addr;
-	usb_props.virt_size = resource_size(res);
-	usb_props.irq = irq;
-	usb_props.summing_threshold = USB_SUMMING_THRESHOLD;
-	usb_props.event_threshold = 512;
-	usb_props.num_pipes = pdata->usb_bam_num_pipes;
+	props.phys_addr = res->start;
+	props.virt_addr = usb_virt_addr;
+	props.virt_size = resource_size(res);
+	props.irq = irq;
+	props.summing_threshold = USB_THRESHOLD;
+	props.event_threshold = USB_THRESHOLD;
+	props.num_pipes = pdata->usb_bam_num_pipes;
 	/*
-	 * HSUSB and HSIC Cores don't support RESET ACK signal to BAMs
-	 * Hence, let BAM to ignore acknowledge from USB while resetting PIPE
-	 */
-	if (pdata->ignore_core_reset_ack && pdata->usb_active_bam != SSUSB_BAM)
-		usb_props.options = SPS_BAM_NO_EXT_P_RST;
-	if (pdata->disable_clk_gating)
-		usb_props.options |= SPS_BAM_NO_LOCAL_CLK_GATING;
+	* HSUSB and HSIC Cores don't support RESET ACK signal to BAMs
+	* Hence, let BAM to ignore acknowledge from USB while resetting PIPE
+	*/
+	if (pdata->ignore_core_reset_ack && bam_idx != SSUSB_BAM)
+		props.options = SPS_BAM_NO_EXT_P_RST;
 
-	ret = sps_register_bam_device(&usb_props, &h_bam);
+	if (pdata->disable_clk_gating)
+		props.options |= SPS_BAM_NO_LOCAL_CLK_GATING;
+
+	ret = sps_register_bam_device(&props, &(ctx.h_bam[bam_idx]));
 	if (ret < 0) {
 		pr_err("%s: register bam error %d\n", __func__, ret);
 		ret = -EFAULT;
@@ -1210,61 +1120,46 @@
 	return 0;
 
 free_qscratch_reg:
-	iounmap(qscratch_ram1_reg);
+	iounmap(ctx.qscratch_ram1_reg);
 free_bam_regs:
 	iounmap(usb_virt_addr);
 
 	return ret;
 }
 
-static ssize_t
-usb_bam_show_enable(struct device *dev, struct device_attribute *attr,
-		    char *buf)
+static int enable_usb_bams(struct platform_device *pdev)
 {
-	struct msm_usb_bam_platform_data *pdata = dev->platform_data;
-
-	if (!pdata)
-		return 0;
-	return scnprintf(buf, PAGE_SIZE, "%s\n",
-			 bam_enable_strings[pdata->usb_active_bam]);
-}
-
-static ssize_t usb_bam_store_enable(struct device *dev,
-				     struct device_attribute *attr,
-				     const char *buf, size_t count)
-{
-	struct msm_usb_bam_platform_data *pdata = dev->platform_data;
-	char str[10], *pstr;
 	int ret, i;
 
-	if (!pdata) {
-		dev_err(dev, "no usb_bam pdata found\n");
-		return -ENODEV;
-	}
-
-	strlcpy(str, buf, sizeof(str));
-	pstr = strim(str);
-
 	for (i = 0; i < ARRAY_SIZE(bam_enable_strings); i++) {
-		if (!strncmp(pstr, bam_enable_strings[i], sizeof(str)))
-			pdata->usb_active_bam = i;
+		ret = usb_bam_init(i);
+		if (ret) {
+			pr_err("failed to init usb bam %s\n",
+				bam_enable_strings[i]);
+			return ret;
+		}
 	}
 
-	dev_dbg(dev, "active_bam=%s\n",
-		bam_enable_strings[pdata->usb_active_bam]);
+	ctx.usb_bam_sps.sps_pipes = devm_kzalloc(&pdev->dev,
+		ctx.max_connections * sizeof(struct sps_pipe *),
+		GFP_KERNEL);
 
-	ret = usb_bam_init();
-	if (ret) {
-		dev_err(dev, "failed to initialize usb bam\n");
-		return ret;
+	if (!ctx.usb_bam_sps.sps_pipes) {
+		pr_err("%s: failed to allocate sps_pipes\n", __func__);
+		return -ENOMEM;
 	}
 
-	return count;
+	ctx.usb_bam_sps.sps_connections = devm_kzalloc(&pdev->dev,
+		ctx.max_connections * sizeof(struct sps_connect),
+		GFP_KERNEL);
+	if (!ctx.usb_bam_sps.sps_connections) {
+		pr_err("%s: failed to allocate sps_connections\n", __func__);
+		return -ENOMEM;
+	}
+
+	return 0;
 }
 
-static DEVICE_ATTR(enable, S_IWUSR | S_IRUSR, usb_bam_show_enable,
-		   usb_bam_store_enable);
-
 static int usb_bam_probe(struct platform_device *pdev)
 {
 	int ret, i;
@@ -1272,89 +1167,126 @@
 
 	dev_dbg(&pdev->dev, "usb_bam_probe\n");
 
-	for (i = 0; i < CONNECTIONS_NUM; i++) {
-		usb_bam_connections[i].src_enabled = 0;
-		usb_bam_connections[i].dst_enabled = 0;
-		INIT_WORK(&usb_bam_connections[i].wake_event.event_w,
-			usb_bam_work);
-	}
+	ctx.mem_clk = devm_clk_get(&pdev->dev, "mem_clk");
+	if (IS_ERR(ctx.mem_clk))
 
-	spin_lock_init(&usb_bam_lock);
-	INIT_WORK(&peer_handhskae_info.reset_event.event_w, usb_bam_sm_work);
 
-	mem_clk = devm_clk_get(&pdev->dev, "mem_clk");
-	if (IS_ERR(mem_clk))
 		dev_dbg(&pdev->dev, "failed to get mem_clock\n");
 
-	mem_iface_clk = devm_clk_get(&pdev->dev, "mem_iface_clk");
-	if (IS_ERR(mem_iface_clk))
+	ctx.mem_iface_clk = devm_clk_get(&pdev->dev, "mem_iface_clk");
+	if (IS_ERR(ctx.mem_iface_clk))
 		dev_dbg(&pdev->dev, "failed to get mem_iface_clock\n");
 
 	if (pdev->dev.of_node) {
 		dev_dbg(&pdev->dev, "device tree enabled\n");
 		pdata = usb_bam_dt_to_pdata(pdev);
 		if (!pdata)
-			return -ENOMEM;
+			return -EINVAL;
 		pdev->dev.platform_data = pdata;
 	} else if (!pdev->dev.platform_data) {
 		dev_err(&pdev->dev, "missing platform_data\n");
 		return -ENODEV;
 	} else {
 		pdata = pdev->dev.platform_data;
-		ret = usb_bam_update_conn_array_index(pdev, pdata->connections,
-				MAX_BAMS, CONNECTIONS_NUM, 2);
-		if (ret) {
-			pr_err("usb_bam_update_conn_array_index failed\n");
-			return ret;
-		}
+		usb_bam_connections = pdata->connections;
+		ctx.max_connections = pdata->max_connections;
 	}
-	usb_bam_pdev = pdev;
+	ctx.usb_bam_pdev = pdev;
 
-	ret = device_create_file(&pdev->dev, &dev_attr_enable);
-	if (ret)
-		dev_err(&pdev->dev, "failed to create device file\n");
+	for (i = 0; i < ctx.max_connections; i++) {
+		usb_bam_connections[i].enabled = 0;
+		INIT_WORK(&usb_bam_connections[i].wake_event.event_w,
+			usb_bam_work);
+	}
 
-	usb_bam_wq = alloc_workqueue("usb_bam_wq",
+	spin_lock_init(&usb_bam_lock);
+	INIT_WORK(&peer_handshake_info.reset_event.event_w, usb_bam_sm_work);
+
+	ctx.usb_bam_wq = alloc_workqueue("usb_bam_wq",
 		WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
-	if (!usb_bam_wq) {
+	if (!ctx.usb_bam_wq) {
 		pr_err("unable to create workqueue usb_bam_wq\n");
 		return -ENOMEM;
 	}
 
+	ret = enable_usb_bams(pdev);
+	if (ret) {
+		destroy_workqueue(ctx.usb_bam_wq);
+		return ret;
+	}
 	usb_bam_ipa_create_resources();
 
 	return ret;
 }
 
-void get_bam2bam_connection_info(u8 conn_idx, enum usb_bam_pipe_dir pipe_dir,
-	u32 *usb_bam_handle, u32 *usb_bam_pipe_idx, u32 *peer_pipe_idx,
+int usb_bam_get_qdss_idx(u8 num)
+{
+	return usb_bam_get_connection_idx(ctx.qdss_core_name, QDSS_P_BAM,
+		PEER_PERIPHERAL_TO_USB, num);
+}
+EXPORT_SYMBOL(usb_bam_get_qdss_idx);
+
+void usb_bam_set_qdss_core(const char *qdss_core)
+{
+	strlcpy(ctx.qdss_core_name, qdss_core, USB_BAM_MAX_STR_LEN);
+}
+
+int get_bam2bam_connection_info(u8 idx, u32 *usb_bam_handle,
+	u32 *usb_bam_pipe_idx, u32 *peer_pipe_idx,
 	struct sps_mem_buffer *desc_fifo, struct sps_mem_buffer *data_fifo)
 {
-	struct sps_connect *connection =
-		&sps_connections[conn_idx][pipe_dir];
+	struct usb_bam_pipe_connect *pipe_connect = &usb_bam_connections[idx];
+	enum usb_bam_pipe_dir dir = pipe_connect->dir;
+	struct sps_connect *sps_connection =
+		&ctx.usb_bam_sps.sps_connections[idx];
 
-
-	if (pipe_dir == USB_TO_PEER_PERIPHERAL) {
-		*usb_bam_handle = connection->source;
-		*usb_bam_pipe_idx = connection->src_pipe_index;
-		*peer_pipe_idx = connection->dest_pipe_index;
+	if (dir == USB_TO_PEER_PERIPHERAL) {
+		*usb_bam_handle = sps_connection->source;
+		*usb_bam_pipe_idx = sps_connection->src_pipe_index;
+		*peer_pipe_idx = sps_connection->dest_pipe_index;
 	} else {
-		*usb_bam_handle = connection->destination;
-		*usb_bam_pipe_idx = connection->dest_pipe_index;
-		*peer_pipe_idx = connection->src_pipe_index;
+		*usb_bam_handle = sps_connection->destination;
+		*usb_bam_pipe_idx = sps_connection->dest_pipe_index;
+		*peer_pipe_idx = sps_connection->src_pipe_index;
 	}
 	if (data_fifo)
-		memcpy(data_fifo, &data_mem_buf[conn_idx][pipe_dir],
-			sizeof(struct sps_mem_buffer));
+		memcpy(data_fifo, &pipe_connect->data_mem_buf,
+		sizeof(struct sps_mem_buffer));
 	if (desc_fifo)
-		memcpy(desc_fifo, &desc_mem_buf[conn_idx][pipe_dir],
-			sizeof(struct sps_mem_buffer));
+		memcpy(desc_fifo, &pipe_connect->desc_mem_buf,
+		sizeof(struct sps_mem_buffer));
+	return 0;
 }
 EXPORT_SYMBOL(get_bam2bam_connection_info);
 
+
+int usb_bam_get_connection_idx(const char *core_name, enum peer_bam client,
+	enum usb_bam_pipe_dir dir, u32 num)
+{
+	u8 i;
+	int bam_type;
+
+	bam_type = get_bam_type_from_core_name(core_name);
+	if (bam_type < 0)
+		return -EINVAL;
+
+	for (i = 0; i < ctx.max_connections; i++)
+		if (usb_bam_connections[i].bam_type == bam_type &&
+				usb_bam_connections[i].peer_bam == client &&
+				usb_bam_connections[i].dir == dir &&
+				usb_bam_connections[i].pipe_num == num) {
+			pr_debug("%s: index %d was found\n", __func__, i);
+			return i;
+		}
+
+	pr_err("%s: failed for %s\n", __func__, core_name);
+	return -ENODEV;
+}
+EXPORT_SYMBOL(usb_bam_get_connection_idx);
+
 static int usb_bam_remove(struct platform_device *pdev)
 {
-	destroy_workqueue(usb_bam_wq);
+	destroy_workqueue(ctx.usb_bam_wq);
 
 	return 0;
 }
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index 0fdadb9..bc6f289 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -115,8 +115,7 @@
 
 	u8				revision1;
 	u8				revision2;
-	int				charger_status;
-	bool				online;
+	int				battery_present;
 	/* platform data */
 	int				r_sense_uohm;
 	unsigned int			v_cutoff_uv;
@@ -149,6 +148,9 @@
 	int				shutdown_soc;
 	int				shutdown_iavg_ma;
 
+	struct wake_lock		low_voltage_wake_lock;
+	bool				low_voltage_wake_lock_held;
+	int				low_voltage_threshold;
 	int				low_soc_calc_threshold;
 	int				low_soc_calculate_soc_ms;
 	int				calculate_soc_ms;
@@ -204,8 +206,7 @@
 };
 
 static enum power_supply_property msm_bms_power_props[] = {
-	POWER_SUPPLY_PROP_STATUS,
-	POWER_SUPPLY_PROP_ONLINE,
+	POWER_SUPPLY_PROP_PRESENT,
 	POWER_SUPPLY_PROP_CAPACITY,
 	POWER_SUPPLY_PROP_CURRENT_NOW,
 	POWER_SUPPLY_PROP_CURRENT_MAX,
@@ -1141,7 +1142,11 @@
 		pr_err("vadc read failed with rc: %d\n", rc);
 		return rc;
 	}
-	*ibat_ua = (int)i_result.result_ua;
+	/*
+	 * reverse the current read by the iadc, since the bms uses
+	 * flipped battery current polarity.
+	 */
+	*ibat_ua = -1 * (int)i_result.result_ua;
 	*vbat_uv = (int)v_result.physical;
 
 	return 0;
@@ -1285,6 +1290,25 @@
 	return chip->prev_chg_soc;
 }
 
+static void very_low_voltage_check(struct qpnp_bms_chip *chip, int vbat_uv)
+{
+	/*
+	 * if battery is very low (v_cutoff voltage + 20mv) hold
+	 * a wakelock untill soc = 0%
+	 */
+	if (vbat_uv <= chip->low_voltage_threshold
+			&& !chip->low_voltage_wake_lock_held) {
+		pr_debug("voltage = %d low holding wakelock\n", vbat_uv);
+		wake_lock(&chip->low_voltage_wake_lock);
+		chip->low_voltage_wake_lock_held = 1;
+	} else if (vbat_uv > chip->low_voltage_threshold
+			&& chip->low_voltage_wake_lock_held) {
+		pr_debug("voltage = %d releasing wakelock\n", vbat_uv);
+		chip->low_voltage_wake_lock_held = 0;
+		wake_unlock(&chip->low_voltage_wake_lock);
+	}
+}
+
 static int adjust_soc(struct qpnp_bms_chip *chip, struct soc_params *params,
 							int soc, int batt_temp)
 {
@@ -1305,6 +1329,8 @@
 		goto out;
 	}
 
+	very_low_voltage_check(chip, vbat_uv);
+
 	delta_ocv_uv_limit = DIV_ROUND_CLOSEST(ibat_ua, 1000);
 
 	ocv_est_uv = vbat_uv + (ibat_ua * params->rbatt_mohm)/1000;
@@ -1620,7 +1646,8 @@
 				calculate_soc_delayed_work.work);
 	int soc = recalculate_soc(chip);
 
-	if (soc < chip->low_soc_calc_threshold)
+	if (soc < chip->low_soc_calc_threshold
+			|| chip->low_voltage_wake_lock_held)
 		schedule_delayed_work(&chip->calculate_soc_delayed_work,
 			round_jiffies_relative(msecs_to_jiffies
 			(chip->low_soc_calculate_soc_ms)));
@@ -1838,24 +1865,15 @@
 	return chip->fcc;
 }
 
-static bool get_prop_bms_online(struct qpnp_bms_chip *chip)
+static int get_prop_bms_present(struct qpnp_bms_chip *chip)
 {
-	return chip->online;
+	return chip->battery_present;
 }
 
-static int get_prop_bms_status(struct qpnp_bms_chip *chip)
+static void set_prop_bms_present(struct qpnp_bms_chip *chip, int present)
 {
-	return chip->charger_status;
-}
-
-static void set_prop_bms_online(struct qpnp_bms_chip *chip, bool online)
-{
-	chip->online = online;
-}
-
-static void set_prop_bms_status(struct qpnp_bms_chip *chip, int status)
-{
-	chip->charger_status = status;
+	if (chip->battery_present != present)
+		chip->battery_present = present;
 }
 
 static void qpnp_bms_external_power_changed(struct power_supply *psy)
@@ -1882,11 +1900,8 @@
 	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
 		val->intval = get_prop_bms_charge_full_design(chip);
 		break;
-	case POWER_SUPPLY_PROP_STATUS:
-		val->intval = get_prop_bms_status(chip);
-		break;
-	case POWER_SUPPLY_PROP_ONLINE:
-		val->intval = get_prop_bms_online(chip);
+	case POWER_SUPPLY_PROP_PRESENT:
+		val->intval = get_prop_bms_present(chip);
 		break;
 	default:
 		return -EINVAL;
@@ -1902,11 +1917,8 @@
 								bms_psy);
 
 	switch (psp) {
-	case POWER_SUPPLY_PROP_ONLINE:
-		set_prop_bms_online(chip, val->intval);
-		break;
-	case POWER_SUPPLY_PROP_STATUS:
-		set_prop_bms_status(chip, (bool)val->intval);
+	case POWER_SUPPLY_PROP_PRESENT:
+		set_prop_bms_present(chip, val->intval);
 		break;
 	default:
 		return -EINVAL;
@@ -2121,6 +2133,7 @@
 			"ocv-voltage-high-threshold-uv", rc);
 	SPMI_PROP_READ(ocv_low_threshold_uv,
 			"ocv-voltage-low-threshold-uv", rc);
+	SPMI_PROP_READ(low_voltage_threshold, "low-voltage-threshold", rc);
 
 	if (chip->adjust_soc_low_threshold >= 45)
 		chip->adjust_soc_low_threshold = 45;
@@ -2294,6 +2307,7 @@
 static int __devinit qpnp_bms_probe(struct spmi_device *spmi)
 {
 	struct qpnp_bms_chip *chip;
+	union power_supply_propval retval = {0,};
 	int rc, vbatt;
 
 	chip = kzalloc(sizeof *chip, GFP_KERNEL);
@@ -2373,6 +2387,8 @@
 
 	wake_lock_init(&chip->soc_wake_lock, WAKE_LOCK_SUSPEND,
 			"qpnp_soc_lock");
+	wake_lock_init(&chip->low_voltage_wake_lock, WAKE_LOCK_SUSPEND,
+			"qpnp_low_voltage_lock");
 	INIT_DELAYED_WORK(&chip->calculate_soc_delayed_work,
 			calculate_soc_work);
 
@@ -2381,6 +2397,14 @@
 	dev_set_drvdata(&spmi->dev, chip);
 	device_init_wakeup(&spmi->dev, 1);
 
+	if (!chip->batt_psy)
+		chip->batt_psy = power_supply_get_by_name("battery");
+	if (chip->batt_psy) {
+		chip->batt_psy->get_property(chip->batt_psy,
+					POWER_SUPPLY_PROP_PRESENT, &retval);
+		chip->battery_present = retval.intval;
+	}
+
 	calculate_soc_work(&(chip->calculate_soc_delayed_work.work));
 
 	/* setup & register the battery power supply */
@@ -2417,6 +2441,7 @@
 
 unregister_dc:
 	wake_lock_destroy(&chip->soc_wake_lock);
+	wake_lock_destroy(&chip->low_voltage_wake_lock);
 	power_supply_unregister(&chip->bms_psy);
 	dev_set_drvdata(&spmi->dev, NULL);
 error_resource:
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 3d9e4b7..eb0d6d4 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-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
@@ -546,6 +546,9 @@
 		power_supply_changed(&chip->batt_psy);
 	}
 
+	if (chip->bms_psy)
+		power_supply_set_present(chip->bms_psy, batt_present);
+
 	return IRQ_HANDLED;
 }
 
@@ -1638,6 +1641,7 @@
 	struct qpnp_chg_chip	*chip;
 	struct resource *resource;
 	struct spmi_resource *spmi_resource;
+	bool present;
 	int rc = 0;
 
 	chip = kzalloc(sizeof *chip, GFP_KERNEL);
@@ -1936,6 +1940,14 @@
 		if (rc)
 			goto fail_chg_enable;
 
+		/* if bms exists, notify it of the presence of the battery */
+		if (!chip->bms_psy)
+			chip->bms_psy = power_supply_get_by_name("bms");
+		if (chip->bms_psy) {
+			present = get_prop_batt_present(chip);
+			power_supply_set_present(chip->bms_psy, present);
+		}
+
 		chip->batt_psy.name = "battery";
 		chip->batt_psy.type = POWER_SUPPLY_TYPE_BATTERY;
 		chip->batt_psy.properties = msm_batt_power_props;
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index 65e4989..63acde1 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -1746,7 +1746,8 @@
 	if (msm_uport->rx.flush != FLUSH_SHUTDOWN) {
 		if (msm_uport->rx.flush == FLUSH_NONE) {
 			msm_hs_stop_rx_locked(uport);
-			msm_uport->rx_discard_flush_issued = true;
+			if (!is_blsp_uart(msm_uport))
+				msm_uport->rx_discard_flush_issued = true;
 		}
 
 		spin_unlock_irqrestore(&uport->lock, flags);
diff --git a/drivers/usb/gadget/f_mbim.c b/drivers/usb/gadget/f_mbim.c
index a32dd15..893f315 100644
--- a/drivers/usb/gadget/f_mbim.c
+++ b/drivers/usb/gadget/f_mbim.c
@@ -662,19 +662,30 @@
 static int mbim_bam_connect(struct f_mbim *dev)
 {
 	int ret;
+	u8 src_connection_idx, dst_connection_idx;
+	struct usb_gadget *gadget = dev->cdev->gadget;
 
 	pr_info("dev:%p portno:%d\n", dev, dev->port_num);
 
+	src_connection_idx = usb_bam_get_connection_idx(gadget->name, A2_P_BAM,
+		USB_TO_PEER_PERIPHERAL, dev->port_num);
+	dst_connection_idx = usb_bam_get_connection_idx(gadget->name, A2_P_BAM,
+		PEER_PERIPHERAL_TO_USB, dev->port_num);
+	if (src_connection_idx < 0 || dst_connection_idx < 0) {
+		pr_err("%s: usb_bam_get_connection_idx failed\n", __func__);
+		return ret;
+	}
+
 	ret = bam_data_connect(&dev->bam_port, dev->port_num,
-		USB_GADGET_XPORT_BAM2BAM, dev->port_num, USB_FUNC_MBIM);
+		USB_GADGET_XPORT_BAM2BAM, src_connection_idx,
+		dst_connection_idx, USB_FUNC_MBIM);
 	if (ret) {
 		pr_err("bam_data_setup failed: err:%d\n",
 				ret);
 		return ret;
-	} else {
-		pr_info("mbim bam connected\n");
 	}
 
+	pr_info("mbim bam connected\n");
 	return 0;
 }
 
diff --git a/drivers/usb/gadget/f_qc_ecm.c b/drivers/usb/gadget/f_qc_ecm.c
index 559fd04..51f0e50 100644
--- a/drivers/usb/gadget/f_qc_ecm.c
+++ b/drivers/usb/gadget/f_qc_ecm.c
@@ -390,14 +390,27 @@
 static int ecm_qc_bam_connect(struct f_ecm_qc *dev)
 {
 	int ret;
+	u8 src_connection_idx, dst_connection_idx;
+	struct usb_composite_dev *cdev = dev->port.func.config->cdev;
+	struct usb_gadget *gadget = cdev->gadget;
+	enum peer_bam peer_bam = (dev->xport == USB_GADGET_XPORT_BAM2BAM_IPA) ?
+		IPA_P_BAM : A2_P_BAM;
 
-	ecm_qc_bam_port.cdev = dev->port.func.config->cdev;
+	ecm_qc_bam_port.cdev = cdev;
 	ecm_qc_bam_port.in = dev->port.in_ep;
 	ecm_qc_bam_port.out = dev->port.out_ep;
 
 	/* currently we use the first connection */
+	src_connection_idx = usb_bam_get_connection_idx(gadget->name, peer_bam,
+		USB_TO_PEER_PERIPHERAL, 0);
+	dst_connection_idx = usb_bam_get_connection_idx(gadget->name, peer_bam,
+		PEER_PERIPHERAL_TO_USB, 0);
+	if (src_connection_idx < 0 || dst_connection_idx < 0) {
+		pr_err("%s: usb_bam_get_connection_idx failed\n", __func__);
+		return ret;
+	}
 	ret = bam_data_connect(&ecm_qc_bam_port, 0, dev->xport,
-					0, USB_FUNC_ECM);
+		src_connection_idx, dst_connection_idx, USB_FUNC_ECM);
 	if (ret) {
 		pr_err("bam_data_connect failed: err:%d\n", ret);
 		return ret;
diff --git a/drivers/usb/gadget/f_qc_rndis.c b/drivers/usb/gadget/f_qc_rndis.c
index 51d7bc1..8b01176 100644
--- a/drivers/usb/gadget/f_qc_rndis.c
+++ b/drivers/usb/gadget/f_qc_rndis.c
@@ -421,22 +421,33 @@
 static int rndis_qc_bam_connect(struct f_rndis_qc *dev)
 {
 	int ret;
+	u8 src_connection_idx, dst_connection_idx;
+	struct usb_composite_dev *cdev = dev->port.func.config->cdev;
+	struct usb_gadget *gadget = cdev->gadget;
 
-	dev->bam_port.cdev = dev->port.func.config->cdev;
+	dev->bam_port.cdev = cdev;
 	dev->bam_port.in = dev->port.in_ep;
 	dev->bam_port.out = dev->port.out_ep;
 
 	/* currently we use the first connection */
+	src_connection_idx = usb_bam_get_connection_idx(gadget->name, A2_P_BAM,
+		USB_TO_PEER_PERIPHERAL, 0);
+	dst_connection_idx = usb_bam_get_connection_idx(gadget->name, A2_P_BAM,
+		PEER_PERIPHERAL_TO_USB, 0);
+	if (src_connection_idx < 0 || dst_connection_idx < 0) {
+		pr_err("%s: usb_bam_get_connection_idx failed\n", __func__);
+		return ret;
+	}
 	ret = bam_data_connect(&dev->bam_port, 0, USB_GADGET_XPORT_BAM2BAM,
-			0, USB_FUNC_RNDIS);
+		src_connection_idx, dst_connection_idx, USB_FUNC_RNDIS);
 	if (ret) {
 		pr_err("bam_data_connect failed: err:%d\n",
 				ret);
 		return ret;
-	} else {
-		pr_info("rndis bam connected\n");
 	}
 
+	pr_info("rndis bam connected\n");
+
 	return 0;
 }
 
diff --git a/drivers/usb/gadget/f_qdss.c b/drivers/usb/gadget/f_qdss.c
index 3069bcb..6518095 100644
--- a/drivers/usb/gadget/f_qdss.c
+++ b/drivers/usb/gadget/f_qdss.c
@@ -1,7 +1,7 @@
 /*
  * f_qdss.c -- QDSS function Driver
  *
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-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
@@ -447,8 +447,8 @@
 		qdss->ch.notify(qdss->ch.priv, USB_QDSS_DISCONNECT, NULL,
 			NULL);
 		/* If the app was never started, we can skip USB BAM reset */
-		status = set_qdss_data_connection(qdss->data,
-			qdss->data->address, 0);
+		status = set_qdss_data_connection(qdss->cdev->gadget,
+			qdss->data, qdss->data->address, 0);
 		if (status)
 			pr_err("qdss_disconnect error");
 	}
@@ -490,7 +490,7 @@
 		return;
 	}
 
-	status = set_qdss_data_connection(qdss->data,
+	status = set_qdss_data_connection(qdss->cdev->gadget, qdss->data,
 		qdss->data->address, 1);
 	if (status) {
 		pr_err("set_qdss_data_connection error");
diff --git a/drivers/usb/gadget/f_rmnet.c b/drivers/usb/gadget/f_rmnet.c
index af68827..4b9dfbf 100644
--- a/drivers/usb/gadget/f_rmnet.c
+++ b/drivers/usb/gadget/f_rmnet.c
@@ -387,6 +387,8 @@
 	unsigned		port_num;
 	enum transport_type	cxport = rmnet_ports[dev->port_num].ctrl_xport;
 	enum transport_type	dxport = rmnet_ports[dev->port_num].data_xport;
+	u8			src_connection_idx, dst_connection_idx;
+	struct usb_gadget	*gadget = dev->cdev->gadget;
 
 	pr_debug("%s: ctrl xport: %s data xport: %s dev: %p portno: %d\n",
 			__func__, xport_to_str(cxport), xport_to_str(dxport),
@@ -435,12 +437,42 @@
 	}
 
 	port_num = rmnet_ports[dev->port_num].data_xport_num;
+
 	switch (dxport) {
 	case USB_GADGET_XPORT_BAM:
 	case USB_GADGET_XPORT_BAM2BAM:
-	case USB_GADGET_XPORT_BAM2BAM_IPA:
+		src_connection_idx = usb_bam_get_connection_idx(gadget->name,
+			A2_P_BAM, USB_TO_PEER_PERIPHERAL, port_num);
+		dst_connection_idx = usb_bam_get_connection_idx(gadget->name,
+			A2_P_BAM, PEER_PERIPHERAL_TO_USB, port_num);
+		if (dst_connection_idx < 0 || src_connection_idx < 0) {
+			pr_err("%s: usb_bam_get_connection_idx failed\n",
+				__func__);
+			gsmd_ctrl_disconnect(&dev->port, port_num);
+			return ret;
+		}
 		ret = gbam_connect(&dev->port, port_num,
-						   dxport, port_num);
+			dxport, src_connection_idx, dst_connection_idx);
+		if (ret) {
+			pr_err("%s: gbam_connect failed: err:%d\n",
+				__func__, ret);
+			gsmd_ctrl_disconnect(&dev->port, port_num);
+			return ret;
+		}
+		break;
+	case USB_GADGET_XPORT_BAM2BAM_IPA:
+		src_connection_idx = usb_bam_get_connection_idx(gadget->name,
+			IPA_P_BAM, USB_TO_PEER_PERIPHERAL, port_num);
+		dst_connection_idx = usb_bam_get_connection_idx(gadget->name,
+			IPA_P_BAM, PEER_PERIPHERAL_TO_USB, port_num);
+		if (dst_connection_idx < 0 || src_connection_idx < 0) {
+			pr_err("%s: usb_bam_get_connection_idx failed\n",
+				__func__);
+			gsmd_ctrl_disconnect(&dev->port, port_num);
+			return ret;
+		}
+		ret = gbam_connect(&dev->port, port_num,
+			dxport, src_connection_idx, dst_connection_idx);
 		if (ret) {
 			pr_err("%s: gbam_connect failed: err:%d\n",
 					__func__, ret);
diff --git a/drivers/usb/gadget/u_bam.c b/drivers/usb/gadget/u_bam.c
index 5a6faf2..3c3fbca 100644
--- a/drivers/usb/gadget/u_bam.c
+++ b/drivers/usb/gadget/u_bam.c
@@ -100,7 +100,8 @@
 
 	u32					src_pipe_idx;
 	u32					dst_pipe_idx;
-	u8					connection_idx;
+	u8					src_connection_idx;
+	u8					dst_connection_idx;
 	enum transport_type trans;
 	struct usb_bam_connect_ipa_params ipa_params;
 
@@ -663,7 +664,7 @@
 	int ret;
 
 	if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
-		ret = usb_bam_disconnect_ipa(d->connection_idx, &d->ipa_params);
+		ret = usb_bam_disconnect_ipa(&d->ipa_params);
 		if (ret)
 			pr_err("%s: usb_bam_disconnect_ipa failed: err:%d\n",
 				__func__, ret);
@@ -715,10 +716,15 @@
 	int ret;
 
 	if (d->trans == USB_GADGET_XPORT_BAM2BAM) {
-		ret = usb_bam_connect(d->connection_idx, &d->src_pipe_idx,
-							  &d->dst_pipe_idx);
+		ret = usb_bam_connect(d->src_connection_idx, &d->src_pipe_idx);
 		if (ret) {
-			pr_err("%s: usb_bam_connect failed: err:%d\n",
+			pr_err("%s: usb_bam_connect (src) failed: err:%d\n",
+				__func__, ret);
+			return;
+		}
+		ret = usb_bam_connect(d->dst_connection_idx, &d->dst_pipe_idx);
+		if (ret) {
+			pr_err("%s: usb_bam_connect (dst) failed: err:%d\n",
 				__func__, ret);
 			return;
 		}
@@ -787,8 +793,7 @@
 
 	if (d->trans == USB_GADGET_XPORT_BAM2BAM && port->port_num == 0) {
 		/* Register for peer reset callback */
-		usb_bam_register_peer_reset_cb(d->connection_idx,
-			gbam_peer_reset_cb, port);
+		usb_bam_register_peer_reset_cb(gbam_peer_reset_cb, port);
 
 		ret = usb_bam_client_ready(true);
 		if (ret) {
@@ -832,7 +837,7 @@
 	msm_hw_bam_disable(1);
 
 	/* Reset BAM */
-	ret = usb_bam_reset();
+	ret = usb_bam_a2_reset();
 	if (ret) {
 		pr_err("%s: BAM reset failed %d\n", __func__, ret);
 		goto reenable_eps;
@@ -867,7 +872,7 @@
 
 	/* Unregister the peer reset callback */
 	if (d->trans == USB_GADGET_XPORT_BAM2BAM && port->port_num == 0)
-		usb_bam_register_peer_reset_cb(d->connection_idx, NULL, NULL);
+		usb_bam_register_peer_reset_cb(NULL, NULL);
 
 	return 0;
 }
@@ -1216,7 +1221,8 @@
 }
 
 int gbam_connect(struct grmnet *gr, u8 port_num,
-				 enum transport_type trans, u8 connection_idx)
+		enum transport_type trans, u8 src_connection_idx,
+		u8 dst_connection_idx)
 {
 	struct gbam_port	*port;
 	struct bam_ch_info	*d;
@@ -1283,12 +1289,14 @@
 
 	if (trans == USB_GADGET_XPORT_BAM2BAM) {
 		port->gr = gr;
-		d->connection_idx = connection_idx;
+		d->src_connection_idx = src_connection_idx;
+		d->dst_connection_idx = dst_connection_idx;
 	} else if (trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
 		port->gr = gr;
 		d->ipa_params.src_pipe = &(d->src_pipe_idx);
 		d->ipa_params.dst_pipe = &(d->dst_pipe_idx);
-		d->ipa_params.idx = connection_idx;
+		d->ipa_params.src_idx = src_connection_idx;
+		d->ipa_params.dst_idx = dst_connection_idx;
 	}
 
 	d->trans = trans;
@@ -1379,7 +1387,7 @@
 
 	pr_debug("%s: suspended port %d\n", __func__, port_num);
 
-	usb_bam_register_wake_cb(d->connection_idx, gbam_wake_cb, port);
+	usb_bam_register_wake_cb(d->dst_connection_idx, gbam_wake_cb, port);
 }
 
 void gbam_resume(struct grmnet *gr, u8 port_num, enum transport_type trans)
@@ -1396,5 +1404,5 @@
 
 	pr_debug("%s: resumed port %d\n", __func__, port_num);
 
-	usb_bam_register_wake_cb(d->connection_idx, NULL, NULL);
+	usb_bam_register_wake_cb(d->dst_connection_idx, NULL, NULL);
 }
diff --git a/drivers/usb/gadget/u_bam_data.c b/drivers/usb/gadget/u_bam_data.c
index 700d07f..83f885a 100644
--- a/drivers/usb/gadget/u_bam_data.c
+++ b/drivers/usb/gadget/u_bam_data.c
@@ -47,7 +47,8 @@
 
 	u32			src_pipe_idx;
 	u32			dst_pipe_idx;
-	u8			connection_idx;
+	u8			src_connection_idx;
+	u8			dst_connection_idx;
 
 	enum function_type			func_type;
 	enum transport_type			trans;
@@ -135,7 +136,7 @@
 	msm_hw_bam_disable(1);
 
 	/* Reset BAM */
-	ret = usb_bam_reset();
+	ret = usb_bam_a2_reset();
 	if (ret) {
 		pr_err("%s: BAM reset failed %d\n", __func__, ret);
 		goto reenable_eps;
@@ -169,7 +170,7 @@
 	}
 
 	/* Unregister the peer reset callback */
-	usb_bam_register_peer_reset_cb(d->connection_idx, NULL, NULL);
+	usb_bam_register_peer_reset_cb(NULL, NULL);
 
 	return 0;
 }
@@ -184,7 +185,7 @@
 	if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
 		if (d->func_type == USB_FUNC_ECM)
 			ecm_ipa_disconnect(d->ipa_params.priv);
-		ret = usb_bam_disconnect_ipa(d->connection_idx, &d->ipa_params);
+		ret = usb_bam_disconnect_ipa(&d->ipa_params);
 		if (ret)
 			pr_err("usb_bam_disconnect_ipa failed: err:%d\n", ret);
 	}
@@ -237,13 +238,17 @@
 			}
 		}
 	} else { /* transport type is USB_GADGET_XPORT_BAM2BAM */
-		ret = usb_bam_connect(d->connection_idx, &d->src_pipe_idx,
-						  &d->dst_pipe_idx);
-		if (ret) {
-			pr_err("usb_bam_connect failed: err:%d\n", ret);
-			return;
-		}
+	ret = usb_bam_connect(d->src_connection_idx, &d->src_pipe_idx);
+	if (ret) {
+		pr_err("usb_bam_connect (src) failed: err:%d\n", ret);
+		return;
 	}
+	ret = usb_bam_connect(d->dst_connection_idx, &d->dst_pipe_idx);
+	if (ret) {
+		pr_err("usb_bam_connect (dst) failed: err:%d\n", ret);
+		return;
+	}
+}
 
 	if (!port->port_usb) {
 		pr_err("port_usb is NULL");
@@ -282,8 +287,7 @@
 
 	/* Register for peer reset callback if USB_GADGET_XPORT_BAM2BAM */
 	if (d->trans != USB_GADGET_XPORT_BAM2BAM_IPA) {
-		usb_bam_register_peer_reset_cb(d->connection_idx,
-			bam_data_peer_reset_cb, port);
+		usb_bam_register_peer_reset_cb(bam_data_peer_reset_cb, port);
 
 		ret = usb_bam_client_ready(true);
 		if (ret) {
@@ -369,7 +373,8 @@
 }
 
 int bam_data_connect(struct data_port *gr, u8 port_num,
-	enum transport_type trans, u8 connection_idx, enum function_type func)
+	enum transport_type trans, u8 src_connection_idx,
+	u8 dst_connection_idx, enum function_type func)
 {
 	struct bam_data_port	*port;
 	struct bam_data_ch_info	*d;
@@ -408,14 +413,16 @@
 
 	port->port_usb = gr;
 
-	d->connection_idx = connection_idx;
+	d->src_connection_idx = src_connection_idx;
+	d->dst_connection_idx = dst_connection_idx;
 
 	d->trans = trans;
 
 	if (trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
 		d->ipa_params.src_pipe = &(d->src_pipe_idx);
 		d->ipa_params.dst_pipe = &(d->dst_pipe_idx);
-		d->ipa_params.idx = connection_idx;
+		d->ipa_params.src_idx = src_connection_idx;
+		d->ipa_params.dst_idx = dst_connection_idx;
 	}
 
 	d->func_type = func;
@@ -499,7 +506,7 @@
 	d = &port->data_ch;
 
 	pr_debug("%s: suspended port %d\n", __func__, port_num);
-	usb_bam_register_wake_cb(d->connection_idx, bam_data_wake_cb, port);
+	usb_bam_register_wake_cb(d->dst_connection_idx, bam_data_wake_cb, port);
 }
 
 void bam_data_resume(u8 port_num)
@@ -512,6 +519,6 @@
 	d = &port->data_ch;
 
 	pr_debug("%s: resumed port %d\n", __func__, port_num);
-	usb_bam_register_wake_cb(d->connection_idx, NULL, NULL);
+	usb_bam_register_wake_cb(d->dst_connection_idx, NULL, NULL);
 }
 
diff --git a/drivers/usb/gadget/u_bam_data.h b/drivers/usb/gadget/u_bam_data.h
index 71a01b9..486191b5 100644
--- a/drivers/usb/gadget/u_bam_data.h
+++ b/drivers/usb/gadget/u_bam_data.h
@@ -30,7 +30,8 @@
 void bam_data_disconnect(struct data_port *gr, u8 port_num);
 
 int bam_data_connect(struct data_port *gr, u8 port_num,
-	enum transport_type trans, u8 connection_idx, enum function_type func);
+	enum transport_type trans, u8 src_connection_idx,
+	u8 dst_connection_idx, enum function_type func);
 
 int bam_data_setup(unsigned int no_bam2bam_port);
 
diff --git a/drivers/usb/gadget/u_qdss.c b/drivers/usb/gadget/u_qdss.c
index 028d5e6..e241e29 100644
--- a/drivers/usb/gadget/u_qdss.c
+++ b/drivers/usb/gadget/u_qdss.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012-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
@@ -15,8 +15,6 @@
 #include <linux/usb/msm_hsusb.h>
 #include <mach/usb_bam.h>
 
-#define BAM_CONNC_IDX 0 /* USB bam connection index */
-
 struct  usb_qdss_bam_connect_info {
 	u32 usb_bam_pipe_idx;
 	u32 peer_pipe_idx;
@@ -60,28 +58,33 @@
 	return 0;
 }
 
-int set_qdss_data_connection(struct usb_ep *data_ep, u8 data_addr, int enable)
+static int set_qdss_data_connection(struct usb_gadget *gadget,
+	struct usb_ep *data_ep, u8 data_addr, int enable)
 {
 	int res = 0;
+	u8 idx;
 
 	pr_debug("set_qdss_data_connection\n");
 
-	if (enable) {
-		res = usb_bam_connect(BAM_CONNC_IDX, NULL,
-			&(bam_info.usb_bam_pipe_idx));
-		if (res) {
-			pr_err("usb_bam_connection error\n");
-			return res;
-		}
+	/* There is only one qdss pipe, so the pipe number can be set to 0 */
+	idx = usb_bam_get_connection_idx(gadget->name, QDSS_P_BAM,
+		PEER_PERIPHERAL_TO_USB, 0);
+	if (idx < 0) {
+		pr_err("%s: usb_bam_get_connection_idx failed\n", __func__);
+		return idx;
+	}
 
+	if (enable) {
+		res = usb_bam_connect(idx, &(bam_info.usb_bam_pipe_idx));
 		bam_info.data_fifo =
 			kzalloc(sizeof(struct sps_mem_buffer *), GFP_KERNEL);
 		if (!bam_info.data_fifo) {
 			pr_err("qdss_data_connection: memory alloc failed\n");
 			return -ENOMEM;
 		}
-		get_bam2bam_connection_info(BAM_CONNC_IDX,
-			PEER_PERIPHERAL_TO_USB, &bam_info.usb_bam_handle,
+		usb_bam_set_qdss_core(gadget->name);
+		get_bam2bam_connection_info(idx,
+			&bam_info.usb_bam_handle,
 			&bam_info.usb_bam_pipe_idx, &bam_info.peer_pipe_idx,
 			NULL, bam_info.data_fifo);
 
@@ -89,13 +92,13 @@
 			bam_info.data_fifo->size, bam_info.usb_bam_pipe_idx);
 	} else {
 		kfree(bam_info.data_fifo);
-		res = usb_bam_disconnect_pipe(BAM_CONNC_IDX);
+		res = usb_bam_disconnect_pipe(idx);
 		if (res) {
 			pr_err("usb_bam_disconnection error\n");
 			return res;
 		}
-
 	}
+
 	return res;
 }
 
diff --git a/drivers/usb/gadget/u_rmnet.h b/drivers/usb/gadget/u_rmnet.h
index cea9369..a9cca50 100644
--- a/drivers/usb/gadget/u_rmnet.h
+++ b/drivers/usb/gadget/u_rmnet.h
@@ -48,8 +48,10 @@
 
 int gbam_setup(unsigned int no_bam_port, unsigned int no_bam2bam_port);
 int gbam_connect(struct grmnet *gr, u8 port_num,
-				 enum transport_type trans, u8 connection_idx);
-void gbam_disconnect(struct grmnet *gr, u8 port_num, enum transport_type trans);
+	enum transport_type trans, u8 src_connection_idx,
+	u8 dst_connection_idx);
+void gbam_disconnect(struct grmnet *gr, u8 port_num,
+	enum transport_type trans);
 void gbam_suspend(struct grmnet *gr, u8 port_num, enum transport_type trans);
 void gbam_resume(struct grmnet *gr, u8 port_num, enum transport_type trans);
 int gsmd_ctrl_connect(struct grmnet *gr, int port_num);
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
index 9c77445..bfcd7ec 100644
--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -28,48 +28,73 @@
 
 static unsigned char *mdss_dsi_base;
 
-static int mdss_dsi_regulator_init(struct platform_device *pdev,
-				   struct dsi_drv_cm_data *dsi_drv)
+static int mdss_dsi_regulator_init(struct platform_device *pdev)
 {
-	int ret;
+	int ret = 0;
+	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+	struct dsi_drv_cm_data *dsi_drv = NULL;
 
-	dsi_drv->vdd_vreg = devm_regulator_get(&pdev->dev, "vdd");
-	if (IS_ERR(dsi_drv->vdd_vreg)) {
-		pr_err("could not get 8941_l22, rc = %ld\n",
-				PTR_ERR(dsi_drv->vdd_vreg));
-		return -ENODEV;
-	}
-
-	ret = regulator_set_voltage(dsi_drv->vdd_vreg, 3000000, 3000000);
-	if (ret) {
-		pr_err("vdd_vreg->set_voltage failed, rc=%d\n", ret);
+	if (!pdev) {
+		pr_err("%s: invalid input\n", __func__);
 		return -EINVAL;
 	}
 
-	dsi_drv->vdd_io_vreg = devm_regulator_get(&pdev->dev, "vdd_io");
-	if (IS_ERR(dsi_drv->vdd_io_vreg)) {
-		pr_err("could not get 8941_l12, rc = %ld\n",
-				PTR_ERR(dsi_drv->vdd_io_vreg));
-		return -ENODEV;
-	}
-
-	ret = regulator_set_voltage(dsi_drv->vdd_io_vreg, 1800000, 1800000);
-	if (ret) {
-		pr_err("vdd_io_vreg->set_voltage failed, rc=%d\n", ret);
+	ctrl_pdata = platform_get_drvdata(pdev);
+	if (!ctrl_pdata) {
+		pr_err("%s: invalid driver data\n", __func__);
 		return -EINVAL;
 	}
 
-	dsi_drv->dsi_vreg = devm_regulator_get(&pdev->dev, "vreg");
-	if (IS_ERR(dsi_drv->dsi_vreg)) {
-		pr_err("could not get 8941_l2, rc = %ld\n",
-				PTR_ERR(dsi_drv->dsi_vreg));
-		return -ENODEV;
-	}
+	dsi_drv = &(ctrl_pdata->shared_pdata);
+	if (ctrl_pdata->power_data.num_vreg > 0) {
+		ret = msm_dss_config_vreg(&pdev->dev,
+				ctrl_pdata->power_data.vreg_config,
+				ctrl_pdata->power_data.num_vreg, 1);
+	} else {
+		dsi_drv->vdd_vreg = devm_regulator_get(&pdev->dev, "vdd");
+		if (IS_ERR(dsi_drv->vdd_vreg)) {
+			pr_err("%s: could not get vdda vreg, rc=%ld\n",
+				__func__, PTR_ERR(dsi_drv->vdd_vreg));
+			return PTR_ERR(dsi_drv->vdd_vreg);
+		}
 
-	ret = regulator_set_voltage(dsi_drv->dsi_vreg, 1200000, 1200000);
-	if (ret) {
-		pr_err("dsi_vreg->set_voltage failed, rc=%d\n", ret);
-		return -EINVAL;
+		ret = regulator_set_voltage(dsi_drv->vdd_vreg, 3000000,
+				3000000);
+		if (ret) {
+			pr_err("%s: set voltage failed on vdda vreg, rc=%d\n",
+				__func__, ret);
+			return ret;
+		}
+
+		dsi_drv->vdd_io_vreg = devm_regulator_get(&pdev->dev, "vddio");
+		if (IS_ERR(dsi_drv->vdd_io_vreg)) {
+			pr_err("%s: could not get vddio reg, rc=%ld\n",
+				__func__, PTR_ERR(dsi_drv->vdd_io_vreg));
+			return PTR_ERR(dsi_drv->vdd_io_vreg);
+		}
+
+		ret = regulator_set_voltage(dsi_drv->vdd_io_vreg, 1800000,
+				1800000);
+		if (ret) {
+			pr_err("%s: set voltage failed on vddio vreg, rc=%d\n",
+				__func__, ret);
+			return ret;
+		}
+
+		dsi_drv->vdda_vreg = devm_regulator_get(&pdev->dev, "vdda");
+		if (IS_ERR(dsi_drv->vdda_vreg)) {
+			pr_err("%s: could not get vdda vreg, rc=%ld\n",
+				__func__, PTR_ERR(dsi_drv->vdda_vreg));
+			return PTR_ERR(dsi_drv->vdda_vreg);
+		}
+
+		ret = regulator_set_voltage(dsi_drv->vdda_vreg, 1200000,
+				1200000);
+		if (ret) {
+			pr_err("%s: set voltage failed on vdda vreg, rc=%d\n",
+				__func__, ret);
+			return ret;
+		}
 	}
 
 	return 0;
@@ -90,51 +115,73 @@
 	pr_debug("%s: enable=%d\n", __func__, enable);
 
 	if (enable) {
-		ret = regulator_set_optimum_mode
-		  ((ctrl_pdata->shared_pdata).vdd_vreg, 100000);
-		if (ret < 0) {
-			pr_err("%s: vdd_vreg set regulator mode failed.\n",
-						       __func__);
-			return ret;
+		if (ctrl_pdata->power_data.num_vreg > 0) {
+			ret = msm_dss_enable_vreg(
+				ctrl_pdata->power_data.vreg_config,
+				ctrl_pdata->power_data.num_vreg, 1);
+			if (ret) {
+				pr_err("%s:Failed to enable regulators.rc=%d\n",
+					__func__, ret);
+				return ret;
+			}
+
+			/*
+			 * A small delay is needed here after enabling
+			 * all regulators and before issuing panel reset
+			 */
+			msleep(20);
+		} else {
+			ret = regulator_set_optimum_mode(
+				(ctrl_pdata->shared_pdata).vdd_vreg, 100000);
+			if (ret < 0) {
+				pr_err("%s: vdd_vreg set opt mode failed.\n",
+					 __func__);
+				return ret;
+			}
+
+			ret = regulator_set_optimum_mode(
+				(ctrl_pdata->shared_pdata).vdd_io_vreg, 100000);
+			if (ret < 0) {
+				pr_err("%s: vdd_io_vreg set opt mode failed.\n",
+					__func__);
+				return ret;
+			}
+
+			ret = regulator_set_optimum_mode
+			  ((ctrl_pdata->shared_pdata).vdda_vreg, 100000);
+			if (ret < 0) {
+				pr_err("%s: vdda_vreg set opt mode failed.\n",
+					__func__);
+				return ret;
+			}
+
+			ret = regulator_enable(
+				(ctrl_pdata->shared_pdata).vdd_io_vreg);
+			if (ret) {
+				pr_err("%s: Failed to enable regulator.\n",
+					__func__);
+				return ret;
+			}
+			msleep(20);
+
+			ret = regulator_enable(
+				(ctrl_pdata->shared_pdata).vdd_vreg);
+			if (ret) {
+				pr_err("%s: Failed to enable regulator.\n",
+					__func__);
+				return ret;
+			}
+			msleep(20);
+
+			ret = regulator_enable(
+				(ctrl_pdata->shared_pdata).vdda_vreg);
+			if (ret) {
+				pr_err("%s: Failed to enable regulator.\n",
+					__func__);
+				return ret;
+			}
 		}
 
-		ret = regulator_set_optimum_mode
-		  ((ctrl_pdata->shared_pdata).vdd_io_vreg, 100000);
-		if (ret < 0) {
-			pr_err("%s: vdd_io_vreg set regulator mode failed.\n",
-						       __func__);
-			return ret;
-		}
-
-		ret = regulator_set_optimum_mode
-		  ((ctrl_pdata->shared_pdata).dsi_vreg, 100000);
-		if (ret < 0) {
-			pr_err("%s: dsi_vreg set regulator mode failed.\n",
-						       __func__);
-			return ret;
-		}
-
-		ret = regulator_enable((ctrl_pdata->shared_pdata).vdd_io_vreg);
-		if (ret) {
-			pr_err("%s: Failed to enable regulator.\n", __func__);
-			return ret;
-		}
-		msleep(20);
-		wmb();
-
-		ret = regulator_enable((ctrl_pdata->shared_pdata).vdd_vreg);
-		if (ret) {
-			pr_err("%s: Failed to enable regulator.\n", __func__);
-			return ret;
-		}
-		msleep(20);
-		wmb();
-
-		ret = regulator_enable((ctrl_pdata->shared_pdata).dsi_vreg);
-		if (ret) {
-			pr_err("%s: Failed to enable regulator.\n", __func__);
-			return ret;
-		}
 		if (pdata->panel_info.panel_power_on == 0)
 			mdss_dsi_panel_reset(pdata, 1);
 
@@ -142,45 +189,62 @@
 
 		mdss_dsi_panel_reset(pdata, 0);
 
-		ret = regulator_disable((ctrl_pdata->shared_pdata).vdd_vreg);
-		if (ret) {
-			pr_err("%s: Failed to disable regulator.\n", __func__);
-			return ret;
-		}
+		if (ctrl_pdata->power_data.num_vreg > 0) {
+			ret = msm_dss_enable_vreg(
+				ctrl_pdata->power_data.vreg_config,
+				ctrl_pdata->power_data.num_vreg, 0);
+			if (ret) {
+				pr_err("%s: Failed to disable regs.rc=%d\n",
+					__func__, ret);
+				return ret;
+			}
+		} else {
+			ret = regulator_disable(
+				(ctrl_pdata->shared_pdata).vdd_vreg);
+			if (ret) {
+				pr_err("%s: Failed to disable regulator.\n",
+					__func__);
+				return ret;
+			}
 
-		ret = regulator_disable((ctrl_pdata->shared_pdata).dsi_vreg);
-		if (ret) {
-			pr_err("%s: Failed to disable regulator.\n", __func__);
-			return ret;
-		}
+			ret = regulator_disable(
+				(ctrl_pdata->shared_pdata).vdda_vreg);
+			if (ret) {
+				pr_err("%s: Failed to disable regulator.\n",
+					__func__);
+				return ret;
+			}
 
-		ret = regulator_disable((ctrl_pdata->shared_pdata).vdd_io_vreg);
-		if (ret) {
-			pr_err("%s: Failed to disable regulator.\n", __func__);
-			return ret;
-		}
+			ret = regulator_disable(
+				(ctrl_pdata->shared_pdata).vdd_io_vreg);
+			if (ret) {
+				pr_err("%s: Failed to disable regulator.\n",
+					__func__);
+				return ret;
+			}
 
-		ret = regulator_set_optimum_mode
-		  ((ctrl_pdata->shared_pdata).vdd_vreg, 100);
-		if (ret < 0) {
-			pr_err("%s: vdd_vreg set regulator mode failed.\n",
-						       __func__);
-			return ret;
-		}
+			ret = regulator_set_optimum_mode(
+				(ctrl_pdata->shared_pdata).vdd_vreg, 100);
+			if (ret < 0) {
+				pr_err("%s: vdd_vreg set opt mode failed.\n",
+					 __func__);
+				return ret;
+			}
 
-		ret = regulator_set_optimum_mode
-		  ((ctrl_pdata->shared_pdata).vdd_io_vreg, 100);
-		if (ret < 0) {
-			pr_err("%s: vdd_io_vreg set regulator mode failed.\n",
-						       __func__);
-			return ret;
-		}
-		ret = regulator_set_optimum_mode
-		  ((ctrl_pdata->shared_pdata).dsi_vreg, 100);
-		if (ret < 0) {
-			pr_err("%s: dsi_vreg set regulator mode failed.\n",
-						       __func__);
-			return ret;
+			ret = regulator_set_optimum_mode(
+				(ctrl_pdata->shared_pdata).vdd_io_vreg, 100);
+			if (ret < 0) {
+				pr_err("%s: vdd_io_vreg set opt mode failed.\n",
+					__func__);
+				return ret;
+			}
+			ret = regulator_set_optimum_mode(
+				(ctrl_pdata->shared_pdata).vdda_vreg, 100);
+			if (ret < 0) {
+				pr_err("%s: vdda_vreg set opt mode failed.\n",
+					__func__);
+				return ret;
+			}
 		}
 	}
 	return 0;
@@ -212,6 +276,154 @@
 	return ret;
 }
 
+static void mdss_dsi_put_dt_vreg_data(struct device *dev,
+	struct dss_module_power *module_power)
+{
+	if (!module_power) {
+		pr_err("%s: invalid input\n", __func__);
+		return;
+	}
+
+	if (module_power->vreg_config) {
+		devm_kfree(dev, module_power->vreg_config);
+		module_power->vreg_config = NULL;
+	}
+	module_power->num_vreg = 0;
+}
+
+static int mdss_dsi_get_dt_vreg_data(struct device *dev,
+	struct dss_module_power *mp)
+{
+	int i, rc = 0;
+	int dt_vreg_total = 0;
+	u32 *val_array = NULL;
+	struct device_node *of_node = NULL;
+
+	if (!dev || !mp) {
+		pr_err("%s: invalid input\n", __func__);
+		rc = -EINVAL;
+		goto error;
+	}
+
+	of_node = dev->of_node;
+
+	mp->num_vreg = 0;
+	dt_vreg_total = of_property_count_strings(of_node, "qcom,supply-names");
+	if (dt_vreg_total < 0) {
+		pr_debug("%s: vreg not found. rc=%d\n", __func__,
+			dt_vreg_total);
+		rc = 0;
+		goto error;
+	} else {
+		pr_debug("%s: vreg found. count=%d\n", __func__, dt_vreg_total);
+	}
+
+	if (dt_vreg_total > 0) {
+		mp->num_vreg = dt_vreg_total;
+		mp->vreg_config = devm_kzalloc(dev, sizeof(struct dss_vreg) *
+			dt_vreg_total, GFP_KERNEL);
+		if (!mp->vreg_config) {
+			pr_err("%s: can't alloc vreg mem\n", __func__);
+			goto error;
+		}
+	} else {
+		pr_debug("%s: no vreg\n", __func__);
+		return 0;
+	}
+
+	val_array = devm_kzalloc(dev, sizeof(u32) * dt_vreg_total, GFP_KERNEL);
+	if (!val_array) {
+		pr_err("%s: can't allocate vreg scratch mem\n", __func__);
+		rc = -ENOMEM;
+		goto error;
+	}
+
+	for (i = 0; i < dt_vreg_total; i++) {
+		const char *st = NULL;
+		/* vreg-name */
+		rc = of_property_read_string_index(of_node, "qcom,supply-names",
+			i, &st);
+		if (rc) {
+			pr_err("%s: error reading name. i=%d, rc=%d\n",
+				__func__, i, rc);
+			goto error;
+		}
+		snprintf(mp->vreg_config[i].vreg_name,
+			ARRAY_SIZE((mp->vreg_config[i].vreg_name)), "%s", st);
+
+		/* vreg-type */
+		rc = of_property_read_string_index(of_node, "qcom,supply-type",
+			i, &st);
+		if (rc) {
+			pr_err("%s: error reading vreg type. rc=%d\n",
+				__func__, rc);
+			goto error;
+		}
+		if (!strncmp(st, "regulator", 9))
+			mp->vreg_config[i].type = 0;
+		else if (!strncmp(st, "switch", 6))
+			mp->vreg_config[i].type = 1;
+
+		/* vreg-min-voltage */
+		memset(val_array, 0, sizeof(u32) * dt_vreg_total);
+		rc = of_property_read_u32_array(of_node,
+			"qcom,supply-min-voltage-level", val_array,
+			dt_vreg_total);
+		if (rc) {
+			pr_err("%s: error reading min volt. rc=%d\n",
+				__func__, rc);
+			goto error;
+		}
+		mp->vreg_config[i].min_voltage = val_array[i];
+
+		/* vreg-max-voltage */
+		memset(val_array, 0, sizeof(u32) * dt_vreg_total);
+		rc = of_property_read_u32_array(of_node,
+			"qcom,supply-max-voltage-level", val_array,
+			dt_vreg_total);
+		if (rc) {
+			pr_err("%s: error reading max volt. rc=%d\n",
+				__func__, rc);
+			goto error;
+		}
+		mp->vreg_config[i].max_voltage = val_array[i];
+
+		/* vreg-peak-current*/
+		memset(val_array, 0, sizeof(u32) * dt_vreg_total);
+		rc = of_property_read_u32_array(of_node,
+			"qcom,supply-peak-current", val_array,
+			dt_vreg_total);
+		if (rc) {
+			pr_err("%s: error reading peak current. rc=%d\n",
+				__func__, rc);
+			goto error;
+		}
+		mp->vreg_config[i].optimum_voltage = val_array[i];
+
+		pr_debug("%s: %s type=%d, min=%d, max=%d, op=%d\n",
+			__func__, mp->vreg_config[i].vreg_name,
+			mp->vreg_config[i].type,
+			mp->vreg_config[i].min_voltage,
+			mp->vreg_config[i].max_voltage,
+			mp->vreg_config[i].optimum_voltage);
+	}
+
+	devm_kfree(dev, val_array);
+
+	return rc;
+
+error:
+	if (mp->vreg_config) {
+		devm_kfree(dev, mp->vreg_config);
+		mp->vreg_config = NULL;
+	}
+	mp->num_vreg = 0;
+
+	if (val_array)
+		devm_kfree(dev, val_array);
+	return rc;
+}
+
 static int mdss_dsi_off(struct mdss_panel_data *pdata)
 {
 	int ret = 0;
@@ -460,6 +672,7 @@
 {
 	int rc = 0;
 	u32 index;
+	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 
 	pr_debug("%s\n", __func__);
 
@@ -467,6 +680,19 @@
 		struct resource *mdss_dsi_mres;
 		const char *ctrl_name;
 
+		ctrl_pdata = platform_get_drvdata(pdev);
+		if (!ctrl_pdata) {
+			ctrl_pdata = devm_kzalloc(&pdev->dev,
+				sizeof(struct mdss_dsi_ctrl_pdata), GFP_KERNEL);
+			if (!ctrl_pdata) {
+				pr_err("%s: FAILED: cannot alloc dsi ctrl\n",
+					__func__);
+				rc = -ENOMEM;
+				goto error_no_mem;
+			}
+			platform_set_drvdata(pdev, ctrl_pdata);
+		}
+
 		ctrl_name = of_get_property(pdev->dev.of_node, "label", NULL);
 		if (!ctrl_name)
 			pr_info("%s:%d, DSI Ctrl name not specified\n",
@@ -481,7 +707,7 @@
 			dev_err(&pdev->dev,
 				"%s: Cell-index not specified, rc=%d\n",
 							__func__, rc);
-			return rc;
+			goto error_no_mem;
 		}
 
 		if (index == 0)
@@ -493,7 +719,8 @@
 		if (!mdss_dsi_mres) {
 			pr_err("%s:%d unable to get the MDSS resources",
 				       __func__, __LINE__);
-			return -ENOMEM;
+			rc = -ENOMEM;
+			goto error_no_mem;
 		}
 		if (mdss_dsi_mres) {
 			mdss_dsi_base = ioremap(mdss_dsi_mres->start,
@@ -501,7 +728,8 @@
 			if (!mdss_dsi_base) {
 				pr_err("%s:%d unable to remap dsi resources",
 					       __func__, __LINE__);
-				return -ENOMEM;
+				rc = -ENOMEM;
+				goto error_no_mem;
 			}
 		}
 
@@ -511,20 +739,48 @@
 			dev_err(&pdev->dev,
 				"%s: failed to add child nodes, rc=%d\n",
 							__func__, rc);
-			iounmap(mdss_dsi_base);
-			return rc;
+			goto error_ioremap;
+		}
+
+		/* Parse the regulator information */
+		rc = mdss_dsi_get_dt_vreg_data(&pdev->dev,
+			&ctrl_pdata->power_data);
+		if (rc) {
+			pr_err("%s: failed to get vreg data from dt. rc=%d\n",
+				__func__, rc);
+			goto error_vreg;
 		}
 
 		pr_debug("%s: Dsi Ctrl->%d initialized\n", __func__, index);
 	}
 
 	return 0;
+
+error_ioremap:
+	iounmap(mdss_dsi_base);
+error_no_mem:
+	devm_kfree(&pdev->dev, ctrl_pdata);
+error_vreg:
+	mdss_dsi_put_dt_vreg_data(&pdev->dev, &ctrl_pdata->power_data);
+
+	return rc;
 }
 
 static int __devexit mdss_dsi_ctrl_remove(struct platform_device *pdev)
 {
 	struct msm_fb_data_type *mfd;
+	struct mdss_dsi_ctrl_pdata *ctrl_pdata = platform_get_drvdata(pdev);
 
+	if (!ctrl_pdata) {
+		pr_err("%s: no driver data\n", __func__);
+		return -ENODEV;
+	}
+
+	if (msm_dss_config_vreg(&pdev->dev,
+			ctrl_pdata->power_data.vreg_config,
+			ctrl_pdata->power_data.num_vreg, 1) < 0)
+		pr_err("%s: failed to de-init vregs\n", __func__);
+	mdss_dsi_put_dt_vreg_data(&pdev->dev, &ctrl_pdata->power_data);
 	mfd = platform_get_drvdata(pdev);
 	iounmap(mdss_dsi_base);
 	return 0;
@@ -592,7 +848,7 @@
 	int rc;
 	u8 lanes = 0, bpp;
 	u32 h_period, v_period, dsi_pclk_rate;
-	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+	struct mdss_dsi_ctrl_pdata *ctrl_pdata;
 	struct device_node *dsi_ctrl_np = NULL;
 	struct platform_device *ctrl_pdev = NULL;
 	unsigned char *ctrl_addr;
@@ -663,27 +919,25 @@
 		dsi_pclk_rate = 35000000;
 	mipi->dsi_pclk_rate = dsi_pclk_rate;
 
-	ctrl_pdata = devm_kzalloc(&pdev->dev,
-		sizeof(struct mdss_dsi_ctrl_pdata), GFP_KERNEL);
-	if (!ctrl_pdata)
-		return -ENOMEM;
-
 	dsi_ctrl_np = of_parse_phandle(pdev->dev.of_node,
 				       "qcom,dsi-ctrl-phandle", 0);
 	if (!dsi_ctrl_np) {
 		pr_err("%s: Dsi controller node not initialized\n", __func__);
-		devm_kfree(&pdev->dev, ctrl_pdata);
 		return -EPROBE_DEFER;
 	}
 
 	ctrl_pdev = of_find_device_by_node(dsi_ctrl_np);
+	ctrl_pdata = platform_get_drvdata(ctrl_pdev);
+	if (!ctrl_pdata) {
+		pr_err("%s: no dsi ctrl driver data\n", __func__);
+		return -EINVAL;
+	}
 
-	rc = mdss_dsi_regulator_init(ctrl_pdev, &(ctrl_pdata->shared_pdata));
+	rc = mdss_dsi_regulator_init(ctrl_pdev);
 	if (rc) {
 		dev_err(&pdev->dev,
 			"%s: failed to init regulator, rc=%d\n",
 						__func__, rc);
-		devm_kfree(&pdev->dev, ctrl_pdata);
 		return rc;
 	}
 
@@ -726,7 +980,6 @@
 
 	if (mdss_dsi_clk_init(ctrl_pdev, ctrl_pdata)) {
 		pr_err("%s: unable to initialize Dsi ctrl clks\n", __func__);
-		devm_kfree(&pdev->dev, ctrl_pdata);
 		return -EPERM;
 	}
 
@@ -734,7 +987,6 @@
 					     panel_data->panel_info.pdest,
 					     &ctrl_addr)) {
 		pr_err("%s: unable to get Dsi controller res\n", __func__);
-		devm_kfree(&pdev->dev, ctrl_pdata);
 		return -EPERM;
 	}
 
@@ -780,7 +1032,6 @@
 	rc = mdss_register_panel(ctrl_pdev, &(ctrl_pdata->panel_data));
 	if (rc) {
 		dev_err(&pdev->dev, "unable to register MIPI DSI panel\n");
-		devm_kfree(&pdev->dev, ctrl_pdata);
 		if (ctrl_pdata->rst_gpio)
 			gpio_free(ctrl_pdata->rst_gpio);
 		if (gpio_is_valid(ctrl_pdata->disp_en_gpio))
diff --git a/drivers/video/msm/mdss/mdss_dsi.h b/drivers/video/msm/mdss/mdss_dsi.h
index 4b920a6..4a06be5 100644
--- a/drivers/video/msm/mdss/mdss_dsi.h
+++ b/drivers/video/msm/mdss/mdss_dsi.h
@@ -18,6 +18,7 @@
 #include <mach/scm-io.h>
 
 #include "mdss_panel.h"
+#include "mdss_io_util.h"
 
 #define MMSS_SERDES_BASE_PHY 0x04f01000 /* mmss (De)Serializer CFG */
 
@@ -267,7 +268,7 @@
 struct dsi_drv_cm_data {
 	struct regulator *vdd_vreg;
 	struct regulator *vdd_io_vreg;
-	struct regulator *dsi_vreg;
+	struct regulator *vdda_vreg;
 	int broadcast_enable;
 };
 
@@ -288,6 +289,7 @@
 	struct dsi_drv_cm_data shared_pdata;
 	u32 pclk_rate;
 	u32 byte_clk_rate;
+	struct dss_module_power power_data;
 };
 
 int dsi_panel_device_register(struct platform_device *pdev,
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 1e0de89..3d632c7 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -1660,6 +1660,22 @@
 	return ret;
 }
 
+static int mdss_fb_get_hw_caps(struct msm_fb_data_type *mfd,
+		struct mdss_hw_caps *caps)
+{
+	struct mdss_data_type *mdata = mfd->mdata;
+
+	if (!mdata)
+		return -ENODEV;
+
+	caps->mdp_rev = mdata->mdp_rev;
+	caps->vig_pipes = mdata->nvig_pipes;
+	caps->rgb_pipes = mdata->nrgb_pipes;
+	caps->dma_pipes = mdata->ndma_pipes;
+
+	return 0;
+}
+
 static int mdss_fb_get_metadata(struct msm_fb_data_type *mfd,
 				struct msmfb_metadata *metadata)
 {
@@ -1669,6 +1685,9 @@
 		metadata->data.panel_frame_rate =
 			mdss_get_panel_framerate(mfd);
 		break;
+	case metadata_op_get_caps:
+		ret = mdss_fb_get_hw_caps(mfd, &metadata->data.caps);
+		break;
 	default:
 		pr_warn("Unsupported request to MDP META IOCTL.\n");
 		ret = -EINVAL;
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index cdb7048..e8a3795 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -449,6 +449,18 @@
 		hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID]) ? 0 : 1;
 } /* hdmi_tx_is_dvi_mode */
 
+static inline void hdmi_tx_send_cable_notification(
+	struct hdmi_tx_ctrl *hdmi_ctrl, int val)
+{
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return;
+	}
+
+	if (!hdmi_ctrl->pdata.primary && (hdmi_ctrl->sdev.state != val))
+		switch_set_state(&hdmi_ctrl->sdev, val);
+} /* hdmi_tx_send_cable_notification */
+
 static inline void hdmi_tx_set_audio_switch_node(struct hdmi_tx_ctrl *hdmi_ctrl,
 	int val, bool force)
 {
@@ -695,11 +707,11 @@
 
 	if (hdmi_ctrl->hpd_state) {
 		hdmi_tx_read_sink_info(hdmi_ctrl);
-		switch_set_state(&hdmi_ctrl->sdev, 1);
+		hdmi_tx_send_cable_notification(hdmi_ctrl, 1);
 		DEV_INFO("%s: sense cable CONNECTED: state switch to %d\n",
 			__func__, hdmi_ctrl->sdev.state);
 	} else {
-		switch_set_state(&hdmi_ctrl->sdev, 0);
+		hdmi_tx_send_cable_notification(hdmi_ctrl, 0);
 		DEV_INFO("%s: sense cable DISCONNECTED: state switch to %d\n",
 			__func__, hdmi_ctrl->sdev.state);
 	}
@@ -2097,6 +2109,7 @@
 
 static int hdmi_tx_power_on(struct mdss_panel_data *panel_data)
 {
+	u32 timeout;
 	int rc = 0;
 	struct dss_io_data *io = NULL;
 	struct hdmi_tx_ctrl *hdmi_ctrl =
@@ -2121,6 +2134,16 @@
 	/* If a power down is already underway, wait for it to finish */
 	flush_work_sync(&hdmi_ctrl->power_off_work);
 
+	if (hdmi_ctrl->pdata.primary) {
+		timeout = wait_for_completion_interruptible_timeout(
+			&hdmi_ctrl->hpd_done, HZ);
+		if (!timeout) {
+			DEV_ERR("%s: cable connection hasn't happened yet\n",
+				__func__);
+			return -ETIMEDOUT;
+		}
+	}
+
 	rc = hdmi_tx_set_video_fmt(hdmi_ctrl, &panel_data->panel_info);
 	if (rc) {
 		DEV_ERR("%s: cannot set video_fmt.rc=%d\n", __func__, rc);
@@ -2265,7 +2288,7 @@
 		} else {
 			hdmi_ctrl->hpd_off_pending = true;
 
-			switch_set_state(&hdmi_ctrl->sdev, 0);
+			hdmi_tx_send_cable_notification(hdmi_ctrl, 0);
 			DEV_DBG("%s: Hdmi state switch to %d\n", __func__,
 				hdmi_ctrl->sdev.state);
 		}
@@ -2441,6 +2464,20 @@
 			hdmi_tx_sysfs_remove(hdmi_ctrl);
 			return rc;
 		}
+
+		if (hdmi_ctrl->pdata.primary) {
+			INIT_COMPLETION(hdmi_ctrl->hpd_done);
+			rc = hdmi_tx_sysfs_enable_hpd(hdmi_ctrl, true);
+			if (rc) {
+				DEV_ERR("%s: hpd_enable failed. rc=%d\n",
+					__func__, rc);
+				hdmi_tx_sysfs_remove(hdmi_ctrl);
+				return rc;
+			} else {
+				hdmi_ctrl->hpd_feature_on = true;
+			}
+		}
+
 		break;
 
 	case MDSS_EVENT_CHECK_PARAMS:
@@ -2487,7 +2524,7 @@
 			if (!timeout & !hdmi_ctrl->hpd_state) {
 				DEV_INFO("%s: cable removed during suspend\n",
 					__func__);
-				switch_set_state(&hdmi_ctrl->sdev, 0);
+				hdmi_tx_send_cable_notification(hdmi_ctrl, 0);
 				rc = -EPERM;
 			} else {
 				DEV_DBG("%s: cable present after resume\n",
@@ -3116,6 +3153,13 @@
 		}
 	}
 
+	if (of_find_property(pdev->dev.of_node, "qcom,primary_panel", NULL)) {
+		u32 tmp;
+		of_property_read_u32(pdev->dev.of_node, "qcom,primary_panel",
+			&tmp);
+		pdata->primary = tmp ? true : false;
+	}
+
 	return rc;
 
 error:
@@ -3175,7 +3219,7 @@
 	if (rc) {
 		DEV_ERR("%s: Failed to add child devices. rc=%d\n",
 			__func__, rc);
-		goto failed_init_features;
+		goto failed_reg_panel;
 	} else {
 		DEV_DBG("%s: Add child devices.\n", __func__);
 	}
@@ -3187,8 +3231,6 @@
 
 	return rc;
 
-failed_init_features:
-	hdmi_tx_sysfs_remove(hdmi_ctrl);
 failed_reg_panel:
 	hdmi_tx_dev_deinit(hdmi_ctrl);
 failed_dev_init:
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.h b/drivers/video/msm/mdss/mdss_hdmi_tx.h
index 06ae427..8d9a477 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.h
@@ -30,8 +30,9 @@
 	HDMI_TX_MAX_PM
 };
 
+/* Data filled from device tree */
 struct hdmi_tx_platform_data {
-	/* Data filled from device tree nodes */
+	bool primary;
 	struct dss_io_data io[HDMI_TX_MAX_IO];
 	struct dss_module_power power_data[HDMI_TX_MAX_PM];
 };
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
index 97428cd..c6b6e3f 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
@@ -265,12 +265,12 @@
 	if (ctx->rot90) {
 		ctx->opmode |= BIT(5); /* ROT 90 */
 		swap(ctx->width, ctx->height);
+		ctx->format = mdss_mdp_get_rotator_dst_format(rot->format);
+	} else {
+		ctx->format = rot->format;
 	}
 
-	if (mdss_mdp_writeback_format_setup(ctx))
-		return -EINVAL;
-
-	return 0;
+	return mdss_mdp_writeback_format_setup(ctx);
 }
 
 static int mdss_mdp_writeback_stop(struct mdss_mdp_ctl *ctl)
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index 005a420..98a8202 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -236,7 +236,7 @@
 	struct mdss_mdp_format_params *fmt;
 	struct mdss_mdp_pipe *pipe;
 	struct mdss_mdp_mixer *mixer = NULL;
-	u32 pipe_type, mixer_mux, len;
+	u32 pipe_type, mixer_mux, len, src_format;
 	int ret;
 
 	if (mfd == NULL || mfd->ctl == NULL)
@@ -255,9 +255,13 @@
 		return -ENOTSUPP;
 	}
 
-	fmt = mdss_mdp_get_format_params(req->src.format);
+	src_format = req->src.format;
+	if (req->flags & MDP_SOURCE_ROTATED_90)
+		src_format = mdss_mdp_get_rotator_dst_format(src_format);
+
+	fmt = mdss_mdp_get_format_params(src_format);
 	if (!fmt) {
-		pr_err("invalid pipe format %d\n", req->src.format);
+		pr_err("invalid pipe format %d\n", src_format);
 		return -EINVAL;
 	}
 
@@ -1148,7 +1152,7 @@
 	ret = wait_for_completion_interruptible_timeout(&mfd->vsync_comp,
 			timeout);
 	if (ret <= 0) {
-		pr_warn("Sending current time as vsync timestamp for fb%d\n",
+		pr_debug("Sending current time as vsync timestamp for fb%d\n",
 				mfd->index);
 		mfd->vsync_time = ktime_get();
 	}
diff --git a/drivers/video/msm/mdss/mdss_mdp_rotator.h b/drivers/video/msm/mdss/mdss_mdp_rotator.h
index 70ef6bf..c46f271 100644
--- a/drivers/video/msm/mdss/mdss_mdp_rotator.h
+++ b/drivers/video/msm/mdss/mdss_mdp_rotator.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-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
@@ -42,6 +42,18 @@
 	struct list_head head;
 };
 
+static inline u32 mdss_mdp_get_rotator_dst_format(u32 in_format)
+{
+	switch (in_format) {
+	case MDP_Y_CBCR_H2V2_VENUS:
+		return MDP_Y_CBCR_H2V2;
+	case MDP_Y_CR_CB_GH2V2:
+		return MDP_Y_CR_CB_H2V2;
+	default:
+		return in_format;
+	}
+}
+
 struct mdss_mdp_rotator_session *mdss_mdp_rotator_session_alloc(void);
 struct mdss_mdp_rotator_session *mdss_mdp_rotator_session_get(u32 session_id);
 
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 50b9e91..6a2c95d 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -595,6 +595,7 @@
 	metadata_op_frame_rate,
 	metadata_op_vic,
 	metadata_op_wb_format,
+	metadata_op_get_caps,
 	metadata_op_max
 };
 
@@ -607,6 +608,13 @@
 	uint32_t alpha;
 };
 
+struct mdss_hw_caps {
+	uint32_t mdp_rev;
+	uint8_t rgb_pipes;
+	uint8_t vig_pipes;
+	uint8_t dma_pipes;
+};
+
 struct msmfb_metadata {
 	uint32_t op;
 	uint32_t flags;
@@ -615,6 +623,7 @@
 		struct mdp_mixer_cfg mixer_cfg;
 		uint32_t panel_frame_rate;
 		uint32_t video_info_code;
+		struct mdss_hw_caps caps;
 	} data;
 };
 
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index ea45a8c..79fe16b 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -1,4 +1,4 @@
-/* linux/include/asm-arm/arch-msm/hsusb.h
+/* include/linux/usb/msm_hsusb.h
  *
  * Copyright (C) 2008 Google, Inc.
  * Author: Brian Swetland <swetland@google.com>
@@ -435,68 +435,6 @@
 	bool core_clk_always_on_workaround;
 };
 
-enum usb_pipe_mem_type {
-	SPS_PIPE_MEM = 0,	/* Default, SPS dedicated pipe memory */
-	USB_PRIVATE_MEM,	/* USB's private memory */
-	SYSTEM_MEM,		/* System RAM, requires allocation */
-};
-
-/**
- * struct usb_bam_pipe_connect: pipe connection information
- * between USB/HSIC BAM and another BAM. USB/HSIC BAM can be
- * either src BAM or dst BAM
- * @src_phy_addr: src bam physical address.
- * @src_pipe_index: src bam pipe index.
- * @dst_phy_addr: dst bam physical address.
- * @dst_pipe_index: dst bam pipe index.
- * @mem_type: type of memory used for BAM FIFOs
- * @data_fifo_base_offset: data fifo offset.
- * @data_fifo_size: data fifo size.
- * @desc_fifo_base_offset: descriptor fifo offset.
- * @desc_fifo_size: descriptor fifo size.
- */
-struct usb_bam_pipe_connect {
-	u32 src_phy_addr;
-	u32 src_pipe_index;
-	u32 dst_phy_addr;
-	u32 dst_pipe_index;
-	enum usb_pipe_mem_type mem_type;
-	u32 data_fifo_base_offset;
-	u32 data_fifo_size;
-	u32 desc_fifo_base_offset;
-	u32 desc_fifo_size;
-};
-
-enum usb_bam {
-	SSUSB_BAM = 0,
-	HSUSB_BAM,
-	HSIC_BAM,
-	MAX_BAMS,
-};
-
-/**
- * struct msm_usb_bam_platform_data: pipe connection information
- * between USB/HSIC BAM and another BAM. USB/HSIC BAM can be
- * either src BAM or dst BAM
- * @connections: holds all pipe connections data.
- * @usb_active_bam: set USB or HSIC as the active BAM.
- * @usb_bam_num_pipes: max number of pipes to use.
- * @active_conn_num: number of active pipe connections.
- * @usb_base_address: BAM physical address.
- * @ignore_core_reset_ack: BAM can ignore ACK from USB core during PIPE RESET
- * @disable_clk_gating: Disable clock gating
- */
-struct msm_usb_bam_platform_data {
-	struct usb_bam_pipe_connect *connections;
-	int usb_active_bam;
-	int usb_bam_num_pipes;
-	u32 total_bam_num;
-	u32 usb_base_address;
-	bool ignore_core_reset_ack;
-	bool reset_on_connect[MAX_BAMS];
-	bool disable_clk_gating;
-};
-
 /**
  * struct usb_ext_notification: event notification structure
  * @notify: pointer to client function to call when ID event is detected.
diff --git a/include/media/msmb_pproc.h b/include/media/msmb_pproc.h
index 56c257d..6f8e865 100644
--- a/include/media/msmb_pproc.h
+++ b/include/media/msmb_pproc.h
@@ -109,6 +109,9 @@
 #define VIDIOC_MSM_CPP_GET_HW_INFO \
 	_IOWR('V', BASE_VIDIOC_PRIVATE + 4, struct msm_camera_v4l2_ioctl_t)
 
+#define VIDIOC_MSM_CPP_FLUSH_QUEUE \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct msm_camera_v4l2_ioctl_t)
+
 #define V4L2_EVENT_CPP_FRAME_DONE  (V4L2_EVENT_PRIVATE_START + 0)
 
 struct msm_camera_v4l2_ioctl_t {
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index f4ea679..0c10548 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -2564,12 +2564,12 @@
 
 	pr_debug("%s: %s event = %d\n", __func__, w->name, event);
 	if (w->shift == 5) {
-		e_pre_on = WCD9XXX_EVENT_PRE_HPHR_PA_ON;
-		e_post_off = WCD9XXX_EVENT_POST_HPHR_PA_OFF;
-		req_clsh_state = WCD9XXX_CLSH_STATE_HPHL;
-	} else if (w->shift == 4) {
 		e_pre_on = WCD9XXX_EVENT_PRE_HPHL_PA_ON;
 		e_post_off = WCD9XXX_EVENT_POST_HPHL_PA_OFF;
+		req_clsh_state = WCD9XXX_CLSH_STATE_HPHL;
+	} else if (w->shift == 4) {
+		e_pre_on = WCD9XXX_EVENT_PRE_HPHR_PA_ON;
+		e_post_off = WCD9XXX_EVENT_POST_HPHR_PA_OFF;
 		req_clsh_state = WCD9XXX_CLSH_STATE_HPHR;
 	} else {
 		pr_err("%s: Invalid w->shift %d\n", __func__, w->shift);
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index 88f0567..5b54e1b 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -1039,7 +1039,7 @@
 		goto exit;
 	}
 
-	for (i = 0, d = dt, ch = 0; i < size; i++, d++) {
+	for (i = 0, d = dt; i < size; i++, d++) {
 		if ((i > 0) && (d->_type != dprev->_type)) {
 			pr_debug("%s: Invalid, inconsistent types\n", __func__);
 			type = PLUG_TYPE_INVALID;
@@ -1068,7 +1068,12 @@
 		     maxv))
 			type = PLUG_TYPE_GND_MIC_SWAP;
 	}
-
+	if (((type == PLUG_TYPE_HEADSET || type == PLUG_TYPE_HEADPHONE) &&
+	    ch != size) || (type == PLUG_TYPE_GND_MIC_SWAP && ch)) {
+		pr_debug("%s: Invalid, not fully inserted, TYPE %d\n",
+		    __func__, type);
+		type = PLUG_TYPE_INVALID;
+	}
 exit:
 	pr_debug("%s: Plug type %d detected\n", __func__, type);
 	return type;
@@ -2455,8 +2460,10 @@
 
 	if (mbhc) {
 		codec = mbhc->codec;
-		if (mbhc->hphlocp_cnt++ < OCP_ATTEMPT) {
+		if ((mbhc->hphlocp_cnt < OCP_ATTEMPT) &&
+		    (!mbhc->hphrocp_cnt)) {
 			pr_info("%s: retry\n", __func__);
+			mbhc->hphlocp_cnt++;
 			snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_OCP_CTL,
 					    0x10, 0x00);
 			snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_OCP_CTL,
@@ -2464,7 +2471,6 @@
 		} else {
 			wcd9xxx_disable_irq(codec->control_data,
 					  WCD9XXX_IRQ_HPH_PA_OCPL_FAULT);
-			mbhc->hphlocp_cnt = 0;
 			mbhc->hph_status |= SND_JACK_OC_HPHL;
 			wcd9xxx_jack_report(mbhc, &mbhc->headset_jack,
 					    mbhc->hph_status,
@@ -2484,8 +2490,10 @@
 
 	pr_info("%s: received HPHR OCP irq\n", __func__);
 	codec = mbhc->codec;
-	if (mbhc->hphrocp_cnt++ < OCP_ATTEMPT) {
+	if ((mbhc->hphrocp_cnt < OCP_ATTEMPT) &&
+	    (!mbhc->hphlocp_cnt)) {
 		pr_info("%s: retry\n", __func__);
+		mbhc->hphrocp_cnt++;
 		snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_OCP_CTL, 0x10,
 				    0x00);
 		snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_OCP_CTL, 0x10,
@@ -2493,7 +2501,6 @@
 	} else {
 		wcd9xxx_disable_irq(mbhc->resmgr->core,
 				    WCD9XXX_IRQ_HPH_PA_OCPR_FAULT);
-		mbhc->hphrocp_cnt = 0;
 		mbhc->hph_status |= SND_JACK_OC_HPHR;
 		wcd9xxx_jack_report(mbhc, &mbhc->headset_jack,
 				    mbhc->hph_status, WCD9XXX_JACK_MASK);
diff --git a/sound/soc/msm/msm8226.c b/sound/soc/msm/msm8226.c
index 7766b60..235b527 100644
--- a/sound/soc/msm/msm8226.c
+++ b/sound/soc/msm/msm8226.c
@@ -84,6 +84,7 @@
 static int msm_btsco_ch = 1;
 
 static struct mutex cdc_mclk_mutex;
+static struct clk *codec_clk;
 static int clk_users;
 
 static int msm_snd_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable,
@@ -95,21 +96,35 @@
 
 	mutex_lock(&cdc_mclk_mutex);
 	if (enable) {
+		if (!codec_clk) {
+			dev_err(codec->dev, "%s: did not get Taiko MCLK\n",
+					__func__);
+			ret = -EINVAL;
+			goto exit;
+		}
 
 		clk_users++;
 		if (clk_users != 1)
 			goto exit;
-		/* TODO: clk_disable */
-		tapan_mclk_enable(codec, 1, dapm);
+		if (codec_clk) {
+			clk_set_rate(codec_clk, TAPAN_EXT_CLK_RATE);
+			clk_prepare_enable(codec_clk);
+			tapan_mclk_enable(codec, 1, dapm);
+		} else {
+			pr_err("%s: Error setting Tapan MCLK\n", __func__);
+			clk_users--;
+			ret = -EINVAL;
+			goto exit;
+		}
 	} else {
 		if (clk_users > 0) {
 			clk_users--;
 			if (clk_users == 0) {
 				tapan_mclk_enable(codec, 0, dapm);
-				/* TODO: clk_enable */
+				clk_disable_unprepare(codec_clk);
 			}
 		} else {
-			pr_err("%s: Error releasing Tabla MCLK\n", __func__);
+			pr_err("%s: Error releasing Tapan MCLK\n", __func__);
 			ret = -EINVAL;
 			goto exit;
 		}
@@ -349,6 +364,11 @@
 
 	snd_soc_dapm_sync(dapm);
 
+	codec_clk = clk_get(cpu_dai->dev, "osr_clk");
+	if (codec_clk < 0)
+		pr_err("%s() Failed to get clock for %s\n",
+			   __func__, dev_name(cpu_dai->dev));
+
 	snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch),
 				    tx_ch, ARRAY_SIZE(rx_ch), rx_ch);
 
@@ -739,6 +759,21 @@
 		.codec_name = "snd-soc-dummy",
 		.be_id = MSM_FRONTEND_DAI_VOLTE,
 	},
+	{
+		.name = "MSM8226 LowLatency",
+		.stream_name = "MultiMedia5",
+		.cpu_dai_name   = "MultiMedia5",
+		.platform_name  = "msm-pcm-dsp.1",
+		.dynamic = 1,
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA5,
+	},
 	/* Backend BT/FM DAI Links */
 	{
 		.name = LPASS_BE_INT_BT_SCO_RX,
@@ -957,6 +992,17 @@
 
 static int msm8226_prepare_codec_mclk(struct snd_soc_card *card)
 {
+	struct msm8226_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+	int ret;
+	if (pdata->mclk_gpio) {
+		ret = gpio_request(pdata->mclk_gpio, "TAPAN_CODEC_PMIC_MCLK");
+		if (ret) {
+			dev_err(card->dev,
+				"%s: Failed to request taiko mclk gpio %d\n",
+				__func__, pdata->mclk_gpio);
+			return ret;
+		}
+	}
 	return 0;
 }
 
@@ -1008,7 +1054,16 @@
 		goto err;
 	}
 
-	/* TODO: MCLK GPIO */
+	pdata->mclk_gpio = of_get_named_gpio(pdev->dev.of_node,
+				"qcom,cdc-mclk-gpios", 0);
+	if (pdata->mclk_gpio < 0) {
+		dev_err(&pdev->dev,
+			"Looking up %s property in node %s failed %d\n",
+			"qcom, cdc-mclk-gpios", pdev->dev.of_node->full_name,
+			pdata->mclk_gpio);
+		ret = -ENODEV;
+		goto err;
+	}
 
 	ret = msm8226_prepare_codec_mclk(card);
 	if (ret)
@@ -1024,6 +1079,12 @@
 
 	return 0;
 err:
+	if (pdata->mclk_gpio > 0) {
+		dev_dbg(&pdev->dev, "%s free gpio %d\n",
+			__func__, pdata->mclk_gpio);
+		gpio_free(pdata->mclk_gpio);
+		pdata->mclk_gpio = 0;
+	}
 	devm_kfree(&pdev->dev, pdata);
 	return ret;
 }
@@ -1031,8 +1092,9 @@
 static int __devexit msm8226_asoc_machine_remove(struct platform_device *pdev)
 {
 	struct snd_soc_card *card = platform_get_drvdata(pdev);
+	struct msm8226_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
 
-	/* TODO: GPIO MCLK */
+	gpio_free(pdata->mclk_gpio);
 	snd_soc_unregister_card(card);
 
 	return 0;